"cpu_utilization": "cpu",
}
-METRIC_MULTIPLIERS = {
- "cpu": 0.0000001
-}
+METRIC_MULTIPLIERS = {"cpu": 0.0000001}
-METRIC_AGGREGATORS = {
- "cpu": "rate:mean"
-}
+METRIC_AGGREGATORS = {"cpu": "rate:mean"}
-INTERFACE_METRICS = ['packets_in_dropped', 'packets_out_dropped', 'packets_received', 'packets_sent']
+INTERFACE_METRICS = [
+ "packets_in_dropped",
+ "packets_out_dropped",
+ "packets_received",
+ "packets_sent",
+]
class MetricType(Enum):
- INSTANCE = 'instance'
- INTERFACE_ALL = 'interface_all'
- INTERFACE_ONE = 'interface_one'
+ INSTANCE = "instance"
+ INTERFACE_ALL = "interface_all"
+ INTERFACE_ONE = "interface_one"
class OpenstackCollector(BaseVimCollector):
sess = OpenstackUtils.get_session(vim_account)
return keystone_client.Client(session=sess)
- def _get_resource_uuid(self, nsr_id: str, vnf_member_index: str, vdur_name: str) -> str:
+ def _get_resource_uuid(
+ self, nsr_id: str, vnf_member_index: str, vdur_name: str
+ ) -> str:
vdur = self.common_db.get_vdur(nsr_id, vnf_member_index, vdur_name)
- return vdur['vim-id']
+ return vdur["vim-id"]
def collect(self, vnfr: dict) -> List[Metric]:
- nsr_id = vnfr['nsr-id-ref']
- vnf_member_index = vnfr['member-vnf-index-ref']
- vnfd = self.common_db.get_vnfd(vnfr['vnfd-id'])
-
+ nsr_id = vnfr["nsr-id-ref"]
+ vnf_member_index = vnfr["member-vnf-index-ref"]
+ vnfd = self.common_db.get_vnfd(vnfr["vnfd-id"])
# Populate extra tags for metrics
tags = {}
- tags['ns_name'] = self.common_db.get_nsr(nsr_id)['name']
- if vnfr['_admin']['projects_read']:
- tags['project_id'] = vnfr['_admin']['projects_read'][0]
+ tags["ns_name"] = self.common_db.get_nsr(nsr_id)["name"]
+ if vnfr["_admin"]["projects_read"]:
+ tags["project_id"] = vnfr["_admin"]["projects_read"][0]
else:
- tags['project_id'] = ''
+ tags["project_id"] = ""
metrics = []
- for vdur in vnfr['vdur']:
+
+ for vdur in vnfr["vdur"]:
# This avoids errors when vdur records have not been completely filled
- if 'name' not in vdur:
+ if "name" not in vdur:
continue
- vdu = next(
- filter(lambda vdu: vdu['id'] == vdur['vdu-id-ref'], vnfd['vdu'])
- )
- if 'monitoring-param' in vdu:
- for param in vdu['monitoring-param']:
- metric_name = param['nfvi-metric']
- interface_name = param['interface-name-ref'] if 'interface-name-ref' in param else None
+ vdu = next(filter(lambda vdu: vdu["id"] == vdur["vdu-id-ref"], vnfd["vdu"]))
+ if "monitoring-parameter" in vdu:
+ for param in vdu["monitoring-parameter"]:
+ metric_name = param["performance-metric"]
openstack_metric_name = METRIC_MAPPINGS[metric_name]
- metric_type = self._get_metric_type(metric_name, interface_name)
+ metric_type = self._get_metric_type(metric_name)
try:
- resource_id = self._get_resource_uuid(nsr_id, vnf_member_index, vdur['name'])
+ resource_id = self._get_resource_uuid(
+ nsr_id, vnf_member_index, vdur["name"]
+ )
except ValueError:
log.warning(
"Could not find resource_uuid for vdur %s, vnf_member_index %s, nsr_id %s. "
"Was it recently deleted?",
- vdur['name'], vnf_member_index, nsr_id)
+ vdur["name"],
+ vnf_member_index,
+ nsr_id,
+ )
continue
try:
- log.info("Collecting metric type: %s and metric_name: %s and resource_id %s and "
- "interface_name: %s", metric_type, metric_name, resource_id, interface_name)
- value = self.backend.collect_metric(metric_type, openstack_metric_name, resource_id,
- interface_name)
+ log.info(
+ "Collecting metric type: %s and metric_name: %s and resource_id %s and ",
+ metric_type,
+ metric_name,
+ resource_id,
+ )
+ value = self.backend.collect_metric(
+ metric_type, openstack_metric_name, resource_id
+ )
if value is not None:
log.info("value: %s", value)
- if interface_name:
- tags['interface'] = interface_name
- metric = VnfMetric(nsr_id, vnf_member_index, vdur['name'], metric_name, value, tags)
+ metric = VnfMetric(
+ nsr_id,
+ vnf_member_index,
+ vdur["name"],
+ metric_name,
+ value,
+ tags,
+ )
metrics.append(metric)
else:
log.info("metric value is empty")
except Exception as e:
- log.exception("Error collecting metric %s for vdu %s" % (metric_name, vdur['name']))
+ log.exception(
+ "Error collecting metric %s for vdu %s"
+ % (metric_name, vdur["name"])
+ )
log.info("Error in metric collection: %s" % e)
return metrics
log.info("Using ceilometer backend to collect metric")
return ceilometer
- def _get_metric_type(self, metric_name: str, interface_name: str) -> MetricType:
+ def _get_metric_type(self, metric_name: str) -> MetricType:
if metric_name not in INTERFACE_METRICS:
return MetricType.INSTANCE
else:
- if interface_name:
- return MetricType.INTERFACE_ONE
return MetricType.INTERFACE_ALL
class OpenstackBackend:
- def collect_metric(self, metric_type: MetricType, metric_name: str, resource_id: str, interface_name: str):
+ def collect_metric(
+ self, metric_type: MetricType, metric_name: str, resource_id: str
+ ):
pass
class GnocchiBackend(OpenstackBackend):
-
def __init__(self, vim_account: dict):
self.client = self._build_gnocchi_client(vim_account)
self.neutron = self._build_neutron_client(vim_account)
sess = OpenstackUtils.get_session(vim_account)
return neutron_client.Client(session=sess)
- def collect_metric(self, metric_type: MetricType, metric_name: str, resource_id: str, interface_name: str):
- if metric_type == MetricType.INTERFACE_ONE:
- return self._collect_interface_one_metric(metric_name, resource_id, interface_name)
-
+ def collect_metric(
+ self, metric_type: MetricType, metric_name: str, resource_id: str
+ ):
if metric_type == MetricType.INTERFACE_ALL:
return self._collect_interface_all_metric(metric_name, resource_id)
return self._collect_instance_metric(metric_name, resource_id)
else:
- raise Exception('Unknown metric type %s' % metric_type.value)
-
- def _collect_interface_one_metric(self, metric_name, resource_id, interface_name):
- ports = self.neutron.list_ports(name=interface_name, device_id=resource_id)
- if not ports or not ports['ports']:
- raise Exception(
- 'Port not found for interface %s on instance %s' % (interface_name, resource_id))
- port = ports['ports'][0]
- port_uuid = port['id'][:11]
- tap_name = 'tap' + port_uuid
- interfaces = self.client.resource.search(resource_type='instance_network_interface',
- query={'=': {'name': tap_name}})
- measures = self.client.metric.get_measures(metric_name,
- resource_id=interfaces[0]['id'],
- limit=1)
- return measures[-1][2] if measures else None
+ raise Exception("Unknown metric type %s" % metric_type.value)
def _collect_interface_all_metric(self, openstack_metric_name, resource_id):
total_measure = None
- interfaces = self.client.resource.search(resource_type='instance_network_interface',
- query={'=': {'instance_id': resource_id}})
+ interfaces = self.client.resource.search(
+ resource_type="instance_network_interface",
+ query={"=": {"instance_id": resource_id}},
+ )
for interface in interfaces:
try:
- measures = self.client.metric.get_measures(openstack_metric_name,
- resource_id=interface['id'],
- limit=1)
+ measures = self.client.metric.get_measures(
+ openstack_metric_name, resource_id=interface["id"], limit=1
+ )
if measures:
if not total_measure:
total_measure = 0.0
total_measure += measures[-1][2]
- except gnocchiclient.exceptions.NotFound as e:
- log.debug("No metric %s found for interface %s: %s", openstack_metric_name,
- interface['id'], e)
+ except (gnocchiclient.exceptions.NotFound, TypeError) as e:
+ # Gnocchi in some Openstack versions raise TypeError instead of NotFound
+ log.debug(
+ "No metric %s found for interface %s: %s",
+ openstack_metric_name,
+ interface["id"],
+ e,
+ )
return total_measure
def _collect_instance_metric(self, openstack_metric_name, resource_id):
aggregation = METRIC_AGGREGATORS.get(openstack_metric_name)
try:
- measures = self.client.metric.get_measures(openstack_metric_name,
- aggregation=aggregation,
- start=time.time() - 1200,
- resource_id=resource_id)
+ measures = self.client.metric.get_measures(
+ openstack_metric_name,
+ aggregation=aggregation,
+ start=time.time() - 1200,
+ resource_id=resource_id,
+ )
if measures:
value = measures[-1][2]
- except gnocchiclient.exceptions.NotFound as e:
+ except (
+ gnocchiclient.exceptions.NotFound,
+ gnocchiclient.exceptions.BadRequest,
+ TypeError,
+ ) as e:
# CPU metric in previous Openstack versions do not support rate:mean aggregation method
+ # Gnocchi in some Openstack versions raise TypeError instead of NotFound or BadRequest
if openstack_metric_name == "cpu":
- log.debug("No metric %s found for instance %s: %s", openstack_metric_name, resource_id, e)
- log.debug("Retrying to get metric %s for instance %s without aggregation",
- openstack_metric_name, resource_id)
- measures = self.client.metric.get_measures(openstack_metric_name,
- resource_id=resource_id,
- limit=1)
+ log.debug(
+ "No metric %s found for instance %s: %s",
+ openstack_metric_name,
+ resource_id,
+ e,
+ )
+ log.info(
+ "Retrying to get metric %s for instance %s without aggregation",
+ openstack_metric_name,
+ resource_id,
+ )
+ measures = self.client.metric.get_measures(
+ openstack_metric_name, resource_id=resource_id, limit=1
+ )
else:
raise e
# measures[-1] is the last measure
if openstack_metric_name in METRIC_MULTIPLIERS:
value = value * METRIC_MULTIPLIERS[openstack_metric_name]
except gnocchiclient.exceptions.NotFound as e:
- log.debug("No metric %s found for instance %s: %s", openstack_metric_name, resource_id,
- e)
+ log.debug(
+ "No metric %s found for instance %s: %s",
+ openstack_metric_name,
+ resource_id,
+ e,
+ )
return value
sess = OpenstackUtils.get_session(vim_account)
return ceilometer_client.Client("2", session=sess)
- def collect_metric(self, metric_type: MetricType, metric_name: str, resource_id: str, interface_name: str):
+ def collect_metric(
+ self, metric_type: MetricType, metric_name: str, resource_id: str
+ ):
if metric_type != MetricType.INSTANCE:
- raise NotImplementedError('Ceilometer backend only support instance metrics')
- measures = self.client.samples.list(meter_name=metric_name, limit=1, q=[
- {'field': 'resource_id', 'op': 'eq', 'value': resource_id}])
+ raise NotImplementedError(
+ "Ceilometer backend only support instance metrics"
+ )
+ measures = self.client.samples.list(
+ meter_name=metric_name,
+ limit=1,
+ q=[{"field": "resource_id", "op": "eq", "value": resource_id}],
+ )
return measures[0].counter_volume if measures else None