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
This commit is contained in:
parent
738066cdca
commit
9dabe06369
|
@ -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'
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 <name> since plugin data may contain
|
||||
<scripts>, <repositories>, <whatever> 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)
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue