282 lines
9.8 KiB
Python
282 lines
9.8 KiB
Python
#
|
|
# Copyright 2012 Red Hat, Inc
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
"""Inspector abstraction for read-only access to hypervisors."""
|
|
|
|
import collections
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log
|
|
from stevedore import driver
|
|
|
|
import ceilometer
|
|
|
|
|
|
OPTS = [
|
|
cfg.StrOpt('hypervisor_inspector',
|
|
default='libvirt',
|
|
help='Inspector to use for inspecting the hypervisor layer. '
|
|
'Known inspectors are libvirt, hyperv, and vsphere.'),
|
|
]
|
|
|
|
|
|
LOG = log.getLogger(__name__)
|
|
|
|
|
|
# Named tuple representing instance statistics
|
|
|
|
class InstanceStats(object):
|
|
fields = [
|
|
'cpu_number', # number: number of CPUs
|
|
'cpu_time', # time: cumulative CPU time
|
|
'cpu_util', # util: CPU utilization in percentage
|
|
'cpu_l3_cache_usage', # cachesize: Amount of CPU L3 cache used
|
|
'memory_usage', # usage: Amount of memory used
|
|
'memory_resident', #
|
|
'memory_swap_in', # memory swap in
|
|
'memory_swap_out', # memory swap out
|
|
'memory_bandwidth_total', # total: total system bandwidth from one
|
|
# level of cache
|
|
'memory_bandwidth_local', # local: bandwidth of memory traffic for a
|
|
# memory controller
|
|
'cpu_cycles', # cpu_cycles: the number of cpu cycles one
|
|
# instruction needs
|
|
'instructions', # instructions: the count of instructions
|
|
'cache_references', # cache_references: the count of cache hits
|
|
'cache_misses', # cache_misses: the count of caches misses
|
|
]
|
|
|
|
def __init__(self, **kwargs):
|
|
for k in self.fields:
|
|
setattr(self, k, kwargs.pop(k, None))
|
|
if kwargs:
|
|
raise AttributeError(
|
|
"'InstanceStats' object has no attributes '%s'" % kwargs)
|
|
|
|
|
|
# Named tuple representing vNIC statistics.
|
|
#
|
|
# name: the name of the vNIC
|
|
# mac: the MAC address
|
|
# fref: the filter ref
|
|
# parameters: miscellaneous parameters
|
|
# rx_bytes: number of received bytes
|
|
# rx_packets: number of received packets
|
|
# tx_bytes: number of transmitted bytes
|
|
# tx_packets: number of transmitted packets
|
|
#
|
|
InterfaceStats = collections.namedtuple('InterfaceStats',
|
|
['name', 'mac', 'fref', 'parameters',
|
|
'rx_bytes', 'tx_bytes',
|
|
'rx_packets', 'tx_packets',
|
|
'rx_drop', 'tx_drop',
|
|
'rx_errors', 'tx_errors',
|
|
'rx_bytes_delta', 'tx_bytes_delta'])
|
|
|
|
|
|
# Named tuple representing vNIC rate statistics.
|
|
#
|
|
# name: the name of the vNIC
|
|
# mac: the MAC address
|
|
# fref: the filter ref
|
|
# parameters: miscellaneous parameters
|
|
# rx_bytes_rate: rate of received bytes
|
|
# tx_bytes_rate: rate of transmitted bytes
|
|
#
|
|
InterfaceRateStats = collections.namedtuple('InterfaceRateStats',
|
|
['name', 'mac',
|
|
'fref', 'parameters',
|
|
'rx_bytes_rate', 'tx_bytes_rate'])
|
|
|
|
|
|
# Named tuple representing disk statistics.
|
|
#
|
|
# read_bytes: number of bytes read
|
|
# read_requests: number of read operations
|
|
# write_bytes: number of bytes written
|
|
# write_requests: number of write operations
|
|
# errors: number of errors
|
|
#
|
|
DiskStats = collections.namedtuple('DiskStats',
|
|
['device',
|
|
'read_bytes', 'read_requests',
|
|
'write_bytes', 'write_requests',
|
|
'errors', 'wr_total_times',
|
|
'rd_total_times'])
|
|
|
|
# Named tuple representing disk rate statistics.
|
|
#
|
|
# read_bytes_rate: number of bytes read per second
|
|
# read_requests_rate: number of read operations per second
|
|
# write_bytes_rate: number of bytes written per second
|
|
# write_requests_rate: number of write operations per second
|
|
#
|
|
DiskRateStats = collections.namedtuple('DiskRateStats',
|
|
['device',
|
|
'read_bytes_rate',
|
|
'read_requests_rate',
|
|
'write_bytes_rate',
|
|
'write_requests_rate'])
|
|
|
|
# Named tuple representing disk latency statistics.
|
|
#
|
|
# disk_latency: average disk latency
|
|
#
|
|
DiskLatencyStats = collections.namedtuple('DiskLatencyStats',
|
|
['device', 'disk_latency'])
|
|
|
|
# Named tuple representing disk iops statistics.
|
|
#
|
|
# iops: number of iops per second
|
|
#
|
|
DiskIOPSStats = collections.namedtuple('DiskIOPSStats',
|
|
['device', 'iops_count'])
|
|
|
|
|
|
# Named tuple representing disk Information.
|
|
#
|
|
# capacity: capacity of the disk
|
|
# allocation: allocation of the disk
|
|
# physical: usage of the disk
|
|
|
|
DiskInfo = collections.namedtuple('DiskInfo',
|
|
['device',
|
|
'capacity',
|
|
'allocation',
|
|
'physical'])
|
|
|
|
|
|
# Exception types
|
|
#
|
|
class InspectorException(Exception):
|
|
def __init__(self, message=None):
|
|
super(InspectorException, self).__init__(message)
|
|
|
|
|
|
class InstanceNotFoundException(InspectorException):
|
|
pass
|
|
|
|
|
|
class InstanceShutOffException(InspectorException):
|
|
pass
|
|
|
|
|
|
class NoDataException(InspectorException):
|
|
pass
|
|
|
|
|
|
# Main virt inspector abstraction layering over the hypervisor API.
|
|
#
|
|
class Inspector(object):
|
|
|
|
def __init__(self, conf):
|
|
self.conf = conf
|
|
|
|
def inspect_instance(self, instance, duration):
|
|
"""Inspect the CPU statistics for an instance.
|
|
|
|
:param instance: the target instance
|
|
:param duration: the last 'n' seconds, over which the value should be
|
|
inspected
|
|
:return: the instance stats
|
|
"""
|
|
raise ceilometer.NotImplementedError
|
|
|
|
def inspect_vnics(self, instance, duration):
|
|
"""Inspect the vNIC statistics for an instance.
|
|
|
|
:param instance: the target instance
|
|
:param duration: the last 'n' seconds, over which the value should be
|
|
inspected
|
|
:return: for each vNIC, the number of bytes & packets
|
|
received and transmitted
|
|
"""
|
|
raise ceilometer.NotImplementedError
|
|
|
|
def inspect_vnic_rates(self, instance, duration):
|
|
"""Inspect the vNIC rate statistics for an instance.
|
|
|
|
:param instance: the target instance
|
|
:param duration: the last 'n' seconds, over which the value should be
|
|
inspected
|
|
:return: for each vNIC, the rate of bytes & packets
|
|
received and transmitted
|
|
"""
|
|
raise ceilometer.NotImplementedError
|
|
|
|
def inspect_disks(self, instance, duration):
|
|
"""Inspect the disk statistics for an instance.
|
|
|
|
:param instance: the target instance
|
|
:param duration: the last 'n' seconds, over which the value should be
|
|
inspected
|
|
:return: for each disk, the number of bytes & operations
|
|
read and written, and the error count
|
|
"""
|
|
raise ceilometer.NotImplementedError
|
|
|
|
def inspect_disk_rates(self, instance, duration):
|
|
"""Inspect the disk statistics as rates for an instance.
|
|
|
|
:param instance: the target instance
|
|
:param duration: the last 'n' seconds, over which the value should be
|
|
inspected
|
|
:return: for each disk, the number of bytes & operations
|
|
read and written per second, with the error count
|
|
"""
|
|
raise ceilometer.NotImplementedError
|
|
|
|
def inspect_disk_latency(self, instance, duration):
|
|
"""Inspect the disk statistics as rates for an instance.
|
|
|
|
:param instance: the target instance
|
|
:param duration: the last 'n' seconds, over which the value should be
|
|
inspected
|
|
:return: for each disk, the average disk latency
|
|
"""
|
|
raise ceilometer.NotImplementedError
|
|
|
|
def inspect_disk_iops(self, instance, duration):
|
|
"""Inspect the disk statistics as rates for an instance.
|
|
|
|
:param instance: the target instance
|
|
:param duration: the last 'n' seconds, over which the value should be
|
|
inspected
|
|
:return: for each disk, the number of iops per second
|
|
"""
|
|
raise ceilometer.NotImplementedError
|
|
|
|
def inspect_disk_info(self, instance, duration):
|
|
"""Inspect the disk information for an instance.
|
|
|
|
:param instance: the target instance
|
|
:param duration: the last 'n' seconds, over which the value should be
|
|
inspected
|
|
:return: for each disk , capacity , allocation and usage
|
|
"""
|
|
raise ceilometer.NotImplementedError
|
|
|
|
|
|
def get_hypervisor_inspector(conf):
|
|
try:
|
|
namespace = 'ceilometer.compute.virt'
|
|
mgr = driver.DriverManager(namespace,
|
|
conf.hypervisor_inspector,
|
|
invoke_on_load=True,
|
|
invoke_args=(conf, ))
|
|
return mgr.driver
|
|
except ImportError as e:
|
|
LOG.error("Unable to load the hypervisor inspector: %s" % e)
|
|
return Inspector(conf)
|