Source code for libcloud.compute.drivers.rackspace

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Rackspace driver
"""
from libcloud.compute.base import NodeLocation, VolumeSnapshot
from libcloud.compute.types import Provider, LibcloudError, VolumeSnapshotState
from libcloud.utils.iso8601 import parse_date
from libcloud.common.rackspace import AUTH_URL
from libcloud.compute.drivers.openstack import (
    OpenStack_1_0_Response,
    OpenStack_1_0_Connection,
    OpenStack_1_0_NodeDriver,
    OpenStack_1_1_Connection,
    OpenStack_1_1_NodeDriver,
)

SERVICE_TYPE = "compute"
SERVICE_NAME_GEN1 = "cloudServers"
SERVICE_NAME_GEN2 = "cloudServersOpenStack"
ENDPOINT_ARGS_MAP = {
    "dfw": {"service_type": SERVICE_TYPE, "name": SERVICE_NAME_GEN2, "region": "DFW"},
    "ord": {"service_type": SERVICE_TYPE, "name": SERVICE_NAME_GEN2, "region": "ORD"},
    "iad": {"service_type": SERVICE_TYPE, "name": SERVICE_NAME_GEN2, "region": "IAD"},
    "lon": {"service_type": SERVICE_TYPE, "name": SERVICE_NAME_GEN2, "region": "LON"},
    "syd": {"service_type": SERVICE_TYPE, "name": SERVICE_NAME_GEN2, "region": "SYD"},
    "hkg": {"service_type": SERVICE_TYPE, "name": SERVICE_NAME_GEN2, "region": "HKG"},
}


[docs]class RackspaceFirstGenConnection(OpenStack_1_0_Connection): """ Connection class for the Rackspace first-gen driver. """ responseCls = OpenStack_1_0_Response XML_NAMESPACE = "http://docs.rackspacecloud.com/servers/api/v1.0" auth_url = AUTH_URL _auth_version = "2.0" cache_busting = True def __init__(self, *args, **kwargs): self.region = kwargs.pop("region", None) super().__init__(*args, **kwargs)
[docs] def get_endpoint(self): if "2.0" in self._auth_version: ep = self.service_catalog.get_endpoint( service_type=SERVICE_TYPE, name=SERVICE_NAME_GEN1 ) else: raise LibcloudError('Auth version "%s" not supported' % (self._auth_version)) public_url = ep.url if not public_url: raise LibcloudError("Could not find specified endpoint") # This is a nasty hack, but it's required because of how the # auth system works. # Old US accounts can access UK API endpoint, but they don't # have this endpoint in the service catalog. Same goes for the # old UK accounts and US endpoint. if self.region == "us": # Old UK account, which only have uk endpoint in the catalog public_url = public_url.replace("https://lon.servers.api", "https://servers.api") elif self.region == "uk": # Old US account, which only has us endpoints in the catalog public_url = public_url.replace("https://servers.api", "https://lon.servers.api") return public_url
[docs] def get_service_name(self): return SERVICE_NAME_GEN1
[docs]class RackspaceFirstGenNodeDriver(OpenStack_1_0_NodeDriver): name = "Rackspace Cloud (First Gen)" website = "http://www.rackspace.com" connectionCls = RackspaceFirstGenConnection type = Provider.RACKSPACE_FIRST_GEN api_name = "rackspace" def __init__(self, key, secret=None, secure=True, host=None, port=None, region="us", **kwargs): """ @inherits: :class:`NodeDriver.__init__` :param region: Region ID which should be used :type region: ``str`` """ if region not in ["us", "uk"]: raise ValueError("Invalid region: %s" % (region)) super().__init__( key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs, )
[docs] def list_locations(self): """ Lists available locations Locations cannot be set or retrieved via the API, but currently there are two locations, DFW and ORD. @inherits: :class:`OpenStack_1_0_NodeDriver.list_locations` """ if self.region == "us": locations = [NodeLocation(0, "Rackspace DFW1/ORD1", "US", self)] elif self.region == "uk": locations = [NodeLocation(0, "Rackspace UK London", "UK", self)] return locations
def _ex_connection_class_kwargs(self): kwargs = self.openstack_connection_kwargs() kwargs["region"] = self.region return kwargs
[docs]class RackspaceConnection(OpenStack_1_1_Connection): """ Connection class for the Rackspace next-gen OpenStack base driver. """ auth_url = AUTH_URL _auth_version = "2.0" def __init__(self, *args, **kwargs): self.region = kwargs.pop("region", None) self.get_endpoint_args = kwargs.pop("get_endpoint_args", None) super().__init__(*args, **kwargs)
[docs] def get_service_name(self): if not self.get_endpoint_args: # if they used ex_force_base_url, assume the Rackspace default return SERVICE_NAME_GEN2 return self.get_endpoint_args.get("name", SERVICE_NAME_GEN2)
[docs] def get_endpoint(self): if not self.get_endpoint_args: raise LibcloudError("RackspaceConnection must have get_endpoint_args set") if "2.0" in self._auth_version: ep = self.service_catalog.get_endpoint(**self.get_endpoint_args) else: raise LibcloudError('Auth version "%s" not supported' % (self._auth_version)) public_url = ep.url if not public_url: raise LibcloudError("Could not find specified endpoint") return public_url
[docs]class RackspaceNodeDriver(OpenStack_1_1_NodeDriver): name = "Rackspace Cloud (Next Gen)" website = "http://www.rackspace.com" connectionCls = RackspaceConnection type = Provider.RACKSPACE _networks_url_prefix = "/os-networksv2" def __init__( self, key, secret=None, secure=True, host=None, port=None, region="dfw", **kwargs, ): """ @inherits: :class:`NodeDriver.__init__` :param region: ID of the region which should be used. :type region: ``str`` """ valid_regions = ENDPOINT_ARGS_MAP.keys() if region not in valid_regions: raise ValueError("Invalid region: %s" % (region)) if region == "lon": self.api_name = "rackspacenovalon" elif region == "syd": self.api_name = "rackspacenovasyd" else: self.api_name = "rackspacenovaus" super().__init__( key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs, ) def _to_snapshot(self, api_node): if "snapshot" in api_node: api_node = api_node["snapshot"] extra = { "volume_id": api_node["volumeId"], "name": api_node["displayName"], "created": api_node["createdAt"], "description": api_node["displayDescription"], "status": api_node["status"], } state = self.SNAPSHOT_STATE_MAP.get(api_node["status"], VolumeSnapshotState.UNKNOWN) try: created_td = parse_date(api_node["createdAt"]) except ValueError: created_td = None snapshot = VolumeSnapshot( id=api_node["id"], driver=self, size=api_node["size"], extra=extra, created=created_td, state=state, name=api_node["displayName"], ) return snapshot def _ex_connection_class_kwargs(self): endpoint_args = ENDPOINT_ARGS_MAP[self.region] kwargs = self.openstack_connection_kwargs() kwargs["region"] = self.region kwargs["get_endpoint_args"] = endpoint_args return kwargs