Stick 'pxe' role to physical interface
* add 'pxe' property to the nic db model * collect 'pxe' property during the bootstrap stage * forbid to assign admin net to non pxe interfaces * allow to assign admin net only to bond interface what containing pxe interface Change-Id: I70dcaed66607728b76ae3d93c59048c310ddb22c Implements: blueprint admin-network-on-bond
This commit is contained in:
parent
3b96ea59de
commit
4bf1095593
|
@ -206,6 +206,7 @@ class NodeAgent
|
|||
:memory => (_dmi_memory or _ohai_memory),
|
||||
}
|
||||
|
||||
admin_mac = _master_ip_and_mac[:mac] rescue nil
|
||||
begin
|
||||
(@os[:network][:interfaces] or {} rescue {}).each do |int, intinfo|
|
||||
# Send info about physical interfaces only
|
||||
|
@ -220,6 +221,7 @@ class NodeAgent
|
|||
(intinfo[:addresses] or {} rescue {}).each do |addr, addrinfo|
|
||||
if (addrinfo[:family] rescue nil) =~ /lladdr/
|
||||
int_meta[:mac] = addr
|
||||
int_meta[:pxe] = admin_mac == int_meta[:mac]
|
||||
begin
|
||||
int_info = Rethtool::InterfaceSettings.new(int)
|
||||
int_meta[:driver] = int_info.driver
|
||||
|
|
|
@ -68,6 +68,7 @@ single_schema = {
|
|||
|
||||
}
|
||||
},
|
||||
"pxe": {"type": "boolean"}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -22,6 +22,7 @@ from nailgun.db import db
|
|||
from nailgun.db.sqlalchemy.models import Cluster
|
||||
from nailgun.db.sqlalchemy.models import Node
|
||||
from nailgun.errors import errors
|
||||
import six
|
||||
|
||||
|
||||
class NetworkConfigurationValidator(BasicValidator):
|
||||
|
@ -274,22 +275,43 @@ class NetAssignmentValidator(BasicValidator):
|
|||
network_group_ids = net_manager.get_node_networkgroups_ids(db_node)
|
||||
|
||||
bonded_eth_ids = set()
|
||||
pxe_iface_name = net_manager._get_pxe_iface_name(db_node)
|
||||
if not pxe_iface_name:
|
||||
raise errors.InvalidData(
|
||||
"Node '{0}': Interfaces configuration can't be changed if"
|
||||
"there is no pxe interface in DB".format(node['id']),
|
||||
log_message=True
|
||||
)
|
||||
|
||||
for iface in interfaces:
|
||||
iface_nets = [n.get('name')
|
||||
for n in iface.get('assigned_networks')]
|
||||
if iface['type'] == consts.NETWORK_INTERFACE_TYPES.ether:
|
||||
db_iface = filter(
|
||||
db_iface = next(six.moves.filter(
|
||||
lambda i: i.id == iface['id'],
|
||||
db_interfaces
|
||||
)
|
||||
), None)
|
||||
if not db_iface:
|
||||
raise errors.InvalidData(
|
||||
"Node '{0}': there is no interface with ID '{1}'"
|
||||
" in DB".format(node['id'], iface['id']),
|
||||
log_message=True
|
||||
)
|
||||
if not db_iface.pxe:
|
||||
if consts.NETWORKS.fuelweb_admin in iface_nets:
|
||||
raise errors.InvalidData(
|
||||
"Node '{0}': admin network can not be assigned to"
|
||||
" non-pxe interface {1}".format(node['id'],
|
||||
iface['name']),
|
||||
log_message=True
|
||||
)
|
||||
elif iface['type'] == consts.NETWORK_INTERFACE_TYPES.bond:
|
||||
pxe_iface_present = False
|
||||
for slave in iface['slaves']:
|
||||
iface_id = [i.id for i in db_interfaces
|
||||
if i.name == slave['name']]
|
||||
if slave["name"] == pxe_iface_name:
|
||||
pxe_iface_present = True
|
||||
if iface_id:
|
||||
if iface_id[0] in bonded_eth_ids:
|
||||
raise errors.InvalidData(
|
||||
|
@ -307,7 +329,6 @@ class NetAssignmentValidator(BasicValidator):
|
|||
log_message=True
|
||||
)
|
||||
|
||||
iface_nets = [n['name'] for n in iface['assigned_networks']]
|
||||
if consts.NETWORKS.fuelweb_admin in iface_nets:
|
||||
prohibited_modes = net_manager.\
|
||||
get_prohibited_admin_bond_modes()
|
||||
|
@ -319,6 +340,14 @@ class NetAssignmentValidator(BasicValidator):
|
|||
node['id'], iface['name'], bond_mode),
|
||||
log_message=True
|
||||
)
|
||||
if not pxe_iface_present:
|
||||
raise errors.InvalidData(
|
||||
"Node '{0}': interface '{1}' belongs to "
|
||||
"admin network and doesn't contain node's pxe "
|
||||
"interface '{2}'".format(
|
||||
node['id'], iface['name'], pxe_iface_name),
|
||||
log_message=True
|
||||
)
|
||||
|
||||
for net in iface['assigned_networks']:
|
||||
if net['id'] not in network_group_ids:
|
||||
|
|
|
@ -85,9 +85,11 @@ def upgrade():
|
|||
extend_releases_model_upgrade()
|
||||
upgrade_task_names()
|
||||
vms_conf_upgrade()
|
||||
extend_nic_model_upgrade()
|
||||
|
||||
|
||||
def downgrade():
|
||||
extend_nic_model_downgrade()
|
||||
extend_releases_model_downgrade()
|
||||
migrate_volumes_into_extension_downgrade()
|
||||
node_roles_as_plugin_downgrade()
|
||||
|
@ -433,3 +435,29 @@ def node_roles_as_plugin_downgrade():
|
|||
|
||||
def extend_releases_model_downgrade():
|
||||
op.drop_column('releases', 'network_roles_metadata')
|
||||
|
||||
|
||||
def extend_nic_model_upgrade():
|
||||
connection = op.get_bind()
|
||||
op.add_column(
|
||||
'node_nic_interfaces',
|
||||
sa.Column('pxe',
|
||||
sa.Boolean,
|
||||
nullable=False,
|
||||
server_default='false'))
|
||||
select_query = sa.sql.text(
|
||||
"SELECT ni.id from node_nic_interfaces ni "
|
||||
"join net_nic_assignments na on ni.id=na.interface_id "
|
||||
"join network_groups ng on ng.id=na.network_id "
|
||||
"WHERE ng.name = 'fuelweb_admin'")
|
||||
update_query = sa.sql.text(
|
||||
"UPDATE node_nic_interfaces SET pxe = true "
|
||||
"WHERE id = :id")
|
||||
|
||||
# change 'pxe' property to 'true' value for admin ifaces
|
||||
for iface_id in connection.execute(select_query):
|
||||
connection.execute(update_query, id=iface_id[0])
|
||||
|
||||
|
||||
def extend_nic_model_downgrade():
|
||||
op.drop_column('node_nic_interfaces', 'pxe')
|
||||
|
|
|
@ -247,6 +247,7 @@ class NodeNICInterface(Base):
|
|||
parent_id = Column(Integer, ForeignKey('node_bond_interfaces.id'))
|
||||
driver = Column(Text)
|
||||
bus_info = Column(Text)
|
||||
pxe = Column(Boolean, default=False, nullable=False)
|
||||
|
||||
offloading_modes = Column(JSON, default=[], nullable=False,
|
||||
server_default='[]')
|
||||
|
|
|
@ -148,7 +148,8 @@
|
|||
"state": null,
|
||||
"sub": []
|
||||
}
|
||||
]
|
||||
],
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"mac": "00:25:90:6a:b1:11",
|
||||
|
@ -185,7 +186,8 @@
|
|||
"state": null,
|
||||
"sub": []
|
||||
}
|
||||
]
|
||||
],
|
||||
"pxe": true
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
|
@ -398,7 +400,8 @@
|
|||
"state": null,
|
||||
"sub": []
|
||||
}
|
||||
]
|
||||
],
|
||||
"pxe": true
|
||||
},
|
||||
{
|
||||
"ip": "192.168.70.234",
|
||||
|
@ -435,7 +438,8 @@
|
|||
"state": true,
|
||||
"sub": []
|
||||
}
|
||||
]
|
||||
],
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"mac": "54:78:ea:05:17:ba",
|
||||
|
@ -471,7 +475,8 @@
|
|||
"state": true,
|
||||
"sub": []
|
||||
}
|
||||
]
|
||||
],
|
||||
"pxe": false
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
|
@ -588,7 +593,8 @@
|
|||
"driver": "igb",
|
||||
"bus_info": "0000:06:00.0",
|
||||
"max_speed": 1000,
|
||||
"current_speed": 1000
|
||||
"current_speed": 1000,
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"name": "eth2",
|
||||
|
@ -598,7 +604,8 @@
|
|||
"driver": "igb",
|
||||
"bus_info": "0000:07:00.0",
|
||||
"max_speed": 1000,
|
||||
"current_speed": 1000
|
||||
"current_speed": 1000,
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"name": "eth3",
|
||||
|
@ -608,7 +615,8 @@
|
|||
"driver": "eth_ipoib",
|
||||
"bus_info": "0000:08:00.0",
|
||||
"max_speed": 56000,
|
||||
"current_speed": 56000
|
||||
"current_speed": 56000,
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"ip": "10.20.0.5",
|
||||
|
@ -617,7 +625,8 @@
|
|||
"name": "eth0",
|
||||
"current_speed": null,
|
||||
"driver": "igb",
|
||||
"bus_info": "0000:09:00.0"
|
||||
"bus_info": "0000:09:00.0",
|
||||
"pxe": true
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
|
@ -734,7 +743,8 @@
|
|||
"name": "eth1",
|
||||
"current_speed": null,
|
||||
"driver": "mlx4_en",
|
||||
"bus_info": "0000:10:00.0"
|
||||
"bus_info": "0000:10:00.0",
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"name": "eth0",
|
||||
|
@ -744,7 +754,8 @@
|
|||
"bus_info": "0000:11:00.0",
|
||||
"mac": "00:25:90:67:9d:24",
|
||||
"max_speed": 1000,
|
||||
"current_speed": 1000
|
||||
"current_speed": 1000,
|
||||
"pxe": true
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
|
@ -863,7 +874,8 @@
|
|||
"current_speed": null,
|
||||
"ip": "10.20.0.7",
|
||||
"driver": "igb",
|
||||
"bus_info": "0000:12:00.0"
|
||||
"bus_info": "0000:12:00.0",
|
||||
"pxe": true
|
||||
},
|
||||
{
|
||||
"name": "eth0",
|
||||
|
@ -872,7 +884,8 @@
|
|||
"driver": "igb",
|
||||
"bus_info": "0000:13:00.0",
|
||||
"max_speed": 1000,
|
||||
"current_speed": 1000
|
||||
"current_speed": 1000,
|
||||
"pxe": false
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
|
@ -966,7 +979,8 @@
|
|||
"driver": "e1000",
|
||||
"bus_info": "0000:14:00.0",
|
||||
"max_speed": 100,
|
||||
"current_speed": 100
|
||||
"current_speed": 100,
|
||||
"pxe": true
|
||||
},
|
||||
{
|
||||
"name": "eth1",
|
||||
|
@ -974,7 +988,8 @@
|
|||
"max_speed": 1000,
|
||||
"current_speed": 100,
|
||||
"driver": "e1000",
|
||||
"bus_info": "0000:15:00.0"
|
||||
"bus_info": "0000:15:00.0",
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"name": "eth2",
|
||||
|
@ -982,7 +997,8 @@
|
|||
"max_speed": 100,
|
||||
"current_speed": null,
|
||||
"driver": "e1000",
|
||||
"bus_info": "0000:16:00.0"
|
||||
"bus_info": "0000:16:00.0",
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"name": "eth3",
|
||||
|
@ -990,7 +1006,8 @@
|
|||
"max_speed": 100,
|
||||
"current_speed": null,
|
||||
"driver": "e1000",
|
||||
"bus_info": "0000:17:00.0"
|
||||
"bus_info": "0000:17:00.0",
|
||||
"pxe": false
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
|
@ -1057,7 +1074,8 @@
|
|||
"max_speed": 100,
|
||||
"current_speed": 100,
|
||||
"driver": "igb",
|
||||
"bus_info": "0000:18:00.0"
|
||||
"bus_info": "0000:18:00.0",
|
||||
"pxe": true
|
||||
},
|
||||
{
|
||||
"name": "eth1",
|
||||
|
@ -1065,7 +1083,8 @@
|
|||
"max_speed": 1000,
|
||||
"current_speed": 1000,
|
||||
"driver": "igb",
|
||||
"bus_info": "0000:19:00.0"
|
||||
"bus_info": "0000:19:00.0",
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"name": "eth2",
|
||||
|
@ -1073,7 +1092,8 @@
|
|||
"max_speed": 100,
|
||||
"current_speed": null,
|
||||
"driver": "igb",
|
||||
"bus_info": "0000:20:00.0"
|
||||
"bus_info": "0000:20:00.0",
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"name": "eth3",
|
||||
|
@ -1081,7 +1101,8 @@
|
|||
"max_speed": 1000,
|
||||
"current_speed": 100,
|
||||
"driver": "igb",
|
||||
"bus_info": "0000:21:00.0"
|
||||
"bus_info": "0000:21:00.0",
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"name": "eth4",
|
||||
|
@ -1089,7 +1110,8 @@
|
|||
"max_speed": 56000,
|
||||
"current_speed": 56000,
|
||||
"driver": "mlx4_en",
|
||||
"bus_info": "0000:22:00.0"
|
||||
"bus_info": "0000:22:00.0",
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"name": "eth5",
|
||||
|
@ -1097,7 +1119,8 @@
|
|||
"max_speed": 100,
|
||||
"current_speed": 100,
|
||||
"driver": "igb",
|
||||
"bus_info": "0000:23:00.0"
|
||||
"bus_info": "0000:23:00.0",
|
||||
"pxe": false
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
|
@ -1254,7 +1277,8 @@
|
|||
"max_speed": 1000,
|
||||
"current_speed": 1000,
|
||||
"driver": "igb",
|
||||
"bus_info": "0000:24:00.0"
|
||||
"bus_info": "0000:24:00.0",
|
||||
"pxe": false
|
||||
},
|
||||
{
|
||||
"ip": "10.20.0.7",
|
||||
|
@ -1263,7 +1287,8 @@
|
|||
"name": "p2p2",
|
||||
"current_speed": null,
|
||||
"driver": "igb",
|
||||
"bus_info": "0000:25:00.0"
|
||||
"bus_info": "0000:25:00.0",
|
||||
"pxe": true
|
||||
}
|
||||
],
|
||||
"disks": [
|
||||
|
|
|
@ -400,6 +400,37 @@ class NetworkManager(object):
|
|||
|
||||
return ips.all()
|
||||
|
||||
@classmethod
|
||||
def _get_pxe_iface_name(cls, node):
|
||||
"""Returns appropriate pxe iface's name
|
||||
|
||||
In case when node has network scheme configured
|
||||
we can not rely on its pxe interface calculation
|
||||
algorithm anymore, because admin ip is moving to
|
||||
bridge and 'pxe' property will have 'False' value
|
||||
for all interfaces. In this case we should rely on
|
||||
db where actual pxe interface was saved during the
|
||||
bootstrap stage.
|
||||
In case when node for some reason has no pxe interface
|
||||
in db we should get pxe interface using appropriate
|
||||
function `get_admin_physical_iface`.
|
||||
"""
|
||||
db_interfaces = node.nic_interfaces
|
||||
pxe = next((
|
||||
i for i in node.meta['interfaces'] if i.get('pxe') or
|
||||
i.get('mac') == node.mac),
|
||||
None)
|
||||
if pxe:
|
||||
return pxe.get('name')
|
||||
pxe_db = next((i for i in db_interfaces if i.pxe), None)
|
||||
if pxe_db:
|
||||
return pxe_db.name
|
||||
if db_interfaces:
|
||||
return objects.Node.get_admin_physical_iface(node).name
|
||||
logger.warning(u'Cannot find pxe interface for node "%s"',
|
||||
node.full_name)
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def clear_assigned_ips(cls, node):
|
||||
db().query(IPAddr).filter_by(node=node.id).delete()
|
||||
|
@ -694,8 +725,11 @@ class NetworkManager(object):
|
|||
except errors.InvalidInterfacesInfo as e:
|
||||
logger.debug("Cannot update interfaces: %s", e.message)
|
||||
return
|
||||
|
||||
pxe_iface_name = cls._get_pxe_iface_name(node)
|
||||
for interface in node.meta["interfaces"]:
|
||||
# set 'pxe' property for appropriate iface
|
||||
if interface['name'] == pxe_iface_name:
|
||||
interface['pxe'] = True
|
||||
# try to get interface by mac address
|
||||
interface_db = next((
|
||||
n for n in node.nic_interfaces
|
||||
|
@ -794,6 +828,7 @@ class NetworkManager(object):
|
|||
interface.state = interface_attrs.get('state')
|
||||
interface.driver = interface_attrs.get('driver')
|
||||
interface.bus_info = interface_attrs.get('bus_info')
|
||||
interface.pxe = interface_attrs.get('pxe', False)
|
||||
if interface_attrs.get('interface_properties'):
|
||||
interface.interface_properties = \
|
||||
interface_attrs['interface_properties']
|
||||
|
|
|
@ -63,7 +63,8 @@ class NodeInterfacesSerializer(BasicSerializer):
|
|||
'assigned_networks',
|
||||
'driver',
|
||||
'bus_info',
|
||||
'offloading_modes'
|
||||
'offloading_modes',
|
||||
'pxe'
|
||||
)
|
||||
bond_fields = (
|
||||
'mac',
|
||||
|
|
|
@ -334,9 +334,10 @@ class EnvironmentManager(object):
|
|||
if_list = [
|
||||
{
|
||||
"name": "eth{0}".format(i),
|
||||
"mac": self.generate_random_mac()
|
||||
"mac": self.generate_random_mac(),
|
||||
}
|
||||
for i in range(if_count)]
|
||||
if_list[0]['pxe'] = True
|
||||
self.set_interfaces_in_meta(meta, if_list)
|
||||
nodes.append(self.create_node(meta=meta, **kwargs))
|
||||
return nodes
|
||||
|
|
|
@ -463,7 +463,8 @@ class TestNodeNICAdminAssigning(BaseIntegrationTest):
|
|||
self.env.generate_random_mac())
|
||||
meta = self.env.default_metadata()
|
||||
meta['interfaces'] = [{'name': 'eth0', 'mac': mac1},
|
||||
{'name': 'eth1', 'mac': mac2, 'ip': admin_ip}]
|
||||
{'name': 'eth1', 'mac': mac2, 'ip': admin_ip,
|
||||
'pxe': True}]
|
||||
self.env.create_node(api=True, meta=meta, mac=mac1,
|
||||
cluster_id=cluster['id'])
|
||||
node_db = self.env.nodes[0]
|
||||
|
@ -517,7 +518,7 @@ class TestNodePublicNetworkToNICAssignment(BaseIntegrationTest):
|
|||
{'name': 'eth3', 'mac': self.env.generate_random_mac()},
|
||||
{'name': 'eth2', 'mac': self.env.generate_random_mac()},
|
||||
{'name': 'eth0', 'mac': self.env.generate_random_mac(),
|
||||
'ip': admin_ip},
|
||||
'ip': admin_ip, 'pxe': True},
|
||||
{'name': 'eth1', 'mac': self.env.generate_random_mac()}
|
||||
]
|
||||
node = self.env.create_node(api=True, meta=meta,
|
||||
|
@ -556,13 +557,19 @@ class TestNodeNICsHandlersValidation(BaseIntegrationTest):
|
|||
|
||||
def setUp(self):
|
||||
super(TestNodeNICsHandlersValidation, self).setUp()
|
||||
meta = self.env.default_metadata()
|
||||
meta["interfaces"] = [
|
||||
{'name': 'eth0', 'mac': self.env.generate_random_mac(),
|
||||
'pxe': True},
|
||||
{'name': 'eth1', 'mac': self.env.generate_random_mac()},
|
||||
]
|
||||
self.env.create(
|
||||
cluster_kwargs={
|
||||
"net_provider": "neutron",
|
||||
"net_segment_type": "gre"
|
||||
},
|
||||
nodes_kwargs=[
|
||||
{"api": True, "pending_addition": True}
|
||||
{"api": True, "pending_addition": True, 'meta': meta}
|
||||
]
|
||||
)
|
||||
resp = self.app.get(
|
||||
|
@ -625,3 +632,12 @@ class TestNodeNICsHandlersValidation(BaseIntegrationTest):
|
|||
"Node '{0}': there is no interface with ID '1234567'"
|
||||
" in DB".format(self.env.nodes[0]["id"])
|
||||
)
|
||||
|
||||
def test_nic_assignment_failed_assign_admin_net_to_non_pxe_iface(self):
|
||||
admin_net = self.nics_w_nets[0]["assigned_networks"][0]
|
||||
del self.nics_w_nets[0]["assigned_networks"][0]
|
||||
self.nics_w_nets[1]["assigned_networks"].append(admin_net)
|
||||
self.node_nics_put_check_error(
|
||||
"Node '{0}': admin network can not be assigned to non-pxe"
|
||||
" interface eth1".format(self.env.nodes[0]["id"])
|
||||
)
|
||||
|
|
|
@ -31,7 +31,7 @@ class TestNodeCollectionNICsHandler(BaseIntegrationTest):
|
|||
mac = self.env.generate_random_mac()
|
||||
meta = {}
|
||||
self.env.set_interfaces_in_meta(meta, [
|
||||
{'name': 'eth0', 'mac': mac},
|
||||
{'name': 'eth0', 'mac': mac, 'pxe': True},
|
||||
{'name': 'eth1', 'mac': self.env.generate_random_mac()}])
|
||||
node = self.env.create_node(api=True, meta=meta, mac=mac,
|
||||
cluster_id=cluster['id'])
|
||||
|
@ -63,10 +63,12 @@ class TestNodeCollectionNICsHandler(BaseIntegrationTest):
|
|||
# Creating cluster with node
|
||||
self.env.create_cluster()
|
||||
cluster = self.env.clusters[0]
|
||||
self.env.create_node(
|
||||
self.env.create_nodes_w_interfaces_count(
|
||||
roles=['controller'],
|
||||
pending_addition=True,
|
||||
cluster_id=cluster.id
|
||||
cluster_id=cluster.id,
|
||||
nodes_count=1,
|
||||
if_count=4
|
||||
)
|
||||
# Deploying cluster
|
||||
deployment_task = self.env.launch_deployment()
|
||||
|
@ -108,8 +110,12 @@ class TestNodeCollectionNICsHandler(BaseIntegrationTest):
|
|||
consts.NODE_STATUSES.deploying: True,
|
||||
consts.NODE_STATUSES.ready: True,
|
||||
consts.NODE_STATUSES.removing: True}
|
||||
meta = self.env.default_metadata()
|
||||
meta['interfaces'] = [{'name': 'eth0', 'pxe': True},
|
||||
{'name': 'eth1'}]
|
||||
self.env.create_node(
|
||||
roles=['controller'],
|
||||
meta=meta
|
||||
)
|
||||
node = self.env.nodes[0]
|
||||
for status, lock in six.iteritems(lock_vs_status):
|
||||
|
|
|
@ -182,14 +182,16 @@ class TestHandlers(BaseIntegrationTest):
|
|||
'name': 'eth0',
|
||||
'mac': mac_eth0,
|
||||
'current_speed': 1,
|
||||
'state': 'up'
|
||||
'state': 'up',
|
||||
'pxe': True
|
||||
}
|
||||
|
||||
eth1 = {
|
||||
'name': 'eth1',
|
||||
'mac': mac_eth1,
|
||||
'current_speed': 1,
|
||||
'state': 'up'
|
||||
'state': 'up',
|
||||
'pxe': False
|
||||
}
|
||||
|
||||
# prepare metadata with our interfaces
|
||||
|
@ -412,7 +414,7 @@ class TestHandlers(BaseIntegrationTest):
|
|||
meta = self.env.default_metadata()
|
||||
self.env.set_interfaces_in_meta(meta, [
|
||||
{'name': 'eth0', 'mac': '00:00:00:00:00:00', 'current_speed': 1,
|
||||
'state': 'up'}])
|
||||
'state': 'up', 'pxe': True}])
|
||||
self.env.create_node(api=True, meta=meta)
|
||||
new_meta = deepcopy(meta)
|
||||
node = self.env.nodes[0]
|
||||
|
@ -446,7 +448,7 @@ class TestHandlers(BaseIntegrationTest):
|
|||
meta = self.env.default_metadata()
|
||||
self.env.set_interfaces_in_meta(meta, [
|
||||
{'name': 'eth0', 'mac': '00:00:00:00:00:00', 'current_speed': 1,
|
||||
'state': 'up'}])
|
||||
'pxe': True, 'state': 'up'}])
|
||||
node = self.env.create_node(api=True, meta=meta)
|
||||
node_data = {'mac': node['mac'], 'meta': meta}
|
||||
# check default interface_properties values
|
||||
|
@ -487,7 +489,7 @@ class TestHandlers(BaseIntegrationTest):
|
|||
meta = self.env.default_metadata()
|
||||
self.env.set_interfaces_in_meta(meta, [
|
||||
{'name': 'eth0', 'mac': '00:00:00:00:00:00', 'current_speed': 1,
|
||||
'state': 'up'}])
|
||||
'pxe': True, 'state': 'up'}])
|
||||
node = self.env.create_node(api=True, meta=meta)
|
||||
|
||||
meta['interfaces'].append({
|
||||
|
@ -622,7 +624,8 @@ class TestHandlers(BaseIntegrationTest):
|
|||
|
||||
meta = self.env.default_metadata()
|
||||
meta["interfaces"] = [
|
||||
{'name': 'eth0', 'mac': self.env.generate_random_mac()},
|
||||
{'name': 'eth0', 'mac': self.env.generate_random_mac(),
|
||||
'pxe': True},
|
||||
{'name': 'eth1', 'mac': self.env.generate_random_mac()},
|
||||
{'name': 'eth2', 'mac': self.env.generate_random_mac()},
|
||||
{'name': 'eth3', 'mac': self.env.generate_random_mac()},
|
||||
|
|
|
@ -33,6 +33,7 @@ class TestNodeNICsBonding(BaseIntegrationTest):
|
|||
self.env.set_interfaces_in_meta(meta, [
|
||||
{"name": "eth0",
|
||||
"mac": "00:00:00:00:00:66",
|
||||
"pxe": True,
|
||||
"offloading_modes": [
|
||||
{
|
||||
"name": "mode_1",
|
||||
|
@ -80,6 +81,7 @@ class TestNodeNICsBonding(BaseIntegrationTest):
|
|||
"sub": []
|
||||
}
|
||||
]}])
|
||||
|
||||
self.env.create(
|
||||
cluster_kwargs={
|
||||
"net_provider": "neutron",
|
||||
|
@ -588,3 +590,26 @@ class TestNodeNICsBonding(BaseIntegrationTest):
|
|||
|
||||
resp = self.put_single()
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
def test_nics_bond_create_failed_admin_net_w_o_pxe_iface(self):
|
||||
mode = BOND_MODES.balance_slb
|
||||
bond_nets = [self.admin_nic["assigned_networks"][0]] + \
|
||||
self.other_nic["assigned_networks"]
|
||||
del self.admin_nic["assigned_networks"][0]
|
||||
self.data.append({
|
||||
"name": 'ovs-bond0',
|
||||
"type": NETWORK_INTERFACE_TYPES.bond,
|
||||
"mode": mode,
|
||||
"slaves": [
|
||||
{"name": self.empty_nic["name"]},
|
||||
{"name": self.other_nic["name"]}],
|
||||
"assigned_networks": bond_nets
|
||||
})
|
||||
|
||||
self.other_nic["assigned_networks"] = []
|
||||
|
||||
self.node_nics_put_check_error(
|
||||
"Node '{0}': interface 'ovs-bond0' belongs to admin network "
|
||||
"and doesn't contain node's pxe interface 'eth0'".format(
|
||||
self.env.nodes[0]["id"])
|
||||
)
|
||||
|
|
|
@ -158,7 +158,7 @@ class TestProvisioningSerializer(BaseIntegrationTest):
|
|||
admin_mac = self.env.generate_random_mac()
|
||||
meta = {
|
||||
'interfaces': [
|
||||
{'name': 'eth1', 'mac': self.env.generate_random_mac()},
|
||||
{'name': 'eth1', 'mac': admin_mac, 'pxe': True},
|
||||
{'name': 'eth2', 'mac': self.env.generate_random_mac()},
|
||||
{'name': 'eth3', 'mac': self.env.generate_random_mac()},
|
||||
{'name': 'eth4', 'mac': self.env.generate_random_mac()}
|
||||
|
|
|
@ -22,12 +22,16 @@ class TestPutSameJson(base.BaseIntegrationTest):
|
|||
|
||||
def setUp(self):
|
||||
super(TestPutSameJson, self).setUp()
|
||||
|
||||
meta = self.env.default_metadata()
|
||||
meta["interfaces"] = [
|
||||
{'name': 'eth0', 'pxe': True},
|
||||
{'name': 'eth1'}, {'name': 'eth2'}
|
||||
]
|
||||
self.cluster = self.env.create(
|
||||
cluster_kwargs={'api': True},
|
||||
nodes_kwargs=[
|
||||
{'api': True},
|
||||
{'api': True, 'pending_addition': True},
|
||||
{'api': True, 'meta': meta},
|
||||
{'api': True, 'pending_addition': True, 'meta': meta},
|
||||
]
|
||||
)
|
||||
self.cluster = self.env.clusters[0]
|
||||
|
|
|
@ -306,12 +306,14 @@ class TestNetworkVerificationWithBonds(BaseIntegrationTest):
|
|||
meta1 = self.env.default_metadata()
|
||||
meta2 = self.env.default_metadata()
|
||||
self.env.set_interfaces_in_meta(meta1, [
|
||||
{"name": "eth0", "mac": "00:00:00:00:00:66"},
|
||||
{"name": "eth0", "mac": "00:00:00:00:00:66",
|
||||
"pxe": True},
|
||||
{"name": "eth1", "mac": "00:00:00:00:00:77"},
|
||||
{"name": "eth2", "mac": "00:00:00:00:00:88"}]
|
||||
)
|
||||
self.env.set_interfaces_in_meta(meta2, [
|
||||
{"name": "eth0", "mac": "00:00:00:00:11:66", "current_speed": 100},
|
||||
{"name": "eth0", "mac": "00:00:00:00:11:66", "current_speed": 100,
|
||||
"pxe": True},
|
||||
{"name": "eth1", "mac": "00:00:00:00:22:77", "current_speed": 100},
|
||||
{"name": "eth2", "mac": "00:00:00:00:33:88", "current_speed": 100}]
|
||||
)
|
||||
|
|
|
@ -204,24 +204,20 @@ class TestInstallationInfo(BaseTestCase):
|
|||
|
||||
def test_nodes_info(self):
|
||||
info = InstallationInfo()
|
||||
self.env.create(
|
||||
cluster = self.env.create(
|
||||
release_kwargs={
|
||||
'operating_system': consts.RELEASE_OS.centos
|
||||
},
|
||||
nodes_kwargs=[
|
||||
{'status': consts.NODE_STATUSES.discover,
|
||||
'roles': ['controller', 'compute'],
|
||||
'meta': {}},
|
||||
{'roles': [],
|
||||
'pending_roles': ['compute'],
|
||||
'meta': {'cpu': {},
|
||||
'interfaces': [{'mac': 'x', 'name': 'eth0'}],
|
||||
'disks': [{'name': 'a', 'disk': 'a'}]}}
|
||||
]
|
||||
)
|
||||
})
|
||||
self.env.create_nodes_w_interfaces_count(
|
||||
nodes_count=2,
|
||||
if_count=4,
|
||||
roles=['controller', 'compute'],
|
||||
pending_addition=True,
|
||||
cluster_id=cluster['id'])
|
||||
|
||||
self.env.make_bond_via_api(
|
||||
'bond0', consts.BOND_MODES.active_backup,
|
||||
['eth0', 'eth1'], node_id=self.env.nodes[0].id)
|
||||
['eth1', 'eth2'], node_id=self.env.nodes[0].id)
|
||||
nodes_info = info.get_nodes_info(self.env.nodes)
|
||||
self.assertEquals(len(self.env.nodes), len(nodes_info))
|
||||
for idx, node in enumerate(self.env.nodes):
|
||||
|
|
|
@ -193,6 +193,55 @@ def prepare():
|
|||
{'role': mongoroleid, 'node': nodeid_c, 'primary': False},
|
||||
])
|
||||
|
||||
db.execute(
|
||||
meta.tables['node_nic_interfaces'].insert(),
|
||||
[
|
||||
{
|
||||
'id': 1,
|
||||
'node_id': nodeid_a,
|
||||
'name': 'test_interface',
|
||||
'mac': '00:00:00:00:00:01',
|
||||
'max_speed': 200,
|
||||
'current_speed': 100,
|
||||
'ip_addr': '10.20.0.2',
|
||||
'netmask': '255.255.255.0',
|
||||
'state': 'test_state',
|
||||
'interface_properties': jsonutils.dumps(
|
||||
{'test_property': 'test_value'}),
|
||||
'driver': 'test_driver',
|
||||
'bus_info': 'some_test_info'
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
'node_id': nodeid_a,
|
||||
'name': 'test_interface_2',
|
||||
'mac': '00:00:00:00:00:02',
|
||||
'max_speed': 200,
|
||||
'current_speed': 100,
|
||||
'ip_addr': '10.30.0.2',
|
||||
'netmask': '255.255.255.0',
|
||||
'state': 'test_state',
|
||||
'interface_properties': jsonutils.dumps(
|
||||
{'test_property': 'test_value'}),
|
||||
'driver': 'test_driver',
|
||||
'bus_info': 'some_test_info'
|
||||
},
|
||||
{
|
||||
'id': 3,
|
||||
'node_id': nodeid_a,
|
||||
'name': 'test_interface_3',
|
||||
'mac': '00:00:00:00:00:03',
|
||||
'max_speed': 200,
|
||||
'current_speed': 100,
|
||||
'ip_addr': '10.30.0.2',
|
||||
'netmask': '255.255.255.0',
|
||||
'state': 'test_state',
|
||||
'interface_properties': jsonutils.dumps(
|
||||
{'test_property': 'test_value'}),
|
||||
'driver': 'test_driver',
|
||||
'bus_info': 'some_test_info'
|
||||
}])
|
||||
|
||||
db.execute(
|
||||
meta.tables['node_bond_interfaces'].insert(),
|
||||
[{
|
||||
|
@ -204,22 +253,42 @@ def prepare():
|
|||
}])
|
||||
|
||||
db.execute(
|
||||
meta.tables['node_nic_interfaces'].insert(),
|
||||
[{
|
||||
'node_id': nodeid_a,
|
||||
'name': 'test_interface',
|
||||
'mac': '00:00:00:00:00:01',
|
||||
'max_speed': 200,
|
||||
'current_speed': 100,
|
||||
'ip_addr': '10.20.0.2',
|
||||
'netmask': '255.255.255.0',
|
||||
'state': 'test_state',
|
||||
'interface_properties': jsonutils.dumps(
|
||||
{'test_property': 'test_value'}),
|
||||
'parent_id': 1,
|
||||
'driver': 'test_driver',
|
||||
'bus_info': 'some_test_info'
|
||||
}])
|
||||
meta.tables['network_groups'].insert(),
|
||||
[
|
||||
{
|
||||
'id': 1,
|
||||
'name': 'fuelweb_admin',
|
||||
'vlan_start': None,
|
||||
'cidr': '10.20.0.0/24',
|
||||
'gateway': '10.20.0.200',
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
'name': 'public',
|
||||
'vlan_start': None,
|
||||
'cidr': '10.30.0.0/24',
|
||||
'gateway': '10.30.0.200'
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
db.execute(
|
||||
meta.tables['net_nic_assignments'].insert(),
|
||||
[
|
||||
{
|
||||
'network_id': 1,
|
||||
'interface_id': 1
|
||||
},
|
||||
{
|
||||
'network_id': 2,
|
||||
'interface_id': 2
|
||||
},
|
||||
{
|
||||
'network_id': 2,
|
||||
'interface_id': 3
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
db.commit()
|
||||
|
||||
|
@ -328,68 +397,20 @@ class TestPublicIpRequired(base.BaseAlembicMigrationTest):
|
|||
class TestInterfacesOffloadingModesMigration(base.BaseAlembicMigrationTest):
|
||||
def test_old_fields_exists(self):
|
||||
# check node_nic_interfaces fields
|
||||
nic_table = self.meta.tables['node_nic_interfaces']
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.node_id]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], 1)
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.name]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], 'test_interface')
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.mac]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], '00:00:00:00:00:01')
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.max_speed]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], 200)
|
||||
|
||||
result = db.execute(
|
||||
sa.select(
|
||||
[self.meta.tables['node_nic_interfaces'].c.current_speed]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], 100)
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.ip_addr]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], '10.20.0.2')
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.netmask]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], '255.255.255.0')
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.state]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], 'test_state')
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces']
|
||||
.c.interface_properties]))
|
||||
self.assertEqual(
|
||||
jsonutils.loads(result.fetchone()[0]),
|
||||
{'test_property': 'test_value'})
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.parent_id]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], 1)
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.driver]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], 'test_driver')
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['node_nic_interfaces'].c.bus_info]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], 'some_test_info')
|
||||
sa.select([nic_table.c.node_id, nic_table.c.name, nic_table.c.mac,
|
||||
nic_table.c.max_speed, nic_table.c.current_speed,
|
||||
nic_table.c.ip_addr, nic_table.c.netmask,
|
||||
nic_table.c.state, nic_table.c.interface_properties,
|
||||
nic_table.c.driver, nic_table.c.bus_info]).
|
||||
where(nic_table.c.id == 1))
|
||||
res = result.fetchone()
|
||||
check_res = [1, u'test_interface', u'00:00:00:00:00:01', 200, 100,
|
||||
u'10.20.0.2', u'255.255.255.0', u'test_state',
|
||||
u'{"test_property": "test_value"}',
|
||||
u'test_driver', u'some_test_info']
|
||||
self.assertListEqual(list(res), check_res)
|
||||
|
||||
def test_new_fields_exists_and_empty(self):
|
||||
# check node_nic_interfaces fields
|
||||
|
@ -406,6 +427,37 @@ class TestInterfacesOffloadingModesMigration(base.BaseAlembicMigrationTest):
|
|||
jsonutils.loads(result.fetchone()[0]), [])
|
||||
|
||||
|
||||
class TestInterfacesPxePropertyMigration(base.BaseAlembicMigrationTest):
|
||||
|
||||
def test_old_fields_exists(self):
|
||||
# check node_nic_interfaces fields
|
||||
ng_table = self.meta.tables['network_groups']
|
||||
result = db.execute(
|
||||
sa.select([ng_table.c.name, ng_table.c.vlan_start,
|
||||
ng_table.c.cidr, ng_table.c.gateway]).
|
||||
where(ng_table.c.id == 1))
|
||||
res = result.fetchone()
|
||||
check_res = [u'fuelweb_admin', None, u'10.20.0.0/24', u'10.20.0.200']
|
||||
self.assertListEqual(list(res), check_res)
|
||||
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['net_nic_assignments'].c.network_id]))
|
||||
self.assertEqual(
|
||||
result.fetchone()[0], 1)
|
||||
|
||||
def test_new_field_exists_and_filled(self):
|
||||
nic_table = self.meta.tables['node_nic_interfaces']
|
||||
result = db.execute(
|
||||
sa.select([nic_table.c.pxe]).where(nic_table.c.id == 1))
|
||||
# check 'pxe' property is true for admin interfaces
|
||||
self.assertTrue(result.fetchone()[0])
|
||||
result = db.execute(
|
||||
sa.select([nic_table.c.pxe]).where(nic_table.c.id != 1))
|
||||
# and 'false' for any others
|
||||
for res in result.fetchall():
|
||||
self.assertFalse(res[0])
|
||||
|
||||
|
||||
class TestMigrateVolumesIntoExtension(base.BaseAlembicMigrationTest):
|
||||
|
||||
def test_data_are_moved_into_buffer_table(self):
|
||||
|
|
|
@ -175,7 +175,8 @@ casper.createNode = function(options) {
|
|||
"mac": "C8:0A:A9:A6:FF:28",
|
||||
"name": "eth1",
|
||||
"max_speed": 1000,
|
||||
"current_speed": 1000
|
||||
"current_speed": 1000,
|
||||
"pxe": true
|
||||
},
|
||||
{
|
||||
"mac": "D4:56:C3:88:99:DF",
|
||||
|
|
Loading…
Reference in New Issue