orig_port = context.original
if new_port['name'] != orig_port['name']:
LOG.info(_LI('Port name changed to %s'), new_port['name'])
+ new_port = context.current
+ device_id = new_port['device_id']
+ device_owner = new_port['device_owner']
+ host = context.host
+
+ # device_id and device_owner are set on VM boot
+ is_vm_boot = device_id and device_owner
+ if host and host != orig_port['binding:host_id'] and is_vm_boot:
+ port_id = new_port['id']
+ network_id = new_port['network_id']
+ tenant_id = new_port['tenant_id']
+ if not tenant_id:
+ tenant_id = context._plugin_context.tenant_id
+ with self.eos_sync_lock:
+ db_lib.update_vm_host(device_id, host, port_id,
+ network_id, tenant_id)
def update_port_postcommit(self, context):
"""Update the name of a given port in EOS.
"""
port = context.current
orig_port = context.original
- if port['name'] == orig_port['name']:
- # nothing to do
- return
device_id = port['device_id']
device_owner = port['device_owner']
)
if vm_provisioned and net_provisioned:
try:
+ orig_host = orig_port['binding:host_id']
+ if host != orig_host:
+ # The port moved to a different host. So delete the
+ # old port on the old host before creating a new
+ # port on the new host.
+ self._delete_port(port, orig_host, tenant_id)
self.rpc.plug_port_into_network(device_id,
hostname,
port_id,
from appropriate network.
"""
port = context.current
- device_id = port['device_id']
host = context.host
- port_id = port['id']
- network_id = port['network_id']
tenant_id = port['tenant_id']
if not tenant_id:
tenant_id = context._plugin_context.tenant_id
+
+ with self.eos_sync_lock:
+ self._delete_port(port, host, tenant_id)
+
+ def _delete_port(self, port, host, tenant_id):
+ """Deletes the port from EOS.
+
+ param port: Port which is to be deleted
+ param host: The host on which the port existed
+ param tenant_id: The tenant to which the port belongs to. Some times
+ the tenant id in the port dict is not present (as in
+ the case of HA router).
+ """
+ device_id = port['device_id']
+ port_id = port['id']
+ network_id = port['network_id']
device_owner = port['device_owner']
try:
- with self.eos_sync_lock:
- hostname = self._host_name(host)
- if device_owner == n_const.DEVICE_OWNER_DHCP:
- self.rpc.unplug_dhcp_port_from_network(device_id,
- hostname,
- port_id,
- network_id,
- tenant_id)
- else:
- self.rpc.unplug_host_from_network(device_id,
- hostname,
- port_id,
- network_id,
- tenant_id)
+ hostname = self._host_name(host)
+ if device_owner == n_const.DEVICE_OWNER_DHCP:
+ self.rpc.unplug_dhcp_port_from_network(device_id,
+ hostname,
+ port_id,
+ network_id,
+ tenant_id)
+ else:
+ self.rpc.unplug_host_from_network(device_id,
+ hostname,
+ port_id,
+ network_id,
+ tenant_id)
# if necessary, delete tenant as well.
self.delete_tenant(tenant_id)
except arista_exc.AristaRpcError:
mechanism_arista.db_lib.assert_has_calls(expected_calls)
+ def test_update_port_precommit(self):
+ tenant_id = 'ten-1'
+ network_id = 'net1-id'
+ segmentation_id = 1001
+ vm_id = 'vm1'
+
+ network_context = self._get_network_context(tenant_id,
+ network_id,
+ segmentation_id,
+ False)
+
+ port_context = self._get_port_context(tenant_id,
+ network_id,
+ vm_id,
+ network_context)
+ host_id = port_context.current['binding:host_id']
+ port_context.original['binding:host_id'] = 'ubuntu0'
+ port_id = port_context.current['id']
+ self.drv.update_port_precommit(port_context)
+
+ expected_calls = [
+ mock.call.update_vm_host(vm_id, host_id, port_id,
+ network_id, tenant_id)
+ ]
+
+ mechanism_arista.db_lib.assert_has_calls(expected_calls)
+
+ def test_update_port_postcommit(self):
+ tenant_id = 'ten-1'
+ network_id = 'net1-id'
+ segmentation_id = 1001
+ vm_id = 'vm1'
+
+ network_context = self._get_network_context(tenant_id,
+ network_id,
+ segmentation_id,
+ False)
+ port_context = self._get_port_context(tenant_id,
+ network_id,
+ vm_id,
+ network_context)
+
+ mechanism_arista.db_lib.is_vm_provisioned.return_value = True
+ mechanism_arista.db_lib.is_network_provisioned.return_value = True
+ mechanism_arista.db_lib.get_shared_network_owner_id.return_value = 1
+ mechanism_arista.db_lib.get_segmentation_id.return_value = 1001
+ mechanism_arista.db_lib.num_nets_provisioned.return_value = 1
+ mechanism_arista.db_lib.num_vms_provisioned.return_value = 1
+
+ port = port_context.current
+ device_id = port['device_id']
+ device_owner = port['device_owner']
+ host_id = port['binding:host_id']
+ orig_host_id = 'ubuntu0'
+ port_context.original['binding:host_id'] = orig_host_id
+ port_id = port['id']
+ port_name = port['name']
+
+ self.drv.update_port_postcommit(port_context)
+
+ expected_calls = [
+ mock.call.NeutronNets(),
+ mock.call.get_segmentation_id(tenant_id, network_id),
+ mock.call.is_vm_provisioned(device_id, host_id, port_id,
+ network_id, tenant_id),
+ mock.call.is_network_provisioned(tenant_id, network_id,
+ segmentation_id),
+ mock.call.unplug_host_from_network(device_id, orig_host_id,
+ port_id, network_id, tenant_id),
+ mock.call.num_nets_provisioned(tenant_id),
+ mock.call.num_vms_provisioned(tenant_id),
+ mock.call.plug_port_into_network(device_id, host_id, port_id,
+ network_id, tenant_id,
+ port_name, device_owner)
+ ]
+
+ mechanism_arista.db_lib.assert_has_calls(expected_calls)
+
def _get_network_context(self, tenant_id, net_id, seg_id, shared):
network = {'id': net_id,
'tenant_id': tenant_id,
'id': 101,
'network_id': net_id
}
- return FakePortContext(port, port, network)
+ return FakePortContext(port, dict(port), network)
class fake_keystone_info_class(object):