Răsfoiți Sursa

Added abstract base classes

nuwan_ag 10 ani în urmă
părinte
comite
84f660ad64

+ 5 - 0
cloudbridge/providers/aws/impl.py

@@ -49,6 +49,11 @@ class AWSCloudProviderV1(BaseCloudProvider):
         self._block_store = AWSBlockStoreService(self)
         self._block_store = AWSBlockStoreService(self)
         self._object_store = AWSObjectStoreService(self)
         self._object_store = AWSObjectStoreService(self)
 
 
+    @property
+    def account(self):
+        raise NotImplementedError(
+            'account not implemented by this provider')
+
     @property
     @property
     def compute(self):
     def compute(self):
         return self._compute
         return self._compute

+ 10 - 0
cloudbridge/providers/aws/resources.py

@@ -463,6 +463,16 @@ class AWSSnapshot(BaseSnapshot):
         """
         """
         self._snapshot.delete()
         self._snapshot.delete()
 
 
+    def create_volume(self, placement, size=None, volume_type=None, iops=None):
+        raise NotImplementedError(
+            'create_volume not implemented by this provider')
+
+    def share(self, user_ids=None):
+        raise NotImplementedError('share not implemented by this provider')
+
+    def unshare(self, user_ids=None):
+        raise NotImplementedError('share not implemented by this provider')
+
     def __repr__(self):
     def __repr__(self):
         return "<CB-AWSSnapshot: {0} ({1})>".format(self.snapshot_id,
         return "<CB-AWSSnapshot: {0} ({1})>".format(self.snapshot_id,
                                                     self.name)
                                                     self.name)

+ 85 - 78
cloudbridge/providers/aws/services.py

@@ -4,21 +4,22 @@ Services implemented by the AWS provider.
 from boto.exception import EC2ResponseError
 from boto.exception import EC2ResponseError
 import requests
 import requests
 
 
-from cloudbridge.providers.interfaces import BlockStoreService
-from cloudbridge.providers.interfaces import ComputeService
-from cloudbridge.providers.interfaces import ImageService
+from cloudbridge.providers.base import BaseBlockStoreService
+from cloudbridge.providers.base import BaseComputeService
+from cloudbridge.providers.base import BaseImageService
+from cloudbridge.providers.base import BaseInstanceTypesService
+from cloudbridge.providers.base import BaseKeyPairService
+from cloudbridge.providers.base import BaseObjectStoreService
+from cloudbridge.providers.base import BaseSecurityGroupService
+from cloudbridge.providers.base import BaseSecurityService
+from cloudbridge.providers.base import BaseSnapshotService
+from cloudbridge.providers.base import BaseVolumeService
+
 from cloudbridge.providers.interfaces import InstanceType
 from cloudbridge.providers.interfaces import InstanceType
-from cloudbridge.providers.interfaces import InstanceTypesService
 from cloudbridge.providers.interfaces import KeyPair
 from cloudbridge.providers.interfaces import KeyPair
-from cloudbridge.providers.interfaces import KeyPairService
 from cloudbridge.providers.interfaces import MachineImage
 from cloudbridge.providers.interfaces import MachineImage
-from cloudbridge.providers.interfaces import ObjectStoreService
 from cloudbridge.providers.interfaces import PlacementZone
 from cloudbridge.providers.interfaces import PlacementZone
 from cloudbridge.providers.interfaces import SecurityGroup
 from cloudbridge.providers.interfaces import SecurityGroup
-from cloudbridge.providers.interfaces import SecurityGroupService
-from cloudbridge.providers.interfaces import SecurityService
-from cloudbridge.providers.interfaces import SnapshotService
-from cloudbridge.providers.interfaces import VolumeService
 
 
 from .resources import AWSContainer
 from .resources import AWSContainer
 from .resources import AWSInstance
 from .resources import AWSInstance
@@ -30,10 +31,10 @@ from .resources import AWSSnapshot
 from .resources import AWSVolume
 from .resources import AWSVolume
 
 
 
 
-class AWSSecurityService(SecurityService):
+class AWSSecurityService(BaseSecurityService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSSecurityService, self).__init__(provider)
 
 
         # Initialize provider services
         # Initialize provider services
         self._key_pairs = AWSKeyPairService(provider)
         self._key_pairs = AWSKeyPairService(provider)
@@ -60,10 +61,10 @@ class AWSSecurityService(SecurityService):
         return self._security_groups
         return self._security_groups
 
 
 
 
-class AWSKeyPairService(KeyPairService):
+class AWSKeyPairService(BaseKeyPairService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSKeyPairService, self).__init__(provider)
 
 
     def list(self):
     def list(self):
         """
         """
@@ -72,8 +73,8 @@ class AWSKeyPairService(KeyPairService):
         :rtype: ``list`` of :class:`.KeyPair`
         :rtype: ``list`` of :class:`.KeyPair`
         :return:  list of KeyPair objects
         :return:  list of KeyPair objects
         """
         """
-        key_pairs = self._provider.ec2_conn.get_all_key_pairs()
-        return [AWSKeyPair(self._provider, kp) for kp in key_pairs]
+        key_pairs = self.provider.ec2_conn.get_all_key_pairs()
+        return [AWSKeyPair(self.provider, kp) for kp in key_pairs]
 
 
     def create(self, name):
     def create(self, name):
         """
         """
@@ -85,9 +86,9 @@ class AWSKeyPairService(KeyPairService):
         :rtype: ``object`` of :class:`.KeyPair`
         :rtype: ``object`` of :class:`.KeyPair`
         :return:  A keypair instance or None if one was not be created.
         :return:  A keypair instance or None if one was not be created.
         """
         """
-        kp = self._provider.ec2_conn.create_key_pair(name)
+        kp = self.provider.ec2_conn.create_key_pair(name)
         if kp:
         if kp:
-            return AWSKeyPair(self._provider, kp)
+            return AWSKeyPair(self.provider, kp)
         return None
         return None
 
 
     def delete(self, name):
     def delete(self, name):
@@ -102,17 +103,17 @@ class AWSKeyPairService(KeyPairService):
                   that this implies that the key may not have been deleted by
                   that this implies that the key may not have been deleted by
                   this method but instead has not existed in the first place.
                   this method but instead has not existed in the first place.
         """
         """
-        for kp in self._provider.ec2_conn.get_all_key_pairs():
+        for kp in self.provider.ec2_conn.get_all_key_pairs():
             if kp.name == name:
             if kp.name == name:
                 kp.delete()
                 kp.delete()
                 return True
                 return True
         return True
         return True
 
 
 
 
-class AWSSecurityGroupService(SecurityGroupService):
+class AWSSecurityGroupService(BaseSecurityGroupService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSSecurityGroupService, self).__init__(provider)
 
 
     def list(self):
     def list(self):
         """
         """
@@ -121,8 +122,8 @@ class AWSSecurityGroupService(SecurityGroupService):
         :rtype: ``list`` of :class:`.SecurityGroup`
         :rtype: ``list`` of :class:`.SecurityGroup`
         :return:  list of SecurityGroup objects
         :return:  list of SecurityGroup objects
         """
         """
-        security_groups = self._provider.ec2_conn.get_all_security_groups()
-        return [AWSSecurityGroup(self._provider, sg) for sg in security_groups]
+        security_groups = self.provider.ec2_conn.get_all_security_groups()
+        return [AWSSecurityGroup(self.provider, sg) for sg in security_groups]
 
 
     def create(self, name, description):
     def create(self, name, description):
         """
         """
@@ -137,9 +138,9 @@ class AWSSecurityGroupService(SecurityGroupService):
         :rtype: ``object`` of :class:`.SecurityGroup`
         :rtype: ``object`` of :class:`.SecurityGroup`
         :return:  A SecurityGroup instance or ``None`` if one was not created.
         :return:  A SecurityGroup instance or ``None`` if one was not created.
         """
         """
-        sg = self._provider.ec2_conn.create_security_group(name, description)
+        sg = self.provider.ec2_conn.create_security_group(name, description)
         if sg:
         if sg:
-            return AWSSecurityGroup(self._provider, sg)
+            return AWSSecurityGroup(self.provider, sg)
         return None
         return None
 
 
     def get(self, group_names=None, group_ids=None):
     def get(self, group_names=None, group_ids=None):
@@ -161,11 +162,11 @@ class AWSSecurityGroupService(SecurityGroupService):
         found.
         found.
         """
         """
         try:
         try:
-            security_groups = self._provider.ec2_conn.get_all_security_groups(
+            security_groups = self.provider.ec2_conn.get_all_security_groups(
                 groupnames=group_names, group_ids=group_ids)
                 groupnames=group_names, group_ids=group_ids)
         except EC2ResponseError:
         except EC2ResponseError:
             security_groups = []
             security_groups = []
-        return [AWSSecurityGroup(self._provider, sg) for sg in security_groups]
+        return [AWSSecurityGroup(self.provider, sg) for sg in security_groups]
 
 
     def delete(self, group_id):
     def delete(self, group_id):
         """
         """
@@ -181,7 +182,7 @@ class AWSSecurityGroupService(SecurityGroupService):
                   the first place.
                   the first place.
         """
         """
         try:
         try:
-            for sg in self._provider.ec2_conn.get_all_security_groups(
+            for sg in self.provider.ec2_conn.get_all_security_groups(
                     group_ids=[group_id]):
                     group_ids=[group_id]):
                 try:
                 try:
                     sg.delete()
                     sg.delete()
@@ -192,14 +193,14 @@ class AWSSecurityGroupService(SecurityGroupService):
         return True
         return True
 
 
 
 
-class AWSBlockStoreService(BlockStoreService):
+class AWSBlockStoreService(BaseBlockStoreService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSBlockStoreService, self).__init__(provider)
 
 
         # Initialize provider services
         # Initialize provider services
-        self._volumes = AWSVolumeService(self._provider)
-        self._snapshots = AWSSnapshotService(self._provider)
+        self._volumes = AWSVolumeService(self.provider)
+        self._snapshots = AWSSnapshotService(self.provider)
 
 
     @property
     @property
     def volumes(self):
     def volumes(self):
@@ -210,17 +211,17 @@ class AWSBlockStoreService(BlockStoreService):
         return self._snapshots
         return self._snapshots
 
 
 
 
-class AWSVolumeService(VolumeService):
+class AWSVolumeService(BaseVolumeService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSVolumeService, self).__init__(provider)
 
 
     def get_volume(self, volume_id):
     def get_volume(self, volume_id):
         """
         """
         Returns a volume given its id.
         Returns a volume given its id.
         """
         """
-        vols = self._provider.ec2_conn.get_all_volumes(volume_ids=[volume_id])
-        return AWSVolume(self._provider, vols[0]) if vols else None
+        vols = self.provider.ec2_conn.get_all_volumes(volume_ids=[volume_id])
+        return AWSVolume(self.provider, vols[0]) if vols else None
 
 
     def find_volume(self, name):
     def find_volume(self, name):
         """
         """
@@ -233,8 +234,8 @@ class AWSVolumeService(VolumeService):
         """
         """
         List all volumes.
         List all volumes.
         """
         """
-        return [AWSVolume(self._provider, vol)
-                for vol in self._provider.ec2_conn.get_all_volumes()]
+        return [AWSVolume(self.provider, vol)
+                for vol in self.provider.ec2_conn.get_all_volumes()]
 
 
     def create_volume(self, name, size, zone, snapshot=None):
     def create_volume(self, name, size, zone, snapshot=None):
         """
         """
@@ -244,28 +245,28 @@ class AWSVolumeService(VolumeService):
         snapshot_id = snapshot.snapshot_id if isinstance(
         snapshot_id = snapshot.snapshot_id if isinstance(
             zone, AWSSnapshot) and snapshot else snapshot
             zone, AWSSnapshot) and snapshot else snapshot
 
 
-        ec2_vol = self._provider.ec2_conn.create_volume(
+        ec2_vol = self.provider.ec2_conn.create_volume(
             size,
             size,
             zone_name,
             zone_name,
             snapshot=snapshot_id)
             snapshot=snapshot_id)
-        cb_vol = AWSVolume(self._provider, ec2_vol)
+        cb_vol = AWSVolume(self.provider, ec2_vol)
         cb_vol.name = name
         cb_vol.name = name
         return cb_vol
         return cb_vol
 
 
 
 
-class AWSObjectStoreService(ObjectStoreService):
+class AWSObjectStoreService(BaseObjectStoreService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSObjectStoreService, self).__init__(provider)
 
 
     def get_container(self, container_id):
     def get_container(self, container_id):
         """
         """
         Returns a container given its id. Returns None if the container
         Returns a container given its id. Returns None if the container
         does not exist.
         does not exist.
         """
         """
-        bucket = self._provider.s3_conn.lookup(container_id)
+        bucket = self.provider.s3_conn.lookup(container_id)
         if bucket:
         if bucket:
-            return AWSContainer(self._provider, bucket)
+            return AWSContainer(self.provider, bucket)
         else:
         else:
             return None
             return None
 
 
@@ -280,31 +281,31 @@ class AWSObjectStoreService(ObjectStoreService):
         """
         """
         List all containers.
         List all containers.
         """
         """
-        buckets = self._provider.s3_conn.get_all_buckets()
-        return [AWSContainer(self._provider, bucket) for bucket in buckets]
+        buckets = self.provider.s3_conn.get_all_buckets()
+        return [AWSContainer(self.provider, bucket) for bucket in buckets]
 
 
     def create_container(self, name, location=None):
     def create_container(self, name, location=None):
         """
         """
         Create a new container.
         Create a new container.
         """
         """
-        bucket = self._provider.s3_conn.create_bucket(
+        bucket = self.provider.s3_conn.create_bucket(
             name,
             name,
             location=location if location else '')
             location=location if location else '')
-        return AWSContainer(self._provider, bucket)
+        return AWSContainer(self.provider, bucket)
 
 
 
 
-class AWSSnapshotService(SnapshotService):
+class AWSSnapshotService(BaseSnapshotService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSSnapshotService, self).__init__(provider)
 
 
     def get_snapshot(self, snapshot_id):
     def get_snapshot(self, snapshot_id):
         """
         """
         Returns a snapshot given its id.
         Returns a snapshot given its id.
         """
         """
-        snaps = self._provider.ec2_conn.get_all_snapshots(
+        snaps = self.provider.ec2_conn.get_all_snapshots(
             snapshot_ids=[snapshot_id])
             snapshot_ids=[snapshot_id])
-        return AWSSnapshot(self._provider, snaps[0]) if snaps else None
+        return AWSSnapshot(self.provider, snaps[0]) if snaps else None
 
 
     def find_snapshot(self, name):
     def find_snapshot(self, name):
         """
         """
@@ -319,9 +320,9 @@ class AWSSnapshotService(SnapshotService):
         """
         """
         # TODO: get_all_images returns too many images - some kind of filtering
         # TODO: get_all_images returns too many images - some kind of filtering
         # abilities are needed. Forced to "self" for now
         # abilities are needed. Forced to "self" for now
-        return [AWSSnapshot(self._provider, snap)
+        return [AWSSnapshot(self.provider, snap)
                 for snap in
                 for snap in
-                self._provider.ec2_conn.get_all_snapshots(owner="self")]
+                self.provider.ec2_conn.get_all_snapshots(owner="self")]
 
 
     def create_snapshot(self, name, volume, description=None):
     def create_snapshot(self, name, volume, description=None):
         """
         """
@@ -331,27 +332,27 @@ class AWSSnapshotService(SnapshotService):
             volume,
             volume,
             AWSVolume) else volume
             AWSVolume) else volume
 
 
-        ec2_snap = self._provider.ec2_conn.create_snapshot(
+        ec2_snap = self.provider.ec2_conn.create_snapshot(
             volume_id,
             volume_id,
             description=description)
             description=description)
-        cb_snap = AWSSnapshot(self._provider, ec2_snap)
+        cb_snap = AWSSnapshot(self.provider, ec2_snap)
         cb_snap.name = name
         cb_snap.name = name
         return cb_snap
         return cb_snap
 
 
 
 
-class AWSImageService(ImageService):
+class AWSImageService(BaseImageService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSImageService, self).__init__(provider)
 
 
     def get_image(self, image_id):
     def get_image(self, image_id):
         """
         """
         Returns an Image given its id
         Returns an Image given its id
         """
         """
         try:
         try:
-            image = self._provider.ec2_conn.get_image(image_id)
+            image = self.provider.ec2_conn.get_image(image_id)
             if image:
             if image:
-                return AWSMachineImage(self._provider, image)
+                return AWSMachineImage(self.provider, image)
         except EC2ResponseError:
         except EC2ResponseError:
             pass
             pass
 
 
@@ -370,20 +371,16 @@ class AWSImageService(ImageService):
         """
         """
         # TODO: get_all_images returns too many images - some kind of filtering
         # TODO: get_all_images returns too many images - some kind of filtering
         # abilities are needed. Forced to "self" for now
         # abilities are needed. Forced to "self" for now
-        images = self._provider.ec2_conn.get_all_images(owners="self")
-        return [AWSMachineImage(self._provider, image) for image in images]
+        images = self.provider.ec2_conn.get_all_images(owners="self")
+        return [AWSMachineImage(self.provider, image) for image in images]
 
 
 
 
-class AWSComputeService(ComputeService):
+class AWSComputeService(BaseComputeService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSComputeService, self).__init__(provider)
         self._instance_types = AWSInstanceTypesService(self.provider)
         self._instance_types = AWSInstanceTypesService(self.provider)
 
 
-    @property
-    def provider(self):
-        return self._provider
-
     @property
     @property
     def instance_types(self):
     def instance_types(self):
         return self._instance_types
         return self._instance_types
@@ -411,14 +408,14 @@ class AWSComputeService(ComputeService):
         else:
         else:
             security_groups_list = None
             security_groups_list = None
 
 
-        reservation = self._provider.ec2_conn.run_instances(
+        reservation = self.provider.ec2_conn.run_instances(
             image_id=image_id, instance_type=instance_size,
             image_id=image_id, instance_type=instance_size,
             min_count=1, max_count=1, placement=zone_name,
             min_count=1, max_count=1, placement=zone_name,
             key_name=keypair_name, security_groups=security_groups_list,
             key_name=keypair_name, security_groups=security_groups_list,
             user_data=user_data
             user_data=user_data
         )
         )
         if reservation:
         if reservation:
-            instance = AWSInstance(self._provider, reservation.instances[0])
+            instance = AWSInstance(self.provider, reservation.instances[0])
             instance.name = name
             instance.name = name
         return instance
         return instance
 
 
@@ -427,10 +424,10 @@ class AWSComputeService(ComputeService):
         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.
         """
         """
-        reservation = self._provider.ec2_conn.get_all_reservations(
+        reservation = self.provider.ec2_conn.get_all_reservations(
             instance_ids=[instance_id])
             instance_ids=[instance_id])
         if reservation:
         if reservation:
-            return AWSInstance(self._provider, reservation[0].instances[0])
+            return AWSInstance(self.provider, reservation[0].instances[0])
         else:
         else:
             return None
             return None
 
 
@@ -448,32 +445,42 @@ class AWSComputeService(ComputeService):
         """
         """
         List all instances.
         List all instances.
         """
         """
-        reservations = self._provider.ec2_conn.get_all_reservations()
-        return [AWSInstance(self._provider, inst)
+        reservations = self.provider.ec2_conn.get_all_reservations()
+        return [AWSInstance(self.provider, inst)
                 for res in reservations
                 for res in reservations
                 for inst in res.instances]
                 for inst in res.instances]
 
 
+    def list_regions(self):
+        """
+        List all data center regions for this provider.
+
+        :rtype: ``list`` of :class:`.Region`
+        :return: list of Region objects
+        """
+        raise NotImplementedError(
+            'list_regions not implemented by this provider')
+
 
 
 AWS_INSTANCE_DATA_DEFAULT_URL = "https://swift.rc.nectar.org.au:8888/v1/" \
 AWS_INSTANCE_DATA_DEFAULT_URL = "https://swift.rc.nectar.org.au:8888/v1/" \
                                 "AUTH_377/cloud-bridge/aws/instance_data.json"
                                 "AUTH_377/cloud-bridge/aws/instance_data.json"
 
 
 
 
-class AWSInstanceTypesService(InstanceTypesService):
+class AWSInstanceTypesService(BaseInstanceTypesService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(AWSInstanceTypesService, self).__init__(provider)
 
 
     @property
     @property
     def instance_data(self):
     def instance_data(self):
         """
         """
         TODO: Neeeds a caching function with timeout
         TODO: Neeeds a caching function with timeout
         """
         """
-        r = requests.get(self._provider.config.get(
+        r = requests.get(self.provider.config.get(
             "aws_instance_info_url", AWS_INSTANCE_DATA_DEFAULT_URL))
             "aws_instance_info_url", AWS_INSTANCE_DATA_DEFAULT_URL))
         return r.json()
         return r.json()
 
 
     def list(self):
     def list(self):
-        return [AWSInstanceType(self._provider, inst_data)
+        return [AWSInstanceType(self.provider, inst_data)
                 for inst_data in self.instance_data]
                 for inst_data in self.instance_data]
 
 
     def find_by_name(self, name):
     def find_by_name(self, name):

+ 74 - 0
cloudbridge/providers/base.py

@@ -20,6 +20,10 @@ from cloudbridge.providers.interfaces import SnapshotState
 from cloudbridge.providers.interfaces import Volume
 from cloudbridge.providers.interfaces import Volume
 from cloudbridge.providers.interfaces import VolumeState
 from cloudbridge.providers.interfaces import VolumeState
 from cloudbridge.providers.interfaces import WaitStateException
 from cloudbridge.providers.interfaces import WaitStateException
+from cloudbridge.providers.interfaces.services import ImageService,\
+    ProviderService, ComputeService, VolumeService, SnapshotService,\
+    BlockStoreService, ObjectStoreService, SecurityService, KeyPairService,\
+    SecurityGroupService, InstanceTypesService
 
 
 
 
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
@@ -275,3 +279,73 @@ class BaseSecurityGroupRule(SecurityGroupRule):
     def __repr__(self):
     def __repr__(self):
         return "<CBSecurityGroupRule: IP: {0}; from: {1}; to: {2}>".format(
         return "<CBSecurityGroupRule: IP: {0}; from: {1}; to: {2}>".format(
             self.ip_protocol, self.from_port, self.to_port)
             self.ip_protocol, self.from_port, self.to_port)
+
+
+class BaseProviderService(ProviderService):
+
+    def __init__(self, provider):
+        self._provider = provider
+
+    @property
+    def provider(self):
+        return self._provider
+
+
+class BaseComputeService(ComputeService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseComputeService, self).__init__(provider)
+
+
+class BaseVolumeService(VolumeService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseVolumeService, self).__init__(provider)
+
+
+class BaseSnapshotService(SnapshotService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseSnapshotService, self).__init__(provider)
+
+
+class BaseBlockStoreService(BlockStoreService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseBlockStoreService, self).__init__(provider)
+
+
+class BaseImageService(ImageService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseImageService, self).__init__(provider)
+
+
+class BaseObjectStoreService(ObjectStoreService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseObjectStoreService, self).__init__(provider)
+
+
+class BaseSecurityService(SecurityService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseSecurityService, self).__init__(provider)
+
+
+class BaseKeyPairService(KeyPairService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseKeyPairService, self).__init__(provider)
+
+
+class BaseSecurityGroupService(SecurityGroupService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseSecurityGroupService, self).__init__(provider)
+
+
+class BaseInstanceTypesService(InstanceTypesService, BaseProviderService):
+
+    def __init__(self, provider):
+        super(BaseInstanceTypesService, self).__init__(provider)

+ 28 - 31
cloudbridge/providers/interfaces/impl.py

@@ -1,14 +1,18 @@
 """
 """
 Specification for a provider interface
 Specification for a provider interface
 """
 """
+from abc import ABCMeta, abstractmethod, abstractproperty
 
 
 
 
 class CloudProvider(object):
 class CloudProvider(object):
 
 
+    __metaclass__ = ABCMeta
+
     """
     """
     Base interface for a cloud provider
     Base interface for a cloud provider
     """
     """
 
 
+    @abstractmethod
     def __init__(self, config):
     def __init__(self, config):
         """
         """
         Create a new provider implementation given a dictionary of
         Create a new provider implementation given a dictionary of
@@ -22,10 +26,9 @@ class CloudProvider(object):
         :rtype: ``object`` of :class:`.CloudProvider`
         :rtype: ``object`` of :class:`.CloudProvider`
         :return:  a concrete provider instance
         :return:  a concrete provider instance
         """
         """
-        raise NotImplementedError(
-            '__init__ not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def config(self):
     def config(self):
         """
         """
         Returns the config object associated with this provider.
         Returns the config object associated with this provider.
@@ -33,9 +36,8 @@ class CloudProvider(object):
         :rtype: ``object``
         :rtype: ``object``
         :return:  The config object used to initialize this provider
         :return:  The config object used to initialize this provider
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.config not implemented by this provider')
 
 
+    @abstractmethod
     def has_service(self, service_type):
     def has_service(self, service_type):
         """
         """
         Checks whether this provider supports a given service.
         Checks whether this provider supports a given service.
@@ -46,10 +48,9 @@ class CloudProvider(object):
         :rtype: bool
         :rtype: bool
         :return: ``True`` if the service type is supported.
         :return: ``True`` if the service type is supported.
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.has_service not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def account(self):
     def account(self):
         """
         """
         Provides access to all user account related services in this provider.
         Provides access to all user account related services in this provider.
@@ -58,10 +59,9 @@ class CloudProvider(object):
         :rtype: ``object`` of :class:`.ComputeService`
         :rtype: ``object`` of :class:`.ComputeService`
         :return:  a ComputeService object
         :return:  a ComputeService object
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.Compute not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def compute(self):
     def compute(self):
         """
         """
         Provides access to all compute related services in this provider.
         Provides access to all compute related services in this provider.
@@ -69,10 +69,9 @@ class CloudProvider(object):
         :rtype: ``object`` of :class:`.ComputeService`
         :rtype: ``object`` of :class:`.ComputeService`
         :return:  a ComputeService object
         :return:  a ComputeService object
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.compute not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def images(self):
     def images(self):
         """
         """
         Provides access to all Image related services in this provider.
         Provides access to all Image related services in this provider.
@@ -81,10 +80,9 @@ class CloudProvider(object):
         :rtype: ``object`` of :class:`.ImageService`
         :rtype: ``object`` of :class:`.ImageService`
         :return: an ImageService object
         :return: an ImageService object
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.images not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def security(self):
     def security(self):
         """
         """
         Provides access to keypair management and firewall control
         Provides access to keypair management and firewall control
@@ -92,10 +90,9 @@ class CloudProvider(object):
         :rtype: ``object`` of :class:`.SecurityService`
         :rtype: ``object`` of :class:`.SecurityService`
         :return: a SecurityService object
         :return: a SecurityService object
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.security not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def block_store(self):
     def block_store(self):
         """
         """
         Provides access to the volume and snapshot services in this
         Provides access to the volume and snapshot services in this
@@ -104,10 +101,9 @@ class CloudProvider(object):
         :rtype: ``object`` of :class:`.BlockStoreService`
         :rtype: ``object`` of :class:`.BlockStoreService`
         :return: a BlockStoreService object
         :return: a BlockStoreService object
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.block_store not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def object_store(self):
     def object_store(self):
         """
         """
         Provides access to object storage services in this provider.
         Provides access to object storage services in this provider.
@@ -115,8 +111,7 @@ class CloudProvider(object):
         :rtype: ``object`` of :class:`.ObjectStoreService`
         :rtype: ``object`` of :class:`.ObjectStoreService`
         :return: an ObjectStoreService object
         :return: an ObjectStoreService object
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.object_store not implemented by this provider')
+        pass
 
 
 
 
 class ContainerProvider(object):
 class ContainerProvider(object):
@@ -124,14 +119,15 @@ class ContainerProvider(object):
     """
     """
     Represents a container instance, such as Docker or LXC
     Represents a container instance, such as Docker or LXC
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def create_container(self):
     def create_container(self):
-        raise NotImplementedError(
-            'create_container not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete_container(self):
     def delete_container(self):
-        raise NotImplementedError(
-            'delete_container not implemented by this provider')
+        pass
 
 
 
 
 class DeploymentProvider(object):
 class DeploymentProvider(object):
@@ -139,10 +135,11 @@ class DeploymentProvider(object):
     """
     """
     Represents a deployment provider, such as Ansible or Shell script provider
     Represents a deployment provider, such as Ansible or Shell script provider
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def deploy(self, target):
     def deploy(self, target):
         """
         """
         Deploys on given target, where target is an Instance or Container
         Deploys on given target, where target is an Instance or Container
         """
         """
-        raise NotImplementedError(
-            'deploy not implemented by this provider')
+        pass

+ 160 - 176
cloudbridge/providers/interfaces/resources.py

@@ -1,6 +1,7 @@
 """
 """
 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
 
 
 
 
 class CloudProviderServiceType(object):
 class CloudProviderServiceType(object):
@@ -48,7 +49,9 @@ class ObjectLifeCycleMixin(object):
     A refresh operation allows the object to synchronise its state with the
     A refresh operation allows the object to synchronise its state with the
     service provider.
     service provider.
     """
     """
-    @property
+    __metaclass__ = ABCMeta
+
+    @abstractproperty
     def state(self):
     def state(self):
         """
         """
         Get the current state of this object.
         Get the current state of this object.
@@ -56,17 +59,17 @@ class ObjectLifeCycleMixin(object):
         :rtype: ``str``
         :rtype: ``str``
         :return: The current state as a string
         :return: The current state as a string
         """
         """
-        raise NotImplementedError(
-            'LifeCycleObject.state not implemented by this service')
+        pass
 
 
+    @abstractmethod
     def refresh(self):
     def refresh(self):
         """
         """
         Refreshs this object's state and synchronize it with the underlying
         Refreshs this object's state and synchronize it with the underlying
         service provider.
         service provider.
         """
         """
-        raise NotImplementedError(
-            'LifeCycleObject.refresh not implemented by this service')
+        pass
 
 
+    @abstractmethod
     def wait_till_ready(self, timeout, interval):
     def wait_till_ready(self, timeout, interval):
         """
         """
         Wait till the current object is in a ready state, which is any
         Wait till the current object is in a ready state, which is any
@@ -87,8 +90,7 @@ class ObjectLifeCycleMixin(object):
         be thrown by the underlying service if the object cannot get into a
         be thrown by the underlying service if the object cannot get into a
         ready state (e.g. If the object is in an error state)
         ready state (e.g. If the object is in an error state)
         """
         """
-        raise NotImplementedError(
-            'LifeCycleObject.wait_till_ready not implemented by this service')
+        pass
 
 
 
 
 class InstanceState(object):
 class InstanceState(object):
@@ -118,7 +120,9 @@ class InstanceState(object):
 
 
 class Instance(ObjectLifeCycleMixin):
 class Instance(ObjectLifeCycleMixin):
 
 
-    @property
+    __metaclass__ = ABCMeta
+
+    @abstractproperty
     def instance_id(self):
     def instance_id(self):
         """
         """
         Get the instance identifier.
         Get the instance identifier.
@@ -126,10 +130,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: str
         :rtype: str
         :return: ID for this instance as returned by the cloud middleware.
         :return: ID for this instance as returned by the cloud middleware.
         """
         """
-        raise NotImplementedError(
-            'Instance.instance_id not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def name(self):
     def name(self):
         """
         """
         Get the instance name.
         Get the instance name.
@@ -137,10 +140,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: str
         :rtype: str
         :return: Name for this instance as returned by the cloud middleware.
         :return: Name for this instance as returned by the cloud middleware.
         """
         """
-        raise NotImplementedError(
-            'Instance.name not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def public_ips(self):
     def public_ips(self):
         """
         """
         Get all the public IP addresses for this instance.
         Get all the public IP addresses for this instance.
@@ -148,10 +150,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: list
         :rtype: list
         :return: A list of public IP addresses associated with this instance.
         :return: A list of public IP addresses associated with this instance.
         """
         """
-        raise NotImplementedError(
-            'Instance.public_ips not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def private_ips(self):
     def private_ips(self):
         """
         """
         Get all the private IP addresses for this instance.
         Get all the private IP addresses for this instance.
@@ -159,10 +160,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: list
         :rtype: list
         :return: A list of private IP addresses associated with this instance.
         :return: A list of private IP addresses associated with this instance.
         """
         """
-        raise NotImplementedError(
-            'Instance.private_ips not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def instance_type(self):
     def instance_type(self):
         """
         """
         Get the instance type.
         Get the instance type.
@@ -170,9 +170,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: str
         :rtype: str
         :return: API type of this instance (e.g., ``m1.large``)
         :return: API type of this instance (e.g., ``m1.large``)
         """
         """
-        raise NotImplementedError(
-            'Instance.instance_type not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def reboot(self):
     def reboot(self):
         """
         """
         Reboot this instance (using the cloud middleware API).
         Reboot this instance (using the cloud middleware API).
@@ -180,9 +180,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: bool
         :rtype: bool
         :return: ``True`` if the reboot was succesful; ``False`` otherwise.
         :return: ``True`` if the reboot was succesful; ``False`` otherwise.
         """
         """
-        raise NotImplementedError(
-            'Instance.reboot not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def terminate(self):
     def terminate(self):
         """
         """
         Permanently terminate this instance.
         Permanently terminate this instance.
@@ -191,10 +191,9 @@ class Instance(ObjectLifeCycleMixin):
         :return: ``True`` if the termination of the instance was succesfully
         :return: ``True`` if the termination of the instance was succesfully
                  initiated; ``False`` otherwise.
                  initiated; ``False`` otherwise.
         """
         """
-        raise NotImplementedError(
-            'Instance.terminate not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def image_id(self):
     def image_id(self):
         """
         """
         Get the image ID for this insance.
         Get the image ID for this insance.
@@ -202,10 +201,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: str
         :rtype: str
         :return: Image ID (i.e., AMI) this instance is using.
         :return: Image ID (i.e., AMI) this instance is using.
         """
         """
-        raise NotImplementedError(
-            'Instance.image_id not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def placement_zone(self):
     def placement_zone(self):
         """
         """
         Get the placement zone where this instance is running.
         Get the placement zone where this instance is running.
@@ -213,10 +211,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: str
         :rtype: str
         :return: Region/zone/placement where this instance is running.
         :return: Region/zone/placement where this instance is running.
         """
         """
-        raise NotImplementedError(
-            'Instance.placement not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def mac_address(self):
     def mac_address(self):
         """
         """
         Get the MAC address for this instance.
         Get the MAC address for this instance.
@@ -224,10 +221,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: str
         :rtype: str
         :return: MAC address for ths instance.
         :return: MAC address for ths instance.
         """
         """
-        raise NotImplementedError(
-            'Instance.mac_address not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def security_groups(self):
     def security_groups(self):
         """
         """
         Get the security groups associated with this instance.
         Get the security groups associated with this instance.
@@ -235,10 +231,9 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: list or :class:``SecurityGroup`` objects
         :rtype: list or :class:``SecurityGroup`` objects
         :return: A list of SecurityGroup objects associated with this instance.
         :return: A list of SecurityGroup objects associated with this instance.
         """
         """
-        raise NotImplementedError(
-            'Instance.security_groups not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def key_pair_name(self):
     def key_pair_name(self):
         """
         """
         Get the name of the key pair associated with this instance.
         Get the name of the key pair associated with this instance.
@@ -246,17 +241,16 @@ class Instance(ObjectLifeCycleMixin):
         :rtype: str
         :rtype: str
         :return: Name of the ssh key pair associated with this instance.
         :return: Name of the ssh key pair associated with this instance.
         """
         """
-        raise NotImplementedError(
-            'Instance.key_pair_name not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def create_image(self, name):
     def create_image(self, name):
         """
         """
         Create a new image based on this instance.
         Create a new image based on this instance.
         :return:  an Image object
         :return:  an Image object
         :rtype: ``object`` of :class:`.Image`
         :rtype: ``object`` of :class:`.Image`
         """
         """
-        raise NotImplementedError(
-            'Instance.create_image not implemented by this provider')
+        pass
 
 
 
 
 class MachineImageState(object):
 class MachineImageState(object):
@@ -278,7 +272,9 @@ class MachineImageState(object):
 
 
 class MachineImage(ObjectLifeCycleMixin):
 class MachineImage(ObjectLifeCycleMixin):
 
 
-    @property
+    __metaclass__ = ABCMeta
+
+    @abstractproperty
     def image_id(self):
     def image_id(self):
         """
         """
         Get the image identifier.
         Get the image identifier.
@@ -286,10 +282,9 @@ class MachineImage(ObjectLifeCycleMixin):
         :rtype: ``str``
         :rtype: ``str``
         :return: ID for this instance as returned by the cloud middleware.
         :return: ID for this instance as returned by the cloud middleware.
         """
         """
-        raise NotImplementedError(
-            'MachineImage.image_id not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def name(self):
     def name(self):
         """
         """
         Get the image name.
         Get the image name.
@@ -297,10 +292,9 @@ class MachineImage(ObjectLifeCycleMixin):
         :rtype: ``str``
         :rtype: ``str``
         :return: Name for this image as returned by the cloud middleware.
         :return: Name for this image as returned by the cloud middleware.
         """
         """
-        raise NotImplementedError(
-            'MachineImage.name not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def description(self):
     def description(self):
         """
         """
         Get the image description.
         Get the image description.
@@ -308,9 +302,9 @@ class MachineImage(ObjectLifeCycleMixin):
         :rtype: ``str``
         :rtype: ``str``
         :return: Description for this image as returned by the cloud middleware
         :return: Description for this image as returned by the cloud middleware
         """
         """
-        raise NotImplementedError(
-            'MachineImage.description not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete(self):
     def delete(self):
         """
         """
         Delete this image
         Delete this image
@@ -318,8 +312,7 @@ class MachineImage(ObjectLifeCycleMixin):
         :rtype: ``bool``
         :rtype: ``bool``
         :return: True if the operation succeeded
         :return: True if the operation succeeded
         """
         """
-        raise NotImplementedError(
-            'MachineImage.delete not implemented by this provider')
+        pass
 
 
 
 
 class VolumeState(object):
 class VolumeState(object):
@@ -347,7 +340,9 @@ class VolumeState(object):
 
 
 class Volume(ObjectLifeCycleMixin):
 class Volume(ObjectLifeCycleMixin):
 
 
-    @property
+    __metaclass__ = ABCMeta
+
+    @abstractproperty
     def volume_id(self):
     def volume_id(self):
         """
         """
         Get the volume identifier.
         Get the volume identifier.
@@ -355,10 +350,9 @@ class Volume(ObjectLifeCycleMixin):
         :rtype: ``str``
         :rtype: ``str``
         :return: ID for this instance as returned by the cloud middleware.
         :return: ID for this instance as returned by the cloud middleware.
         """
         """
-        raise NotImplementedError(
-            'Volume.volume_id not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def name(self):
     def name(self):
         """
         """
         Get the volume name.
         Get the volume name.
@@ -366,9 +360,9 @@ class Volume(ObjectLifeCycleMixin):
         :rtype: ``str``
         :rtype: ``str``
         :return: Name for this volume as returned by the cloud middleware.
         :return: Name for this volume as returned by the cloud middleware.
         """
         """
-        raise NotImplementedError(
-            'Volume.name not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def attach(self, instance_id, device):
     def attach(self, instance_id, device):
         """
         """
         Attach this volume to an instance.
         Attach this volume to an instance.
@@ -384,9 +378,9 @@ class Volume(ObjectLifeCycleMixin):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError(
-            'Volume.attach not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def detach(self, force=False):
     def detach(self, force=False):
         """
         """
         Detach this volume from an instance.
         Detach this volume from an instance.
@@ -404,9 +398,9 @@ class Volume(ObjectLifeCycleMixin):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError(
-            'Volume.detach not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def create_snapshot(self, description=None):
     def create_snapshot(self, description=None):
         """
         """
         Create a snapshot of this Volume.
         Create a snapshot of this Volume.
@@ -418,9 +412,9 @@ class Volume(ObjectLifeCycleMixin):
         :rtype: :class:`.Snapshot`
         :rtype: :class:`.Snapshot`
         :return: The created Snapshot object
         :return: The created Snapshot object
         """
         """
-        raise NotImplementedError(
-            'Volume.snapshot not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete(self):
     def delete(self):
         """
         """
         Delete this volume.
         Delete this volume.
@@ -428,8 +422,7 @@ class Volume(ObjectLifeCycleMixin):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError(
-            'Volume.delete not implemented by this provider')
+        pass
 
 
 
 
 class SnapshotState(object):
 class SnapshotState(object):
@@ -453,6 +446,9 @@ class SnapshotState(object):
 
 
 class Snapshot(ObjectLifeCycleMixin):
 class Snapshot(ObjectLifeCycleMixin):
 
 
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
     def create_volume(self, placement, size=None, volume_type=None, iops=None):
     def create_volume(self, placement, size=None, volume_type=None, iops=None):
         """
         """
         Create a new Volume from this Snapshot.
         Create a new Volume from this Snapshot.
@@ -476,9 +472,9 @@ class Snapshot(ObjectLifeCycleMixin):
         :rtype: :class:`.Volume`
         :rtype: :class:`.Volume`
         :return: An instance of the created Volume
         :return: An instance of the created Volume
         """
         """
-        raise NotImplementedError(
-            'create_volume not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def share(self, user_ids=None):
     def share(self, user_ids=None):
         """
         """
         Share this Snapshot.
         Share this Snapshot.
@@ -490,8 +486,9 @@ class Snapshot(ObjectLifeCycleMixin):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError('share not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def unshare(self, user_ids=None):
     def unshare(self, user_ids=None):
         """
         """
         Unshare this Snapshot.
         Unshare this Snapshot.
@@ -503,8 +500,9 @@ class Snapshot(ObjectLifeCycleMixin):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError('unshare not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete(self):
     def delete(self):
         """
         """
         Delete this snapshot.
         Delete this snapshot.
@@ -512,12 +510,14 @@ class Snapshot(ObjectLifeCycleMixin):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError('delete not implemented by this provider')
+        pass
 
 
 
 
 class KeyPair(object):
 class KeyPair(object):
 
 
-    @property
+    __metaclass__ = ABCMeta
+
+    @abstractproperty
     def name(self):
     def name(self):
         """
         """
         Return the name of this key pair.
         Return the name of this key pair.
@@ -525,10 +525,9 @@ class KeyPair(object):
         :rtype: str
         :rtype: str
         :return: A name of this ssh key pair
         :return: A name of this ssh key pair
         """
         """
-        raise NotImplementedError(
-            'name not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def material(self):
     def material(self):
         """
         """
         Unencrypted private key.
         Unencrypted private key.
@@ -536,9 +535,9 @@ class KeyPair(object):
         :rtype: str
         :rtype: str
         :return: Unencrypted private key or ``None`` if not available.
         :return: Unencrypted private key or ``None`` if not available.
         """
         """
-        raise NotImplementedError(
-            'material not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete(self):
     def delete(self):
         """
         """
         Delete this key pair.
         Delete this key pair.
@@ -546,8 +545,7 @@ class KeyPair(object):
         :rtype: bool
         :rtype: bool
         :return: ``True`` is successful.
         :return: ``True`` is successful.
         """
         """
-        raise NotImplementedError(
-            'delete not implemented by this provider')
+        pass
 
 
 
 
 class Region(object):
 class Region(object):
@@ -556,8 +554,9 @@ class Region(object):
     Represents a cloud region, typically a separate geographic area and will
     Represents a cloud region, typically a separate geographic area and will
     contain at least one placement zone.
     contain at least one placement zone.
     """
     """
+    __metaclass__ = ABCMeta
 
 
-    @property
+    @abstractproperty
     def name(self):
     def name(self):
         """
         """
         Name of the region.
         Name of the region.
@@ -565,9 +564,9 @@ class Region(object):
         :rtype: str
         :rtype: str
         :return: Name of the region.
         :return: Name of the region.
         """
         """
-        raise NotImplementedError(
-            'name not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def list_zones(self):
     def list_zones(self):
         """
         """
         List all available placement zones within this region.
         List all available placement zones within this region.
@@ -575,8 +574,7 @@ class Region(object):
         :rtype: list
         :rtype: list
         :return: List of all the available placement zones.
         :return: List of all the available placement zones.
         """
         """
-        raise NotImplementedError(
-            'list_zones not implemented by this provider')
+        pass
 
 
 
 
 class PlacementZone(object):
 class PlacementZone(object):
@@ -584,8 +582,9 @@ class PlacementZone(object):
     """
     """
     Represents a placement zone. A placement zone is contained within a Region.
     Represents a placement zone. A placement zone is contained within a Region.
     """
     """
+    __metaclass__ = ABCMeta
 
 
-    @property
+    @abstractproperty
     def name(self):
     def name(self):
         """
         """
         Name of the placement zone.
         Name of the placement zone.
@@ -593,10 +592,9 @@ class PlacementZone(object):
         :rtype: str
         :rtype: str
         :return: Name of the placement zone.
         :return: Name of the placement zone.
         """
         """
-        raise NotImplementedError(
-            'PlacementZone.name not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def region(self):
     def region(self):
         """
         """
         A region this placement zone is associated with.
         A region this placement zone is associated with.
@@ -604,8 +602,7 @@ class PlacementZone(object):
         :rtype: str
         :rtype: str
         :return: The name of the region the zone is associated with.
         :return: The name of the region the zone is associated with.
         """
         """
-        raise NotImplementedError(
-            'region_name not implemented by this provider')
+        pass
 
 
 
 
 class InstanceType(object):
 class InstanceType(object):
@@ -613,18 +610,17 @@ class InstanceType(object):
     """
     """
     An instance type object.
     An instance type object.
     """
     """
+    __metaclass__ = ABCMeta
 
 
-    @property
+    @abstractproperty
     def id(self):
     def id(self):
-        raise NotImplementedError(
-            'InstanceType.id not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def name(self):
     def name(self):
-        raise NotImplementedError(
-            'InstanceType.name not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def family(self):
     def family(self):
         """
         """
         The family/group that this instance type belongs to. For example,
         The family/group that this instance type belongs to. For example,
@@ -634,10 +630,9 @@ class InstanceType(object):
         :rtype: str
         :rtype: str
         :return: Name of the instance family.
         :return: Name of the instance family.
         """
         """
-        raise NotImplementedError(
-            'InstanceType.family not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def vcpus(self):
     def vcpus(self):
         """
         """
         The number of VCPUs supported by this instance type.
         The number of VCPUs supported by this instance type.
@@ -645,10 +640,9 @@ class InstanceType(object):
         :rtype: int
         :rtype: int
         :return: Number of VCPUs
         :return: Number of VCPUs
         """
         """
-        raise NotImplementedError(
-            'InstanceType.vcpus not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def ram(self):
     def ram(self):
         """
         """
         The amount of RAM (in mb) supported by this instance type.
         The amount of RAM (in mb) supported by this instance type.
@@ -656,10 +650,9 @@ class InstanceType(object):
         :rtype: int
         :rtype: int
         :return: Total RAM (in MB).
         :return: Total RAM (in MB).
         """
         """
-        raise NotImplementedError(
-            'InstanceType.ram not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def root_disk(self):
     def root_disk(self):
         """
         """
         The size of this instance types's root disk (in GB).
         The size of this instance types's root disk (in GB).
@@ -667,10 +660,9 @@ class InstanceType(object):
         :rtype: int
         :rtype: int
         :return: Size of root disk (in GB).
         :return: Size of root disk (in GB).
         """
         """
-        raise NotImplementedError(
-            'InstanceType.root_disk not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def ephemeral_disk(self):
     def ephemeral_disk(self):
         """
         """
         The size of this instance types's total ephemeral storage (in GB).
         The size of this instance types's total ephemeral storage (in GB).
@@ -678,10 +670,9 @@ class InstanceType(object):
         :rtype: int
         :rtype: int
         :return: Size of ephemeral disks (in GB).
         :return: Size of ephemeral disks (in GB).
         """
         """
-        raise NotImplementedError(
-            'InstanceType.ephemeral_disk not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def total_disk(self):
     def total_disk(self):
         """
         """
         The total disk space available on this instance type.
         The total disk space available on this instance type.
@@ -690,10 +681,9 @@ class InstanceType(object):
         :rtype: int
         :rtype: int
         :return: Size of total disk space (in GB).
         :return: Size of total disk space (in GB).
         """
         """
-        raise NotImplementedError(
-            'InstanceType.total_disk not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def extra_data(self):
     def extra_data(self):
         """
         """
         A dictionary of extra data about this instance. May contain
         A dictionary of extra data about this instance. May contain
@@ -702,13 +692,24 @@ class InstanceType(object):
         :rtype: dict
         :rtype: dict
         :return: Extra attributes for this instance type
         :return: Extra attributes for this instance type
         """
         """
-        raise NotImplementedError(
-            'InstanceType.extra_data not implemented by this provider')
+        pass
 
 
 
 
 class SecurityGroup(object):
 class SecurityGroup(object):
 
 
-    @property
+    __metaclass__ = ABCMeta
+
+    @abstractproperty
+    def id(self):
+        """
+        Get the ID of this security group.
+
+        :rtype: str
+        :return: Security group ID
+        """
+        pass
+
+    @abstractproperty
     def name(self):
     def name(self):
         """
         """
         Return the name of this security group.
         Return the name of this security group.
@@ -716,10 +717,9 @@ class SecurityGroup(object):
         :rtype: str
         :rtype: str
         :return: A name of this security group.
         :return: A name of this security group.
         """
         """
-        raise NotImplementedError(
-            'name not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def description(self):
     def description(self):
         """
         """
         Return the description of this security group.
         Return the description of this security group.
@@ -727,21 +727,9 @@ class SecurityGroup(object):
         :rtype: str
         :rtype: str
         :return: A description of this security group.
         :return: A description of this security group.
         """
         """
-        raise NotImplementedError(
-            'description not implemented by this provider')
-
-    @property
-    def id(self):
-        """
-        Get the ID of this security group.
-
-        :rtype: str
-        :return: Security group ID
-        """
-        raise NotImplementedError(
-            'id not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def rules(self):
     def rules(self):
         """
         """
         Get the list of rules for this security group.
         Get the list of rules for this security group.
@@ -749,9 +737,9 @@ class SecurityGroup(object):
         :rtype: list of :class:``.SecurityGroupRule``
         :rtype: list of :class:``.SecurityGroupRule``
         :return: A list of security group rule objects
         :return: A list of security group rule objects
         """
         """
-        raise NotImplementedError(
-            'rules not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete(self):
     def delete(self):
         """
         """
         Delete this security group.
         Delete this security group.
@@ -759,9 +747,9 @@ class SecurityGroup(object):
         :rtype: bool
         :rtype: bool
         :return: ``True`` is successful.
         :return: ``True`` is successful.
         """
         """
-        raise NotImplementedError(
-            'delete not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def add_rule(self, ip_protocol=None, from_port=None, to_port=None,
     def add_rule(self, ip_protocol=None, from_port=None, to_port=None,
                  cidr_ip=None, src_group=None):
                  cidr_ip=None, src_group=None):
         """
         """
@@ -790,8 +778,7 @@ class SecurityGroup(object):
         :rtype: bool
         :rtype: bool
         :return: True if successful.
         :return: True if successful.
         """
         """
-        raise NotImplementedError(
-            'add_rule not implemented by this provider')
+        pass
 
 
 
 
 class SecurityGroupRule(object):
 class SecurityGroupRule(object):
@@ -799,40 +786,37 @@ class SecurityGroupRule(object):
     """
     """
     Represents a security group rule.
     Represents a security group rule.
     """
     """
+    __metaclass__ = ABCMeta
 
 
-    @property
+    @abstractproperty
     def ip_protocol(self):
     def ip_protocol(self):
         """
         """
         IP protocol used. Either ``tcp`` | ``udp`` | ``icmp``.
         IP protocol used. Either ``tcp`` | ``udp`` | ``icmp``.
         """
         """
-        raise NotImplementedError(
-            'ip_protocol not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def from_port(self):
     def from_port(self):
         """
         """
         Lowest port number opened as part of this rule.
         Lowest port number opened as part of this rule.
         """
         """
-        raise NotImplementedError(
-            'from_port not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def to_port(self):
     def to_port(self):
         """
         """
         Highest port number opened as part of this rule.
         Highest port number opened as part of this rule.
         """
         """
-        raise NotImplementedError(
-            'to_port not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def cidr_ip(self):
     def cidr_ip(self):
         """
         """
         CIDR block this security group is providing access to.
         CIDR block this security group is providing access to.
         """
         """
-        raise NotImplementedError(
-            'cidr_ip not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def group(self):
     def group(self):
         """
         """
         Security group given access permissions by this rule.
         Security group given access permissions by this rule.
@@ -840,8 +824,7 @@ class SecurityGroupRule(object):
         :rtype: ``object`` of :class:`.SecurityGroup`
         :rtype: ``object`` of :class:`.SecurityGroup`
         :return: The Security Group with granting access.
         :return: The Security Group with granting access.
         """
         """
-        raise NotImplementedError(
-            'group not implemented by this provider')
+        pass
 
 
 
 
 class ContainerObject(object):
 class ContainerObject(object):
@@ -849,8 +832,9 @@ class ContainerObject(object):
     """
     """
     Represents an object stored within a container.
     Represents an object stored within a container.
     """
     """
+    __metaclass__ = ABCMeta
 
 
-    @property
+    @abstractproperty
     def name(self):
     def name(self):
         """
         """
         Get this object's name.
         Get this object's name.
@@ -858,9 +842,9 @@ class ContainerObject(object):
         :rtype: ``str``
         :rtype: ``str``
         :return: Name of this object as returned by the cloud middleware.
         :return: Name of this object as returned by the cloud middleware.
         """
         """
-        raise NotImplementedError(
-            'ContainerObject.name not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def download(self, target_stream):
     def download(self, target_stream):
         """
         """
         Download this object and write its
         Download this object and write its
@@ -869,9 +853,9 @@ class ContainerObject(object):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError(
-            'ContainerObject.download not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def upload(self, source_stream):
     def upload(self, source_stream):
         """
         """
         Set the contents of this object to the data read from the source
         Set the contents of this object to the data read from the source
@@ -880,9 +864,9 @@ class ContainerObject(object):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError(
-            'ContainerObject.upload not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete(self):
     def delete(self):
         """
         """
         Delete this object.
         Delete this object.
@@ -890,13 +874,14 @@ class ContainerObject(object):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError(
-            'ContainerObject.delete not implemented by this provider')
+        pass
 
 
 
 
 class Container(object):
 class Container(object):
 
 
-    @property
+    __metaclass__ = ABCMeta
+
+    @abstractproperty
     def name(self):
     def name(self):
         """
         """
         Get this container's name.
         Get this container's name.
@@ -904,9 +889,9 @@ class Container(object):
         :rtype: ``str``
         :rtype: ``str``
         :return: Name of this container as returned by the cloud middleware.
         :return: Name of this container as returned by the cloud middleware.
         """
         """
-        raise NotImplementedError(
-            'Container.name not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def get(self, key):
     def get(self, key):
         """
         """
         Retrieve a given object from this container.
         Retrieve a given object from this container.
@@ -917,9 +902,9 @@ class Container(object):
         :rtype: ContainerObject
         :rtype: ContainerObject
         :return: The ContainerObject or None if it cannot be found.
         :return: The ContainerObject or None if it cannot be found.
         """
         """
-        raise NotImplementedError(
-            'Container.list not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def list(self):
     def list(self):
         """
         """
         List all objects within this container.
         List all objects within this container.
@@ -927,9 +912,9 @@ class Container(object):
         :rtype: ContainerObject
         :rtype: ContainerObject
         :return: List of all available ContainerObjects within this container
         :return: List of all available ContainerObjects within this container
         """
         """
-        raise NotImplementedError(
-            'Container.list not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete(self, delete_contents=False):
     def delete(self, delete_contents=False):
         """
         """
         Delete this container.
         Delete this container.
@@ -941,5 +926,4 @@ class Container(object):
         :rtype: bool
         :rtype: bool
         :return: True if successful
         :return: True if successful
         """
         """
-        raise NotImplementedError(
-            'Container.delete not implemented by this provider')
+        pass

+ 90 - 74
cloudbridge/providers/interfaces/services.py

@@ -1,6 +1,7 @@
 """
 """
 Specifications for services available through a provider
 Specifications for services available through a provider
 """
 """
+from abc import ABCMeta, abstractmethod, abstractproperty
 
 
 
 
 class ProviderService(object):
 class ProviderService(object):
@@ -8,7 +9,9 @@ class ProviderService(object):
     """
     """
     Base interface for any service supported by a provider
     Base interface for any service supported by a provider
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractproperty
     def provider(self):
     def provider(self):
         """
         """
         Returns the provider instance associated with this service.
         Returns the provider instance associated with this service.
@@ -16,8 +19,7 @@ class ProviderService(object):
         :rtype: ``object`` of :class:`.CloudProvider`
         :rtype: ``object`` of :class:`.CloudProvider`
         :return: a Provider object
         :return: a Provider object
         """
         """
-        raise NotImplementedError(
-            'ComputeService.Provider not implemented by this provider')
+        pass
 
 
 
 
 class ComputeService(ProviderService):
 class ComputeService(ProviderService):
@@ -25,7 +27,9 @@ class ComputeService(ProviderService):
     """
     """
     Base interface for compute service supported by a provider
     Base interface for compute service supported by a provider
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def get_instance(self, instance_id):
     def get_instance(self, instance_id):
         """
         """
         Returns an instance given its id. Returns None
         Returns an instance given its id. Returns None
@@ -34,9 +38,9 @@ class ComputeService(ProviderService):
         :rtype: ``object`` of :class:`.Instance`
         :rtype: ``object`` of :class:`.Instance`
         :return:  an Instance object
         :return:  an Instance object
         """
         """
-        raise NotImplementedError(
-            'get_instance not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def find_instance(self, name):
     def find_instance(self, name):
         """
         """
         Searches for an instance by a given list of attributes.
         Searches for an instance by a given list of attributes.
@@ -44,9 +48,9 @@ class ComputeService(ProviderService):
         :rtype: ``object`` of :class:`.Instance`
         :rtype: ``object`` of :class:`.Instance`
         :return: an Instance object
         :return: an Instance object
         """
         """
-        raise NotImplementedError(
-            'find_instance not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def list_instances(self):
     def list_instances(self):
         """
         """
         List all instances.
         List all instances.
@@ -54,10 +58,9 @@ class ComputeService(ProviderService):
         :rtype: ``list`` of :class:`.Instance`
         :rtype: ``list`` of :class:`.Instance`
         :return: list of Instance objects
         :return: list of Instance objects
         """
         """
-        raise NotImplementedError(
-            'list_instances not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def instance_types(self):
     def instance_types(self):
         """
         """
         Provides access to all Instance type related services in this provider.
         Provides access to all Instance type related services in this provider.
@@ -65,9 +68,9 @@ class ComputeService(ProviderService):
         :rtype: ``object`` of :class:`.InstanceTypeService`
         :rtype: ``object`` of :class:`.InstanceTypeService`
         :return:  an InstanceTypeService object
         :return:  an InstanceTypeService object
         """
         """
-        raise NotImplementedError(
-            'instance_types not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def list_regions(self):
     def list_regions(self):
         """
         """
         List all data center regions for this provider.
         List all data center regions for this provider.
@@ -75,12 +78,13 @@ class ComputeService(ProviderService):
         :rtype: ``list`` of :class:`.Region`
         :rtype: ``list`` of :class:`.Region`
         :return: list of Region objects
         :return: list of Region objects
         """
         """
-        raise NotImplementedError(
-            'list_regions not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def create_instance(self, name, image, instance_type, zone=None,
     def create_instance(self, name, image, instance_type, zone=None,
                         keypair=None, security_groups=None, user_data=None,
                         keypair=None, security_groups=None, user_data=None,
                         block_device_mapping=None, network_interfaces=None,
                         block_device_mapping=None, network_interfaces=None,
+                        launch_configuration=None,
                         **kwargs):
                         **kwargs):
         """
         """
         Creates a new virtual machine instance.
         Creates a new virtual machine instance.
@@ -123,11 +127,17 @@ class ComputeService(ProviderService):
                                    describes network interfaces for this
                                    describes network interfaces for this
                                    instance.
                                    instance.
 
 
+        :type  launch_configuration: ``LaunchConfiguration`` object
+        :param launch_configuration: A ``LaunchConfiguration`` object which
+        describes advanced launch configuration options for an instance. This
+        include blck_device_mappings and network_interfaces. To construct a
+        launch configuration object, call
+        provider.compute.instances.create_launch_configuration()
+
         :rtype: `object`` of :class:`.Instance`
         :rtype: `object`` of :class:`.Instance`
         :return:  an instance of Instance class
         :return:  an instance of Instance class
         """
         """
-        raise NotImplementedError(
-            'create_instance not implemented by this provider')
+        pass
 
 
 
 
 class VolumeService(ProviderService):
 class VolumeService(ProviderService):
@@ -135,7 +145,9 @@ class VolumeService(ProviderService):
     """
     """
     Base interface for a Volume Service
     Base interface for a Volume Service
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def get_volume(self, volume_id):
     def get_volume(self, volume_id):
         """
         """
         Returns a volume given its id. Returns None if the volume
         Returns a volume given its id. Returns None if the volume
@@ -144,9 +156,9 @@ class VolumeService(ProviderService):
         :rtype: ``object`` of :class:`.Volume`
         :rtype: ``object`` of :class:`.Volume`
         :return: a Volume object
         :return: a Volume object
         """
         """
-        raise NotImplementedError(
-            'get_volume not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def find_volume(self, name):
     def find_volume(self, name):
         """
         """
         Searches for a volume by a given list of attributes.
         Searches for a volume by a given list of attributes.
@@ -154,9 +166,9 @@ class VolumeService(ProviderService):
         :rtype: ``object`` of :class:`.Volume`
         :rtype: ``object`` of :class:`.Volume`
         :return: a Volume object or ``None`` if not found
         :return: a Volume object or ``None`` if not found
         """
         """
-        raise NotImplementedError(
-            'find_volume not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def list_volumes(self):
     def list_volumes(self):
         """
         """
         List all volumes.
         List all volumes.
@@ -164,9 +176,9 @@ class VolumeService(ProviderService):
         :rtype: ``list`` of :class:`.Volume`
         :rtype: ``list`` of :class:`.Volume`
         :return: a list of Volume objects
         :return: a list of Volume objects
         """
         """
-        raise NotImplementedError(
-            'list_volumes not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def create_volume(self, name, size, zone, snapshot=None, description=None):
     def create_volume(self, name, size, zone, snapshot=None, description=None):
         """
         """
         Creates a new volume.
         Creates a new volume.
@@ -188,8 +200,7 @@ class VolumeService(ProviderService):
         :rtype: ``object`` of :class:`.Volume`
         :rtype: ``object`` of :class:`.Volume`
         :return: a newly created Volume object
         :return: a newly created Volume object
         """
         """
-        raise NotImplementedError(
-            'create_volume not implemented by this provider')
+        pass
 
 
 
 
 class SnapshotService(ProviderService):
 class SnapshotService(ProviderService):
@@ -197,7 +208,9 @@ class SnapshotService(ProviderService):
     """
     """
     Base interface for a Snapshot Service
     Base interface for a Snapshot Service
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def get_snapshot(self, volume_id):
     def get_snapshot(self, volume_id):
         """
         """
         Returns a snapshot given its id. Returns None if the snapshot
         Returns a snapshot given its id. Returns None if the snapshot
@@ -206,9 +219,9 @@ class SnapshotService(ProviderService):
         :rtype: ``object`` of :class:`.Snapshot`
         :rtype: ``object`` of :class:`.Snapshot`
         :return: a Snapshot object
         :return: a Snapshot object
         """
         """
-        raise NotImplementedError(
-            'get_snapshot not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def find_snapshot(self, name):
     def find_snapshot(self, name):
         """
         """
         Searches for a snapshot by a given list of attributes.
         Searches for a snapshot by a given list of attributes.
@@ -216,9 +229,9 @@ class SnapshotService(ProviderService):
         :rtype: ``object`` of :class:`.Snapshot`
         :rtype: ``object`` of :class:`.Snapshot`
         :return: a Snapshot object or ``None`` if not found
         :return: a Snapshot object or ``None`` if not found
         """
         """
-        raise NotImplementedError(
-            'find_snapshot not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def list_snapshots(self):
     def list_snapshots(self):
         """
         """
         List all snapshots.
         List all snapshots.
@@ -226,9 +239,9 @@ class SnapshotService(ProviderService):
         :rtype: ``list`` of :class:`.Snapshot`
         :rtype: ``list`` of :class:`.Snapshot`
         :return: a list of Snapshot objects
         :return: a list of Snapshot objects
         """
         """
-        raise NotImplementedError(
-            'list_snapshots not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def create_snapshot(self, name, volume, description=None):
     def create_snapshot(self, name, volume, description=None):
         """
         """
         Creates a new snapshot off a volume.
         Creates a new snapshot off a volume.
@@ -247,8 +260,7 @@ class SnapshotService(ProviderService):
         :rtype: ``object`` of :class:`.Snapshot`
         :rtype: ``object`` of :class:`.Snapshot`
         :return: a newly created Snapshot object
         :return: a newly created Snapshot object
         """
         """
-        raise NotImplementedError(
-            'create_snapshot not implemented by this provider')
+        pass
 
 
 
 
 class BlockStoreService(ProviderService):
 class BlockStoreService(ProviderService):
@@ -256,8 +268,9 @@ class BlockStoreService(ProviderService):
     """
     """
     Base interface for a Block Store Service
     Base interface for a Block Store Service
     """
     """
+    __metaclass__ = ABCMeta
 
 
-    @property
+    @abstractproperty
     def volumes(self):
     def volumes(self):
         """
         """
         Provides access to the volumes (i.e., block storage) for this provider.
         Provides access to the volumes (i.e., block storage) for this provider.
@@ -265,10 +278,9 @@ class BlockStoreService(ProviderService):
         :rtype: ``object`` of :class:`.VolumeService`
         :rtype: ``object`` of :class:`.VolumeService`
         :return: a VolumeService object
         :return: a VolumeService object
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.block_store not implemented by this provider')
+        pass
 
 
-    @property
+    @abstractproperty
     def snapshots(self):
     def snapshots(self):
         """
         """
         Provides access to volume snapshots for this provider.
         Provides access to volume snapshots for this provider.
@@ -276,8 +288,7 @@ class BlockStoreService(ProviderService):
         :rtype: ``object`` of :class:`.SnapshotService`
         :rtype: ``object`` of :class:`.SnapshotService`
         :return: an SnapshotService object
         :return: an SnapshotService object
         """
         """
-        raise NotImplementedError(
-            'CloudProvider.object_store not implemented by this provider')
+        pass
 
 
 
 
 class ImageService(ProviderService):
 class ImageService(ProviderService):
@@ -285,7 +296,9 @@ class ImageService(ProviderService):
     """
     """
     Base interface for an Image Service
     Base interface for an Image Service
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def get_image(self, image_id):
     def get_image(self, image_id):
         """
         """
         Returns an Image given its id. Returns None if the Image does not
         Returns an Image given its id. Returns None if the Image does not
@@ -294,9 +307,9 @@ class ImageService(ProviderService):
         :rtype: ``object`` of :class:`.Image`
         :rtype: ``object`` of :class:`.Image`
         :return:  an Image instance
         :return:  an Image instance
         """
         """
-        raise NotImplementedError(
-            'get_image implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def find_image(self, name):
     def find_image(self, name):
         """
         """
         Searches for an image by a given list of attributes
         Searches for an image by a given list of attributes
@@ -304,9 +317,9 @@ class ImageService(ProviderService):
         :rtype: ``object`` of :class:`.Image`
         :rtype: ``object`` of :class:`.Image`
         :return:  an Image instance
         :return:  an Image instance
         """
         """
-        raise NotImplementedError(
-            'find_image not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def list_images(self):
     def list_images(self):
         """
         """
         List all images.
         List all images.
@@ -314,8 +327,7 @@ class ImageService(ProviderService):
         :rtype: ``list`` of :class:`.Image`
         :rtype: ``list`` of :class:`.Image`
         :return:  list of image objects
         :return:  list of image objects
         """
         """
-        raise NotImplementedError(
-            'list_images not implemented by this provider')
+        pass
 
 
 
 
 class ObjectStoreService(ProviderService):
 class ObjectStoreService(ProviderService):
@@ -323,7 +335,9 @@ class ObjectStoreService(ProviderService):
     """
     """
     Base interface for an Object Storage Service
     Base interface for an Object Storage Service
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def get_container(self, container_id):
     def get_container(self, container_id):
         """
         """
         Returns a container given its id. Returns None if the container
         Returns a container given its id. Returns None if the container
@@ -332,9 +346,9 @@ class ObjectStoreService(ProviderService):
         :rtype: ``object`` of :class:`.Container`
         :rtype: ``object`` of :class:`.Container`
         :return:  a Container instance
         :return:  a Container instance
         """
         """
-        raise NotImplementedError(
-            'get_container implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def find_container(self, name):
     def find_container(self, name):
         """
         """
         Searches for a container by a given list of attributes
         Searches for a container by a given list of attributes
@@ -342,9 +356,9 @@ class ObjectStoreService(ProviderService):
         :rtype: ``object`` of :class:`.Container`
         :rtype: ``object`` of :class:`.Container`
         :return:  a Container instance
         :return:  a Container instance
         """
         """
-        raise NotImplementedError(
-            'find_container not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def list_containers(self):
     def list_containers(self):
         """
         """
         List all containers.
         List all containers.
@@ -352,9 +366,9 @@ class ObjectStoreService(ProviderService):
         :rtype: ``list`` of :class:`.Container`
         :rtype: ``list`` of :class:`.Container`
         :return:  list of container objects
         :return:  list of container objects
         """
         """
-        raise NotImplementedError(
-            'list_containers not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def create_container(self, name, location=None):
     def create_container(self, name, location=None):
         """
         """
         Create a new container.
         Create a new container.
@@ -368,8 +382,7 @@ class ObjectStoreService(ProviderService):
         :return:  a Container object
         :return:  a Container object
         :rtype: ``object`` of :class:`.Container`
         :rtype: ``object`` of :class:`.Container`
         """
         """
-        raise NotImplementedError(
-            'create_container not implemented by this provider')
+        pass
 
 
 
 
 class SecurityService(ProviderService):
 class SecurityService(ProviderService):
@@ -377,8 +390,9 @@ class SecurityService(ProviderService):
     """
     """
     Base interface for a Security Service.
     Base interface for a Security Service.
     """
     """
+    __metaclass__ = ABCMeta
 
 
-    @property
+    @abstractproperty
     def key_pairs(self):
     def key_pairs(self):
         """
         """
         Provides access to key pairs for this provider.
         Provides access to key pairs for this provider.
@@ -386,9 +400,9 @@ class SecurityService(ProviderService):
         :rtype: ``object`` of :class:`.KeyPairService`
         :rtype: ``object`` of :class:`.KeyPairService`
         :return: a KeyPairService object
         :return: a KeyPairService object
         """
         """
-        return self._key_pairs
+        pass
 
 
-    @property
+    @abstractproperty
     def security_groups(self):
     def security_groups(self):
         """
         """
         Provides access to security groups for this provider.
         Provides access to security groups for this provider.
@@ -396,7 +410,7 @@ class SecurityService(ProviderService):
         :rtype: ``object`` of :class:`.SecurityGroupService`
         :rtype: ``object`` of :class:`.SecurityGroupService`
         :return: a SecurityGroupService object
         :return: a SecurityGroupService object
         """
         """
-        return self._security_groups
+        pass
 
 
 
 
 class KeyPairService(ProviderService):
 class KeyPairService(ProviderService):
@@ -404,7 +418,9 @@ class KeyPairService(ProviderService):
     """
     """
     Base interface for key pairs.
     Base interface for key pairs.
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def list(self):
     def list(self):
         """
         """
         List all key pairs associated with this account.
         List all key pairs associated with this account.
@@ -412,9 +428,9 @@ class KeyPairService(ProviderService):
         :rtype: ``list`` of :class:`.KeyPair`
         :rtype: ``list`` of :class:`.KeyPair`
         :return:  list of KeyPair objects
         :return:  list of KeyPair objects
         """
         """
-        raise NotImplementedError(
-            'list_key_pairs not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def create(self, name):
     def create(self, name):
         """
         """
         Create a new keypair.
         Create a new keypair.
@@ -425,9 +441,9 @@ class KeyPairService(ProviderService):
         :rtype: ``object`` of :class:`.KeyPair`
         :rtype: ``object`` of :class:`.KeyPair`
         :return:  A keypair instance
         :return:  A keypair instance
         """
         """
-        raise NotImplementedError(
-            'create_key_pair not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete(self, name):
     def delete(self, name):
         """
         """
         Delete an existing SecurityGroup.
         Delete an existing SecurityGroup.
@@ -440,8 +456,7 @@ class KeyPairService(ProviderService):
                   that this implies that the key may not have been deleted by
                   that this implies that the key may not have been deleted by
                   this method but instead has not existed at all.
                   this method but instead has not existed at all.
         """
         """
-        raise NotImplementedError(
-            'delete not implemented by this provider')
+        pass
 
 
 
 
 class SecurityGroupService(ProviderService):
 class SecurityGroupService(ProviderService):
@@ -449,7 +464,9 @@ class SecurityGroupService(ProviderService):
     """
     """
     Base interface for security groups.
     Base interface for security groups.
     """
     """
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def list(self):
     def list(self):
         """
         """
         List all security groups associated with this account.
         List all security groups associated with this account.
@@ -457,9 +474,9 @@ class SecurityGroupService(ProviderService):
         :rtype: ``list`` of :class:`.SecurityGroup`
         :rtype: ``list`` of :class:`.SecurityGroup`
         :return:  list of SecurityGroup objects
         :return:  list of SecurityGroup objects
         """
         """
-        raise NotImplementedError(
-            'list not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def create(self, name, description):
     def create(self, name, description):
         """
         """
         Create a new SecurityGroup.
         Create a new SecurityGroup.
@@ -473,9 +490,9 @@ class SecurityGroupService(ProviderService):
         :rtype: ``object`` of :class:`.SecurityGroup`
         :rtype: ``object`` of :class:`.SecurityGroup`
         :return:  A SecurityGroup instance or ``None`` if one was not created.
         :return:  A SecurityGroup instance or ``None`` if one was not created.
         """
         """
-        raise NotImplementedError(
-            'create not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def get(self, group_names=None, group_ids=None):
     def get(self, group_names=None, group_ids=None):
         """
         """
         Get all security groups associated with your account.
         Get all security groups associated with your account.
@@ -494,9 +511,9 @@ class SecurityGroupService(ProviderService):
         :return: A list of SecurityGroup objects or an empty list if none
         :return: A list of SecurityGroup objects or an empty list if none
         found.
         found.
         """
         """
-        raise NotImplementedError(
-            'get not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def delete(self, group_id):
     def delete(self, group_id):
         """
         """
         Delete an existing SecurityGroup.
         Delete an existing SecurityGroup.
@@ -510,12 +527,13 @@ class SecurityGroupService(ProviderService):
                   been deleted by this method but instead has not existed in
                   been deleted by this method but instead has not existed in
                   the first place.
                   the first place.
         """
         """
-        raise NotImplementedError(
-            'delete not implemented by this provider')
+        pass
 
 
 
 
 class InstanceTypesService(object):
 class InstanceTypesService(object):
+    __metaclass__ = ABCMeta
 
 
+    @abstractmethod
     def list(self):
     def list(self):
         """
         """
         List all instance types.
         List all instance types.
@@ -523,9 +541,9 @@ class InstanceTypesService(object):
         :rtype: ``list`` of :class:`.InstanceType`
         :rtype: ``list`` of :class:`.InstanceType`
         :return: list of InstanceType objects
         :return: list of InstanceType objects
         """
         """
-        raise NotImplementedError(
-            'InstanceTypesService.list not implemented by this provider')
+        pass
 
 
+    @abstractmethod
     def find_by_name(self, name):
     def find_by_name(self, name):
         """
         """
         Searches for an instance by a given list of attributes.
         Searches for an instance by a given list of attributes.
@@ -533,6 +551,4 @@ class InstanceTypesService(object):
         :rtype: ``object`` of :class:`.InstanceType`
         :rtype: ``object`` of :class:`.InstanceType`
         :return: an Instance object
         :return: an Instance object
         """
         """
-        raise NotImplementedError(
-            'InstanceTypesService.find_instance not implemented by this'
-            'provider')
+        pass

+ 5 - 0
cloudbridge/providers/openstack/impl.py

@@ -48,6 +48,11 @@ class OpenStackCloudProviderV1(BaseCloudProvider):
         self._block_store = OpenStackBlockStoreService(self)
         self._block_store = OpenStackBlockStoreService(self)
         self._object_store = OpenStackObjectStoreService(self)
         self._object_store = OpenStackObjectStoreService(self)
 
 
+    @property
+    def account(self):
+        raise NotImplementedError(
+            'account not implemented by this provider')
+
     @property
     @property
     def compute(self):
     def compute(self):
         return self._compute
         return self._compute

+ 10 - 0
cloudbridge/providers/openstack/resources.py

@@ -497,6 +497,16 @@ class OpenStackSnapshot(BaseSnapshot):
         """
         """
         self._snapshot.delete()
         self._snapshot.delete()
 
 
+    def create_volume(self, placement, size=None, volume_type=None, iops=None):
+        raise NotImplementedError(
+            'create_volume not implemented by this provider')
+
+    def share(self, user_ids=None):
+        raise NotImplementedError('share not implemented by this provider')
+
+    def unshare(self, user_ids=None):
+        raise NotImplementedError('share not implemented by this provider')
+
     def __repr__(self):
     def __repr__(self):
         return "<CB-OSSnapshot: {0} ({1}>".format(self.snapshot_id, self.name)
         return "<CB-OSSnapshot: {0} ({1}>".format(self.snapshot_id, self.name)
 
 

+ 40 - 35
cloudbridge/providers/openstack/services.py

@@ -2,22 +2,24 @@
 Services implemented by the OpenStack provider.
 Services implemented by the OpenStack provider.
 """
 """
 from cinderclient.exceptions import NotFound as CinderNotFound
 from cinderclient.exceptions import NotFound as CinderNotFound
-from cloudbridge.providers.interfaces import BlockStoreService
-from cloudbridge.providers.interfaces import ComputeService
-from cloudbridge.providers.interfaces import ImageService
+from novaclient.exceptions import NotFound as NovaNotFound
+
+from cloudbridge.providers.base import BaseBlockStoreService
+from cloudbridge.providers.base import BaseComputeService
+from cloudbridge.providers.base import BaseImageService
+from cloudbridge.providers.base import BaseInstanceTypesService
+from cloudbridge.providers.base import BaseKeyPairService
+from cloudbridge.providers.base import BaseObjectStoreService
+from cloudbridge.providers.base import BaseSecurityGroupService
+from cloudbridge.providers.base import BaseSecurityService
+from cloudbridge.providers.base import BaseSnapshotService
+from cloudbridge.providers.base import BaseVolumeService
+
 from cloudbridge.providers.interfaces import InstanceType
 from cloudbridge.providers.interfaces import InstanceType
-from cloudbridge.providers.interfaces import InstanceTypesService
 from cloudbridge.providers.interfaces import KeyPair
 from cloudbridge.providers.interfaces import KeyPair
-from cloudbridge.providers.interfaces import KeyPairService
 from cloudbridge.providers.interfaces import MachineImage
 from cloudbridge.providers.interfaces import MachineImage
-from cloudbridge.providers.interfaces import ObjectStoreService
 from cloudbridge.providers.interfaces import PlacementZone
 from cloudbridge.providers.interfaces import PlacementZone
 from cloudbridge.providers.interfaces import SecurityGroup
 from cloudbridge.providers.interfaces import SecurityGroup
-from cloudbridge.providers.interfaces import SecurityGroupService
-from cloudbridge.providers.interfaces import SecurityService
-from cloudbridge.providers.interfaces import SnapshotService
-from cloudbridge.providers.interfaces import VolumeService
-from novaclient.exceptions import NotFound as NovaNotFound
 
 
 from .resources import OpenStackContainer
 from .resources import OpenStackContainer
 from .resources import OpenStackInstance
 from .resources import OpenStackInstance
@@ -30,10 +32,10 @@ from .resources import OpenStackSnapshot
 from .resources import OpenStackVolume
 from .resources import OpenStackVolume
 
 
 
 
-class OpenStackSecurityService(SecurityService):
+class OpenStackSecurityService(BaseSecurityService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackSecurityService, self).__init__(provider)
 
 
         # Initialize provider services
         # Initialize provider services
         self._key_pairs = OpenStackKeyPairService(provider)
         self._key_pairs = OpenStackKeyPairService(provider)
@@ -60,10 +62,10 @@ class OpenStackSecurityService(SecurityService):
         return self._security_groups
         return self._security_groups
 
 
 
 
-class OpenStackKeyPairService(KeyPairService):
+class OpenStackKeyPairService(BaseKeyPairService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackKeyPairService, self).__init__(provider)
 
 
     def list(self):
     def list(self):
         """
         """
@@ -110,10 +112,10 @@ class OpenStackKeyPairService(KeyPairService):
             return True
             return True
 
 
 
 
-class OpenStackSecurityGroupService(SecurityGroupService):
+class OpenStackSecurityGroupService(BaseSecurityGroupService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackSecurityGroupService, self).__init__(provider)
 
 
     def list(self):
     def list(self):
         """
         """
@@ -197,10 +199,10 @@ class OpenStackSecurityGroupService(SecurityGroupService):
         return True
         return True
 
 
 
 
-class OpenStackImageService(ImageService):
+class OpenStackImageService(BaseImageService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackImageService, self).__init__(provider)
 
 
     def get_image(self, image_id):
     def get_image(self, image_id):
         """
         """
@@ -228,10 +230,10 @@ class OpenStackImageService(ImageService):
                 for image in images]
                 for image in images]
 
 
 
 
-class OpenStackInstanceTypesService(InstanceTypesService):
+class OpenStackInstanceTypesService(BaseInstanceTypesService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackInstanceTypesService, self).__init__(provider)
 
 
     def list(self):
     def list(self):
         return [OpenStackInstanceType(f)
         return [OpenStackInstanceType(f)
@@ -242,10 +244,10 @@ class OpenStackInstanceTypesService(InstanceTypesService):
             (itype for itype in self.list() if itype.name == name), None)
             (itype for itype in self.list() if itype.name == name), None)
 
 
 
 
-class OpenStackBlockStoreService(BlockStoreService):
+class OpenStackBlockStoreService(BaseBlockStoreService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackBlockStoreService, self).__init__(provider)
 
 
         # Initialize provider services
         # Initialize provider services
         self._volumes = OpenStackVolumeService(self._provider)
         self._volumes = OpenStackVolumeService(self._provider)
@@ -260,10 +262,10 @@ class OpenStackBlockStoreService(BlockStoreService):
         return self._snapshots
         return self._snapshots
 
 
 
 
-class OpenStackVolumeService(VolumeService):
+class OpenStackVolumeService(BaseVolumeService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackVolumeService, self).__init__(provider)
 
 
     def get_volume(self, volume_id):
     def get_volume(self, volume_id):
         """
         """
@@ -303,10 +305,10 @@ class OpenStackVolumeService(VolumeService):
         return OpenStackVolume(self._provider, os_vol)
         return OpenStackVolume(self._provider, os_vol)
 
 
 
 
-class OpenStackSnapshotService(SnapshotService):
+class OpenStackSnapshotService(BaseSnapshotService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackSnapshotService, self).__init__(provider)
 
 
     def get_snapshot(self, snapshot_id):
     def get_snapshot(self, snapshot_id):
         """
         """
@@ -346,10 +348,10 @@ class OpenStackSnapshotService(SnapshotService):
         return OpenStackSnapshot(self._provider, os_snap)
         return OpenStackSnapshot(self._provider, os_snap)
 
 
 
 
-class OpenStackObjectStoreService(ObjectStoreService):
+class OpenStackObjectStoreService(BaseObjectStoreService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackObjectStoreService, self).__init__(provider)
 
 
     def get_container(self, container_id):
     def get_container(self, container_id):
         """
         """
@@ -386,16 +388,12 @@ class OpenStackObjectStoreService(ObjectStoreService):
         return self.get_container(name)
         return self.get_container(name)
 
 
 
 
-class OpenStackComputeService(ComputeService):
+class OpenStackComputeService(BaseComputeService):
 
 
     def __init__(self, provider):
     def __init__(self, provider):
-        self._provider = provider
+        super(OpenStackComputeService, self).__init__(provider)
         self._instance_types = OpenStackInstanceTypesService(self._provider)
         self._instance_types = OpenStackInstanceTypesService(self._provider)
 
 
-    @property
-    def provider(self):
-        return self._provider
-
     @property
     @property
     def instance_types(self):
     def instance_types(self):
         return self._instance_types
         return self._instance_types
@@ -435,6 +433,13 @@ class OpenStackComputeService(ComputeService):
             userdata=user_data)
             userdata=user_data)
         return OpenStackInstance(self._provider, os_instance)
         return OpenStackInstance(self._provider, os_instance)
 
 
+    def find_instance(self, name):
+        """
+        Searches for an instance by a given list of attributes.
+        """
+        raise NotImplementedError(
+            'find_instance not implemented by this provider')
+
     def list_instances(self):
     def list_instances(self):
         """
         """
         List all instances.
         List all instances.