[Ironic] Add baremetal network for ironic
This change adds: * new optional baremetal network * baremetal sections in Neutron L3 configuration Ironic requires separate baremetal network on infra nodes and neutron flat network mapped to this physical network. New baremetal network is optional and depends on Ironic component enabled in settings. Implements: blueprint fuel-integrate-ironic (partially) Change-Id: I742bf69d3f3ac5e4b4ecd39a12e3171c566563e8
This commit is contained in:
parent
f8ba3f9cd4
commit
d0bb7c17cf
|
@ -94,6 +94,10 @@ NULLABLE_IP_ADDRESS = {
|
|||
'anyOf': [IP_ADDRESS, NULL]
|
||||
}
|
||||
|
||||
NULLABLE_IP_ADDRESS_RANGE = {
|
||||
'anyOf': [IP_ADDRESS_RANGE, NULL]
|
||||
}
|
||||
|
||||
NET_ADDRESS = {
|
||||
'type': 'string',
|
||||
# check for valid ip address and route prefix
|
||||
|
|
|
@ -167,7 +167,12 @@ NEUTRON_NETWORK_CONFIGURATION = {
|
|||
"exclusiveMinimum": False,
|
||||
"exclusiveMaximum": False
|
||||
}
|
||||
}
|
||||
},
|
||||
"baremetal_gateway": base_types.NULLABLE_IP_ADDRESS,
|
||||
"baremetal_range": base_types.NULLABLE_IP_ADDRESS_RANGE,
|
||||
},
|
||||
"dependencies": {
|
||||
"baremetal_range": ["baremetal_gateway"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ NETWORKS = Enum(
|
|||
# Node networks
|
||||
'fuelweb_admin',
|
||||
'storage',
|
||||
'baremetal',
|
||||
# internal in terms of fuel
|
||||
'management',
|
||||
'public',
|
||||
|
@ -101,6 +102,7 @@ DEFAULT_BRIDGES_NAMES = Enum(
|
|||
'br-ex',
|
||||
'br-mesh',
|
||||
'br-aux',
|
||||
'br-baremetal',
|
||||
names=(
|
||||
'br_fw_admin',
|
||||
'br_storage',
|
||||
|
@ -110,7 +112,8 @@ DEFAULT_BRIDGES_NAMES = Enum(
|
|||
'br_int',
|
||||
'br_ex',
|
||||
'br_mesh',
|
||||
'br_aux'
|
||||
'br_aux',
|
||||
'br_baremetal'
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@ from nailgun.settings import settings
|
|||
ALLOWED_LOCKS_CHAINS = [
|
||||
('attributes', 'clusters'),
|
||||
('attributes', 'clusters', 'ip_addr_ranges'),
|
||||
('attributes', 'ip_addr_ranges'),
|
||||
('attributes', 'ip_addrs'),
|
||||
('attributes', 'ip_addrs', 'network_groups'),
|
||||
('clusters', 'nodes'),
|
||||
('tasks', 'clusters'),
|
||||
('tasks', 'clusters', 'nodes'),
|
||||
|
|
|
@ -30,6 +30,7 @@ from oslo_serialization import jsonutils
|
|||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql as psql
|
||||
|
||||
from nailgun.db.sqlalchemy.models.fields import JSON
|
||||
from nailgun.utils.migration import drop_enum
|
||||
from nailgun.utils.migration import upgrade_enum
|
||||
|
||||
|
@ -108,9 +109,11 @@ def upgrade():
|
|||
add_node_discover_error_upgrade()
|
||||
upgrade_neutron_parameters()
|
||||
upgrade_cluster_plugins()
|
||||
upgrade_add_baremetal_net()
|
||||
|
||||
|
||||
def downgrade():
|
||||
downgrade_add_baremetal_net()
|
||||
downgrade_cluster_plugins()
|
||||
downgrade_neutron_parameters()
|
||||
add_node_discover_error_downgrade()
|
||||
|
@ -474,3 +477,17 @@ def downgrade_cluster_plugins():
|
|||
'cluster_id',
|
||||
nullable=None
|
||||
)
|
||||
|
||||
|
||||
def upgrade_add_baremetal_net():
|
||||
op.add_column('neutron_config',
|
||||
sa.Column('baremetal_gateway', sa.String(length=25),
|
||||
nullable=True))
|
||||
op.add_column('neutron_config',
|
||||
sa.Column('baremetal_range', JSON(), nullable=True,
|
||||
server_default='[]'))
|
||||
|
||||
|
||||
def downgrade_add_baremetal_net():
|
||||
op.drop_column('neutron_config', 'baremetal_gateway')
|
||||
op.drop_column('neutron_config', 'baremetal_range')
|
||||
|
|
|
@ -61,6 +61,8 @@ class NeutronConfig(NetworkingConfig):
|
|||
base_mac = Column(LowercaseString(17), nullable=False)
|
||||
internal_cidr = Column(String(25))
|
||||
internal_gateway = Column(String(25))
|
||||
baremetal_gateway = Column(String(25))
|
||||
baremetal_range = Column(JSON, default=[])
|
||||
|
||||
# Neutron L3 names for default internal / floating networks
|
||||
# which were previously knows as net04 and net04_ext.
|
||||
|
|
|
@ -429,6 +429,17 @@
|
|||
render_addr_mask: null
|
||||
map_priority: 2
|
||||
configurable: true
|
||||
- name: "baremetal"
|
||||
cidr: "192.168.3.0/24"
|
||||
ip_range: ["192.168.3.1", "192.168.3.50"]
|
||||
vlan_start: 104
|
||||
use_gateway: false
|
||||
notation: "ip_ranges"
|
||||
render_type: null
|
||||
map_priority: 2
|
||||
configurable: true
|
||||
restrictions:
|
||||
- condition: "settings:additional_components.ironic.value == false"
|
||||
config:
|
||||
vlan_range: [1000, 1030]
|
||||
gre_id_range: [2, 65535]
|
||||
|
@ -438,6 +449,8 @@
|
|||
internal_gateway: "192.168.111.1"
|
||||
floating_name: "admin_floating_net"
|
||||
floating_ranges: [["172.16.0.130", "172.16.0.254"]]
|
||||
baremetal_gateway: "192.168.3.51"
|
||||
baremetal_range: ["192.168.3.52", "192.168.3.254"]
|
||||
parameters:
|
||||
amqp:
|
||||
provider: "rabbitmq"
|
||||
|
|
|
@ -1089,6 +1089,17 @@ class Cluster(NailgunObject):
|
|||
consts.CLUSTER_STATUSES.error]
|
||||
return instance.status not in allowed
|
||||
|
||||
@classmethod
|
||||
def is_component_enabled(cls, instance, component):
|
||||
"""Checks is specified additional component enabled in cluster
|
||||
|
||||
:param instance: nailgun.db.sqlalchemy.models.Cluster instance
|
||||
:param component: name of additional component
|
||||
:returns: The result depends on current component status in settings
|
||||
"""
|
||||
return bool(instance.attributes.editable['additional_components'].
|
||||
get((component), {}).get('value'))
|
||||
|
||||
|
||||
class ClusterCollection(NailgunCollection):
|
||||
"""Cluster collection."""
|
||||
|
|
|
@ -95,6 +95,14 @@ class NeutronNetworkConfigurationSerializer(NetworkConfigurationSerializer):
|
|||
'vlan_range',
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def serialize_network_params(cls, cluster):
|
||||
"""Overrides default serialization, adds baremetal fields if need"""
|
||||
fields = cls.network_cfg_fields
|
||||
if objects.Cluster.is_component_enabled(cluster, 'ironic'):
|
||||
fields += ('baremetal_gateway', 'baremetal_range')
|
||||
return BasicSerializer.serialize(cluster.network_config, fields)
|
||||
|
||||
@classmethod
|
||||
def serialize_for_cluster(cls, cluster):
|
||||
result = cls.serialize_net_groups_and_vips(cluster)
|
||||
|
|
|
@ -26,9 +26,7 @@ from nailgun import consts
|
|||
from nailgun.db import db
|
||||
from nailgun.db.sqlalchemy import models
|
||||
from nailgun.logger import logger
|
||||
from nailgun.objects import Cluster
|
||||
from nailgun.objects import Node
|
||||
from nailgun.objects import NodeGroupCollection
|
||||
from nailgun import objects
|
||||
from nailgun.orchestrator.base_serializers import NetworkDeploymentSerializer
|
||||
from nailgun.settings import settings
|
||||
from nailgun import utils
|
||||
|
@ -45,7 +43,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
if cluster.mode == 'multinode':
|
||||
for node in cluster.nodes:
|
||||
if cls._node_has_role_by_name(node, 'controller'):
|
||||
net_manager = Cluster.get_network_manager(cluster)
|
||||
net_manager = objects.Cluster.get_network_manager(cluster)
|
||||
networks = net_manager.get_node_networks(node)
|
||||
mgmt_cidr = net_manager.get_network_by_netname(
|
||||
'management', networks)['ip']
|
||||
|
@ -57,7 +55,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
@classmethod
|
||||
def network_provider_node_attrs(cls, cluster, node):
|
||||
"""Serialize node, then it will be merged with common attributes."""
|
||||
nm = Cluster.get_network_manager(cluster)
|
||||
nm = objects.Cluster.get_network_manager(cluster)
|
||||
networks = nm.get_node_networks(node)
|
||||
node_attrs = {
|
||||
'network_scheme': cls.generate_network_scheme(node, networks),
|
||||
|
@ -75,15 +73,15 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
"""
|
||||
# Get Mellanox data
|
||||
neutron_mellanox_data = \
|
||||
Cluster.get_editable_attributes(cluster)\
|
||||
objects.Cluster.get_editable_attributes(cluster)\
|
||||
.get('neutron_mellanox', {})
|
||||
|
||||
# Get storage data
|
||||
storage_data = \
|
||||
Cluster.get_editable_attributes(cluster).get('storage', {})
|
||||
objects.Cluster.get_editable_attributes(cluster).get('storage', {})
|
||||
|
||||
# Get network manager
|
||||
nm = Cluster.get_network_manager(cluster)
|
||||
nm = objects.Cluster.get_network_manager(cluster)
|
||||
|
||||
# Init mellanox dict
|
||||
node_attrs['neutron_mellanox'] = {}
|
||||
|
@ -192,7 +190,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
if cluster.release.operating_system == 'RHEL':
|
||||
attrs['amqp'] = {'provider': 'qpid-rh'}
|
||||
|
||||
cluster_attrs = Cluster.get_editable_attributes(cluster)
|
||||
cluster_attrs = objects.Cluster.get_editable_attributes(cluster)
|
||||
if 'nsx_plugin' in cluster_attrs and \
|
||||
cluster_attrs['nsx_plugin']['metadata']['enabled']:
|
||||
attrs['L2']['provider'] = 'nsx'
|
||||
|
@ -221,11 +219,11 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
'transformations': []
|
||||
}
|
||||
|
||||
if Node.should_have_public(node):
|
||||
if objects.Node.should_have_public(node):
|
||||
attrs['endpoints']['br-ex'] = {}
|
||||
attrs['roles']['ex'] = 'br-ex'
|
||||
|
||||
nm = Cluster.get_network_manager(node.cluster)
|
||||
nm = objects.Cluster.get_network_manager(node.cluster)
|
||||
iface_types = consts.NETWORK_INTERFACE_TYPES
|
||||
|
||||
# Add a dynamic data to a structure.
|
||||
|
@ -282,7 +280,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
# to provide a right ordering of ifdown/ifup operations with
|
||||
# IP interfaces.
|
||||
brnames = ['br-ex', 'br-mgmt', 'br-storage', 'br-fw-admin']
|
||||
if not Node.should_have_public(node):
|
||||
if not objects.Node.should_have_public(node):
|
||||
brnames.pop(0)
|
||||
|
||||
for brname in brnames:
|
||||
|
@ -297,7 +295,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
('management', 'br-mgmt'),
|
||||
('fuelweb_admin', 'br-fw-admin'),
|
||||
]
|
||||
if Node.should_have_public(node):
|
||||
if objects.Node.should_have_public(node):
|
||||
netgroup_mapping.append(('public', 'br-ex'))
|
||||
|
||||
netgroups = {}
|
||||
|
@ -309,7 +307,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
attrs['endpoints'][brname]['IP'] = [netgroup['ip']]
|
||||
netgroups[ngname] = netgroup
|
||||
|
||||
if Node.should_have_public(node):
|
||||
if objects.Node.should_have_public(node):
|
||||
attrs['endpoints']['br-ex']['gateway'] = \
|
||||
netgroups['public']['gateway']
|
||||
else:
|
||||
|
@ -439,7 +437,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
"router_ext": True,
|
||||
"physnet": "physnet1"
|
||||
},
|
||||
"tenant": Cluster.get_creds(cluster)['tenant']['value'],
|
||||
"tenant": objects.Cluster.get_creds(cluster)['tenant']['value'],
|
||||
"shared": False
|
||||
}
|
||||
|
||||
|
@ -460,7 +458,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
"physnet": "physnet2"
|
||||
if cluster.network_config.segmentation_type == "vlan" else None
|
||||
},
|
||||
"tenant": Cluster.get_creds(cluster)['tenant']['value'],
|
||||
"tenant": objects.Cluster.get_creds(cluster)['tenant']['value'],
|
||||
"shared": False
|
||||
}
|
||||
|
||||
|
@ -500,7 +498,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
}
|
||||
|
||||
# Set non-default ml2 configurations
|
||||
attrs = Cluster.get_editable_attributes(cluster)
|
||||
attrs = objects.Cluster.get_editable_attributes(cluster)
|
||||
if 'neutron_mellanox' in attrs and \
|
||||
attrs['neutron_mellanox']['plugin']['value'] == 'ethernet':
|
||||
res['mechanism_drivers'] = 'mlnx,openvswitch'
|
||||
|
@ -515,7 +513,7 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer):
|
|||
l3 = {
|
||||
"use_namespaces": True
|
||||
}
|
||||
attrs = Cluster.get_editable_attributes(cluster)
|
||||
attrs = objects.Cluster.get_editable_attributes(cluster)
|
||||
if 'nsx_plugin' in attrs and \
|
||||
attrs['nsx_plugin']['metadata']['enabled']:
|
||||
dhcp_attrs = l3.setdefault('dhcp_agent', {})
|
||||
|
@ -564,7 +562,7 @@ class NeutronNetworkDeploymentSerializer60(
|
|||
# Include information about all subnets that don't belong to this node.
|
||||
# This is used during deployment to configure routes to all other
|
||||
# networks in the environment.
|
||||
nm = Cluster.get_network_manager(node.cluster)
|
||||
nm = objects.Cluster.get_network_manager(node.cluster)
|
||||
other_nets = nm.get_networks_not_on_node(node, networks)
|
||||
|
||||
netgroup_mapping = [
|
||||
|
@ -572,7 +570,7 @@ class NeutronNetworkDeploymentSerializer60(
|
|||
('management', 'br-mgmt'),
|
||||
('fuelweb_admin', 'br-fw-admin'),
|
||||
]
|
||||
if Node.should_have_public(node):
|
||||
if objects.Node.should_have_public(node):
|
||||
netgroup_mapping.append(('public', 'br-ex'))
|
||||
|
||||
for ngname, brname in netgroup_mapping:
|
||||
|
@ -582,7 +580,7 @@ class NeutronNetworkDeploymentSerializer60(
|
|||
attrs['endpoints'][brname]['other_nets'] = \
|
||||
other_nets.get(ngname, [])
|
||||
|
||||
if Node.should_have_public(node):
|
||||
if objects.Node.should_have_public(node):
|
||||
attrs['endpoints']['br-ex']['default_gateway'] = True
|
||||
else:
|
||||
gw = nm.get_default_gateway(node.id)
|
||||
|
@ -716,14 +714,14 @@ class NeutronNetworkDeploymentSerializer61(
|
|||
},
|
||||
}
|
||||
|
||||
is_public = Node.should_have_public(node)
|
||||
is_public = objects.Node.should_have_public(node)
|
||||
if is_public:
|
||||
attrs['endpoints']['br-ex'] = {'IP': 'none'}
|
||||
attrs['endpoints']['br-floating'] = {'IP': 'none'}
|
||||
attrs['roles']['ex'] = 'br-ex'
|
||||
attrs['roles']['neutron/floating'] = 'br-floating'
|
||||
|
||||
nm = Cluster.get_network_manager(node.cluster)
|
||||
nm = objects.Cluster.get_network_manager(node.cluster)
|
||||
|
||||
# Populate IP and GW information to endpoints.
|
||||
netgroup_mapping = [
|
||||
|
@ -794,7 +792,7 @@ class NeutronNetworkDeploymentSerializer61(
|
|||
attrs['transformations'] = cls.generate_transformations(
|
||||
node, nm, nets_by_ifaces, is_public, prv_base_ep)
|
||||
|
||||
if NodeGroupCollection.get_by_cluster_id(
|
||||
if objects.NodeGroupCollection.get_by_cluster_id(
|
||||
node.cluster.id).count() > 1:
|
||||
cls.generate_routes(node, attrs, nm, netgroup_mapping, netgroups,
|
||||
networks)
|
||||
|
@ -868,7 +866,7 @@ class NeutronNetworkDeploymentSerializer70(
|
|||
@classmethod
|
||||
def get_node_non_default_networks(cls, node):
|
||||
"""Returns list of non-default networks assigned to node."""
|
||||
nm = Cluster.get_network_manager(node.cluster)
|
||||
nm = objects.Cluster.get_network_manager(node.cluster)
|
||||
return filter(lambda net: net['name'] not in consts.NETWORKS,
|
||||
nm.get_node_networks(node))
|
||||
|
||||
|
@ -915,7 +913,7 @@ class NeutronNetworkDeploymentSerializer70(
|
|||
consts.NETWORKS.management: 'br-mgmt'}
|
||||
|
||||
# roles can be assigned to br-ex only in case it has a public IP
|
||||
if Node.should_have_public_with_ip(node):
|
||||
if objects.Node.should_have_public_with_ip(node):
|
||||
mapping[consts.NETWORKS.public] = 'br-ex'
|
||||
|
||||
if node.cluster.network_config.segmentation_type in \
|
||||
|
@ -928,7 +926,7 @@ class NeutronNetworkDeploymentSerializer70(
|
|||
|
||||
@classmethod
|
||||
def get_network_to_ip_mapping(cls, node):
|
||||
nm = Cluster.get_network_manager(node.cluster)
|
||||
nm = objects.Cluster.get_network_manager(node.cluster)
|
||||
|
||||
mapping = dict()
|
||||
networks = nm.get_node_networks(node)
|
||||
|
@ -948,7 +946,7 @@ class NeutronNetworkDeploymentSerializer70(
|
|||
- 'get_network_role_mapping_to_interfaces'.
|
||||
"""
|
||||
roles = dict()
|
||||
for role in Cluster.get_network_roles(node.cluster):
|
||||
for role in objects.Cluster.get_network_roles(node.cluster):
|
||||
default_mapping = mapping.get(role['default_mapping'])
|
||||
if default_mapping:
|
||||
roles[role['id']] = default_mapping
|
||||
|
@ -1005,14 +1003,14 @@ class NeutronNetworkDeploymentSerializer70(
|
|||
'roles': cls.get_network_role_mapping_to_interfaces(node),
|
||||
}
|
||||
|
||||
is_public = Node.should_have_public(node)
|
||||
is_public = objects.Node.should_have_public(node)
|
||||
if is_public:
|
||||
attrs['endpoints']['br-ex'] = {'IP': 'none'}
|
||||
attrs['endpoints']['br-floating'] = {'IP': 'none'}
|
||||
attrs['roles']['ex'] = 'br-ex'
|
||||
attrs['roles']['neutron/floating'] = 'br-floating'
|
||||
|
||||
nm = Cluster.get_network_manager(node.cluster)
|
||||
nm = objects.Cluster.get_network_manager(node.cluster)
|
||||
|
||||
# Populate IP and GW information to endpoints.
|
||||
netgroup_mapping = (cls.get_network_to_endpoint_mapping(node)
|
||||
|
@ -1046,7 +1044,7 @@ class NeutronNetworkDeploymentSerializer70(
|
|||
})
|
||||
|
||||
# Add gateway.
|
||||
if Node.should_have_public_with_ip(node):
|
||||
if objects.Node.should_have_public_with_ip(node):
|
||||
attrs['endpoints']['br-ex']['gateway'] = \
|
||||
netgroups['public']['gateway']
|
||||
else:
|
||||
|
@ -1084,7 +1082,7 @@ class NeutronNetworkDeploymentSerializer70(
|
|||
attrs['transformations'] = cls.generate_transformations(
|
||||
node, nm, nets_by_ifaces, is_public, prv_base_ep)
|
||||
|
||||
if NodeGroupCollection.get_by_cluster_id(
|
||||
if objects.NodeGroupCollection.get_by_cluster_id(
|
||||
node.cluster.id).count() > 1:
|
||||
cls.generate_routes(node, attrs, nm, netgroup_mapping, netgroups,
|
||||
networks)
|
||||
|
@ -1120,16 +1118,16 @@ class NeutronNetworkDeploymentSerializer70(
|
|||
@classmethod
|
||||
def generate_network_metadata(cls, cluster):
|
||||
nodes = dict()
|
||||
nm = Cluster.get_network_manager(cluster)
|
||||
nm = objects.Cluster.get_network_manager(cluster)
|
||||
|
||||
for node in Cluster.get_nodes_not_for_deletion(cluster):
|
||||
name = Node.get_slave_name(node)
|
||||
node_roles = Node.all_roles(node)
|
||||
for node in objects.Cluster.get_nodes_not_for_deletion(cluster):
|
||||
name = objects.Node.get_slave_name(node)
|
||||
node_roles = objects.Node.all_roles(node)
|
||||
network_roles = cls.get_network_role_mapping_to_ip(node)
|
||||
|
||||
nodes[name] = {
|
||||
"uid": node.uid,
|
||||
"fqdn": Node.get_node_fqdn(node),
|
||||
"fqdn": objects.Node.get_node_fqdn(node),
|
||||
"name": name,
|
||||
"user_node_name": node.name,
|
||||
"swift_zone": node.uid,
|
||||
|
@ -1208,7 +1206,7 @@ class NeutronNetworkTemplateSerializer70(
|
|||
'roles': roles,
|
||||
}
|
||||
|
||||
nm = Cluster.get_network_manager(node.cluster)
|
||||
nm = objects.Cluster.get_network_manager(node.cluster)
|
||||
|
||||
netgroups = nm.get_node_networks_with_ips(node)
|
||||
netgroup_mapping = nm.get_node_network_mapping(node)
|
||||
|
@ -1251,7 +1249,7 @@ class NeutronNetworkTemplateSerializer70(
|
|||
|
||||
attrs['transformations'] = cls.generate_transformations(node)
|
||||
|
||||
if NodeGroupCollection.get_by_cluster_id(
|
||||
if objects.NodeGroupCollection.get_by_cluster_id(
|
||||
node.cluster.id).count() > 1:
|
||||
cls.generate_routes(node, attrs, nm, netgroup_mapping, netgroups,
|
||||
networks)
|
||||
|
@ -1262,7 +1260,7 @@ class NeutronNetworkTemplateSerializer70(
|
|||
|
||||
@classmethod
|
||||
def _get_endpoint_to_ip_mapping(cls, node):
|
||||
nm = Cluster.get_network_manager(node.cluster)
|
||||
nm = objects.Cluster.get_network_manager(node.cluster)
|
||||
net_to_ips = nm.get_node_networks_with_ips(node)
|
||||
|
||||
mapping = dict()
|
||||
|
@ -1294,8 +1292,8 @@ class NeutronNetworkTemplateSerializer70(
|
|||
|
||||
This info is deprecated in 7.0 and should be removed in later version.
|
||||
"""
|
||||
nm = Cluster.get_network_manager(cluster)
|
||||
for node in Cluster.get_nodes_not_for_deletion(cluster):
|
||||
nm = objects.Cluster.get_network_manager(cluster)
|
||||
for node in objects.Cluster.get_nodes_not_for_deletion(cluster):
|
||||
netw_data = []
|
||||
for name, data in six.iteritems(
|
||||
nm.get_node_networks_with_ips(node)):
|
||||
|
@ -1322,6 +1320,41 @@ class NeutronNetworkDeploymentSerializer80(
|
|||
def render_floating_ranges(cls, floating_ranges):
|
||||
return [utils.join_range(x) for x in floating_ranges]
|
||||
|
||||
@classmethod
|
||||
def get_network_to_endpoint_mapping(cls, node):
|
||||
mapping = {
|
||||
consts.NETWORKS.fuelweb_admin:
|
||||
consts.DEFAULT_BRIDGES_NAMES.br_fw_admin,
|
||||
consts.NETWORKS.storage:
|
||||
consts.DEFAULT_BRIDGES_NAMES.br_storage,
|
||||
consts.NETWORKS.management:
|
||||
consts.DEFAULT_BRIDGES_NAMES.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
|
||||
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
|
||||
if objects.Cluster.is_component_enabled(node.cluster, 'ironic'):
|
||||
mapping[consts.NETWORKS.baremetal] = \
|
||||
consts.DEFAULT_BRIDGES_NAMES.br_baremetal
|
||||
mapping.update(cls.get_node_non_default_bridge_mapping(node))
|
||||
return mapping
|
||||
|
||||
@classmethod
|
||||
def generate_transformations(cls, node, nm, nets_by_ifaces, is_public,
|
||||
prv_base_ep):
|
||||
transformations = (super(NeutronNetworkDeploymentSerializer80, cls)
|
||||
.generate_transformations(node, nm, nets_by_ifaces,
|
||||
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))
|
||||
return transformations
|
||||
|
||||
|
||||
class NeutronNetworkTemplateSerializer80(NeutronNetworkTemplateSerializer70):
|
||||
pass
|
||||
|
|
|
@ -18,7 +18,9 @@ import copy
|
|||
from mock import patch
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
import yaml
|
||||
|
||||
from nailgun.objects import Cluster
|
||||
from nailgun.objects.serializers.network_configuration \
|
||||
import NeutronNetworkConfigurationSerializer
|
||||
from nailgun.objects.serializers.network_configuration \
|
||||
|
@ -238,3 +240,28 @@ class TestNetworkModels(BaseIntegrationTest):
|
|||
"admin_internal_net", cluster.network_config.internal_name)
|
||||
self.assertEqual(
|
||||
"admin_floating_net", cluster.network_config.floating_name)
|
||||
|
||||
def test_neutron_networking_parameters_baremetal(self):
|
||||
attributes_metadata = """
|
||||
editable:
|
||||
additional_components:
|
||||
ironic:
|
||||
value: %r
|
||||
type: "checkbox"
|
||||
"""
|
||||
cluster = self.env.create_cluster(
|
||||
api=False,
|
||||
net_provider=consts.CLUSTER_NET_PROVIDERS.neutron)
|
||||
# Ensure baremetal_* fields are not serialized when Ironic disabled
|
||||
nw_params = NeutronNetworkConfigurationSerializer. \
|
||||
serialize_network_params(cluster)
|
||||
self.assertNotIn('baremetal_gateway', nw_params)
|
||||
self.assertNotIn('baremetal_range', nw_params)
|
||||
# Ensure baremetal_* fields are serialized when Ironic enabled
|
||||
Cluster.patch_attributes(
|
||||
cluster, yaml.load(attributes_metadata % True))
|
||||
self.db.refresh(cluster)
|
||||
nw_params = NeutronNetworkConfigurationSerializer. \
|
||||
serialize_network_params(cluster)
|
||||
self.assertIn('baremetal_gateway', nw_params)
|
||||
self.assertIn('baremetal_range', nw_params)
|
||||
|
|
|
@ -114,11 +114,11 @@ class TestDeploymentAttributesSerialization70(
|
|||
):
|
||||
segmentation_type = consts.NEUTRON_SEGMENT_TYPES.vlan
|
||||
custom_network = {
|
||||
'name': 'baremetal',
|
||||
'role': 'ironic/baremetal',
|
||||
'name': 'custom',
|
||||
'role': 'plugin/custom',
|
||||
'cidr': '192.168.3.0/24',
|
||||
'vlan_start': 50,
|
||||
'bridge': 'br-baremetal',
|
||||
'bridge': 'br-custom',
|
||||
}
|
||||
plugin_network_roles = yaml.safe_load("""
|
||||
- id: "{role}"
|
||||
|
@ -232,25 +232,25 @@ class TestDeploymentAttributesSerialization70(
|
|||
transformations = node['network_scheme']['transformations']
|
||||
node_network_roles = (node['network_metadata']['nodes']
|
||||
['node-' + node['uid']]['network_roles'])
|
||||
baremetal_ip = node_network_roles.get(self.custom_network['role'],
|
||||
'0.0.0.0')
|
||||
baremetal_brs = filter(lambda t: t.get('name') ==
|
||||
self.custom_network['bridge'],
|
||||
transformations)
|
||||
baremetal_ports = filter(lambda t: t.get('name') ==
|
||||
("eth0.%s" %
|
||||
self.custom_network['vlan_start']),
|
||||
transformations)
|
||||
custom_ip = node_network_roles.get(self.custom_network['role'],
|
||||
'0.0.0.0')
|
||||
custom_brs = filter(lambda t: t.get('name') ==
|
||||
self.custom_network['bridge'],
|
||||
transformations)
|
||||
custom_ports = filter(lambda t: t.get('name') ==
|
||||
("eth0.%s" %
|
||||
self.custom_network['vlan_start']),
|
||||
transformations)
|
||||
self.assertEqual(roles.get(self.custom_network['role']),
|
||||
self.custom_network['bridge'])
|
||||
self.assertEqual(vips.get(self.custom_network['name'],
|
||||
{}).get('network_role'),
|
||||
self.custom_network['role'])
|
||||
self.assertTrue(netaddr.IPAddress(baremetal_ip) in
|
||||
self.assertTrue(netaddr.IPAddress(custom_ip) in
|
||||
netaddr.IPNetwork(self.custom_network['cidr']))
|
||||
self.assertEqual(len(baremetal_brs), 1)
|
||||
self.assertEqual(len(baremetal_ports), 1)
|
||||
self.assertEqual(baremetal_ports[0]['bridge'],
|
||||
self.assertEqual(len(custom_brs), 1)
|
||||
self.assertEqual(len(custom_ports), 1)
|
||||
self.assertEqual(custom_ports[0]['bridge'],
|
||||
self.custom_network['bridge'])
|
||||
|
||||
def test_network_scheme(self):
|
||||
|
|
|
@ -555,3 +555,40 @@ class TestClusterPluginsMigration(base.BaseAlembicMigrationTest):
|
|||
'weight': 25,
|
||||
'label': 'label'
|
||||
})
|
||||
|
||||
|
||||
class TestBaremetalFields(base.BaseAlembicMigrationTest):
|
||||
|
||||
def test_baremetal_fields_saving(self):
|
||||
baremetal_gateway = '192.168.3.51'
|
||||
baremetal_range = jsonutils.dumps(['192.168.3.52', '192.168.3.254'])
|
||||
result = db.execute(
|
||||
self.meta.tables['networking_configs'].insert(),
|
||||
[{
|
||||
'cluster_id': None,
|
||||
'dns_nameservers': ['8.8.8.8'],
|
||||
'floating_ranges': [],
|
||||
'configuration_template': None,
|
||||
}])
|
||||
db.execute(
|
||||
self.meta.tables['neutron_config'].insert(),
|
||||
[{
|
||||
'id': result.inserted_primary_key[0],
|
||||
'vlan_range': [],
|
||||
'gre_id_range': [],
|
||||
'base_mac': '00:00:00:00:00:00',
|
||||
'internal_cidr': '10.10.10.00/24',
|
||||
'internal_gateway': '10.10.10.01',
|
||||
'internal_name': 'my_internal_name',
|
||||
'floating_name': 'my_floating_name',
|
||||
'baremetal_gateway': baremetal_gateway,
|
||||
'baremetal_range': baremetal_range,
|
||||
'segmentation_type': 'vlan',
|
||||
'net_l23_provider': 'ovs'
|
||||
}])
|
||||
result = db.execute(
|
||||
sa.select(
|
||||
[self.meta.tables['neutron_config'].c.baremetal_gateway,
|
||||
self.meta.tables['neutron_config'].c.baremetal_range])).\
|
||||
fetchall()
|
||||
self.assertIn((baremetal_gateway, baremetal_range), result)
|
||||
|
|
|
@ -528,7 +528,9 @@ class TestNeutronNetworkConfigurationValidatorProtocol(
|
|||
"internal_gateway": "192.168.111.1",
|
||||
"net_l23_provider": consts.NEUTRON_L23_PROVIDERS.ovs,
|
||||
"segmentation_type": consts.NEUTRON_SEGMENT_TYPES.gre,
|
||||
"vlan_range": [1000, 1030]
|
||||
"vlan_range": [1000, 1030],
|
||||
"baremetal_gateway": "192.168.3.51",
|
||||
"baremetal_range": ["192.168.3.52", "192.168.3.254"]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -648,6 +650,16 @@ class TestNeutronNetworkConfigurationValidatorProtocol(
|
|||
self.nc['networking_parameters']['vlan_range'] = [2, 2]
|
||||
self.assertRaisesNonUnique(self.nc, "[2, 2]")
|
||||
|
||||
def test_baremetal_gateway_invalid_type(self):
|
||||
self.nc['networking_parameters']['baremetal_gateway'] = []
|
||||
self.assertRaisesInvalidAnyOf(
|
||||
self.nc, [], "['networking_parameters']['baremetal_gateway']")
|
||||
|
||||
def test_baremetal_range_invalid_value(self):
|
||||
self.nc['networking_parameters']['baremetal_range'] = ["bad"]
|
||||
self.assertRaisesInvalidAnyOf(
|
||||
self.nc, ["bad"], "['networking_parameters']['baremetal_range']")
|
||||
|
||||
|
||||
class TestNeutronNetworkConfigurationValidator(base.BaseIntegrationTest):
|
||||
|
||||
|
|
Loading…
Reference in New Issue