summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasyl Saienko <vsaienko@mirantis.com>2017-03-17 12:06:47 +0200
committerVasyl Saienko <vsaienko@mirantis.com>2017-03-31 10:21:34 +0300
commit9dabe063699799ebac5c42178650f09c11e0febe (patch)
treef36e2d39c9b6be30bed5f8d9c8f2ed5c6563cb03
parent738066cdca67baec683c15d4b48679fe0a505405 (diff)
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
Notes
Notes (review): Verified+1: Fuel CI <fuel-ci-bot@mirantis.com> Code-Review+2: Aleksey Kasatkin <akasatkin@mirantis.com> Code-Review+2: Alexander Kislitsky <akislitsky@mirantis.com> Workflow+1: Vladimir Kuklin <vkuklin@mirantis.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Mon, 03 Apr 2017 14:42:28 +0000 Reviewed-on: https://review.openstack.org/444863 Project: openstack/fuel-web Branch: refs/heads/master
-rw-r--r--nailgun/nailgun/consts.py4
-rw-r--r--nailgun/nailgun/extensions/network_manager/serializers/neutron_serializers.py169
-rw-r--r--nailgun/nailgun/fixtures/openstack.yaml14
-rw-r--r--nailgun/nailgun/orchestrator/deployment_serializers.py13
-rw-r--r--nailgun/nailgun/statistics/fuel_statistics/installation_info.py3
-rw-r--r--nailgun/nailgun/test/integration/test_orchestrator_serializer_100.py239
-rw-r--r--nailgun/nailgun/test/integration/test_orchestrator_serializer_110.py15
7 files changed, 422 insertions, 35 deletions
diff --git a/nailgun/nailgun/consts.py b/nailgun/nailgun/consts.py
index 4c790cc..fb4290f 100644
--- a/nailgun/nailgun/consts.py
+++ b/nailgun/nailgun/consts.py
@@ -104,6 +104,7 @@ DEFAULT_BRIDGES_NAMES = Enum(
104 'br-aux', 104 'br-aux',
105 'br-baremetal', 105 'br-baremetal',
106 'br-ironic', 106 'br-ironic',
107 'br-bm-phy',
107 names=( 108 names=(
108 'br_fw_admin', 109 'br_fw_admin',
109 'br_storage', 110 'br_storage',
@@ -115,7 +116,8 @@ DEFAULT_BRIDGES_NAMES = Enum(
115 'br_mesh', 116 'br_mesh',
116 'br_aux', 117 'br_aux',
117 'br_baremetal', 118 'br_baremetal',
118 'br_ironic' 119 'br_ironic',
120 'br_bm_phy'
119 ) 121 )
120) 122)
121 123
diff --git a/nailgun/nailgun/extensions/network_manager/serializers/neutron_serializers.py b/nailgun/nailgun/extensions/network_manager/serializers/neutron_serializers.py
index f7c16dc..5290b7f 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 \
27 import NetworkDeploymentSerializer 27 import NetworkDeploymentSerializer
28 28
29from nailgun import consts 29from nailgun import consts
30from nailgun.consts import DEFAULT_BRIDGES_NAMES as DBN
30from nailgun.db import db 31from nailgun.db import db
31from nailgun.db.sqlalchemy import models 32from nailgun.db.sqlalchemy import models
32from nailgun.logger import logger 33from nailgun.logger import logger
@@ -602,7 +603,7 @@ class NeutronNetworkDeploymentSerializer61(
602 (consts.NEUTRON_SEGMENT_TYPES.gre, 603 (consts.NEUTRON_SEGMENT_TYPES.gre,
603 consts.NEUTRON_SEGMENT_TYPES.tun): 604 consts.NEUTRON_SEGMENT_TYPES.tun):
604 transformations.append( 605 transformations.append(
605 cls.add_bridge(consts.DEFAULT_BRIDGES_NAMES.br_mesh)) 606 cls.add_bridge(DBN.br_mesh))
606 607
607 @classmethod 608 @classmethod
608 def add_bond_interface(cls, transformations, iface, nets_by_ifaces, nm): 609 def add_bond_interface(cls, transformations, iface, nets_by_ifaces, nm):
@@ -792,14 +793,14 @@ class NeutronNetworkDeploymentSerializer61(
792 """ 793 """
793 794
794 transformations.append(cls.add_bridge( 795 transformations.append(cls.add_bridge(
795 consts.DEFAULT_BRIDGES_NAMES.br_prv, 796 DBN.br_prv,
796 provider=consts.NEUTRON_L23_PROVIDERS.ovs)) 797 provider=consts.NEUTRON_L23_PROVIDERS.ovs))
797 if not prv_base_ep: 798 if not prv_base_ep:
798 prv_base_ep = consts.DEFAULT_BRIDGES_NAMES.br_aux 799 prv_base_ep = DBN.br_aux
799 transformations.append(cls.add_bridge(prv_base_ep)) 800 transformations.append(cls.add_bridge(prv_base_ep))
800 801
801 transformations.append(cls.add_patch( 802 transformations.append(cls.add_patch(
802 bridges=[consts.DEFAULT_BRIDGES_NAMES.br_prv, prv_base_ep], 803 bridges=[DBN.br_prv, prv_base_ep],
803 provider=consts.NEUTRON_L23_PROVIDERS.ovs, 804 provider=consts.NEUTRON_L23_PROVIDERS.ovs,
804 mtu=65000)) 805 mtu=65000))
805 806
@@ -830,7 +831,7 @@ class NeutronNetworkDeploymentSerializer70(
830 @classmethod 831 @classmethod
831 def is_valid_non_default_bridge_name(cls, name): 832 def is_valid_non_default_bridge_name(cls, name):
832 """Validate bridge name for non-default network.""" 833 """Validate bridge name for non-default network."""
833 if name in consts.DEFAULT_BRIDGES_NAMES: 834 if name in DBN:
834 return False 835 return False
835 return bool(cls.RE_BRIDGE_NAME.match(name)) 836 return bool(cls.RE_BRIDGE_NAME.match(name))
836 837
@@ -1285,12 +1286,12 @@ class GenerateL23Mixin80(object):
1285 def generate_l2(cls, cluster): 1286 def generate_l2(cls, cluster):
1286 l2 = super(GenerateL23Mixin80, cls).generate_l2(cluster) 1287 l2 = super(GenerateL23Mixin80, cls).generate_l2(cluster)
1287 l2["phys_nets"]["physnet1"] = { 1288 l2["phys_nets"]["physnet1"] = {
1288 "bridge": consts.DEFAULT_BRIDGES_NAMES.br_floating, 1289 "bridge": DBN.br_floating,
1289 "vlan_range": None 1290 "vlan_range": None
1290 } 1291 }
1291 if objects.Cluster.is_component_enabled(cluster, 'ironic'): 1292 if objects.Cluster.is_component_enabled(cluster, 'ironic'):
1292 l2["phys_nets"]["physnet-ironic"] = { 1293 l2["phys_nets"]["physnet-ironic"] = {
1293 "bridge": consts.DEFAULT_BRIDGES_NAMES.br_ironic, 1294 "bridge": DBN.br_ironic,
1294 "vlan_range": None 1295 "vlan_range": None
1295 } 1296 }
1296 return l2 1297 return l2
@@ -1355,23 +1356,23 @@ class NeutronNetworkDeploymentSerializer80(
1355 def get_network_to_endpoint_mapping(cls, node): 1356 def get_network_to_endpoint_mapping(cls, node):
1356 mapping = { 1357 mapping = {
1357 consts.NETWORKS.fuelweb_admin: 1358 consts.NETWORKS.fuelweb_admin:
1358 consts.DEFAULT_BRIDGES_NAMES.br_fw_admin, 1359 DBN.br_fw_admin,
1359 consts.NETWORKS.storage: 1360 consts.NETWORKS.storage:
1360 consts.DEFAULT_BRIDGES_NAMES.br_storage, 1361 DBN.br_storage,
1361 consts.NETWORKS.management: 1362 consts.NETWORKS.management:
1362 consts.DEFAULT_BRIDGES_NAMES.br_mgmt} 1363 DBN.br_mgmt}
1363 # roles can be assigned to br-ex only in case it has a public IP 1364 # roles can be assigned to br-ex only in case it has a public IP
1364 if objects.Node.should_have_public_with_ip(node): 1365 if objects.Node.should_have_public_with_ip(node):
1365 mapping[consts.NETWORKS.public] = \ 1366 mapping[consts.NETWORKS.public] = \
1366 consts.DEFAULT_BRIDGES_NAMES.br_ex 1367 DBN.br_ex
1367 if node.cluster.network_config.segmentation_type in \ 1368 if node.cluster.network_config.segmentation_type in \
1368 (consts.NEUTRON_SEGMENT_TYPES.gre, 1369 (consts.NEUTRON_SEGMENT_TYPES.gre,
1369 consts.NEUTRON_SEGMENT_TYPES.tun): 1370 consts.NEUTRON_SEGMENT_TYPES.tun):
1370 mapping[consts.NETWORKS.private] = \ 1371 mapping[consts.NETWORKS.private] = \
1371 consts.DEFAULT_BRIDGES_NAMES.br_mesh 1372 DBN.br_mesh
1372 if objects.Cluster.is_component_enabled(node.cluster, 'ironic'): 1373 if objects.Cluster.is_component_enabled(node.cluster, 'ironic'):
1373 mapping[consts.NETWORKS.baremetal] = \ 1374 mapping[consts.NETWORKS.baremetal] = \
1374 consts.DEFAULT_BRIDGES_NAMES.br_baremetal 1375 DBN.br_baremetal
1375 mapping.update(cls.get_node_non_default_bridge_mapping(node)) 1376 mapping.update(cls.get_node_non_default_bridge_mapping(node))
1376 return mapping 1377 return mapping
1377 1378
@@ -1383,12 +1384,12 @@ class NeutronNetworkDeploymentSerializer80(
1383 is_public, prv_base_ep)) 1384 is_public, prv_base_ep))
1384 if objects.Cluster.is_component_enabled(node.cluster, 'ironic'): 1385 if objects.Cluster.is_component_enabled(node.cluster, 'ironic'):
1385 transformations.insert(0, cls.add_bridge( 1386 transformations.insert(0, cls.add_bridge(
1386 consts.DEFAULT_BRIDGES_NAMES.br_baremetal)) 1387 DBN.br_baremetal))
1387 transformations.append(cls.add_bridge( 1388 transformations.append(cls.add_bridge(
1388 consts.DEFAULT_BRIDGES_NAMES.br_ironic, provider='ovs')) 1389 DBN.br_ironic, provider='ovs'))
1389 transformations.append(cls.add_patch( 1390 transformations.append(cls.add_patch(
1390 bridges=[consts.DEFAULT_BRIDGES_NAMES.br_ironic, 1391 bridges=[DBN.br_ironic,
1391 consts.DEFAULT_BRIDGES_NAMES.br_baremetal], 1392 DBN.br_baremetal],
1392 provider='ovs')) 1393 provider='ovs'))
1393 return transformations 1394 return transformations
1394 1395
@@ -1489,9 +1490,9 @@ class DPDKSerializerMixin90(object):
1489 vendor_specific = {'datapath_type': 'netdev'} 1490 vendor_specific = {'datapath_type': 'netdev'}
1490 if node.cluster.network_config.segmentation_type == \ 1491 if node.cluster.network_config.segmentation_type == \
1491 consts.NEUTRON_SEGMENT_TYPES.vlan: 1492 consts.NEUTRON_SEGMENT_TYPES.vlan:
1492 br_name = consts.DEFAULT_BRIDGES_NAMES.br_prv 1493 br_name = DBN.br_prv
1493 else: 1494 else:
1494 br_name = consts.DEFAULT_BRIDGES_NAMES.br_mesh 1495 br_name = DBN.br_mesh
1495 vlan_id = objects.NetworkGroup.get_node_network_by_name( 1496 vlan_id = objects.NetworkGroup.get_node_network_by_name(
1496 node, 'private').vlan_start 1497 node, 'private').vlan_start
1497 if vlan_id: 1498 if vlan_id:
@@ -1653,18 +1654,142 @@ class NeutronNetworkTemplateSerializer90(
1653 pass 1654 pass
1654 1655
1655 1656
1656class NeutronNetworkTemplateSerializer110( 1657class NeutronNetworkTemplateSerializer100(
1657 NeutronNetworkTemplateSerializer90 1658 NeutronNetworkTemplateSerializer90
1658): 1659):
1659 pass 1660 pass
1660 1661
1661 1662
1662class NeutronNetworkDeploymentSerializer110( 1663class NeutronNetworkDeploymentSerializer100(
1663 NeutronNetworkDeploymentSerializer90 1664 NeutronNetworkDeploymentSerializer90
1664): 1665):
1666
1667 @classmethod
1668 def _is_ironic_multitenancy_enabled(cls, cluster):
1669 """Check if ironic multitenancy is enabled."""
1670 return bool(
1671 utils.get_in(
1672 cluster.attributes.editable,
1673 'ironic_settings',
1674 'ironic_provision_network',
1675 'value'
1676 )
1677 )
1678
1679 @classmethod
1680 def _generate_baremetal_network(cls, cluster):
1681 ng = objects.NetworkGroup.get_from_node_group_by_name(
1682 objects.Cluster.get_default_group(cluster).id, 'baremetal')
1683
1684 network_type = 'flat'
1685 segment_id = None
1686 shared = True
1687 if cls._is_ironic_multitenancy_enabled(cluster):
1688 network_type = 'vlan'
1689 segment_id = ng.vlan_start
1690 shared = False
1691 return {
1692 "L3": {
1693 "subnet": ng.cidr,
1694 "nameservers": cluster.network_config.dns_nameservers,
1695 "gateway": cluster.network_config.baremetal_gateway,
1696 "floating": utils.join_range(
1697 cluster.network_config.baremetal_range),
1698 "enable_dhcp": True
1699 },
1700 "L2": {
1701 "network_type": network_type,
1702 "segment_id": segment_id,
1703 "router_ext": False,
1704 "physnet": "physnet-ironic"
1705 },
1706 "tenant": objects.Cluster.get_creds(
1707 cluster)['tenant']['value'],
1708 "shared": shared
1709 }
1710
1711 @classmethod
1712 def generate_l2(cls, cluster):
1713 l2 = super(NeutronNetworkDeploymentSerializer100,
1714 cls).generate_l2(cluster)
1715
1716 if (objects.Cluster.is_component_enabled(cluster, 'ironic') and
1717 cls._is_ironic_multitenancy_enabled(cluster)):
1718 ng = objects.NetworkGroup.get_from_node_group_by_name(
1719 objects.Cluster.get_default_group(cluster).id, 'baremetal')
1720 vlan_range = "{0}:{0}".format(ng.vlan_start)
1721 l2["phys_nets"]["physnet-ironic"] = {
1722 "bridge": DBN.br_ironic,
1723 "vlan_range": vlan_range
1724 }
1725 return l2
1726
1727 @classmethod
1728 def generate_transformations(cls, node, nm, nets_by_ifaces, is_public,
1729 prv_base_ep):
1730 transformations = (
1731 super(NeutronNetworkDeploymentSerializer100, cls)
1732 .generate_transformations(
1733 node, nm, nets_by_ifaces, is_public, prv_base_ep))
1734
1735 if (objects.Cluster.is_component_enabled(node.cluster, 'ironic') and
1736 cls._is_ironic_multitenancy_enabled(node.cluster)):
1737 transformations.insert(0, {'action': 'add-br',
1738 'name': DBN.br_bm_phy})
1739 netgroup = nm.get_network_by_netname('baremetal',
1740 node.network_data)
1741 br_bm_phy_sub = '{0}.{1}'.format(DBN.br_bm_phy, netgroup['vlan'])
1742 bm_phy_configured = False
1743 for t in transformations:
1744 action = t.get('action')
1745 # Each transformation can be matched with the only one
1746 # condition at a time.
1747 if (action == 'add-patch' and
1748 t.get('bridges') == [DBN.br_ironic,
1749 DBN.br_baremetal]):
1750 t['bridges'] = [DBN.br_ironic,
1751 DBN.br_bm_phy]
1752 elif (action == 'add-port' and
1753 t.get('name') == netgroup['dev']):
1754 transformations.append(
1755 cls.add_patch(bridges=[DBN.br_bm_phy,
1756 t.get('bridge')]))
1757 bm_phy_configured = True
1758 elif (action == 'add-port' and
1759 t.get('bridge') == DBN.br_baremetal):
1760 t['name'] = br_bm_phy_sub
1761 # This is possible when only baremetal network is assigned to
1762 # interface. Add physical interface to br-bm-phy in this case.
1763 if not bm_phy_configured:
1764 transformations.append(cls.add_port(netgroup['dev'],
1765 DBN.br_bm_phy))
1766
1767 return transformations
1768
1769 @classmethod
1770 def generate_network_scheme(cls, node, networks):
1771 attrs = super(NeutronNetworkDeploymentSerializer100,
1772 cls).generate_network_scheme(node, networks)
1773
1774 if (objects.Cluster.is_component_enabled(node.cluster, 'ironic') and
1775 cls._is_ironic_multitenancy_enabled(node.cluster)):
1776 attrs['endpoints'][DBN.br_ironic] = {'IP': 'none'}
1777
1778 return attrs
1779
1780
1781class NeutronNetworkTemplateSerializer110(
1782 NeutronNetworkTemplateSerializer100
1783):
1784 pass
1785
1786
1787class NeutronNetworkDeploymentSerializer110(
1788 NeutronNetworkDeploymentSerializer100,
1789):
1665 @classmethod 1790 @classmethod
1666 def generate_transformations_by_segmentation_type( 1791 def generate_transformations_by_segmentation_type(
1667 cls, node, nm, transformations, prv_base_ep, nets_by_ifaces 1792 cls, node, nm, transformations, prv_base_ep, nets_by_ifaces
1668 ): 1793 ):
1669 (super(NeutronNetworkDeploymentSerializer110, cls) 1794 (super(NeutronNetworkDeploymentSerializer110, cls)
1670 .generate_transformations_by_segmentation_type( 1795 .generate_transformations_by_segmentation_type(
diff --git a/nailgun/nailgun/fixtures/openstack.yaml b/nailgun/nailgun/fixtures/openstack.yaml
index ce5790b..f809db9 100644
--- a/nailgun/nailgun/fixtures/openstack.yaml
+++ b/nailgun/nailgun/fixtures/openstack.yaml
@@ -948,6 +948,20 @@
948 description: "Name for Mongo replication set" 948 description: "Name for Mongo replication set"
949 weight: 30 949 weight: 30
950 type: "text" 950 type: "text"
951 ironic_settings:
952 metadata:
953 label: "Ironic Settings"
954 weight: 40
955 group: "openstack_services"
956 restrictions:
957 - condition: "settings:additional_components.ironic.value == false"
958 action: "hide"
959 ironic_provision_network:
960 value: false
961 label: "Use separate provisioning network"
962 description: "When selected Ironic instance will be provisioned in separate network."
963 weight: 10
964 type: "checkbox"
951 additional_components: 965 additional_components:
952 metadata: 966 metadata:
953 label: "Additional Components" 967 label: "Additional Components"
diff --git a/nailgun/nailgun/orchestrator/deployment_serializers.py b/nailgun/nailgun/orchestrator/deployment_serializers.py
index eb40f5a..257494c 100644
--- a/nailgun/nailgun/orchestrator/deployment_serializers.py
+++ b/nailgun/nailgun/orchestrator/deployment_serializers.py
@@ -809,7 +809,17 @@ class DeploymentLCMSerializer(DeploymentHASerializer90):
809 return serialized_node 809 return serialized_node
810 810
811 811
812class DeploymentLCMSerializer110(DeploymentLCMSerializer): 812class DeploymentLCMSerializer100(DeploymentLCMSerializer):
813
814 @classmethod
815 def get_net_provider_serializer(cls, cluster):
816 if cluster.network_config.configuration_template:
817 return neutron_serializers.NeutronNetworkTemplateSerializer100
818 else:
819 return neutron_serializers.NeutronNetworkDeploymentSerializer100
820
821
822class DeploymentLCMSerializer110(DeploymentLCMSerializer100):
813 823
814 @classmethod 824 @classmethod
815 def get_net_provider_serializer(cls, cluster): 825 def get_net_provider_serializer(cls, cluster):
@@ -897,6 +907,7 @@ def serialize_for_lcm(cluster, nodes,
897 ignore_customized=False, skip_extensions=False): 907 ignore_customized=False, skip_extensions=False):
898 serializers_map = { 908 serializers_map = {
899 'default': DeploymentLCMSerializer, 909 'default': DeploymentLCMSerializer,
910 '10.0': DeploymentLCMSerializer100,
900 '11.0': DeploymentLCMSerializer110, 911 '11.0': DeploymentLCMSerializer110,
901 } 912 }
902 913
diff --git a/nailgun/nailgun/statistics/fuel_statistics/installation_info.py b/nailgun/nailgun/statistics/fuel_statistics/installation_info.py
index d024cdd..6ab460e 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):
157 WhiteListRule(('murano_settings', 157 WhiteListRule(('murano_settings',
158 'murano_glance_artifacts_plugin', 'value'), 158 'murano_glance_artifacts_plugin', 'value'),
159 'murano_glance_artifacts_plugin', None), 159 'murano_glance_artifacts_plugin', None),
160 WhiteListRule(('ironic_settings',
161 'ironic_provision_network', 'value'),
162 'ironic_provision_network', None),
160 163
161 WhiteListRule(('workloads_collector', 'enabled', 'value'), 164 WhiteListRule(('workloads_collector', 'enabled', 'value'),
162 'workloads_collector_enabled', None), 165 '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 0000000..d1bd793
--- /dev/null
+++ b/nailgun/nailgun/test/integration/test_orchestrator_serializer_100.py
@@ -0,0 +1,239 @@
1# -*- coding: utf-8 -*-
2
3# Copyright 2016 Mirantis, Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17from nailgun import consts
18from nailgun import objects
19
20from nailgun.orchestrator import deployment_serializers
21from nailgun.orchestrator.deployment_serializers import \
22 deployment_info_to_legacy
23from nailgun.test.integration.test_orchestrator_serializer import \
24 BaseDeploymentSerializer
25from nailgun.test.integration import test_orchestrator_serializer_90
26
27
28from nailgun.extensions.network_manager.serializers.neutron_serializers \
29 import NeutronNetworkDeploymentSerializer100
30from nailgun.extensions.network_manager.serializers.neutron_serializers \
31 import NeutronNetworkTemplateSerializer100
32
33
34class TestSerializer100Mixin(object):
35 env_version = 'newton-10.0'
36 task_deploy = True
37
38 @classmethod
39 def create_serializer(cls, cluster):
40 return deployment_serializers.DeploymentLCMSerializer100()
41
42 @classmethod
43 def _get_serializer(cluster):
44 return deployment_serializers.DeploymentLCMSerializer100()
45
46 @staticmethod
47 def _get_plugins_names(plugins):
48 """Plugins names for LCM serializers
49
50 Single out <name> since plugin data may contain
51 <scripts>, <repositories>, <whatever> as well.
52
53 :param nodes: array of plugins data
54 :returns: singled out names of plugins
55 """
56 return [plugin['name'] for plugin in plugins]
57
58 def _setup_cluster_with_ironic(self, ironic_provision_network,
59 separate_interface=False):
60 self.env._set_additional_component(self.cluster, 'ironic', True)
61 if ironic_provision_network:
62 objects.Cluster.patch_attributes(
63 self.cluster,
64 {'editable': {
65 'ironic_settings': {
66 'ironic_provision_network': {
67 'value': True}}}})
68 node = self.env.create_nodes_w_interfaces_count(
69 1, 4, cluster_id=self.cluster.id,
70 roles=['controller', 'ironic'])[0]
71
72 if separate_interface:
73 nic_1 = node.nic_interfaces[0]
74 nic_4 = node.nic_interfaces[3]
75 nets_1 = nic_1.assigned_networks_list
76 nets_4 = nic_4.assigned_networks_list
77 for i, net in enumerate(nets_1):
78 if net['name'] == 'baremetal':
79 nets_4.append(nets_1.pop(i))
80 break
81 objects.NIC.assign_networks(nic_1, nets_1)
82 objects.NIC.assign_networks(nic_4, nets_4)
83 objects.Cluster.prepare_for_deployment(self.cluster)
84
85
86class TestSerializeInterfaceDriversData100(
87 TestSerializer100Mixin,
88 test_orchestrator_serializer_90.TestSerializeInterfaceDriversData90
89):
90 pass
91
92
93class TestDeploymentTasksSerialization100(
94 TestSerializer100Mixin,
95 test_orchestrator_serializer_90.TestDeploymentTasksSerialization90
96):
97 pass
98
99
100class TestNetworkTemplateSerializer100(
101 TestSerializer100Mixin,
102 test_orchestrator_serializer_90.TestNetworkTemplateSerializer90
103):
104 pass
105
106
107class TestNetworkDeploymentSerializer100(
108 TestSerializer100Mixin,
109 BaseDeploymentSerializer,
110):
111
112 legacy_serializer = NeutronNetworkDeploymentSerializer100
113 template_serializer = NeutronNetworkTemplateSerializer100
114
115 def setUp(self, *args):
116 super(TestNetworkDeploymentSerializer100, self).setUp()
117 self.cluster = self.env.create(
118 release_kwargs={'version': self.env_version},
119 cluster_kwargs={
120 'mode': consts.CLUSTER_MODES.ha_compact,
121 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
122 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan})
123 self.serializer = self.create_serializer(self.cluster)
124
125 def test_baremetal_neutron_attrs_flat(self):
126 self._setup_cluster_with_ironic(ironic_provision_network=False)
127 serialized_for_astute = self.serializer.serialize(
128 self.cluster, self.cluster.nodes)
129 serialized_for_astute = deployment_info_to_legacy(
130 serialized_for_astute)
131 for node in serialized_for_astute:
132 expected_network = {
133 "network_type": "flat",
134 "segment_id": None,
135 "router_ext": False,
136 "physnet": "physnet-ironic"
137 }
138 self.assertEqual(expected_network, node['quantum_settings']
139 ['predefined_networks']['baremetal']['L2'])
140 self.assertIn("physnet-ironic",
141 node['quantum_settings']['L2']['phys_nets'])
142 self.assertEqual(consts.DEFAULT_BRIDGES_NAMES.br_ironic,
143 (node['quantum_settings']['L2']['phys_nets']
144 ["physnet-ironic"]["bridge"]))
145 self.assertEqual(None, (node['quantum_settings']['L2']['phys_nets']
146 ["physnet-ironic"]["vlan_range"]))
147
148 def test_baremetal_neutron_attrs_vlan(self):
149 self._setup_cluster_with_ironic(ironic_provision_network=True)
150 serialized_for_astute = self.serializer.serialize(
151 self.cluster, self.cluster.nodes)
152 serialized_for_astute = deployment_info_to_legacy(
153 serialized_for_astute)
154 for node in serialized_for_astute:
155 expected_network = {
156 "network_type": "vlan",
157 "segment_id": 104,
158 "router_ext": False,
159 "physnet": "physnet-ironic"
160 }
161 self.assertEqual(expected_network, node['quantum_settings']
162 ['predefined_networks']['baremetal']['L2'])
163 self.assertIn("physnet-ironic",
164 node['quantum_settings']['L2']['phys_nets'])
165 self.assertEqual(consts.DEFAULT_BRIDGES_NAMES.br_ironic,
166 (node['quantum_settings']['L2']['phys_nets']
167 ["physnet-ironic"]["bridge"]))
168 self.assertEqual('104:104',
169 (node['quantum_settings']['L2']['phys_nets']
170 ["physnet-ironic"]["vlan_range"]))
171
172 def test_baremetal_transformations_flat(self):
173 self._setup_cluster_with_ironic(ironic_provision_network=False)
174 serialized_for_astute = self.serializer.serialize(
175 self.cluster, self.cluster.nodes)
176 serialized_for_astute = deployment_info_to_legacy(
177 serialized_for_astute)
178 net_tr = serialized_for_astute[0]['network_scheme']['transformations']
179 expected_actions = [
180 {'action': 'add-br', 'name': 'br-baremetal'},
181 {'action': 'add-port', 'bridge': 'br-baremetal',
182 'name': 'eth0.104'},
183 {'action': 'add-br', 'name': 'br-ironic', 'provider': 'ovs'},
184 {'action': 'add-patch', 'bridges': ['br-ironic', 'br-baremetal'],
185 'provider': 'ovs'}]
186
187 for element in expected_actions:
188 self.assertIn(element, net_tr)
189
190 def test_baremetal_transformations_vlan(self):
191 self._setup_cluster_with_ironic(ironic_provision_network=True)
192 serialized_for_astute = self.serializer.serialize(
193 self.cluster, self.cluster.nodes)
194 serialized_for_astute = deployment_info_to_legacy(
195 serialized_for_astute)
196 net_tr = serialized_for_astute[0]['network_scheme']['transformations']
197 expected_actions = [
198 {'action': 'add-br', 'name': 'br-bm-phy'},
199 {'action': 'add-br', 'name': 'br-baremetal'},
200 {'action': 'add-port', 'bridge': 'br-baremetal',
201 'name': 'br-bm-phy.104'},
202 {'action': 'add-br', 'name': 'br-ironic', 'provider': 'ovs'},
203 {'action': 'add-patch', 'bridges': ['br-ironic', 'br-bm-phy'],
204 'provider': 'ovs'},
205 {'action': 'add-patch', 'bridges': ['br-bm-phy', 'br-fw-admin']}]
206
207 not_expected = [
208 {'action': 'add-port', 'bridge': 'br-bm-phy', 'name': u'eth0'}]
209
210 for element in expected_actions:
211 self.assertIn(element, net_tr)
212 for elemnet in not_expected:
213 self.assertNotIn(elemnet, net_tr)
214
215 def test_baremetal_transformations_vlan_baremetal_on_separate_nic(self):
216 self._setup_cluster_with_ironic(ironic_provision_network=True,
217 separate_interface=True)
218 serialized_for_astute = self.serializer.serialize(
219 self.cluster, self.cluster.nodes)
220 serialized_for_astute = deployment_info_to_legacy(
221 serialized_for_astute)
222 net_tr = serialized_for_astute[0]['network_scheme']['transformations']
223 expected_actions = [
224 {'action': 'add-br', 'name': 'br-bm-phy'},
225 {'action': 'add-br', 'name': 'br-baremetal'},
226 {'action': 'add-port', 'bridge': 'br-baremetal',
227 'name': 'br-bm-phy.104'},
228 {'action': 'add-br', 'name': 'br-ironic', 'provider': 'ovs'},
229 {'action': 'add-patch', 'bridges': ['br-ironic', 'br-bm-phy'],
230 'provider': 'ovs'},
231 {'action': 'add-port', 'bridge': 'br-bm-phy', 'name': u'eth3'}]
232
233 not_expected = [
234 {'action': 'add-patch', 'bridges': ['br-bm-phy', 'br-fw-admin']}]
235
236 for element in expected_actions:
237 self.assertIn(element, net_tr)
238 for elemnet in not_expected:
239 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 091cf2a..2a0a90b 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 @@
16 16
17from nailgun import consts 17from nailgun import consts
18from nailgun.orchestrator import deployment_serializers 18from nailgun.orchestrator import deployment_serializers
19from nailgun.test.integration import test_orchestrator_serializer_90 19from nailgun.test.integration import test_orchestrator_serializer_100
20 20
21 21
22class TestSerializer110Mixin(object): 22class TestSerializer110Mixin(object):
@@ -45,22 +45,15 @@ class TestSerializer110Mixin(object):
45 return [plugin['name'] for plugin in plugins] 45 return [plugin['name'] for plugin in plugins]
46 46
47 47
48class TestDeploymentAttributesSerialization110( 48class TestNetworkDeploymentSerializer110(
49 TestSerializer110Mixin, 49 TestSerializer110Mixin,
50 test_orchestrator_serializer_90.TestDeploymentAttributesSerialization90 50 test_orchestrator_serializer_100.TestNetworkDeploymentSerializer100
51):
52 pass
53
54
55class TestDeploymentLCMSerialization110(
56 TestSerializer110Mixin,
57 test_orchestrator_serializer_90.TestDeploymentLCMSerialization90
58): 51):
59 pass 52 pass
60 53
61 54
62class TestSerializeInterfaceDriversData110( 55class TestSerializeInterfaceDriversData110(
63 TestSerializer110Mixin, 56 TestSerializer110Mixin,
64 test_orchestrator_serializer_90.TestSerializeInterfaceDriversData90 57 test_orchestrator_serializer_100.TestSerializeInterfaceDriversData100
65): 58):
66 pass 59 pass