# -*- coding: utf-8 -*- # Copyright 2015 Mirantis, 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. import mock import six import nailgun from nailgun import consts from nailgun.db.sqlalchemy import models from nailgun import objects from nailgun import rpc from nailgun.extensions.network_manager.serializers.neutron_serializers import \ NeutronNetworkDeploymentSerializer80 from nailgun.extensions.network_manager.serializers.neutron_serializers import \ NeutronNetworkTemplateSerializer80 from nailgun.orchestrator import deployment_serializers # from nailgun.orchestrator.deployment_serializers import \ # deployment_info_to_legacy from nailgun.orchestrator.deployment_serializers import \ get_serializer_for_cluster from nailgun.test.integration.test_orchestrator_serializer import \ BaseDeploymentSerializer from nailgun.test.integration.test_orchestrator_serializer import \ TestSerializeInterfaceDriversData from nailgun.test.integration.test_orchestrator_serializer_70 import \ TestDeploymentHASerializer70 from nailgun.test.integration.test_orchestrator_serializer_80 import \ TestSerializer80Mixin class TestSerializerWrapper(deployment_serializers.DeploymentLCMSerializer): def serialize(self, cluster, nodes, ignore_customized=False): return deployment_serializers.serialize_for_lcm( cluster, nodes, ignore_customized=ignore_customized) def get_net_provider_serializer(cls, cluster): return deployment_serializers\ .DeploymentHASerializer80.get_net_provider_serializer(cluster) class TestSerializerConverter80To90MixIn(TestSerializer80Mixin): env_version = "liberty-8.0" task_deploy = True is_propagate_task_deploy = True enforce_lcm = True @classmethod def create_serializer(cls, cluster): serializer_type = TestSerializerWrapper return serializer_type(None) class TestNetworkTemplateSerializer80MixIn( TestSerializerConverter80To90MixIn, BaseDeploymentSerializer ): legacy_serializer = NeutronNetworkDeploymentSerializer80 template_serializer = NeutronNetworkTemplateSerializer80 def setUp(self, *args): super(TestNetworkTemplateSerializer80MixIn, self).setUp() self.env.create( release_kwargs={'version': self.env_version}, cluster_kwargs={ 'mode': consts.CLUSTER_MODES.ha_compact, 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron, 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan}) self.net_template = self.env.read_fixtures(['network_template_80'])[0] self.cluster = self.env.clusters[-1] self.cluster.extensions = ['volume_manager', 'converted_serializers'] self.serializer = self.create_serializer(self.cluster) def test_get_net_provider_serializer(self): self.cluster.network_config.configuration_template = None net_serializer = self.serializer.\ get_net_provider_serializer(self.cluster) self.assertIs(net_serializer, self.legacy_serializer) self.cluster.network_config.configuration_template = \ self.net_template net_serializer = self.serializer.\ get_net_provider_serializer(self.cluster) self.assertIs(net_serializer, self.template_serializer) # def test_baremetal_neutron_attrs(self): # brmtl_template = deepcopy( # self.net_template['adv_net_template']['default']) # brmtl_template['network_assignments']['baremetal'] = { # 'ep': 'br-baremetal'} # brmtl_template['templates_for_node_role']['controller'].append( # 'baremetal') # brmtl_template['nic_mapping']['default']['if8'] = 'eth7' # brmtl_template['network_scheme']['baremetal'] = { # 'endpoints': ['br-baremetal'], # 'transformations': [], # 'roles': {'baremetal': 'br-baremetal'}} # self.cluster.network_config.configuration_template = { # 'adv_net_template': {'default': brmtl_template}, 'pk': 1} # self._check_baremetal_neutron_attrs(self.cluster) def test_network_schemes_priorities(self): expected = [ { "action": "add-br", "name": "br-prv", "provider": "ovs" }, { "action": "add-br", "name": "br-aux" }, { "action": "add-patch", "bridges": [ "br-prv", "br-aux" ], "provider": "ovs", "mtu": 65000 }, { "action": "add-port", "bridge": "br-aux", "name": "eth3.101" }, { "action": "add-br", "name": "br-fw-admin" }, { "action": "add-port", "bridge": "br-fw-admin", "name": "eth0" }, { "action": "add-br", "name": "br-mgmt" }, { "action": "add-port", "bridge": "br-mgmt", "name": "eth1.104" }, { "action": "add-br", "name": "br-storage" }, { "action": "add-port", "bridge": "br-storage", "name": "eth2" } ] objects.Cluster.set_network_template( self.cluster, self.net_template ) node = self.env.create_nodes_w_interfaces_count( 1, 8, roles=['compute', 'cinder'], cluster_id=self.cluster.id )[0] self.serializer = get_serializer_for_cluster(self.cluster) net_serializer = self.serializer.get_net_provider_serializer( self.cluster) nm = objects.Cluster.get_network_manager(self.cluster) network_scheme = net_serializer.generate_network_scheme( node, nm.get_node_networks(node)) self.assertEqual(expected, network_scheme['transformations']) class TestDeploymentTasksSerialization80MixIn( TestSerializerConverter80To90MixIn, BaseDeploymentSerializer ): tasks_for_rerun = {"globals", "netconfig"} def setUp(self): super(TestDeploymentTasksSerialization80MixIn, self).setUp() self.env.create( release_kwargs={'version': self.env_version}, cluster_kwargs={ 'mode': consts.CLUSTER_MODES.ha_compact, 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron, 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan, 'status': consts.CLUSTER_STATUSES.operational}, nodes_kwargs=[ {'roles': ['controller'], 'status': consts.NODE_STATUSES.ready}] ) self.cluster = self.env.clusters[-1] self.cluster.extensions = ['volume_manager', 'converted_serializers'] if not self.task_deploy: self.env.disable_task_deploy(self.cluster) def add_node(self, role): return self.env.create_node( cluster_id=self.cluster.id, pending_roles=[role], pending_addition=True ) def get_rpc_args(self): self.env.launch_deployment() args, kwargs = nailgun.task.manager.rpc.cast.call_args return args[1][1]['args'] def check_add_node_for_task_deploy(self, rpc_message): tasks_graph = rpc_message['tasks_graph'] for node_id, tasks in six.iteritems(tasks_graph): if node_id is None or node_id == consts.MASTER_NODE_UID: # skip virtual node continue task_ids = { t['id'] for t in tasks if t['type'] != consts.ORCHESTRATOR_TASK_TYPES.skipped } # all tasks are run on all nodes self.assertTrue(self.tasks_for_rerun.issubset(task_ids)) def check_add_compute_for_granular_deploy(self, new_node_uid, rpc_message): for node in rpc_message['deployment_info']: task_ids = {t['id'] for t in node['tasks']} if node['tasks'][0]['uids'] == [new_node_uid]: # all tasks are run on a new node self.assertTrue( self.tasks_for_rerun.issubset(task_ids)) else: # only selected tasks are run on a deployed node self.assertItemsEqual(self.tasks_for_rerun, task_ids) def check_add_controller_for_granular_deploy(self, rpc_message): for node in rpc_message['deployment_info']: task_ids = {t['id'] for t in node['tasks']} # controller is redeployed when other one is added # so all tasks are run on all nodes self.assertTrue( self.tasks_for_rerun.issubset(task_ids)) # @mock.patch('nailgun.rpc.cast') # def test_add_compute(self, _): # new_node = self.add_node('compute') # rpc_deploy_message = self.get_rpc_args() # if self.task_deploy: # self.check_add_node_for_task_deploy(rpc_deploy_message) # else: # self.check_add_compute_for_granular_deploy( # new_node.uid, rpc_deploy_message # ) # @mock.patch('nailgun.rpc.cast') # def test_add_controller(self, _): # self.add_node('controller') # rpc_deploy_message = self.get_rpc_args() # # if self.task_deploy: # self.check_add_node_for_task_deploy(rpc_deploy_message) # else: # self.check_add_controller_for_granular_deploy(rpc_deploy_message) class TestDeploymentAttributesSerialization80MixIn( TestSerializerConverter80To90MixIn, BaseDeploymentSerializer ): def setUp(self): super(TestDeploymentAttributesSerialization80MixIn, self).setUp() self.cluster = self.env.create( release_kwargs={ 'version': self.env_version, 'operating_system': consts.RELEASE_OS.ubuntu}, cluster_kwargs={ 'mode': consts.CLUSTER_MODES.ha_compact, 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron, 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan}) self.cluster_db = self.db.query(models.Cluster).get(self.cluster['id']) self.cluster.extensions = ['volume_manager', 'converted_serializers'] self.serializer = self.create_serializer(self.cluster_db) # def test_neutron_attrs(self): # self.env.create_node( # cluster_id=self.cluster_db.id, # roles=['controller'], primary_roles=['controller'] # ) # objects.Cluster.prepare_for_deployment(self.cluster_db) # serialized_for_astute = self.serializer.serialize( # self.cluster_db, self.cluster_db.nodes) # serialized_for_astute = deployment_info_to_legacy( # serialized_for_astute) # for node in serialized_for_astute: # self.assertEqual( # { # "bridge": consts.DEFAULT_BRIDGES_NAMES.br_floating, # "vlan_range": None # }, # node['quantum_settings']['L2']['phys_nets']['physnet1'] # ) # l2 = (node["quantum_settings"]["predefined_networks"] # [self.cluster_db.network_config.floating_name]["L2"]) # # self.assertEqual("physnet1", l2["physnet"]) # self.assertEqual("flat", l2["network_type"]) # def test_baremetal_transformations(self): # self.env._set_additional_component(self.cluster_db, 'ironic', True) # self.env.create_node(cluster_id=self.cluster_db.id, # roles=['primary-controller']) # objects.Cluster.prepare_for_deployment(self.cluster_db) # serialized_for_astute = self.serializer.serialize( # self.cluster_db, self.cluster_db.nodes) # for node in serialized_for_astute: # if node['uid'] == 'master': # continue # transformations = node['network_scheme']['transformations'] # baremetal_brs = filter(lambda t: t.get('name') == # consts.DEFAULT_BRIDGES_NAMES.br_baremetal, # transformations) # baremetal_ports = filter(lambda t: t.get('name') == "eth0.104", # transformations) # expected_patch = { # 'action': 'add-patch', # 'bridges': [consts.DEFAULT_BRIDGES_NAMES.br_ironic, # consts.DEFAULT_BRIDGES_NAMES.br_baremetal], # 'provider': 'ovs'} # self.assertEqual(len(baremetal_brs), 1) # self.assertEqual(len(baremetal_ports), 1) # self.assertEqual(baremetal_ports[0]['bridge'], # consts.DEFAULT_BRIDGES_NAMES.br_baremetal) # self.assertIn(expected_patch, transformations) # def test_disks_attrs(self): # disks = [ # { # "model": "TOSHIBA MK1002TS", # "name": "sda", # "disk": "sda", # "size": 1004886016 # }, # ] # expected_node_volumes_hash = [ # { # u'name': u'sda', # u'bootable': True, # u'extra': [], # u'free_space': 330, # u'volumes': [ # { # u'type': u'boot', # u'size': 300 # }, # { # u'mount': u'/boot', # u'type': u'partition', # u'file_system': u'ext2', # u'name': u'Boot', # u'size': 200 # }, # { # u'type': u'lvm_meta_pool', # u'size': 64 # }, # { # u'vg': u'os', # u'type': u'pv', # u'lvm_meta_size': 64, # u'size': 394 # }, # { # u'vg': u'vm', # u'type': u'pv', # u'lvm_meta_size': 0, # u'size': 0 # } # ], # u'type': u'disk', # u'id': u'sda', # u'size': 958 # }, # { # u'_allocate_size': u'min', # u'label': u'Base System', # u'min_size': 19456, # u'volumes': [ # { # u'mount': u'/', # u'size': -3766, # u'type': u'lv', # u'name': u'root', # u'file_system': u'ext4' # }, # { # u'mount': u'swap', # u'size': 4096, # u'type': u'lv', # u'name': u'swap', # u'file_system': u'swap' # } # ], # u'type': u'vg', # u'id': u'os' # }, # { # u'_allocate_size': u'all', # u'label': u'Virtual Storage', # u'min_size': 5120, # u'volumes': [ # { # u'mount': u'/var/lib/nova', # u'size': 0, # u'type': u'lv', # u'name': u'nova', # u'file_system': u'xfs' # } # ], # u'type': u'vg', # u'id': u'vm' # } # ] # self.env.create_node( # cluster_id=self.cluster_db.id, # roles=['compute'], # meta={"disks": disks}, # ) # objects.Cluster.prepare_for_deployment(self.cluster_db) # serialized_for_astute = self.serializer.serialize( # self.cluster_db, self.cluster_db.nodes) # for node in serialized_for_astute: # if node['uid'] == 'master': # continue # self.assertIn("node_volumes", node) # self.assertItemsEqual( # expected_node_volumes_hash, node["node_volumes"]) # def test_attributes_contains_plugins(self): # self.env.create_plugin( # cluster=self.cluster_db, # name='plugin_1', # attributes_metadata={'attributes': {'name': 'plugin_1'}}, # package_version='4.0.0', # fuel_version=['8.0']) # self.env.create_plugin( # cluster=self.cluster_db, # name='plugin_2', # attributes_metadata={'attributes': {'name': 'plugin_2'}}, # package_version='4.0.0', # fuel_version=['8.0']) # self.env.create_plugin( # cluster=self.cluster_db, # enabled=False, # name='plugin_3', # attributes_metadata={'attributes': {'name': 'plugin_3'}}, # package_version='4.0.0', # fuel_version=['8.0']) expected_plugins_list = ['plugin_1', 'plugin_2'] self.env.create_node( cluster_id=self.cluster_db.id, roles=['compute'] ) objects.Cluster.prepare_for_deployment(self.cluster_db) serialized_for_astute = self.serializer.serialize( self.cluster_db, self.cluster_db.nodes) for node in serialized_for_astute: if node['uid'] == 'master': continue self.assertIn('plugins', node) self.assertItemsEqual( expected_plugins_list, node['plugins']) self.assertTrue(all(name in node for name in expected_plugins_list)) # def test_common_attributes_contains_plugin_metadata(self): # expected_value = 'check_value' # plugin = self.env.create_plugin( # cluster=self.cluster_db, # name='test_plugin', # package_version='4.0.0', # fuel_version=['8.0'], # attributes_metadata={ # 'attributes': { # 'config': { # 'description': "Description", # 'weight': 52, # 'value': expected_value # } # } # } # ) # attrs = self.serializer.get_common_attrs(self.cluster_db) # self.assertIn('test_plugin', attrs) # self.assertIn('metadata', attrs['test_plugin']) # self.assertEqual( # plugin.id, attrs['test_plugin']['metadata']['plugin_id'] # ) # self.assertEqual(expected_value, attrs['test_plugin']['config']) class TestMultiNodeGroupsSerialization80MixIn( TestSerializerConverter80To90MixIn, BaseDeploymentSerializer ): def setUp(self): super(TestMultiNodeGroupsSerialization80MixIn, self).setUp() cluster = self.env.create( release_kwargs={'version': self.env_version}, cluster_kwargs={ 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron, 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan} ) self.env.create_nodes_w_interfaces_count( nodes_count=3, if_count=2, roles=['controller', 'cinder'], pending_addition=True, cluster_id=cluster['id']) self.cluster_db = self.db.query(models.Cluster).get(cluster['id']) cluster.extensions = ['volume_manager', 'converted_serializers'] self.serializer = self.create_serializer(cluster) def _add_node_group_with_node(self, cidr_start, node_address): node_group = self.env.create_node_group( api=False, cluster_id=self.cluster_db.id, name='ng_' + cidr_start + '_' + str(node_address)) with mock.patch.object(rpc, 'cast'): resp = self.env.setup_networks_for_nodegroup( cluster_id=self.cluster_db.id, node_group=node_group, cidr_start=cidr_start) self.assertEqual(resp.status_code, 200) self.db.query(models.Task).filter_by( name=consts.TASK_NAMES.update_dnsmasq ).delete(synchronize_session=False) self.env.create_nodes_w_interfaces_count( nodes_count=1, if_count=2, roles=['compute'], pending_addition=True, cluster_id=self.cluster_db.id, group_id=node_group.id, ip='{0}.9.{1}'.format(cidr_start, node_address)) def _check_routes_count(self, count): objects.Cluster.prepare_for_deployment(self.cluster_db) facts = self.serializer.serialize( self.cluster_db, self.cluster_db.nodes) for node in facts: if node['uid'] == 'master': continue endpoints = node['network_scheme']['endpoints'] for name, descr in six.iteritems(endpoints): if descr['IP'] == 'none': self.assertNotIn('routes', descr) else: self.assertEqual(len(descr['routes']), count) # def test_routes_with_no_shared_networks_2_nodegroups(self): # self._add_node_group_with_node('199.99', 3) # # all networks have different CIDRs # self._check_routes_count(1) # def test_routes_with_no_shared_networks_3_nodegroups(self): # self._add_node_group_with_node('199.99', 3) # self._add_node_group_with_node('199.77', 3) # # all networks have different CIDRs # self._check_routes_count(2) # def test_routes_with_shared_networks_3_nodegroups(self): # self._add_node_group_with_node('199.99', 3) # self._add_node_group_with_node('199.99', 4) # # networks in two racks have equal CIDRs # self._check_routes_count(1) # class TestBlockDeviceDevicesSerialization80MixIn( # TestSerializerConverter80To90MixIn, # BaseDeploymentSerializer # ): # def setUp(self): # super(TestBlockDeviceDevicesSerialization80MixIn, self).setUp() # self.cluster = self.env.create( # release_kwargs={'version': self.env_version}, # cluster_kwargs={ # 'mode': consts.CLUSTER_MODES.ha_compact, # 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron, # 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan}) # self.cluster_db = self.db.query(models.Cluster). # get(self.cluster['id']) # self.cluster.extensions = ['volume_manager', 'converted_serializers'] # self.serializer = self.create_serializer(self.cluster_db) # # def test_block_device_disks(self): # self.env.create_node( # cluster_id=self.cluster_db.id, # roles=['cinder-block-device'] # ) # self.env.create_node( # cluster_id=self.cluster_db.id, # roles=['controller'] # ) # objects.Cluster.prepare_for_deployment(self.cluster_db) # serialized_for_astute = self.serializer.serialize( # self.cluster_db, self.cluster_db.nodes) # for node in serialized_for_astute: # if node['uid'] == 'master': # continue # self.assertIn("node_volumes", node) # for node_volume in node["node_volumes"]: # if node_volume["id"] == "cinder-block-device": # self.assertEqual(node_volume["volumes"], []) # else: # self.assertNotEqual(node_volume["volumes"], []) class TestSerializeInterfaceDriversData80MixIn( TestSerializerConverter80To90MixIn, TestSerializeInterfaceDriversData ): pass class TestDeploymentHASerializer80MixIn( TestSerializerConverter80To90MixIn, TestDeploymentHASerializer70 ): pass