Skip to content

Commit

Permalink
vMotion VLAN ID fix
Browse files Browse the repository at this point in the history
Check VLAN availability after vMotion

Change-Id: I739e77dcee6f89fad67fbb529ad75e5dcba4f6d0
Closes-Bug: #1783979
  • Loading branch information
aszc-dev committed Jul 27, 2018
1 parent 461394a commit 8ae8897
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 9 deletions.
7 changes: 5 additions & 2 deletions cvm/services.py
Expand Up @@ -230,8 +230,11 @@ def _create_or_update(self, vmi_model):
def _assign_vlan_id(self, vmi_model):
with self._vcenter_api_client:
current_vlan_id = self._vcenter_api_client.get_vlan_id(vmi_model.vcenter_port)
vmi_model.vcenter_port.vlan_id = current_vlan_id or self._vlan_id_pool.get_available()
if not current_vlan_id:
if current_vlan_id and self._vlan_id_pool.is_available(current_vlan_id):
vmi_model.vcenter_port.vlan_id = current_vlan_id
self._vlan_id_pool.reserve(current_vlan_id)
else:
vmi_model.vcenter_port.vlan_id = self._vlan_id_pool.get_available()
self._vcenter_api_client.set_vlan_id(vmi_model.vcenter_port)

def _add_vnc_info_to(self, vmi_model):
Expand Down
41 changes: 37 additions & 4 deletions tests/functional/test_vm_created_vlan_id.py
Expand Up @@ -4,16 +4,16 @@
def test_vm_created_vlan_id(controller, database, vcenter_api_client, vm_created_update, vn_model_1, vlan_id_pool):
"""
What happens when the created interface is already using an overriden VLAN ID?
We should keep it, not removing old/adding new VLAN ID, since it breaks the connectivity
for a moment.
We should keep it (if it's available on the host), not removing old/adding new VLAN ID,
since it breaks the connectivity for a moment.
"""

# Virtual Networks are already created for us and after synchronization,
# their models are stored in our database
database.save(vn_model_1)

# Some vlan ids should be already reserved
reserve_vlan_ids(vlan_id_pool, [0, 1, 5])
reserve_vlan_ids(vlan_id_pool, [0, 1])

# When we ask vCenter for the VLAN ID it turns out that the VLAN ID has already been overridden
vcenter_api_client.get_vlan_id.return_value = 5
Expand All @@ -25,7 +25,7 @@ def test_vm_created_vlan_id(controller, database, vcenter_api_client, vm_created
vcenter_api_client.set_vlan_id.assert_not_called()

# Check inner VMI model state
vm_model = database.get_vm_model_by_uuid('12345678-1234-1234-1234-123456789012')
vm_model = database.get_vm_model_by_uuid('vmware-vm-uuid-1')
vmi_model = database.get_all_vmi_models()[0]
assert_vmi_model_state(
vmi_model,
Expand All @@ -36,3 +36,36 @@ def test_vm_created_vlan_id(controller, database, vcenter_api_client, vm_created
vn_model=vn_model_1,
vm_model=vm_model
)


def test_vmotion_vlan_unavailable(controller, database, vcenter_api_client, vm_created_update, vn_model_1,
vlan_id_pool):
""" When the VLAN ID is unavailable on a host, we should change it to a new value"""
# Virtual Networks are already created for us and after synchronization,
# their models are stored in our database
database.save(vn_model_1)

# Some vlan ids should be already reserved
reserve_vlan_ids(vlan_id_pool, [0, 1, 5])

# When we ask vCenter for the VLAN ID it turns out that the VLAN ID has already been overridden
vcenter_api_client.get_vlan_id.return_value = 5

# A new update containing VmCreatedEvent arrives and is being handled by the controller
controller.handle_update(vm_created_update)

# Check if VLAN ID has been changed
vmi_model = database.get_all_vmi_models()[0]
vcenter_api_client.set_vlan_id.assert_called_once_with(vmi_model.vcenter_port)

# Check inner VMI model state
vm_model = database.get_vm_model_by_uuid('vmware-vm-uuid-1')
assert_vmi_model_state(
vmi_model,
mac_address='mac-address',
ip_address='192.168.100.5',
vlan_id=2,
display_name='vmi-DPG1-VM1',
vn_model=vn_model_1,
vm_model=vm_model
)
15 changes: 12 additions & 3 deletions tests/unit/services/test_vlan_ids.py
Expand Up @@ -30,17 +30,26 @@ def test_assign_new_vlan_id(vmi_service, database, vcenter_api_client,
assert vmi_model.vcenter_port.vlan_id == 2


def test_retain_old_vlan_id(vmi_service, database, vcenter_api_client,
vlan_id_pool, vmi_model):
def test_retain_old_vlan_id(vmi_service, database, vcenter_api_client, vmi_model):
database.vmis_to_update.append(vmi_model)
reserve_vlan_ids(vlan_id_pool, [20])
vcenter_api_client.get_vlan_id.return_value = 20

vmi_service.update_vmis()

assert vmi_model.vcenter_port.vlan_id == 20


def test_current_not_available(vmi_service, database, vcenter_api_client,
vlan_id_pool, vmi_model):
database.vmis_to_update.append(vmi_model)
vcenter_api_client.get_vlan_id.return_value = 20
reserve_vlan_ids(vlan_id_pool, [20])

vmi_service.update_vmis()

assert vmi_model.vcenter_port.vlan_id == 0


def test_restore_vlan_id(vmi_service, database, vcenter_api_client,
vlan_id_pool, vmi_model):
reserve_vlan_ids(vlan_id_pool, [20])
Expand Down

0 comments on commit 8ae8897

Please sign in to comment.