Browse Source

Merge pull request #177 from CloudVE/middleware3

Middleware3
Nuwan Goonasekera 7 years ago
parent
commit
58e7e334ff

+ 58 - 1
cloudbridge/cloud/base/events.py

@@ -10,6 +10,39 @@ from ..interfaces.exceptions import HandlerException
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 
 
 
 
+def intercept(event_pattern, priority):
+    def deco(f):
+        # Mark function as having an event_handler so we can discover it
+        # The callback cannot be set to f as it is not bound yet and will be
+        # set during auto discovery
+        f.__event_handler = InterceptingEventHandler(
+            event_pattern, priority, None)
+        return f
+    return deco
+
+
+def observe(event_pattern, priority):
+    def deco(f):
+        # Mark function as having an event_handler so we can discover it
+        # The callback cannot be set to f as it is not bound yet and will be
+        # set during auto discovery
+        f.__event_handler = ObservingEventHandler(
+            event_pattern, priority, None)
+        return f
+    return deco
+
+
+def execute(event_pattern, priority):
+    def deco(f):
+        # Mark function as having an event_handler so we can discover it
+        # The callback cannot be set to f as it is not bound yet and will be
+        # set during auto discovery
+        f.__event_handler = ExecutingEventHandler(
+            event_pattern, priority, None)
+        return f
+    return deco
+
+
 class InterceptingEventHandler(EventHandler):
 class InterceptingEventHandler(EventHandler):
 
 
     def __init__(self, event_pattern, priority, callback):
     def __init__(self, event_pattern, priority, callback):
@@ -56,7 +89,10 @@ class InterceptingEventHandler(EventHandler):
         event_args['next_handler'] = next_handler
         event_args['next_handler'] = next_handler
         # callback is responsible for invoking the next_handler and
         # callback is responsible for invoking the next_handler and
         # controlling the result value
         # controlling the result value
-        return self.callback(event_args, *args, **kwargs)
+        result = self.callback(event_args, *args, **kwargs)
+        # Remove handler specific callback info
+        event_args.pop('next_handler', None)
+        return result
 
 
     def unsubscribe(self):
     def unsubscribe(self):
         if self.dispatcher:
         if self.dispatcher:
@@ -82,6 +118,22 @@ class ObservingEventHandler(InterceptingEventHandler):
             return None
             return None
 
 
 
 
+class ExecutingEventHandler(InterceptingEventHandler):
+
+    def __init__(self, event_pattern, priority, callback):
+        super(ExecutingEventHandler, self).__init__(event_pattern, priority,
+                                                    callback)
+
+    def invoke(self, event_args, *args, **kwargs):
+        result = self.callback(*args, **kwargs)
+        next_handler = event_args.get('next_handler')
+        if next_handler:
+            event_args['result'] = result
+            next_handler.invoke(event_args, *args, **kwargs)
+            event_args.pop['result']
+        return result
+
+
 class SimpleEventDispatcher(EventDispatcher):
 class SimpleEventDispatcher(EventDispatcher):
 
 
     def __init__(self):
     def __init__(self):
@@ -155,6 +207,11 @@ class SimpleEventDispatcher(EventDispatcher):
         self.subscribe(handler)
         self.subscribe(handler)
         return handler
         return handler
 
 
+    def execute(self, event_pattern, priority, callback):
+        handler = ExecutingEventHandler(event_pattern, priority, callback)
+        self.subscribe(handler)
+        return handler
+
     def emit(self, sender, event, *args, **kwargs):
     def emit(self, sender, event, *args, **kwargs):
         handlers = self.get_handlers_for_event(event)
         handlers = self.get_handlers_for_event(event)
 
 

+ 2 - 24
cloudbridge/cloud/base/middleware.py

@@ -4,8 +4,8 @@ import sys
 
 
 import six
 import six
 
 
-from ..base.events import InterceptingEventHandler
-from ..base.events import ObservingEventHandler
+from ..base.events import intercept
+from ..base.events import observe
 from ..interfaces.exceptions import CloudBridgeBaseException
 from ..interfaces.exceptions import CloudBridgeBaseException
 from ..interfaces.middleware import Middleware
 from ..interfaces.middleware import Middleware
 from ..interfaces.middleware import MiddlewareManager
 from ..interfaces.middleware import MiddlewareManager
@@ -13,28 +13,6 @@ from ..interfaces.middleware import MiddlewareManager
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 
 
 
 
-def intercept(event_pattern, priority):
-    def deco(f):
-        # Mark function as having an event_handler so we can discover it
-        # The callback cannot be set to f as it is not bound yet and will be
-        # set during auto discovery
-        f.__event_handler = InterceptingEventHandler(
-            event_pattern, priority, None)
-        return f
-    return deco
-
-
-def observe(event_pattern, priority):
-    def deco(f):
-        # Mark function as having an event_handler so we can discover it
-        # The callback cannot be set to f as it is not bound yet and will be
-        # set during auto discovery
-        f.__event_handler = ObservingEventHandler(
-            event_pattern, priority, None)
-        return f
-    return deco
-
-
 class SimpleMiddlewareManager(MiddlewareManager):
 class SimpleMiddlewareManager(MiddlewareManager):
 
 
     def __init__(self, event_manager):
     def __init__(self, event_manager):

+ 60 - 65
cloudbridge/cloud/base/services.py

@@ -4,6 +4,7 @@ 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.events import execute
 from cloudbridge.cloud.base.middleware import observe
 from cloudbridge.cloud.base.middleware import observe
 from cloudbridge.cloud.base.resources import BaseBucket
 from cloudbridge.cloud.base.resources import BaseBucket
 from cloudbridge.cloud.base.resources import BaseNetwork
 from cloudbridge.cloud.base.resources import BaseNetwork
@@ -40,25 +41,34 @@ log = logging.getLogger(__name__)
 
 
 class BaseCloudService(CloudService):
 class BaseCloudService(CloudService):
 
 
+    STANDARD_EVENT_PRIORITY = 2500
+
     def __init__(self, provider):
     def __init__(self, provider):
         self._provider = provider
         self._provider = provider
-        self._service_event_pattern = "provider"
+        # discover and register all middleware
+        provider.middleware.add(self)
 
 
     @property
     @property
     def provider(self):
     def provider(self):
         return self._provider
         return self._provider
 
 
+    def emit(self, sender, event, *args, **kwargs):
+        return self._provider.events.emit(sender, event, *args, **kwargs)
+
     def _generate_event_pattern(self, func_name):
     def _generate_event_pattern(self, func_name):
         return ".".join((self._service_event_pattern, func_name))
         return ".".join((self._service_event_pattern, func_name))
 
 
-    def observe(self, func_name, priority, callback):
+    def observe_function(self, func_name, priority, callback):
         event_pattern = self._generate_event_pattern(func_name)
         event_pattern = self._generate_event_pattern(func_name)
         self.provider.events.observe(event_pattern, priority, callback)
         self.provider.events.observe(event_pattern, priority, callback)
 
 
-    def call(self, func_name, priority, callback, **kwargs):
+    def intercept_function(self, func_name, priority, callback):
         event_pattern = self._generate_event_pattern(func_name)
         event_pattern = self._generate_event_pattern(func_name)
-        return self.provider.events.call(event_pattern, priority, callback,
-                                         **kwargs)
+        self.provider.events.intercept(event_pattern, priority, callback)
+
+    def execute_function(self, func_name, priority, callback):
+        event_pattern = self._generate_event_pattern(func_name)
+        self.provider.events.execute(event_pattern, priority, callback)
 
 
 
 
 class BaseSecurityService(SecurityService, BaseCloudService):
 class BaseSecurityService(SecurityService, BaseCloudService):
@@ -147,68 +157,48 @@ class BaseBucketService(
         self._service_event_pattern += ".buckets"
         self._service_event_pattern += ".buckets"
 
 
     @observe(event_pattern="provider.storage.buckets.get", priority=2000)
     @observe(event_pattern="provider.storage.buckets.get", priority=2000)
-    def _get_pre_log(self, bucket_id):
+    def _pre_log_get(self, event_args, bucket_id):
         log.debug("Getting {} bucket with the id: {}".format(
         log.debug("Getting {} bucket with the id: {}".format(
             self.provider.name, bucket_id))
             self.provider.name, bucket_id))
 
 
     @observe(event_pattern="provider.storage.buckets.get", priority=3000)
     @observe(event_pattern="provider.storage.buckets.get", priority=3000)
-    def _get_post_log(self, callback_result, bucket_id):
+    def _post_log_get(self, event_args, bucket_id):
+        log.debug("Returned bucket obj: {}".format(event_args.get('result')))
+
+    @observe(event_pattern="provider.storage.buckets.find", priority=2000)
+    def _pre_log_find(self, *args, **kwargs):
+        log.debug("Finding {} buckets with the following arguments: {}"
+                  .format(self.provider.name, kwargs))
+
+    @observe(event_pattern="provider.storage.buckets.find", priority=3000)
+    def _post_log_find(self, event_args, *args, **kwargs):
+        log.debug("Returned bucket obj: {}".format(event_args.get('result')))
+
+    def _list_pre_log(self, limit, marker):
+        message = "Listing {} buckets".format(self.provider.name)
+        if limit:
+            message += " with limit: {}".format(limit)
+        if marker:
+            message += " with marker: {}".format(marker)
+        log.debug(message)
+
+    def _list_post_log(self, callback_result, limit, marker):
+        log.debug("Returned bucket objects: {}".format(callback_result))
+
+    def _create_pre_log(self, name, location):
+        message = "Creating {} bucket with name '{}'".format(
+            self.provider.name, name)
+        if location:
+            message += " in location: {}".format(location)
+        log.debug(message)
+
+    def _create_post_log(self, callback_result, name, location):
         log.debug("Returned bucket object: {}".format(callback_result))
         log.debug("Returned bucket object: {}".format(callback_result))
 
 
-    def _init_find(self):
-        def _find_pre_log(**kwargs):
-            log.debug("Finding {} buckets with the following arguments: {}"
-                      .format(self.provider.name, kwargs))
-
-        def _find_post_log(callback_result, **kwargs):
-            log.debug("Returned bucket objects: {}".format(callback_result))
-
-        self.observe("find", 2000, _find_pre_log)
-        self.observe("find", 3000, _find_post_log)
-        self.mark_initialized("find")
-
-    def _init_list(self):
-            def _list_pre_log(limit, marker):
-                message = "Listing {} buckets".format(self.provider.name)
-                if limit:
-                    message += " with limit: {}".format(limit)
-                if marker:
-                    message += " with marker: {}".format(marker)
-                log.debug(message)
-
-            def _list_post_log(callback_result, limit, marker):
-                log.debug(
-                    "Returned bucket objects: {}".format(callback_result))
-
-            self.observe("list", 2000, _list_pre_log)
-            self.observe("list", 3000, _list_post_log)
-            self.mark_initialized("list")
-
-    def _init_create(self):
-        def _create_pre_log(name, location):
-            message = "Creating {} bucket with name '{}'".format(
-                self.provider.name, name)
-            if location:
-                message += " in location: {}".format(location)
-            log.debug(message)
-
-        def _create_post_log(callback_result, name, location):
-            log.debug("Returned bucket object: {}".format(callback_result))
-
-        self.observe("create", 2000, _create_pre_log)
-        self.observe("create", 3000, _create_post_log)
-        self.mark_initialized("create")
-
-    def get(self, bucket_id):
-        """
-        Returns a bucket given its ID. Returns ``None`` if the bucket
-        does not exist.
-        """
-        return self.call("get", priority=2500, callback=self._get,
-                         bucket_id=bucket_id)
-
     # 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
+    @execute(event_pattern="provider.storage.buckets.find",
+             priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
     def _find(self, **kwargs):
     def _find(self, **kwargs):
         obj_list = self
         obj_list = self
         filters = ['name']
         filters = ['name']
@@ -223,18 +213,24 @@ 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.
+        """
+        return self.emit(self, "provider.storage.buckets.get", bucket_id)
+
     def find(self, **kwargs):
     def find(self, **kwargs):
         """
         """
         Returns a list of buckets filtered by the given keyword arguments.
         Returns a list of buckets filtered by the given keyword arguments.
         """
         """
-        return self.call("find", priority=2500, callback=self._find,
-                         **kwargs)
+        return self.emit(self, "provider.storage.buckets.find", **kwargs)
 
 
     def list(self, limit=None, marker=None):
     def list(self, limit=None, marker=None):
         """
         """
         List all buckets.
         List all buckets.
         """
         """
-        return self.call("list", priority=2500, callback=self._list,
+        return self.emit(self, "provider.storage.buckets.list",
                          limit=limit, marker=marker)
                          limit=limit, marker=marker)
 
 
     def create(self, name, location=None):
     def create(self, name, location=None):
@@ -242,9 +238,8 @@ class BaseBucketService(
         Create a new bucket.
         Create a new bucket.
         """
         """
         BaseBucket.assert_valid_resource_name(name)
         BaseBucket.assert_valid_resource_name(name)
-        location = location or self.provider.region_name
-        return self.call("create", priority=2500, callback=self._create,
-                         name=name, location=location)
+        return self.emit(self, "provider.storage.buckets.create",
+                         name, location=location)
 
 
 
 
 class BaseBucketObjectService(
 class BaseBucketObjectService(

+ 2 - 1
cloudbridge/cloud/interfaces/events.py

@@ -1,4 +1,5 @@
-from abc import ABCMeta, abstractmethod
+from abc import ABCMeta
+from abc import abstractmethod
 from abc import abstractproperty
 from abc import abstractproperty
 
 
 
 

+ 2 - 1
cloudbridge/cloud/interfaces/middleware.py

@@ -1,4 +1,5 @@
-from abc import ABCMeta, abstractmethod
+from abc import ABCMeta
+from abc import abstractmethod
 
 
 
 
 class Middleware(object):
 class Middleware(object):

+ 3 - 1
cloudbridge/cloud/interfaces/provider.py

@@ -1,7 +1,9 @@
 """
 """
 Specification for a provider interface
 Specification for a provider interface
 """
 """
-from abc import ABCMeta, abstractmethod, abstractproperty
+from abc import ABCMeta
+from abc import abstractmethod
+from abc import abstractproperty
 
 
 
 
 class CloudProvider(object):
 class CloudProvider(object):

+ 3 - 1
cloudbridge/cloud/interfaces/resources.py

@@ -1,7 +1,9 @@
 """
 """
 Specifications for data objects exposed through a ``provider`` or ``service``.
 Specifications for data objects exposed through a ``provider`` or ``service``.
 """
 """
-from abc import ABCMeta, abstractmethod, abstractproperty
+from abc import ABCMeta
+from abc import abstractmethod
+from abc import abstractproperty
 from enum import Enum
 from enum import Enum
 
 
 
 

+ 3 - 1
cloudbridge/cloud/interfaces/services.py

@@ -1,7 +1,9 @@
 """
 """
 Specifications for services available through a provider
 Specifications for services available through a provider
 """
 """
-from abc import ABCMeta, abstractmethod, abstractproperty
+from abc import ABCMeta
+from abc import abstractmethod
+from abc import abstractproperty
 
 
 from cloudbridge.cloud.interfaces.resources import PageableObjectMixin
 from cloudbridge.cloud.interfaces.resources import PageableObjectMixin
 
 

+ 12 - 2
cloudbridge/cloud/providers/aws/services.py

@@ -10,6 +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.events import execute
 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
@@ -28,8 +29,9 @@ from cloudbridge.cloud.base.services import BaseSubnetService
 from cloudbridge.cloud.base.services import BaseVMFirewallService
 from cloudbridge.cloud.base.services import BaseVMFirewallService
 from cloudbridge.cloud.base.services import BaseVMTypeService
 from cloudbridge.cloud.base.services import BaseVMTypeService
 from cloudbridge.cloud.base.services import BaseVolumeService
 from cloudbridge.cloud.base.services import BaseVolumeService
-from cloudbridge.cloud.interfaces.exceptions \
-    import DuplicateResourceException, InvalidConfigurationException
+from cloudbridge.cloud.interfaces.exceptions import DuplicateResourceException
+from cloudbridge.cloud.interfaces.exceptions import \
+    InvalidConfigurationException
 from cloudbridge.cloud.interfaces.resources import KeyPair
 from cloudbridge.cloud.interfaces.resources import KeyPair
 from cloudbridge.cloud.interfaces.resources import MachineImage
 from cloudbridge.cloud.interfaces.resources import MachineImage
 from cloudbridge.cloud.interfaces.resources import Network
 from cloudbridge.cloud.interfaces.resources import Network
@@ -307,6 +309,8 @@ class AWSBucketService(BaseBucketService):
                                  cb_resource=AWSBucket,
                                  cb_resource=AWSBucket,
                                  boto_collection_name='buckets')
                                  boto_collection_name='buckets')
 
 
+    @execute(event_pattern="provider.storage.buckets.get",
+             priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
     def _get(self, bucket_id):
     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
@@ -335,10 +339,16 @@ 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
 
 
+    @execute(event_pattern="provider.storage.buckets.list",
+             priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
     def _list(self, limit, marker):
     def _list(self, limit, marker):
         return self.svc.list(limit=limit, marker=marker)
         return self.svc.list(limit=limit, marker=marker)
 
 
+    @execute(event_pattern="provider.storage.buckets.create",
+             priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
     def _create(self, name, location):
     def _create(self, name, location):
+        AWSBucket.assert_valid_resource_name(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
         # LocationConstraint results in an InvalidLocationConstraint.
         # LocationConstraint results in an InvalidLocationConstraint.
         # Therefore, it must be special-cased and omitted altogether.
         # Therefore, it must be special-cased and omitted altogether.

+ 4 - 3
cloudbridge/cloud/providers/azure/azure_client.py

@@ -19,9 +19,10 @@ from msrestazure.azure_exceptions import CloudError
 
 
 import tenacity
 import tenacity
 
 
-from cloudbridge.cloud.interfaces.exceptions import \
-    DuplicateResourceException, InvalidLabelException, \
-    ProviderConnectionException, WaitStateException
+from cloudbridge.cloud.interfaces.exceptions import DuplicateResourceException
+from cloudbridge.cloud.interfaces.exceptions import InvalidLabelException
+from cloudbridge.cloud.interfaces.exceptions import ProviderConnectionException
+from cloudbridge.cloud.interfaces.exceptions import WaitStateException
 
 
 from . import helpers as azure_helpers
 from . import helpers as azure_helpers
 
 

+ 4 - 3
cloudbridge/cloud/providers/azure/provider.py

@@ -12,9 +12,10 @@ from cloudbridge.cloud.base import BaseCloudProvider
 from cloudbridge.cloud.base.helpers import get_env
 from cloudbridge.cloud.base.helpers import get_env
 from cloudbridge.cloud.interfaces.exceptions import ProviderConnectionException
 from cloudbridge.cloud.interfaces.exceptions import ProviderConnectionException
 from cloudbridge.cloud.providers.azure.azure_client import AzureClient
 from cloudbridge.cloud.providers.azure.azure_client import AzureClient
-from cloudbridge.cloud.providers.azure.services \
-    import AzureComputeService, AzureNetworkingService, \
-    AzureSecurityService, AzureStorageService
+from cloudbridge.cloud.providers.azure.services import AzureComputeService
+from cloudbridge.cloud.providers.azure.services import AzureNetworkingService
+from cloudbridge.cloud.providers.azure.services import AzureSecurityService
+from cloudbridge.cloud.providers.azure.services import AzureStorageService
 
 
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 
 

+ 33 - 11
cloudbridge/cloud/providers/azure/resources.py

@@ -13,17 +13,39 @@ from msrestazure.azure_exceptions import CloudError
 
 
 import pysftp
 import pysftp
 
 
-from cloudbridge.cloud.base.resources import BaseAttachmentInfo, \
-    BaseBucket, BaseBucketContainer, BaseBucketObject, BaseFloatingIP, \
-    BaseFloatingIPContainer, BaseGatewayContainer, BaseInstance, \
-    BaseInternetGateway, BaseKeyPair, BaseLaunchConfig, \
-    BaseMachineImage, BaseNetwork, BasePlacementZone, BaseRegion, BaseRouter, \
-    BaseSnapshot, BaseSubnet, BaseVMFirewall, BaseVMFirewallRule, \
-    BaseVMFirewallRuleContainer, BaseVMType, BaseVolume, ClientPagedResultList
-from cloudbridge.cloud.interfaces import InstanceState, VolumeState
-from cloudbridge.cloud.interfaces.resources import Instance, \
-    MachineImageState, NetworkState, RouterState, \
-    SnapshotState, SubnetState, TrafficDirection
+from cloudbridge.cloud.base.resources import BaseAttachmentInfo
+from cloudbridge.cloud.base.resources import BaseBucket
+from cloudbridge.cloud.base.resources import BaseBucketContainer
+from cloudbridge.cloud.base.resources import BaseBucketObject
+from cloudbridge.cloud.base.resources import BaseFloatingIP
+from cloudbridge.cloud.base.resources import BaseFloatingIPContainer
+from cloudbridge.cloud.base.resources import BaseGatewayContainer
+from cloudbridge.cloud.base.resources import BaseInstance
+from cloudbridge.cloud.base.resources import BaseInternetGateway
+from cloudbridge.cloud.base.resources import BaseKeyPair
+from cloudbridge.cloud.base.resources import BaseLaunchConfig
+from cloudbridge.cloud.base.resources import BaseMachineImage
+from cloudbridge.cloud.base.resources import BaseNetwork
+from cloudbridge.cloud.base.resources import BasePlacementZone
+from cloudbridge.cloud.base.resources import BaseRegion
+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 BaseVMFirewall
+from cloudbridge.cloud.base.resources import BaseVMFirewallRule
+from cloudbridge.cloud.base.resources import BaseVMFirewallRuleContainer
+from cloudbridge.cloud.base.resources import BaseVMType
+from cloudbridge.cloud.base.resources import BaseVolume
+from cloudbridge.cloud.base.resources import ClientPagedResultList
+from cloudbridge.cloud.interfaces import InstanceState
+from cloudbridge.cloud.interfaces import VolumeState
+from cloudbridge.cloud.interfaces.resources import Instance
+from cloudbridge.cloud.interfaces.resources import MachineImageState
+from cloudbridge.cloud.interfaces.resources import NetworkState
+from cloudbridge.cloud.interfaces.resources import RouterState
+from cloudbridge.cloud.interfaces.resources import SnapshotState
+from cloudbridge.cloud.interfaces.resources import SubnetState
+from cloudbridge.cloud.interfaces.resources import TrafficDirection
 
 
 from . import helpers as azure_helpers
 from . import helpers as azure_helpers
 
 

+ 45 - 19
cloudbridge/cloud/providers/azure/services.py

@@ -8,25 +8,50 @@ 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.resources import ClientPagedResultList, \
-    ServerPagedResultList
-from cloudbridge.cloud.base.services import BaseBucketObjectService, \
-    BaseBucketService, BaseComputeService, \
-    BaseImageService, BaseInstanceService, BaseKeyPairService, \
-    BaseNetworkService, BaseNetworkingService, BaseRegionService, \
-    BaseRouterService, BaseSecurityService, BaseSnapshotService, \
-    BaseStorageService, BaseSubnetService, BaseVMFirewallService, \
-    BaseVMTypeService, BaseVolumeService
-from cloudbridge.cloud.interfaces.exceptions import \
-    DuplicateResourceException, InvalidValueException
-from cloudbridge.cloud.interfaces.resources import MachineImage, \
-    Network, PlacementZone, Snapshot, Subnet, VMFirewall, VMType, Volume
-
-from .resources import AzureBucket, AzureBucketObject, \
-    AzureInstance, AzureKeyPair, \
-    AzureLaunchConfig, AzureMachineImage, AzureNetwork, \
-    AzureRegion, AzureRouter, AzureSnapshot, AzureSubnet, \
-    AzureVMFirewall, AzureVMType, AzureVolume
+from cloudbridge.cloud.base.resources import ClientPagedResultList
+from cloudbridge.cloud.base.resources import ServerPagedResultList
+from cloudbridge.cloud.base.services import BaseBucketObjectService
+from cloudbridge.cloud.base.services import BaseBucketService
+from cloudbridge.cloud.base.services import BaseComputeService
+from cloudbridge.cloud.base.services import BaseImageService
+from cloudbridge.cloud.base.services import BaseInstanceService
+from cloudbridge.cloud.base.services import BaseKeyPairService
+from cloudbridge.cloud.base.services import BaseNetworkService
+from cloudbridge.cloud.base.services import BaseNetworkingService
+from cloudbridge.cloud.base.services import BaseRegionService
+from cloudbridge.cloud.base.services import BaseRouterService
+from cloudbridge.cloud.base.services import BaseSecurityService
+from cloudbridge.cloud.base.services import BaseSnapshotService
+from cloudbridge.cloud.base.services import BaseStorageService
+from cloudbridge.cloud.base.services import BaseSubnetService
+from cloudbridge.cloud.base.services import BaseVMFirewallService
+from cloudbridge.cloud.base.services import BaseVMTypeService
+from cloudbridge.cloud.base.services import BaseVolumeService
+from cloudbridge.cloud.interfaces.exceptions import DuplicateResourceException
+from cloudbridge.cloud.interfaces.exceptions import InvalidValueException
+from cloudbridge.cloud.interfaces.resources import MachineImage
+from cloudbridge.cloud.interfaces.resources import Network
+from cloudbridge.cloud.interfaces.resources import PlacementZone
+from cloudbridge.cloud.interfaces.resources import Snapshot
+from cloudbridge.cloud.interfaces.resources import Subnet
+from cloudbridge.cloud.interfaces.resources import VMFirewall
+from cloudbridge.cloud.interfaces.resources import VMType
+from cloudbridge.cloud.interfaces.resources import Volume
+
+from .resources import AzureBucket
+from .resources import AzureBucketObject
+from .resources import AzureInstance
+from .resources import AzureKeyPair
+from .resources import AzureLaunchConfig
+from .resources import AzureMachineImage
+from .resources import AzureNetwork
+from .resources import AzureRegion
+from .resources import AzureRouter
+from .resources import AzureSnapshot
+from .resources import AzureSubnet
+from .resources import AzureVMFirewall
+from .resources import AzureVMType
+from .resources import AzureVolume
 
 
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 
 
@@ -392,6 +417,7 @@ class AzureBucketService(BaseBucketService):
         """
         """
         Create a new bucket.
         Create a new bucket.
         """
         """
+        AzureBucket.assert_valid_resource_name(name)
         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)
 
 

+ 2 - 1
cloudbridge/cloud/providers/openstack/resources.py

@@ -23,7 +23,8 @@ from openstack.exceptions import NotFoundException
 from openstack.exceptions import ResourceNotFound
 from openstack.exceptions import ResourceNotFound
 
 
 import swiftclient
 import swiftclient
-from swiftclient.service import SwiftService, SwiftUploadObject
+from swiftclient.service import SwiftService
+from swiftclient.service import SwiftUploadObject
 from swiftclient.utils import generate_temp_url
 from swiftclient.utils import generate_temp_url
 
 
 import cloudbridge.cloud.base.helpers as cb_helpers
 import cloudbridge.cloud.base.helpers as cb_helpers

+ 2 - 0
cloudbridge/cloud/providers/openstack/services.py

@@ -447,6 +447,8 @@ class OpenStackBucketService(BaseBucketService):
         return oshelpers.to_server_paged_list(self.provider, cb_buckets, limit)
         return oshelpers.to_server_paged_list(self.provider, cb_buckets, limit)
 
 
     def _create(self, name, location):
     def _create(self, name, location):
+        OpenStackBucket.assert_valid_resource_name(name)
+        location = location or self.provider.region_name
         try:
         try:
             self.provider.swift.head_container(name)
             self.provider.swift.head_container(name)
             raise DuplicateResourceException(
             raise DuplicateResourceException(

+ 11 - 10
test/test_security_service.py

@@ -24,15 +24,16 @@ class CloudSecurityServiceTestCase(ProviderTestBase):
                                                   "provider.security",
                                                   "provider.security",
                                                   self.provider.security.
                                                   self.provider.security.
                                                   _service_event_pattern))
                                                   _service_event_pattern))
-        self.assertEqual(self.provider.security.key_pairs.
-                         _service_event_pattern,
-                         "provider.security.key_pairs",
-                         "Event pattern for {} service should be '{}', "
-                         "but found '{}'.".format("key_pairs",
-                                                  "provider.security.key_pairs",
-                                                  self.provider.security.
-                                                  key_pairs.
-                                                  _service_event_pattern))
+        self.assertEqual(
+            self.provider.security.key_pairs.
+            _service_event_pattern,
+            "provider.security.key_pairs",
+            "Event pattern for {} service should be '{}', "
+            "but found '{}'.".format("key_pairs",
+                                     "provider.security.key_pairs",
+                                     self.provider.security.
+                                     key_pairs.
+                                     _service_event_pattern))
         self.assertEqual(
         self.assertEqual(
             self.provider.security.vm_firewalls._service_event_pattern,
             self.provider.security.vm_firewalls._service_event_pattern,
             "provider.security.vm_firewalls",
             "provider.security.vm_firewalls",
@@ -40,7 +41,7 @@ class CloudSecurityServiceTestCase(ProviderTestBase):
             "but found '{}'.".format("vm_firewalls",
             "but found '{}'.".format("vm_firewalls",
                                      "provider.security.vm_firewalls",
                                      "provider.security.vm_firewalls",
                                      self.provider.security.vm_firewalls.
                                      self.provider.security.vm_firewalls.
-                                     _service_event_pattern))    
+                                     _service_event_pattern))
 
 
     @helpers.skipIfNoService(['security.key_pairs'])
     @helpers.skipIfNoService(['security.key_pairs'])
     def test_crud_key_pair_service(self):
     def test_crud_key_pair_service(self):