almahmoud 7 лет назад
Родитель
Сommit
b5d89016db

+ 3 - 0
cloudbridge/cloud/base/resources.py

@@ -323,6 +323,9 @@ class BaseInstance(BaseCloudResource, BaseObjectLifeCycleMixin, Instance):
             timeout=timeout,
             interval=interval)
 
+    def delete(self):
+        self._provider.compute.instances.delete(self.id)
+
 
 class BaseLaunchConfig(LaunchConfig):
 

+ 70 - 0
cloudbridge/cloud/base/services.py

@@ -6,6 +6,7 @@ import logging
 import cloudbridge.cloud.base.helpers as cb_helpers
 from cloudbridge.cloud.base.middleware import implement
 from cloudbridge.cloud.base.resources import BaseBucket
+from cloudbridge.cloud.base.resources import BaseInstance
 from cloudbridge.cloud.base.resources import BaseKeyPair
 from cloudbridge.cloud.base.resources import BaseNetwork
 from cloudbridge.cloud.base.resources import BaseRouter
@@ -519,6 +520,75 @@ class BaseInstanceService(
         super(BaseInstanceService, self).__init__(provider)
         self._service_event_pattern += ".compute.instances"
 
+    def get(self, instance_id):
+        """
+        Returns a instance given its ID. Returns ``None`` if the instance
+        does not exist.
+
+        :type instance_id: str
+        :param instance_id: The id of the desired instance.
+
+        :rtype: ``Instance``
+        :return:  ``None`` is returned if the instance does not exist, and
+                  the instance's provider-specific CloudBridge object is
+                  returned if the instance is found.
+        """
+        return self.dispatch(self, "provider.compute.instances.get",
+                             instance_id)
+
+    def find(self, **kwargs):
+        """
+        Returns a list of instances filtered by the given keyword arguments.
+        Accepted search arguments are: 'label'
+        """
+        return self.dispatch(self, "provider.compute.instances.find",
+                             **kwargs)
+
+    def list(self, limit=None, marker=None):
+        """
+        List all instances.
+        """
+        return self.dispatch(self, "provider.compute.instances.list",
+                             limit=limit, marker=marker)
+
+    def create(self, label, image, vm_type, subnet, zone,
+               key_pair=None, vm_firewalls=None, user_data=None,
+               launch_config=None, **kwargs):
+        """
+        Create a new instance.
+
+        :type label: str
+        :param label: The label of the instance to be created. Note that labels
+                     do not have to be unique, and are changeable.
+        :type image: ``MachineImage``
+        :param image: The image to be used when creating the instance
+        :type vm_type: ``VMType``
+        :param vm_type: The type of virtual machine desired for this instance
+        :type subnet: ``Subnet``
+        :param subnet: The subnet to which the instance should be attached
+        :type zone: ``PlacementZone``
+        :param zone: The zone in which to place the instance
+
+        :rtype: ``Instance``
+        :return:  The created instance's provider-specific CloudBridge object.
+        """
+        BaseInstance.assert_valid_resource_label(label)
+        return self.dispatch(self, "provider.compute.instances.create",
+                             label, image, vm_type, subnet, zone,
+                             key_pair=key_pair, vm_firewalls=vm_firewalls,
+                             user_data=user_data, launch_config=launch_config,
+                             **kwargs)
+
+    def delete(self, instance_id):
+        """
+        Delete an existing instance.
+
+        :type instance_id: str
+        :param instance_id: The ID of the instance to be deleted.
+        """
+        return self.dispatch(self, "provider.compute.instances.delete",
+                             instance_id)
+
 
 class BaseVMTypeService(
         BasePageableObjectMixin, VMTypeService, BaseCloudService):

+ 0 - 3
cloudbridge/cloud/providers/aws/resources.py

@@ -280,9 +280,6 @@ class AWSInstance(BaseInstance):
     def reboot(self):
         self._ec2_instance.reboot()
 
-    def delete(self):
-        self._ec2_instance.terminate()
-
     @property
     def image_id(self):
         return self._ec2_instance.image_id

+ 61 - 53
cloudbridge/cloud/providers/aws/services.py

@@ -533,56 +533,6 @@ class AWSInstanceService(BaseInstanceService):
                                   cb_resource=AWSInstance,
                                   boto_collection_name='instances')
 
-    def create(self, label, image, vm_type, subnet, zone,
-               key_pair=None, vm_firewalls=None, user_data=None,
-               launch_config=None, **kwargs):
-        log.debug("Creating AWS Instance Service with the params "
-                  "[label: %s image: %s type: %s subnet: %s zone: %s "
-                  "key pair: %s firewalls: %s user data: %s config %s "
-                  "others: %s]", label, image, vm_type, subnet, zone,
-                  key_pair, vm_firewalls, user_data, launch_config, kwargs)
-        AWSInstance.assert_valid_resource_label(label)
-
-        image_id = image.id if isinstance(image, MachineImage) else image
-        vm_size = vm_type.id if \
-            isinstance(vm_type, VMType) else vm_type
-        subnet = (self.provider.networking.subnets.get(subnet)
-                  if isinstance(subnet, str) else subnet)
-        zone_id = zone.id if isinstance(zone, PlacementZone) else zone
-        key_pair_name = key_pair.name if isinstance(
-            key_pair,
-            KeyPair) else key_pair
-        if launch_config:
-            bdm = self._process_block_device_mappings(launch_config)
-        else:
-            bdm = None
-
-        subnet_id, zone_id, vm_firewall_ids = \
-            self._resolve_launch_options(subnet, zone_id, vm_firewalls)
-
-        placement = {'AvailabilityZone': zone_id} if zone_id else None
-        inst = self.svc.create('create_instances',
-                               ImageId=image_id,
-                               MinCount=1,
-                               MaxCount=1,
-                               KeyName=key_pair_name,
-                               SecurityGroupIds=vm_firewall_ids or None,
-                               UserData=str(user_data) or None,
-                               InstanceType=vm_size,
-                               Placement=placement,
-                               BlockDeviceMappings=bdm,
-                               SubnetId=subnet_id
-                               )
-        if inst and len(inst) == 1:
-            # Wait until the resource exists
-            # pylint:disable=protected-access
-            inst[0]._wait_till_exists()
-            # Tag the instance w/ the name
-            inst[0].label = label
-            return inst[0]
-        raise ValueError(
-            'Expected a single object response, got a list: %s' % inst)
-
     def _resolve_launch_options(self, subnet=None, zone_id=None,
                                 vm_firewalls=None):
         """
@@ -668,10 +618,60 @@ class AWSInstanceService(BaseInstanceService):
     def create_launch_config(self):
         return AWSLaunchConfig(self.provider)
 
-    def get(self, instance_id):
+    @implement(event_pattern="provider.compute.instances.create",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _create(self, label, image, vm_type, subnet, zone,
+                key_pair=None, vm_firewalls=None, user_data=None,
+                launch_config=None, **kwargs):
+
+        image_id = image.id if isinstance(image, MachineImage) else image
+        vm_size = vm_type.id if \
+            isinstance(vm_type, VMType) else vm_type
+        subnet = (self.provider.networking.subnets.get(subnet)
+                  if isinstance(subnet, str) else subnet)
+        zone_id = zone.id if isinstance(zone, PlacementZone) else zone
+        key_pair_name = key_pair.name if isinstance(
+            key_pair,
+            KeyPair) else key_pair
+        if launch_config:
+            bdm = self._process_block_device_mappings(launch_config)
+        else:
+            bdm = None
+
+        subnet_id, zone_id, vm_firewall_ids = \
+            self._resolve_launch_options(subnet, zone_id, vm_firewalls)
+
+        placement = {'AvailabilityZone': zone_id} if zone_id else None
+        inst = self.svc.create('create_instances',
+                               ImageId=image_id,
+                               MinCount=1,
+                               MaxCount=1,
+                               KeyName=key_pair_name,
+                               SecurityGroupIds=vm_firewall_ids or None,
+                               UserData=str(user_data) or None,
+                               InstanceType=vm_size,
+                               Placement=placement,
+                               BlockDeviceMappings=bdm,
+                               SubnetId=subnet_id
+                               )
+        if inst and len(inst) == 1:
+            # Wait until the resource exists
+            # pylint:disable=protected-access
+            inst[0]._wait_till_exists()
+            # Tag the instance w/ the name
+            inst[0].label = label
+            return inst[0]
+        raise ValueError(
+            'Expected a single object response, got a list: %s' % inst)
+
+    @implement(event_pattern="provider.compute.instances.get",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _get(self, instance_id):
         return self.svc.get(instance_id)
 
-    def find(self, **kwargs):
+    @implement(event_pattern="provider.compute.instances.find",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _find(self, **kwargs):
         label = kwargs.pop('label', None)
 
         # All kwargs should have been popped at this time.
@@ -681,9 +681,17 @@ class AWSInstanceService(BaseInstanceService):
 
         return self.svc.find(filter_name='tag:Name', filter_value=label)
 
-    def list(self, limit=None, marker=None):
+    @implement(event_pattern="provider.compute.instances.list",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _list(self, limit=None, marker=None):
         return self.svc.list(limit=limit, marker=marker)
 
+    @implement(event_pattern="provider.compute.instances.delete",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _delete(self, instance_id):
+        aws_ins = self.svc.get_raw(instance_id)
+        aws_ins.terminate()
+
 
 class AWSVMTypeService(BaseVMTypeService):
 

+ 0 - 25
cloudbridge/cloud/providers/azure/resources.py

@@ -1271,31 +1271,6 @@ class AzureInstance(BaseInstance):
         """
         self._provider.azure_client.restart_vm(self.id)
 
-    def delete(self):
-        """
-        Permanently terminate this instance.
-        After deleting the VM. we are deleting the network interface
-        associated to the instance, public ip addresses associated to
-        the instance and also removing OS disk and data disks where
-        tag with name 'delete_on_terminate' has value True.
-        """
-        # Remove IPs first to avoid a network interface conflict
-        for public_ip_id in self._public_ip_ids:
-            self.remove_floating_ip(public_ip_id)
-        self._provider.azure_client.deallocate_vm(self.id)
-        self._provider.azure_client.delete_vm(self.id)
-        for nic_id in self._nic_ids:
-            self._provider.azure_client.delete_nic(nic_id)
-        for data_disk in self._vm.storage_profile.data_disks:
-            if data_disk.managed_disk:
-                if self._vm.tags.get('delete_on_terminate',
-                                     'False') == 'True':
-                    self._provider.azure_client.\
-                        delete_disk(data_disk.managed_disk.id)
-        if self._vm.storage_profile.os_disk.managed_disk:
-            self._provider.azure_client. \
-                delete_disk(self._vm.storage_profile.os_disk.managed_disk.id)
-
     @property
     def image_id(self):
         """

+ 171 - 138
cloudbridge/cloud/providers/azure/services.py

@@ -579,141 +579,6 @@ class AzureInstanceService(BaseInstanceService):
     def __init__(self, provider):
         super(AzureInstanceService, self).__init__(provider)
 
-    def create(self, label, image, vm_type, subnet, zone,
-               key_pair=None, vm_firewalls=None, user_data=None,
-               launch_config=None, **kwargs):
-
-        AzureInstance.assert_valid_resource_label(label)
-
-        instance_name = AzureInstance._generate_name_from_label(label,
-                                                                "cb-ins")
-
-        image = (image if isinstance(image, AzureMachineImage) else
-                 self.provider.compute.images.get(image))
-        if not isinstance(image, AzureMachineImage):
-            raise Exception("Provided image %s is not a valid azure image"
-                            % image)
-
-        instance_size = vm_type.id if \
-            isinstance(vm_type, VMType) else vm_type
-
-        if not subnet:
-            # Azure has only a single zone per region; use the current one
-            zone = self.provider.compute.regions.get(
-                self.provider.region_name).zones[0]
-            subnet = self.provider.networking.subnets.get_or_create_default(
-                zone)
-        else:
-            subnet = (self.provider.networking.subnets.get(subnet)
-                      if isinstance(subnet, str) else subnet)
-
-        zone_id = zone.id if isinstance(zone, PlacementZone) else zone
-
-        subnet_id, zone_id, vm_firewall_id = \
-            self._resolve_launch_options(instance_name,
-                                         subnet, zone_id, vm_firewalls)
-
-        storage_profile = self._create_storage_profile(image, launch_config,
-                                                       instance_name, zone_id)
-
-        nic_params = {
-            'location': self.provider.region_name,
-            'ip_configurations': [{
-                'name': instance_name + '_ip_config',
-                'private_ip_allocation_method': 'Dynamic',
-                'subnet': {
-                    'id': subnet_id
-                }
-            }]
-        }
-
-        if vm_firewall_id:
-            nic_params['network_security_group'] = {
-                'id': vm_firewall_id
-            }
-        nic_info = self.provider.azure_client.create_nic(
-            instance_name + '_nic',
-            nic_params
-        )
-        # #! indicates shell script
-        ud = '#cloud-config\n' + user_data \
-            if user_data and not user_data.startswith('#!')\
-            and not user_data.startswith('#cloud-config') else user_data
-
-        # Key_pair is mandatory in azure and it should not be None.
-        temp_key_pair = None
-        if key_pair:
-            key_pair = (key_pair if isinstance(key_pair, AzureKeyPair)
-                        else self.provider.security.key_pairs.get(key_pair))
-        else:
-            # Create a temporary keypair if none is provided to keep Azure
-            # happy, but the private key will be discarded, so it'll be all
-            # but useless. However, this will allow an instance to be launched
-            # without specifying a keypair, so users may still be able to login
-            # if they have a preinstalled keypair/password baked into the image
-            temp_kp_name = "".join(["cb-default-kp-",
-                                   str(uuid.uuid5(uuid.NAMESPACE_OID,
-                                                  instance_name))[-6:]])
-            key_pair = self.provider.security.key_pairs.create(
-                name=temp_kp_name)
-            temp_key_pair = key_pair
-
-        params = {
-            'location': zone_id or self.provider.region_name,
-            'os_profile': {
-                'admin_username': self.provider.vm_default_user_name,
-                'computer_name': instance_name,
-                'linux_configuration': {
-                    "disable_password_authentication": True,
-                    "ssh": {
-                        "public_keys": [{
-                            "path":
-                                "/home/{}/.ssh/authorized_keys".format(
-                                        self.provider.vm_default_user_name),
-                                "key_data": key_pair._key_pair.Key
-                        }]
-                    }
-                }
-            },
-            'hardware_profile': {
-                'vm_size': instance_size
-            },
-            'network_profile': {
-                'network_interfaces': [{
-                    'id': nic_info.id
-                }]
-            },
-            'storage_profile': storage_profile,
-            'tags': {'Label': label}
-        }
-
-        for disk_def in storage_profile.get('data_disks', []):
-            params['tags'] = dict(disk_def.get('tags', {}), **params['tags'])
-
-        if user_data:
-            custom_data = base64.b64encode(bytes(ud, 'utf-8'))
-            params['os_profile']['custom_data'] = str(custom_data, 'utf-8')
-
-        if not temp_key_pair:
-            params['tags'].update(Key_Pair=key_pair.id)
-
-        try:
-            vm = self.provider.azure_client.create_vm(instance_name, params)
-        except Exception as e:
-            # If VM creation fails, attempt to clean up intermediary resources
-            self.provider.azure_client.delete_nic(nic_info.id)
-            for disk_def in storage_profile.get('data_disks', []):
-                if disk_def.get('tags', {}).get('delete_on_terminate'):
-                    disk_id = disk_def.get('managed_disk', {}).get('id')
-                    if disk_id:
-                        vol = self.provider.storage.volumes.get(disk_id)
-                        vol.delete()
-            raise e
-        finally:
-            if temp_key_pair:
-                temp_key_pair.delete()
-        return AzureInstance(self.provider, vm)
-
     def _resolve_launch_options(self, inst_name, subnet=None, zone_id=None,
                                 vm_firewalls=None):
         if subnet:
@@ -852,7 +717,143 @@ class AzureInstanceService(BaseInstanceService):
     def create_launch_config(self):
         return AzureLaunchConfig(self.provider)
 
-    def list(self, limit=None, marker=None):
+    @implement(event_pattern="provider.compute.instances.create",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _create(self, label, image, vm_type, subnet, zone,
+                key_pair=None, vm_firewalls=None, user_data=None,
+                launch_config=None, **kwargs):
+        instance_name = AzureInstance._generate_name_from_label(label,
+                                                                "cb-ins")
+
+        image = (image if isinstance(image, AzureMachineImage) else
+                 self.provider.compute.images.get(image))
+        if not isinstance(image, AzureMachineImage):
+            raise Exception("Provided image %s is not a valid azure image"
+                            % image)
+
+        instance_size = vm_type.id if \
+            isinstance(vm_type, VMType) else vm_type
+
+        if not subnet:
+            # Azure has only a single zone per region; use the current one
+            zone = self.provider.compute.regions.get(
+                self.provider.region_name).zones[0]
+            subnet = self.provider.networking.subnets.get_or_create_default(
+                zone)
+        else:
+            subnet = (self.provider.networking.subnets.get(subnet)
+                      if isinstance(subnet, str) else subnet)
+
+        zone_id = zone.id if isinstance(zone, PlacementZone) else zone
+
+        subnet_id, zone_id, vm_firewall_id = \
+            self._resolve_launch_options(instance_name,
+                                         subnet, zone_id, vm_firewalls)
+
+        storage_profile = self._create_storage_profile(image, launch_config,
+                                                       instance_name, zone_id)
+
+        nic_params = {
+            'location': self.provider.region_name,
+            'ip_configurations': [{
+                'name': instance_name + '_ip_config',
+                'private_ip_allocation_method': 'Dynamic',
+                'subnet': {
+                    'id': subnet_id
+                }
+            }]
+        }
+
+        if vm_firewall_id:
+            nic_params['network_security_group'] = {
+                'id': vm_firewall_id
+            }
+        nic_info = self.provider.azure_client.create_nic(
+            instance_name + '_nic',
+            nic_params
+        )
+        # #! indicates shell script
+        ud = '#cloud-config\n' + user_data \
+            if user_data and not user_data.startswith('#!')\
+            and not user_data.startswith('#cloud-config') else user_data
+
+        # Key_pair is mandatory in azure and it should not be None.
+        temp_key_pair = None
+        if key_pair:
+            key_pair = (key_pair if isinstance(key_pair, AzureKeyPair)
+                        else self.provider.security.key_pairs.get(key_pair))
+        else:
+            # Create a temporary keypair if none is provided to keep Azure
+            # happy, but the private key will be discarded, so it'll be all
+            # but useless. However, this will allow an instance to be launched
+            # without specifying a keypair, so users may still be able to login
+            # if they have a preinstalled keypair/password baked into the image
+            temp_kp_name = "".join(["cb-default-kp-",
+                                   str(uuid.uuid5(uuid.NAMESPACE_OID,
+                                                  instance_name))[-6:]])
+            key_pair = self.provider.security.key_pairs.create(
+                name=temp_kp_name)
+            temp_key_pair = key_pair
+
+        params = {
+            'location': zone_id or self.provider.region_name,
+            'os_profile': {
+                'admin_username': self.provider.vm_default_user_name,
+                'computer_name': instance_name,
+                'linux_configuration': {
+                    "disable_password_authentication": True,
+                    "ssh": {
+                        "public_keys": [{
+                            "path":
+                                "/home/{}/.ssh/authorized_keys".format(
+                                        self.provider.vm_default_user_name),
+                                "key_data": key_pair._key_pair.Key
+                        }]
+                    }
+                }
+            },
+            'hardware_profile': {
+                'vm_size': instance_size
+            },
+            'network_profile': {
+                'network_interfaces': [{
+                    'id': nic_info.id
+                }]
+            },
+            'storage_profile': storage_profile,
+            'tags': {'Label': label}
+        }
+
+        for disk_def in storage_profile.get('data_disks', []):
+            params['tags'] = dict(disk_def.get('tags', {}), **params['tags'])
+
+        if user_data:
+            custom_data = base64.b64encode(bytes(ud, 'utf-8'))
+            params['os_profile']['custom_data'] = str(custom_data, 'utf-8')
+
+        if not temp_key_pair:
+            params['tags'].update(Key_Pair=key_pair.id)
+
+        try:
+            vm = self.provider.azure_client.create_vm(instance_name, params)
+        except Exception as e:
+            # If VM creation fails, attempt to clean up intermediary resources
+            self.provider.azure_client.delete_nic(nic_info.id)
+            for disk_def in storage_profile.get('data_disks', []):
+                if disk_def.get('tags', {}).get('delete_on_terminate'):
+                    disk_id = disk_def.get('managed_disk', {}).get('id')
+                    if disk_id:
+                        vol = self.provider.storage.volumes.get(disk_id)
+                        vol.delete()
+            raise e
+        finally:
+            if temp_key_pair:
+                temp_key_pair.delete()
+        return AzureInstance(self.provider, vm)
+
+    @implement(event_pattern="provider.compute.instances.list",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _list(self, limit=None, marker=None):
         """
         List all instances.
         """
@@ -861,7 +862,9 @@ class AzureInstanceService(BaseInstanceService):
         return ClientPagedResultList(self.provider, instances,
                                      limit=limit, marker=marker)
 
-    def get(self, instance_id):
+    @implement(event_pattern="provider.compute.instances.get",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _get(self, instance_id):
         """
         Returns an instance given its id. Returns None
         if the object does not exist.
@@ -874,7 +877,9 @@ class AzureInstanceService(BaseInstanceService):
             log.exception(cloud_error)
             return None
 
-    def find(self, **kwargs):
+    @implement(event_pattern="provider.compute.instances.find",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _find(self, **kwargs):
         obj_list = self
         filters = ['label']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -888,6 +893,34 @@ class AzureInstanceService(BaseInstanceService):
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
 
+    @implement(event_pattern="provider.compute.instances.delete",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _delete(self, instance_id):
+        """
+        Permanently terminate this instance.
+        After deleting the VM. we are deleting the network interface
+        associated to the instance, and also removing OS disk and data disks
+        where tag with name 'delete_on_terminate' has value True.
+        """
+        ins = self.get(instance_id)
+
+        # Remove IPs first to avoid a network interface conflict
+        for public_ip_id in ins._public_ip_ids:
+            ins.remove_floating_ip(public_ip_id)
+        self.provider.azure_client.deallocate_vm(ins.id)
+        self.provider.azure_client.delete_vm(ins.id)
+        for nic_id in ins._nic_ids:
+            self.provider.azure_client.delete_nic(nic_id)
+        for data_disk in ins._vm.storage_profile.data_disks:
+            if data_disk.managed_disk:
+                if ins._vm.tags.get('delete_on_terminate',
+                                    'False') == 'True':
+                    self.provider.azure_client. \
+                        delete_disk(data_disk.managed_disk.id)
+        if ins._vm.storage_profile.os_disk.managed_disk:
+            self.provider.azure_client. \
+                delete_disk(ins._vm.storage_profile.os_disk.managed_disk.id)
+
 
 class AzureVMTypeService(BaseVMTypeService):
 

+ 0 - 13
cloudbridge/cloud/providers/gce/resources.py

@@ -957,19 +957,6 @@ class GCEInstance(BaseInstance):
                     instance=self.name)
              .execute())
 
-    def delete(self):
-        """
-        Permanently terminate this instance.
-        """
-        name = self.name
-        (self._provider
-         .gce_compute
-         .instances()
-         .delete(project=self._provider.project_name,
-                 zone=self.zone_name,
-                 instance=name)
-         .execute())
-
     def stop(self):
         """
         Stop this instance.

+ 28 - 6
cloudbridge/cloud/providers/gce/services.py

@@ -356,9 +356,11 @@ class GCEInstanceService(BaseInstanceService):
     def __init__(self, provider):
         super(GCEInstanceService, self).__init__(provider)
 
-    def create(self, label, image, vm_type, subnet, zone=None,
-               key_pair=None, vm_firewalls=None, user_data=None,
-               launch_config=None, **kwargs):
+    @implement(event_pattern="provider.compute.instances.create",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _create(self, label, image, vm_type, subnet, zone=None,
+                key_pair=None, vm_firewalls=None, user_data=None,
+                launch_config=None, **kwargs):
         """
         Creates a new virtual machine instance.
         """
@@ -505,7 +507,9 @@ class GCEInstanceService(BaseInstanceService):
         cb_inst = self.get(instance_id)
         return cb_inst
 
-    def get(self, instance_id):
+    @implement(event_pattern="provider.compute.instances.get",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _get(self, instance_id):
         """
         Returns an instance given its name. Returns None
         if the object does not exist.
@@ -516,7 +520,9 @@ class GCEInstanceService(BaseInstanceService):
         instance = self.provider.get_resource('instances', instance_id)
         return GCEInstance(self.provider, instance) if instance else None
 
-    def find(self, label, limit=None, marker=None):
+    @implement(event_pattern="provider.compute.instances.find",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _find(self, label, limit=None, marker=None):
         """
         Searches for instances by instance label.
         :return: a list of Instance objects
@@ -527,7 +533,9 @@ class GCEInstanceService(BaseInstanceService):
             instances = instances[:limit]
         return instances
 
-    def list(self, limit=None, marker=None):
+    @implement(event_pattern="provider.compute.instances.list",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _list(self, limit=None, marker=None):
         """
         List all instances.
         """
@@ -551,6 +559,20 @@ class GCEInstanceService(BaseInstanceService):
                                      response.get('nextPageToken'),
                                      False, data=instances)
 
+    @implement(event_pattern="provider.compute.instances.delete",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _delete(self, instance_id):
+        gce_instance = self.provider.get_resource('instances', instance_id)
+        (self._provider
+         .gce_compute
+         .instances()
+         .delete(project=self.provider.project_name,
+                 zone=self.provider
+                          .parse_url(gce_instance.get('zone'))
+                          .parameters['zone'],
+                 instance=gce_instance.get('name'))
+         .execute())
+
     def create_launch_config(self):
         return GCELaunchConfig(self.provider)
 

+ 0 - 11
cloudbridge/cloud/providers/openstack/resources.py

@@ -366,17 +366,6 @@ class OpenStackInstance(BaseInstance):
         """
         self._os_instance.reboot()
 
-    def delete(self):
-        """
-        Permanently delete this instance.
-        """
-        # delete the port we created when launching
-        # Assumption: it's the first interface in the list
-        iface_list = self._os_instance.interface_list()
-        if iface_list:
-            self._provider.neutron.delete_port(iface_list[0].port_id)
-        self._os_instance.delete()
-
     @property
     def image_id(self):
         """

+ 81 - 61
cloudbridge/cloud/providers/openstack/services.py

@@ -615,12 +615,64 @@ class OpenStackInstanceService(BaseInstanceService):
     def __init__(self, provider):
         super(OpenStackInstanceService, self).__init__(provider)
 
-    def create(self, label, image, vm_type, subnet, zone,
-               key_pair=None, vm_firewalls=None, user_data=None,
-               launch_config=None, **kwargs):
-        """Create a new virtual machine instance."""
-        OpenStackInstance.assert_valid_resource_label(label)
+    def _to_block_device_mapping(self, launch_config):
+        """
+        Extracts block device mapping information
+        from a launch config and constructs a BlockDeviceMappingV2
+        object.
+        """
+        bdm = []
+        for device in launch_config.block_devices:
+            bdm_dict = dict()
+
+            if device.is_volume:
+                bdm_dict['destination_type'] = 'volume'
+
+                if device.is_root:
+                    bdm_dict['device_name'] = '/dev/sda'
+                    bdm_dict['boot_index'] = 0
+
+                if isinstance(device.source, Snapshot):
+                    bdm_dict['source_type'] = 'snapshot'
+                    bdm_dict['uuid'] = device.source.id
+                elif isinstance(device.source, Volume):
+                    bdm_dict['source_type'] = 'volume'
+                    bdm_dict['uuid'] = device.source.id
+                elif isinstance(device.source, MachineImage):
+                    bdm_dict['source_type'] = 'image'
+                    bdm_dict['uuid'] = device.source.id
+                else:
+                    bdm_dict['source_type'] = 'blank'
+
+                if device.delete_on_terminate is not None:
+                    bdm_dict[
+                        'delete_on_termination'] = device.delete_on_terminate
 
+                if device.size:
+                    bdm_dict['volume_size'] = device.size
+            else:
+                bdm_dict['destination_type'] = 'local'
+                bdm_dict['source_type'] = 'blank'
+                bdm_dict['delete_on_termination'] = True
+            bdm.append(bdm_dict)
+        return bdm
+
+    def _has_root_device(self, launch_config):
+        if not launch_config:
+            return False
+        for device in launch_config.block_devices:
+            if device.is_root:
+                return True
+        return False
+
+    def create_launch_config(self):
+        return BaseLaunchConfig(self.provider)
+
+    @implement(event_pattern="provider.compute.instances.create",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _create(self, label, image, vm_type, subnet, zone,
+                key_pair=None, vm_firewalls=None, user_data=None,
+                launch_config=None, **kwargs):
         image_id = image.id if isinstance(image, MachineImage) else image
         vm_size = vm_type.id if \
             isinstance(vm_type, VMType) else \
@@ -698,60 +750,9 @@ class OpenStackInstanceService(BaseInstanceService):
             nics=nics)
         return OpenStackInstance(self.provider, os_instance)
 
-    def _to_block_device_mapping(self, launch_config):
-        """
-        Extracts block device mapping information
-        from a launch config and constructs a BlockDeviceMappingV2
-        object.
-        """
-        bdm = []
-        for device in launch_config.block_devices:
-            bdm_dict = dict()
-
-            if device.is_volume:
-                bdm_dict['destination_type'] = 'volume'
-
-                if device.is_root:
-                    bdm_dict['device_name'] = '/dev/sda'
-                    bdm_dict['boot_index'] = 0
-
-                if isinstance(device.source, Snapshot):
-                    bdm_dict['source_type'] = 'snapshot'
-                    bdm_dict['uuid'] = device.source.id
-                elif isinstance(device.source, Volume):
-                    bdm_dict['source_type'] = 'volume'
-                    bdm_dict['uuid'] = device.source.id
-                elif isinstance(device.source, MachineImage):
-                    bdm_dict['source_type'] = 'image'
-                    bdm_dict['uuid'] = device.source.id
-                else:
-                    bdm_dict['source_type'] = 'blank'
-
-                if device.delete_on_terminate is not None:
-                    bdm_dict[
-                        'delete_on_termination'] = device.delete_on_terminate
-
-                if device.size:
-                    bdm_dict['volume_size'] = device.size
-            else:
-                bdm_dict['destination_type'] = 'local'
-                bdm_dict['source_type'] = 'blank'
-                bdm_dict['delete_on_termination'] = True
-            bdm.append(bdm_dict)
-        return bdm
-
-    def _has_root_device(self, launch_config):
-        if not launch_config:
-            return False
-        for device in launch_config.block_devices:
-            if device.is_root:
-                return True
-        return False
-
-    def create_launch_config(self):
-        return BaseLaunchConfig(self.provider)
-
-    def find(self, **kwargs):
+    @implement(event_pattern="provider.compute.instances.find",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _find(self, **kwargs):
         label = kwargs.pop('label', None)
 
         # All kwargs should have been popped at this time.
@@ -768,7 +769,9 @@ class OpenStackInstanceService(BaseInstanceService):
                 marker=None)]
         return oshelpers.to_server_paged_list(self.provider, cb_insts)
 
-    def list(self, limit=None, marker=None):
+    @implement(event_pattern="provider.compute.instances.list",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _list(self, limit=None, marker=None):
         """
         List all instances.
         """
@@ -779,7 +782,9 @@ class OpenStackInstanceService(BaseInstanceService):
                 marker=marker)]
         return oshelpers.to_server_paged_list(self.provider, cb_insts, limit)
 
-    def get(self, instance_id):
+    @implement(event_pattern="provider.compute.instances.get",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _get(self, instance_id):
         """
         Returns an instance given its id.
         """
@@ -790,6 +795,21 @@ class OpenStackInstanceService(BaseInstanceService):
             log.debug("Instance %s was not found.", instance_id)
             return None
 
+    @implement(event_pattern="provider.compute.instances.delete",
+               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def _delete(self, instance_id):
+        try:
+            os_instance = self.provider.nova.servers.get(instance_id)
+        except NovaNotFound:
+            log.debug("Instance %s was not found.", instance_id)
+            return None
+        # delete the port we created when launching
+        # Assumption: it's the first interface in the list
+        iface_list = os_instance.interface_list()
+        if iface_list:
+            self.provider.neutron.delete_port(iface_list[0].port_id)
+        os_instance.delete()
+
 
 class OpenStackVMTypeService(BaseVMTypeService):