From af4cf6c6e5b6b28139e30f55d1a78d84cb760544 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Wed, 13 May 2015 18:54:18 -0700 Subject: [PATCH] vnf-update: update attributes Change-Id: Id5b11643bf28e977c52caccadd5d574132d72c24 --- tacker/db/vm/vm_db.py | 13 ++++++- tacker/tests/unit/services/vm/drivers/noop.py | 19 +++++----- tacker/vm/drivers/abstract_driver.py | 4 ++- tacker/vm/drivers/heat/heat.py | 35 +++++++++++++++++-- tacker/vm/drivers/nova/nova.py | 3 +- tacker/vm/plugin.py | 9 +++-- 6 files changed, 65 insertions(+), 18 deletions(-) diff --git a/tacker/db/vm/vm_db.py b/tacker/db/vm/vm_db.py index ce4bf2730..1a2c2d50b 100644 --- a/tacker/db/vm/vm_db.py +++ b/tacker/db/vm/vm_db.py @@ -605,13 +605,24 @@ class ServiceResourcePluginDb(servicevm.ServiceVMPluginBase, context, device_id, _ACTIVE_UPDATE, constants.PENDING_UPDATE) return self._make_device_dict(device_db) - def _update_device_post(self, context, device_id, new_status): + def _update_device_post(self, context, device_id, new_status, + new_device_dict=None): with context.session.begin(subtransactions=True): (self._model_query(context, Device). filter(Device.id == device_id). filter(Device.status == constants.PENDING_UPDATE). update({'status': new_status})) + dev_attrs = new_device_dict.get('attributes', {}) + (context.session.query(DeviceAttribute). + filter(DeviceAttribute.device_id == device_id). + filter(~DeviceAttribute.key.in_(dev_attrs.keys())). + delete(synchronize_session='fetch')) + + for (key, value) in dev_attrs.items(): + self._device_attribute_update_or_create(context, device_id, + key, value) + def _delete_device_pre(self, context, device_id): with context.session.begin(subtransactions=True): # TODO(yamahata): race. keep others from inserting new binding diff --git a/tacker/tests/unit/services/vm/drivers/noop.py b/tacker/tests/unit/services/vm/drivers/noop.py index be6a4ff42..a9fd0a6da 100644 --- a/tacker/tests/unit/services/vm/drivers/noop.py +++ b/tacker/tests/unit/services/vm/drivers/noop.py @@ -22,6 +22,7 @@ # TODO(yamahata): once unittests are impletemted, move this there import uuid +from tacker.common import log from tacker.openstack.common import log as logging from tacker.vm.drivers import abstract_driver @@ -46,28 +47,30 @@ class DeviceNoop(abstract_driver.DeviceAbstractDriver): def get_description(self): return 'Nuetron Device Noop driver' + @log.log def create(self, **kwargs): - LOG.debug(_('create %s'), kwargs) instance_id = str(uuid.uuid4()) self._instances.add(instance_id) return instance_id + @log.log def create_wait(self, plugin, context, device_dict, device_id): - LOG.debug(_('create_wait %s'), device_id) + pass - def update(self, plugin, context, device_id, **kwargs): - LOG.debug(_('update device_id %(devcie_id)s kwargs %(kwargs)s'), - {'device_id': device_id, 'kwargs': kwargs}) + @log.log + def update(self, plugin, context, device_id, device_dict, device): if device_id not in self._instances: LOG.debug(_('not found')) raise ValueError('No instance %s' % device_id) + @log.log def update_wait(self, plugin, context, device_id): - LOG.debug(_('update_wait %s'), device_id) + pass + @log.log def delete(self, plugin, context, device_id): - LOG.debug(_('delete %s'), device_id) self._instances.remove(device_id) + @log.log def delete_wait(self, plugin, context, device_id): - LOG.debug(_('delete_wait %s'), device_id) + pass diff --git a/tacker/vm/drivers/abstract_driver.py b/tacker/vm/drivers/abstract_driver.py index ba7529fa4..7656e58b0 100644 --- a/tacker/vm/drivers/abstract_driver.py +++ b/tacker/vm/drivers/abstract_driver.py @@ -58,7 +58,9 @@ class DeviceAbstractDriver(extensions.PluginInterface): """wait for device creation to complete.""" @abc.abstractmethod - def update(self, plugin, context, device): + def update(self, plugin, context, device_id, device_dict, device): + # device_dict: old device_dict to be updated + # device: update with device dict pass @abc.abstractmethod diff --git a/tacker/vm/drivers/heat/heat.py b/tacker/vm/drivers/heat/heat.py index 26e4b0666..87b9adeb3 100644 --- a/tacker/vm/drivers/heat/heat.py +++ b/tacker/vm/drivers/heat/heat.py @@ -266,10 +266,39 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver): # work around. mgmt suports Only single vm for now. device_dict['mgmt_url'] = mgmt_ips[0] - def update(self, plugin, context, device): - # do nothing but checking if the stack exists at the moment + @log.log + def update(self, plugin, context, device_id, device_dict, device): + # checking if the stack exists at the moment heatclient_ = HeatClient(context) - heatclient_.get(device['id']) + heatclient_.get(device_id) + + # update config attribute + config_yaml = device_dict.get('attributes', {}).get('config', '') + update_yaml = device['device'].get('attributes', {}).get('config', '') + LOG.debug('yaml orig %(orig)s update %(update)s', + {'orig': config_yaml, 'update': update_yaml}) + config_dict = yaml.load(config_yaml) or {} + update_dict = yaml.load(update_yaml) + if not update_dict: + return + + @log.log + def deep_update(orig_dict, new_dict): + for key, value in new_dict.items(): + if isinstance(value, dict): + if key in orig_dict and isinstance(orig_dict[key], dict): + deep_update(orig_dict[key], value) + continue + + orig_dict[key] = value + + LOG.debug('dict orig %(orig)s update %(update)s', + {'orig': config_dict, 'update': update_dict}) + deep_update(config_dict, update_dict) + LOG.debug('dict new %(new)s update %(update)s', + {'new': config_dict, 'update': update_dict}) + new_yaml = yaml.dump(config_dict) + device_dict.setdefault('attributes', {})['config'] = new_yaml def update_wait(self, plugin, context, device_id): # do nothing but checking if the stack exists at the moment diff --git a/tacker/vm/drivers/nova/nova.py b/tacker/vm/drivers/nova/nova.py index 27da07c84..868aa17fc 100644 --- a/tacker/vm/drivers/nova/nova.py +++ b/tacker/vm/drivers/nova/nova.py @@ -240,9 +240,8 @@ class DeviceNova(abstract_driver.DeviceAbstractDriver): if status == 'ERROR': raise RuntimeError(_("creation of server %s faild") % device_id) - def update(self, plugin, context, device): + def update(self, plugin, context, device_id, device_dict, device): # do nothing but checking if the instance exists at the moment - device_id = device['id'] nova = self._nova_client() nova.servers.get(device_id) diff --git a/tacker/vm/plugin.py b/tacker/vm/plugin.py index fb3d90e48..910548e90 100644 --- a/tacker/vm/plugin.py +++ b/tacker/vm/plugin.py @@ -339,7 +339,9 @@ class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin): new_status = constants.ERROR device_dict['status'] = new_status self.mgmt_update_post(context, device_dict) - self._update_device_post(context, device_dict['id'], new_status) + + self._update_device_post(context, device_dict['id'], + new_status, device_dict) def update_device(self, context, device_id, device): device_dict = self._update_device_pre(context, device_id) @@ -348,8 +350,9 @@ class ServiceVMPlugin(vm_db.ServiceResourcePluginDb, ServiceVMMgmtMixin): try: self.mgmt_update_pre(context, device_dict) - self._device_manager.invoke(driver_name, 'update', plugin=self, - context=context, device_id=instance_id) + self._device_manager.invoke( + driver_name, 'update', plugin=self, context=context, + device_id=instance_id, device_dict=device_dict, device=device) except Exception: with excutils.save_and_reraise_exception(): device_dict['status'] = constants.ERROR