You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by an...@apache.org on 2016/11/14 23:51:14 UTC
[27/56] [abbrv] libcloud git commit: Removed sdist
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/ecp.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/ecp.py b/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/ecp.py
deleted file mode 100644
index 380b7af..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/ecp.py
+++ /dev/null
@@ -1,385 +0,0 @@
-# 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.
-
-"""
-Enomaly ECP driver
-"""
-import time
-import base64
-import os
-import socket
-import binascii
-
-from libcloud.utils.py3 import httplib
-from libcloud.utils.py3 import b
-
-# JSON is included in the standard library starting with Python 2.6. For 2.5
-# and 2.4, there's a simplejson egg at: http://pypi.python.org/pypi/simplejson
-try:
- import simplejson as json
-except ImportError:
- import json
-
-from libcloud.common.base import Response, ConnectionUserAndKey
-from libcloud.compute.base import NodeDriver, NodeSize, NodeLocation
-from libcloud.compute.base import NodeImage, Node
-from libcloud.compute.types import Provider, NodeState, InvalidCredsError
-from libcloud.utils.networking import is_private_subnet
-
-# Defaults
-API_HOST = ''
-API_PORT = (80, 443)
-
-
-class ECPResponse(Response):
- def success(self):
- if self.status == httplib.OK or self.status == httplib.CREATED:
- try:
- j_body = json.loads(self.body)
- except ValueError:
- self.error = "JSON response cannot be decoded."
- return False
- if j_body['errno'] == 0:
- return True
- else:
- self.error = "ECP error: %s" % j_body['message']
- return False
- elif self.status == httplib.UNAUTHORIZED:
- raise InvalidCredsError()
- else:
- self.error = "HTTP Error Code: %s" % self.status
- return False
-
- def parse_error(self):
- return self.error
-
- # Interpret the json responses - no error checking required
- def parse_body(self):
- return json.loads(self.body)
-
- def getheaders(self):
- return self.headers
-
-
-class ECPConnection(ConnectionUserAndKey):
- """
- Connection class for the Enomaly ECP driver
- """
-
- responseCls = ECPResponse
- host = API_HOST
- port = API_PORT
-
- def add_default_headers(self, headers):
- # Authentication
- username = self.user_id
- password = self.key
- base64string = base64.encodestring(
- b('%s:%s' % (username, password)))[:-1]
- authheader = "Basic %s" % base64string
- headers['Authorization'] = authheader
-
- return headers
-
- def _encode_multipart_formdata(self, fields):
- """
- Based on Wade Leftwich's function:
- http://code.activestate.com/recipes/146306/
- """
- # use a random boundary that does not appear in the fields
- boundary = ''
- while boundary in ''.join(fields):
- boundary = binascii.hexlify(os.urandom(16)).decode('utf-8')
- L = []
- for i in fields:
- L.append('--' + boundary)
- L.append('Content-Disposition: form-data; name="%s"' % i)
- L.append('')
- L.append(fields[i])
- L.append('--' + boundary + '--')
- L.append('')
- body = '\r\n'.join(L)
- content_type = 'multipart/form-data; boundary=%s' % boundary
- header = {'Content-Type': content_type}
- return header, body
-
-
-class ECPNodeDriver(NodeDriver):
- """
- Enomaly ECP node driver
- """
-
- name = "Enomaly Elastic Computing Platform"
- website = 'http://www.enomaly.com/'
- type = Provider.ECP
- connectionCls = ECPConnection
-
- def list_nodes(self):
- """
- Returns a list of all running Nodes
-
- :rtype: ``list`` of :class:`Node`
- """
-
- # Make the call
- res = self.connection.request('/rest/hosting/vm/list').parse_body()
-
- # Put together a list of node objects
- nodes = []
- for vm in res['vms']:
- node = self._to_node(vm)
- if node is not None:
- nodes.append(node)
-
- # And return it
- return nodes
-
- def _to_node(self, vm):
- """
- Turns a (json) dictionary into a Node object.
- This returns only running VMs.
- """
-
- # Check state
- if not vm['state'] == "running":
- return None
-
- # IPs
- iplist = [interface['ip'] for interface in vm['interfaces'] if
- interface['ip'] != '127.0.0.1']
-
- public_ips = []
- private_ips = []
- for ip in iplist:
- try:
- socket.inet_aton(ip)
- except socket.error:
- # not a valid ip
- continue
- if is_private_subnet(ip):
- private_ips.append(ip)
- else:
- public_ips.append(ip)
-
- # Create the node object
- n = Node(
- id=vm['uuid'],
- name=vm['name'],
- state=NodeState.RUNNING,
- public_ips=public_ips,
- private_ips=private_ips,
- driver=self,
- )
-
- return n
-
- def reboot_node(self, node):
- """
- Shuts down a VM and then starts it again.
-
- @inherits: :class:`NodeDriver.reboot_node`
- """
-
- # Turn the VM off
- # Black magic to make the POST requests work
- d = self.connection._encode_multipart_formdata({'action': 'stop'})
- self.connection.request(
- '/rest/hosting/vm/%s' % node.id,
- method='POST',
- headers=d[0],
- data=d[1]
- ).parse_body()
-
- node.state = NodeState.REBOOTING
- # Wait for it to turn off and then continue (to turn it on again)
- while node.state == NodeState.REBOOTING:
- # Check if it's off.
- response = self.connection.request(
- '/rest/hosting/vm/%s' % node.id
- ).parse_body()
- if response['vm']['state'] == 'off':
- node.state = NodeState.TERMINATED
- else:
- time.sleep(5)
-
- # Turn the VM back on.
- # Black magic to make the POST requests work
- d = self.connection._encode_multipart_formdata({'action': 'start'})
- self.connection.request(
- '/rest/hosting/vm/%s' % node.id,
- method='POST',
- headers=d[0],
- data=d[1]
- ).parse_body()
-
- node.state = NodeState.RUNNING
- return True
-
- def destroy_node(self, node):
- """
- Shuts down and deletes a VM.
-
- @inherits: :class:`NodeDriver.destroy_node`
- """
-
- # Shut down first
- # Black magic to make the POST requests work
- d = self.connection._encode_multipart_formdata({'action': 'stop'})
- self.connection.request(
- '/rest/hosting/vm/%s' % node.id,
- method='POST',
- headers=d[0],
- data=d[1]
- ).parse_body()
-
- # Ensure there was no application level error
- node.state = NodeState.PENDING
- # Wait for the VM to turn off before continuing
- while node.state == NodeState.PENDING:
- # Check if it's off.
- response = self.connection.request(
- '/rest/hosting/vm/%s' % node.id
- ).parse_body()
- if response['vm']['state'] == 'off':
- node.state = NodeState.TERMINATED
- else:
- time.sleep(5)
-
- # Delete the VM
- # Black magic to make the POST requests work
- d = self.connection._encode_multipart_formdata({'action': 'delete'})
- self.connection.request(
- '/rest/hosting/vm/%s' % (node.id),
- method='POST',
- headers=d[0],
- data=d[1]
- ).parse_body()
-
- return True
-
- def list_images(self, location=None):
- """
- Returns a list of all package templates aka appliances aka images.
-
- @inherits: :class:`NodeDriver.list_images`
- """
-
- # Make the call
- response = self.connection.request(
- '/rest/hosting/ptemplate/list').parse_body()
-
- # Turn the response into an array of NodeImage objects
- images = []
- for ptemplate in response['packages']:
- images.append(NodeImage(
- id=ptemplate['uuid'],
- name='%s: %s' % (ptemplate['name'], ptemplate['description']),
- driver=self,)
- )
-
- return images
-
- def list_sizes(self, location=None):
- """
- Returns a list of all hardware templates
-
- @inherits: :class:`NodeDriver.list_sizes`
- """
-
- # Make the call
- response = self.connection.request(
- '/rest/hosting/htemplate/list').parse_body()
-
- # Turn the response into an array of NodeSize objects
- sizes = []
- for htemplate in response['templates']:
- sizes.append(NodeSize(
- id=htemplate['uuid'],
- name=htemplate['name'],
- ram=htemplate['memory'],
- disk=0, # Disk is independent of hardware template.
- bandwidth=0, # There is no way to keep track of bandwidth.
- price=0, # The billing system is external.
- driver=self,)
- )
-
- return sizes
-
- def list_locations(self):
- """
- This feature does not exist in ECP. Returns hard coded dummy location.
-
- :rtype: ``list`` of :class:`NodeLocation`
- """
- return [NodeLocation(id=1,
- name="Cloud",
- country='',
- driver=self),
- ]
-
- def create_node(self, **kwargs):
- """
- Creates a virtual machine.
-
- :keyword name: String with a name for this new node (required)
- :type name: ``str``
-
- :keyword size: The size of resources allocated to this node .
- (required)
- :type size: :class:`NodeSize`
-
- :keyword image: OS Image to boot on node. (required)
- :type image: :class:`NodeImage`
-
- :rtype: :class:`Node`
- """
-
- # Find out what network to put the VM on.
- res = self.connection.request(
- '/rest/hosting/network/list').parse_body()
-
- # Use the first / default network because there is no way to specific
- # which one
- network = res['networks'][0]['uuid']
-
- # Prepare to make the VM
- data = {
- 'name': str(kwargs['name']),
- 'package': str(kwargs['image'].id),
- 'hardware': str(kwargs['size'].id),
- 'network_uuid': str(network),
- 'disk': ''
- }
-
- # Black magic to make the POST requests work
- d = self.connection._encode_multipart_formdata(data)
- response = self.connection.request(
- '/rest/hosting/vm/',
- method='PUT',
- headers=d[0],
- data=d[1]
- ).parse_body()
-
- # Create a node object and return it.
- n = Node(
- id=response['machine_id'],
- name=data['name'],
- state=NodeState.PENDING,
- public_ips=[],
- private_ips=[],
- driver=self,
- )
-
- return n
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/ecs.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/ecs.py b/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/ecs.py
deleted file mode 100644
index c9d53f8..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/ecs.py
+++ /dev/null
@@ -1,1533 +0,0 @@
-# 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.
-
-"""
-Node driver for Aliyun.
-"""
-
-try:
- import simplejson as json
-except ImportError:
- import json
-import time
-
-from libcloud.common.aliyun import AliyunXmlResponse, SignedAliyunConnection
-from libcloud.common.types import LibcloudError
-from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeSize, \
- StorageVolume, VolumeSnapshot, NodeLocation
-from libcloud.compute.types import NodeState, StorageVolumeState, \
- VolumeSnapshotState
-from libcloud.utils.py3 import _real_unicode as u
-from libcloud.utils.xml import findall, findattr, findtext
-
-__all__ = [
- 'DiskCategory',
- 'InternetChargeType',
- 'ECS_API_VERSION',
- 'ECSDriver',
- 'ECSSecurityGroup',
- 'ECSZone'
-]
-
-ECS_API_VERSION = '2014-05-26'
-ECS_API_ENDPOINT = 'ecs.aliyuncs.com'
-DEFAULT_SIGNATURE_VERSION = '1.0'
-
-
-def _parse_bool(value):
- if isinstance(value, bool):
- return value
- if u(value).lower() == 'true':
- return True
- return False
-
-
-"""
-Define the extra dictionary for specific resources
-"""
-RESOURCE_EXTRA_ATTRIBUTES_MAP = {
- 'node': {
- 'description': {
- 'xpath': 'Description',
- 'transform_func': u
- },
- 'image_id': {
- 'xpath': 'ImageId',
- 'transform_func': u
- },
- 'zone_id': {
- 'xpath': 'ZoneId',
- 'transform_func': u
- },
- 'instance_type': {
- 'xpath': 'InstanceType',
- 'transform_func': u
- },
- 'instance_type_family': {
- 'xpath': 'InstanceTypeFamily',
- 'transform_func': u
- },
- 'hostname': {
- 'xpath': 'HostName',
- 'transform_func': u
- },
- 'serial_number': {
- 'xpath': 'SerialNumber',
- 'transform_func': u
- },
- 'internet_charge_type': {
- 'xpath': 'InternetChargeType',
- 'transform_func': u
- },
- 'creation_time': {
- 'xpath': 'CreationTime',
- 'transform_func': u
- },
- 'instance_network_type': {
- 'xpath': 'InstanceNetworkType',
- 'transform_func': u
- },
- 'instance_charge_type': {
- 'xpath': 'InstanceChargeType',
- 'transform_func': u
- },
- 'device_available': {
- 'xpath': 'DeviceAvailable',
- 'transform_func': u
- },
- 'io_optimized': {
- 'xpath': 'IoOptimized',
- 'transform_func': u
- },
- 'expired_time': {
- 'xpath': 'ExpiredTime',
- 'transform_func': u
- }
- },
- 'vpc_attributes': {
- 'vpc_id': {
- 'xpath': 'VpcId',
- 'transform_func': u
- },
- 'vswitch_id': {
- 'xpath': 'VSwitchId',
- 'transform_func': u
- },
- 'private_ip_address': {
- 'xpath': 'PrivateIpAddress/IpAddress',
- 'transform_func': u
- },
- 'nat_ip_address': {
- 'xpath': 'NatIpAddress',
- 'transform_func': u
- }
- },
- 'eip_address_associate': {
- 'allocation_id': {
- 'xpath': 'AllocationId',
- 'transform_func': u
- },
- 'ip_address': {
- 'xpath': 'IpAddress',
- 'transform_func': u
- },
- 'bandwidth': {
- 'xpath': 'Bandwidth',
- 'transform_func': int
- },
- 'internet_charge_type': {
- 'xpath': 'InternetChargeType',
- 'transform_func': u
- }
- },
- 'operation_locks': {
- 'lock_reason': {
- 'xpath': 'LockReason',
- 'transform_func': u
- }
- },
- 'volume': {
- 'region_id': {
- 'xpath': 'RegionId',
- 'transform_func': u
- },
- 'zone_id': {
- 'xpath': 'ZoneId',
- 'transform_func': u
- },
- 'description': {
- 'xpath': 'Description',
- 'transform_func': u
- },
- 'type': {
- 'xpath': 'Type',
- 'transform_func': u
- },
- 'category': {
- 'xpath': 'Category',
- 'transform_func': u
- },
- 'image_id': {
- 'xpath': 'ImageId',
- 'transform_func': u
- },
- 'source_snapshot_id': {
- 'xpath': 'SourceSnapshotId',
- 'transform_func': u
- },
- 'product_code': {
- 'xpath': 'ProductCode',
- 'transform_func': u
- },
- 'portable': {
- 'xpath': 'Portable',
- 'transform_func': _parse_bool
- },
- 'instance_id': {
- 'xpath': 'InstanceId',
- 'transform_func': u
- },
- 'device': {
- 'xpath': 'Device',
- 'transform_func': u
- },
- 'delete_with_instance': {
- 'xpath': 'DeleteWithInstance',
- 'transform_func': _parse_bool
- },
- 'enable_auto_snapshot': {
- 'xpath': 'EnableAutoSnapshot',
- 'transform_func': _parse_bool
- },
- 'creation_time': {
- 'xpath': 'CreationTime',
- 'transform_func': u
- },
- 'attached_time': {
- 'xpath': 'AttachedTime',
- 'transform_func': u
- },
- 'detached_time': {
- 'xpath': 'DetachedTime',
- 'transform_func': u
- },
- 'disk_charge_type': {
- 'xpath': 'DiskChargeType',
- 'transform_func': u
- }
- },
- 'snapshot': {
- 'snapshot_name': {
- 'xpath': 'SnapshotName',
- 'transform_func': u
- },
- 'description': {
- 'xpath': 'Description',
- 'transform_func': u
- },
- 'progress': {
- 'xpath': 'Progress',
- 'transform_func': u
- },
- 'source_disk_id': {
- 'xpath': 'SourceDiskId',
- 'transform_func': u
- },
- 'source_disk_size': {
- 'xpath': 'SourceDiskSize',
- 'transform_func': int
- },
- 'source_disk_type': {
- 'xpath': 'SourceDiskType',
- 'transform_func': u
- },
- 'product_code': {
- 'xpath': 'ProductCode',
- 'transform_func': u
- },
- 'usage': {
- 'xpath': 'Usage',
- 'transform_func': u
- }
- },
- 'image': {
- 'image_version': {
- 'xpath': 'ImageVersion',
- 'transform_func': u
- },
- 'os_type': {
- 'xpath': 'OSType',
- 'transform_func': u
- },
- 'platform': {
- 'xpath': 'Platform',
- 'transform_func': u
- },
- 'architecture': {
- 'xpath': 'Architecture',
- 'transform_func': u
- },
- 'description': {
- 'xpath': 'Description',
- 'transform_func': u
- },
- 'size': {
- 'xpath': 'Size',
- 'transform_func': int
- },
- 'image_owner_alias': {
- 'xpath': 'ImageOwnerAlias',
- 'transform_func': u
- },
- 'os_name': {
- 'xpath': 'OSName',
- 'transform_func': u
- },
- 'product_code': {
- 'xpath': 'ProductCode',
- 'transform_func': u
- },
- 'is_subscribed': {
- 'xpath': 'IsSubscribed',
- 'transform_func': _parse_bool
- },
- 'progress': {
- 'xpath': 'Progress',
- 'transform_func': u
- },
- 'creation_time': {
- 'xpath': 'CreationTime',
- 'transform_func': u
- },
- 'usage': {
- 'xpath': 'Usage',
- 'transform_func': u
- },
- 'is_copied': {
- 'xpath': 'IsCopied',
- 'transform_func': _parse_bool
- }
- },
- 'disk_device_mapping': {
- 'snapshot_id': {
- 'xpath': 'SnapshotId',
- 'transform_func': u
- },
- 'size': {
- 'xpath': 'Size',
- 'transform_func': int
- },
- 'device': {
- 'xpath': 'Device',
- 'transform_func': u
- },
- 'format': {
- 'xpath': 'Format',
- 'transform_func': u
- },
- 'import_oss_bucket': {
- 'xpath': 'ImportOSSBucket',
- 'transform_func': u
- },
- 'import_oss_object': {
- 'xpath': 'ImportOSSObject',
- 'transform_func': u
- }
- }
-}
-
-
-class ECSConnection(SignedAliyunConnection):
- """
- Represents a single connection to the Aliyun ECS Endpoint.
- """
-
- version = ECS_API_VERSION
- host = ECS_API_ENDPOINT
- responseCls = AliyunXmlResponse
- service_name = 'ecs'
-
-
-class ECSSecurityGroup(object):
- """
- Security group used to control nodes internet and intranet accessibility.
- """
- def __init__(self, id, name, description=None, driver=None, vpc_id=None,
- creation_time=None):
- self.id = id
- self.name = name
- self.description = description
- self.driver = driver
- self.vpc_id = vpc_id
- self.creation_time = creation_time
-
- def __repr__(self):
- return ('<ECSSecurityGroup: id=%s, name=%s, driver=%s ...>' %
- (self.id, self.name, self.driver.name))
-
-
-class ECSZone(object):
- """
- ECSZone used to represent an availability zone in a region.
- """
- def __init__(self, id, name, driver=None,
- available_resource_types=None,
- available_instance_types=None,
- available_disk_categories=None):
- self.id = id
- self.name = name
- self.driver = driver
- self.available_resource_types = available_resource_types
- self.available_instance_types = available_instance_types
- self.available_disk_categories = available_disk_categories
-
- def __repr__(self):
- return ('<ECSZone: id=%s, name=%s, driver=%s>' %
- (self.id, self.name, self.driver))
-
-
-class InternetChargeType(object):
- """
- Internet connection billing types for Aliyun Nodes.
- """
- BY_BANDWIDTH = 'PayByBandwidth'
- BY_TRAFFIC = 'PayByTraffic'
-
-
-class DiskCategory(object):
- """
- Enum defined disk types supported by Aliyun system and data disks.
- """
- CLOUD = 'cloud'
- CLOUD_EFFICIENCY = 'cloud_efficiency'
- CLOUD_SSD = 'cloud_ssd'
- EPHEMERAL_SSD = 'ephemeral_ssd'
-
-
-class Pagination(object):
- """
- Pagination used to describe the multiple pages results.
- """
- def __init__(self, total, size, current):
- """
- Create a pagination.
-
- :param total: the total count of the results
- :param size: the page size of each page
- :param current: the current page number, 1-based
- """
- self.total = total
- self.size = size
- self.current = current
-
- def next(self):
- """
- Switch to the next page.
- :return: the new pagination or None when no more page
- :rtype: ``Pagination``
- """
- if self.total is None or (self.size * self.current >= self.total):
- return None
- self.current += 1
- return self
-
- def to_dict(self):
- return {'PageNumber': self.current,
- 'PageSize': self.size}
-
- def __repr__(self):
- return ('<Pagination total=%d, size=%d, current page=%d>' %
- (self.total, self.size, self.current))
-
-
-class ECSDriver(NodeDriver):
- """
- Aliyun ECS node driver.
-
- Used for Aliyun ECS service.
-
- TODO:
- Create public IP address
- Get guest OS root password
- Adjust internet bandwidth settings
- Manage security groups and rules
- """
-
- name = 'Aliyun ECS'
- website = 'https://www.aliyun.com/product/ecs'
- connectionCls = ECSConnection
- features = {'create_node': ['password']}
- namespace = None
- path = '/'
-
- internet_charge_types = InternetChargeType
- disk_categories = DiskCategory
-
- NODE_STATE_MAPPING = {
- 'Starting': NodeState.PENDING,
- 'Running': NodeState.RUNNING,
- 'Stopping': NodeState.PENDING,
- 'Stopped': NodeState.STOPPED
- }
-
- VOLUME_STATE_MAPPING = {
- 'In_use': StorageVolumeState.INUSE,
- 'Available': StorageVolumeState.AVAILABLE,
- 'Attaching': StorageVolumeState.ATTACHING,
- 'Detaching': StorageVolumeState.INUSE,
- 'Creating': StorageVolumeState.CREATING,
- 'ReIniting': StorageVolumeState.CREATING}
-
- SNAPSHOT_STATE_MAPPING = {
- 'progressing': VolumeSnapshotState.CREATING,
- 'accomplished': VolumeSnapshotState.AVAILABLE,
- 'failed': VolumeSnapshotState.ERROR}
-
- def list_nodes(self, ex_node_ids=None, ex_filters=None):
- """
- List all nodes.
-
- @inherits: :class:`NodeDriver.create_node`
-
- :keyword ex_node_ids: a list of node's ids used to filter nodes.
- Only the nodes which's id in this list
- will be returned.
- :type ex_node_ids: ``list`` of ``str``
- :keyword ex_filters: node attribute and value pairs to filter nodes.
- Only the nodes which matchs all the pairs will
- be returned.
- If the filter attribute need a json array value,
- use ``list`` object, the driver will convert it.
- :type ex_filters: ``dict``
- """
-
- params = {'Action': 'DescribeInstances',
- 'RegionId': self.region}
-
- if ex_node_ids:
- if isinstance(ex_node_ids, list):
- params['InstanceIds'] = self._list_to_json_array(ex_node_ids)
- else:
- raise AttributeError('ex_node_ids should be a list of '
- 'node ids.')
-
- if ex_filters:
- if isinstance(ex_filters, dict):
- params.update(ex_filters)
- else:
- raise AttributeError('ex_filters should be a dict of '
- 'node attributes.')
-
- nodes = self._request_multiple_pages(self.path, params,
- self._to_nodes)
- return nodes
-
- def list_sizes(self, location=None):
- params = {'Action': 'DescribeInstanceTypes'}
-
- resp_body = self.connection.request(self.path, params).object
- size_elements = findall(resp_body, 'InstanceTypes/InstanceType',
- namespace=self.namespace)
- sizes = [self._to_size(each) for each in size_elements]
- return sizes
-
- def list_locations(self):
- params = {'Action': 'DescribeRegions'}
-
- resp_body = self.connection.request(self.path, params).object
- location_elements = findall(resp_body, 'Regions/Region',
- namespace=self.namespace)
- locations = [self._to_location(each) for each in location_elements]
- return locations
-
- def create_node(self, name, size, image, auth=None,
- ex_security_group_id=None, ex_description=None,
- ex_internet_charge_type=None,
- ex_internet_max_bandwidth_out=None,
- ex_internet_max_bandwidth_in=None,
- ex_hostname=None, ex_io_optimized=None,
- ex_system_disk=None, ex_data_disks=None,
- ex_vswitch_id=None, ex_private_ip_address=None,
- ex_client_token=None, **kwargs):
- """
- @inherits: :class:`NodeDriver.create_node`
-
- :param name: The name for this new node (required)
- :type name: ``str``
-
- :param image: The image to use when creating this node (required)
- :type image: `NodeImage`
-
- :param size: The size of the node to create (required)
- :type size: `NodeSize`
-
- :keyword auth: Initial authentication information for the node
- (optional)
- :type auth: :class:`NodeAuthSSHKey` or :class:`NodeAuthPassword`
-
- :keyword ex_security_group_id: The id of the security group the
- new created node is attached to.
- (required)
- :type ex_security_group_id: ``str``
-
- :keyword ex_description: A description string for this node (optional)
- :type ex_description: ``str``
-
- :keyword ex_internet_charge_type: The internet charge type (optional)
- :type ex_internet_charge_type: a ``str`` of 'PayByTraffic'
- or 'PayByBandwidth'
-
- :keyword ex_internet_max_bandwidth_out: The max output bandwidth,
- in Mbps (optional)
- Required for 'PayByTraffic'
- internet charge type
- :type ex_internet_max_bandwidth_out: a ``int`` in range [0, 100]
- a ``int`` in range [1, 100] for
- 'PayByTraffic' internet charge
- type
-
- :keyword ex_internet_max_bandwidth_in: The max input bandwidth,
- in Mbps (optional)
- :type ex_internet_max_bandwidth_in: a ``int`` in range [1, 200]
- default to 200 in server side
-
- :keyword ex_hostname: The hostname for the node (optional)
- :type ex_hostname: ``str``
-
- :keyword ex_io_optimized: Whether the node is IO optimized (optional)
- :type ex_io_optimized: ``boll``
-
- :keyword ex_system_disk: The system disk for the node (optional)
- :type ex_system_disk: ``dict``
-
- :keyword ex_data_disks: The data disks for the node (optional)
- :type ex_data_disks: a `list` of `dict`
-
- :keyword ex_vswitch_id: The id of vswitch for a VPC type node
- (optional)
- :type ex_vswitch_id: ``str``
-
- :keyword ex_private_ip_address: The IP address in private network
- (optional)
- :type ex_private_ip_address: ``str``
-
- :keyword ex_client_token: A token generated by client to keep
- requests idempotency (optional)
- :type keyword ex_client_token: ``str``
- """
-
- params = {'Action': 'CreateInstance',
- 'RegionId': self.region,
- 'ImageId': image.id,
- 'InstanceType': size.id,
- 'InstanceName': name}
-
- if not ex_security_group_id:
- raise AttributeError('ex_security_group_id is mandatory')
- params['SecurityGroupId'] = ex_security_group_id
-
- if ex_description:
- params['Description'] = ex_description
-
- inet_params = self._get_internet_related_params(
- ex_internet_charge_type,
- ex_internet_max_bandwidth_in,
- ex_internet_max_bandwidth_out)
- if inet_params:
- params.update(inet_params)
-
- if ex_hostname:
- params['HostName'] = ex_hostname
-
- if auth:
- auth = self._get_and_check_auth(auth)
- params['Password'] = auth.password
-
- if ex_io_optimized is not None:
- optimized = ex_io_optimized
- if not isinstance(optimized, bool):
- optimized = str(optimized).lower() == 'true'
- params['IoOptimized'] = 'true' if optimized else 'false'
-
- if ex_system_disk:
- system_disk = self._get_system_disk(ex_system_disk)
- if system_disk:
- params.update(system_disk)
-
- if ex_data_disks:
- data_disks = self._get_data_disks(ex_data_disks)
- if data_disks:
- params.update(data_disks)
-
- if ex_vswitch_id:
- params['VSwitchId'] = ex_vswitch_id
-
- if ex_private_ip_address:
- if not ex_vswitch_id:
- raise AttributeError('must provide ex_private_ip_address '
- 'and ex_vswitch_id at the same time')
- else:
- params['PrivateIpAddress'] = ex_private_ip_address
-
- if ex_client_token:
- params['ClientToken'] = ex_client_token
-
- resp = self.connection.request(self.path, params=params)
- node_id = findtext(resp.object, xpath='InstanceId',
- namespace=self.namespace)
- nodes = self.list_nodes(ex_node_ids=[node_id])
- if len(nodes) != 1:
- raise LibcloudError('could not find the new created node '
- 'with id %s. ' % node_id,
- driver=self)
- node = nodes[0]
- self.ex_start_node(node)
- self._wait_until_state(nodes, NodeState.RUNNING)
- return node
-
- def reboot_node(self, node, ex_force_stop=False):
- """
- Reboot the given node
-
- @inherits :class:`NodeDriver.reboot_node`
-
- :keyword ex_force_stop: if ``True``, stop node force (maybe lose data)
- otherwise, stop node normally,
- default to ``False``
- :type ex_force_stop: ``bool``
- """
- params = {'Action': 'RebootInstance',
- 'InstanceId': node.id,
- 'ForceStop': u(ex_force_stop).lower()}
- resp = self.connection.request(self.path, params=params)
- return resp.success() and \
- self._wait_until_state([node], NodeState.RUNNING)
-
- def destroy_node(self, node):
- nodes = self.list_nodes(ex_node_ids=[node.id])
- if len(nodes) != 1 and node.id != nodes[0].id:
- raise LibcloudError('could not find the node with id %s.'
- % node.id)
- current = nodes[0]
- if current.state == NodeState.RUNNING:
- # stop node first
- self.ex_stop_node(node)
- self._wait_until_state(nodes, NodeState.STOPPED)
- params = {'Action': 'DeleteInstance',
- 'InstanceId': node.id}
- resp = self.connection.request(self.path, params)
- return resp.success()
-
- def ex_start_node(self, node):
- """
- Start node to running state.
-
- :param node: the ``Node`` object to start
- :type node: ``Node``
-
- :return: starting operation result.
- :rtype: ``bool``
- """
- params = {'Action': 'StartInstance',
- 'InstanceId': node.id}
- resp = self.connection.request(self.path, params)
- return resp.success() and \
- self._wait_until_state([node], NodeState.RUNNING)
-
- def ex_stop_node(self, node, ex_force_stop=False):
- """
- Stop a running node.
-
- :param node: The node to stop
- :type node: :class:`Node`
-
- :keyword ex_force_stop: if ``True``, stop node force (maybe lose data)
- otherwise, stop node normally,
- default to ``False``
- :type ex_force_stop: ``bool``
-
- :return: stopping operation result.
- :rtype: ``bool``
- """
- params = {'Action': 'StopInstance',
- 'InstanceId': node.id,
- 'ForceStop': u(ex_force_stop).lower()}
- resp = self.connection.request(self.path, params)
- return resp.success() and \
- self._wait_until_state([node], NodeState.STOPPED)
-
- def ex_list_security_groups(self, ex_filters=None):
- """
- List security groups in the current region.
-
- :keyword ex_filters: security group attributes to filter results.
- :type ex_filters: ``dict``
-
- :return: a list of defined security groups
- :rtype: ``list`` of ``ECSSecurityGroup``
- """
- params = {'Action': 'DescribeSecurityGroups',
- 'RegionId': self.region}
-
- if ex_filters and isinstance(ex_filters, dict):
- ex_filters.update(params)
- params = ex_filters
-
- def _parse_response(resp_object):
- sg_elements = findall(resp_object, 'SecurityGroups/SecurityGroup',
- namespace=self.namespace)
- sgs = [self._to_security_group(el) for el in sg_elements]
- return sgs
- return self._request_multiple_pages(self.path, params,
- _parse_response)
-
- def ex_list_zones(self, region_id=None):
- """
- List availability zones in the given region or the current region.
-
- :keyword region_id: the id of the region to query zones from
- :type region_id: ``str``
-
- :return: list of zones
- :rtype: ``list`` of ``ECSZone``
- """
- params = {'Action': 'DescribeZones'}
- if region_id:
- params['RegionId'] = region_id
- else:
- params['RegionId'] = self.region
- resp_body = self.connection.request(self.path, params).object
- zone_elements = findall(resp_body, 'Zones/Zone',
- namespace=self.namespace)
- zones = [self._to_zone(el) for el in zone_elements]
- return zones
-
- ##
- # Volume and snapshot management methods
- ##
-
- def list_volumes(self, ex_volume_ids=None, ex_filters=None):
- """
- List all volumes.
-
- @inherits: :class:`NodeDriver.list_volumes`
-
- :keyword ex_volume_ids: a list of volume's ids used to filter volumes.
- Only the volumes which's id in this list
- will be returned.
- :type ex_volume_ids: ``list`` of ``str``
-
- :keyword ex_filters: volume attribute and value pairs to filter
- volumes. Only the volumes which matchs all will
- be returned.
- If the filter attribute need a json array value,
- use ``list`` object, the driver will convert it.
- :type ex_filters: ``dict``
- """
- params = {'Action': 'DescribeDisks',
- 'RegionId': self.region}
-
- if ex_volume_ids:
- if isinstance(ex_volume_ids, list):
- params['DiskIds'] = self._list_to_json_array(ex_volume_ids)
- else:
- raise AttributeError('ex_volume_ids should be a list of '
- 'volume ids.')
-
- if ex_filters:
- if not isinstance(ex_filters, dict):
- raise AttributeError('ex_filters should be a dict of '
- 'volume attributes.')
- else:
- for key in ex_filters.keys():
- params[key] = ex_filters[key]
-
- def _parse_response(resp_object):
- disk_elements = findall(resp_object, 'Disks/Disk',
- namespace=self.namespace)
- volumes = [self._to_volume(each) for each in disk_elements]
- return volumes
- return self._request_multiple_pages(self.path, params,
- _parse_response)
-
- def list_volume_snapshots(self, volume, ex_snapshot_ids=[],
- ex_filters=None):
- """
- List snapshots for a storage volume.
-
- @inherites :class:`NodeDriver.list_volume_snapshots`
-
- :keyword ex_snapshot_ids: a list of snapshot ids to filter the
- snapshots returned.
- :type ex_snapshot_ids: ``list`` of ``str``
-
- :keyword ex_filters: snapshot attribute and value pairs to filter
- snapshots. Only the snapshot which matchs all
- the pairs will be returned.
- If the filter attribute need a json array value,
- use ``list`` object, the driver will convert it.
- :type ex_filters: ``dict``
- """
- params = {'Action': 'DescribeSnapshots',
- 'RegionId': self.region}
-
- if volume:
- params['DiskId'] = volume.id
- if ex_snapshot_ids and isinstance(ex_snapshot_ids, list):
- params['SnapshotIds'] = self._list_to_json_array(ex_snapshot_ids)
- if ex_filters and isinstance(ex_filters, dict):
- for key in ex_filters.keys():
- params[key] = ex_filters[key]
-
- def _parse_response(resp_body):
- snapshot_elements = findall(resp_body, 'Snapshots/Snapshot',
- namespace=self.namespace)
- snapshots = [self._to_snapshot(each) for each in snapshot_elements]
- return snapshots
-
- return self._request_multiple_pages(self.path, params,
- _parse_response)
-
- def create_volume(self, size, name, location=None, snapshot=None,
- ex_zone_id=None, ex_description=None,
- ex_disk_category=None, ex_client_token=None):
- """
- Create a new volume.
-
- @inherites :class:`NodeDriver.create_volume`
-
- :keyword ex_zone_id: the availability zone id (required)
- :type ex_zone_id: ``str``
-
- :keyword ex_description: volume description
- :type ex_description: ``unicode``
-
- :keyword ex_disk_category: disk category for data disk
- :type ex_disk_category: ``str``
-
- :keyword ex_client_token: a token generated by client to identify
- each request.
- :type ex_client_token: ``str``
- """
- params = {'Action': 'CreateDisk',
- 'RegionId': self.region,
- 'DiskName': name,
- 'Size': size}
- if ex_zone_id is None:
- raise AttributeError('ex_zone_id is required')
- params['ZoneId'] = ex_zone_id
-
- if snapshot is not None and isinstance(snapshot, VolumeSnapshot):
- params['SnapshotId'] = snapshot.id
- if ex_description:
- params['Description'] = ex_description
- if ex_disk_category:
- params['DiskCategory'] = ex_disk_category
- if ex_client_token:
- params['ClientToken'] = ex_client_token
- resp = self.connection.request(self.path, params).object
- volume_id = findtext(resp, 'DiskId', namespace=self.namespace)
- volumes = self.list_volumes(ex_volume_ids=[volume_id])
- if len(volumes) != 1:
- raise LibcloudError('could not find the new create volume '
- 'with id %s.' % volume_id,
- driver=self)
- return volumes[0]
-
- def create_volume_snapshot(self, volume, name=None, ex_description=None,
- ex_client_token=None):
- """
- Creates a snapshot of the storage volume.
-
- @inherits :class:`NodeDriver.create_volume_snapshot`
-
- :keyword ex_description: description of the snapshot.
- :type ex_description: ``unicode``
-
- :keyword ex_client_token: a token generated by client to identify
- each request.
- :type ex_client_token: ``str``
- """
- params = {'Action': 'CreateSnapshot',
- 'DiskId': volume.id}
- if name:
- params['SnapshotName'] = name
- if ex_description:
- params['Description'] = ex_description
- if ex_client_token:
- params['ClientToken'] = ex_client_token
-
- snapshot_elements = self.connection.request(self.path, params).object
- snapshot_id = findtext(snapshot_elements, 'SnapshotId',
- namespace=self.namespace)
- snapshots = self.list_volume_snapshots(volume=None,
- ex_snapshot_ids=[snapshot_id])
- if len(snapshots) != 1:
- raise LibcloudError('could not find new created snapshot with '
- 'id %s.' % snapshot_id, driver=self)
- return snapshots[0]
-
- def attach_volume(self, node, volume, device=None,
- ex_delete_with_instance=None):
- """
- Attaches volume to node.
-
- @inherits :class:`NodeDriver.attach_volume`
-
- :keyword device: device path allocated for this attached volume
- :type device: ``str`` between /dev/xvdb to xvdz,
- if empty, allocated by the system
- :keyword ex_delete_with_instance: if to delete this volume when the
- instance is deleted.
- :type ex_delete_with_instance: ``bool``
- """
- params = {'Action': 'AttachDisk',
- 'InstanceId': node.id,
- 'DiskId': volume.id}
-
- if device:
- params['Device'] = device
- if ex_delete_with_instance:
- params['DeleteWithInstance'] = \
- str(bool(ex_delete_with_instance)).lower()
- resp = self.connection.request(self.path, params)
- return resp.success()
-
- def detach_volume(self, volume, ex_instance_id=None):
- """
- Detaches a volume from a node.
-
- @inherits :class:`NodeDriver.detach_volume`
-
- :keyword ex_instance_id: the id of the instance from which the volume
- is detached.
- :type ex_instance_id: ``str``
- """
- params = {'Action': 'DetachDisk',
- 'DiskId': volume.id}
-
- if ex_instance_id:
- params['InstanceId'] = ex_instance_id
- else:
- volumes = self.list_volumes(ex_volume_ids=[volume.id])
- if len(volumes) != 1:
- raise AttributeError('could not find the instance id '
- 'the volume %s attached to, '
- 'ex_instance_id is required.' %
- volume.id)
- params['InstanceId'] = volumes[0].extra['instance_id']
-
- resp = self.connection.request(self.path, params)
- return resp.success()
-
- def destroy_volume(self, volume):
- params = {'Action': 'DeleteDisk',
- 'DiskId': volume.id}
- volumes = self.list_volumes(ex_volume_ids=[volume.id])
- if len(volumes) != 1:
- raise LibcloudError('could not find the volume with id %s.' %
- volume.id,
- driver=self)
- if volumes[0].state != StorageVolumeState.AVAILABLE:
- raise LibcloudError('only volume in AVAILABLE state could be '
- 'destroyed.', driver=self)
- resp = self.connection.request(self.path, params)
- return resp.success()
-
- def destroy_volume_snapshot(self, snapshot):
- params = {'Action': 'DeleteSnapshot'}
-
- if snapshot and isinstance(snapshot, VolumeSnapshot):
- params['SnapshotId'] = snapshot.id
- else:
- raise AttributeError('snapshot is required and must be a '
- 'VolumeSnapshot')
- resp = self.connection.request(self.path, params)
- return resp.success()
-
- ##
- # Image management methods
- ##
-
- def list_images(self, location=None, ex_image_ids=None, ex_filters=None):
- """
- List images on a provider.
-
- @inherits :class:`NodeDriver.list_images`
-
- :keyword ex_image_ids: a list of image ids to filter the images to
- be returned.
- :type ex_image_ids: ``list`` of ``str``
-
- :keyword ex_filters: image attribute and value pairs to filter
- images. Only the image which matchs all
- the pairs will be returned.
- If the filter attribute need a json array value,
- use ``list`` object, the driver will convert it.
- :type ex_filters: ``dict``
- """
-
- if location and isinstance(location, NodeLocation):
- region = location.id
- else:
- region = self.region
- params = {'Action': 'DescribeImages',
- 'RegionId': region}
- if ex_image_ids:
- if isinstance(ex_image_ids, list):
- params['ImageId'] = ','.join(ex_image_ids)
- else:
- raise AttributeError('ex_image_ids should be a list of '
- 'image ids')
- if ex_filters and isinstance(ex_filters, dict):
- for key in ex_filters.keys():
- params[key] = ex_filters[key]
-
- def _parse_response(resp_body):
- image_elements = findall(resp_body, 'Images/Image',
- namespace=self.namespace)
- images = [self._to_image(each) for each in image_elements]
- return images
- return self._request_multiple_pages(self.path, params,
- _parse_response)
-
- def create_image(self, node, name, description=None, ex_snapshot_id=None,
- ex_image_version=None, ex_client_token=None):
- """
- Creates an image from a system disk snapshot.
-
- @inherits :class:`NodeDriver.create_image`
-
- :keyword ex_snapshot_id: the id of the snapshot to create the image.
- (required)
- :type ex_snapshot_id: ``str``
-
- :keyword ex_image_version: the version number of the image
- :type ex_image_version: ``str``
-
- :keyword ex_client_token: a token generated by client to identify
- each request.
- :type ex_client_token: ``str``
- """
- params = {'Action': 'CreateImage',
- 'RegionId': self.region}
- if name:
- params['ImageName'] = name
- if description:
- params['Description'] = description
- if ex_snapshot_id:
- params['SnapshotId'] = ex_snapshot_id
- else:
- raise AttributeError('ex_snapshot_id is required')
- if ex_image_version:
- params['ImageVersion'] = ex_image_version
- if ex_client_token:
- params['ClientToken'] = ex_client_token
-
- resp = self.connection.request(self.path, params)
- image_id = findtext(resp.object, 'ImageId', namespace=self.namespace)
- return self.get_image(image_id=image_id)
-
- def delete_image(self, node_image):
- params = {'Action': 'DeleteImage',
- 'RegionId': self.region,
- 'ImageId': node_image.id}
- resp = self.connection.request(self.path, params)
- return resp.success()
-
- def get_image(self, image_id, ex_region_id=None):
- if ex_region_id:
- region = ex_region_id
- else:
- region = self.region
- location = NodeLocation(id=region, name=None, country=None,
- driver=self)
- images = self.list_images(location, ex_image_ids=[image_id])
- if len(images) != 1:
- raise LibcloudError('could not find the image with id %s' %
- image_id,
- driver=self)
- return images[0]
-
- def copy_image(self, source_region, node_image, name, description=None,
- ex_destination_region_id=None, ex_client_token=None):
- """
- Copies an image from a source region to the destination region.
- If not provide a destination region, default to the current region.
-
- @inherits :class:`NodeDriver.copy_image`
-
- :keyword ex_destination_region_id: id of the destination region
- :type ex_destination_region_id: ``str``
-
- :keyword ex_client_token: a token generated by client to identify
- each request.
- :type ex_client_token: ``str``
- """
- params = {'Action': 'CopyImage',
- 'RegionId': source_region,
- 'ImageId': node_image.id}
- if ex_destination_region_id is not None:
- params['DestinationRegionId'] = ex_destination_region_id
- else:
- params['DestinationRegionId'] = self.region
- if name:
- params['DestinationImageName'] = name
- if description:
- params['DestinationDescription'] = description
- if ex_client_token:
- params['ClientToken'] = ex_client_token
- resp = self.connection.request(self.path, params)
- image_id = findtext(resp.object, 'ImageId', namespace=self.namespace)
- return self.get_image(image_id=image_id)
-
- def _to_nodes(self, object):
- """
- Convert response to Node object list
-
- :param object: parsed response object
- :return: a list of ``Node``
- :rtype: ``list``
- """
- node_elements = findall(object, 'Instances/Instance', self.namespace)
- return [self._to_node(el) for el in node_elements]
-
- def _to_node(self, instance):
- """
- Convert an InstanceAttributesType object to ``Node`` object
-
- :param instance: a xml element represents an instance
- :return: a ``Node`` object
- :rtype: ``Node``
- """
- _id = findtext(element=instance, xpath='InstanceId',
- namespace=self.namespace)
- name = findtext(element=instance, xpath='InstanceName',
- namespace=self.namespace)
- instance_status = findtext(element=instance, xpath='Status',
- namespace=self.namespace)
- state = self.NODE_STATE_MAPPING.get(instance_status, NodeState.UNKNOWN)
-
- def _get_ips(ip_address_els):
- return [each.text for each in ip_address_els]
-
- public_ip_els = findall(element=instance,
- xpath='PublicIpAddress/IpAddress',
- namespace=self.namespace)
- public_ips = _get_ips(public_ip_els)
- private_ip_els = findall(element=instance,
- xpath='InnerIpAddress/IpAddress',
- namespace=self.namespace)
- private_ips = _get_ips(private_ip_els)
-
- # Extra properties
- extra = self._get_extra_dict(instance,
- RESOURCE_EXTRA_ATTRIBUTES_MAP['node'])
- extra['vpc_attributes'] = self._get_vpc_attributes(instance)
- extra['eip_address'] = self._get_eip_address(instance)
- extra['operation_locks'] = self._get_operation_locks(instance)
-
- node = Node(id=_id, name=name, state=state,
- public_ips=public_ips, private_ips=private_ips,
- driver=self.connection.driver, extra=extra)
- return node
-
- def _get_extra_dict(self, element, mapping):
- """
- Extract attributes from the element based on rules provided in the
- mapping dictionary.
-
- :param element: Element to parse the values from.
- :type element: xml.etree.ElementTree.Element.
-
- :param mapping: Dictionary with the extra layout
- :type node: :class:`Node`
-
- :rtype: ``dict``
- """
- extra = {}
- for attribute, values in mapping.items():
- transform_func = values['transform_func']
- value = findattr(element=element,
- xpath=values['xpath'],
- namespace=self.namespace)
- if value:
- try:
- extra[attribute] = transform_func(value)
- except Exception:
- extra[attribute] = None
- else:
- extra[attribute] = value
-
- return extra
-
- def _get_internet_related_params(self, ex_internet_charge_type,
- ex_internet_max_bandwidth_in,
- ex_internet_max_bandwidth_out):
- params = {}
- if ex_internet_charge_type:
- params['InternetChargeType'] = ex_internet_charge_type
- if ex_internet_charge_type.lower() == 'paybytraffic':
- if ex_internet_max_bandwidth_out:
- params['InternetMaxBandwidthOut'] = \
- ex_internet_max_bandwidth_out
- else:
- raise AttributeError('ex_internet_max_bandwidth_out is '
- 'mandatory for PayByTraffic internet'
- ' charge type.')
-
- if ex_internet_max_bandwidth_in:
- params['InternetMaxBandwidthIn'] = \
- ex_internet_max_bandwidth_in
- return params
-
- def _get_system_disk(self, ex_system_disk):
- if not isinstance(ex_system_disk, dict):
- raise AttributeError('ex_system_disk is not a dict')
- sys_disk_dict = ex_system_disk
- key_base = 'SystemDisk.'
- # TODO(samsong8610): Use a type instead of dict
- mappings = {'category': 'Category',
- 'disk_name': 'DiskName',
- 'description': 'Description'}
- params = {}
- for attr in mappings.keys():
- if attr in sys_disk_dict:
- params[key_base + mappings[attr]] = sys_disk_dict[attr]
- return params
-
- def _get_data_disks(self, ex_data_disks):
- if isinstance(ex_data_disks, dict):
- data_disks = [ex_data_disks]
- elif isinstance(ex_data_disks, list):
- data_disks = ex_data_disks
- else:
- raise AttributeError('ex_data_disks should be a list of dict')
- # TODO(samsong8610): Use a type instead of dict
- mappings = {'size': 'Size',
- 'category': 'Category',
- 'snapshot_id': 'SnapshotId',
- 'disk_name': 'DiskName',
- 'description': 'Description',
- 'device': 'Device',
- 'delete_with_instance': 'DeleteWithInstance'}
- params = {}
- for idx, disk in enumerate(data_disks):
- key_base = 'DataDisk.{0}.'.format(idx + 1)
- for attr in mappings.keys():
- if attr in disk:
- if attr == 'delete_with_instance':
- # Convert bool value to str
- value = str(disk[attr]).lower()
- else:
- value = disk[attr]
- params[key_base + mappings[attr]] = value
- return params
-
- def _get_vpc_attributes(self, instance):
- vpcs = findall(instance, xpath='VpcAttributes',
- namespace=self.namespace)
- if len(vpcs) <= 0:
- return None
- return self._get_extra_dict(
- vpcs[0], RESOURCE_EXTRA_ATTRIBUTES_MAP['vpc_attributes'])
-
- def _get_eip_address(self, instance):
- eips = findall(instance, xpath='EipAddress',
- namespace=self.namespace)
- if len(eips) <= 0:
- return None
- return self._get_extra_dict(
- eips[0], RESOURCE_EXTRA_ATTRIBUTES_MAP['eip_address_associate'])
-
- def _get_operation_locks(self, instance):
- locks = findall(instance, xpath='OperationLocks',
- namespace=self.namespace)
- if len(locks) <= 0:
- return None
- return self._get_extra_dict(
- locks[0], RESOURCE_EXTRA_ATTRIBUTES_MAP['operation_locks'])
-
- def _wait_until_state(self, nodes, state, wait_period=3, timeout=600):
- """
- Block until the provided nodes are in the desired state.
- :param nodes: List of nodes to wait for
- :type nodes: ``list`` of :class:`.Node`
- :param state: desired state
- :type state: ``NodeState``
- :param wait_period: How many seconds to wait between each loop
- iteration. (default is 3)
- :type wait_period: ``int``
- :param timeout: How many seconds to wait before giving up.
- (default is 600)
- :type timeout: ``int``
- :return: if the nodes are in the desired state.
- :rtype: ``bool``
- """
- start = time.time()
- end = start + timeout
- node_ids = [node.id for node in nodes]
-
- while(time.time() < end):
- matched_nodes = self.list_nodes(ex_node_ids=node_ids)
- if len(matched_nodes) > len(node_ids):
- found_ids = [node.id for node in matched_nodes]
- msg = ('found multiple nodes with same ids, '
- 'desired ids: %(ids)s, found ids: %(found_ids)s' %
- {'ids': node_ids, 'found_ids': found_ids})
- raise LibcloudError(value=msg, driver=self)
- desired_nodes = [node for node in matched_nodes
- if node.state == state]
-
- if len(desired_nodes) == len(node_ids):
- return True
- else:
- time.sleep(wait_period)
- continue
-
- raise LibcloudError(value='Timed out after %s seconds' % (timeout),
- driver=self)
-
- def _to_volume(self, element):
- _id = findtext(element, 'DiskId', namespace=self.namespace)
- name = findtext(element, 'DiskName', namespace=self.namespace)
- size = int(findtext(element, 'Size', namespace=self.namespace))
- status_str = findtext(element, 'Status', namespace=self.namespace)
- status = self.VOLUME_STATE_MAPPING.get(status_str,
- StorageVolumeState.UNKNOWN)
-
- extra = self._get_extra_dict(element,
- RESOURCE_EXTRA_ATTRIBUTES_MAP['volume'])
- extra['operation_locks'] = self._get_operation_locks(element)
- return StorageVolume(_id, name, size, self, state=status, extra=extra)
-
- def _list_to_json_array(self, value):
- try:
- return json.dumps(value)
- except Exception:
- raise AttributeError('could not convert list to json array')
-
- def _to_snapshot(self, element):
- _id = findtext(element, 'SnapshotId', namespace=self.namespace)
- created = findtext(element, 'CreationTime', namespace=self.namespace)
- status_str = findtext(element, 'Status', namespace=self.namespace)
- state = self.SNAPSHOT_STATE_MAPPING.get(status_str,
- VolumeSnapshotState.UNKNOWN)
- extra = self._get_extra_dict(element,
- RESOURCE_EXTRA_ATTRIBUTES_MAP['snapshot'])
- return VolumeSnapshot(id=_id, driver=self, extra=extra,
- created=created, state=state)
-
- def _to_size(self, element):
- _id = findtext(element, 'InstanceTypeId', namespace=self.namespace)
- ram = float(findtext(element, 'MemorySize', namespace=self.namespace))
- extra = {}
- extra['cpu_core_count'] = int(findtext(element, 'CpuCoreCount',
- namespace=self.namespace))
- extra['instance_type_family'] = findtext(element, 'InstanceTypeFamily',
- namespace=self.namespace)
- return NodeSize(id=_id, name=_id, ram=ram, disk=None, bandwidth=None,
- price=None, driver=self, extra=extra)
-
- def _to_location(self, element):
- _id = findtext(element, 'RegionId', namespace=self.namespace)
- localname = findtext(element, 'LocalName', namespace=self.namespace)
- return NodeLocation(id=_id, name=localname, country=None, driver=self)
-
- def _to_image(self, element):
- _id = findtext(element, 'ImageId', namespace=self.namespace)
- name = findtext(element, 'ImageName', namespace=self.namespace)
- extra = self._get_extra_dict(element,
- RESOURCE_EXTRA_ATTRIBUTES_MAP['image'])
- extra['disk_device_mappings'] = self._get_disk_device_mappings(
- element.find('DiskDeviceMappings'))
- return NodeImage(id=_id, name=name, driver=self, extra=extra)
-
- def _get_disk_device_mappings(self, element):
- if element is None:
- return None
- mapping_element = element.find('DiskDeviceMapping')
- if mapping_element is not None:
- return self._get_extra_dict(
- mapping_element,
- RESOURCE_EXTRA_ATTRIBUTES_MAP['disk_device_mapping'])
- return None
-
- def _to_security_group(self, element):
- _id = findtext(element, 'SecurityGroupId', namespace=self.namespace)
- name = findtext(element, 'SecurityGroupName',
- namespace=self.namespace)
- description = findtext(element, 'Description',
- namespace=self.namespace)
- vpc_id = findtext(element, 'VpcId', namespace=self.namespace)
- creation_time = findtext(element, 'CreationTime',
- namespace=self.namespace)
- return ECSSecurityGroup(_id, name, description=description,
- driver=self, vpc_id=vpc_id,
- creation_time=creation_time)
-
- def _to_zone(self, element):
- _id = findtext(element, 'ZoneId', namespace=self.namespace)
- local_name = findtext(element, 'LocalName', namespace=self.namespace)
- resource_types = findall(element,
- 'AvailableResourceCreation/ResourceTypes',
- namespace=self.namespace)
- instance_types = findall(element,
- 'AvailableInstanceTypes/InstanceTypes',
- namespace=self.namespace)
- disk_categories = findall(element,
- 'AvailableDiskCategories/DiskCategories',
- namespace=self.namespace)
-
- def _text(element):
- return element.text
-
- return ECSZone(id=_id, name=local_name, driver=self,
- available_resource_types=list(
- map(_text, resource_types)),
- available_instance_types=list(
- map(_text, instance_types)),
- available_disk_categories=list(
- map(_text, disk_categories)))
-
- def _get_pagination(self, element):
- page_number = int(findtext(element, 'PageNumber'))
- total_count = int(findtext(element, 'TotalCount'))
- page_size = int(findtext(element, 'PageSize'))
- return Pagination(total=total_count, size=page_size,
- current=page_number)
-
- def _request_multiple_pages(self, path, params, parse_func):
- """
- Request all resources by multiple pages.
- :param path: the resource path
- :type path: ``str``
- :param params: the query parameters
- :type params: ``dict``
- :param parse_func: the function object to parse the response body
- :param type: ``function``
- :return: list of resource object, if not found any, return []
- :rtype: ``list``
- """
- results = []
- while True:
- one_page = self.connection.request(path, params).object
- resources = parse_func(one_page)
- results += resources
- pagination = self._get_pagination(one_page)
- if pagination.next() is None:
- break
- params.update(pagination.to_dict())
- return results
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/elastichosts.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/elastichosts.py b/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/elastichosts.py
deleted file mode 100644
index 736ac7f..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/elastichosts.py
+++ /dev/null
@@ -1,236 +0,0 @@
-# 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.
-
-"""
-ElasticHosts Driver
-"""
-
-from libcloud.compute.types import Provider
-from libcloud.compute.drivers.elasticstack import ElasticStackBaseNodeDriver
-
-
-# API end-points
-API_ENDPOINTS = {
- 'lon-p': {
- 'name': 'London Peer 1',
- 'country': 'United Kingdom',
- 'host': 'api-lon-p.elastichosts.com'
- },
- 'lon-b': {
- 'name': 'London BlueSquare',
- 'country': 'United Kingdom',
- 'host': 'api-lon-b.elastichosts.com'
- },
- 'sat-p': {
- 'name': 'San Antonio Peer 1',
- 'country': 'United States',
- 'host': 'api-sat-p.elastichosts.com'
- },
- 'lax-p': {
- 'name': 'Los Angeles Peer 1',
- 'country': 'United States',
- 'host': 'api-lax-p.elastichosts.com'
- },
- 'sjc-c': {
- 'name': 'San Jose (Silicon Valley)',
- 'country': 'United States',
- 'host': 'api-sjc-c.elastichosts.com'
- },
- 'tor-p': {
- 'name': 'Toronto Peer 1',
- 'country': 'Canada',
- 'host': 'api-tor-p.elastichosts.com'
- },
- 'syd-y': {
- 'name': 'Sydney',
- 'country': 'Australia',
- 'host': 'api-syd-v.elastichosts.com'
- },
- 'cn-1': {
- 'name': 'Hong Kong',
- 'country': 'China',
- 'host': 'api-hkg-e.elastichosts.com'
- }
-}
-
-# Default API end-point for the base connection class.
-DEFAULT_REGION = 'sat-p'
-
-# Retrieved from http://www.elastichosts.com/cloud-hosting/api
-STANDARD_DRIVES = {
- '38df0986-4d85-4b76-b502-3878ffc80161': {
- 'uuid': '38df0986-4d85-4b76-b502-3878ffc80161',
- 'description': 'CentOS Linux 5.5',
- 'size_gunzipped': '3GB',
- 'supports_deployment': True,
- },
- '980cf63c-f21e-4382-997b-6541d5809629': {
- 'uuid': '980cf63c-f21e-4382-997b-6541d5809629',
- 'description': 'Debian Linux 5.0',
- 'size_gunzipped': '1GB',
- 'supports_deployment': True,
- },
- 'aee5589a-88c3-43ef-bb0a-9cab6e64192d': {
- 'uuid': 'aee5589a-88c3-43ef-bb0a-9cab6e64192d',
- 'description': 'Ubuntu Linux 10.04',
- 'size_gunzipped': '1GB',
- 'supports_deployment': True,
- },
- '62f512cd-82c7-498e-88d8-a09ac2ef20e7': {
- 'uuid': '62f512cd-82c7-498e-88d8-a09ac2ef20e7',
- 'description': 'Ubuntu Linux 12.04',
- 'size_gunzipped': '1GB',
- 'supports_deployment': True,
- },
- 'b9d0eb72-d273-43f1-98e3-0d4b87d372c0': {
- 'uuid': 'b9d0eb72-d273-43f1-98e3-0d4b87d372c0',
- 'description': 'Windows Web Server 2008',
- 'size_gunzipped': '13GB',
- 'supports_deployment': False,
- },
- '30824e97-05a4-410c-946e-2ba5a92b07cb': {
- 'uuid': '30824e97-05a4-410c-946e-2ba5a92b07cb',
- 'description': 'Windows Web Server 2008 R2',
- 'size_gunzipped': '13GB',
- 'supports_deployment': False,
- },
- '9ecf810e-6ad1-40ef-b360-d606f0444671': {
- 'uuid': '9ecf810e-6ad1-40ef-b360-d606f0444671',
- 'description': 'Windows Web Server 2008 R2 + SQL Server',
- 'size_gunzipped': '13GB',
- 'supports_deployment': False,
- },
- '10a88d1c-6575-46e3-8d2c-7744065ea530': {
- 'uuid': '10a88d1c-6575-46e3-8d2c-7744065ea530',
- 'description': 'Windows Server 2008 Standard R2',
- 'size_gunzipped': '13GB',
- 'supports_deployment': False,
- },
- '2567f25c-8fb8-45c7-95fc-bfe3c3d84c47': {
- 'uuid': '2567f25c-8fb8-45c7-95fc-bfe3c3d84c47',
- 'description': 'Windows Server 2008 Standard R2 + SQL Server',
- 'size_gunzipped': '13GB',
- 'supports_deployment': False,
- },
-}
-
-
-class ElasticHostsException(Exception):
- def __str__(self):
- return self.args[0]
-
- def __repr__(self):
- return "<ElasticHostsException '%s'>" % (self.args[0])
-
-
-class ElasticHostsNodeDriver(ElasticStackBaseNodeDriver):
- """
- Node Driver class for ElasticHosts
- """
- type = Provider.ELASTICHOSTS
- api_name = 'elastichosts'
- name = 'ElasticHosts'
- website = 'http://www.elastichosts.com/'
- features = {"create_node": ["generates_password"]}
- _standard_drives = STANDARD_DRIVES
-
- def __init__(self, key, secret=None, secure=True, host=None, port=None,
- region=DEFAULT_REGION, **kwargs):
-
- if hasattr(self, '_region'):
- region = self._region
-
- if region not in API_ENDPOINTS:
- raise ValueError('Invalid region: %s' % (region))
-
- self._host_argument_set = host is not None
- super(ElasticHostsNodeDriver, self).__init__(key=key, secret=secret,
- secure=secure, host=host,
- port=port,
- region=region, **kwargs)
-
- def _ex_connection_class_kwargs(self):
- """
- Return the host value based on the user supplied region.
- """
- kwargs = {}
- if not self._host_argument_set:
- kwargs['host'] = API_ENDPOINTS[self.region]['host']
-
- return kwargs
-
-
-class ElasticHostsUK1NodeDriver(ElasticHostsNodeDriver):
- """
- ElasticHosts node driver for the London Peer 1 end-point
- """
- name = 'ElasticHosts (lon-p)'
- _region = 'lon-p'
-
-
-class ElasticHostsUK2NodeDriver(ElasticHostsNodeDriver):
- """
- ElasticHosts node driver for the London Bluesquare end-point
- """
- name = 'ElasticHosts (lon-b)'
- _region = 'lon-b'
-
-
-class ElasticHostsUS1NodeDriver(ElasticHostsNodeDriver):
- """
- ElasticHosts node driver for the San Antonio Peer 1 end-point
- """
- name = 'ElasticHosts (sat-p)'
- _region = 'sat-p'
-
-
-class ElasticHostsUS2NodeDriver(ElasticHostsNodeDriver):
- """
- ElasticHosts node driver for the Los Angeles Peer 1 end-point
- """
- name = 'ElasticHosts (lax-p)'
- _region = 'lax-p'
-
-
-class ElasticHostsUS3NodeDriver(ElasticHostsNodeDriver):
- """
- ElasticHosts node driver for the San Jose (Silicon Valley) end-point
- """
- name = 'ElasticHosts (sjc-c)'
- _region = 'sjc-c'
-
-
-class ElasticHostsCA1NodeDriver(ElasticHostsNodeDriver):
- """
- ElasticHosts node driver for the Toronto Peer 1 end-point
- """
- name = 'ElasticHosts (tor-p)'
- _region = 'tor-p'
-
-
-class ElasticHostsAU1NodeDriver(ElasticHostsNodeDriver):
- """
- ElasticHosts node driver for the Sydney end-point
- """
- name = 'ElasticHosts (syd-y)'
- _region = 'syd-y'
-
-
-class ElasticHostsCN1NodeDriver(ElasticHostsNodeDriver):
- """
- ElasticHosts node driver for the Hong Kong end-point
- """
- name = 'ElasticHosts (cn-1)'
- _region = 'cn-1'