فهرست منبع

Simplified events through dispatch decorator

Nuwan Goonasekera 7 سال پیش
والد
کامیت
eff258d337

+ 24 - 640
cloudbridge/cloud/base/services.py

@@ -4,16 +4,11 @@ Base implementation for services available through a provider
 import logging
 import logging
 
 
 import cloudbridge.cloud.base.helpers as cb_helpers
 import cloudbridge.cloud.base.helpers as cb_helpers
-from cloudbridge.cloud.base.middleware import implement
+from cloudbridge.cloud.base.middleware import dispatch
 from cloudbridge.cloud.base.resources import BaseBucket
 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 BaseNetwork
 from cloudbridge.cloud.base.resources import BaseRouter
 from cloudbridge.cloud.base.resources import BaseRouter
-from cloudbridge.cloud.base.resources import BaseSnapshot
 from cloudbridge.cloud.base.resources import BaseSubnet
 from cloudbridge.cloud.base.resources import BaseSubnet
-from cloudbridge.cloud.base.resources import BaseVMFirewall
-from cloudbridge.cloud.base.resources import BaseVolume
 from cloudbridge.cloud.interfaces.exceptions import \
 from cloudbridge.cloud.interfaces.exceptions import \
     InvalidConfigurationException
     InvalidConfigurationException
 from cloudbridge.cloud.interfaces.exceptions import InvalidParamException
 from cloudbridge.cloud.interfaces.exceptions import InvalidParamException
@@ -57,40 +52,9 @@ class BaseCloudService(CloudService):
     def provider(self):
     def provider(self):
         return self._provider
         return self._provider
 
 
-    def dispatch(self, sender, event, *args, **kwargs):
-        return self._provider.events.dispatch(sender, event, *args, **kwargs)
-
-    def _generate_event_pattern(self, func_name):
-        return ".".join((self._service_event_pattern, func_name))
-
-    def observe_function(self, func_name, priority, callback):
-        event_pattern = self._generate_event_pattern(func_name)
-        self.provider.events.observe(event_pattern, priority, callback)
-
-    def intercept_function(self, func_name, priority, callback):
-        event_pattern = self._generate_event_pattern(func_name)
-        self.provider.events.intercept(event_pattern, priority, callback)
-
-    def implement_function(self, func_name, priority, callback):
-        event_pattern = self._generate_event_pattern(func_name)
-        self.provider.events.implement(event_pattern, priority, callback)
-
-    def dispatch_function(self, sender, func_name, *args, **kwargs):
-        """
-        Emits the event corresponding to the given function name for the
-        current service
-
-        :type sender: CloudService
-        :param sender: The CloudBridge Service object sending the emit signal
-        :type func_name: str
-        :param func_name: The name of the function to be emitted. e.g.: 'get'
-        :type args: CloudService
-
-        :return:  The return value resulting from the handler chain invocations
-        """
-        full_event_name = self._generate_event_pattern(func_name)
-        return self._provider.events.dispatch(sender, full_event_name,
-                                              *args, **kwargs)
+    @property
+    def events(self):
+        return self._provider.events
 
 
 
 
 class BaseSecurityService(SecurityService, BaseCloudService):
 class BaseSecurityService(SecurityService, BaseCloudService):
@@ -106,68 +70,6 @@ class BaseKeyPairService(
         super(BaseKeyPairService, self).__init__(provider)
         super(BaseKeyPairService, self).__init__(provider)
         self._service_event_pattern += ".security.key_pairs"
         self._service_event_pattern += ".security.key_pairs"
 
 
-    def get(self, key_pair_id):
-        """
-        Returns a key_pair given its ID. Returns ``None`` if the key_pair
-        does not exist.
-
-        :type key_pair_id: str
-        :param key_pair_id: The id of the desired key pair.
-
-        :rtype: ``KeyPair``
-        :return:  ``None`` is returned if the key pair does not exist, and
-                  the key pair's provider-specific CloudBridge object is
-                  returned if the key pair is found.
-        """
-        return self.dispatch(self, "provider.security.key_pairs.get",
-                             key_pair_id)
-
-    def find(self, **kwargs):
-        """
-        Returns a list of key pairs filtered by the given keyword arguments.
-        Accepted search arguments are: 'name'
-        """
-        return self.dispatch(self, "provider.security.key_pairs.find",
-                             **kwargs)
-
-    def list(self, limit=None, marker=None):
-        """
-        List all key pairs.
-        """
-        return self.dispatch(self, "provider.security.key_pairs.list",
-                             limit=limit, marker=marker)
-
-    def create(self, name, public_key_material=None):
-        """
-        Create a new key pair.
-
-        :type name: str
-        :param name: The name of the key pair to be created. Note that names
-                     must be unique, and are unchangeable.
-
-        :rtype: ``KeyPair``
-        :return:  The created key pair's provider-specific CloudBridge object.
-        """
-        BaseKeyPair.assert_valid_resource_name(name)
-        return self.dispatch(self, "provider.security.key_pairs.create",
-                             name,  public_key_material=public_key_material)
-
-    def delete(self, key_pair):
-        return self.dispatch(self, "provider.security.key_pairs.delete",
-                             key_pair)
-
-    @implement(event_pattern="provider.security.key_pairs.delete",
-               priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, key_pair_id):
-        """
-        Delete an existing key pair.
-
-        :type key_pair_id: str
-        :param key_pair_id: The ID of the key pair to be deleted.
-        """
-        return self.dispatch(self, "provider.security.key_pairs.delete",
-                             key_pair_id)
-
 
 
 class BaseVMFirewallService(
 class BaseVMFirewallService(
         BasePageableObjectMixin, VMFirewallService, BaseCloudService):
         BasePageableObjectMixin, VMFirewallService, BaseCloudService):
@@ -176,62 +78,9 @@ class BaseVMFirewallService(
         super(BaseVMFirewallService, self).__init__(provider)
         super(BaseVMFirewallService, self).__init__(provider)
         self._service_event_pattern += ".security.vm_firewalls"
         self._service_event_pattern += ".security.vm_firewalls"
 
 
-    def get(self, vm_firewall_id):
-        """
-        Returns a vm_firewall given its ID. Returns ``None`` if the vm_firewall
-        does not exist.
-
-        :type vm_firewall_id: str
-        :param vm_firewall_id: The id of the desired firewall.
-
-        :rtype: ``VMFirewall``
-        :return:  ``None`` is returned if the firewall does not exist, and
-                  the firewall's provider-specific CloudBridge object is
-                  returned if the firewall is found.
-        """
-        return self.dispatch(self, "provider.security.vm_firewalls.get",
-                             vm_firewall_id)
-
+    @dispatch(event="provider.security.vm_firewalls.find",
+              priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
     def find(self, **kwargs):
     def find(self, **kwargs):
-        """
-        Returns a list of firewalls filtered by the given keyword arguments.
-        Accepted search arguments are: 'label'
-        """
-        return self.dispatch(self, "provider.security.vm_firewalls.find",
-                             **kwargs)
-
-    def list(self, limit=None, marker=None):
-        """
-        List all firewalls.
-        """
-        return self.dispatch(self, "provider.security.vm_firewalls.list",
-                             limit=limit, marker=marker)
-
-    def create(self, label, network, description=None):
-        """
-        Create a new firewall.
-
-        :type label: str
-        :param label: The label of the firewall to be created. Note that labels
-                     do not have to be unique, and are changeable.
-
-        :rtype: ``VMFirewall``
-        :return:  The created firewall's provider-specific CloudBridge object.
-        """
-        BaseVMFirewall.assert_valid_resource_label(label)
-        return self.dispatch(self, "provider.security.vm_firewalls.create",
-                             label, network, description)
-
-    def delete(self, vm_firewall):
-        """
-        Delete an existing firewall.
-        """
-        return self.dispatch(self, "provider.security.vm_firewalls.delete",
-                             vm_firewall)
-
-    @implement(event_pattern="provider.security.vm_firewalls.find",
-               priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['label']
         filters = ['label']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -259,63 +108,6 @@ class BaseVolumeService(
         super(BaseVolumeService, self).__init__(provider)
         super(BaseVolumeService, self).__init__(provider)
         self._service_event_pattern += ".storage.volumes"
         self._service_event_pattern += ".storage.volumes"
 
 
-    def get(self, volume_id):
-        """
-        Returns a volume given its ID. Returns ``None`` if the volume
-        does not exist.
-
-        :type volume_id: str
-        :param volume_id: The id of the desired volume.
-
-        :rtype: ``Volume``
-        :return:  ``None`` is returned if the volume does not exist, and
-                  the volume's provider-specific CloudBridge object is
-                  returned if the volume is found.
-        """
-        return self.dispatch(self, "provider.storage.volumes.get",
-                             volume_id)
-
-    def find(self, **kwargs):
-        """
-        Returns a list of volumes filtered by the given keyword arguments.
-        Accepted search arguments are: 'label'
-        """
-        return self.dispatch(self, "provider.storage.volumes.find",
-                             **kwargs)
-
-    def list(self, limit=None, marker=None):
-        """
-        List all volumes.
-        """
-        return self.dispatch(self, "provider.storage.volumes.list",
-                             limit=limit, marker=marker)
-
-    def create(self, label, size, zone, snapshot=None, description=None):
-        """
-        Create a new volume.
-
-        :type label: str
-        :param label: The label of the volume to be created. Note that labels
-                     do not have to be unique, and are changeable.
-        :type size: int
-        :param size: The size (in Gb) of the volume to be created
-        :type zone: ``PlacementZone``
-        :param zone: The availability zone in which to create the volume
-
-        :rtype: ``Volume``
-        :return:  The created volume's provider-specific CloudBridge object.
-        """
-        BaseVolume.assert_valid_resource_label(label)
-        return self.dispatch(self, "provider.storage.volumes.create",
-                             label, size, zone, snapshot, description)
-
-    def delete(self, volume):
-        """
-        Delete an existing volume.
-        """
-        return self.dispatch(self, "provider.storage.volumes.delete",
-                             volume)
-
 
 
 class BaseSnapshotService(
 class BaseSnapshotService(
         BasePageableObjectMixin, SnapshotService, BaseCloudService):
         BasePageableObjectMixin, SnapshotService, BaseCloudService):
@@ -324,61 +116,6 @@ class BaseSnapshotService(
         super(BaseSnapshotService, self).__init__(provider)
         super(BaseSnapshotService, self).__init__(provider)
         self._service_event_pattern += ".storage.snapshots"
         self._service_event_pattern += ".storage.snapshots"
 
 
-    def get(self, snapshot_id):
-        """
-        Returns a snapshot given its ID. Returns ``None`` if the snapshot
-        does not exist.
-
-        :type snapshot_id: str
-        :param snapshot_id: The id of the desired snapshot.
-
-        :rtype: ``Snapshot``
-        :return:  ``None`` is returned if the snapshot does not exist, and
-                  the snapshot's provider-specific CloudBridge object is
-                  returned if the snapshot is found.
-        """
-        return self.dispatch(self, "provider.storage.snapshots.get",
-                             snapshot_id)
-
-    def find(self, **kwargs):
-        """
-        Returns a list of snapshots filtered by the given keyword arguments.
-        Accepted search arguments are: 'label'
-        """
-        return self.dispatch(self, "provider.storage.snapshots.find",
-                             **kwargs)
-
-    def list(self, limit=None, marker=None):
-        """
-        List all snapshots.
-        """
-        return self.dispatch(self, "provider.storage.snapshots.list",
-                             limit=limit, marker=marker)
-
-    def create(self, label, volume, description=None):
-        """
-        Create a new snapshot.
-
-        :type label: str
-        :param label: The label of the snapshot to be created. Note that labels
-                     do not have to be unique, and are changeable.
-        :type volume: ``Volume``
-        :param volume: The volume from which to create this snapshot.
-
-        :rtype: ``Snapshot``
-        :return:  The created snapshot's provider-specific CloudBridge object.
-        """
-        BaseSnapshot.assert_valid_resource_label(label)
-        return self.dispatch(self, "provider.storage.snapshots.create",
-                             label, volume, description)
-
-    def delete(self, snapshot):
-        """
-        Delete an existing snapshot.
-        """
-        return self.dispatch(self, "provider.storage.snapshots.delete",
-                             snapshot)
-
 
 
 class BaseBucketService(
 class BaseBucketService(
         BasePageableObjectMixin, BucketService, BaseCloudService):
         BasePageableObjectMixin, BucketService, BaseCloudService):
@@ -389,9 +126,9 @@ class BaseBucketService(
 
 
     # Generic find will be used for providers where we have not implemented
     # Generic find will be used for providers where we have not implemented
     # provider-specific querying for find method
     # provider-specific querying for find method
-    @implement(event_pattern="provider.storage.buckets.find",
-               priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.storage.buckets.find",
+              priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['name']
         filters = ['name']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -405,57 +142,6 @@ class BaseBucketService(
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
                                      matches if matches else [])
 
 
-    def get(self, bucket_id):
-        """
-        Returns a bucket given its ID. Returns ``None`` if the bucket
-        does not exist.
-
-        :type bucket_id: str
-        :param bucket_id: The id of the desired bucket.
-
-        :rtype: ``Bucket``
-        :return:  ``None`` is returned if the bucket does not exist, and
-                  the bucket's provider-specific CloudBridge object is
-                  returned if the bucket is found.
-        """
-        return self.dispatch(self, "provider.storage.buckets.get", bucket_id)
-
-    def find(self, **kwargs):
-        """
-        Returns a list of buckets filtered by the given keyword arguments.
-        Accepted search arguments are: 'name'
-        """
-        return self.dispatch(self, "provider.storage.buckets.find", **kwargs)
-
-    def list(self, limit=None, marker=None):
-        """
-        List all buckets.
-        """
-        return self.dispatch(self, "provider.storage.buckets.list",
-                             limit=limit, marker=marker)
-
-    def create(self, name, location=None):
-        """
-        Create a new bucket.
-
-        :type name: str
-        :param name: The name of the bucket to be created. Note that names
-                     must be unique, and are unchangeable.
-
-        :rtype: ``Bucket``
-        :return:  The created bucket's provider-specific CloudBridge object.
-        """
-        BaseBucket.assert_valid_resource_name(name)
-        return self.dispatch(self, "provider.storage.buckets.create",
-                             name, location=location)
-
-    def delete(self, bucket):
-        """
-        Delete an existing bucket.
-        """
-        return self.dispatch(self, "provider.storage.buckets.delete",
-                             bucket)
-
 
 
 class BaseBucketObjectService(
 class BaseBucketObjectService(
         BasePageableObjectMixin, BucketObjectService, BaseCloudService):
         BasePageableObjectMixin, BucketObjectService, BaseCloudService):
@@ -513,72 +199,6 @@ class BaseInstanceService(
         super(BaseInstanceService, self).__init__(provider)
         super(BaseInstanceService, self).__init__(provider)
         self._service_event_pattern += ".compute.instances"
         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):
-        """
-        Delete an existing instance.
-        """
-        return self.dispatch(self, "provider.compute.instances.delete",
-                             instance)
-
 
 
 class BaseVMTypeService(
 class BaseVMTypeService(
         BasePageableObjectMixin, VMTypeService, BaseCloudService):
         BasePageableObjectMixin, VMTypeService, BaseCloudService):
@@ -587,51 +207,20 @@ class BaseVMTypeService(
         super(BaseVMTypeService, self).__init__(provider)
         super(BaseVMTypeService, self).__init__(provider)
         self._service_event_pattern += ".compute.vm_types"
         self._service_event_pattern += ".compute.vm_types"
 
 
-    @implement(event_pattern="provider.compute.vm_types.get",
-               priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
-    def _get(self, vm_type_id):
+    @dispatch(event="provider.compute.vm_types.get",
+              priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
+    def get(self, vm_type_id):
         vm_type = (t for t in self if t.id == vm_type_id)
         vm_type = (t for t in self if t.id == vm_type_id)
         return next(vm_type, None)
         return next(vm_type, None)
 
 
-    @implement(event_pattern="provider.compute.vm_types.find",
-               priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.compute.vm_types.find",
+              priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['name']
         filters = ['name']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         return ClientPagedResultList(self._provider, list(matches))
         return ClientPagedResultList(self._provider, list(matches))
 
 
-    def get(self, vm_type_id):
-        """
-        Returns a vm_type given its ID. Returns ``None`` if the vm_type
-        does not exist.
-
-        :type vm_type_id: str
-        :param vm_type_id: The id of the desired VM type.
-
-        :rtype: ``VMType``
-        :return:  ``None`` is returned if the VM type does not exist, and
-                  the VM type's provider-specific CloudBridge object is
-                  returned if the VM type is found.
-        """
-        return self.dispatch(self, "provider.compute.vm_types.get",
-                             vm_type_id)
-
-    def find(self, **kwargs):
-        """
-        Returns a list of VM types filtered by the given keyword arguments.
-        Accepted search arguments are: 'name'
-        """
-        return self.dispatch(self, "provider.compute.vm_types.find",
-                             **kwargs)
-
-    def list(self, limit=None, marker=None):
-        """
-        List all VM types.
-        """
-        return self.dispatch(self, "provider.compute.vm_types.list",
-                             limit=limit, marker=marker)
-
 
 
 class BaseRegionService(
 class BaseRegionService(
         BasePageableObjectMixin, RegionService, BaseCloudService):
         BasePageableObjectMixin, RegionService, BaseCloudService):
@@ -640,45 +229,14 @@ class BaseRegionService(
         super(BaseRegionService, self).__init__(provider)
         super(BaseRegionService, self).__init__(provider)
         self._service_event_pattern += ".compute.regions"
         self._service_event_pattern += ".compute.regions"
 
 
-    @implement(event_pattern="provider.compute.regions.find",
-               priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.compute.regions.find",
+              priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['name']
         filters = ['name']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         return ClientPagedResultList(self._provider, list(matches))
         return ClientPagedResultList(self._provider, list(matches))
 
 
-    def get(self, region_id):
-        """
-        Returns a region given its ID. Returns ``None`` if the region
-        does not exist.
-
-        :type region_id: str
-        :param region_id: The id of the desired region.
-
-        :rtype: ``Region``
-        :return:  ``None`` is returned if the region does not exist, and
-                  the region's provider-specific CloudBridge object is
-                  returned if the region is found.
-        """
-        return self.dispatch(self, "provider.compute.regions.get",
-                             region_id)
-
-    def find(self, **kwargs):
-        """
-        Returns a list of regions filtered by the given keyword arguments.
-        Accepted search arguments are: 'name'
-        """
-        return self.dispatch(self, "provider.compute.regions.find",
-                             **kwargs)
-
-    def list(self, limit=None, marker=None):
-        """
-        List all regions.
-        """
-        return self.dispatch(self, "provider.compute.regions.list",
-                             limit=limit, marker=marker)
-
 
 
 class BaseNetworkingService(NetworkingService, BaseCloudService):
 class BaseNetworkingService(NetworkingService, BaseCloudService):
 
 
@@ -710,9 +268,9 @@ class BaseNetworkService(
             return self.provider.networking.networks.create(
             return self.provider.networking.networks.create(
                 BaseNetwork.CB_DEFAULT_NETWORK_LABEL, '10.0.0.0/16')
                 BaseNetwork.CB_DEFAULT_NETWORK_LABEL, '10.0.0.0/16')
 
 
-    @implement(event_pattern="provider.networking.networks.find",
-               priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.networking.networks.find",
+              priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['label']
         filters = ['label']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -726,62 +284,6 @@ class BaseNetworkService(
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
                                      matches if matches else [])
 
 
-    def get(self, network_id):
-        """
-        Returns a network given its ID. Returns ``None`` if the network
-        does not exist.
-
-        :type network_id: str
-        :param network_id: The id of the desired network.
-
-        :rtype: ``network``
-        :return:  ``None`` is returned if the network does not exist, and
-                  the network's provider-specific CloudBridge object is
-                  returned if the network is found.
-        """
-        return self.dispatch(self, "provider.networking.networks.get",
-                             network_id)
-
-    def find(self, **kwargs):
-        """
-        Returns a list of networks filtered by the given keyword arguments.
-        Accepted search arguments are: 'label'
-        """
-        return self.dispatch(self, "provider.networking.networks.find",
-                             **kwargs)
-
-    def list(self, limit=None, marker=None):
-        """
-        List all networks.
-        """
-        return self.dispatch(self, "provider.networking.networks.list",
-                             limit=limit, marker=marker)
-
-    def create(self, label, cidr_block):
-        """
-        Create a new network.
-
-        :type label: str
-        :param label: The label of the network to be created. Note that labels
-                      do not have to be unique and can be changed.
-        :type cidr_block: str
-        :param cidr_block: A string representing a 'Classless Inter-Domain
-                           Routing' notation
-
-        :rtype: ``Network``
-        :return:  The created network's provider-specific CloudBridge object.
-        """
-        BaseNetwork.assert_valid_resource_label(label)
-        return self.dispatch(self, "provider.networking.networks.create",
-                             label, cidr_block)
-
-    def delete(self, network):
-        """
-        Delete an existing network.
-        """
-        return self.dispatch(self, "provider.networking.networks.delete",
-                             network)
-
 
 
 class BaseSubnetService(
 class BaseSubnetService(
         BasePageableObjectMixin, SubnetService, BaseCloudService):
         BasePageableObjectMixin, SubnetService, BaseCloudService):
@@ -790,9 +292,9 @@ class BaseSubnetService(
         super(BaseSubnetService, self).__init__(provider)
         super(BaseSubnetService, self).__init__(provider)
         self._service_event_pattern += ".networking.subnets"
         self._service_event_pattern += ".networking.subnets"
 
 
-    @implement(event_pattern="provider.networking.subnets.find",
-               priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
-    def _find(self, network=None, **kwargs):
+    @dispatch(event="provider.networking.subnets.find",
+              priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
+    def find(self, network=None, **kwargs):
         if not network:
         if not network:
             obj_list = self
             obj_list = self
         else:
         else:
@@ -813,69 +315,6 @@ class BaseSubnetService(
                              BaseSubnet.CB_DEFAULT_SUBNET_IPV4RANGE, zone)
                              BaseSubnet.CB_DEFAULT_SUBNET_IPV4RANGE, zone)
         return subnet
         return subnet
 
 
-    def get(self, subnet_id):
-        """
-        Returns a subnet given its ID. Returns ``None`` if the subnet
-        does not exist.
-
-        :type subnet_id: str
-        :param subnet_id: The id of the desired subnet.
-
-        :rtype: ``Subnet``
-        :return:  ``None`` is returned if the subnet does not exist, and
-                  the subnet's provider-specific CloudBridge object is
-                  returned if the subnet is found.
-        """
-        return self.dispatch(self, "provider.networking.subnets.get",
-                             subnet_id)
-
-    def find(self, network=None, **kwargs):
-        """
-        Returns a list of subnets filtered by the given keyword arguments.
-        Accepted search arguments are: 'label'
-        """
-        return self.dispatch(self, "provider.networking.subnets.find",
-                             network=network, **kwargs)
-
-    def list(self, network=None, limit=None, marker=None):
-        """
-        List all subnets.
-        """
-        return self.dispatch(self, "provider.networking.subnets.list",
-                             network=network, limit=limit, marker=marker)
-
-    def create(self, label, network, cidr_block, zone):
-        """
-        Create a new subnet.
-
-        :type label: str
-        :param label: The label of the subnet to be created. Note that labels
-                      do not have to be unique and can be changed.
-        :type network: ``Network``
-        :param network: The network in which the subnet should be created
-        :type cidr_block: str
-        :param cidr_block: A string representing a 'Classless Inter-Domain
-                           Routing' notation
-        :type cidr_block: str
-        :param cidr_block: A string representing a 'Classless Inter-Domain
-                           Routing' notation
-        :type zone: ``PlacementZone``
-        :param zone: The availability zone in which to create the subnet
-
-        :rtype: ``Subnet``
-        :return:  The created subnet's provider-specific CloudBridge object.
-        """
-        BaseSubnet.assert_valid_resource_label(label)
-        return self.dispatch(self, "provider.networking.subnets.create",
-                             label, network, cidr_block, zone)
-
-    def delete(self, subnet):
-        """
-        Delete an existing subnet.
-        """
-        return self.dispatch(self, "provider.networking.subnets.delete",
-                             subnet)
-
 
 
 class BaseRouterService(
 class BaseRouterService(
         BasePageableObjectMixin, RouterService, BaseCloudService):
         BasePageableObjectMixin, RouterService, BaseCloudService):
@@ -894,58 +333,3 @@ class BaseRouterService(
         else:
         else:
             return self.provider.networking.routers.create(
             return self.provider.networking.routers.create(
                 network=net_id, label=BaseRouter.CB_DEFAULT_ROUTER_LABEL)
                 network=net_id, label=BaseRouter.CB_DEFAULT_ROUTER_LABEL)
-
-    def get(self, router_id):
-        """
-        Returns a router given its ID. Returns ``None`` if the router
-        does not exist.
-
-        :type router_id: str
-        :param router_id: The id of the desired router.
-
-        :rtype: ``Router``
-        :return:  ``None`` is returned if the router does not exist, and
-                  the router's provider-specific CloudBridge object is
-                  returned if the router is found.
-        """
-        return self.dispatch(self, "provider.networking.routers.get",
-                             router_id)
-
-    def find(self, **kwargs):
-        """
-        Returns a list of routers filtered by the given keyword arguments.
-        Accepted search arguments are: 'label'
-        """
-        return self.dispatch(self, "provider.networking.routers.find",
-                             **kwargs)
-
-    def list(self, limit=None, marker=None):
-        """
-        List all routers.
-        """
-        return self.dispatch(self, "provider.networking.routers.list",
-                             limit=limit, marker=marker)
-
-    def create(self, label, network):
-        """
-        Create a new router.
-
-        :type label: str
-        :param label: The label of the router to be created. Note that labels
-                      do not have to be unique and can be changed.
-        :type network: ``Network``
-        :param network: The network in which the router should be created
-
-        :rtype: ``Router``
-        :return:  The created router's provider-specific CloudBridge object.
-        """
-        BaseRouter.assert_valid_resource_label(label)
-        return self.dispatch(self, "provider.networking.routers.create",
-                             label, network)
-
-    def delete(self, router):
-        """
-        Delete an existing router.
-        """
-        return self.dispatch(self, "provider.networking.routers.delete",
-                             router)

+ 146 - 144
cloudbridge/cloud/providers/aws/services.py

@@ -10,7 +10,7 @@ import cachetools
 import requests
 import requests
 
 
 import cloudbridge.cloud.base.helpers as cb_helpers
 import cloudbridge.cloud.base.helpers as cb_helpers
-from cloudbridge.cloud.base.middleware import implement
+from cloudbridge.cloud.base.middleware import dispatch
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketObjectService
 from cloudbridge.cloud.base.services import BaseBucketObjectService
 from cloudbridge.cloud.base.services import BaseBucketService
 from cloudbridge.cloud.base.services import BaseBucketService
@@ -89,20 +89,20 @@ class AWSKeyPairService(BaseKeyPairService):
                                   cb_resource=AWSKeyPair,
                                   cb_resource=AWSKeyPair,
                                   boto_collection_name='key_pairs')
                                   boto_collection_name='key_pairs')
 
 
-    @implement(event_pattern="provider.security.key_pairs.get",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _get(self, key_pair_id):
+    @dispatch(event="provider.security.key_pairs.get",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def get(self, key_pair_id):
         log.debug("Getting Key Pair Service %s", key_pair_id)
         log.debug("Getting Key Pair Service %s", key_pair_id)
         return self.svc.get(key_pair_id)
         return self.svc.get(key_pair_id)
 
 
-    @implement(event_pattern="provider.security.key_pairs.list",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.security.key_pairs.list",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         return self.svc.list(limit=limit, marker=marker)
         return self.svc.list(limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.security.key_pairs.find",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.security.key_pairs.find",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         name = kwargs.pop('name', None)
         name = kwargs.pop('name', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -114,9 +114,10 @@ class AWSKeyPairService(BaseKeyPairService):
         log.debug("Searching for Key Pair %s", name)
         log.debug("Searching for Key Pair %s", name)
         return self.svc.find(filter_name='key-name', filter_value=name)
         return self.svc.find(filter_name='key-name', filter_value=name)
 
 
-    @implement(event_pattern="provider.security.key_pairs.create",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _create(self, name, public_key_material=None):
+    @dispatch(event="provider.security.key_pairs.create",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def create(self, name, public_key_material=None):
+        AWSKeyPair.assert_valid_resource_name(name)
         private_key = None
         private_key = None
         if not public_key_material:
         if not public_key_material:
             public_key_material, private_key = cb_helpers.generate_key_pair()
             public_key_material, private_key = cb_helpers.generate_key_pair()
@@ -132,9 +133,9 @@ class AWSKeyPairService(BaseKeyPairService):
             else:
             else:
                 raise e
                 raise e
 
 
-    @implement(event_pattern="provider.security.key_pairs.delete",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, kp):
+    @dispatch(event="provider.security.key_pairs.delete",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def delete(self, kp):
         key_pair = kp if isinstance(kp, AWSKeyPair) else self.get(kp)
         key_pair = kp if isinstance(kp, AWSKeyPair) else self.get(kp)
         if key_pair:
         if key_pair:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -149,21 +150,21 @@ class AWSVMFirewallService(BaseVMFirewallService):
                                   cb_resource=AWSVMFirewall,
                                   cb_resource=AWSVMFirewall,
                                   boto_collection_name='security_groups')
                                   boto_collection_name='security_groups')
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.get",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _get(self, vm_firewall_id):
+    @dispatch(event="provider.security.vm_firewalls.get",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def get(self, vm_firewall_id):
         log.debug("Getting Firewall Service with the id: %s", vm_firewall_id)
         log.debug("Getting Firewall Service with the id: %s", vm_firewall_id)
         return self.svc.get(vm_firewall_id)
         return self.svc.get(vm_firewall_id)
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.list",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.security.vm_firewalls.list",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         return self.svc.list(limit=limit, marker=marker)
         return self.svc.list(limit=limit, marker=marker)
 
 
     @cb_helpers.deprecated_alias(network_id='network')
     @cb_helpers.deprecated_alias(network_id='network')
-    @implement(event_pattern="provider.security.vm_firewalls.create",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network, description=None):
+    @dispatch(event="provider.security.vm_firewalls.create",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network, description=None):
         name = AWSVMFirewall._generate_name_from_label(label, 'cb-fw')
         name = AWSVMFirewall._generate_name_from_label(label, 'cb-fw')
         network_id = network.id if isinstance(network, Network) else network
         network_id = network.id if isinstance(network, Network) else network
         obj = self.svc.create('create_security_group', GroupName=name,
         obj = self.svc.create('create_security_group', GroupName=name,
@@ -172,9 +173,9 @@ class AWSVMFirewallService(BaseVMFirewallService):
         obj.label = label
         obj.label = label
         return obj
         return obj
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.find",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.security.vm_firewalls.find",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         # Filter by name or label
         # Filter by name or label
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
         log.debug("Searching for Firewall Service %s", label)
         log.debug("Searching for Firewall Service %s", label)
@@ -186,9 +187,9 @@ class AWSVMFirewallService(BaseVMFirewallService):
         return self.svc.find(filter_name='tag:Name',
         return self.svc.find(filter_name='tag:Name',
                              filter_value=label)
                              filter_value=label)
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.delete",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, vmf):
+    @dispatch(event="provider.security.vm_firewalls.delete",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def delete(self, vmf):
         firewall = vmf if isinstance(vmf, AWSVMFirewall) else self.get(vmf)
         firewall = vmf if isinstance(vmf, AWSVMFirewall) else self.get(vmf)
         if firewall:
         if firewall:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -231,14 +232,14 @@ class AWSVolumeService(BaseVolumeService):
                                   cb_resource=AWSVolume,
                                   cb_resource=AWSVolume,
                                   boto_collection_name='volumes')
                                   boto_collection_name='volumes')
 
 
-    @implement(event_pattern="provider.storage.volumes.get",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _get(self, volume_id):
+    @dispatch(event="provider.storage.volumes.get",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def get(self, volume_id):
         return self.svc.get(volume_id)
         return self.svc.get(volume_id)
 
 
-    @implement(event_pattern="provider.storage.volumes.find",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.storage.volumes.find",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -250,14 +251,14 @@ class AWSVolumeService(BaseVolumeService):
         log.debug("Searching for AWS Volume Service %s", label)
         log.debug("Searching for AWS Volume Service %s", label)
         return self.svc.find(filter_name='tag:Name', filter_value=label)
         return self.svc.find(filter_name='tag:Name', filter_value=label)
 
 
-    @implement(event_pattern="provider.storage.volumes.list",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.storage.volumes.list",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         return self.svc.list(limit=limit, marker=marker)
         return self.svc.list(limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.storage.volumes.create",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, size, zone, snapshot=None, description=None):
+    @dispatch(event="provider.storage.volumes.create",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, size, zone, snapshot=None, description=None):
         zone_id = zone.id if isinstance(zone, PlacementZone) else zone
         zone_id = zone.id if isinstance(zone, PlacementZone) else zone
         snapshot_id = snapshot.id if isinstance(
         snapshot_id = snapshot.id if isinstance(
             snapshot, AWSSnapshot) and snapshot else snapshot
             snapshot, AWSSnapshot) and snapshot else snapshot
@@ -272,9 +273,9 @@ class AWSVolumeService(BaseVolumeService):
             cb_vol.description = description
             cb_vol.description = description
         return cb_vol
         return cb_vol
 
 
-    @implement(event_pattern="provider.storage.volumes.delete",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, vol):
+    @dispatch(event="provider.storage.volumes.delete",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def delete(self, vol):
         volume = vol if isinstance(vol, AWSVolume) else self.get(vol)
         volume = vol if isinstance(vol, AWSVolume) else self.get(vol)
         if volume:
         if volume:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -289,14 +290,14 @@ class AWSSnapshotService(BaseSnapshotService):
                                   cb_resource=AWSSnapshot,
                                   cb_resource=AWSSnapshot,
                                   boto_collection_name='snapshots')
                                   boto_collection_name='snapshots')
 
 
-    @implement(event_pattern="provider.storage.snapshots.get",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _get(self, snapshot_id):
+    @dispatch(event="provider.storage.snapshots.get",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def get(self, snapshot_id):
         return self.svc.get(snapshot_id)
         return self.svc.get(snapshot_id)
 
 
-    @implement(event_pattern="provider.storage.snapshots.find",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.storage.snapshots.find",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         # Filter by description or label
         # Filter by description or label
         label = kwargs.get('label', None)
         label = kwargs.get('label', None)
 
 
@@ -311,15 +312,15 @@ class AWSSnapshotService(BaseSnapshotService):
         filters = ['label']
         filters = ['label']
         return cb_helpers.generic_find(filters, kwargs, obj_list)
         return cb_helpers.generic_find(filters, kwargs, obj_list)
 
 
-    @implement(event_pattern="provider.storage.snapshots.list",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.storage.snapshots.list",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         return self.svc.list(limit=limit, marker=marker,
         return self.svc.list(limit=limit, marker=marker,
                              OwnerIds=['self'])
                              OwnerIds=['self'])
 
 
-    @implement(event_pattern="provider.storage.snapshots.create",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, volume, description=None):
+    @dispatch(event="provider.storage.snapshots.create",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, volume, description=None):
         volume_id = volume.id if isinstance(volume, AWSVolume) else volume
         volume_id = volume.id if isinstance(volume, AWSVolume) else volume
 
 
         cb_snap = self.svc.create('create_snapshot', VolumeId=volume_id)
         cb_snap = self.svc.create('create_snapshot', VolumeId=volume_id)
@@ -330,9 +331,9 @@ class AWSSnapshotService(BaseSnapshotService):
             cb_snap.description = description
             cb_snap.description = description
         return cb_snap
         return cb_snap
 
 
-    @implement(event_pattern="provider.storage.snapshots.delete",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, snap):
+    @dispatch(event="provider.storage.snapshots.delete",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def delete(self, snap):
         snapshot = snap if isinstance(snap, AWSSnapshot) else self.get(snap)
         snapshot = snap if isinstance(snap, AWSSnapshot) else self.get(snap)
         if snapshot:
         if snapshot:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -347,9 +348,9 @@ class AWSBucketService(BaseBucketService):
                                  cb_resource=AWSBucket,
                                  cb_resource=AWSBucket,
                                  boto_collection_name='buckets')
                                  boto_collection_name='buckets')
 
 
-    @implement(event_pattern="provider.storage.buckets.get",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _get(self, bucket_id):
+    @dispatch(event="provider.storage.buckets.get",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def get(self, bucket_id):
         """
         """
         Returns a bucket given its ID. Returns ``None`` if the bucket
         Returns a bucket given its ID. Returns ``None`` if the bucket
         does not exist.
         does not exist.
@@ -377,14 +378,14 @@ class AWSBucketService(BaseBucketService):
         # For all other responses, it's assumed that the bucket does not exist.
         # For all other responses, it's assumed that the bucket does not exist.
         return None
         return None
 
 
-    @implement(event_pattern="provider.storage.buckets.list",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit, marker):
+    @dispatch(event="provider.storage.buckets.list",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         return self.svc.list(limit=limit, marker=marker)
         return self.svc.list(limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.storage.buckets.create",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _create(self, name, location):
+    @dispatch(event="provider.storage.buckets.create",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def create(self, name, location=None):
         AWSBucket.assert_valid_resource_name(name)
         AWSBucket.assert_valid_resource_name(name)
         location = location or self.provider.region_name
         location = location or self.provider.region_name
         # Due to an API issue in S3, specifying us-east-1 as a
         # Due to an API issue in S3, specifying us-east-1 as a
@@ -417,9 +418,9 @@ class AWSBucketService(BaseBucketService):
                 else:
                 else:
                     raise
                     raise
 
 
-    @implement(event_pattern="provider.storage.buckets.delete",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, bucket):
+    @dispatch(event="provider.storage.buckets.delete",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def delete(self, bucket):
         b = bucket if isinstance(bucket, AWSBucket) else self.get(bucket)
         b = bucket if isinstance(bucket, AWSBucket) else self.get(bucket)
         if b:
         if b:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -632,11 +633,11 @@ class AWSInstanceService(BaseInstanceService):
     def create_launch_config(self):
     def create_launch_config(self):
         return AWSLaunchConfig(self.provider)
         return AWSLaunchConfig(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):
+    @dispatch(event="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
         image_id = image.id if isinstance(image, MachineImage) else image
         vm_size = vm_type.id if \
         vm_size = vm_type.id if \
@@ -678,14 +679,14 @@ class AWSInstanceService(BaseInstanceService):
         raise ValueError(
         raise ValueError(
             'Expected a single object response, got a list: %s' % inst)
             '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):
+    @dispatch(event="provider.compute.instances.get",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def get(self, instance_id):
         return self.svc.get(instance_id)
         return self.svc.get(instance_id)
 
 
-    @implement(event_pattern="provider.compute.instances.find",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.compute.instances.find",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -696,14 +697,14 @@ class AWSInstanceService(BaseInstanceService):
 
 
         return self.svc.find(filter_name='tag:Name', filter_value=label)
         return self.svc.find(filter_name='tag:Name', filter_value=label)
 
 
-    @implement(event_pattern="provider.compute.instances.list",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.instances.list",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         return self.svc.list(limit=limit, marker=marker)
         return self.svc.list(limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.compute.instances.delete",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, inst):
+    @dispatch(event="provider.compute.instances.delete",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def delete(self, inst):
         aws_inst = inst if isinstance(inst, AWSInstance) else self.get(inst)
         aws_inst = inst if isinstance(inst, AWSInstance) else self.get(inst)
         if aws_inst:
         if aws_inst:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -738,9 +739,9 @@ class AWSVMTypeService(BaseVMTypeService):
         return [vm_type for vm_type in vm_types_list
         return [vm_type for vm_type in vm_types_list
                 if vm_type.get('pricing', {}).get(self.provider.region_name)]
                 if vm_type.get('pricing', {}).get(self.provider.region_name)]
 
 
-    @implement(event_pattern="provider.compute.vm_types.list",
-               priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.vm_types.list",
+              priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         vm_types = [AWSVMType(self.provider, vm_type)
         vm_types = [AWSVMType(self.provider, vm_type)
                     for vm_type in self.instance_data]
                     for vm_type in self.instance_data]
         return ClientPagedResultList(self.provider, vm_types,
         return ClientPagedResultList(self.provider, vm_types,
@@ -752,9 +753,9 @@ class AWSRegionService(BaseRegionService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(AWSRegionService, self).__init__(provider)
         super(AWSRegionService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.compute.regions.get",
-               priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
-    def _get(self, region_id):
+    @dispatch(event="provider.compute.regions.get",
+              priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
+    def get(self, region_id):
         log.debug("Getting AWS Region Service with the id: %s",
         log.debug("Getting AWS Region Service with the id: %s",
                   region_id)
                   region_id)
         region = [r for r in self if r.id == region_id]
         region = [r for r in self if r.id == region_id]
@@ -763,9 +764,9 @@ class AWSRegionService(BaseRegionService):
         else:
         else:
             return None
             return None
 
 
-    @implement(event_pattern="provider.compute.regions.list",
-               priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.regions.list",
+              priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         regions = [
         regions = [
             AWSRegion(self.provider, region) for region in
             AWSRegion(self.provider, region) for region in
             self.provider.ec2_conn.meta.client.describe_regions()
             self.provider.ec2_conn.meta.client.describe_regions()
@@ -807,19 +808,19 @@ class AWSNetworkService(BaseNetworkService):
                                   cb_resource=AWSNetwork,
                                   cb_resource=AWSNetwork,
                                   boto_collection_name='vpcs')
                                   boto_collection_name='vpcs')
 
 
-    @implement(event_pattern="provider.networking.networks.get",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _get(self, network_id):
+    @dispatch(event="provider.networking.networks.get",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def get(self, network_id):
         return self.svc.get(network_id)
         return self.svc.get(network_id)
 
 
-    @implement(event_pattern="provider.networking.networks.list",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.networking.networks.list",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         return self.svc.list(limit=limit, marker=marker)
         return self.svc.list(limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.networks.find",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.networking.networks.find",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -831,9 +832,9 @@ class AWSNetworkService(BaseNetworkService):
         log.debug("Searching for AWS Network Service %s", label)
         log.debug("Searching for AWS Network Service %s", label)
         return self.svc.find(filter_name='tag:Name', filter_value=label)
         return self.svc.find(filter_name='tag:Name', filter_value=label)
 
 
-    @implement(event_pattern="provider.networking.networks.create",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, cidr_block):
+    @dispatch(event="provider.networking.networks.create",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, cidr_block):
         AWSNetwork.assert_valid_resource_label(label)
         AWSNetwork.assert_valid_resource_label(label)
 
 
         cb_net = self.svc.create('create_vpc', CidrBlock=cidr_block)
         cb_net = self.svc.create('create_vpc', CidrBlock=cidr_block)
@@ -843,9 +844,9 @@ class AWSNetworkService(BaseNetworkService):
             cb_net.label = label
             cb_net.label = label
         return cb_net
         return cb_net
 
 
-    @implement(event_pattern="provider.networking.networks.delete",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, net):
+    @dispatch(event="provider.networking.networks.delete",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def delete(self, net):
         network = net if isinstance(net, AWSNetwork) else self.get(net)
         network = net if isinstance(net, AWSNetwork) else self.get(net)
         if network:
         if network:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -879,14 +880,14 @@ class AWSSubnetService(BaseSubnetService):
                                   cb_resource=AWSSubnet,
                                   cb_resource=AWSSubnet,
                                   boto_collection_name='subnets')
                                   boto_collection_name='subnets')
 
 
-    @implement(event_pattern="provider.networking.subnets.get",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _get(self, subnet_id):
+    @dispatch(event="provider.networking.subnets.get",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def get(self, subnet_id):
         return self.svc.get(subnet_id)
         return self.svc.get(subnet_id)
 
 
-    @implement(event_pattern="provider.networking.subnets.list",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _list(self, network=None, limit=None, marker=None):
+    @dispatch(event="provider.networking.subnets.list",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def list(self, network=None, limit=None, marker=None):
         network_id = network.id if isinstance(network, AWSNetwork) else network
         network_id = network.id if isinstance(network, AWSNetwork) else network
         if network_id:
         if network_id:
             return self.svc.find(
             return self.svc.find(
@@ -895,9 +896,9 @@ class AWSSubnetService(BaseSubnetService):
         else:
         else:
             return self.svc.list(limit=limit, marker=marker)
             return self.svc.list(limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.subnets.find",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _find(self, network=None, **kwargs):
+    @dispatch(event="provider.networking.subnets.find",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def find(self, network=None, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -909,9 +910,10 @@ class AWSSubnetService(BaseSubnetService):
         log.debug("Searching for AWS Subnet Service %s", label)
         log.debug("Searching for AWS Subnet Service %s", label)
         return self.svc.find(filter_name='tag:Name', filter_value=label)
         return self.svc.find(filter_name='tag:Name', filter_value=label)
 
 
-    @implement(event_pattern="provider.networking.subnets.create",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network, cidr_block, zone):
+    @dispatch(event="provider.networking.subnets.create",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network, cidr_block, zone):
+        AWSSubnet.assert_valid_resource_label(label)
         zone_name = zone.name if isinstance(
         zone_name = zone.name if isinstance(
             zone, AWSPlacementZone) else zone
             zone, AWSPlacementZone) else zone
 
 
@@ -925,9 +927,9 @@ class AWSSubnetService(BaseSubnetService):
             subnet.label = label
             subnet.label = label
         return subnet
         return subnet
 
 
-    @implement(event_pattern="provider.networking.subnets.delete",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, subnet):
+    @dispatch(event="provider.networking.subnets.delete",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def delete(self, subnet):
         sn = subnet if isinstance(subnet, AWSSubnet) else self.get(subnet)
         sn = subnet if isinstance(subnet, AWSSubnet) else self.get(subnet)
         if sn:
         if sn:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -1045,14 +1047,14 @@ class AWSRouterService(BaseRouterService):
                                   cb_resource=AWSRouter,
                                   cb_resource=AWSRouter,
                                   boto_collection_name='route_tables')
                                   boto_collection_name='route_tables')
 
 
-    @implement(event_pattern="provider.networking.routers.get",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _get(self, router_id):
+    @dispatch(event="provider.networking.routers.get",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def get(self, router_id):
         return self.svc.get(router_id)
         return self.svc.get(router_id)
 
 
-    @implement(event_pattern="provider.networking.routers.find",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.networking.routers.find",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -1064,14 +1066,14 @@ class AWSRouterService(BaseRouterService):
         log.debug("Searching for AWS Router Service %s", label)
         log.debug("Searching for AWS Router Service %s", label)
         return self.svc.find(filter_name='tag:Name', filter_value=label)
         return self.svc.find(filter_name='tag:Name', filter_value=label)
 
 
-    @implement(event_pattern="provider.networking.routers.list",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.networking.routers.list",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         return self.svc.list(limit=limit, marker=marker)
         return self.svc.list(limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.routers.create",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network):
+    @dispatch(event="provider.networking.routers.create",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network):
         network_id = network.id if isinstance(network, AWSNetwork) else network
         network_id = network.id if isinstance(network, AWSNetwork) else network
 
 
         cb_router = self.svc.create('create_route_table', VpcId=network_id)
         cb_router = self.svc.create('create_route_table', VpcId=network_id)
@@ -1079,9 +1081,9 @@ class AWSRouterService(BaseRouterService):
             cb_router.label = label
             cb_router.label = label
         return cb_router
         return cb_router
 
 
-    @implement(event_pattern="provider.networking.routers.delete",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, router):
+    @dispatch(event="provider.networking.routers.delete",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def delete(self, router):
         r = router if isinstance(router, AWSRouter) else self.get(router)
         r = router if isinstance(router, AWSRouter) else self.get(router)
         if r:
         if r:
             # pylint:disable=protected-access
             # pylint:disable=protected-access

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

@@ -8,7 +8,7 @@ from azure.mgmt.compute.models import DiskCreateOption
 from msrestazure.azure_exceptions import CloudError
 from msrestazure.azure_exceptions import CloudError
 
 
 import cloudbridge.cloud.base.helpers as cb_helpers
 import cloudbridge.cloud.base.helpers as cb_helpers
-from cloudbridge.cloud.base.middleware import implement
+from cloudbridge.cloud.base.middleware import dispatch
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.resources import ServerPagedResultList
 from cloudbridge.cloud.base.resources import ServerPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketObjectService
 from cloudbridge.cloud.base.services import BaseBucketObjectService
@@ -78,9 +78,9 @@ class AzureVMFirewallService(BaseVMFirewallService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(AzureVMFirewallService, self).__init__(provider)
         super(AzureVMFirewallService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.get",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _get(self, vm_firewall_id):
+    @dispatch(event="provider.security.vm_firewalls.get",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def get(self, vm_firewall_id):
         try:
         try:
             fws = self.provider.azure_client.get_vm_firewall(vm_firewall_id)
             fws = self.provider.azure_client.get_vm_firewall(vm_firewall_id)
             return AzureVMFirewall(self.provider, fws)
             return AzureVMFirewall(self.provider, fws)
@@ -89,17 +89,17 @@ class AzureVMFirewallService(BaseVMFirewallService):
             log.exception(cloud_error)
             log.exception(cloud_error)
             return None
             return None
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.list",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.security.vm_firewalls.list",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         fws = [AzureVMFirewall(self.provider, fw)
         fws = [AzureVMFirewall(self.provider, fw)
                for fw in self.provider.azure_client.list_vm_firewall()]
                for fw in self.provider.azure_client.list_vm_firewall()]
         return ClientPagedResultList(self.provider, fws, limit, marker)
         return ClientPagedResultList(self.provider, fws, limit, marker)
 
 
     @cb_helpers.deprecated_alias(network_id='network')
     @cb_helpers.deprecated_alias(network_id='network')
-    @implement(event_pattern="provider.security.vm_firewalls.create",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network, description=None):
+    @dispatch(event="provider.security.vm_firewalls.create",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network, description=None):
         name = AzureVMFirewall._generate_name_from_label(label, "cb-fw")
         name = AzureVMFirewall._generate_name_from_label(label, "cb-fw")
         net = network.id if isinstance(network, Network) else network
         net = network.id if isinstance(network, Network) else network
         parameters = {"location": self.provider.region_name,
         parameters = {"location": self.provider.region_name,
@@ -140,9 +140,9 @@ class AzureVMFirewallService(BaseVMFirewallService):
         cb_fw = AzureVMFirewall(self.provider, fw)
         cb_fw = AzureVMFirewall(self.provider, fw)
         return cb_fw
         return cb_fw
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.delete",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, vmf):
+    @dispatch(event="provider.security.vm_firewalls.delete",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def delete(self, vmf):
         fw_id = vmf.id if isinstance(vmf, AzureVMFirewall) else vmf
         fw_id = vmf.id if isinstance(vmf, AzureVMFirewall) else vmf
         self.provider.azure_client.delete_vm_firewall(fw_id)
         self.provider.azure_client.delete_vm_firewall(fw_id)
 
 
@@ -153,9 +153,9 @@ class AzureKeyPairService(BaseKeyPairService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(AzureKeyPairService, self).__init__(provider)
         super(AzureKeyPairService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.security.key_pairs.get",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _get(self, key_pair_id):
+    @dispatch(event="provider.security.key_pairs.get",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def get(self, key_pair_id):
         try:
         try:
             key_pair = self.provider.azure_client.\
             key_pair = self.provider.azure_client.\
                 get_public_key(key_pair_id)
                 get_public_key(key_pair_id)
@@ -168,9 +168,9 @@ class AzureKeyPairService(BaseKeyPairService):
             log.debug(error)
             log.debug(error)
             return None
             return None
 
 
-    @implement(event_pattern="provider.security.key_pairs.list",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.security.key_pairs.list",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         key_pairs, resume_marker = self.provider.azure_client.list_public_keys(
         key_pairs, resume_marker = self.provider.azure_client.list_public_keys(
             AzureKeyPairService.PARTITION_KEY, marker=marker,
             AzureKeyPairService.PARTITION_KEY, marker=marker,
             limit=limit or self.provider.config.default_result_limit)
             limit=limit or self.provider.config.default_result_limit)
@@ -181,9 +181,9 @@ class AzureKeyPairService(BaseKeyPairService):
                                      supports_total=False,
                                      supports_total=False,
                                      data=results)
                                      data=results)
 
 
-    @implement(event_pattern="provider.security.key_pairs.find",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.security.key_pairs.find",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['name']
         filters = ['name']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -197,9 +197,10 @@ class AzureKeyPairService(BaseKeyPairService):
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
                                      matches if matches else [])
 
 
-    @implement(event_pattern="provider.security.key_pairs.create",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _create(self, name, public_key_material=None):
+    @dispatch(event="provider.security.key_pairs.create",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def create(self, name, public_key_material=None):
+        AzureKeyPair.assert_valid_resource_name(name)
         key_pair = self.get(name)
         key_pair = self.get(name)
 
 
         if key_pair:
         if key_pair:
@@ -222,9 +223,9 @@ class AzureKeyPairService(BaseKeyPairService):
         key_pair.material = private_key
         key_pair.material = private_key
         return key_pair
         return key_pair
 
 
-    @implement(event_pattern="provider.security.key_pairs.delete",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, kp):
+    @dispatch(event="provider.security.key_pairs.delete",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def delete(self, kp):
         key_pair = kp if isinstance(kp, AzureKeyPair) else self.get(kp)
         key_pair = kp if isinstance(kp, AzureKeyPair) else self.get(kp)
         if key_pair:
         if key_pair:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -262,9 +263,9 @@ class AzureVolumeService(BaseVolumeService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(AzureVolumeService, self).__init__(provider)
         super(AzureVolumeService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.storage.volumes.get",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _get(self, volume_id):
+    @dispatch(event="provider.storage.volumes.get",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def get(self, volume_id):
         try:
         try:
             volume = self.provider.azure_client.get_disk(volume_id)
             volume = self.provider.azure_client.get_disk(volume_id)
             return AzureVolume(self.provider, volume)
             return AzureVolume(self.provider, volume)
@@ -273,9 +274,9 @@ class AzureVolumeService(BaseVolumeService):
             log.exception(cloud_error)
             log.exception(cloud_error)
             return None
             return None
 
 
-    @implement(event_pattern="provider.storage.volumes.find",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.storage.volumes.find",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['label']
         filters = ['label']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -289,17 +290,17 @@ class AzureVolumeService(BaseVolumeService):
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
                                      matches if matches else [])
 
 
-    @implement(event_pattern="provider.storage.volumes.list",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.storage.volumes.list",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         azure_vols = self.provider.azure_client.list_disks()
         azure_vols = self.provider.azure_client.list_disks()
         cb_vols = [AzureVolume(self.provider, vol) for vol in azure_vols]
         cb_vols = [AzureVolume(self.provider, vol) for vol in azure_vols]
         return ClientPagedResultList(self.provider, cb_vols,
         return ClientPagedResultList(self.provider, cb_vols,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.storage.volumes.create",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, size, zone, snapshot=None, description=None):
+    @dispatch(event="provider.storage.volumes.create",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, size, zone, snapshot=None, description=None):
         disk_name = AzureVolume._generate_name_from_label(label, "cb-vol")
         disk_name = AzureVolume._generate_name_from_label(label, "cb-vol")
         tags = {'Label': label}
         tags = {'Label': label}
 
 
@@ -343,9 +344,9 @@ class AzureVolumeService(BaseVolumeService):
 
 
         return cb_vol
         return cb_vol
 
 
-    @implement(event_pattern="provider.storage.volumes.delete",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, volume_id):
+    @dispatch(event="provider.storage.volumes.delete",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def delete(self, volume_id):
         vol_id = (volume_id.id if isinstance(volume_id, AzureVolume)
         vol_id = (volume_id.id if isinstance(volume_id, AzureVolume)
                   else volume_id)
                   else volume_id)
         self.provider.azure_client.delete_disk(vol_id)
         self.provider.azure_client.delete_disk(vol_id)
@@ -355,9 +356,9 @@ class AzureSnapshotService(BaseSnapshotService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(AzureSnapshotService, self).__init__(provider)
         super(AzureSnapshotService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.storage.snapshots.get",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _get(self, snapshot_id):
+    @dispatch(event="provider.storage.snapshots.get",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def get(self, snapshot_id):
         try:
         try:
             snapshot = self.provider.azure_client.get_snapshot(snapshot_id)
             snapshot = self.provider.azure_client.get_snapshot(snapshot_id)
             return AzureSnapshot(self.provider, snapshot)
             return AzureSnapshot(self.provider, snapshot)
@@ -366,9 +367,9 @@ class AzureSnapshotService(BaseSnapshotService):
             log.exception(cloud_error)
             log.exception(cloud_error)
             return None
             return None
 
 
-    @implement(event_pattern="provider.storage.snapshots.find",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.storage.snapshots.find",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['label']
         filters = ['label']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -382,17 +383,17 @@ class AzureSnapshotService(BaseSnapshotService):
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
                                      matches if matches else [])
 
 
-    @implement(event_pattern="provider.storage.snapshots.list",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.storage.snapshots.list",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         snaps = [AzureSnapshot(self.provider, obj)
         snaps = [AzureSnapshot(self.provider, obj)
                  for obj in
                  for obj in
                  self.provider.azure_client.list_snapshots()]
                  self.provider.azure_client.list_snapshots()]
         return ClientPagedResultList(self.provider, snaps, limit, marker)
         return ClientPagedResultList(self.provider, snaps, limit, marker)
 
 
-    @implement(event_pattern="provider.storage.snapshots.create",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, volume, description=None):
+    @dispatch(event="provider.storage.snapshots.create",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, volume, description=None):
         snapshot_name = AzureSnapshot._generate_name_from_label(label,
         snapshot_name = AzureSnapshot._generate_name_from_label(label,
                                                                 "cb-snap")
                                                                 "cb-snap")
         tags = {'Label': label}
         tags = {'Label': label}
@@ -416,9 +417,9 @@ class AzureSnapshotService(BaseSnapshotService):
                                                                 params)
                                                                 params)
         return AzureSnapshot(self.provider, azure_snap)
         return AzureSnapshot(self.provider, azure_snap)
 
 
-    @implement(event_pattern="provider.storage.snapshots.delete",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, snapshot_id):
+    @dispatch(event="provider.storage.snapshots.delete",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def delete(self, snapshot_id):
         snap_id = (snapshot_id.id if isinstance(snapshot_id, AzureSnapshot)
         snap_id = (snapshot_id.id if isinstance(snapshot_id, AzureSnapshot)
                    else snapshot_id)
                    else snapshot_id)
         self.provider.azure_client.delete_snapshot(snap_id)
         self.provider.azure_client.delete_snapshot(snap_id)
@@ -428,9 +429,9 @@ class AzureBucketService(BaseBucketService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(AzureBucketService, self).__init__(provider)
         super(AzureBucketService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.storage.buckets.get",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _get(self, bucket_id):
+    @dispatch(event="provider.storage.buckets.get",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def get(self, bucket_id):
         """
         """
         Returns a bucket given its ID. Returns ``None`` if the bucket
         Returns a bucket given its ID. Returns ``None`` if the bucket
         does not exist.
         does not exist.
@@ -442,18 +443,18 @@ class AzureBucketService(BaseBucketService):
             log.exception(error)
             log.exception(error)
             return None
             return None
 
 
-    @implement(event_pattern="provider.storage.buckets.list",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit, marker):
+    @dispatch(event="provider.storage.buckets.list",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit, marker):
         buckets = [AzureBucket(self.provider, bucket)
         buckets = [AzureBucket(self.provider, bucket)
                    for bucket
                    for bucket
                    in self.provider.azure_client.list_containers()[0]]
                    in self.provider.azure_client.list_containers()[0]]
         return ClientPagedResultList(self.provider, buckets,
         return ClientPagedResultList(self.provider, buckets,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.storage.buckets.create",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _create(self, name, location=None):
+    @dispatch(event="provider.storage.buckets.create",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def create(self, name, location=None):
         """
         """
         Create a new bucket.
         Create a new bucket.
         """
         """
@@ -461,9 +462,9 @@ class AzureBucketService(BaseBucketService):
         bucket = self.provider.azure_client.create_container(name)
         bucket = self.provider.azure_client.create_container(name)
         return AzureBucket(self.provider, bucket)
         return AzureBucket(self.provider, bucket)
 
 
-    @implement(event_pattern="provider.storage.buckets.delete",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, bucket):
+    @dispatch(event="provider.storage.buckets.delete",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def delete(self, bucket):
         """
         """
         Delete this bucket.
         Delete this bucket.
         """
         """
@@ -725,11 +726,11 @@ class AzureInstanceService(BaseInstanceService):
     def create_launch_config(self):
     def create_launch_config(self):
         return AzureLaunchConfig(self.provider)
         return AzureLaunchConfig(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):
+    @dispatch(event="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,
         instance_name = AzureInstance._generate_name_from_label(label,
                                                                 "cb-ins")
                                                                 "cb-ins")
 
 
@@ -859,9 +860,9 @@ class AzureInstanceService(BaseInstanceService):
                 temp_key_pair.delete()
                 temp_key_pair.delete()
         return AzureInstance(self.provider, vm)
         return AzureInstance(self.provider, vm)
 
 
-    @implement(event_pattern="provider.compute.instances.list",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.instances.list",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         """
         """
         List all instances.
         List all instances.
         """
         """
@@ -870,9 +871,9 @@ class AzureInstanceService(BaseInstanceService):
         return ClientPagedResultList(self.provider, instances,
         return ClientPagedResultList(self.provider, instances,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.compute.instances.get",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _get(self, instance_id):
+    @dispatch(event="provider.compute.instances.get",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def get(self, instance_id):
         """
         """
         Returns an instance given its id. Returns None
         Returns an instance given its id. Returns None
         if the object does not exist.
         if the object does not exist.
@@ -885,9 +886,9 @@ class AzureInstanceService(BaseInstanceService):
             log.exception(cloud_error)
             log.exception(cloud_error)
             return None
             return None
 
 
-    @implement(event_pattern="provider.compute.instances.find",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.compute.instances.find",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['label']
         filters = ['label']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -901,9 +902,9 @@ class AzureInstanceService(BaseInstanceService):
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
                                      matches if matches else [])
 
 
-    @implement(event_pattern="provider.compute.instances.delete",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, inst):
+    @dispatch(event="provider.compute.instances.delete",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def delete(self, inst):
         """
         """
         Permanently terminate this instance.
         Permanently terminate this instance.
         After deleting the VM. we are deleting the network interface
         After deleting the VM. we are deleting the network interface
@@ -945,9 +946,9 @@ class AzureVMTypeService(BaseVMTypeService):
         r = self.provider.azure_client.list_vm_types()
         r = self.provider.azure_client.list_vm_types()
         return r
         return r
 
 
-    @implement(event_pattern="provider.compute.vm_types.list",
-               priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.vm_types.list",
+              priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         vm_types = [AzureVMType(self.provider, vm_type)
         vm_types = [AzureVMType(self.provider, vm_type)
                     for vm_type in self.instance_data]
                     for vm_type in self.instance_data]
         return ClientPagedResultList(self.provider, vm_types,
         return ClientPagedResultList(self.provider, vm_types,
@@ -958,9 +959,9 @@ class AzureRegionService(BaseRegionService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(AzureRegionService, self).__init__(provider)
         super(AzureRegionService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.compute.regions.get",
-               priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
-    def _get(self, region_id):
+    @dispatch(event="provider.compute.regions.get",
+              priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
+    def get(self, region_id):
         region = None
         region = None
         for azureRegion in self.provider.azure_client.list_locations():
         for azureRegion in self.provider.azure_client.list_locations():
             if azureRegion.name == region_id:
             if azureRegion.name == region_id:
@@ -968,9 +969,9 @@ class AzureRegionService(BaseRegionService):
                 break
                 break
         return region
         return region
 
 
-    @implement(event_pattern="provider.compute.regions.list",
-               priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.regions.list",
+              priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         regions = [AzureRegion(self.provider, region)
         regions = [AzureRegion(self.provider, region)
                    for region in self.provider.azure_client.list_locations()]
                    for region in self.provider.azure_client.list_locations()]
         return ClientPagedResultList(self.provider, regions,
         return ClientPagedResultList(self.provider, regions,
@@ -1005,9 +1006,9 @@ class AzureNetworkService(BaseNetworkService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(AzureNetworkService, self).__init__(provider)
         super(AzureNetworkService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.networking.networks.get",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _get(self, network_id):
+    @dispatch(event="provider.networking.networks.get",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def get(self, network_id):
         try:
         try:
             network = self.provider.azure_client.get_network(network_id)
             network = self.provider.azure_client.get_network(network_id)
             return AzureNetwork(self.provider, network)
             return AzureNetwork(self.provider, network)
@@ -1016,17 +1017,17 @@ class AzureNetworkService(BaseNetworkService):
             log.exception(cloud_error)
             log.exception(cloud_error)
             return None
             return None
 
 
-    @implement(event_pattern="provider.networking.networks.list",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.networking.networks.list",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         networks = [AzureNetwork(self.provider, network)
         networks = [AzureNetwork(self.provider, network)
                     for network in self.provider.azure_client.list_networks()]
                     for network in self.provider.azure_client.list_networks()]
         return ClientPagedResultList(self.provider, networks,
         return ClientPagedResultList(self.provider, networks,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.networks.create",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, cidr_block):
+    @dispatch(event="provider.networking.networks.create",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, cidr_block):
         params = {
         params = {
             'location': self.provider.azure_client.region_name,
             'location': self.provider.azure_client.region_name,
             'address_space': {
             'address_space': {
@@ -1042,9 +1043,9 @@ class AzureNetworkService(BaseNetworkService):
         cb_network = AzureNetwork(self.provider, az_network)
         cb_network = AzureNetwork(self.provider, az_network)
         return cb_network
         return cb_network
 
 
-    @implement(event_pattern="provider.networking.networks.delete",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, net):
+    @dispatch(event="provider.networking.networks.delete",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def delete(self, net):
         net_id = net.id if isinstance(net, AzureNetwork) else net
         net_id = net.id if isinstance(net, AzureNetwork) else net
         if net_id:
         if net_id:
             self.provider.azure_client.delete_network(net_id)
             self.provider.azure_client.delete_network(net_id)
@@ -1077,9 +1078,9 @@ class AzureSubnetService(BaseSubnetService):
 
 
         return subnets
         return subnets
 
 
-    @implement(event_pattern="provider.networking.subnets.get",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _get(self, subnet_id):
+    @dispatch(event="provider.networking.subnets.get",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def get(self, subnet_id):
         """
         """
          Azure does not provide an api to get the subnet directly by id.
          Azure does not provide an api to get the subnet directly by id.
          It also requires the network id.
          It also requires the network id.
@@ -1095,16 +1096,16 @@ class AzureSubnetService(BaseSubnetService):
             log.exception(cloud_error)
             log.exception(cloud_error)
             return None
             return None
 
 
-    @implement(event_pattern="provider.networking.subnets.list",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _list(self, network=None, limit=None, marker=None):
+    @dispatch(event="provider.networking.subnets.list",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def list(self, network=None, limit=None, marker=None):
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      self._list_subnets(network),
                                      self._list_subnets(network),
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.subnets.find",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _find(self, network=None, **kwargs):
+    @dispatch(event="provider.networking.subnets.find",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def find(self, network=None, **kwargs):
         obj_list = self._list_subnets(network)
         obj_list = self._list_subnets(network)
         filters = ['label']
         filters = ['label']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -1112,9 +1113,10 @@ class AzureSubnetService(BaseSubnetService):
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
                                      matches if matches else [])
 
 
-    @implement(event_pattern="provider.networking.subnets.create",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network, cidr_block, zone):
+    @dispatch(event="provider.networking.subnets.create",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network, cidr_block, zone):
+        AzureSubnet.assert_valid_resource_label(label)
         # Although Subnet doesn't support tags in Azure, we use the parent
         # Although Subnet doesn't support tags in Azure, we use the parent
         # Network's tags to track its subnets' labels
         # Network's tags to track its subnets' labels
         subnet_name = AzureSubnet._generate_name_from_label(label, "cb-sn")
         subnet_name = AzureSubnet._generate_name_from_label(label, "cb-sn")
@@ -1135,9 +1137,9 @@ class AzureSubnetService(BaseSubnetService):
         subnet.label = label
         subnet.label = label
         return subnet
         return subnet
 
 
-    @implement(event_pattern="provider.networking.subnets.delete",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, subnet):
+    @dispatch(event="provider.networking.subnets.delete",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def delete(self, subnet):
         sn = subnet if isinstance(subnet, AzureSubnet) else self.get(subnet)
         sn = subnet if isinstance(subnet, AzureSubnet) else self.get(subnet)
         if sn:
         if sn:
             self.provider.azure_client.delete_subnet(sn.id)
             self.provider.azure_client.delete_subnet(sn.id)
@@ -1155,9 +1157,9 @@ class AzureRouterService(BaseRouterService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(AzureRouterService, self).__init__(provider)
         super(AzureRouterService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.networking.routers.get",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _get(self, router_id):
+    @dispatch(event="provider.networking.routers.get",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def get(self, router_id):
         try:
         try:
             route = self.provider.azure_client.get_route_table(router_id)
             route = self.provider.azure_client.get_route_table(router_id)
             return AzureRouter(self.provider, route)
             return AzureRouter(self.provider, route)
@@ -1166,9 +1168,9 @@ class AzureRouterService(BaseRouterService):
             log.exception(cloud_error)
             log.exception(cloud_error)
             return None
             return None
 
 
-    @implement(event_pattern="provider.networking.routers.find",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.networking.routers.find",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['label']
         filters = ['label']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
@@ -1182,9 +1184,9 @@ class AzureRouterService(BaseRouterService):
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
                                      matches if matches else [])
 
 
-    @implement(event_pattern="provider.networking.routers.list",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.networking.routers.list",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         routes = [AzureRouter(self.provider, route)
         routes = [AzureRouter(self.provider, route)
                   for route in
                   for route in
                   self.provider.azure_client.list_route_tables()]
                   self.provider.azure_client.list_route_tables()]
@@ -1192,9 +1194,9 @@ class AzureRouterService(BaseRouterService):
                                      routes,
                                      routes,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.routers.create",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network):
+    @dispatch(event="provider.networking.routers.create",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network):
         router_name = AzureRouter._generate_name_from_label(label, "cb-router")
         router_name = AzureRouter._generate_name_from_label(label, "cb-router")
 
 
         parameters = {"location": self.provider.region_name,
         parameters = {"location": self.provider.region_name,
@@ -1204,9 +1206,9 @@ class AzureRouterService(BaseRouterService):
             create_route_table(router_name, parameters)
             create_route_table(router_name, parameters)
         return AzureRouter(self.provider, route)
         return AzureRouter(self.provider, route)
 
 
-    @implement(event_pattern="provider.networking.routers.delete",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, router):
+    @dispatch(event="provider.networking.routers.delete",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def delete(self, router):
         r = router if isinstance(router, AzureRouter) else self.get(router)
         r = router if isinstance(router, AzureRouter) else self.get(router)
         if r:
         if r:
             self.provider.azure_client.delete_route_table(r.name)
             self.provider.azure_client.delete_route_table(r.name)

+ 148 - 146
cloudbridge/cloud/providers/gce/services.py

@@ -9,7 +9,7 @@ import googleapiclient
 
 
 import cloudbridge as cb
 import cloudbridge as cb
 from cloudbridge.cloud.base import helpers as cb_helpers
 from cloudbridge.cloud.base import helpers as cb_helpers
-from cloudbridge.cloud.base.middleware import implement
+from cloudbridge.cloud.base.middleware import dispatch
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.resources import ServerPagedResultList
 from cloudbridge.cloud.base.resources import ServerPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketObjectService
 from cloudbridge.cloud.base.services import BaseBucketObjectService
@@ -78,9 +78,9 @@ class GCEKeyPairService(BaseKeyPairService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(GCEKeyPairService, self).__init__(provider)
         super(GCEKeyPairService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.security.key_pairs.get",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _get(self, key_pair_id):
+    @dispatch(event="provider.security.key_pairs.get",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def get(self, key_pair_id):
         """
         """
         Returns a KeyPair given its ID.
         Returns a KeyPair given its ID.
         """
         """
@@ -90,9 +90,9 @@ class GCEKeyPairService(BaseKeyPairService):
         else:
         else:
             return None
             return None
 
 
-    @implement(event_pattern="provider.security.key_pairs.list",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.security.key_pairs.list",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         key_pairs = []
         key_pairs = []
         for item in helpers.find_matching_metadata_items(
         for item in helpers.find_matching_metadata_items(
                 self.provider, GCEKeyPair.KP_TAG_REGEX):
                 self.provider, GCEKeyPair.KP_TAG_REGEX):
@@ -102,9 +102,9 @@ class GCEKeyPairService(BaseKeyPairService):
         return ClientPagedResultList(self.provider, key_pairs,
         return ClientPagedResultList(self.provider, key_pairs,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.security.key_pairs.find",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.security.key_pairs.find",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         """
         """
         Searches for a key pair by a given list of attributes.
         Searches for a key pair by a given list of attributes.
         """
         """
@@ -121,9 +121,10 @@ class GCEKeyPairService(BaseKeyPairService):
         return ClientPagedResultList(self.provider,
         return ClientPagedResultList(self.provider,
                                      matches if matches else [])
                                      matches if matches else [])
 
 
-    @implement(event_pattern="provider.security.key_pairs.create",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _create(self, name, public_key_material=None):
+    @dispatch(event="provider.security.key_pairs.create",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def create(self, name, public_key_material=None):
+        GCEKeyPair.assert_valid_resource_name(name)
         private_key = None
         private_key = None
         if not public_key_material:
         if not public_key_material:
             public_key_material, private_key = cb_helpers.generate_key_pair()
             public_key_material, private_key = cb_helpers.generate_key_pair()
@@ -146,9 +147,9 @@ class GCEKeyPairService(BaseKeyPairService):
                         'A KeyPair with name {0} already exists'.format(name))
                         'A KeyPair with name {0} already exists'.format(name))
             raise
             raise
 
 
-    @implement(event_pattern="provider.security.key_pairs.delete",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, kp):
+    @dispatch(event="provider.security.key_pairs.delete",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def delete(self, kp):
         kp = kp if isinstance(kp, GCEKeyPair) else self.get(kp)
         kp = kp if isinstance(kp, GCEKeyPair) else self.get(kp)
         if kp:
         if kp:
             helpers.remove_metadata_item(
             helpers.remove_metadata_item(
@@ -161,9 +162,9 @@ class GCEVMFirewallService(BaseVMFirewallService):
         super(GCEVMFirewallService, self).__init__(provider)
         super(GCEVMFirewallService, self).__init__(provider)
         self._delegate = GCEFirewallsDelegate(provider)
         self._delegate = GCEFirewallsDelegate(provider)
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.get",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _get(self, vm_firewall_id):
+    @dispatch(event="provider.security.vm_firewalls.get",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def get(self, vm_firewall_id):
         tag, network_name = \
         tag, network_name = \
             self._delegate.get_tag_network_from_id(vm_firewall_id)
             self._delegate.get_tag_network_from_id(vm_firewall_id)
         if tag is None:
         if tag is None:
@@ -171,9 +172,9 @@ class GCEVMFirewallService(BaseVMFirewallService):
         network = self.provider.networking.networks.get(network_name)
         network = self.provider.networking.networks.get(network_name)
         return GCEVMFirewall(self._delegate, tag, network)
         return GCEVMFirewall(self._delegate, tag, network)
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.list",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.security.vm_firewalls.list",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         vm_firewalls = []
         vm_firewalls = []
         for tag, network_name in self._delegate.tag_networks:
         for tag, network_name in self._delegate.tag_networks:
             network = self.provider.networking.networks.get(
             network = self.provider.networking.networks.get(
@@ -183,9 +184,9 @@ class GCEVMFirewallService(BaseVMFirewallService):
         return ClientPagedResultList(self.provider, vm_firewalls,
         return ClientPagedResultList(self.provider, vm_firewalls,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.create",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network, description=None):
+    @dispatch(event="provider.security.vm_firewalls.create",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network, description=None):
         network = (network if isinstance(network, GCENetwork)
         network = (network if isinstance(network, GCENetwork)
                    else self.provider.networking.networks.get(network))
                    else self.provider.networking.networks.get(network))
         fw = GCEVMFirewall(self._delegate, label, network, description)
         fw = GCEVMFirewall(self._delegate, label, network, description)
@@ -197,9 +198,9 @@ class GCEVMFirewallService(BaseVMFirewallService):
         fw.label = label
         fw.label = label
         return fw
         return fw
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.delete",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, vmf):
+    @dispatch(event="provider.security.vm_firewalls.delete",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def delete(self, vmf):
         fw_id = vmf.id if isinstance(vmf, GCEVMFirewall) else vmf
         fw_id = vmf.id if isinstance(vmf, GCEVMFirewall) else vmf
         return self._delegate.delete_tag_network_with_id(fw_id)
         return self._delegate.delete_tag_network_with_id(fw_id)
 
 
@@ -235,15 +236,15 @@ class GCEVMTypeService(BaseVMTypeService):
                         .execute())
                         .execute())
         return response['items']
         return response['items']
 
 
-    @implement(event_pattern="provider.compute.vm_types.get",
-               priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
-    def _get(self, vm_type_id):
+    @dispatch(event="provider.compute.vm_types.get",
+              priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
+    def get(self, vm_type_id):
         vm_type = self.provider.get_resource('machineTypes', vm_type_id)
         vm_type = self.provider.get_resource('machineTypes', vm_type_id)
         return GCEVMType(self.provider, vm_type) if vm_type else None
         return GCEVMType(self.provider, vm_type) if vm_type else None
 
 
-    @implement(event_pattern="provider.compute.vm_types.find",
-               priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.compute.vm_types.find",
+              priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         matched_inst_types = []
         matched_inst_types = []
         for inst_type in self.instance_data:
         for inst_type in self.instance_data:
             is_match = True
             is_match = True
@@ -259,9 +260,9 @@ class GCEVMTypeService(BaseVMTypeService):
                     GCEVMType(self.provider, inst_type))
                     GCEVMType(self.provider, inst_type))
         return matched_inst_types
         return matched_inst_types
 
 
-    @implement(event_pattern="provider.compute.vm_types.list",
-               priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.vm_types.list",
+              priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         inst_types = [GCEVMType(self.provider, inst_type)
         inst_types = [GCEVMType(self.provider, inst_type)
                       for inst_type in self.instance_data]
                       for inst_type in self.instance_data]
         return ClientPagedResultList(self.provider, inst_types,
         return ClientPagedResultList(self.provider, inst_types,
@@ -273,16 +274,16 @@ class GCERegionService(BaseRegionService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(GCERegionService, self).__init__(provider)
         super(GCERegionService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.compute.regions.get",
-               priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
-    def _get(self, region_id):
+    @dispatch(event="provider.compute.regions.get",
+              priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
+    def get(self, region_id):
         region = self.provider.get_resource('regions', region_id,
         region = self.provider.get_resource('regions', region_id,
                                             region=region_id)
                                             region=region_id)
         return GCERegion(self.provider, region) if region else None
         return GCERegion(self.provider, region) if region else None
 
 
-    @implement(event_pattern="provider.compute.regions.list",
-               priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.regions.list",
+              priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         max_result = limit if limit is not None and limit < 500 else 500
         max_result = limit if limit is not None and limit < 500 else 500
         regions_response = (self.provider
         regions_response = (self.provider
                                 .gce_compute
                                 .gce_compute
@@ -376,11 +377,11 @@ class GCEInstanceService(BaseInstanceService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(GCEInstanceService, self).__init__(provider)
         super(GCEInstanceService, self).__init__(provider)
 
 
-    @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):
+    @dispatch(event="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.
         Creates a new virtual machine instance.
         """
         """
@@ -527,9 +528,9 @@ class GCEInstanceService(BaseInstanceService):
         cb_inst = self.get(instance_id)
         cb_inst = self.get(instance_id)
         return cb_inst
         return cb_inst
 
 
-    @implement(event_pattern="provider.compute.instances.get",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _get(self, instance_id):
+    @dispatch(event="provider.compute.instances.get",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def get(self, instance_id):
         """
         """
         Returns an instance given its name. Returns None
         Returns an instance given its name. Returns None
         if the object does not exist.
         if the object does not exist.
@@ -540,9 +541,9 @@ class GCEInstanceService(BaseInstanceService):
         instance = self.provider.get_resource('instances', instance_id)
         instance = self.provider.get_resource('instances', instance_id)
         return GCEInstance(self.provider, instance) if instance else None
         return GCEInstance(self.provider, instance) if instance else None
 
 
-    @implement(event_pattern="provider.compute.instances.find",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _find(self, limit=None, marker=None, **kwargs):
+    @dispatch(event="provider.compute.instances.find",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def find(self, limit=None, marker=None, **kwargs):
         """
         """
         Searches for instances by instance label.
         Searches for instances by instance label.
         :return: a list of Instance objects
         :return: a list of Instance objects
@@ -560,9 +561,9 @@ class GCEInstanceService(BaseInstanceService):
         return ClientPagedResultList(self.provider, instances,
         return ClientPagedResultList(self.provider, instances,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.compute.instances.list",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.instances.list",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         """
         """
         List all instances.
         List all instances.
         """
         """
@@ -586,9 +587,9 @@ class GCEInstanceService(BaseInstanceService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=instances)
                                      False, data=instances)
 
 
-    @implement(event_pattern="provider.compute.instances.delete",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, inst):
+    @dispatch(event="provider.compute.instances.delete",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def delete(self, inst):
         instance = inst if isinstance(inst, GCEInstance) else self.get(inst)
         instance = inst if isinstance(inst, GCEInstance) else self.get(inst)
         if instance:
         if instance:
             (self._provider
             (self._provider
@@ -655,15 +656,15 @@ class GCENetworkService(BaseNetworkService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(GCENetworkService, self).__init__(provider)
         super(GCENetworkService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.networking.networks.get",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _get(self, network_id):
+    @dispatch(event="provider.networking.networks.get",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def get(self, network_id):
         network = self.provider.get_resource('networks', network_id)
         network = self.provider.get_resource('networks', network_id)
         return GCENetwork(self.provider, network) if network else None
         return GCENetwork(self.provider, network) if network else None
 
 
-    @implement(event_pattern="provider.networking.networks.find",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _find(self, limit=None, marker=None, **kwargs):
+    @dispatch(event="provider.networking.networks.find",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def find(self, limit=None, marker=None, **kwargs):
         """
         """
         GCE networks are global. There is at most one network with a given
         GCE networks are global. There is at most one network with a given
         name.
         name.
@@ -674,9 +675,9 @@ class GCENetworkService(BaseNetworkService):
         return ClientPagedResultList(self._provider, list(matches),
         return ClientPagedResultList(self._provider, list(matches),
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.networks.list",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None, filter=None):
+    @dispatch(event="provider.networking.networks.list",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None, filter=None):
         # TODO: Decide whether we keep filter in 'list'
         # TODO: Decide whether we keep filter in 'list'
         networks = []
         networks = []
         response = (self.provider
         response = (self.provider
@@ -690,9 +691,9 @@ class GCENetworkService(BaseNetworkService):
         return ClientPagedResultList(self.provider, networks,
         return ClientPagedResultList(self.provider, networks,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.networks.create",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, cidr_block):
+    @dispatch(event="provider.networking.networks.create",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, cidr_block):
         """
         """
         Creates an auto mode VPC network with default subnets. It is possible
         Creates an auto mode VPC network with default subnets. It is possible
         to add additional subnets later.
         to add additional subnets later.
@@ -725,9 +726,9 @@ class GCENetworkService(BaseNetworkService):
                 label=GCENetwork.CB_DEFAULT_NETWORK_LABEL,
                 label=GCENetwork.CB_DEFAULT_NETWORK_LABEL,
                 cidr_block=GCENetwork.CB_DEFAULT_IPV4RANGE)
                 cidr_block=GCENetwork.CB_DEFAULT_IPV4RANGE)
 
 
-    @implement(event_pattern="provider.networking.networks.delete",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, network):
+    @dispatch(event="provider.networking.networks.delete",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def delete(self, network):
         # Accepts network object
         # Accepts network object
         if isinstance(network, GCENetwork):
         if isinstance(network, GCENetwork):
             name = network.name
             name = network.name
@@ -756,15 +757,15 @@ class GCERouterService(BaseRouterService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(GCERouterService, self).__init__(provider)
         super(GCERouterService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.networking.routers.get",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _get(self, router_id):
+    @dispatch(event="provider.networking.routers.get",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def get(self, router_id):
         router = self.provider.get_resource(
         router = self.provider.get_resource(
             'routers', router_id, region=self.provider.region_name)
             'routers', router_id, region=self.provider.region_name)
         return GCERouter(self.provider, router) if router else None
         return GCERouter(self.provider, router) if router else None
 
 
-    @implement(event_pattern="provider.networking.routers.find",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    @dispatch(event="provider.networking.routers.find",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
     def find(self, limit=None, marker=None, **kwargs):
     def find(self, limit=None, marker=None, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['name', 'label']
         filters = ['name', 'label']
@@ -772,9 +773,9 @@ class GCERouterService(BaseRouterService):
         return ClientPagedResultList(self._provider, list(matches),
         return ClientPagedResultList(self._provider, list(matches),
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.routers.list",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.networking.routers.list",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         region = self.provider.region_name
         region = self.provider.region_name
         max_result = limit if limit is not None and limit < 500 else 500
         max_result = limit if limit is not None and limit < 500 else 500
         response = (self.provider
         response = (self.provider
@@ -795,9 +796,9 @@ class GCERouterService(BaseRouterService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=routers)
                                      False, data=routers)
 
 
-    @implement(event_pattern="provider.networking.routers.create",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network):
+    @dispatch(event="provider.networking.routers.create",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network):
         log.debug("Creating GCE Router Service with params "
         log.debug("Creating GCE Router Service with params "
                   "[label: %s network: %s]", label, network)
                   "[label: %s network: %s]", label, network)
         GCERouter.assert_valid_resource_label(label)
         GCERouter.assert_valid_resource_label(label)
@@ -820,9 +821,9 @@ class GCERouterService(BaseRouterService):
         cb_router.label = label
         cb_router.label = label
         return cb_router
         return cb_router
 
 
-    @implement(event_pattern="provider.networking.routers.delete",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, router):
+    @dispatch(event="provider.networking.routers.delete",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def delete(self, router):
         r = router if isinstance(router, GCERouter) else self.get(router)
         r = router if isinstance(router, GCERouter) else self.get(router)
         if r:
         if r:
             (self.provider
             (self.provider
@@ -854,15 +855,15 @@ class GCESubnetService(BaseSubnetService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(GCESubnetService, self).__init__(provider)
         super(GCESubnetService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.networking.subnets.get",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _get(self, subnet_id):
+    @dispatch(event="provider.networking.subnets.get",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def get(self, subnet_id):
         subnet = self.provider.get_resource('subnetworks', subnet_id)
         subnet = self.provider.get_resource('subnetworks', subnet_id)
         return GCESubnet(self.provider, subnet) if subnet else None
         return GCESubnet(self.provider, subnet) if subnet else None
 
 
-    @implement(event_pattern="provider.networking.subnets.list",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _list(self, network=None, zone=None, limit=None, marker=None):
+    @dispatch(event="provider.networking.subnets.list",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def list(self, network=None, zone=None, limit=None, marker=None):
         """
         """
         If the zone is not given, we list all subnets in the default region.
         If the zone is not given, we list all subnets in the default region.
         """
         """
@@ -888,9 +889,9 @@ class GCESubnetService(BaseSubnetService):
         return ClientPagedResultList(self.provider, subnets,
         return ClientPagedResultList(self.provider, subnets,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.subnets.create",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network, cidr_block, zone):
+    @dispatch(event="provider.networking.subnets.create",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network, cidr_block, zone):
         """
         """
         GCE subnets are regional. The region is inferred from the zone;
         GCE subnets are regional. The region is inferred from the zone;
         otherwise, the default region, as set in the
         otherwise, the default region, as set in the
@@ -900,6 +901,7 @@ class GCESubnetService(BaseSubnetService):
         instead of creating a new subnet. In this case, other parameters, i.e.
         instead of creating a new subnet. In this case, other parameters, i.e.
         the name and the zone, are ignored.
         the name and the zone, are ignored.
         """
         """
+        GCESubnet.assert_valid_resource_label(label)
         name = GCESubnet._generate_name_from_label(label, 'cbsubnet')
         name = GCESubnet._generate_name_from_label(label, 'cbsubnet')
         region_name = self._zone_to_region(zone)
         region_name = self._zone_to_region(zone)
 #         for subnet in self.iter(network=network):
 #         for subnet in self.iter(network=network):
@@ -931,9 +933,9 @@ class GCESubnetService(BaseSubnetService):
         cb_subnet.label = label
         cb_subnet.label = label
         return cb_subnet
         return cb_subnet
 
 
-    @implement(event_pattern="provider.networking.subnets.delete",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, subnet):
+    @dispatch(event="provider.networking.subnets.delete",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def delete(self, subnet):
         sn = subnet if isinstance(subnet, GCESubnet) else self.get(subnet)
         sn = subnet if isinstance(subnet, GCESubnet) else self.get(subnet)
         if not sn:
         if not sn:
             return
             return
@@ -1048,15 +1050,15 @@ class GCEVolumeService(BaseVolumeService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(GCEVolumeService, self).__init__(provider)
         super(GCEVolumeService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.storage.volumes.get",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _get(self, volume_id):
+    @dispatch(event="provider.storage.volumes.get",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def get(self, volume_id):
         vol = self.provider.get_resource('disks', volume_id)
         vol = self.provider.get_resource('disks', volume_id)
         return GCEVolume(self.provider, vol) if vol else None
         return GCEVolume(self.provider, vol) if vol else None
 
 
-    @implement(event_pattern="provider.storage.volumes.find",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _find(self, limit=None, marker=None, **kwargs):
+    @dispatch(event="provider.storage.volumes.find",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def find(self, limit=None, marker=None, **kwargs):
         """
         """
         Searches for a volume by a given list of attributes.
         Searches for a volume by a given list of attributes.
         """
         """
@@ -1088,9 +1090,9 @@ class GCEVolumeService(BaseVolumeService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=gce_vols)
                                      False, data=gce_vols)
 
 
-    @implement(event_pattern="provider.storage.volumes.list",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.storage.volumes.list",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         """
         """
         List all volumes.
         List all volumes.
 
 
@@ -1118,9 +1120,9 @@ class GCEVolumeService(BaseVolumeService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=gce_vols)
                                      False, data=gce_vols)
 
 
-    @implement(event_pattern="provider.storage.volumes.create",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, size, zone, snapshot=None, description=None):
+    @dispatch(event="provider.storage.volumes.create",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, size, zone, snapshot=None, description=None):
         name = GCEVolume._generate_name_from_label(label, 'cb-vol')
         name = GCEVolume._generate_name_from_label(label, 'cb-vol')
         if not isinstance(zone, GCEPlacementZone):
         if not isinstance(zone, GCEPlacementZone):
             zone = GCEPlacementZone(
             zone = GCEPlacementZone(
@@ -1148,9 +1150,9 @@ class GCEVolumeService(BaseVolumeService):
         cb_vol = self.get(operation.get('targetLink'))
         cb_vol = self.get(operation.get('targetLink'))
         return cb_vol
         return cb_vol
 
 
-    @implement(event_pattern="provider.storage.volumes.delete",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, vol):
+    @dispatch(event="provider.storage.volumes.delete",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def delete(self, vol):
         volume = vol if isinstance(vol, GCEVolume) else self.get(vol)
         volume = vol if isinstance(vol, GCEVolume) else self.get(vol)
         if volume:
         if volume:
             (self._provider.gce_compute
             (self._provider.gce_compute
@@ -1166,15 +1168,15 @@ class GCESnapshotService(BaseSnapshotService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(GCESnapshotService, self).__init__(provider)
         super(GCESnapshotService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.storage.snapshots.get",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _get(self, snapshot_id):
+    @dispatch(event="provider.storage.snapshots.get",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def get(self, snapshot_id):
         snapshot = self.provider.get_resource('snapshots', snapshot_id)
         snapshot = self.provider.get_resource('snapshots', snapshot_id)
         return GCESnapshot(self.provider, snapshot) if snapshot else None
         return GCESnapshot(self.provider, snapshot) if snapshot else None
 
 
-    @implement(event_pattern="provider.storage.snapshots.find",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _find(self, limit=None, marker=None, **kwargs):
+    @dispatch(event="provider.storage.snapshots.find",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def find(self, limit=None, marker=None, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -1202,9 +1204,9 @@ class GCESnapshotService(BaseSnapshotService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=snapshots)
                                      False, data=snapshots)
 
 
-    @implement(event_pattern="provider.storage.snapshots.list",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.storage.snapshots.list",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         max_result = limit if limit is not None and limit < 500 else 500
         max_result = limit if limit is not None and limit < 500 else 500
         response = (self.provider
         response = (self.provider
                         .gce_compute
                         .gce_compute
@@ -1222,9 +1224,9 @@ class GCESnapshotService(BaseSnapshotService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=snapshots)
                                      False, data=snapshots)
 
 
-    @implement(event_pattern="provider.storage.snapshots.create",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, volume, description=None):
+    @dispatch(event="provider.storage.snapshots.create",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, volume, description=None):
         name = GCESnapshot._generate_name_from_label(label, 'cbsnap')
         name = GCESnapshot._generate_name_from_label(label, 'cbsnap')
         volume_name = volume.name if isinstance(volume, GCEVolume) else volume
         volume_name = volume.name if isinstance(volume, GCEVolume) else volume
         snapshot_body = {
         snapshot_body = {
@@ -1247,9 +1249,9 @@ class GCESnapshotService(BaseSnapshotService):
         cb_snap = self.get(name)
         cb_snap = self.get(name)
         return cb_snap
         return cb_snap
 
 
-    @implement(event_pattern="provider.storage.snapshots.delete",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, snap):
+    @dispatch(event="provider.storage.snapshots.delete",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def delete(self, snap):
         snapshot = snap if isinstance(snap, GCESnapshot) else self.get(snap)
         snapshot = snap if isinstance(snap, GCESnapshot) else self.get(snap)
         if snapshot:
         if snapshot:
             (self.provider
             (self.provider
@@ -1265,9 +1267,9 @@ class GCSBucketService(BaseBucketService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(GCSBucketService, self).__init__(provider)
         super(GCSBucketService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.storage.buckets.get",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _get(self, bucket_id):
+    @dispatch(event="provider.storage.buckets.get",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def get(self, bucket_id):
         """
         """
         Returns a bucket given its ID. Returns ``None`` if the bucket
         Returns a bucket given its ID. Returns ``None`` if the bucket
         does not exist or if the user does not have permission to access the
         does not exist or if the user does not have permission to access the
@@ -1276,9 +1278,9 @@ class GCSBucketService(BaseBucketService):
         bucket = self.provider.get_resource('buckets', bucket_id)
         bucket = self.provider.get_resource('buckets', bucket_id)
         return GCSBucket(self.provider, bucket) if bucket else None
         return GCSBucket(self.provider, bucket) if bucket else None
 
 
-    @implement(event_pattern="provider.storage.buckets.find",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _find(self, limit=None, marker=None, **kwargs):
+    @dispatch(event="provider.storage.buckets.find",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def find(self, limit=None, marker=None, **kwargs):
         name = kwargs.pop('name', None)
         name = kwargs.pop('name', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -1291,9 +1293,9 @@ class GCSBucketService(BaseBucketService):
         return ClientPagedResultList(self.provider, buckets, limit=limit,
         return ClientPagedResultList(self.provider, buckets, limit=limit,
                                      marker=marker)
                                      marker=marker)
 
 
-    @implement(event_pattern="provider.storage.buckets.list",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.storage.buckets.list",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         """
         """
         List all containers.
         List all containers.
         """
         """
@@ -1315,9 +1317,9 @@ class GCSBucketService(BaseBucketService):
                                      response.get('nextPageToken'),
                                      response.get('nextPageToken'),
                                      False, data=buckets)
                                      False, data=buckets)
 
 
-    @implement(event_pattern="provider.storage.buckets.create",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _create(self, name, location=None):
+    @dispatch(event="provider.storage.buckets.create",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def create(self, name, location=None):
         GCSBucket.assert_valid_resource_name(name)
         GCSBucket.assert_valid_resource_name(name)
         body = {'name': name}
         body = {'name': name}
         if location:
         if location:
@@ -1342,9 +1344,9 @@ class GCSBucketService(BaseBucketService):
             else:
             else:
                 raise
                 raise
 
 
-    @implement(event_pattern="provider.storage.buckets.delete",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, bucket):
+    @dispatch(event="provider.storage.buckets.delete",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def delete(self, bucket):
         """
         """
         Delete this bucket.
         Delete this bucket.
         """
         """

+ 143 - 141
cloudbridge/cloud/providers/openstack/services.py

@@ -16,7 +16,7 @@ from openstack.exceptions import ResourceNotFound
 from swiftclient import ClientException as SwiftClientException
 from swiftclient import ClientException as SwiftClientException
 
 
 import cloudbridge.cloud.base.helpers as cb_helpers
 import cloudbridge.cloud.base.helpers as cb_helpers
-from cloudbridge.cloud.base.middleware import implement
+from cloudbridge.cloud.base.middleware import dispatch
 from cloudbridge.cloud.base.resources import BaseLaunchConfig
 from cloudbridge.cloud.base.resources import BaseLaunchConfig
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.services import BaseBucketObjectService
 from cloudbridge.cloud.base.services import BaseBucketObjectService
@@ -132,9 +132,9 @@ class OpenStackKeyPairService(BaseKeyPairService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackKeyPairService, self).__init__(provider)
         super(OpenStackKeyPairService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.security.key_pairs.get",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _get(self, key_pair_id):
+    @dispatch(event="provider.security.key_pairs.get",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def get(self, key_pair_id):
         """
         """
         Returns a KeyPair given its id.
         Returns a KeyPair given its id.
         """
         """
@@ -146,9 +146,9 @@ class OpenStackKeyPairService(BaseKeyPairService):
             log.debug("KeyPair %s was not found.", key_pair_id)
             log.debug("KeyPair %s was not found.", key_pair_id)
             return None
             return None
 
 
-    @implement(event_pattern="provider.security.key_pairs.list",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.security.key_pairs.list",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         """
         """
         List all key pairs associated with this account.
         List all key pairs associated with this account.
 
 
@@ -163,9 +163,9 @@ class OpenStackKeyPairService(BaseKeyPairService):
         return ClientPagedResultList(self.provider, results,
         return ClientPagedResultList(self.provider, results,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.security.key_pairs.find",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.security.key_pairs.find",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         name = kwargs.pop('name', None)
         name = kwargs.pop('name', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -180,9 +180,10 @@ class OpenStackKeyPairService(BaseKeyPairService):
         log.debug("Searching for %s in: %s", name, keypairs)
         log.debug("Searching for %s in: %s", name, keypairs)
         return ClientPagedResultList(self.provider, results)
         return ClientPagedResultList(self.provider, results)
 
 
-    @implement(event_pattern="provider.security.key_pairs.create",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _create(self, name, public_key_material=None):
+    @dispatch(event="provider.security.key_pairs.create",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def create(self, name, public_key_material=None):
+        OpenStackKeyPair.assert_valid_resource_name(name)
         existing_kp = self.find(name=name)
         existing_kp = self.find(name=name)
         if existing_kp:
         if existing_kp:
             raise DuplicateResourceException(
             raise DuplicateResourceException(
@@ -198,9 +199,9 @@ class OpenStackKeyPairService(BaseKeyPairService):
         cb_kp.material = private_key
         cb_kp.material = private_key
         return cb_kp
         return cb_kp
 
 
-    @implement(event_pattern="provider.security.key_pairs.delete",
-               priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, kp):
+    @dispatch(event="provider.security.key_pairs.delete",
+              priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
+    def delete(self, kp):
         keypair = kp if isinstance(kp, OpenStackKeyPair) else self.get(kp)
         keypair = kp if isinstance(kp, OpenStackKeyPair) else self.get(kp)
         if keypair:
         if keypair:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -212,9 +213,9 @@ class OpenStackVMFirewallService(BaseVMFirewallService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackVMFirewallService, self).__init__(provider)
         super(OpenStackVMFirewallService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.get",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _get(self, vm_firewall_id):
+    @dispatch(event="provider.security.vm_firewalls.get",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def get(self, vm_firewall_id):
         try:
         try:
             return OpenStackVMFirewall(
             return OpenStackVMFirewall(
                 self.provider,
                 self.provider,
@@ -224,9 +225,9 @@ class OpenStackVMFirewallService(BaseVMFirewallService):
             log.debug("Firewall %s not found.", vm_firewall_id)
             log.debug("Firewall %s not found.", vm_firewall_id)
             return None
             return None
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.list",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.security.vm_firewalls.list",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         firewalls = [
         firewalls = [
             OpenStackVMFirewall(self.provider, fw)
             OpenStackVMFirewall(self.provider, fw)
             for fw in self.provider.os_conn.network.security_groups()]
             for fw in self.provider.os_conn.network.security_groups()]
@@ -235,9 +236,9 @@ class OpenStackVMFirewallService(BaseVMFirewallService):
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
     @cb_helpers.deprecated_alias(network_id='network')
     @cb_helpers.deprecated_alias(network_id='network')
-    @implement(event_pattern="provider.security.vm_firewalls.create",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network, description=None):
+    @dispatch(event="provider.security.vm_firewalls.create",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network, description=None):
         net = network.id if isinstance(network, Network) else network
         net = network.id if isinstance(network, Network) else network
         # We generally simulate a network being associated with a firewall
         # We generally simulate a network being associated with a firewall
         # by storing the supplied value in the firewall description field that
         # by storing the supplied value in the firewall description field that
@@ -255,9 +256,9 @@ class OpenStackVMFirewallService(BaseVMFirewallService):
             return OpenStackVMFirewall(self.provider, sg)
             return OpenStackVMFirewall(self.provider, sg)
         return None
         return None
 
 
-    @implement(event_pattern="provider.security.vm_firewalls.delete",
-               priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, vmf):
+    @dispatch(event="provider.security.vm_firewalls.delete",
+              priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
+    def delete(self, vmf):
         fw = vmf if isinstance(vmf, OpenStackVMFirewall) else self.get(vmf)
         fw = vmf if isinstance(vmf, OpenStackVMFirewall) else self.get(vmf)
         if fw:
         if fw:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -297,9 +298,9 @@ class OpenStackVolumeService(BaseVolumeService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackVolumeService, self).__init__(provider)
         super(OpenStackVolumeService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.storage.volumes.get",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _get(self, volume_id):
+    @dispatch(event="provider.storage.volumes.get",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def get(self, volume_id):
         try:
         try:
             return OpenStackVolume(
             return OpenStackVolume(
                 self.provider, self.provider.cinder.volumes.get(volume_id))
                 self.provider, self.provider.cinder.volumes.get(volume_id))
@@ -307,9 +308,9 @@ class OpenStackVolumeService(BaseVolumeService):
             log.debug("Volume %s was not found.", volume_id)
             log.debug("Volume %s was not found.", volume_id)
             return None
             return None
 
 
-    @implement(event_pattern="provider.storage.volumes.find",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.storage.volumes.find",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -329,9 +330,9 @@ class OpenStackVolumeService(BaseVolumeService):
 
 
         return oshelpers.to_server_paged_list(self.provider, cb_vols)
         return oshelpers.to_server_paged_list(self.provider, cb_vols)
 
 
-    @implement(event_pattern="provider.storage.volumes.list",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.storage.volumes.list",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         cb_vols = [
         cb_vols = [
             OpenStackVolume(self.provider, vol)
             OpenStackVolume(self.provider, vol)
             for vol in self.provider.cinder.volumes.list(
             for vol in self.provider.cinder.volumes.list(
@@ -340,9 +341,9 @@ class OpenStackVolumeService(BaseVolumeService):
 
 
         return oshelpers.to_server_paged_list(self.provider, cb_vols, limit)
         return oshelpers.to_server_paged_list(self.provider, cb_vols, limit)
 
 
-    @implement(event_pattern="provider.storage.volumes.create",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, size, zone, snapshot=None, description=None):
+    @dispatch(event="provider.storage.volumes.create",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, size, zone, snapshot=None, description=None):
         zone_id = zone.id if isinstance(zone, PlacementZone) else zone
         zone_id = zone.id if isinstance(zone, PlacementZone) else zone
         snapshot_id = snapshot.id if isinstance(
         snapshot_id = snapshot.id if isinstance(
             snapshot, OpenStackSnapshot) and snapshot else snapshot
             snapshot, OpenStackSnapshot) and snapshot else snapshot
@@ -352,9 +353,9 @@ class OpenStackVolumeService(BaseVolumeService):
             availability_zone=zone_id, snapshot_id=snapshot_id)
             availability_zone=zone_id, snapshot_id=snapshot_id)
         return OpenStackVolume(self.provider, os_vol)
         return OpenStackVolume(self.provider, os_vol)
 
 
-    @implement(event_pattern="provider.storage.volumes.delete",
-               priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, vol):
+    @dispatch(event="provider.storage.volumes.delete",
+              priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
+    def delete(self, vol):
         volume = vol if isinstance(vol, OpenStackVolume) else self.get(vol)
         volume = vol if isinstance(vol, OpenStackVolume) else self.get(vol)
         if volume:
         if volume:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -366,9 +367,9 @@ class OpenStackSnapshotService(BaseSnapshotService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackSnapshotService, self).__init__(provider)
         super(OpenStackSnapshotService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.storage.snapshots.get",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _get(self, snapshot_id):
+    @dispatch(event="provider.storage.snapshots.get",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def get(self, snapshot_id):
         try:
         try:
             return OpenStackSnapshot(
             return OpenStackSnapshot(
                 self.provider,
                 self.provider,
@@ -377,9 +378,9 @@ class OpenStackSnapshotService(BaseSnapshotService):
             log.debug("Snapshot %s was not found.", snapshot_id)
             log.debug("Snapshot %s was not found.", snapshot_id)
             return None
             return None
 
 
-    @implement(event_pattern="provider.storage.snapshots.find",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.storage.snapshots.find",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -400,9 +401,9 @@ class OpenStackSnapshotService(BaseSnapshotService):
 
 
         return oshelpers.to_server_paged_list(self.provider, cb_snaps)
         return oshelpers.to_server_paged_list(self.provider, cb_snaps)
 
 
-    @implement(event_pattern="provider.storage.snapshots.list",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.storage.snapshots.list",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         cb_snaps = [
         cb_snaps = [
             OpenStackSnapshot(self.provider, snap) for
             OpenStackSnapshot(self.provider, snap) for
             snap in self.provider.cinder.volume_snapshots.list(
             snap in self.provider.cinder.volume_snapshots.list(
@@ -411,9 +412,9 @@ class OpenStackSnapshotService(BaseSnapshotService):
                              'marker': marker})]
                              'marker': marker})]
         return oshelpers.to_server_paged_list(self.provider, cb_snaps, limit)
         return oshelpers.to_server_paged_list(self.provider, cb_snaps, limit)
 
 
-    @implement(event_pattern="provider.storage.snapshots.create",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, volume, description=None):
+    @dispatch(event="provider.storage.snapshots.create",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, volume, description=None):
         volume_id = (volume.id if isinstance(volume, OpenStackVolume)
         volume_id = (volume.id if isinstance(volume, OpenStackVolume)
                      else volume)
                      else volume)
 
 
@@ -422,9 +423,9 @@ class OpenStackSnapshotService(BaseSnapshotService):
             description=description)
             description=description)
         return OpenStackSnapshot(self.provider, os_snap)
         return OpenStackSnapshot(self.provider, os_snap)
 
 
-    @implement(event_pattern="provider.storage.snapshots.delete",
-               priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, snap):
+    @dispatch(event="provider.storage.snapshots.delete",
+              priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
+    def delete(self, snap):
         s = snap if isinstance(snap, OpenStackSnapshot) else self.get(snap)
         s = snap if isinstance(snap, OpenStackSnapshot) else self.get(snap)
         if s:
         if s:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -436,9 +437,9 @@ class OpenStackBucketService(BaseBucketService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackBucketService, self).__init__(provider)
         super(OpenStackBucketService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.storage.buckets.get",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _get(self, bucket_id):
+    @dispatch(event="provider.storage.buckets.get",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def get(self, bucket_id):
         """
         """
         Returns a bucket given its ID. Returns ``None`` if the bucket
         Returns a bucket given its ID. Returns ``None`` if the bucket
         does not exist.
         does not exist.
@@ -453,9 +454,9 @@ class OpenStackBucketService(BaseBucketService):
             log.debug("Bucket %s was not found.", bucket_id)
             log.debug("Bucket %s was not found.", bucket_id)
             return None
             return None
 
 
-    @implement(event_pattern="provider.storage.buckets.find",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.storage.buckets.find",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         name = kwargs.pop('name', None)
         name = kwargs.pop('name', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -469,9 +470,9 @@ class OpenStackBucketService(BaseBucketService):
                       if name in c.get("name")]
                       if name in c.get("name")]
         return oshelpers.to_server_paged_list(self.provider, cb_buckets)
         return oshelpers.to_server_paged_list(self.provider, cb_buckets)
 
 
-    @implement(event_pattern="provider.storage.buckets.list",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit, marker):
+    @dispatch(event="provider.storage.buckets.list",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit, marker):
         _, container_list = self.provider.swift.get_account(
         _, container_list = self.provider.swift.get_account(
             limit=oshelpers.os_result_limit(self.provider, limit),
             limit=oshelpers.os_result_limit(self.provider, limit),
             marker=marker)
             marker=marker)
@@ -479,9 +480,9 @@ class OpenStackBucketService(BaseBucketService):
                       for c in container_list]
                       for c in container_list]
         return oshelpers.to_server_paged_list(self.provider, cb_buckets, limit)
         return oshelpers.to_server_paged_list(self.provider, cb_buckets, limit)
 
 
-    @implement(event_pattern="provider.storage.buckets.create",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _create(self, name, location):
+    @dispatch(event="provider.storage.buckets.create",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def create(self, name, location):
         OpenStackBucket.assert_valid_resource_name(name)
         OpenStackBucket.assert_valid_resource_name(name)
         location = location or self.provider.region_name
         location = location or self.provider.region_name
         try:
         try:
@@ -492,9 +493,9 @@ class OpenStackBucketService(BaseBucketService):
             self.provider.swift.put_container(name)
             self.provider.swift.put_container(name)
             return self.get(name)
             return self.get(name)
 
 
-    @implement(event_pattern="provider.storage.buckets.delete",
-               priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, bucket):
+    @dispatch(event="provider.storage.buckets.delete",
+              priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
+    def delete(self, bucket):
         b_id = bucket.id if isinstance(bucket, OpenStackBucket) else bucket
         b_id = bucket.id if isinstance(bucket, OpenStackBucket) else bucket
         self.provider.swift.delete_container(b_id)
         self.provider.swift.delete_container(b_id)
 
 
@@ -676,11 +677,11 @@ class OpenStackInstanceService(BaseInstanceService):
     def create_launch_config(self):
     def create_launch_config(self):
         return BaseLaunchConfig(self.provider)
         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):
+    @dispatch(event="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
         image_id = image.id if isinstance(image, MachineImage) else image
         vm_size = vm_type.id if \
         vm_size = vm_type.id if \
             isinstance(vm_type, VMType) else \
             isinstance(vm_type, VMType) else \
@@ -758,9 +759,9 @@ class OpenStackInstanceService(BaseInstanceService):
             nics=nics)
             nics=nics)
         return OpenStackInstance(self.provider, os_instance)
         return OpenStackInstance(self.provider, os_instance)
 
 
-    @implement(event_pattern="provider.compute.instances.find",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.compute.instances.find",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -778,9 +779,9 @@ class OpenStackInstanceService(BaseInstanceService):
                 marker=None)]
                 marker=None)]
         return oshelpers.to_server_paged_list(self.provider, cb_insts)
         return oshelpers.to_server_paged_list(self.provider, cb_insts)
 
 
-    @implement(event_pattern="provider.compute.instances.list",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.instances.list",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         """
         """
         List all instances.
         List all instances.
         """
         """
@@ -791,9 +792,9 @@ class OpenStackInstanceService(BaseInstanceService):
                 marker=marker)]
                 marker=marker)]
         return oshelpers.to_server_paged_list(self.provider, cb_insts, limit)
         return oshelpers.to_server_paged_list(self.provider, cb_insts, limit)
 
 
-    @implement(event_pattern="provider.compute.instances.get",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _get(self, instance_id):
+    @dispatch(event="provider.compute.instances.get",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def get(self, instance_id):
         """
         """
         Returns an instance given its id.
         Returns an instance given its id.
         """
         """
@@ -804,9 +805,9 @@ class OpenStackInstanceService(BaseInstanceService):
             log.debug("Instance %s was not found.", instance_id)
             log.debug("Instance %s was not found.", instance_id)
             return None
             return None
 
 
-    @implement(event_pattern="provider.compute.instances.delete",
-               priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, inst):
+    @dispatch(event="provider.compute.instances.delete",
+              priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
+    def delete(self, inst):
         ins = inst if isinstance(inst, OpenStackInstance) else self.get(inst)
         ins = inst if isinstance(inst, OpenStackInstance) else self.get(inst)
         if ins:
         if ins:
             # pylint:disable=protected-access
             # pylint:disable=protected-access
@@ -824,9 +825,9 @@ class OpenStackVMTypeService(BaseVMTypeService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackVMTypeService, self).__init__(provider)
         super(OpenStackVMTypeService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.compute.vm_types.list",
-               priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.vm_types.list",
+              priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         cb_itypes = [
         cb_itypes = [
             OpenStackVMType(self.provider, obj)
             OpenStackVMType(self.provider, obj)
             for obj in self.provider.nova.flavors.list(
             for obj in self.provider.nova.flavors.list(
@@ -841,16 +842,16 @@ class OpenStackRegionService(BaseRegionService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackRegionService, self).__init__(provider)
         super(OpenStackRegionService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.compute.regions.get",
-               priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
-    def _get(self, region_id):
+    @dispatch(event="provider.compute.regions.get",
+              priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
+    def get(self, region_id):
         log.debug("Getting OpenStack Region with the id: %s", region_id)
         log.debug("Getting OpenStack Region with the id: %s", region_id)
         region = (r for r in self if r.id == region_id)
         region = (r for r in self if r.id == region_id)
         return next(region, None)
         return next(region, None)
 
 
-    @implement(event_pattern="provider.compute.regions.list",
-               priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.compute.regions.list",
+              priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         # pylint:disable=protected-access
         # pylint:disable=protected-access
         if self.provider._keystone_version == 3:
         if self.provider._keystone_version == 3:
             os_regions = [OpenStackRegion(self.provider, region)
             os_regions = [OpenStackRegion(self.provider, region)
@@ -904,24 +905,24 @@ class OpenStackNetworkService(BaseNetworkService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackNetworkService, self).__init__(provider)
         super(OpenStackNetworkService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.networking.networks.get",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _get(self, network_id):
+    @dispatch(event="provider.networking.networks.get",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def get(self, network_id):
         network = (n for n in self if n.id == network_id)
         network = (n for n in self if n.id == network_id)
         return next(network, None)
         return next(network, None)
 
 
-    @implement(event_pattern="provider.networking.networks.list",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.networking.networks.list",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         networks = [OpenStackNetwork(self.provider, network)
         networks = [OpenStackNetwork(self.provider, network)
                     for network in self.provider.neutron.list_networks()
                     for network in self.provider.neutron.list_networks()
                     .get('networks') if network]
                     .get('networks') if network]
         return ClientPagedResultList(self.provider, networks,
         return ClientPagedResultList(self.provider, networks,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.networks.find",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.networking.networks.find",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         label = kwargs.pop('label', None)
         label = kwargs.pop('label', None)
 
 
         # All kwargs should have been popped at this time.
         # All kwargs should have been popped at this time.
@@ -937,9 +938,9 @@ class OpenStackNetworkService(BaseNetworkService):
                     .get('networks') if network]
                     .get('networks') if network]
         return ClientPagedResultList(self.provider, networks)
         return ClientPagedResultList(self.provider, networks)
 
 
-    @implement(event_pattern="provider.networking.networks.create",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, cidr_block):
+    @dispatch(event="provider.networking.networks.create",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, cidr_block):
         OpenStackNetwork.assert_valid_resource_label(label)
         OpenStackNetwork.assert_valid_resource_label(label)
         net_info = {'name': label or ""}
         net_info = {'name': label or ""}
         network = self.provider.neutron.create_network({'network': net_info})
         network = self.provider.neutron.create_network({'network': net_info})
@@ -948,9 +949,9 @@ class OpenStackNetworkService(BaseNetworkService):
             cb_net.label = label
             cb_net.label = label
         return cb_net
         return cb_net
 
 
-    @implement(event_pattern="provider.networking.networks.delete",
-               priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, net):
+    @dispatch(event="provider.networking.networks.delete",
+              priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
+    def delete(self, net):
         network = net if isinstance(net, OpenStackNetwork) else self.get(net)
         network = net if isinstance(net, OpenStackNetwork) else self.get(net)
         if not network:
         if not network:
             return
             return
@@ -974,15 +975,15 @@ class OpenStackSubnetService(BaseSubnetService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackSubnetService, self).__init__(provider)
         super(OpenStackSubnetService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.networking.subnets.get",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _get(self, subnet_id):
+    @dispatch(event="provider.networking.subnets.get",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def get(self, subnet_id):
         subnet = (s for s in self if s.id == subnet_id)
         subnet = (s for s in self if s.id == subnet_id)
         return next(subnet, None)
         return next(subnet, None)
 
 
-    @implement(event_pattern="provider.networking.subnets.list",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _list(self, network=None, limit=None, marker=None):
+    @dispatch(event="provider.networking.subnets.list",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def list(self, network=None, limit=None, marker=None):
         if network:
         if network:
             network_id = (network.id if isinstance(network, OpenStackNetwork)
             network_id = (network.id if isinstance(network, OpenStackNetwork)
                           else network)
                           else network)
@@ -994,10 +995,11 @@ class OpenStackSubnetService(BaseSubnetService):
         return ClientPagedResultList(self.provider, subnets,
         return ClientPagedResultList(self.provider, subnets,
                                      limit=limit, marker=marker)
                                      limit=limit, marker=marker)
 
 
-    @implement(event_pattern="provider.networking.subnets.create",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network, cidr_block, zone):
+    @dispatch(event="provider.networking.subnets.create",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network, cidr_block, zone):
         """zone param is ignored."""
         """zone param is ignored."""
+        OpenStackSubnet.assert_valid_resource_label(label)
         network_id = (network.id if isinstance(network, OpenStackNetwork)
         network_id = (network.id if isinstance(network, OpenStackNetwork)
                       else network)
                       else network)
         subnet_info = {'name': label, 'network_id': network_id,
         subnet_info = {'name': label, 'network_id': network_id,
@@ -1007,9 +1009,9 @@ class OpenStackSubnetService(BaseSubnetService):
         cb_subnet = OpenStackSubnet(self.provider, subnet)
         cb_subnet = OpenStackSubnet(self.provider, subnet)
         return cb_subnet
         return cb_subnet
 
 
-    @implement(event_pattern="provider.networking.subnets.delete",
-               priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, subnet):
+    @dispatch(event="provider.networking.subnets.delete",
+              priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
+    def delete(self, subnet):
         sn_id = subnet.id if isinstance(subnet, OpenStackSubnet) else subnet
         sn_id = subnet.id if isinstance(subnet, OpenStackSubnet) else subnet
         self.provider.neutron.delete_subnet(sn_id)
         self.provider.neutron.delete_subnet(sn_id)
 
 
@@ -1042,38 +1044,38 @@ class OpenStackRouterService(BaseRouterService):
     def __init__(self, provider):
     def __init__(self, provider):
         super(OpenStackRouterService, self).__init__(provider)
         super(OpenStackRouterService, self).__init__(provider)
 
 
-    @implement(event_pattern="provider.networking.routers.get",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _get(self, router_id):
+    @dispatch(event="provider.networking.routers.get",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def get(self, router_id):
         log.debug("Getting OpenStack Router with the id: %s", router_id)
         log.debug("Getting OpenStack Router with the id: %s", router_id)
         router = self.provider.os_conn.get_router(router_id)
         router = self.provider.os_conn.get_router(router_id)
         return OpenStackRouter(self.provider, router) if router else None
         return OpenStackRouter(self.provider, router) if router else None
 
 
-    @implement(event_pattern="provider.networking.routers.list",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _list(self, limit=None, marker=None):
+    @dispatch(event="provider.networking.routers.list",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def list(self, limit=None, marker=None):
         routers = self.provider.os_conn.list_routers()
         routers = self.provider.os_conn.list_routers()
         os_routers = [OpenStackRouter(self.provider, r) for r in routers]
         os_routers = [OpenStackRouter(self.provider, r) for r in routers]
         return ClientPagedResultList(self.provider, os_routers, limit=limit,
         return ClientPagedResultList(self.provider, os_routers, limit=limit,
                                      marker=marker)
                                      marker=marker)
 
 
-    @implement(event_pattern="provider.networking.routers.find",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _find(self, **kwargs):
+    @dispatch(event="provider.networking.routers.find",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['label']
         filters = ['label']
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         matches = cb_helpers.generic_find(filters, kwargs, obj_list)
         return ClientPagedResultList(self._provider, list(matches))
         return ClientPagedResultList(self._provider, list(matches))
 
 
-    @implement(event_pattern="provider.networking.routers.create",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _create(self, label, network):
+    @dispatch(event="provider.networking.routers.create",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def create(self, label, network):
         """Parameter ``network`` is not used by OpenStack."""
         """Parameter ``network`` is not used by OpenStack."""
         router = self.provider.os_conn.create_router(name=label)
         router = self.provider.os_conn.create_router(name=label)
         return OpenStackRouter(self.provider, router)
         return OpenStackRouter(self.provider, router)
 
 
-    @implement(event_pattern="provider.networking.routers.delete",
-               priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
-    def _delete(self, router):
+    @dispatch(event="provider.networking.routers.delete",
+              priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
+    def delete(self, router):
         r_id = router.id if isinstance(router, OpenStackRouter) else router
         r_id = router.id if isinstance(router, OpenStackRouter) else router
         self.provider.os_conn.delete_router(r_id)
         self.provider.os_conn.delete_router(r_id)

+ 2 - 2
docs/topics/event_system.rst

@@ -116,7 +116,7 @@ getter, from the CloudBridge developer perspective.
         def __init__(self, provider):
         def __init__(self, provider):
             super(MyFirstProviderService, self).__init__(provider)
             super(MyFirstProviderService, self).__init__(provider)
 
 
-        def _get(self, obj_id):
+        def get(self, obj_id):
             # do the getting
             # do the getting
             resource = ...
             resource = ...
             return MyFirstProviderResource(resource)
             return MyFirstProviderResource(resource)
@@ -126,7 +126,7 @@ getter, from the CloudBridge developer perspective.
         def __init__(self, provider):
         def __init__(self, provider):
             super(MySecondProviderService, self).__init__(provider)
             super(MySecondProviderService, self).__init__(provider)
 
 
-        def _get(self, obj_id):
+        def get(self, obj_id):
             # do the getting
             # do the getting
             resource = ...
             resource = ...
             return MySecondProviderResource(resource)
             return MySecondProviderResource(resource)

+ 1 - 1
test/test_security_service.py

@@ -44,7 +44,7 @@ class CloudSecurityServiceTestCase(ProviderTestBase):
 
 
         def cleanup_kp(kp):
         def cleanup_kp(kp):
             if kp:
             if kp:
-                self.provider.security.key_pairs.delete(key_pair=kp.id)
+                self.provider.security.key_pairs.delete(kp.id)
 
 
         def extra_tests(kp):
         def extra_tests(kp):
             # Recreating existing keypair should raise an exception
             # Recreating existing keypair should raise an exception