| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033 |
- """
- Services implemented by the OpenStack provider.
- """
- import logging
- from cinderclient.exceptions import NotFound as CinderNotFound
- from neutronclient.common.exceptions import NeutronClientException
- from neutronclient.common.exceptions import PortNotFoundClient
- from novaclient.exceptions import NotFound as NovaNotFound
- from openstack.exceptions import NotFoundException
- from openstack.exceptions import ResourceNotFound
- from swiftclient import ClientException as SwiftClientException
- import cloudbridge.cloud.base.helpers as cb_helpers
- from cloudbridge.cloud.base.middleware import implement
- from cloudbridge.cloud.base.resources import BaseLaunchConfig
- from cloudbridge.cloud.base.resources import ClientPagedResultList
- from cloudbridge.cloud.base.services import BaseBucketObjectService
- from cloudbridge.cloud.base.services import BaseBucketService
- from cloudbridge.cloud.base.services import BaseComputeService
- from cloudbridge.cloud.base.services import BaseImageService
- from cloudbridge.cloud.base.services import BaseInstanceService
- from cloudbridge.cloud.base.services import BaseKeyPairService
- from cloudbridge.cloud.base.services import BaseNetworkService
- from cloudbridge.cloud.base.services import BaseNetworkingService
- from cloudbridge.cloud.base.services import BaseRegionService
- from cloudbridge.cloud.base.services import BaseRouterService
- from cloudbridge.cloud.base.services import BaseSecurityService
- from cloudbridge.cloud.base.services import BaseSnapshotService
- from cloudbridge.cloud.base.services import BaseStorageService
- from cloudbridge.cloud.base.services import BaseSubnetService
- from cloudbridge.cloud.base.services import BaseVMFirewallService
- from cloudbridge.cloud.base.services import BaseVMTypeService
- from cloudbridge.cloud.base.services import BaseVolumeService
- from cloudbridge.cloud.interfaces.exceptions \
- import DuplicateResourceException
- from cloudbridge.cloud.interfaces.resources import KeyPair
- from cloudbridge.cloud.interfaces.resources import MachineImage
- from cloudbridge.cloud.interfaces.resources import Network
- from cloudbridge.cloud.interfaces.resources import PlacementZone
- from cloudbridge.cloud.interfaces.resources import Snapshot
- from cloudbridge.cloud.interfaces.resources import Subnet
- from cloudbridge.cloud.interfaces.resources import VMFirewall
- from cloudbridge.cloud.interfaces.resources import VMType
- from cloudbridge.cloud.interfaces.resources import Volume
- from cloudbridge.cloud.providers.openstack import helpers as oshelpers
- from .resources import OpenStackBucket
- from .resources import OpenStackBucketObject
- from .resources import OpenStackInstance
- from .resources import OpenStackKeyPair
- from .resources import OpenStackMachineImage
- from .resources import OpenStackNetwork
- from .resources import OpenStackRegion
- from .resources import OpenStackRouter
- from .resources import OpenStackSnapshot
- from .resources import OpenStackSubnet
- from .resources import OpenStackVMFirewall
- from .resources import OpenStackVMType
- from .resources import OpenStackVolume
- log = logging.getLogger(__name__)
- class OpenStackSecurityService(BaseSecurityService):
- def __init__(self, provider):
- super(OpenStackSecurityService, self).__init__(provider)
- # Initialize provider services
- self._key_pairs = OpenStackKeyPairService(provider)
- self._vm_firewalls = OpenStackVMFirewallService(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 vm_firewalls(self):
- """
- Provides access to VM firewalls for this provider.
- :rtype: ``object`` of :class:`.VMFirewallService`
- :return: a VMFirewallService object
- """
- return self._vm_firewalls
- def get_or_create_ec2_credentials(self):
- """
- A provider specific method than returns the ec2 credentials for the
- current user, or creates a new pair if one doesn't exist.
- """
- keystone = self.provider.keystone
- if hasattr(keystone, 'ec2'):
- user_id = keystone.session.get_user_id()
- user_creds = [cred for cred in keystone.ec2.list(user_id) if
- cred.tenant_id == keystone.session.get_project_id()]
- if user_creds:
- return user_creds[0]
- else:
- return keystone.ec2.create(
- user_id, keystone.session.get_project_id())
- return None
- def get_ec2_endpoints(self):
- """
- A provider specific method than returns the ec2 endpoints if
- available.
- """
- keystone = self.provider.keystone
- ec2_url = keystone.session.get_endpoint(service_type='ec2')
- s3_url = keystone.session.get_endpoint(service_type='s3')
- return {'ec2_endpoint': ec2_url,
- 's3_endpoint': s3_url}
- class OpenStackKeyPairService(BaseKeyPairService):
- def __init__(self, provider):
- super(OpenStackKeyPairService, self).__init__(provider)
- @implement(event_pattern="provider.security.key_pairs.get",
- priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
- def _get(self, key_pair_id):
- """
- Returns a KeyPair given its id.
- """
- log.debug("Returning KeyPair with the id %s", key_pair_id)
- try:
- return OpenStackKeyPair(
- self.provider, self.provider.nova.keypairs.get(key_pair_id))
- except NovaNotFound:
- log.debug("KeyPair %s was not found.", key_pair_id)
- return None
- @implement(event_pattern="provider.security.key_pairs.list",
- priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
- def _list(self, limit=None, marker=None):
- """
- List all key pairs associated with this account.
- :rtype: ``list`` of :class:`.KeyPair`
- :return: list of KeyPair objects
- """
- keypairs = self.provider.nova.keypairs.list()
- results = [OpenStackKeyPair(self.provider, kp)
- for kp in keypairs]
- log.debug("Listing all key pairs associated with OpenStack "
- "Account: %s", results)
- return ClientPagedResultList(self.provider, results,
- limit=limit, marker=marker)
- @implement(event_pattern="provider.security.key_pairs.find",
- priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
- def _find(self, **kwargs):
- name = kwargs.pop('name', None)
- # All kwargs should have been popped at this time.
- if len(kwargs) > 0:
- raise TypeError("Unrecognised parameters for search: %s."
- " Supported attributes: %s" % (kwargs, 'name'))
- keypairs = self.provider.nova.keypairs.findall(name=name)
- results = [OpenStackKeyPair(self.provider, kp)
- for kp in keypairs]
- log.debug("Searching for %s in: %s", name, keypairs)
- return ClientPagedResultList(self.provider, results)
- @implement(event_pattern="provider.security.key_pairs.create",
- priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
- def _create(self, name, public_key_material=None):
- existing_kp = self.find(name=name)
- if existing_kp:
- raise DuplicateResourceException(
- 'Keypair already exists with name {0}'.format(name))
- private_key = None
- if not public_key_material:
- public_key_material, private_key = cb_helpers.generate_key_pair()
- kp = self.provider.nova.keypairs.create(name,
- public_key=public_key_material)
- cb_kp = OpenStackKeyPair(self.provider, kp)
- cb_kp.material = private_key
- return cb_kp
- @implement(event_pattern="provider.security.key_pairs.delete",
- priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
- def _delete(self, key_pair_id):
- os_kp = self.provider.nova.keypairs.get(key_pair_id)
- os_kp.delete()
- class OpenStackVMFirewallService(BaseVMFirewallService):
- def __init__(self, provider):
- super(OpenStackVMFirewallService, self).__init__(provider)
- @implement(event_pattern="provider.security.vm_firewalls.get",
- priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
- def _get(self, vm_firewall_id):
- try:
- return OpenStackVMFirewall(
- self.provider,
- self.provider.os_conn.network
- .get_security_group(vm_firewall_id))
- except (ResourceNotFound, NotFoundException):
- log.debug("Firewall %s not found.", vm_firewall_id)
- return None
- @implement(event_pattern="provider.security.vm_firewalls.list",
- priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
- def _list(self, limit=None, marker=None):
- firewalls = [
- OpenStackVMFirewall(self.provider, fw)
- for fw in self.provider.os_conn.network.security_groups()]
- return ClientPagedResultList(self.provider, firewalls,
- limit=limit, marker=marker)
- @cb_helpers.deprecated_alias(network_id='network')
- @implement(event_pattern="provider.security.vm_firewalls.create",
- priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
- def _create(self, label, network, description=None):
- net = network.id if isinstance(network, Network) else network
- # We generally simulate a network being associated with a firewall
- # by storing the supplied value in the firewall description field that
- # is not modifiable after creation; however, because of some networking
- # specificity in Nectar, we must also allow an empty network id value.
- if not net:
- net = ""
- if not description:
- description = ""
- description += " [{}{}]".format(OpenStackVMFirewall._network_id_tag,
- net)
- sg = self.provider.os_conn.network.create_security_group(
- name=label, description=description)
- if sg:
- return OpenStackVMFirewall(self.provider, sg)
- return None
- @implement(event_pattern="provider.security.vm_firewalls.delete",
- priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
- def _delete(self, vm_firewall_id):
- try:
- os_fw = self.provider.os_conn.network.get_security_group(
- vm_firewall_id)
- os_fw.delete(self.provider.os_conn.session)
- return True
- except (ResourceNotFound, NotFoundException):
- log.debug("Firewall %s not found.", vm_firewall_id)
- return True
- class OpenStackStorageService(BaseStorageService):
- def __init__(self, provider):
- super(OpenStackStorageService, self).__init__(provider)
- # Initialize provider services
- self._volume_svc = OpenStackVolumeService(self.provider)
- self._snapshot_svc = OpenStackSnapshotService(self.provider)
- self._bucket_svc = OpenStackBucketService(self.provider)
- self._bucket_obj_svc = OpenStackBucketObjectService(self.provider)
- @property
- def volumes(self):
- return self._volume_svc
- @property
- def snapshots(self):
- return self._snapshot_svc
- @property
- def buckets(self):
- return self._bucket_svc
- @property
- def bucket_objects(self):
- return self._bucket_obj_svc
- class OpenStackVolumeService(BaseVolumeService):
- def __init__(self, provider):
- super(OpenStackVolumeService, self).__init__(provider)
- @implement(event_pattern="provider.storage.volumes.get",
- priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
- def _get(self, volume_id):
- try:
- return OpenStackVolume(
- self.provider, self.provider.cinder.volumes.get(volume_id))
- except CinderNotFound:
- log.debug("Volume %s was not found.", volume_id)
- return None
- @implement(event_pattern="provider.storage.volumes.find",
- priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
- def _find(self, **kwargs):
- label = kwargs.pop('label', None)
- # All kwargs should have been popped at this time.
- if len(kwargs) > 0:
- raise TypeError("Unrecognised parameters for search: %s."
- " Supported attributes: %s" % (kwargs, 'label'))
- log.debug("Searching for an OpenStack Volume with the label %s", label)
- search_opts = {'name': label}
- cb_vols = [
- OpenStackVolume(self.provider, vol)
- for vol in self.provider.cinder.volumes.list(
- search_opts=search_opts,
- limit=oshelpers.os_result_limit(self.provider),
- marker=None)]
- return oshelpers.to_server_paged_list(self.provider, cb_vols)
- @implement(event_pattern="provider.storage.volumes.list",
- priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
- def _list(self, limit=None, marker=None):
- cb_vols = [
- OpenStackVolume(self.provider, vol)
- for vol in self.provider.cinder.volumes.list(
- limit=oshelpers.os_result_limit(self.provider, limit),
- marker=marker)]
- return oshelpers.to_server_paged_list(self.provider, cb_vols, limit)
- @implement(event_pattern="provider.storage.volumes.create",
- priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
- def _create(self, label, size, zone, snapshot=None, description=None):
- zone_id = zone.id if isinstance(zone, PlacementZone) else zone
- snapshot_id = snapshot.id if isinstance(
- snapshot, OpenStackSnapshot) and snapshot else snapshot
- os_vol = self.provider.cinder.volumes.create(
- size, name=label, description=description,
- availability_zone=zone_id, snapshot_id=snapshot_id)
- return OpenStackVolume(self.provider, os_vol)
- @implement(event_pattern="provider.storage.volumes.delete",
- priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
- def _delete(self, volume_id):
- os_vol = self.provider.cinder.volumes.get(volume_id)
- os_vol.delete()
- class OpenStackSnapshotService(BaseSnapshotService):
- def __init__(self, provider):
- super(OpenStackSnapshotService, self).__init__(provider)
- @implement(event_pattern="provider.storage.snapshots.get",
- priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
- def _get(self, snapshot_id):
- try:
- return OpenStackSnapshot(
- self.provider,
- self.provider.cinder.volume_snapshots.get(snapshot_id))
- except CinderNotFound:
- log.debug("Snapshot %s was not found.", snapshot_id)
- return None
- @implement(event_pattern="provider.storage.snapshots.find",
- priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
- def _find(self, **kwargs):
- label = kwargs.pop('label', None)
- # All kwargs should have been popped at this time.
- if len(kwargs) > 0:
- raise TypeError("Unrecognised parameters for search: %s."
- " Supported attributes: %s" % (kwargs, 'label'))
- search_opts = {'name': label, # TODO: Cinder is ignoring name
- 'limit': oshelpers.os_result_limit(self.provider),
- 'marker': None}
- log.debug("Searching for an OpenStack snapshot with the following "
- "params: %s", search_opts)
- cb_snaps = [
- OpenStackSnapshot(self.provider, snap) for
- snap in self.provider.cinder.volume_snapshots.list(search_opts)
- if snap.name == label]
- return oshelpers.to_server_paged_list(self.provider, cb_snaps)
- @implement(event_pattern="provider.storage.snapshots.list",
- priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
- def _list(self, limit=None, marker=None):
- cb_snaps = [
- OpenStackSnapshot(self.provider, snap) for
- snap in self.provider.cinder.volume_snapshots.list(
- search_opts={'limit': oshelpers.os_result_limit(self.provider,
- limit),
- 'marker': marker})]
- return oshelpers.to_server_paged_list(self.provider, cb_snaps, limit)
- @implement(event_pattern="provider.storage.snapshots.create",
- priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
- def _create(self, label, volume, description=None):
- volume_id = (volume.id if isinstance(volume, OpenStackVolume)
- else volume)
- os_snap = self.provider.cinder.volume_snapshots.create(
- volume_id, name=label,
- description=description)
- return OpenStackSnapshot(self.provider, os_snap)
- @implement(event_pattern="provider.storage.snapshots.delete",
- priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
- def _delete(self, snapshot_id):
- os_snap = self.provider.cinder.volume_snapshots.get(snapshot_id)
- os_snap.delete()
- class OpenStackBucketService(BaseBucketService):
- def __init__(self, provider):
- super(OpenStackBucketService, self).__init__(provider)
- @implement(event_pattern="provider.storage.buckets.get",
- priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
- def _get(self, bucket_id):
- """
- Returns a bucket given its ID. Returns ``None`` if the bucket
- does not exist.
- """
- _, container_list = self.provider.swift.get_account(
- prefix=bucket_id)
- if container_list:
- return OpenStackBucket(self.provider,
- next((c for c in container_list
- if c['name'] == bucket_id), None))
- else:
- log.debug("Bucket %s was not found.", bucket_id)
- return None
- @implement(event_pattern="provider.storage.buckets.find",
- priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
- def _find(self, **kwargs):
- name = kwargs.pop('name', None)
- # All kwargs should have been popped at this time.
- if len(kwargs) > 0:
- raise TypeError("Unrecognised parameters for search: %s."
- " Supported attributes: %s" % (kwargs, 'name'))
- _, container_list = self.provider.swift.get_account()
- cb_buckets = [OpenStackBucket(self.provider, c)
- for c in container_list
- if name in c.get("name")]
- return oshelpers.to_server_paged_list(self.provider, cb_buckets)
- @implement(event_pattern="provider.storage.buckets.list",
- priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
- def _list(self, limit, marker):
- _, container_list = self.provider.swift.get_account(
- limit=oshelpers.os_result_limit(self.provider, limit),
- marker=marker)
- cb_buckets = [OpenStackBucket(self.provider, c)
- for c in container_list]
- return oshelpers.to_server_paged_list(self.provider, cb_buckets, limit)
- @implement(event_pattern="provider.storage.buckets.create",
- priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
- def _create(self, name, location):
- OpenStackBucket.assert_valid_resource_name(name)
- location = location or self.provider.region_name
- try:
- self.provider.swift.head_container(name)
- raise DuplicateResourceException(
- 'Bucket already exists with name {0}'.format(name))
- except SwiftClientException:
- self.provider.swift.put_container(name)
- return self.get(name)
- @implement(event_pattern="provider.storage.buckets.delete",
- priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
- def _delete(self, bucket_id):
- self.provider.swift.delete_container(bucket_id)
- class OpenStackBucketObjectService(BaseBucketObjectService):
- def __init__(self, provider):
- super(OpenStackBucketObjectService, self).__init__(provider)
- def get(self, bucket, name):
- """
- Retrieve a given object from this bucket.
- """
- # Swift always returns a reference for the container first,
- # followed by a list containing references to objects.
- _, object_list = self.provider.swift.get_container(
- bucket.name, prefix=name)
- # Loop through list of objects looking for an exact name vs. a prefix
- for obj in object_list:
- if obj.get('name') == name:
- return OpenStackBucketObject(self.provider,
- bucket,
- obj)
- return None
- def list(self, bucket, limit=None, marker=None, prefix=None):
- """
- List all objects within this bucket.
- :rtype: BucketObject
- :return: List of all available BucketObjects within this bucket.
- """
- _, object_list = self.provider.swift.get_container(
- bucket.name,
- limit=oshelpers.os_result_limit(self.provider, limit),
- marker=marker, prefix=prefix)
- cb_objects = [OpenStackBucketObject(
- self.provider, bucket, obj) for obj in object_list]
- return oshelpers.to_server_paged_list(
- self.provider,
- cb_objects,
- limit)
- def find(self, bucket, **kwargs):
- _, obj_list = self.provider.swift.get_container(bucket.name)
- cb_objs = [OpenStackBucketObject(self.provider, bucket, obj)
- for obj in obj_list]
- filters = ['name']
- matches = cb_helpers.generic_find(filters, kwargs, cb_objs)
- return ClientPagedResultList(self.provider, list(matches))
- def create(self, bucket, object_name):
- self.provider.swift.put_object(bucket.name, object_name, None)
- return self.get(bucket, object_name)
- class OpenStackComputeService(BaseComputeService):
- def __init__(self, provider):
- super(OpenStackComputeService, self).__init__(provider)
- self._vm_type_svc = OpenStackVMTypeService(self.provider)
- self._instance_svc = OpenStackInstanceService(self.provider)
- self._region_svc = OpenStackRegionService(self.provider)
- self._images_svc = OpenStackImageService(self.provider)
- @property
- def images(self):
- return self._images_svc
- @property
- def vm_types(self):
- return self._vm_type_svc
- @property
- def instances(self):
- return self._instance_svc
- @property
- def regions(self):
- return self._region_svc
- class OpenStackImageService(BaseImageService):
- def __init__(self, provider):
- super(OpenStackImageService, self).__init__(provider)
- def get(self, image_id):
- """
- Returns an Image given its id
- """
- log.debug("Getting OpenStack Image with the id: %s", image_id)
- try:
- return OpenStackMachineImage(
- self.provider, self.provider.os_conn.image.get_image(image_id))
- except (NotFoundException, ResourceNotFound):
- log.debug("Image %s not found", image_id)
- return None
- def find(self, **kwargs):
- filters = ['label']
- obj_list = self
- return cb_helpers.generic_find(filters, kwargs, obj_list)
- def list(self, filter_by_owner=True, limit=None, marker=None):
- """
- List all images.
- """
- project_id = None
- if filter_by_owner:
- project_id = self.provider.os_conn.session.get_project_id()
- os_images = self.provider.os_conn.image.images(
- owner=project_id,
- limit=oshelpers.os_result_limit(self.provider, limit),
- marker=marker)
- cb_images = [
- OpenStackMachineImage(self.provider, img)
- for img in os_images]
- return oshelpers.to_server_paged_list(self.provider, cb_images, limit)
- class OpenStackInstanceService(BaseInstanceService):
- def __init__(self, provider):
- super(OpenStackInstanceService, self).__init__(provider)
- def create(self, label, image, vm_type, subnet, zone,
- key_pair=None, vm_firewalls=None, user_data=None,
- launch_config=None, **kwargs):
- """Create a new virtual machine instance."""
- OpenStackInstance.assert_valid_resource_label(label)
- image_id = image.id if isinstance(image, MachineImage) else image
- vm_size = vm_type.id if \
- isinstance(vm_type, VMType) else \
- self.provider.compute.vm_types.find(
- name=vm_type)[0].id
- if isinstance(subnet, Subnet):
- subnet_id = subnet.id
- net_id = subnet.network_id
- else:
- subnet_id = subnet
- net_id = (self.provider.networking.subnets
- .get(subnet_id).network_id
- if subnet_id else None)
- zone_id = zone.id if isinstance(zone, PlacementZone) else zone
- key_pair_name = key_pair.name if \
- isinstance(key_pair, KeyPair) else key_pair
- bdm = None
- if launch_config:
- bdm = self._to_block_device_mapping(launch_config)
- # Security groups must be passed in as a list of IDs and attached to a
- # port if a port is being created. Otherwise, the security groups must
- # be passed in as a list of names to the servers.create() call.
- # OpenStack will respect the port's security groups first and then
- # fall-back to the named security groups.
- sg_name_list = []
- nics = None
- if subnet_id:
- log.debug("Creating network port for %s in subnet: %s",
- label, subnet_id)
- sg_list = []
- if vm_firewalls:
- if isinstance(vm_firewalls, list) and \
- isinstance(vm_firewalls[0], VMFirewall):
- sg_list = vm_firewalls
- else:
- sg_list = (self.provider.security.vm_firewalls
- .find(label=sg) for sg in vm_firewalls)
- sg_list = (sg[0] for sg in sg_list if sg)
- sg_id_list = [sg.id for sg in sg_list]
- port_def = {
- "port": {
- "admin_state_up": True,
- "name": OpenStackInstance._generate_name_from_label(
- label, 'cb-port'),
- "network_id": net_id,
- "fixed_ips": [{"subnet_id": subnet_id}],
- "security_groups": sg_id_list
- }
- }
- port_id = self.provider.neutron.create_port(port_def)['port']['id']
- nics = [{'net-id': net_id, 'port-id': port_id}]
- else:
- if vm_firewalls:
- if isinstance(vm_firewalls, list) and \
- isinstance(vm_firewalls[0], VMFirewall):
- sg_name_list = [sg.name for sg in vm_firewalls]
- else:
- sg_list = (self.provider.security.vm_firewalls.get(sg)
- for sg in vm_firewalls)
- sg_name_list = (sg[0].name for sg in sg_list if sg)
- log.debug("Launching in subnet %s", subnet_id)
- os_instance = self.provider.nova.servers.create(
- label,
- None if self._has_root_device(launch_config) else image_id,
- vm_size,
- min_count=1,
- max_count=1,
- availability_zone=zone_id,
- key_name=key_pair_name,
- security_groups=sg_name_list,
- userdata=str(user_data) or None,
- block_device_mapping_v2=bdm,
- nics=nics)
- return OpenStackInstance(self.provider, os_instance)
- def _to_block_device_mapping(self, launch_config):
- """
- Extracts block device mapping information
- from a launch config and constructs a BlockDeviceMappingV2
- object.
- """
- bdm = []
- for device in launch_config.block_devices:
- bdm_dict = dict()
- if device.is_volume:
- bdm_dict['destination_type'] = 'volume'
- if device.is_root:
- bdm_dict['device_name'] = '/dev/sda'
- bdm_dict['boot_index'] = 0
- if isinstance(device.source, Snapshot):
- bdm_dict['source_type'] = 'snapshot'
- bdm_dict['uuid'] = device.source.id
- elif isinstance(device.source, Volume):
- bdm_dict['source_type'] = 'volume'
- bdm_dict['uuid'] = device.source.id
- elif isinstance(device.source, MachineImage):
- bdm_dict['source_type'] = 'image'
- bdm_dict['uuid'] = device.source.id
- else:
- bdm_dict['source_type'] = 'blank'
- if device.delete_on_terminate is not None:
- bdm_dict[
- 'delete_on_termination'] = device.delete_on_terminate
- if device.size:
- bdm_dict['volume_size'] = device.size
- else:
- bdm_dict['destination_type'] = 'local'
- bdm_dict['source_type'] = 'blank'
- bdm_dict['delete_on_termination'] = True
- bdm.append(bdm_dict)
- return bdm
- def _has_root_device(self, launch_config):
- if not launch_config:
- return False
- for device in launch_config.block_devices:
- if device.is_root:
- return True
- return False
- def create_launch_config(self):
- return BaseLaunchConfig(self.provider)
- def find(self, **kwargs):
- label = kwargs.pop('label', None)
- # All kwargs should have been popped at this time.
- if len(kwargs) > 0:
- raise TypeError("Unrecognised parameters for search: %s."
- " Supported attributes: %s" % (kwargs, 'label'))
- search_opts = {'name': label}
- cb_insts = [
- OpenStackInstance(self.provider, inst)
- for inst in self.provider.nova.servers.list(
- search_opts=search_opts,
- limit=oshelpers.os_result_limit(self.provider),
- marker=None)]
- return oshelpers.to_server_paged_list(self.provider, cb_insts)
- def list(self, limit=None, marker=None):
- """
- List all instances.
- """
- cb_insts = [
- OpenStackInstance(self.provider, inst)
- for inst in self.provider.nova.servers.list(
- limit=oshelpers.os_result_limit(self.provider, limit),
- marker=marker)]
- return oshelpers.to_server_paged_list(self.provider, cb_insts, limit)
- def get(self, instance_id):
- """
- Returns an instance given its id.
- """
- try:
- os_instance = self.provider.nova.servers.get(instance_id)
- return OpenStackInstance(self.provider, os_instance)
- except NovaNotFound:
- log.debug("Instance %s was not found.", instance_id)
- return None
- class OpenStackVMTypeService(BaseVMTypeService):
- def __init__(self, provider):
- super(OpenStackVMTypeService, self).__init__(provider)
- def list(self, limit=None, marker=None):
- cb_itypes = [
- OpenStackVMType(self.provider, obj)
- for obj in self.provider.nova.flavors.list(
- limit=oshelpers.os_result_limit(self.provider, limit),
- marker=marker)]
- return oshelpers.to_server_paged_list(self.provider, cb_itypes, limit)
- class OpenStackRegionService(BaseRegionService):
- def __init__(self, provider):
- super(OpenStackRegionService, self).__init__(provider)
- def get(self, region_id):
- log.debug("Getting OpenStack Region with the id: %s", region_id)
- region = (r for r in self if r.id == region_id)
- return next(region, None)
- def list(self, limit=None, marker=None):
- # pylint:disable=protected-access
- if self.provider._keystone_version == 3:
- os_regions = [OpenStackRegion(self.provider, region)
- for region in self.provider.keystone.regions.list()]
- return ClientPagedResultList(self.provider, os_regions,
- limit=limit, marker=marker)
- else:
- # Keystone v3 onwards supports directly listing regions
- # but for v2, this convoluted method is necessary.
- regions = (
- endpoint.get('region') or endpoint.get('region_id')
- for svc in self.provider.keystone.service_catalog.get_data()
- for endpoint in svc.get('endpoints', [])
- )
- regions = set(region for region in regions if region)
- os_regions = [OpenStackRegion(self.provider, region)
- for region in regions]
- return ClientPagedResultList(self.provider, os_regions,
- limit=limit, marker=marker)
- @property
- def current(self):
- nova_region = self.provider.nova.client.region_name
- return self.get(nova_region) if nova_region else None
- class OpenStackNetworkingService(BaseNetworkingService):
- def __init__(self, provider):
- super(OpenStackNetworkingService, self).__init__(provider)
- self._network_service = OpenStackNetworkService(self.provider)
- self._subnet_service = OpenStackSubnetService(self.provider)
- self._router_service = OpenStackRouterService(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
- class OpenStackNetworkService(BaseNetworkService):
- def __init__(self, provider):
- super(OpenStackNetworkService, self).__init__(provider)
- @implement(event_pattern="provider.networking.networks.get",
- priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
- def _get(self, network_id):
- network = (n for n in self if n.id == network_id)
- return next(network, None)
- @implement(event_pattern="provider.networking.networks.list",
- priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
- def _list(self, limit=None, marker=None):
- networks = [OpenStackNetwork(self.provider, network)
- for network in self.provider.neutron.list_networks()
- .get('networks') if network]
- return ClientPagedResultList(self.provider, networks,
- limit=limit, marker=marker)
- @implement(event_pattern="provider.networking.networks.find",
- priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
- def _find(self, **kwargs):
- label = kwargs.pop('label', None)
- # All kwargs should have been popped at this time.
- if len(kwargs) > 0:
- raise TypeError("Unrecognised parameters for search: %s."
- " Supported attributes: %s" % (kwargs, 'label'))
- log.debug("Searching for OpenStack Network with label: %s", label)
- networks = [OpenStackNetwork(self.provider, network)
- for network in self.provider.neutron.list_networks(
- name=label)
- .get('networks') if network]
- return ClientPagedResultList(self.provider, networks)
- @implement(event_pattern="provider.networking.networks.create",
- priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
- def _create(self, label, cidr_block):
- OpenStackNetwork.assert_valid_resource_label(label)
- net_info = {'name': label or ""}
- network = self.provider.neutron.create_network({'network': net_info})
- cb_net = OpenStackNetwork(self.provider, network.get('network'))
- if label:
- cb_net.label = label
- return cb_net
- @implement(event_pattern="provider.networking.networks.create",
- priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
- def _delete(self, network_id):
- network = self.get(network_id)
- if not network.external and network_id in str(
- self.provider.neutron.list_networks()):
- # If there are ports associated with the network, it won't delete
- ports = self.provider.neutron.list_ports(
- network_id=network_id).get('ports', [])
- for port in ports:
- try:
- self.provider.neutron.delete_port(port.get('id'))
- except PortNotFoundClient:
- # Ports could have already been deleted if instances
- # are terminated etc. so exceptions can be safely ignored
- pass
- self.provider.neutron.delete_network(network_id)
- class OpenStackSubnetService(BaseSubnetService):
- def __init__(self, provider):
- super(OpenStackSubnetService, self).__init__(provider)
- def get(self, subnet_id):
- log.debug("Getting OpenStack Subnet with the id: %s", subnet_id)
- subnet = (s for s in self if s.id == subnet_id)
- return next(subnet, None)
- def list(self, network=None, limit=None, marker=None):
- if network:
- network_id = (network.id if isinstance(network, OpenStackNetwork)
- else network)
- subnets = [subnet for subnet in self if network_id ==
- subnet.network_id]
- else:
- subnets = [OpenStackSubnet(self.provider, subnet) for subnet in
- self.provider.neutron.list_subnets().get('subnets', [])]
- return ClientPagedResultList(self.provider, subnets,
- limit=limit, marker=marker)
- def create(self, label, network, cidr_block, zone):
- """zone param is ignored."""
- log.debug("Creating OpenStack Subnet with the params: "
- "[Label: %s Network: %s Cinder Block: %s Zone: -ignored-]",
- label, network, cidr_block)
- OpenStackSubnet.assert_valid_resource_label(label)
- network_id = (network.id if isinstance(network, OpenStackNetwork)
- else network)
- subnet_info = {'name': label, 'network_id': network_id,
- 'cidr': cidr_block, 'ip_version': 4}
- subnet = (self.provider.neutron.create_subnet({'subnet': subnet_info})
- .get('subnet'))
- cb_subnet = OpenStackSubnet(self.provider, subnet)
- return cb_subnet
- def get_or_create_default(self, zone):
- """
- Subnet zone is not supported by OpenStack and is thus ignored.
- """
- try:
- sn = self.find(label=OpenStackSubnet.CB_DEFAULT_SUBNET_LABEL)
- if sn:
- return sn[0]
- # No default subnet look for default network, then create subnet
- net = self.provider.networking.networks.get_or_create_default()
- sn = self.provider.networking.subnets.create(
- label=OpenStackSubnet.CB_DEFAULT_SUBNET_LABEL,
- cidr_block=OpenStackSubnet.CB_DEFAULT_SUBNET_IPV4RANGE,
- network=net)
- router = self.provider.networking.routers.get_or_create_default(
- net)
- router.attach_subnet(sn)
- gateway = net.gateways.get_or_create_inet_gateway()
- router.attach_gateway(gateway)
- return sn
- except NeutronClientException:
- return None
- def delete(self, subnet):
- log.debug("Deleting subnet: %s", subnet)
- subnet_id = (subnet.id if isinstance(subnet, OpenStackSubnet)
- else subnet)
- self.provider.neutron.delete_subnet(subnet_id)
- # Adhere to the interface docs
- if subnet_id not in self:
- return True
- return False
- class OpenStackRouterService(BaseRouterService):
- def __init__(self, provider):
- super(OpenStackRouterService, self).__init__(provider)
- def get(self, router_id):
- log.debug("Getting OpenStack Router with the id: %s", router_id)
- router = self.provider.os_conn.get_router(router_id)
- return OpenStackRouter(self.provider, router) if router else None
- def list(self, limit=None, marker=None):
- routers = self.provider.os_conn.list_routers()
- os_routers = [OpenStackRouter(self.provider, r) for r in routers]
- return ClientPagedResultList(self.provider, os_routers, limit=limit,
- marker=marker)
- def find(self, **kwargs):
- obj_list = self
- filters = ['label']
- matches = cb_helpers.generic_find(filters, kwargs, obj_list)
- return ClientPagedResultList(self._provider, list(matches))
- def create(self, label, network):
- """Parameter ``network`` is not used by OpenStack."""
- log.debug("Creating OpenStack Router with the label: %s", label)
- OpenStackRouter.assert_valid_resource_label(label)
- router = self.provider.os_conn.create_router(name=label)
- return OpenStackRouter(self.provider, router)
|