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 return res
def _make_bm_port_dict(record): def _make_port_dict(record):
"""Make a dict from the BM profile DB record.""" """Make a dict from the BM profile DB record."""
return {'port_id': record.port_id, return {'port_id': record.port_id,
'host_id': record.host, 'host_id': record.host,
@ -431,10 +431,21 @@ def get_all_baremetal_ports():
querry = session.query(ml2_models.PortBinding) querry = session.query(ml2_models.PortBinding)
bm_ports = querry.filter_by(vnic_type='baremetal').all() 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} 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): def get_port_binding_level(filters):
"""Returns entries from PortBindingLevel based on the specified filters.""" """Returns entries from PortBindingLevel based on the specified filters."""
session = db.get_reader_session() session = db.get_reader_session()

View File

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

View File

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