Merge "Resolve problems with audit scope and add tests"

This commit is contained in:
Zuul 2019-04-30 09:20:27 +00:00 committed by Gerrit Code Review
commit 8ac5e620f4
2 changed files with 185 additions and 166 deletions

View File

@ -208,10 +208,9 @@ class ModelBuilder(object):
self.osc = osc
self.model = None
self.model_scope = dict()
self.no_model_scope_flag = False
self.nova = osc.nova()
self.nova_helper = nova_helper.NovaHelper(osc=self.osc)
# self.neutron = osc.neutron()
# self.cinder = osc.cinder()
def _collect_aggregates(self, host_aggregates, _nodes):
aggregate_list = self.nova_helper.get_aggregate_list()
@ -237,7 +236,7 @@ class ModelBuilder(object):
include_all_nodes = True
for service in service_list:
if service.zone in zone_names or include_all_nodes:
_nodes.update(service.host)
_nodes.add(service.host)
def _add_physical_layer(self):
"""Add the physical layer of the graph.
@ -254,6 +253,7 @@ class ModelBuilder(object):
self._collect_zones(availability_zones, compute_nodes)
if not compute_nodes:
self.no_model_scope_flag = True
all_nodes = self.nova_helper.get_compute_node_list()
compute_nodes = set(
[node.hypervisor_hostname for node in all_nodes])
@ -315,47 +315,6 @@ class ModelBuilder(object):
# node_attributes)
return compute_node
# def _build_network_compute_node(self, base_node):
# attributes = {}
# net_node = self._build_node("physical", "network", "NIC", attributes)
# net_id = "{}_network".format(base_node)
# return net_id, net_node
# def build_disk_compute_node(self, base_node, compute):
# # Build disk node attributes.
# disk_attributes = {
# "size_gb": compute.local_gb,
# "used_gb": compute.local_gb_used,
# "available_gb": compute.free_disk_gb}
# disk_node = self._build_node("physical", "storage", "disk",
# disk_attributes)
# disk_id = "{}_disk".format(base_node)
# return disk_id, disk_node
# def build_memory_compute_node(self, base_node, compute):
# # Build memory node attributes.
# memory_attrs = {"size_mb": compute.memory_mb,
# "used_mb": compute.memory_mb_used,
# "available_mb": compute.free_ram_mb}
# memory_node = self._build_node("physical", "memory", "memory",
# memory_attrs)
# memory_id = "{}_memory".format(base_node)
# return memory_id, memory_node
# def build_cpu_compute_node(self, base_node, compute):
# # Build memory node attributes.
# cpu_attributes = {"vcpus": compute.vcpus,
# "vcpus_used": compute.vcpus_used,
# "info": jsonutils.loads(compute.cpu_info)}
# cpu_node = self._build_node("physical", "cpu", "cpu", cpu_attributes)
# cpu_id = "{}_cpu".format(base_node)
# return cpu_id, cpu_node
# @staticmethod
# def _build_node(layer, category, node_type, attributes):
# return {"layer": layer, "category": category, "type": node_type,
# "attributes": attributes}
def _add_virtual_layer(self):
"""Add the virtual layer to the graph.
@ -439,137 +398,23 @@ class ModelBuilder(object):
# node_attributes["attributes"] = instance_attributes
return element.Instance(**instance_attributes)
# def _add_virtual_storage(self):
# try:
# volumes = self.cinder.volumes.list()
# except Exception:
# return
# for volume in volumes:
# volume_id, volume_node = self._build_storage_node(volume)
# self.add_node(volume_id, volume_node)
# host = self._get_volume_host_id(volume_node)
# self.add_edge(volume_id, host)
# # Add connections to an instance.
# if volume_node['attributes']['attachments']:
# for attachment in volume_node['attributes']['attachments']:
# self.add_edge(volume_id, attachment['server_id'],
# label='ATTACHED_TO')
# volume_node['attributes'].pop('attachments')
# def _add_virtual_network(self):
# try:
# routers = self.neutron.list_routers()
# except Exception:
# return
# for network in self.neutron.list_networks()['networks']:
# self.add_node(*self._build_network(network))
# for router in routers['routers']:
# self.add_node(*self._build_router(router))
# router_interfaces, _, compute_ports = self._group_ports()
# for router_interface in router_interfaces:
# interface = self._build_router_interface(router_interface)
# router_interface_id = interface[0]
# router_interface_node = interface[1]
# router_id = interface[2]
# self.add_node(router_interface_id, router_interface_node)
# self.add_edge(router_id, router_interface_id)
# network_id = router_interface_node['attributes']['network_id']
# self.add_edge(router_interface_id, network_id)
# for compute_port in compute_ports:
# cp_id, cp_node, instance_id = self._build_compute_port_node(
# compute_port)
# self.add_node(cp_id, cp_node)
# self.add_edge(cp_id, vm_id)
# net_id = cp_node['attributes']['network_id']
# self.add_edge(net_id, cp_id)
# # Connect port to physical node
# phys_net_node = "{}_network".format(cp_node['attributes']
# ['binding:host_id'])
# self.add_edge(cp_id, phys_net_node)
# def _get_volume_host_id(self, volume_node):
# host = volume_node['attributes']['os-vol-host-attr:host']
# if host.find('@') != -1:
# host = host.split('@')[0]
# elif host.find('#') != -1:
# host = host.split('#')[0]
# return "{}_disk".format(host)
# def _build_storage_node(self, volume_obj):
# volume = volume_obj.__dict__
# volume["name"] = volume["id"]
# volume.pop("id")
# volume.pop("manager")
# node = self._build_node("virtual", "storage", 'volume', volume)
# return volume["name"], node
# def _build_compute_port_node(self, compute_port):
# compute_port["name"] = compute_port["id"]
# compute_port.pop("id")
# nde_type = "{}_port".format(
# compute_port["device_owner"].split(":")[0])
# compute_port.pop("device_owner")
# device_id = compute_port["device_id"]
# compute_port.pop("device_id")
# node = self._build_node("virtual", "network", nde_type, compute_port)
# return compute_port["name"], node, device_id
# def _group_ports(self):
# router_interfaces = []
# floating_ips = []
# compute_ports = []
# interface_types = ["network:router_interface",
# 'network:router_gateway']
# for port in self.neutron.list_ports()['ports']:
# if port['device_owner'] in interface_types:
# router_interfaces.append(port)
# elif port['device_owner'].startswith('compute:'):
# compute_ports.append(port)
# elif port['device_owner'] == 'network:floatingip':
# floating_ips.append(port)
# return router_interfaces, floating_ips, compute_ports
# def _build_router_interface(self, interface):
# interface["name"] = interface["id"]
# interface.pop("id")
# node_type = interface["device_owner"].split(":")[1]
# node = self._build_node("virtual", "network", node_type, interface)
# return interface["name"], node, interface["device_id"]
# def _build_router(self, router):
# router_attrs = {"uuid": router['id'],
# "name": router['name'],
# "state": router['status']}
# node = self._build_node('virtual', 'network', 'router', router_attrs)
# return str(router['id']), node
# def _build_network(self, network):
# node = self._build_node('virtual', 'network', 'network', network)
# return network['id'], node
def _merge_compute_scope(self, compute_scope):
model_keys = self.model_scope.keys()
update_flag = False
role_keys = ("host_aggregates", "availability_zones")
for role in compute_scope:
role_key = role.keys()[0]
role_key = list(role.keys())[0]
if role_key not in role_keys:
continue
role_values = role.values()[0]
role_values = list(role.values())[0]
if role_key in model_keys:
for value in role_values:
if value not in self.model_scope[role_key]:
self.model_scope[role_key].sppend(value)
self.model_scope[role_key].append(value)
update_flag = True
else:
self.self.model_scope[role_key] = role_values
self.model_scope[role_key] = role_values
update_flag = True
return update_flag
@ -581,10 +426,9 @@ class ModelBuilder(object):
compute_scope = _scope['compute']
break
if self.model_scope:
if model_scope:
if compute_scope:
update_flag = self._merge_compute_scope(compute_scope)
if self.no_model_scope_flag is False:
if compute_scope:
update_flag = self._merge_compute_scope(compute_scope)
else:
self.model_scope = dict()
update_flag = True

View File

@ -0,0 +1,175 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2019 European Organization for Nuclear Research (CERN)
#
# Authors: Corne Lukken <info@dantalion.nl>
#
# 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.
import mock
from oslo_config import cfg
from oslo_log import log
from watcher.common import nova_helper
from watcher.decision_engine.model.collector import nova
from watcher.tests import base
CONF = cfg.CONF
LOG = log.getLogger(__name__)
class TestModelBuilder(base.BaseTestCase):
"""Test the collector ModelBuilder
Objects under test are preceded with t_ and mocked objects are preceded
with m_ , additionally, patched objects are preceded with p_ no object
under test should be created in setUp this can influence the results.
"""
def setUp(self):
super(TestModelBuilder, self).setUp()
def test_check_model(self):
"""Initialize collector ModelBuilder and test check model"""
m_scope = [{"compute": [
{"host_aggregates": [{"id": 5}]},
{"availability_zones": [{"name": "av_a"}]}
]}]
t_nova_cluster = nova.ModelBuilder(mock.Mock())
self.assertTrue(t_nova_cluster._check_model_scope(m_scope))
def test_check_model_update_false(self):
"""Initialize check model with multiple identical scopes
The seconds check_model should return false as the models are the same
"""
m_scope = [{"compute": [
{"host_aggregates": [{"id": 5}]},
{"availability_zones": [{"name": "av_a"}]}
]}]
t_nova_cluster = nova.ModelBuilder(mock.Mock())
self.assertTrue(t_nova_cluster._check_model_scope(m_scope))
self.assertFalse(t_nova_cluster._check_model_scope(m_scope))
def test_check_model_update_true(self):
"""Initialize check model with multiple different scopes
Since the models differ both should return True for the update flag
"""
m_scope_one = [{"compute": [
{"host_aggregates": [{"id": 5}]},
{"availability_zones": [{"name": "av_a"}]}
]}]
m_scope_two = [{"compute": [
{"host_aggregates": [{"id": 2}]},
{"availability_zones": [{"name": "av_b"}]}
]}]
t_nova_cluster = nova.ModelBuilder(mock.Mock())
self.assertTrue(t_nova_cluster._check_model_scope(m_scope_one))
self.assertTrue(t_nova_cluster._check_model_scope(m_scope_two))
def test_merge_compute_scope(self):
""""""
m_scope_one = [
{"host_aggregates": [{"id": 5}]},
{"availability_zones": [{"name": "av_a"}]}
]
m_scope_two = [
{"host_aggregates": [{"id": 4}]},
{"availability_zones": [{"name": "av_b"}]}
]
reference = {'availability_zones':
[{'name': 'av_a'}, {'name': 'av_b'}],
'host_aggregates':
[{'id': 5}, {'id': 4}]}
t_nova_cluster = nova.ModelBuilder(mock.Mock())
t_nova_cluster._merge_compute_scope(m_scope_one)
t_nova_cluster._merge_compute_scope(m_scope_two)
self.assertEqual(reference, t_nova_cluster.model_scope)
@mock.patch.object(nova_helper, 'NovaHelper')
def test_collect_aggregates(self, m_nova):
""""""
m_nova.return_value.get_aggregate_list.return_value = \
[mock.Mock(id=1, name='example'),
mock.Mock(id=5, name='example', hosts=['hostone', 'hosttwo'])]
m_nova.return_value.get_compute_node_by_name.return_value = False
m_scope = [{'id': 5}]
t_nova_cluster = nova.ModelBuilder(mock.Mock())
result = set()
t_nova_cluster._collect_aggregates(m_scope, result)
self.assertEqual(set(['hostone', 'hosttwo']), result)
@mock.patch.object(nova_helper, 'NovaHelper')
def test_collect_zones(self, m_nova):
""""""
m_nova.return_value.get_service_list.return_value = \
[mock.Mock(zone='av_b'),
mock.Mock(zone='av_a', host='hostone')]
m_nova.return_value.get_compute_node_by_name.return_value = False
m_scope = [{'name': 'av_a'}]
t_nova_cluster = nova.ModelBuilder(mock.Mock())
result = set()
t_nova_cluster._collect_zones(m_scope, result)
self.assertEqual(set(['hostone']), result)
@mock.patch.object(nova_helper, 'NovaHelper')
def test_add_physical_layer(self, m_nova):
""""""
m_nova.return_value.get_aggregate_list.return_value = \
[mock.Mock(id=1, name='example'),
mock.Mock(id=5, name='example', hosts=['hostone', 'hosttwo'])]
m_nova.return_value.get_service_list.return_value = \
[mock.Mock(zone='av_b', host='hostthree'),
mock.Mock(zone='av_a', host='hostone')]
m_nova.return_value.get_compute_node_by_name.return_value = False
m_scope = [{"compute": [
{"host_aggregates": [{"id": 5}]},
{"availability_zones": [{"name": "av_a"}]}
]}]
t_nova_cluster = nova.ModelBuilder(mock.Mock())
t_nova_cluster.execute(m_scope)
m_nova.return_value.get_compute_node_by_name.assert_any_call(
'hostone', servers=True)
m_nova.return_value.get_compute_node_by_name.assert_any_call(
'hosttwo', servers=True)
self.assertEqual(
m_nova.return_value.get_compute_node_by_name.call_count, 2)