Use vnic_type to determine whether a port is baremetal

In ocata, the tenant network port for baremetal instances
is owned by compute:<zone> instead of baremetal:<zone>. The
vnic_type for those ports is still 'baremetal', so use the
vnic_type to identify baremetal ports.

Change-Id: I677148a7964ea4b3673cc918999073b2cd5caafd
This commit is contained in:
Mitchell Jameson 2017-05-07 17:15:02 -07:00
parent 357444b2ac
commit 418c436cc9
3 changed files with 132 additions and 139 deletions

View File

@ -416,7 +416,7 @@ def get_tenants():
return res
def _make_bm_port_dict(record):
def _make_port_dict(record):
"""Make a dict from the BM profile DB record."""
return {'port_id': record.port_id,
'host_id': record.host,
@ -431,10 +431,21 @@ def get_all_baremetal_ports():
querry = session.query(ml2_models.PortBinding)
bm_ports = querry.filter_by(vnic_type='baremetal').all()
return {bm_port.port_id: _make_bm_port_dict(bm_port)
return {bm_port.port_id: _make_port_dict(bm_port)
for bm_port in bm_ports}
def get_all_portbindings():
"""Returns a list of all ports bindings."""
session = db.get_session()
with session.begin():
query = session.query(ml2_models.PortBinding)
ports = query.all()
return {port.port_id: _make_port_dict(port)
for port in ports}
def get_port_binding_level(filters):
"""Returns entries from PortBindingLevel based on the specified filters."""
session = db.get_reader_session()

View File

@ -413,7 +413,7 @@ class AristaRPCWrapperBase(object):
@abc.abstractmethod
def create_instance_bulk(self, tenant_id, neutron_ports, vms,
bm_port_profiles, sync=False):
port_profiles, sync=False):
"""Sends a bulk request to create ports.
:param tenant_id: globaly unique neutron tenant identifier
@ -873,7 +873,7 @@ class AristaRPCWrapperJSON(AristaRPCWrapperBase):
return self._send_api_request(path, 'POST', data)
def create_instance_bulk(self, tenant_id, neutron_ports, vms,
bm_port_profiles, sync=False):
port_profiles, sync=False):
self._create_tenant_if_needed(tenant_id)
vmInst = {}
@ -885,25 +885,6 @@ class AristaRPCWrapperJSON(AristaRPCWrapperBase):
portBindings = {}
for vm in vms.values():
for v_port in vm['ports']:
port_id = v_port['portId']
if (port_id in neutron_ports and
neutron_ports[port_id]['device_owner'].startswith(
'baremetal')):
vm['baremetal_instance'] = True
# Filter out all virtual ports, if instance type is baremetal
index = 0
for index, v_port in enumerate(vm['ports']):
port_id = v_port['portId']
if port_id in neutron_ports:
device_owner = neutron_ports[port_id]['device_owner']
if(device_owner.startswith('compute') and
vm['baremetal_instance']):
del vm['ports'][index]
# Now we are left with the ports that we are interested that
# require provisioning
for v_port in vm['ports']:
port_id = v_port['portId']
if not v_port['hosts']:
@ -919,18 +900,21 @@ class AristaRPCWrapperJSON(AristaRPCWrapperBase):
instance = self._create_instance_data(inst_id, inst_host)
device_owner = neutron_port['device_owner']
vnic_type = port_profiles[port_id]['vnic_type']
if device_owner == n_const.DEVICE_OWNER_DHCP:
instance_type = InstanceType.DHCP
if inst_id not in dhcpInst:
dhcpInst[inst_id] = instance
elif device_owner.startswith('compute'):
instance_type = InstanceType.VM
if inst_id not in vmInst:
vmInst[inst_id] = instance
elif device_owner.startswith('baremetal'):
instance_type = InstanceType.BAREMETAL
if inst_id not in baremetalInst:
baremetalInst[inst_id] = instance
elif (device_owner.startswith('compute') or
device_owner.startswith('baremetal')):
if vnic_type == 'baremetal':
instance_type = InstanceType.BAREMETAL
if inst_id not in baremetalInst:
baremetalInst[inst_id] = instance
else:
instance_type = InstanceType.VM
if inst_id not in vmInst:
vmInst[inst_id] = instance
elif device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE:
instance_type = InstanceType.ROUTER
if inst_id not in routerInst:
@ -957,7 +941,7 @@ class AristaRPCWrapperJSON(AristaRPCWrapperBase):
port_id, inst_host, network_id,
networkSegments[network_id])
elif instance_type in InstanceType.BAREMETAL_INSTANCE_TYPES:
switch_profile = json.loads(bm_port_profiles[
switch_profile = json.loads(port_profiles[
port_id]['profile'])
portBinding = self._get_switch_bindings(
port_id, inst_host, network_id,
@ -1025,10 +1009,12 @@ class AristaRPCWrapperJSON(AristaRPCWrapperBase):
device_type = ''
if device_owner == n_const.DEVICE_OWNER_DHCP:
device_type = InstanceType.DHCP
elif device_owner.startswith('compute'):
device_type = InstanceType.VM
elif device_owner.startswith('baremetal'):
device_type = InstanceType.BAREMETAL
elif (device_owner.startswith('compute')
or device_owner.startswith('baremetal')):
if vnic_type == 'baremetal':
device_type = InstanceType.BAREMETAL
else:
device_type = InstanceType.VM
elif device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE:
device_type = InstanceType.ROUTER
else:
@ -1066,10 +1052,12 @@ class AristaRPCWrapperJSON(AristaRPCWrapperBase):
device_type = ''
if device_owner == n_const.DEVICE_OWNER_DHCP:
device_type = InstanceType.DHCP
elif device_owner.startswith('compute'):
device_type = InstanceType.VM
elif device_owner.startswith('baremetal'):
device_type = InstanceType.BAREMETAL
elif (device_owner.startswith('compute') or
device_owner.startswith('baremetal')):
if vnic_type == 'baremetal':
device_type = InstanceType.BAREMETAL
else:
device_type = InstanceType.VM
elif device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE:
device_type = InstanceType.ROUTER
else:
@ -1361,25 +1349,27 @@ class AristaRPCWrapperEapi(AristaRPCWrapperBase):
tenant_id,
segments,
port_name)
elif device_owner.startswith('compute'):
self.plug_host_into_network(device_id,
host_id,
port_id,
net_id,
tenant_id,
segments,
port_name)
elif device_owner.startswith('baremetal'):
self.plug_baremetal_into_network(device_id,
host_id,
port_id,
net_id,
tenant_id,
segments,
port_name,
sg, orig_sg,
vnic_type,
switch_bindings)
elif (device_owner.startswith('compute') or
device_owner.startswith('baremetal')):
if vnic_type == 'baremetal':
self.plug_baremetal_into_network(device_id,
host_id,
port_id,
net_id,
tenant_id,
segments,
port_name,
sg, orig_sg,
vnic_type,
switch_bindings)
else:
self.plug_host_into_network(device_id,
host_id,
port_id,
net_id,
tenant_id,
segments,
port_name)
elif device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE:
self.plug_distributed_router_port_into_network(device_id,
host_id,
@ -1397,21 +1387,23 @@ class AristaRPCWrapperEapi(AristaRPCWrapperBase):
port_id,
network_id,
tenant_id)
elif device_owner.startswith('compute'):
self.unplug_host_from_network(device_id,
hostname,
port_id,
network_id,
tenant_id)
elif device_owner.startswith('baremetal'):
self.unplug_baremetal_from_network(device_id,
hostname,
port_id,
network_id,
tenant_id,
sg,
vnic_type,
switch_bindings)
elif (device_owner.startswith('compute') or
device_owner.startswith('baremetal')):
if vnic_type == 'baremetal':
self.unplug_baremetal_from_network(device_id,
hostname,
port_id,
network_id,
tenant_id,
sg,
vnic_type,
switch_bindings)
else:
self.unplug_host_from_network(device_id,
hostname,
port_id,
network_id,
tenant_id)
elif device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE:
self.unplug_distributed_router_port_from_network(device_id,
port_id,
@ -1656,7 +1648,7 @@ class AristaRPCWrapperEapi(AristaRPCWrapperBase):
self._run_openstack_cmds(cmds, sync=sync)
def create_instance_bulk(self, tenant_id, neutron_ports, vms,
bm_port_profiles, sync=False):
port_profiles, sync=False):
cmds = ['tenant %s' % tenant_id]
# Create a reference to function to avoid name lookups in the loop
append_cmd = cmds.append
@ -1664,27 +1656,6 @@ class AristaRPCWrapperEapi(AristaRPCWrapperBase):
for vm in vms.values():
counter += 1
# Mark an instance as baremetal if any of the ports is baremetal
for v_port in vm['ports']:
port_id = v_port['portId']
if (port_id in neutron_ports and
neutron_ports[port_id]['device_owner'].startswith(
'baremetal')):
vm['baremetal_instance'] = True
# Filter out all virtual ports, if instance type is baremetal
index = 0
for v_port in vm['ports']:
port_id = v_port['portId']
if port_id in neutron_ports:
device_owner = neutron_ports[port_id]['device_owner']
if(device_owner.startswith('compute') and
vm['baremetal_instance']):
del vm['ports'][index]
index += 1
# Now we are left with the ports that we are interested that
# require provisioning
for v_port in vm['ports']:
port_id = v_port['portId']
if not v_port['hosts']:
@ -1700,6 +1671,7 @@ class AristaRPCWrapperEapi(AristaRPCWrapperBase):
port_name = 'name "%s"' % neutron_port['name']
device_owner = neutron_port['device_owner']
vnic_type = port_profiles[port_id]['vnic_type']
network_id = neutron_port['network_id']
segments = []
if self.hpb_supported():
@ -1712,44 +1684,47 @@ class AristaRPCWrapperEapi(AristaRPCWrapperBase):
cmds.extend(
'segment level %d id %s' % (level, segment['id'])
for level, segment in enumerate(segments))
elif device_owner.startswith('baremetal'):
append_cmd('instance id %s hostid %s type baremetal' %
(vm['vmId'], v_port['hosts'][0]))
profile = bm_port_profiles[neutron_port['id']]
profile = json.loads(profile['profile'])
for binding in profile['local_link_information']:
if not binding or not isinstance(binding, dict):
# skip all empty entries
continue
# Ensure that profile contains switch and port ID info
if binding['switch_id'] and binding['port_id']:
if port_name:
cmds.append('port id %s name "%s" '
'network-id %s type native '
'switch-id %s switchport %s' %
(port_id, port_name, network_id,
binding['switch_id'],
binding['port_id']))
else:
cmds.append('port id %s network-id %s '
'type native '
'switch-id %s switchport %s' %
(port_id, network_id,
binding['switch_id'],
binding['port_id']))
cmds.extend('segment level %d id %s' % (
level, segment['id'])
for level, segment in enumerate(segments))
elif (device_owner.startswith('compute') or
device_owner.startswith('baremetal')):
if vnic_type == 'baremetal':
append_cmd('instance id %s hostid %s type baremetal' %
(vm['vmId'], v_port['hosts'][0]))
profile = port_profiles[neutron_port['id']]
profile = json.loads(profile['profile'])
for binding in profile['local_link_information']:
if not binding or not isinstance(binding, dict):
# skip all empty entries
continue
# Ensure that profile contains local link info
if binding['switch_id'] and binding['port_id']:
if port_name:
cmds.append('port id %s name "%s" '
'network-id %s type native '
'switch-id %s switchport %s' %
(port_id, port_name,
network_id,
binding['switch_id'],
binding['port_id']))
else:
cmds.append('port id %s network-id %s '
'type native '
'switch-id %s switchport %s' %
(port_id, network_id,
binding['switch_id'],
binding['port_id']))
cmds.extend('segment level %d id %s' % (
level, segment['id'])
for level, segment in enumerate(segments))
elif device_owner.startswith('compute'):
append_cmd('vm id %s hostid %s' % (vm['vmId'],
v_port['hosts'][0]))
append_cmd('port id %s %s network-id %s' %
(neutron_port['id'], port_name,
neutron_port['network_id']))
cmds.extend('segment level %d id %s' % (level,
segment['id'])
for level, segment in enumerate(segments))
else:
append_cmd('vm id %s hostid %s' % (vm['vmId'],
v_port['hosts'][0]))
append_cmd('port id %s %s network-id %s' %
(neutron_port['id'], port_name,
neutron_port['network_id']))
cmds.extend('segment level %d id %s' % (level,
segment['id'])
for level, segment in enumerate(segments))
elif device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE:
if not self.bm_and_dvr_supported():
LOG.info(ERR_DVR_NOT_SUPPORTED)
@ -2125,7 +2100,7 @@ class SyncService(object):
)
# Get Baremetal port switch_bindings, if any
bm_port_profiles = db_lib.get_all_baremetal_ports()
port_profiles = db_lib.get_all_portbindings()
# To support shared networks, split the sync loop in two parts:
# In first loop, delete unwanted VM and networks and update networks
# In second loop, update VMs. This is done to ensure that networks for
@ -2230,7 +2205,7 @@ class SyncService(object):
self._rpc.create_instance_bulk(tenant,
ports_of_interest,
db_vms,
bm_port_profiles,
port_profiles,
sync=True)
except arista_exc.AristaRpcError:
LOG.warning(EOS_UNREACHABLE_MSG)

View File

@ -490,8 +490,10 @@ class TestAristaJSONRPCWrapper(testlib_api.SqlTestCase):
profiles = {}
for port in port_list:
profiles[port['portId']] = {'vnic_type': 'normal'}
if port['device_owner'] == 'baremetal':
profiles[port['portId']] = {
'vnic_type': 'baremetal',
'profile': '{"local_link_information":'
'[{"switch_id": "switch01", "port_id": "Ethernet1"}]}'}
self.drv.create_instance_bulk(tenant_id, create_ports, devices,
@ -741,7 +743,7 @@ class TestAristaJSONRPCWrapper(testlib_api.SqlTestCase):
switch_bindings = [{'switch_id': 'switch01', 'port_id': 'Ethernet1',
'switch_info': 'switch01'}]
self.drv.plug_port_into_network('bm1', 'h1', 'p1', 'n1', 't1', 'port1',
'baremetal', sg, None, None,
'baremetal', sg, None, 'baremetal',
segments,
switch_bindings=switch_bindings)
calls = [
@ -767,7 +769,8 @@ class TestAristaJSONRPCWrapper(testlib_api.SqlTestCase):
mock_get_instance_ports.return_value = []
switch_bindings = [{'switch_id': 'switch01', 'port_id': 'Ethernet1'}]
self.drv.unplug_port_from_network('bm1', 'baremetal', 'h1', 'p1', 'n1',
't1', None, None, switch_bindings)
't1', None, 'baremetal',
switch_bindings)
port = self.drv._create_port_data('p1', None, None, 'bm1', None,
'baremetal', None)
calls = [
@ -1174,12 +1177,14 @@ class PositiveRPCWrapperValidConfigTestCase(testlib_api.SqlTestCase):
net_count += 1
create_ports = {}
port_profiles = {}
for port in port_list:
create_ports.update(port_dict_representation(port))
port_profiles[port['portId']] = {'vnic_type': 'normal'}
self.drv.cli_commands[arista_ml2.CMD_INSTANCE] = 'instance'
self.drv.create_instance_bulk(tenant_id, create_ports, devices,
bm_port_profiles=None)
port_profiles=port_profiles)
cmd1 = ['show openstack agent uuid']
cmd2 = ['enable',
'configure',
@ -1470,12 +1475,14 @@ class PositiveRPCWrapperValidConfigTestCase(testlib_api.SqlTestCase):
net_count += 1
create_ports = {}
port_profiles = {}
for port in port_list:
create_ports.update(port_dict_representation(port))
port_profiles[port['portId']] = {'vnic_type': 'normal'}
self.drv.cli_commands[arista_ml2.CMD_INSTANCE] = 'instance'
self.drv.create_instance_bulk(tenant_id, create_ports, devices,
bm_port_profiles=None, sync=True)
port_profiles=port_profiles, sync=True)
cmd1 = ['show openstack agent uuid']
cmd2 = ['enable',
'configure',