From 9dabe063699799ebac5c42178650f09c11e0febe Mon Sep 17 00:00:00 2001 From: Vasyl Saienko Date: Fri, 17 Mar 2017 12:06:47 +0200 Subject: [PATCH] Add Ironic multitenancy support This patch adds support to deploy Ironic with separate Neutron network for provisioning baremetal instances. * Add NetworkDeploymentSerializer100 as Ironic multitenancy is supported from Newton, and we will backport this till stable/newton. * Update network scheme generation to create 'vlan' baremetal network, assign IPs to Ironic conductors from this network, make them accessible from baremetal servers. * Add new checkbox at 'Openstack Settings/Additional components' tab which allows to define if separate provisioning network should be used during deployment. This is a trigger to switch ironic deployment to multitenancy case. If not selected old behaviour is kept, 'flat' network is used. The checkbox is shown only when Ironic component is enabled. Change-Id: I861a8b3b046202526d6a856c9f2dca2cfaddc887 Related-Bug: #1588380 --- nailgun/nailgun/consts.py | 4 +- .../serializers/neutron_serializers.py | 169 +++++++++++-- nailgun/nailgun/fixtures/openstack.yaml | 14 + .../orchestrator/deployment_serializers.py | 13 +- .../fuel_statistics/installation_info.py | 3 + .../test_orchestrator_serializer_100.py | 239 ++++++++++++++++++ .../test_orchestrator_serializer_110.py | 15 +- 7 files changed, 422 insertions(+), 35 deletions(-) create mode 100644 nailgun/nailgun/test/integration/test_orchestrator_serializer_100.py diff --git a/nailgun/nailgun/consts.py b/nailgun/nailgun/consts.py index 4c790cc992..fb4290f4fb 100644 --- a/nailgun/nailgun/consts.py +++ b/nailgun/nailgun/consts.py @@ -104,6 +104,7 @@ DEFAULT_BRIDGES_NAMES = Enum( 'br-aux', 'br-baremetal', 'br-ironic', + 'br-bm-phy', names=( 'br_fw_admin', 'br_storage', @@ -115,7 +116,8 @@ DEFAULT_BRIDGES_NAMES = Enum( 'br_mesh', 'br_aux', 'br_baremetal', - 'br_ironic' + 'br_ironic', + 'br_bm_phy' ) ) diff --git a/nailgun/nailgun/extensions/network_manager/serializers/neutron_serializers.py b/nailgun/nailgun/extensions/network_manager/serializers/neutron_serializers.py index f7c16dcad9..5290b7fdc8 100644 --- a/nailgun/nailgun/extensions/network_manager/serializers/neutron_serializers.py +++ b/nailgun/nailgun/extensions/network_manager/serializers/neutron_serializers.py @@ -27,6 +27,7 @@ from nailgun.extensions.network_manager.serializers.base \ import NetworkDeploymentSerializer from nailgun import consts +from nailgun.consts import DEFAULT_BRIDGES_NAMES as DBN from nailgun.db import db from nailgun.db.sqlalchemy import models from nailgun.logger import logger @@ -602,7 +603,7 @@ class NeutronNetworkDeploymentSerializer61( (consts.NEUTRON_SEGMENT_TYPES.gre, consts.NEUTRON_SEGMENT_TYPES.tun): transformations.append( - cls.add_bridge(consts.DEFAULT_BRIDGES_NAMES.br_mesh)) + cls.add_bridge(DBN.br_mesh)) @classmethod def add_bond_interface(cls, transformations, iface, nets_by_ifaces, nm): @@ -792,14 +793,14 @@ class NeutronNetworkDeploymentSerializer61( """ transformations.append(cls.add_bridge( - consts.DEFAULT_BRIDGES_NAMES.br_prv, + DBN.br_prv, provider=consts.NEUTRON_L23_PROVIDERS.ovs)) if not prv_base_ep: - prv_base_ep = consts.DEFAULT_BRIDGES_NAMES.br_aux + prv_base_ep = DBN.br_aux transformations.append(cls.add_bridge(prv_base_ep)) transformations.append(cls.add_patch( - bridges=[consts.DEFAULT_BRIDGES_NAMES.br_prv, prv_base_ep], + bridges=[DBN.br_prv, prv_base_ep], provider=consts.NEUTRON_L23_PROVIDERS.ovs, mtu=65000)) @@ -830,7 +831,7 @@ class NeutronNetworkDeploymentSerializer70( @classmethod def is_valid_non_default_bridge_name(cls, name): """Validate bridge name for non-default network.""" - if name in consts.DEFAULT_BRIDGES_NAMES: + if name in DBN: return False return bool(cls.RE_BRIDGE_NAME.match(name)) @@ -1285,12 +1286,12 @@ class GenerateL23Mixin80(object): def generate_l2(cls, cluster): l2 = super(GenerateL23Mixin80, cls).generate_l2(cluster) l2["phys_nets"]["physnet1"] = { - "bridge": consts.DEFAULT_BRIDGES_NAMES.br_floating, + "bridge": DBN.br_floating, "vlan_range": None } if objects.Cluster.is_component_enabled(cluster, 'ironic'): l2["phys_nets"]["physnet-ironic"] = { - "bridge": consts.DEFAULT_BRIDGES_NAMES.br_ironic, + "bridge": DBN.br_ironic, "vlan_range": None } return l2 @@ -1355,23 +1356,23 @@ class NeutronNetworkDeploymentSerializer80( def get_network_to_endpoint_mapping(cls, node): mapping = { consts.NETWORKS.fuelweb_admin: - consts.DEFAULT_BRIDGES_NAMES.br_fw_admin, + DBN.br_fw_admin, consts.NETWORKS.storage: - consts.DEFAULT_BRIDGES_NAMES.br_storage, + DBN.br_storage, consts.NETWORKS.management: - consts.DEFAULT_BRIDGES_NAMES.br_mgmt} + DBN.br_mgmt} # roles can be assigned to br-ex only in case it has a public IP if objects.Node.should_have_public_with_ip(node): mapping[consts.NETWORKS.public] = \ - consts.DEFAULT_BRIDGES_NAMES.br_ex + DBN.br_ex if node.cluster.network_config.segmentation_type in \ (consts.NEUTRON_SEGMENT_TYPES.gre, consts.NEUTRON_SEGMENT_TYPES.tun): mapping[consts.NETWORKS.private] = \ - consts.DEFAULT_BRIDGES_NAMES.br_mesh + DBN.br_mesh if objects.Cluster.is_component_enabled(node.cluster, 'ironic'): mapping[consts.NETWORKS.baremetal] = \ - consts.DEFAULT_BRIDGES_NAMES.br_baremetal + DBN.br_baremetal mapping.update(cls.get_node_non_default_bridge_mapping(node)) return mapping @@ -1383,12 +1384,12 @@ class NeutronNetworkDeploymentSerializer80( is_public, prv_base_ep)) if objects.Cluster.is_component_enabled(node.cluster, 'ironic'): transformations.insert(0, cls.add_bridge( - consts.DEFAULT_BRIDGES_NAMES.br_baremetal)) + DBN.br_baremetal)) transformations.append(cls.add_bridge( - consts.DEFAULT_BRIDGES_NAMES.br_ironic, provider='ovs')) + DBN.br_ironic, provider='ovs')) transformations.append(cls.add_patch( - bridges=[consts.DEFAULT_BRIDGES_NAMES.br_ironic, - consts.DEFAULT_BRIDGES_NAMES.br_baremetal], + bridges=[DBN.br_ironic, + DBN.br_baremetal], provider='ovs')) return transformations @@ -1489,9 +1490,9 @@ class DPDKSerializerMixin90(object): vendor_specific = {'datapath_type': 'netdev'} if node.cluster.network_config.segmentation_type == \ consts.NEUTRON_SEGMENT_TYPES.vlan: - br_name = consts.DEFAULT_BRIDGES_NAMES.br_prv + br_name = DBN.br_prv else: - br_name = consts.DEFAULT_BRIDGES_NAMES.br_mesh + br_name = DBN.br_mesh vlan_id = objects.NetworkGroup.get_node_network_by_name( node, 'private').vlan_start if vlan_id: @@ -1653,18 +1654,142 @@ class NeutronNetworkTemplateSerializer90( pass -class NeutronNetworkTemplateSerializer110( +class NeutronNetworkTemplateSerializer100( NeutronNetworkTemplateSerializer90 ): pass -class NeutronNetworkDeploymentSerializer110( +class NeutronNetworkDeploymentSerializer100( NeutronNetworkDeploymentSerializer90 ): + + @classmethod + def _is_ironic_multitenancy_enabled(cls, cluster): + """Check if ironic multitenancy is enabled.""" + return bool( + utils.get_in( + cluster.attributes.editable, + 'ironic_settings', + 'ironic_provision_network', + 'value' + ) + ) + + @classmethod + def _generate_baremetal_network(cls, cluster): + ng = objects.NetworkGroup.get_from_node_group_by_name( + objects.Cluster.get_default_group(cluster).id, 'baremetal') + + network_type = 'flat' + segment_id = None + shared = True + if cls._is_ironic_multitenancy_enabled(cluster): + network_type = 'vlan' + segment_id = ng.vlan_start + shared = False + return { + "L3": { + "subnet": ng.cidr, + "nameservers": cluster.network_config.dns_nameservers, + "gateway": cluster.network_config.baremetal_gateway, + "floating": utils.join_range( + cluster.network_config.baremetal_range), + "enable_dhcp": True + }, + "L2": { + "network_type": network_type, + "segment_id": segment_id, + "router_ext": False, + "physnet": "physnet-ironic" + }, + "tenant": objects.Cluster.get_creds( + cluster)['tenant']['value'], + "shared": shared + } + + @classmethod + def generate_l2(cls, cluster): + l2 = super(NeutronNetworkDeploymentSerializer100, + cls).generate_l2(cluster) + + if (objects.Cluster.is_component_enabled(cluster, 'ironic') and + cls._is_ironic_multitenancy_enabled(cluster)): + ng = objects.NetworkGroup.get_from_node_group_by_name( + objects.Cluster.get_default_group(cluster).id, 'baremetal') + vlan_range = "{0}:{0}".format(ng.vlan_start) + l2["phys_nets"]["physnet-ironic"] = { + "bridge": DBN.br_ironic, + "vlan_range": vlan_range + } + return l2 + + @classmethod + def generate_transformations(cls, node, nm, nets_by_ifaces, is_public, + prv_base_ep): + transformations = ( + super(NeutronNetworkDeploymentSerializer100, cls) + .generate_transformations( + node, nm, nets_by_ifaces, is_public, prv_base_ep)) + + if (objects.Cluster.is_component_enabled(node.cluster, 'ironic') and + cls._is_ironic_multitenancy_enabled(node.cluster)): + transformations.insert(0, {'action': 'add-br', + 'name': DBN.br_bm_phy}) + netgroup = nm.get_network_by_netname('baremetal', + node.network_data) + br_bm_phy_sub = '{0}.{1}'.format(DBN.br_bm_phy, netgroup['vlan']) + bm_phy_configured = False + for t in transformations: + action = t.get('action') + # Each transformation can be matched with the only one + # condition at a time. + if (action == 'add-patch' and + t.get('bridges') == [DBN.br_ironic, + DBN.br_baremetal]): + t['bridges'] = [DBN.br_ironic, + DBN.br_bm_phy] + elif (action == 'add-port' and + t.get('name') == netgroup['dev']): + transformations.append( + cls.add_patch(bridges=[DBN.br_bm_phy, + t.get('bridge')])) + bm_phy_configured = True + elif (action == 'add-port' and + t.get('bridge') == DBN.br_baremetal): + t['name'] = br_bm_phy_sub + # This is possible when only baremetal network is assigned to + # interface. Add physical interface to br-bm-phy in this case. + if not bm_phy_configured: + transformations.append(cls.add_port(netgroup['dev'], + DBN.br_bm_phy)) + + return transformations + + @classmethod + def generate_network_scheme(cls, node, networks): + attrs = super(NeutronNetworkDeploymentSerializer100, + cls).generate_network_scheme(node, networks) + + if (objects.Cluster.is_component_enabled(node.cluster, 'ironic') and + cls._is_ironic_multitenancy_enabled(node.cluster)): + attrs['endpoints'][DBN.br_ironic] = {'IP': 'none'} + + return attrs + + +class NeutronNetworkTemplateSerializer110( + NeutronNetworkTemplateSerializer100 +): + pass + + +class NeutronNetworkDeploymentSerializer110( + NeutronNetworkDeploymentSerializer100, +): @classmethod def generate_transformations_by_segmentation_type( - cls, node, nm, transformations, prv_base_ep, nets_by_ifaces + cls, node, nm, transformations, prv_base_ep, nets_by_ifaces ): (super(NeutronNetworkDeploymentSerializer110, cls) .generate_transformations_by_segmentation_type( diff --git a/nailgun/nailgun/fixtures/openstack.yaml b/nailgun/nailgun/fixtures/openstack.yaml index ce5790b7b6..f809db98e5 100644 --- a/nailgun/nailgun/fixtures/openstack.yaml +++ b/nailgun/nailgun/fixtures/openstack.yaml @@ -948,6 +948,20 @@ description: "Name for Mongo replication set" weight: 30 type: "text" + ironic_settings: + metadata: + label: "Ironic Settings" + weight: 40 + group: "openstack_services" + restrictions: + - condition: "settings:additional_components.ironic.value == false" + action: "hide" + ironic_provision_network: + value: false + label: "Use separate provisioning network" + description: "When selected Ironic instance will be provisioned in separate network." + weight: 10 + type: "checkbox" additional_components: metadata: label: "Additional Components" diff --git a/nailgun/nailgun/orchestrator/deployment_serializers.py b/nailgun/nailgun/orchestrator/deployment_serializers.py index eb40f5a7bd..257494c2e6 100644 --- a/nailgun/nailgun/orchestrator/deployment_serializers.py +++ b/nailgun/nailgun/orchestrator/deployment_serializers.py @@ -809,7 +809,17 @@ class DeploymentLCMSerializer(DeploymentHASerializer90): return serialized_node -class DeploymentLCMSerializer110(DeploymentLCMSerializer): +class DeploymentLCMSerializer100(DeploymentLCMSerializer): + + @classmethod + def get_net_provider_serializer(cls, cluster): + if cluster.network_config.configuration_template: + return neutron_serializers.NeutronNetworkTemplateSerializer100 + else: + return neutron_serializers.NeutronNetworkDeploymentSerializer100 + + +class DeploymentLCMSerializer110(DeploymentLCMSerializer100): @classmethod def get_net_provider_serializer(cls, cluster): @@ -897,6 +907,7 @@ def serialize_for_lcm(cluster, nodes, ignore_customized=False, skip_extensions=False): serializers_map = { 'default': DeploymentLCMSerializer, + '10.0': DeploymentLCMSerializer100, '11.0': DeploymentLCMSerializer110, } diff --git a/nailgun/nailgun/statistics/fuel_statistics/installation_info.py b/nailgun/nailgun/statistics/fuel_statistics/installation_info.py index d024cddd0b..6ab460e7c0 100644 --- a/nailgun/nailgun/statistics/fuel_statistics/installation_info.py +++ b/nailgun/nailgun/statistics/fuel_statistics/installation_info.py @@ -157,6 +157,9 @@ class InstallationInfo(object): WhiteListRule(('murano_settings', 'murano_glance_artifacts_plugin', 'value'), 'murano_glance_artifacts_plugin', None), + WhiteListRule(('ironic_settings', + 'ironic_provision_network', 'value'), + 'ironic_provision_network', None), WhiteListRule(('workloads_collector', 'enabled', 'value'), 'workloads_collector_enabled', None), diff --git a/nailgun/nailgun/test/integration/test_orchestrator_serializer_100.py b/nailgun/nailgun/test/integration/test_orchestrator_serializer_100.py new file mode 100644 index 0000000000..d1bd79355e --- /dev/null +++ b/nailgun/nailgun/test/integration/test_orchestrator_serializer_100.py @@ -0,0 +1,239 @@ +# -*- coding: utf-8 -*- + +# Copyright 2016 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. + +from nailgun import consts +from nailgun import objects + +from nailgun.orchestrator import deployment_serializers +from nailgun.orchestrator.deployment_serializers import \ + deployment_info_to_legacy +from nailgun.test.integration.test_orchestrator_serializer import \ + BaseDeploymentSerializer +from nailgun.test.integration import test_orchestrator_serializer_90 + + +from nailgun.extensions.network_manager.serializers.neutron_serializers \ + import NeutronNetworkDeploymentSerializer100 +from nailgun.extensions.network_manager.serializers.neutron_serializers \ + import NeutronNetworkTemplateSerializer100 + + +class TestSerializer100Mixin(object): + env_version = 'newton-10.0' + task_deploy = True + + @classmethod + def create_serializer(cls, cluster): + return deployment_serializers.DeploymentLCMSerializer100() + + @classmethod + def _get_serializer(cluster): + return deployment_serializers.DeploymentLCMSerializer100() + + @staticmethod + def _get_plugins_names(plugins): + """Plugins names for LCM serializers + + Single out since plugin data may contain + , , as well. + + :param nodes: array of plugins data + :returns: singled out names of plugins + """ + return [plugin['name'] for plugin in plugins] + + def _setup_cluster_with_ironic(self, ironic_provision_network, + separate_interface=False): + self.env._set_additional_component(self.cluster, 'ironic', True) + if ironic_provision_network: + objects.Cluster.patch_attributes( + self.cluster, + {'editable': { + 'ironic_settings': { + 'ironic_provision_network': { + 'value': True}}}}) + node = self.env.create_nodes_w_interfaces_count( + 1, 4, cluster_id=self.cluster.id, + roles=['controller', 'ironic'])[0] + + if separate_interface: + nic_1 = node.nic_interfaces[0] + nic_4 = node.nic_interfaces[3] + nets_1 = nic_1.assigned_networks_list + nets_4 = nic_4.assigned_networks_list + for i, net in enumerate(nets_1): + if net['name'] == 'baremetal': + nets_4.append(nets_1.pop(i)) + break + objects.NIC.assign_networks(nic_1, nets_1) + objects.NIC.assign_networks(nic_4, nets_4) + objects.Cluster.prepare_for_deployment(self.cluster) + + +class TestSerializeInterfaceDriversData100( + TestSerializer100Mixin, + test_orchestrator_serializer_90.TestSerializeInterfaceDriversData90 +): + pass + + +class TestDeploymentTasksSerialization100( + TestSerializer100Mixin, + test_orchestrator_serializer_90.TestDeploymentTasksSerialization90 +): + pass + + +class TestNetworkTemplateSerializer100( + TestSerializer100Mixin, + test_orchestrator_serializer_90.TestNetworkTemplateSerializer90 +): + pass + + +class TestNetworkDeploymentSerializer100( + TestSerializer100Mixin, + BaseDeploymentSerializer, +): + + legacy_serializer = NeutronNetworkDeploymentSerializer100 + template_serializer = NeutronNetworkTemplateSerializer100 + + def setUp(self, *args): + super(TestNetworkDeploymentSerializer100, 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.serializer = self.create_serializer(self.cluster) + + def test_baremetal_neutron_attrs_flat(self): + self._setup_cluster_with_ironic(ironic_provision_network=False) + serialized_for_astute = self.serializer.serialize( + self.cluster, self.cluster.nodes) + serialized_for_astute = deployment_info_to_legacy( + serialized_for_astute) + for node in serialized_for_astute: + expected_network = { + "network_type": "flat", + "segment_id": None, + "router_ext": False, + "physnet": "physnet-ironic" + } + self.assertEqual(expected_network, node['quantum_settings'] + ['predefined_networks']['baremetal']['L2']) + self.assertIn("physnet-ironic", + node['quantum_settings']['L2']['phys_nets']) + self.assertEqual(consts.DEFAULT_BRIDGES_NAMES.br_ironic, + (node['quantum_settings']['L2']['phys_nets'] + ["physnet-ironic"]["bridge"])) + self.assertEqual(None, (node['quantum_settings']['L2']['phys_nets'] + ["physnet-ironic"]["vlan_range"])) + + def test_baremetal_neutron_attrs_vlan(self): + self._setup_cluster_with_ironic(ironic_provision_network=True) + serialized_for_astute = self.serializer.serialize( + self.cluster, self.cluster.nodes) + serialized_for_astute = deployment_info_to_legacy( + serialized_for_astute) + for node in serialized_for_astute: + expected_network = { + "network_type": "vlan", + "segment_id": 104, + "router_ext": False, + "physnet": "physnet-ironic" + } + self.assertEqual(expected_network, node['quantum_settings'] + ['predefined_networks']['baremetal']['L2']) + self.assertIn("physnet-ironic", + node['quantum_settings']['L2']['phys_nets']) + self.assertEqual(consts.DEFAULT_BRIDGES_NAMES.br_ironic, + (node['quantum_settings']['L2']['phys_nets'] + ["physnet-ironic"]["bridge"])) + self.assertEqual('104:104', + (node['quantum_settings']['L2']['phys_nets'] + ["physnet-ironic"]["vlan_range"])) + + def test_baremetal_transformations_flat(self): + self._setup_cluster_with_ironic(ironic_provision_network=False) + serialized_for_astute = self.serializer.serialize( + self.cluster, self.cluster.nodes) + serialized_for_astute = deployment_info_to_legacy( + serialized_for_astute) + net_tr = serialized_for_astute[0]['network_scheme']['transformations'] + expected_actions = [ + {'action': 'add-br', 'name': 'br-baremetal'}, + {'action': 'add-port', 'bridge': 'br-baremetal', + 'name': 'eth0.104'}, + {'action': 'add-br', 'name': 'br-ironic', 'provider': 'ovs'}, + {'action': 'add-patch', 'bridges': ['br-ironic', 'br-baremetal'], + 'provider': 'ovs'}] + + for element in expected_actions: + self.assertIn(element, net_tr) + + def test_baremetal_transformations_vlan(self): + self._setup_cluster_with_ironic(ironic_provision_network=True) + serialized_for_astute = self.serializer.serialize( + self.cluster, self.cluster.nodes) + serialized_for_astute = deployment_info_to_legacy( + serialized_for_astute) + net_tr = serialized_for_astute[0]['network_scheme']['transformations'] + expected_actions = [ + {'action': 'add-br', 'name': 'br-bm-phy'}, + {'action': 'add-br', 'name': 'br-baremetal'}, + {'action': 'add-port', 'bridge': 'br-baremetal', + 'name': 'br-bm-phy.104'}, + {'action': 'add-br', 'name': 'br-ironic', 'provider': 'ovs'}, + {'action': 'add-patch', 'bridges': ['br-ironic', 'br-bm-phy'], + 'provider': 'ovs'}, + {'action': 'add-patch', 'bridges': ['br-bm-phy', 'br-fw-admin']}] + + not_expected = [ + {'action': 'add-port', 'bridge': 'br-bm-phy', 'name': u'eth0'}] + + for element in expected_actions: + self.assertIn(element, net_tr) + for elemnet in not_expected: + self.assertNotIn(elemnet, net_tr) + + def test_baremetal_transformations_vlan_baremetal_on_separate_nic(self): + self._setup_cluster_with_ironic(ironic_provision_network=True, + separate_interface=True) + serialized_for_astute = self.serializer.serialize( + self.cluster, self.cluster.nodes) + serialized_for_astute = deployment_info_to_legacy( + serialized_for_astute) + net_tr = serialized_for_astute[0]['network_scheme']['transformations'] + expected_actions = [ + {'action': 'add-br', 'name': 'br-bm-phy'}, + {'action': 'add-br', 'name': 'br-baremetal'}, + {'action': 'add-port', 'bridge': 'br-baremetal', + 'name': 'br-bm-phy.104'}, + {'action': 'add-br', 'name': 'br-ironic', 'provider': 'ovs'}, + {'action': 'add-patch', 'bridges': ['br-ironic', 'br-bm-phy'], + 'provider': 'ovs'}, + {'action': 'add-port', 'bridge': 'br-bm-phy', 'name': u'eth3'}] + + not_expected = [ + {'action': 'add-patch', 'bridges': ['br-bm-phy', 'br-fw-admin']}] + + for element in expected_actions: + self.assertIn(element, net_tr) + for elemnet in not_expected: + self.assertNotIn(elemnet, net_tr) diff --git a/nailgun/nailgun/test/integration/test_orchestrator_serializer_110.py b/nailgun/nailgun/test/integration/test_orchestrator_serializer_110.py index 091cf2a09e..2a0a90b8bb 100644 --- a/nailgun/nailgun/test/integration/test_orchestrator_serializer_110.py +++ b/nailgun/nailgun/test/integration/test_orchestrator_serializer_110.py @@ -16,7 +16,7 @@ from nailgun import consts from nailgun.orchestrator import deployment_serializers -from nailgun.test.integration import test_orchestrator_serializer_90 +from nailgun.test.integration import test_orchestrator_serializer_100 class TestSerializer110Mixin(object): @@ -45,22 +45,15 @@ class TestSerializer110Mixin(object): return [plugin['name'] for plugin in plugins] -class TestDeploymentAttributesSerialization110( +class TestNetworkDeploymentSerializer110( TestSerializer110Mixin, - test_orchestrator_serializer_90.TestDeploymentAttributesSerialization90 -): - pass - - -class TestDeploymentLCMSerialization110( - TestSerializer110Mixin, - test_orchestrator_serializer_90.TestDeploymentLCMSerialization90 + test_orchestrator_serializer_100.TestNetworkDeploymentSerializer100 ): pass class TestSerializeInterfaceDriversData110( TestSerializer110Mixin, - test_orchestrator_serializer_90.TestSerializeInterfaceDriversData90 + test_orchestrator_serializer_100.TestSerializeInterfaceDriversData100 ): pass