Skip to content

Commit

Permalink
Handler for VmReconfiguredEvent
Browse files Browse the repository at this point in the history
Add VmReconfiguredHandler to VmwareController handlers

Delete and create VMI on VMIs network update

Refactored asserting VMI model state

Change-Id: Iba22674eb4de98f557faae6a4f2d3a7b906c91e6
Closes-Bug: #1774661
  • Loading branch information
krzysztofg256 authored and aszc-dev committed Jun 7, 2018
1 parent 944be4b commit 791be8e
Show file tree
Hide file tree
Showing 7 changed files with 344 additions and 115 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -105,3 +105,6 @@ config.yaml

# idea files
.idea/

# pytest
.pytest_cache/
6 changes: 4 additions & 2 deletions cvm/__main__.py
Expand Up @@ -8,7 +8,7 @@
import cvm.constants as const
from cvm.clients import (ESXiAPIClient, VCenterAPIClient, VNCAPIClient,
VRouterAPIClient)
from cvm.controllers import VmRenamedHandler, VmwareController
from cvm.controllers import VmRenamedHandler, VmReconfiguredHandler, VmwareController
from cvm.database import Database
from cvm.monitors import VMwareMonitor
from cvm.services import (VirtualMachineInterfaceService,
Expand Down Expand Up @@ -56,7 +56,9 @@ def main():
database=database
)
vm_renamed_handler = VmRenamedHandler(vm_service, vmi_service)
vmware_controller = VmwareController(vm_service, vn_service, vmi_service, [vm_renamed_handler])
vm_reconfigured_handler = VmReconfiguredHandler(vm_service, vmi_service)
handlers = [vm_renamed_handler, vm_reconfigured_handler]
vmware_controller = VmwareController(vm_service, vn_service, vmi_service, handlers)
vmware_monitor = VMwareMonitor(esxi_api_client, vmware_controller)

greenlets = [
Expand Down
44 changes: 38 additions & 6 deletions cvm/controllers.py
@@ -1,3 +1,4 @@
from abc import abstractmethod, ABCMeta
import logging

from pyVmomi import vim, vmodl # pylint: disable=no-name-in-module
Expand Down Expand Up @@ -50,7 +51,6 @@ def _handle_event(self, event):
vim.event.VmCreatedEvent,
vim.event.VmClonedEvent,
vim.event.VmDeployedEvent,
vim.event.VmReconfiguredEvent,
vim.event.VmMacChangedEvent,
vim.event.VmMacAssignedEvent,
vim.event.DrsVmMigratedEvent,
Expand Down Expand Up @@ -91,10 +91,8 @@ def _handle_net_change(self, nic_infos):
self._vmi_service.update_nic(nic_info)


class VmRenamedHandler(object):
def __init__(self, vm_service, vmi_service):
self._vm_service = vm_service
self._vmi_service = vmi_service
class AbstractEventHandler(object):
__metaclass__ = ABCMeta

def handle_update(self, update_set):
for property_filter_update in update_set.filterSet:
Expand All @@ -107,10 +105,44 @@ def _handle_change(self, property_change):
value = getattr(property_change, 'val', None)
if value:
if name.startswith('latestPage'):
if isinstance(value, vim.event.VmRenamedEvent):
if isinstance(value, self.EVENTS):
self._handle_event(value)

@abstractmethod
def _handle_event(self, event):
pass


class VmRenamedHandler(AbstractEventHandler):
EVENTS = (vim.event.VmRenamedEvent,)

def __init__(self, vm_service, vmi_service):
self._vm_service = vm_service
self._vmi_service = vmi_service

def _handle_event(self, event):
vmware_vm = event.vm.vm
self._vm_service.rename_vm(vmware_vm)
self._vmi_service.rename_vmis(vmware_vm)


class VmReconfiguredHandler(AbstractEventHandler):
EVENTS = (vim.event.VmReconfiguredEvent,)

def __init__(self, vm_service, vmi_service):
self._vm_service = vm_service
self._vmi_service = vmi_service

def _handle_event(self, event):
logger.info('Detected VmReconfiguredEvent')
vmware_vm = event.vm.vm
for device_spec in event.configSpec.deviceChange:
device = device_spec.device
if isinstance(device, vim.vm.device.VirtualVmxnet3):
logger.info('Detected VmReconfiguredEvent with %s device', type(device))
mac_address = device.macAddress
portgroup_key = device.backing.port.portgroupKey
self._vm_service.update_vm_models_interface(vmware_vm, mac_address, portgroup_key)
self._vmi_service.update_vmis_vn(vmware_vm, mac_address, portgroup_key)
else:
logger.info('Detected VmReconfiguredEvent with unsupported %s device', type(device))
32 changes: 17 additions & 15 deletions cvm/models.py
Expand Up @@ -93,6 +93,9 @@ def rename(self, vmware_vm):
self.vmware_vm = vmware_vm
self.vm_properties['name'] = vmware_vm.name

def update_interface_portgroup_key(self, mac_address, portgroup_key):
self.interfaces[mac_address] = portgroup_key

def _read_interfaces(self):
try:
return {device.macAddress: device.backing.port.portgroupKey
Expand Down Expand Up @@ -187,6 +190,7 @@ def __init__(self, vm_model, vn_model, parent, security_group):
self.vn_model = vn_model
self.mac_address = find_vm_mac_address(self.vm_model.vmware_vm, self.vn_model.key)
self.ip_address = None
self.port_key = None
self.vlan_id = None
self.security_group = security_group
self.vnc_vmi = None
Expand All @@ -201,23 +205,21 @@ def uuid(self):
def display_name(self):
return 'vmi-{}-{}'.format(self.vn_model.name, self.vm_model.name)

@property
def port_key(self):
return find_vmi_port_key(self.vm_model.vmware_vm, self.mac_address)
def refresh_port_key(self):
self.port_key = find_vmi_port_key(self.vm_model.vmware_vm, self.mac_address)

def to_vnc(self):
if not self.vnc_vmi:
self.vnc_vmi = VirtualMachineInterface(name=self.uuid,
display_name=self.display_name,
parent_obj=self.parent,
id_perms=ID_PERMS)
self.vnc_vmi.set_uuid(self.uuid)
self.vnc_vmi.add_virtual_machine(self.vm_model.vnc_vm)
self.vnc_vmi.set_virtual_network(self.vn_model.vnc_vn)
self.vnc_vmi.set_virtual_machine_interface_mac_addresses(MacAddressesType([self.mac_address]))
self.vnc_vmi.set_port_security_enabled(True)
self.vnc_vmi.set_security_group(self.security_group)
return self.vnc_vmi
vnc_vmi = VirtualMachineInterface(name=self.uuid,
display_name=self.display_name,
parent_obj=self.parent,
id_perms=ID_PERMS)
vnc_vmi.set_uuid(self.uuid)
vnc_vmi.add_virtual_machine(self.vm_model.vnc_vm)
vnc_vmi.set_virtual_network(self.vn_model.vnc_vn)
vnc_vmi.set_virtual_machine_interface_mac_addresses(MacAddressesType([self.mac_address]))
vnc_vmi.set_port_security_enabled(True)
vnc_vmi.set_security_group(self.security_group)
return vnc_vmi

def construct_instance_ip(self):
if not self._should_construct_instance_ip():
Expand Down
44 changes: 25 additions & 19 deletions cvm/services.py
Expand Up @@ -84,6 +84,10 @@ def rename_vm(self, vmware_vm):
self._vnc_api_client.update_or_create_vm(vm_model.vnc_vm)
self._database.save(vm_model)

def update_vm_models_interface(self, vmware_vm, mac_address, portgroup_key):
vm_model = self._database.get_vm_model_by_uuid(vmware_vm.config.instanceUuid)
vm_model.update_interface_portgroup_key(mac_address, portgroup_key)


class VirtualNetworkService(Service):
def __init__(self, vcenter_api_client, vnc_api_client, database):
Expand Down Expand Up @@ -122,32 +126,34 @@ def update_vmis_for_vm_model(self, vm_model):
existing_vmi_models = {vmi_model.mac_address: vmi_model
for vmi_model in self._database.get_vmi_models_by_vm_uuid(vm_model.uuid)}
for mac_address, portgroup_key in vm_model.interfaces.iteritems():
vmi_model = existing_vmi_models.pop(mac_address, None)
vn_model = self._database.get_vn_model_by_key(portgroup_key)
if vmi_model:
self._update_vmis_vn(vmi_model, vn_model)
else:
vmi_model = VirtualMachineInterfaceModel(
vm_model,
vn_model,
self._project,
self._default_security_group
)
self._create_or_update(vmi_model)
existing_vmi_models.pop(mac_address, None)
self.update_vmis_vn(vm_model.vmware_vm, mac_address, portgroup_key)

for unused_vmi_model in existing_vmi_models.values():
self._delete(unused_vmi_model)

def _update_vmis_vn(self, vmi_model, vn_model):
if vmi_model.vn_model == vn_model:
return
vmi_model.clear_vlan_id()
vmi_model.vn_model = vn_model
self._vnc_api_client.delete_instance_ip(vmi_model.vnc_instance_ip)
def update_vmis_vn(self, vmware_vm, mac_address, portgroup_key):
vmi_model = self._database.get_vmi_model_by_uuid(VirtualMachineInterfaceModel.get_uuid(mac_address))
vn_model = self._database.get_vn_model_by_key(portgroup_key)
vm_model = self._database.get_vm_model_by_uuid(vmware_vm.config.instanceUuid)
if not vmi_model:
vmi_model = VirtualMachineInterfaceModel(
vm_model,
vn_model,
self._project,
self._default_security_group
)
if vmi_model.vn_model != vn_model:
with self._vcenter_api_client:
self._vcenter_api_client.restore_vlan_id(vmi_model.vn_model.dvs_name, vmi_model.port_key)
vmi_model.clear_vlan_id()
vmi_model.vn_model = vn_model
self._delete(vmi_model)
self._create_or_update(vmi_model)

def _create_or_update(self, vmi_model):
with self._vcenter_api_client:
self._vcenter_api_client.restore_vlan_id(vmi_model.vn_model.dvs_name, vmi_model.port_key)
vmi_model.refresh_port_key()
vmi_model.acquire_vlan_id()
self._vcenter_api_client.set_vlan_id(vmi_model.vn_model.dvs_name, vmi_model.port_key, vmi_model.vlan_id)
self._vnc_api_client.update_or_create_vmi(vmi_model.to_vnc())
Expand Down

0 comments on commit 791be8e

Please sign in to comment.