| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964 |
- """Services implemented by the AWS provider."""
- import string
- import time
- from boto.ec2.blockdevicemapping import BlockDeviceMapping
- from boto.ec2.blockdevicemapping import BlockDeviceType
- from boto.exception import EC2ResponseError, S3ResponseError
- from cloudbridge.cloud.base.resources import ClientPagedResultList
- from cloudbridge.cloud.base.resources import ServerPagedResultList
- from cloudbridge.cloud.base.services import BaseBlockStoreService
- from cloudbridge.cloud.base.services import BaseComputeService
- from cloudbridge.cloud.base.services import BaseGatewayService
- from cloudbridge.cloud.base.services import BaseImageService
- from cloudbridge.cloud.base.services import BaseInstanceService
- from cloudbridge.cloud.base.services import BaseInstanceTypesService
- from cloudbridge.cloud.base.services import BaseKeyPairService
- from cloudbridge.cloud.base.services import BaseNetworkService
- from cloudbridge.cloud.base.services import BaseNetworkingService
- from cloudbridge.cloud.base.services import BaseObjectStoreService
- from cloudbridge.cloud.base.services import BaseRegionService
- from cloudbridge.cloud.base.services import BaseRouterService
- from cloudbridge.cloud.base.services import BaseSecurityGroupService
- from cloudbridge.cloud.base.services import BaseSecurityService
- from cloudbridge.cloud.base.services import BaseSnapshotService
- from cloudbridge.cloud.base.services import BaseSubnetService
- from cloudbridge.cloud.base.services import BaseVolumeService
- from cloudbridge.cloud.interfaces.exceptions \
- import InvalidConfigurationException
- from cloudbridge.cloud.interfaces.resources import InstanceState
- from cloudbridge.cloud.interfaces.resources import InstanceType
- from cloudbridge.cloud.interfaces.resources import KeyPair
- from cloudbridge.cloud.interfaces.resources import MachineImage
- from cloudbridge.cloud.interfaces.resources import NetworkState
- from cloudbridge.cloud.interfaces.resources import PlacementZone
- from cloudbridge.cloud.interfaces.resources import SecurityGroup
- from cloudbridge.cloud.interfaces.resources import Snapshot
- from cloudbridge.cloud.interfaces.resources import SubnetState
- from cloudbridge.cloud.interfaces.resources import Volume
- import requests
- from .resources import AWSBucket
- from .resources import AWSFloatingIP
- from .resources import AWSInstance
- from .resources import AWSInstanceType
- from .resources import AWSInternetGateway
- from .resources import AWSKeyPair
- from .resources import AWSLaunchConfig
- from .resources import AWSMachineImage
- from .resources import AWSNetwork
- from .resources import AWSRegion
- from .resources import AWSRouter
- from .resources import AWSSecurityGroup
- from .resources import AWSSnapshot
- from .resources import AWSSubnet
- from .resources import AWSVolume
- # Uncomment to enable logging by default for this module
- # import cloudbridge as cb
- # cb.set_stream_logger(__name__)
- class AWSSecurityService(BaseSecurityService):
- def __init__(self, provider):
- super(AWSSecurityService, self).__init__(provider)
- # Initialize provider services
- self._key_pairs = AWSKeyPairService(provider)
- self._security_groups = AWSSecurityGroupService(provider)
- @property
- def key_pairs(self):
- """
- Provides access to key pairs for this provider.
- :rtype: ``object`` of :class:`.KeyPairService`
- :return: a KeyPairService object
- """
- return self._key_pairs
- @property
- def security_groups(self):
- """
- Provides access to security groups for this provider.
- :rtype: ``object`` of :class:`.SecurityGroupService`
- :return: a SecurityGroupService object
- """
- return self._security_groups
- class AWSKeyPairService(BaseKeyPairService):
- def __init__(self, provider):
- super(AWSKeyPairService, self).__init__(provider)
- def get(self, key_pair_id):
- """
- Returns a KeyPair given its ID.
- """
- try:
- kps = self.provider.ec2_conn.get_all_key_pairs(
- keynames=[key_pair_id])
- return AWSKeyPair(self.provider, kps[0])
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidKeyPair.NotFound':
- return None
- elif ec2e.code == 'InvalidParameterValue':
- return None
- else:
- raise ec2e
- def list(self, limit=None, marker=None):
- """
- List all key pairs associated with this account.
- :rtype: ``list`` of :class:`.KeyPair`
- :return: list of KeyPair objects
- """
- key_pairs = [AWSKeyPair(self.provider, kp)
- for kp in self.provider.ec2_conn.get_all_key_pairs()]
- return ClientPagedResultList(self.provider, key_pairs,
- limit=limit, marker=marker)
- def find(self, name, limit=None, marker=None):
- """
- Searches for a key pair by a given list of attributes.
- """
- try:
- key_pairs = [
- AWSKeyPair(self.provider, kp) for kp in
- self.provider.ec2_conn.get_all_key_pairs(keynames=[name])]
- return ClientPagedResultList(self.provider, key_pairs,
- limit=limit, marker=marker)
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidKeyPair.NotFound':
- return []
- elif ec2e.code == 'InvalidParameterValue':
- return []
- else:
- raise ec2e
- def create(self, name):
- """
- Create a new key pair or raise an exception if one already exists.
- :type name: str
- :param name: The name of the key pair to be created.
- :rtype: ``object`` of :class:`.KeyPair`
- :return: A key pair instance or ``None`` if one was not be created.
- """
- kp = self.provider.ec2_conn.create_key_pair(name)
- if kp:
- return AWSKeyPair(self.provider, kp)
- return None
- class AWSSecurityGroupService(BaseSecurityGroupService):
- def __init__(self, provider):
- super(AWSSecurityGroupService, self).__init__(provider)
- def get(self, sg_id):
- """
- Returns a SecurityGroup given its id.
- """
- try:
- sgs = self.provider.ec2_conn.get_all_security_groups(
- group_ids=[sg_id])
- return AWSSecurityGroup(self.provider, sgs[0]) if sgs else None
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidGroup.NotFound':
- return None
- elif ec2e.code == 'InvalidGroupId.Malformed':
- return None
- else:
- raise ec2e
- def list(self, limit=None, marker=None):
- """
- List all security groups associated with this account.
- :rtype: ``list`` of :class:`.SecurityGroup`
- :return: list of SecurityGroup objects
- """
- sgs = [AWSSecurityGroup(self.provider, sg)
- for sg in self.provider.ec2_conn.get_all_security_groups()]
- return ClientPagedResultList(self.provider, sgs,
- limit=limit, marker=marker)
- def create(self, name, description, network_id):
- """
- Create a new SecurityGroup.
- :type name: str
- :param name: The name of the new security group.
- :type description: str
- :param description: The description of the new security group.
- :type network_id: ``str``
- :param network_id: The ID of the VPC under which to create the security
- group.
- :rtype: ``object`` of :class:`.SecurityGroup`
- :return: A SecurityGroup instance or ``None`` if one was not created.
- """
- sg = self.provider.ec2_conn.create_security_group(name, description,
- network_id)
- if sg:
- return AWSSecurityGroup(self.provider, sg)
- return None
- def find(self, name, limit=None, marker=None):
- """
- Get all security groups associated with your account.
- """
- flters = {'group-name': name}
- ec2_sgs = self.provider.ec2_conn.get_all_security_groups(
- filters=flters)
- sgs = [AWSSecurityGroup(self.provider, sg) for sg in ec2_sgs]
- return ClientPagedResultList(self.provider, sgs,
- limit=limit, marker=marker)
- def delete(self, group_id):
- """
- Delete an existing SecurityGroup.
- :type group_id: str
- :param group_id: The security group ID to be deleted.
- :rtype: ``bool``
- :return: ``True`` if the security group does not exist, ``False``
- otherwise. Note that this implies that the group may not have
- been deleted by this method but instead has not existed in
- the first place.
- """
- sg = self.get(group_id)
- if sg:
- sg.delete()
- return True
- return False
- class AWSBlockStoreService(BaseBlockStoreService):
- def __init__(self, provider):
- super(AWSBlockStoreService, self).__init__(provider)
- # Initialize provider services
- self._volume_svc = AWSVolumeService(self.provider)
- self._snapshot_svc = AWSSnapshotService(self.provider)
- @property
- def volumes(self):
- return self._volume_svc
- @property
- def snapshots(self):
- return self._snapshot_svc
- class AWSVolumeService(BaseVolumeService):
- def __init__(self, provider):
- super(AWSVolumeService, self).__init__(provider)
- def get(self, volume_id):
- """
- Returns a volume given its id.
- """
- try:
- vols = self.provider.ec2_conn.get_all_volumes(
- volume_ids=[volume_id])
- return AWSVolume(self.provider, vols[0]) if vols else None
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidVolume.NotFound':
- return None
- elif ec2e.code == 'InvalidParameterValue':
- # Occurs if volume_id does not start with 'vol-...'
- return None
- raise ec2e
- def find(self, name, limit=None, marker=None):
- """
- Searches for a volume by a given list of attributes.
- """
- filtr = {'tag:Name': name}
- aws_vols = self.provider.ec2_conn.get_all_volumes(filters=filtr)
- cb_vols = [AWSVolume(self.provider, vol) for vol in aws_vols]
- return ClientPagedResultList(self.provider, cb_vols,
- limit=limit, marker=marker)
- def list(self, limit=None, marker=None):
- """
- List all volumes.
- """
- aws_vols = self.provider.ec2_conn.get_all_volumes()
- cb_vols = [AWSVolume(self.provider, vol) for vol in aws_vols]
- return ClientPagedResultList(self.provider, cb_vols,
- limit=limit, marker=marker)
- def create(self, name, size, zone, snapshot=None, description=None):
- """
- Creates a new volume.
- """
- zone_id = zone.id if isinstance(zone, PlacementZone) else zone
- snapshot_id = snapshot.id if isinstance(
- snapshot, AWSSnapshot) and snapshot else snapshot
- ec2_vol = self.provider.ec2_conn.create_volume(
- size,
- zone_id,
- snapshot=snapshot_id)
- cb_vol = AWSVolume(self.provider, ec2_vol)
- cb_vol.name = name
- if description:
- cb_vol.description = description
- return cb_vol
- class AWSSnapshotService(BaseSnapshotService):
- def __init__(self, provider):
- super(AWSSnapshotService, self).__init__(provider)
- def get(self, snapshot_id):
- """
- Returns a snapshot given its id.
- """
- try:
- snaps = self.provider.ec2_conn.get_all_snapshots(
- snapshot_ids=[snapshot_id])
- return AWSSnapshot(self.provider, snaps[0]) if snaps else None
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidSnapshot.NotFound':
- return None
- elif ec2e.code == 'InvalidParameterValue':
- # Occurs if snapshot_id does not start with 'snap-...'
- return None
- raise ec2e
- def find(self, name, limit=None, marker=None):
- """
- Searches for a snapshot by a given list of attributes.
- """
- filtr = {'tag-value': name}
- snaps = [AWSSnapshot(self.provider, snap) for snap in
- self.provider.ec2_conn.get_all_snapshots(filters=filtr)]
- return ClientPagedResultList(self.provider, snaps,
- limit=limit, marker=marker)
- def list(self, limit=None, marker=None):
- """
- List all snapshots.
- """
- snaps = [AWSSnapshot(self.provider, snap)
- for snap in self.provider.ec2_conn.get_all_snapshots(
- owner='self')]
- return ClientPagedResultList(self.provider, snaps,
- limit=limit, marker=marker)
- def create(self, name, volume, description=None):
- """
- Creates a new snapshot of a given volume.
- """
- volume_id = volume.id if isinstance(volume, AWSVolume) else volume
- ec2_snap = self.provider.ec2_conn.create_snapshot(
- volume_id,
- description=description)
- cb_snap = AWSSnapshot(self.provider, ec2_snap)
- cb_snap.name = name
- if description:
- cb_snap.description = description
- return cb_snap
- class AWSObjectStoreService(BaseObjectStoreService):
- def __init__(self, provider):
- super(AWSObjectStoreService, self).__init__(provider)
- def get(self, bucket_id):
- """
- Returns a bucket given its ID. Returns ``None`` if the bucket
- does not exist.
- """
- try:
- # Make a call to make sure the bucket exists. While this would
- # normally return a Bucket instance, there's an edge case where a
- # 403 response can occur when the bucket exists but the
- # user simply does not have permissions to access it. See below.
- bucket = self.provider.s3_conn.get_bucket(bucket_id)
- return AWSBucket(self.provider, bucket)
- except S3ResponseError as e:
- # If 403, it means the bucket exists, but the user does not have
- # permissions to access the bucket. However, limited operations
- # may be permitted (with a session token for example), so return a
- # Bucket instance to allow further operations.
- # http://stackoverflow.com/questions/32331456/using-boto-upload-file-to-s3-
- # sub-folder-when-i-have-no-permissions-on-listing-fo
- if e.status == 403:
- bucket = self.provider.s3_conn.get_bucket(bucket_id,
- validate=False)
- return AWSBucket(self.provider, bucket)
- # For all other responses, it's assumed that the bucket does not exist.
- return None
- def find(self, name, limit=None, marker=None):
- """
- Searches for a bucket by a given list of attributes.
- """
- buckets = [AWSBucket(self.provider, bucket)
- for bucket in self.provider.s3_conn.get_all_buckets()
- if name in bucket.name]
- return ClientPagedResultList(self.provider, buckets,
- limit=limit, marker=marker)
- def list(self, limit=None, marker=None):
- """
- List all containers.
- """
- buckets = [AWSBucket(self.provider, bucket)
- for bucket in self.provider.s3_conn.get_all_buckets()]
- return ClientPagedResultList(self.provider, buckets,
- limit=limit, marker=marker)
- def create(self, name, location=None):
- """
- Create a new bucket.
- """
- bucket = self.provider.s3_conn.create_bucket(
- name,
- location=location if location else '')
- return AWSBucket(self.provider, bucket)
- class AWSImageService(BaseImageService):
- def __init__(self, provider):
- super(AWSImageService, self).__init__(provider)
- def get(self, image_id):
- """
- Returns an Image given its id
- """
- try:
- image = self.provider.ec2_conn.get_image(image_id)
- return AWSMachineImage(self.provider, image) if image else None
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidAMIID.NotFound':
- return None
- elif ec2e.code == 'InvalidAMIID.Malformed':
- # Occurs if image_id does not start with 'ami-...'
- return None
- raise ec2e
- def find(self, name, limit=None, marker=None):
- """
- Searches for an image by a given list of attributes
- """
- filters = {'name': name}
- images = [AWSMachineImage(self.provider, image) for image in
- self.provider.ec2_conn.get_all_images(filters=filters)]
- return ClientPagedResultList(self.provider, images,
- limit=limit, marker=marker)
- def list(self, limit=None, marker=None):
- """
- List all images.
- """
- images = [AWSMachineImage(self.provider, image)
- for image in self.provider.ec2_conn.get_all_images()]
- return ClientPagedResultList(self.provider, images,
- limit=limit, marker=marker)
- class AWSComputeService(BaseComputeService):
- def __init__(self, provider):
- super(AWSComputeService, self).__init__(provider)
- self._instance_type_svc = AWSInstanceTypesService(self.provider)
- self._instance_svc = AWSInstanceService(self.provider)
- self._region_svc = AWSRegionService(self.provider)
- self._images_svc = AWSImageService(self.provider)
- @property
- def images(self):
- return self._images_svc
- @property
- def instance_types(self):
- return self._instance_type_svc
- @property
- def instances(self):
- return self._instance_svc
- @property
- def regions(self):
- return self._region_svc
- class AWSInstanceService(BaseInstanceService):
- def __init__(self, provider):
- super(AWSInstanceService, self).__init__(provider)
- def create(self, name, image, instance_type, subnet, zone=None,
- key_pair=None, security_groups=None, user_data=None,
- launch_config=None, **kwargs):
- image_id = image.id if isinstance(image, MachineImage) else image
- instance_size = instance_type.id if \
- isinstance(instance_type, InstanceType) else instance_type
- subnet = (self.provider.network.subnets.get(subnet)
- if isinstance(subnet, str) else subnet)
- zone_id = zone.id if isinstance(zone, PlacementZone) else zone
- key_pair_name = key_pair.name if isinstance(
- key_pair,
- KeyPair) else key_pair
- if launch_config:
- bdm = self._process_block_device_mappings(launch_config, zone_id)
- else:
- bdm = None
- subnet_id, zone_id, security_group_ids = \
- self._resolve_launch_options(subnet, zone_id, security_groups)
- reservation = self.provider.ec2_conn.run_instances(
- image_id=image_id, instance_type=instance_size,
- min_count=1, max_count=1, placement=zone_id,
- key_name=key_pair_name, security_group_ids=security_group_ids,
- user_data=user_data, block_device_map=bdm, subnet_id=subnet_id)
- instance = None
- if reservation:
- instance = AWSInstance(self.provider, reservation.instances[0])
- instance.wait_for(
- [InstanceState.PENDING, InstanceState.RUNNING],
- terminal_states=[InstanceState.TERMINATED,
- InstanceState.ERROR])
- instance.name = name
- return instance
- def _resolve_launch_options(self, subnet=None, zone_id=None,
- security_groups=None):
- """
- Work out interdependent launch options.
- Some launch options are required and interdependent so make sure
- they conform to the interface contract.
- :type subnet: ``Subnet``
- :param subnet: Subnet object within which to launch.
- :type zone_id: ``str``
- :param zone_id: ID of the zone where the launch should happen.
- :type security_groups: ``list`` of ``id``
- :param zone_id: List of security group IDs.
- :rtype: triplet of ``str``
- :return: Subnet ID, zone ID and security group IDs for launch.
- :raise ValueError: In case a conflicting combination is found.
- """
- if subnet:
- # subnet's zone takes precedence
- zone_id = subnet.zone.id
- if isinstance(security_groups, list) and isinstance(
- security_groups[0], SecurityGroup):
- security_group_ids = [sg.id for sg in security_groups]
- else:
- security_group_ids = security_groups
- return subnet.id, zone_id, security_group_ids
- def _process_block_device_mappings(self, launch_config, zone=None):
- """
- Processes block device mapping information
- and returns a Boto BlockDeviceMapping object. If new volumes
- are requested (source is None and destination is VOLUME), they will be
- created and the relevant volume ids included in the mapping.
- """
- bdm = BlockDeviceMapping()
- # Assign letters from f onwards
- # http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/device_naming.html
- next_letter = iter(list(string.ascii_lowercase[6:]))
- # assign ephemeral devices from 0 onwards
- ephemeral_counter = 0
- for device in launch_config.block_devices:
- bd_type = BlockDeviceType()
- if device.is_volume:
- if device.is_root:
- bdm['/dev/sda1'] = bd_type
- else:
- bdm['sd' + next(next_letter)] = bd_type
- if isinstance(device.source, Snapshot):
- bd_type.snapshot_id = device.source.id
- elif isinstance(device.source, Volume):
- bd_type.volume_id = device.source.id
- elif isinstance(device.source, MachineImage):
- # Not supported
- pass
- else:
- # source is None, but destination is volume, therefore
- # create a blank volume. If the Zone is None, this
- # could fail since the volume and instance may be created
- # in two different zones.
- if not zone:
- raise InvalidConfigurationException(
- "A zone must be specified when launching with a"
- " new blank volume block device mapping.")
- new_vol = self.provider.block_store.volumes.create(
- '',
- device.size,
- zone)
- bd_type.volume_id = new_vol.id
- bd_type.delete_on_terminate = device.delete_on_terminate
- if device.size:
- bd_type.size = device.size
- else: # device is ephemeral
- bd_type.ephemeral_name = 'ephemeral%s' % ephemeral_counter
- return bdm
- def create_launch_config(self):
- return AWSLaunchConfig(self.provider)
- def get(self, instance_id):
- """
- Returns an instance given its id. Returns None
- if the object does not exist.
- """
- try:
- reservation = self.provider.ec2_conn.get_all_reservations(
- instance_ids=[instance_id])
- return (AWSInstance(self.provider, reservation[0].instances[0])
- if reservation else None)
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidInstanceID.NotFound':
- return None
- elif ec2e.code == 'InvalidParameterValue':
- # Occurs if id does not start with 'inst-...'
- return None
- raise ec2e
- def find(self, name, limit=None, marker=None):
- """
- Searches for an instance by a given list of attributes.
- :rtype: ``object`` of :class:`.Instance`
- :return: an Instance object
- """
- filtr = {'tag:Name': name}
- reservations = self.provider.ec2_conn.get_all_reservations(
- filters=filtr,
- max_results=limit,
- next_token=marker)
- instances = [AWSInstance(self.provider, inst)
- for res in reservations
- for inst in res.instances]
- return ServerPagedResultList(reservations.is_truncated,
- reservations.next_token,
- False, data=instances)
- def list(self, limit=None, marker=None):
- """
- List all instances.
- """
- reservations = self.provider.ec2_conn.get_all_reservations(
- max_results=limit,
- next_token=marker)
- instances = [AWSInstance(self.provider, inst)
- for res in reservations
- for inst in res.instances]
- return ServerPagedResultList(reservations.is_truncated,
- reservations.next_token,
- False, data=instances)
- class AWSInstanceTypesService(BaseInstanceTypesService):
- def __init__(self, provider):
- super(AWSInstanceTypesService, self).__init__(provider)
- @property
- def instance_data(self):
- """
- Fetch info about the available instances.
- To update this information, update the file pointed to by the
- ``provider.AWS_INSTANCE_DATA_DEFAULT_URL`` above. The content for this
- file should be obtained from this repo:
- https://github.com/powdahound/ec2instances.info (in particular, this
- file: https://raw.githubusercontent.com/powdahound/ec2instances.info/
- master/www/instances.json).
- TODO: Needs a caching function with timeout
- """
- r = requests.get(self.provider.config.get(
- "aws_instance_info_url",
- self.provider.AWS_INSTANCE_DATA_DEFAULT_URL))
- return r.json()
- def list(self, limit=None, marker=None):
- inst_types = [AWSInstanceType(self.provider, inst_type)
- for inst_type in self.instance_data]
- return ClientPagedResultList(self.provider, inst_types,
- limit=limit, marker=marker)
- class AWSRegionService(BaseRegionService):
- def __init__(self, provider):
- super(AWSRegionService, self).__init__(provider)
- def get(self, region_id):
- region = [r for r in self if r.id == region_id]
- if region:
- return region[0]
- else:
- return None
- def list(self, limit=None, marker=None):
- regions = [AWSRegion(self.provider, region)
- for region in self.provider.ec2_conn.get_all_regions()]
- return ClientPagedResultList(self.provider, regions,
- limit=limit, marker=marker)
- @property
- def current(self):
- return self.get(self._provider.region_name)
- class AWSNetworkingService(BaseNetworkingService):
- def __init__(self, provider):
- super(AWSNetworkingService, self).__init__(provider)
- self._network_service = AWSNetworkService(self.provider)
- self._subnet_service = AWSSubnetService(self.provider)
- self._router_service = AWSRouterService(self.provider)
- self._gateway_service = AWSGatewayService(self.provider)
- @property
- def networks(self):
- return self._network_service
- @property
- def subnets(self):
- return self._subnet_service
- @property
- def routers(self):
- return self._router_service
- @property
- def gateways(self):
- return self._gateway_service
- class AWSNetworkService(BaseNetworkService):
- def __init__(self, provider):
- super(AWSNetworkService, self).__init__(provider)
- self._subnet_svc = AWSSubnetService(self.provider)
- def get(self, network_id):
- try:
- network = self.provider.vpc_conn.get_all_vpcs(vpc_ids=[network_id])
- return AWSNetwork(self.provider, network[0]) if network else None
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidVpcID.NotFound':
- return None
- elif ec2e.code == 'InvalidParameterValue':
- # Occurs if id does not start with 'vpc-...'
- return None
- raise ec2e
- def list(self, limit=None, marker=None):
- networks = [AWSNetwork(self.provider, network)
- for network in self.provider.vpc_conn.get_all_vpcs()]
- return ClientPagedResultList(self.provider, networks,
- limit=limit, marker=marker)
- def find(self, name, limit=None, marker=None):
- filtr = {'tag:Name': name}
- networks = [AWSNetwork(self.provider, network)
- for network in self.provider.vpc_conn.get_all_vpcs(
- filters=filtr)]
- return ClientPagedResultList(self.provider, networks,
- limit=limit, marker=marker)
- def create(self, name, cidr_block):
- network = self.provider.vpc_conn.create_vpc(cidr_block=cidr_block)
- cb_network = AWSNetwork(self.provider, network)
- if name:
- cb_network.wait_for(
- [NetworkState.PENDING, NetworkState.AVAILABLE],
- terminal_states=[NetworkState.ERROR])
- cb_network.name = name
- return cb_network
- @property
- def subnets(self):
- return self._subnet_svc
- @property
- def floating_ips(self):
- # fltrs = None
- # if network_id:
- # fltrs = {'network-interface-id': network_id}
- al = self.provider.vpc_conn.get_all_addresses()
- return [AWSFloatingIP(self.provider, a) for a in al]
- def create_floating_ip(self):
- ip = self.provider.ec2_conn.allocate_address(domain='vpc')
- return AWSFloatingIP(self.provider, ip)
- def routers(self):
- routers = self.provider.vpc_conn.get_all_internet_gateways()
- return [AWSRouter(self.provider, r) for r in routers]
- def create_router(self, name=None):
- router = self.provider.vpc_conn.create_internet_gateway()
- cb_router = AWSRouter(self.provider, router)
- if name:
- time.sleep(2) # Some time is required
- cb_router.name = name
- return cb_router
- class AWSSubnetService(BaseSubnetService):
- def __init__(self, provider):
- super(AWSSubnetService, self).__init__(provider)
- def get(self, subnet_id):
- try:
- subnets = self.provider.vpc_conn.get_all_subnets([subnet_id])
- return AWSSubnet(self.provider, subnets[0]) if subnets else None
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidSubnetID.NotFound':
- return None
- elif ec2e.code == 'InvalidParameterValue':
- # Occurs if id does not start with 'subnet-...'
- return None
- raise ec2e
- def list(self, network=None, limit=None, marker=None):
- fltr = None
- if network:
- network_id = (network.id if isinstance(network, AWSNetwork) else
- network)
- fltr = {'vpc-id': network_id}
- subnets = [AWSSubnet(self.provider, subnet) for subnet in
- self.provider.vpc_conn.get_all_subnets(filters=fltr)]
- return ClientPagedResultList(self.provider, subnets,
- limit=limit, marker=marker)
- def create(self, name, network, cidr_block, zone=None):
- network_id = network.id if isinstance(network, AWSNetwork) else network
- subnet = self.provider.vpc_conn.create_subnet(network_id, cidr_block,
- availability_zone=zone)
- cb_subnet = AWSSubnet(self.provider, subnet)
- if name:
- cb_subnet.wait_for(
- [SubnetState.PENDING, SubnetState.AVAILABLE],
- terminal_states=[SubnetState.ERROR])
- cb_subnet.name = name
- return cb_subnet
- def get_or_create_default(self, zone=None):
- filtr = {'availabilityZone': zone} if zone else None
- sns = self.provider.vpc_conn.get_all_subnets(filters=filtr)
- for sn in sns:
- if sn.defaultForAz:
- return AWSSubnet(self.provider, sn)
- # No provider-default Subnet exists, look for a library-default one
- for sn in sns:
- if sn.tags.get('Name') == AWSSubnet.CB_DEFAULT_SUBNET_NAME:
- return AWSSubnet(self.provider, sn)
- # No provider-default Subnet exists, try to create it (net + subnets)
- default_net = self.provider.network.create(
- name=AWSNetwork.CB_DEFAULT_NETWORK_NAME, cidr_block='10.0.0.0/16')
- # Create a subnet in each of the region's zones
- region = self.provider.compute.regions.get(
- self.provider.vpc_conn.region.name)
- default_sn = None
- for i, z in enumerate(region.zones):
- sn = self.create(AWSSubnet.CB_DEFAULT_SUBNET_NAME, default_net,
- '10.0.{0}.0/24'.format(i), z.name)
- if zone and zone == z.name:
- default_sn = sn
- # No specific zone was supplied; return the last created subnet
- if not default_sn:
- default_sn = sn
- return default_sn
- def delete(self, subnet):
- subnet_id = subnet.id if isinstance(subnet, AWSSubnet) else subnet
- return self.provider.vpc_conn.delete_subnet(subnet_id=subnet_id)
- class AWSRouterService(BaseRouterService):
- """For AWS, a CloudBridge router corresponds to an AWS Route Table."""
- def __init__(self, provider):
- super(AWSRouterService, self).__init__(provider)
- def get(self, router_id):
- try:
- routers = self.provider.vpc_conn.get_all_route_tables([router_id])
- return AWSRouter(self.provider, routers[0]) if routers else None
- except EC2ResponseError as ec2e:
- if ec2e.code == 'InvalidRouteTableID.NotFound':
- return None
- elif ec2e.code == 'InvalidParameterValue':
- # Occurs if id does not start with 'rtb-...'
- return None
- raise ec2e
- def find(self, name, limit=None, marker=None):
- filtr = {'tag:Name': name}
- routers = self.provider.vpc_conn.get_all_route_tables(filters=filtr)
- aws_routers = [AWSRouter(self.provider, r) for r in routers]
- return ClientPagedResultList(self.provider, aws_routers, limit=limit,
- marker=marker)
- def list(self, limit=None, marker=None):
- routers = self.provider.vpc_conn.get_all_route_tables()
- aws_routers = [AWSRouter(self.provider, r) for r in routers]
- return ClientPagedResultList(self.provider, aws_routers, limit=limit,
- marker=marker)
- def create(self, name, network):
- network_id = network.id if isinstance(network, AWSNetwork) else network
- router = self.provider.vpc_conn.create_route_table(vpc_id=network_id)
- cb_router = AWSRouter(self.provider, router)
- if name:
- time.sleep(2) # Some time is required
- cb_router.name = name
- return cb_router
- class AWSGatewayService(BaseGatewayService):
- def __init__(self, provider):
- super(AWSGatewayService, self).__init__(provider)
- def get_or_create_inet_gateway(self, name):
- gateway = self.provider.vpc_conn.create_internet_gateway()
- cb_gateway = AWSInternetGateway(self.provider, gateway)
- cb_gateway.wait_till_ready()
- cb_gateway.name = name
- return cb_gateway
- def delete(self, gateway):
- gateway.delete()
|