~ubuntu-branches/ubuntu/vivid/ceilometer/vivid

« back to all changes in this revision

Viewing changes to ceilometer/compute/virt/vmware/vsphere_operations.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2014-03-06 14:44:28 UTC
  • mto: (28.1.1 utopic-proposed) (1.2.1)
  • mto: This revision was merged to the branch mainline in revision 19.
  • Revision ID: package-import@ubuntu.com-20140306144428-rvphsh4igwyulzf0
Tags: upstream-2014.1~b3
ImportĀ upstreamĀ versionĀ 2014.1~b3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2014 VMware, Inc.
 
2
# All Rights Reserved.
 
3
#
 
4
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
5
#    not use this file except in compliance with the License. You may obtain
 
6
#    a copy of the License at
 
7
#
 
8
#         http://www.apache.org/licenses/LICENSE-2.0
 
9
#
 
10
#    Unless required by applicable law or agreed to in writing, software
 
11
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
12
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
13
#    License for the specific language governing permissions and limitations
 
14
#    under the License.
 
15
 
 
16
from oslo.vmware import vim_util
 
17
 
 
18
 
 
19
PERF_MANAGER_TYPE = "PerformanceManager"
 
20
PERF_COUNTER_PROPERTY = "perfCounter"
 
21
VM_INSTANCE_ID_PROPERTY = 'config.extraConfig["nvp.vm-uuid"].value'
 
22
 
 
23
# ESXi Servers sample performance data every 20 seconds. 20-second interval
 
24
# data is called instance data or real-time data. To retrieve instance data,
 
25
# we need to specify a value of 20 seconds for the "PerfQuerySpec.intervalId"
 
26
# property. In that case the "QueryPerf" method operates as a raw data feed
 
27
# that bypasses the vCenter database and instead retrieves performance data
 
28
# from an ESXi host.
 
29
# The following value is time interval for real-time performance stats
 
30
# in seconds and it is not configurable.
 
31
VC_REAL_TIME_SAMPLING_INTERVAL = 20
 
32
 
 
33
 
 
34
class VsphereOperations(object):
 
35
    """Class to invoke vSphere APIs calls required by various
 
36
       pollsters, collecting data from VMware infrastructure.
 
37
    """
 
38
    def __init__(self, api_session, max_objects):
 
39
        self._api_session = api_session
 
40
        self._max_objects = max_objects
 
41
        # Mapping between "VM's Nova instance Id" -> "VM's MOID"
 
42
        # In case a VM is deployed by Nova, then its name is instance ID.
 
43
        # So this map essentially has VM names as keys.
 
44
        self._vm_moid_lookup_map = {}
 
45
 
 
46
        # Mapping from full name -> ID, for VC Performance counters
 
47
        self._perf_counter_id_lookup_map = None
 
48
 
 
49
    def _init_vm_moid_lookup_map(self):
 
50
        session = self._api_session
 
51
        result = session.invoke_api(vim_util, "get_objects", session.vim,
 
52
                                    "VirtualMachine", self._max_objects,
 
53
                                    [VM_INSTANCE_ID_PROPERTY],
 
54
                                    False)
 
55
        while result:
 
56
            for vm_object in result.objects:
 
57
                vm_moid = vm_object.obj.value
 
58
                vm_instance_id = vm_object.propSet[0].val
 
59
                if vm_instance_id:
 
60
                    self._vm_moid_lookup_map[vm_instance_id] = vm_moid
 
61
 
 
62
            result = session.invoke_api(vim_util, "continue_retrieval",
 
63
                                        session.vim, result)
 
64
 
 
65
    def get_vm_moid(self, vm_instance_id):
 
66
        """Method returns VC MOID of the VM by its NOVA instance ID.
 
67
        """
 
68
        if vm_instance_id not in self._vm_moid_lookup_map:
 
69
            self._init_vm_moid_lookup_map()
 
70
 
 
71
        return self._vm_moid_lookup_map.get(vm_instance_id, None)
 
72
 
 
73
    def _init_perf_counter_id_lookup_map(self):
 
74
 
 
75
        # Query details of all the performance counters from VC
 
76
        session = self._api_session
 
77
        client_factory = session.vim.client.factory
 
78
        perf_manager = session.vim.service_content.perfManager
 
79
 
 
80
        prop_spec = vim_util.build_property_spec(
 
81
            client_factory, PERF_MANAGER_TYPE, [PERF_COUNTER_PROPERTY])
 
82
 
 
83
        obj_spec = vim_util.build_object_spec(
 
84
            client_factory, perf_manager, None)
 
85
 
 
86
        filter_spec = vim_util.build_property_filter_spec(
 
87
            client_factory, [prop_spec], [obj_spec])
 
88
 
 
89
        options = client_factory.create('ns0:RetrieveOptions')
 
90
        options.maxObjects = 1
 
91
 
 
92
        prop_collector = session.vim.service_content.propertyCollector
 
93
        result = session.invoke_api(session.vim, "RetrievePropertiesEx",
 
94
                                    prop_collector, specSet=[filter_spec],
 
95
                                    options=options)
 
96
 
 
97
        perf_counter_infos = result.objects[0].propSet[0].val.PerfCounterInfo
 
98
 
 
99
        # Extract the counter Id for each counter and populate the map
 
100
        self._perf_counter_id_lookup_map = {}
 
101
        for perf_counter_info in perf_counter_infos:
 
102
 
 
103
            counter_group = perf_counter_info.groupInfo.key
 
104
            counter_name = perf_counter_info.nameInfo.key
 
105
            counter_rollup_type = perf_counter_info.rollupType
 
106
            counter_id = perf_counter_info.key
 
107
 
 
108
            counter_full_name = (counter_group + ":" + counter_name + ":" +
 
109
                                 counter_rollup_type)
 
110
            self._perf_counter_id_lookup_map[counter_full_name] = counter_id
 
111
 
 
112
    def get_perf_counter_id(self, counter_full_name):
 
113
        """Method returns the ID of VC performance counter by its full name.
 
114
 
 
115
        A VC performance counter is uniquely identified by the
 
116
        tuple {'Group Name', 'Counter Name', 'Rollup Type'}.
 
117
        It will have an id - counter ID (changes from one VC to another),
 
118
        which is required to query performance stats from that VC.
 
119
        This method returns the ID for a counter,
 
120
        assuming 'CounterFullName' => 'Group Name:CounterName:RollupType'.
 
121
        """
 
122
        if not self._perf_counter_id_lookup_map:
 
123
            self._init_perf_counter_id_lookup_map()
 
124
        return self._perf_counter_id_lookup_map[counter_full_name]
 
125
 
 
126
    # TODO(akhils@vmware.com) Move this method to common library
 
127
    # when it gets checked-in
 
128
    def query_vm_property(self, vm_moid, property_name):
 
129
        """Method returns the value of specified property for a VM.
 
130
 
 
131
        :param vm_moid: moid of the VM whose property is to be queried
 
132
        :param property_name: path of the property
 
133
        """
 
134
        vm_mobj = vim_util.get_moref(vm_moid, "VirtualMachine")
 
135
        session = self._api_session
 
136
        return session.invoke_api(vim_util, "get_object_property",
 
137
                                  session.vim, vm_mobj, property_name)
 
138
 
 
139
    def query_vm_aggregate_stats(self, vm_moid, counter_id):
 
140
        """Method queries the aggregated real-time stat value for a VM.
 
141
 
 
142
        This method should be used for aggregate counters.
 
143
 
 
144
        :param vm_moid: moid of the VM
 
145
        :param counter_id: id of the perf counter in VC
 
146
        :return: the aggregated stats value for the counter
 
147
        """
 
148
        # For aggregate counters, device_name should be ""
 
149
        stats = self._query_vm_perf_stats(vm_moid, counter_id, "")
 
150
 
 
151
        # Performance manager provides the aggregated stats value
 
152
        # with device name -> None
 
153
        return stats.get(None, 0)
 
154
 
 
155
    def query_vm_device_stats(self, vm_moid, counter_id):
 
156
        """Method queries the real-time stat values for a VM, for all devices.
 
157
 
 
158
        This method should be used for device(non-aggregate) counters.
 
159
 
 
160
        :param vm_moid: moid of the VM
 
161
        :param counter_id: id of the perf counter in VC
 
162
        :return: a map containing the stat values keyed by the device ID/name
 
163
        """
 
164
        # For device counters, device_name should be "*" to get stat values
 
165
        # for all devices.
 
166
        stats = self._query_vm_perf_stats(vm_moid, counter_id, "*")
 
167
 
 
168
        # For some device counters, in addition to the per device value
 
169
        # the Performance manager also returns the aggregated value.
 
170
        # Just to be consistent, deleting the aggregated value if present.
 
171
        stats.pop(None, None)
 
172
        return stats
 
173
 
 
174
    def _query_vm_perf_stats(self, vm_moid, counter_id, device_name):
 
175
        """Method queries the real-time stat values for a VM.
 
176
 
 
177
        :param vm_moid: moid of the VM for which stats are needed
 
178
        :param counter_id: id of the perf counter in VC
 
179
        :param device_name: name of the device for which stats are to be
 
180
            queried. For aggregate counters pass empty string ("").
 
181
            For device counters pass "*", if stats are required over all
 
182
            devices.
 
183
        :return: a map containing the stat values keyed by the device ID/name
 
184
        """
 
185
 
 
186
        session = self._api_session
 
187
        client_factory = session.vim.client.factory
 
188
 
 
189
        # Construct the QuerySpec
 
190
        metric_id = client_factory.create('ns0:PerfMetricId')
 
191
        metric_id.counterId = counter_id
 
192
        metric_id.instance = device_name
 
193
 
 
194
        query_spec = client_factory.create('ns0:PerfQuerySpec')
 
195
        query_spec.entity = vim_util.get_moref(vm_moid, "VirtualMachine")
 
196
        query_spec.metricId = [metric_id]
 
197
        query_spec.intervalId = VC_REAL_TIME_SAMPLING_INTERVAL
 
198
        # The following setting ensures that we need only one latest sample
 
199
        query_spec.maxSample = 1
 
200
 
 
201
        perf_manager = session.vim.service_content.perfManager
 
202
        perf_stats = session.invoke_api(session.vim, 'QueryPerf', perf_manager,
 
203
                                        querySpec=[query_spec])
 
204
 
 
205
        stat_values = {}
 
206
        if perf_stats:
 
207
            entity_metric = perf_stats[0]
 
208
            sample_infos = entity_metric.sampleInfo
 
209
            samples_count = len(sample_infos)
 
210
 
 
211
            if samples_count > 0:
 
212
                for metric_series in entity_metric.value:
 
213
                    stat_value = metric_series.value[samples_count - 1]
 
214
                    device_id = metric_series.id.instance
 
215
                    stat_values[device_id] = stat_value
 
216
 
 
217
        return stat_values