http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/common/zonomi.py ---------------------------------------------------------------------- diff --git a/apache-libcloud-1.0.0rc2/libcloud/common/zonomi.py b/apache-libcloud-1.0.0rc2/libcloud/common/zonomi.py deleted file mode 100644 index 3ef913d..0000000 --- a/apache-libcloud-1.0.0rc2/libcloud/common/zonomi.py +++ /dev/null @@ -1,138 +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. - -from libcloud.common.base import XmlResponse -from libcloud.common.base import ConnectionKey - - -__all__ = [ - 'ZonomiException', - 'ZonomiResponse', - 'ZonomiConnection' -] - -# Endpoint for Zonomi API. -API_HOST = 'zonomi.com' - -SPECIAL_ERRORS = [ - 'Not found.', - 'ERROR: This zone is already in your zone list.', - 'Record not deleted.' -] - - -class ZonomiException(Exception): - def __init__(self, code, message): - self.code = code - self.message = message - self.args = (code, message) - - def __str__(self): - return "%s %s" % (self.code, self.message) - - def __repr__(self): - return "ZonomiException %s %s" % (self.code, self.message) - - -class ZonomiResponse(XmlResponse): - errors = None - objects = None - - def __init__(self, response, connection): - self.errors = [] - super(ZonomiResponse, self).__init__(response=response, - connection=connection) - self.objects, self.errors = self.parse_body_and_errors() - if self.errors: - raise self._make_excp(self.errors[0]) - - def parse_body_and_errors(self): - error_dict = {} - actions = None - result_counts = None - action_childrens = None - data = [] - errors = [] - xml_body = super(ZonomiResponse, self).parse_body() - # Error handling - if xml_body.text is not None and xml_body.tag == 'error': - error_dict['ERRORCODE'] = self.status - if xml_body.text.startswith('ERROR: No zone found for'): - error_dict['ERRORCODE'] = '404' - error_dict['ERRORMESSAGE'] = 'Not found.' - else: - error_dict['ERRORMESSAGE'] = xml_body.text - errors.append(error_dict) - - # Data handling - childrens = xml_body.getchildren() - if len(childrens) == 3: - result_counts = childrens[1] - actions = childrens[2] - - if actions is not None: - actions_childrens = actions.getchildren() - action = actions_childrens[0] - action_childrens = action.getchildren() - - if action_childrens is not None: - for child in action_childrens: - if child.tag == 'zone' or child.tag == 'record': - data.append(child.attrib) - - if result_counts is not None and \ - result_counts.attrib.get('deleted') == '1': - data.append('DELETED') - - if result_counts is not None and \ - result_counts.attrib.get('deleted') == '0' and \ - action.get('action') == 'DELETE': - error_dict['ERRORCODE'] = self.status - error_dict['ERRORMESSAGE'] = 'Record not deleted.' - errors.append(error_dict) - - return (data, errors) - - def success(self): - return (len(self.errors) == 0) - - def _make_excp(self, error): - """ - :param error: contains error code and error message - :type error: dict - """ - return ZonomiException(error['ERRORCODE'], error['ERRORMESSAGE']) - - -class ZonomiConnection(ConnectionKey): - host = API_HOST - responseCls = ZonomiResponse - - def add_default_params(self, params): - """ - Adds default parameters to perform a request, - such as api_key. - """ - params['api_key'] = self.key - - return params - - def add_default_headers(self, headers): - """ - Adds default headers needed to perform a successful - request such as Content-Type, User-Agent. - """ - headers['Content-Type'] = 'text/xml;charset=UTF-8' - - return headers
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/__init__.py ---------------------------------------------------------------------- diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/__init__.py b/apache-libcloud-1.0.0rc2/libcloud/compute/__init__.py deleted file mode 100644 index 6d0970a..0000000 --- a/apache-libcloud-1.0.0rc2/libcloud/compute/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Module for working with Cloud Servers -""" http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/base.py ---------------------------------------------------------------------- diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/base.py b/apache-libcloud-1.0.0rc2/libcloud/compute/base.py deleted file mode 100644 index b64dd31..0000000 --- a/apache-libcloud-1.0.0rc2/libcloud/compute/base.py +++ /dev/null @@ -1,1531 +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. - -""" -Provides base classes for working with drivers -""" - -from __future__ import with_statement - -import sys -import time -import hashlib -import os -import socket -import random -import binascii - -from libcloud.utils.py3 import b - -import libcloud.compute.ssh -from libcloud.pricing import get_size_price -from libcloud.compute.types import NodeState, StorageVolumeState,\ - DeploymentError -from libcloud.compute.ssh import SSHClient -from libcloud.common.base import ConnectionKey -from libcloud.common.base import BaseDriver -from libcloud.common.types import LibcloudError -from libcloud.compute.ssh import have_paramiko - -from libcloud.utils.networking import is_private_subnet -from libcloud.utils.networking import is_valid_ip_address - -if have_paramiko: - from paramiko.ssh_exception import SSHException - from paramiko.ssh_exception import AuthenticationException - - SSH_TIMEOUT_EXCEPTION_CLASSES = (AuthenticationException, SSHException, - IOError, socket.gaierror, socket.error) -else: - SSH_TIMEOUT_EXCEPTION_CLASSES = (IOError, socket.gaierror, socket.error) - -# How long to wait for the node to come online after creating it -NODE_ONLINE_WAIT_TIMEOUT = 10 * 60 - -# How long to try connecting to a remote SSH server when running a deployment -# script. -SSH_CONNECT_TIMEOUT = 5 * 60 - - -__all__ = [ - 'Node', - 'NodeState', - 'NodeSize', - 'NodeImage', - 'NodeLocation', - 'NodeAuthSSHKey', - 'NodeAuthPassword', - 'NodeDriver', - - 'StorageVolume', - 'StorageVolumeState', - 'VolumeSnapshot', - - # Deprecated, moved to libcloud.utils.networking - 'is_private_subnet', - 'is_valid_ip_address' -] - - -class UuidMixin(object): - """ - Mixin class for get_uuid function. - """ - - def __init__(self): - self._uuid = None - - def get_uuid(self): - """ - Unique hash for a node, node image, or node size - - The hash is a function of an SHA1 hash of the node, node image, - or node size's ID and its driver which means that it should be - unique between all objects of its type. - In some subclasses (e.g. GoGridNode) there is no ID - available so the public IP address is used. This means that, - unlike a properly done system UUID, the same UUID may mean a - different system install at a different time - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> node = driver.create_node() - >>> node.get_uuid() - 'd3748461511d8b9b0e0bfa0d4d3383a619a2bb9f' - - Note, for example, that this example will always produce the - same UUID! - - :rtype: ``str`` - """ - if not self._uuid: - self._uuid = hashlib.sha1(b('%s:%s' % - (self.id, self.driver.type))).hexdigest() - - return self._uuid - - @property - def uuid(self): - return self.get_uuid() - - -class Node(UuidMixin): - """ - Provide a common interface for handling nodes of all types. - - The Node object provides the interface in libcloud through which - we can manipulate nodes in different cloud providers in the same - way. Node objects don't actually do much directly themselves, - instead the node driver handles the connection to the node. - - You don't normally create a node object yourself; instead you use - a driver and then have that create the node for you. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> node = driver.create_node() - >>> node.public_ips[0] - '127.0.0.3' - >>> node.name - 'dummy-3' - - You can also get nodes from the driver's list_node function. - - >>> node = driver.list_nodes()[0] - >>> node.name - 'dummy-1' - - The node keeps a reference to its own driver which means that we - can work on nodes from different providers without having to know - which is which. - - >>> driver = DummyNodeDriver(72) - >>> node2 = driver.create_node() - >>> node.driver.creds - 0 - >>> node2.driver.creds - 72 - - Although Node objects can be subclassed, this isn't normally - done. Instead, any driver specific information is stored in the - "extra" attribute of the node. - - >>> node.extra - {'foo': 'bar'} - """ - - def __init__(self, id, name, state, public_ips, private_ips, - driver, size=None, image=None, extra=None, created_at=None): - """ - :param id: Node ID. - :type id: ``str`` - - :param name: Node name. - :type name: ``str`` - - :param state: Node state. - :type state: :class:`libcloud.compute.types.NodeState` - - :param public_ips: Public IP addresses associated with this node. - :type public_ips: ``list`` - - :param private_ips: Private IP addresses associated with this node. - :type private_ips: ``list`` - - :param driver: Driver this node belongs to. - :type driver: :class:`.NodeDriver` - - :param size: Size of this node. (optional) - :type size: :class:`.NodeSize` - - :param image: Image of this node. (optional) - :type size: :class:`.NodeImage` - - :param created_at: The datetime this node was created (optional) - :type created_at: :class: `datetime.datetime` - - :param extra: Optional provider specific attributes associated with - this node. - :type extra: ``dict`` - - """ - self.id = str(id) if id else None - self.name = name - self.state = state - self.public_ips = public_ips if public_ips else [] - self.private_ips = private_ips if private_ips else [] - self.driver = driver - self.size = size - self.created_at = created_at - self.image = image - self.extra = extra or {} - UuidMixin.__init__(self) - - def reboot(self): - """ - Reboot this node - - :return: ``bool`` - - This calls the node's driver and reboots the node - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> node = driver.create_node() - >>> node.state == NodeState.RUNNING - True - >>> node.state == NodeState.REBOOTING - False - >>> node.reboot() - True - >>> node.state == NodeState.REBOOTING - True - """ - return self.driver.reboot_node(self) - - def destroy(self): - """ - Destroy this node - - :return: ``bool`` - - This calls the node's driver and destroys the node - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> from libcloud.compute.types import NodeState - >>> node = driver.create_node() - >>> node.state == NodeState.RUNNING - True - >>> node.destroy() - True - >>> node.state == NodeState.RUNNING - False - - """ - return self.driver.destroy_node(self) - - def __repr__(self): - state = NodeState.tostring(self.state) - - return (('<Node: uuid=%s, name=%s, state=%s, public_ips=%s, ' - 'private_ips=%s, provider=%s ...>') - % (self.uuid, self.name, state, self.public_ips, - self.private_ips, self.driver.name)) - - -class NodeSize(UuidMixin): - """ - A Base NodeSize class to derive from. - - NodeSizes are objects which are typically returned a driver's - list_sizes function. They contain a number of different - parameters which define how big an image is. - - The exact parameters available depends on the provider. - - N.B. Where a parameter is "unlimited" (for example bandwidth in - Amazon) this will be given as 0. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> size = driver.list_sizes()[0] - >>> size.ram - 128 - >>> size.bandwidth - 500 - >>> size.price - 4 - """ - - def __init__(self, id, name, ram, disk, bandwidth, price, - driver, extra=None): - """ - :param id: Size ID. - :type id: ``str`` - - :param name: Size name. - :type name: ``str`` - - :param ram: Amount of memory (in MB) provided by this size. - :type ram: ``int`` - - :param disk: Amount of disk storage (in GB) provided by this image. - :type disk: ``int`` - - :param bandwidth: Amount of bandiwdth included with this size. - :type bandwidth: ``int`` - - :param price: Price (in US dollars) of running this node for an hour. - :type price: ``float`` - - :param driver: Driver this size belongs to. - :type driver: :class:`.NodeDriver` - - :param extra: Optional provider specific attributes associated with - this size. - :type extra: ``dict`` - """ - self.id = str(id) - self.name = name - self.ram = ram - self.disk = disk - self.bandwidth = bandwidth - self.price = price - self.driver = driver - self.extra = extra or {} - UuidMixin.__init__(self) - - def __repr__(self): - return (('<NodeSize: id=%s, name=%s, ram=%s disk=%s bandwidth=%s ' - 'price=%s driver=%s ...>') - % (self.id, self.name, self.ram, self.disk, self.bandwidth, - self.price, self.driver.name)) - - -class NodeImage(UuidMixin): - """ - An operating system image. - - NodeImage objects are typically returned by the driver for the - cloud provider in response to the list_images function - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> image = driver.list_images()[0] - >>> image.name - 'Ubuntu 9.10' - - Apart from name and id, there is no further standard information; - other parameters are stored in a driver specific "extra" variable - - When creating a node, a node image should be given as an argument - to the create_node function to decide which OS image to use. - - >>> node = driver.create_node(image=image) - """ - - def __init__(self, id, name, driver, extra=None): - """ - :param id: Image ID. - :type id: ``str`` - - :param name: Image name. - :type name: ``str`` - - :param driver: Driver this image belongs to. - :type driver: :class:`.NodeDriver` - - :param extra: Optional provided specific attributes associated with - this image. - :type extra: ``dict`` - """ - self.id = str(id) - self.name = name - self.driver = driver - self.extra = extra or {} - UuidMixin.__init__(self) - - def __repr__(self): - return (('<NodeImage: id=%s, name=%s, driver=%s ...>') - % (self.id, self.name, self.driver.name)) - - -class NodeLocation(object): - """ - A physical location where nodes can be. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> location = driver.list_locations()[0] - >>> location.country - 'US' - """ - - def __init__(self, id, name, country, driver): - """ - :param id: Location ID. - :type id: ``str`` - - :param name: Location name. - :type name: ``str`` - - :param country: Location country. - :type country: ``str`` - - :param driver: Driver this location belongs to. - :type driver: :class:`.NodeDriver` - """ - self.id = str(id) - self.name = name - self.country = country - self.driver = driver - - def __repr__(self): - return (('<NodeLocation: id=%s, name=%s, country=%s, driver=%s>') - % (self.id, self.name, self.country, self.driver.name)) - - -class NodeAuthSSHKey(object): - """ - An SSH key to be installed for authentication to a node. - - This is the actual contents of the users ssh public key which will - normally be installed as root's public key on the node. - - >>> pubkey = '...' # read from file - >>> from libcloud.compute.base import NodeAuthSSHKey - >>> k = NodeAuthSSHKey(pubkey) - >>> k - <NodeAuthSSHKey> - """ - - def __init__(self, pubkey): - """ - :param pubkey: Public key matetiral. - :type pubkey: ``str`` - """ - self.pubkey = pubkey - - def __repr__(self): - return '<NodeAuthSSHKey>' - - -class NodeAuthPassword(object): - """ - A password to be used for authentication to a node. - """ - def __init__(self, password, generated=False): - """ - :param password: Password. - :type password: ``str`` - - :type generated: ``True`` if this password was automatically generated, - ``False`` otherwise. - """ - self.password = password - self.generated = generated - - def __repr__(self): - return '<NodeAuthPassword>' - - -class StorageVolume(UuidMixin): - """ - A base StorageVolume class to derive from. - """ - - def __init__(self, id, name, size, driver, - state=None, extra=None): - """ - :param id: Storage volume ID. - :type id: ``str`` - - :param name: Storage volume name. - :type name: ``str`` - - :param size: Size of this volume (in GB). - :type size: ``int`` - - :param driver: Driver this image belongs to. - :type driver: :class:`.NodeDriver` - - :param state: Optional state of the StorageVolume. If not - provided, will default to UNKNOWN. - :type state: :class:`.StorageVolumeState` - - :param extra: Optional provider specific attributes. - :type extra: ``dict`` - """ - self.id = id - self.name = name - self.size = size - self.driver = driver - self.extra = extra - self.state = state - UuidMixin.__init__(self) - - def list_snapshots(self): - """ - :rtype: ``list`` of ``VolumeSnapshot`` - """ - return self.driver.list_volume_snapshots(volume=self) - - def attach(self, node, device=None): - """ - Attach this volume to a node. - - :param node: Node to attach volume to - :type node: :class:`.Node` - - :param device: Where the device is exposed, - e.g. '/dev/sdb (optional) - :type device: ``str`` - - :return: ``True`` if attach was successful, ``False`` otherwise. - :rtype: ``bool`` - """ - - return self.driver.attach_volume(node=node, volume=self, device=device) - - def detach(self): - """ - Detach this volume from its node - - :return: ``True`` if detach was successful, ``False`` otherwise. - :rtype: ``bool`` - """ - - return self.driver.detach_volume(volume=self) - - def snapshot(self, name): - """ - Creates a snapshot of this volume. - - :return: Created snapshot. - :rtype: ``VolumeSnapshot`` - """ - return self.driver.create_volume_snapshot(volume=self, name=name) - - def destroy(self): - """ - Destroy this storage volume. - - :return: ``True`` if destroy was successful, ``False`` otherwise. - :rtype: ``bool`` - """ - - return self.driver.destroy_volume(volume=self) - - def __repr__(self): - return '<StorageVolume id=%s size=%s driver=%s>' % ( - self.id, self.size, self.driver.name) - - -class VolumeSnapshot(object): - """ - A base VolumeSnapshot class to derive from. - """ - def __init__(self, id, driver, size=None, extra=None, created=None, - state=None): - """ - VolumeSnapshot constructor. - - :param id: Snapshot ID. - :type id: ``str`` - - :param driver: The driver that represents a connection to the - provider - :type driver: `NodeDriver` - - :param size: A snapshot size in GB. - :type size: ``int`` - - :param extra: Provider depends parameters for snapshot. - :type extra: ``dict`` - - :param created: A datetime object that represents when the - snapshot was created - :type created: ``datetime.datetime`` - - :param state: A string representing the state the snapshot is - in. See `libcloud.compute.types.StorageVolumeState`. - :type state: ``str`` - """ - self.id = id - self.driver = driver - self.size = size - self.extra = extra or {} - self.created = created - self.state = state - - def destroy(self): - """ - Destroys this snapshot. - - :rtype: ``bool`` - """ - return self.driver.destroy_volume_snapshot(snapshot=self) - - def __repr__(self): - return ('<VolumeSnapshot id=%s size=%s driver=%s state=%s>' % - (self.id, self.size, self.driver.name, self.state)) - - -class KeyPair(object): - """ - Represents a SSH key pair. - """ - - def __init__(self, name, public_key, fingerprint, driver, private_key=None, - extra=None): - """ - Constructor. - - :keyword name: Name of the key pair object. - :type name: ``str`` - - :keyword fingerprint: Key fingerprint. - :type fingerprint: ``str`` - - :keyword public_key: Public key in OpenSSH format. - :type public_key: ``str`` - - :keyword private_key: Private key in PEM format. - :type private_key: ``str`` - - :keyword extra: Provider specific attributes associated with this - key pair. (optional) - :type extra: ``dict`` - """ - self.name = name - self.fingerprint = fingerprint - self.public_key = public_key - self.private_key = private_key - self.driver = driver - self.extra = extra or {} - - def __repr__(self): - return ('<KeyPair name=%s fingerprint=%s driver=%s>' % - (self.name, self.fingerprint, self.driver.name)) - - -class NodeDriver(BaseDriver): - """ - A base NodeDriver class to derive from - - This class is always subclassed by a specific driver. For - examples of base behavior of most functions (except deploy node) - see the dummy driver. - - """ - - connectionCls = ConnectionKey - name = None - type = None - port = None - features = {'create_node': []} - - """ - List of available features for a driver. - - :meth:`libcloud.compute.base.NodeDriver.create_node` - - ssh_key: Supports :class:`.NodeAuthSSHKey` as an authentication - method for nodes. - - password: Supports :class:`.NodeAuthPassword` as an - authentication - method for nodes. - - generates_password: Returns a password attribute on the Node - object returned from creation. - """ - - NODE_STATE_MAP = {} - - def list_nodes(self): - """ - List all nodes. - - :return: list of node objects - :rtype: ``list`` of :class:`.Node` - """ - raise NotImplementedError( - 'list_nodes not implemented for this driver') - - def list_sizes(self, location=None): - """ - List sizes on a provider - - :param location: The location at which to list sizes - :type location: :class:`.NodeLocation` - - :return: list of node size objects - :rtype: ``list`` of :class:`.NodeSize` - """ - raise NotImplementedError( - 'list_sizes not implemented for this driver') - - def list_locations(self): - """ - List data centers for a provider - - :return: list of node location objects - :rtype: ``list`` of :class:`.NodeLocation` - """ - raise NotImplementedError( - 'list_locations not implemented for this driver') - - def create_node(self, **kwargs): - """ - Create a new node instance. This instance will be started - automatically. - - Not all hosting API's are created equal and to allow libcloud to - support as many as possible there are some standard supported - variations of ``create_node``. These are declared using a - ``features`` API. - You can inspect ``driver.features['create_node']`` to see what - variation of the API you are dealing with: - - ``ssh_key`` - You can inject a public key into a new node allows key based SSH - authentication. - ``password`` - You can inject a password into a new node for SSH authentication. - If no password is provided libcloud will generated a password. - The password will be available as - ``return_value.extra['password']``. - ``generates_password`` - The hosting provider will generate a password. It will be returned - to you via ``return_value.extra['password']``. - - Some drivers allow you to set how you will authenticate with the - instance that is created. You can inject this initial authentication - information via the ``auth`` parameter. - - If a driver supports the ``ssh_key`` feature flag for ``created_node`` - you can upload a public key into the new instance:: - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> auth = NodeAuthSSHKey('pubkey data here') - >>> node = driver.create_node("test_node", auth=auth) - - If a driver supports the ``password`` feature flag for ``create_node`` - you can set a password:: - - >>> driver = DummyNodeDriver(0) - >>> auth = NodeAuthPassword('mysecretpassword') - >>> node = driver.create_node("test_node", auth=auth) - - If a driver supports the ``password`` feature and you don't provide the - ``auth`` argument libcloud will assign a password:: - - >>> driver = DummyNodeDriver(0) - >>> node = driver.create_node("test_node") - >>> password = node.extra['password'] - - A password will also be returned in this way for drivers that declare - the ``generates_password`` feature, though in that case the password is - actually provided to the driver API by the hosting provider rather than - generated by libcloud. - - You can only pass a :class:`.NodeAuthPassword` or - :class:`.NodeAuthSSHKey` to ``create_node`` via the auth parameter if - has the corresponding feature flag. - - :param name: String with a name for this new node (required) - :type name: ``str`` - - :param size: The size of resources allocated to this node. - (required) - :type size: :class:`.NodeSize` - - :param image: OS Image to boot on node. (required) - :type image: :class:`.NodeImage` - - :param location: Which data center to create a node in. If empty, - undefined behavior will be selected. (optional) - :type location: :class:`.NodeLocation` - - :param auth: Initial authentication information for the node - (optional) - :type auth: :class:`.NodeAuthSSHKey` or :class:`NodeAuthPassword` - - :return: The newly created node. - :rtype: :class:`.Node` - """ - raise NotImplementedError( - 'create_node not implemented for this driver') - - def deploy_node(self, **kwargs): - """ - Create a new node, and start deployment. - - In order to be able to SSH into a created node access credentials are - required. - - A user can pass either a :class:`.NodeAuthPassword` or - :class:`.NodeAuthSSHKey` to the ``auth`` argument. If the - ``create_node`` implementation supports that kind if credential (as - declared in ``self.features['create_node']``) then it is passed on to - ``create_node``. Otherwise it is not passed on to ``create_node`` and - it is only used for authentication. - - If the ``auth`` parameter is not supplied but the driver declares it - supports ``generates_password`` then the password returned by - ``create_node`` will be used to SSH into the server. - - Finally, if the ``ssh_key_file`` is supplied that key will be used to - SSH into the server. - - This function may raise a :class:`DeploymentException`, if a - create_node call was successful, but there is a later error (like SSH - failing or timing out). This exception includes a Node object which - you may want to destroy if incomplete deployments are not desirable. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> from libcloud.compute.deployment import ScriptDeployment - >>> from libcloud.compute.deployment import MultiStepDeployment - >>> from libcloud.compute.base import NodeAuthSSHKey - >>> driver = DummyNodeDriver(0) - >>> key = NodeAuthSSHKey('...') # read from file - >>> script = ScriptDeployment("yum -y install emacs strace tcpdump") - >>> msd = MultiStepDeployment([key, script]) - >>> def d(): - ... try: - ... driver.deploy_node(deploy=msd) - ... except NotImplementedError: - ... print ("not implemented for dummy driver") - >>> d() - not implemented for dummy driver - - Deploy node is typically not overridden in subclasses. The - existing implementation should be able to handle most such. - - :param deploy: Deployment to run once machine is online and - available to SSH. - :type deploy: :class:`Deployment` - - :param ssh_username: Optional name of the account which is used - when connecting to - SSH server (default is root) - :type ssh_username: ``str`` - - :param ssh_alternate_usernames: Optional list of ssh usernames to - try to connect with if using the - default one fails - :type ssh_alternate_usernames: ``list`` - - :param ssh_port: Optional SSH server port (default is 22) - :type ssh_port: ``int`` - - :param ssh_timeout: Optional SSH connection timeout in seconds - (default is 10) - :type ssh_timeout: ``float`` - - :param auth: Initial authentication information for the node - (optional) - :type auth: :class:`.NodeAuthSSHKey` or :class:`NodeAuthPassword` - - :param ssh_key: A path (or paths) to an SSH private key with which - to attempt to authenticate. (optional) - :type ssh_key: ``str`` or ``list`` of ``str`` - - :param timeout: How many seconds to wait before timing out. - (default is 600) - :type timeout: ``int`` - - :param max_tries: How many times to retry if a deployment fails - before giving up (default is 3) - :type max_tries: ``int`` - - :param ssh_interface: The interface to wait for. Default is - 'public_ips', other option is 'private_ips'. - :type ssh_interface: ``str`` - """ - if not libcloud.compute.ssh.have_paramiko: - raise RuntimeError('paramiko is not installed. You can install ' + - 'it using pip: pip install paramiko') - - if 'auth' in kwargs: - auth = kwargs['auth'] - if not isinstance(auth, (NodeAuthSSHKey, NodeAuthPassword)): - raise NotImplementedError( - 'If providing auth, only NodeAuthSSHKey or' - 'NodeAuthPassword is supported') - elif 'ssh_key' in kwargs: - # If an ssh_key is provided we can try deploy_node - pass - elif 'create_node' in self.features: - f = self.features['create_node'] - if 'generates_password' not in f and "password" not in f: - raise NotImplementedError( - 'deploy_node not implemented for this driver') - else: - raise NotImplementedError( - 'deploy_node not implemented for this driver') - - node = self.create_node(**kwargs) - max_tries = kwargs.get('max_tries', 3) - - password = None - if 'auth' in kwargs: - if isinstance(kwargs['auth'], NodeAuthPassword): - password = kwargs['auth'].password - elif 'password' in node.extra: - password = node.extra['password'] - - ssh_interface = kwargs.get('ssh_interface', 'public_ips') - - # Wait until node is up and running and has IP assigned - try: - node, ip_addresses = self.wait_until_running( - nodes=[node], - wait_period=3, - timeout=kwargs.get('timeout', NODE_ONLINE_WAIT_TIMEOUT), - ssh_interface=ssh_interface)[0] - except Exception: - e = sys.exc_info()[1] - raise DeploymentError(node=node, original_exception=e, driver=self) - - ssh_username = kwargs.get('ssh_username', 'root') - ssh_alternate_usernames = kwargs.get('ssh_alternate_usernames', []) - ssh_port = kwargs.get('ssh_port', 22) - ssh_timeout = kwargs.get('ssh_timeout', 10) - ssh_key_file = kwargs.get('ssh_key', None) - timeout = kwargs.get('timeout', SSH_CONNECT_TIMEOUT) - - deploy_error = None - - for username in ([ssh_username] + ssh_alternate_usernames): - try: - self._connect_and_run_deployment_script( - task=kwargs['deploy'], node=node, - ssh_hostname=ip_addresses[0], ssh_port=ssh_port, - ssh_username=username, ssh_password=password, - ssh_key_file=ssh_key_file, ssh_timeout=ssh_timeout, - timeout=timeout, max_tries=max_tries) - except Exception: - # Try alternate username - # Todo: Need to fix paramiko so we can catch a more specific - # exception - e = sys.exc_info()[1] - deploy_error = e - else: - # Script successfully executed, don't try alternate username - deploy_error = None - break - - if deploy_error is not None: - raise DeploymentError(node=node, original_exception=deploy_error, - driver=self) - - return node - - def reboot_node(self, node): - """ - Reboot a node. - - :param node: The node to be rebooted - :type node: :class:`.Node` - - :return: True if the reboot was successful, otherwise False - :rtype: ``bool`` - """ - raise NotImplementedError( - 'reboot_node not implemented for this driver') - - def destroy_node(self, node): - """ - Destroy a node. - - Depending upon the provider, this may destroy all data associated with - the node, including backups. - - :param node: The node to be destroyed - :type node: :class:`.Node` - - :return: True if the destroy was successful, False otherwise. - :rtype: ``bool`` - """ - raise NotImplementedError( - 'destroy_node not implemented for this driver') - - ## - # Volume and snapshot management methods - ## - - def list_volumes(self): - """ - List storage volumes. - - :rtype: ``list`` of :class:`.StorageVolume` - """ - raise NotImplementedError( - 'list_volumes not implemented for this driver') - - def list_volume_snapshots(self, volume): - """ - List snapshots for a storage volume. - - :rtype: ``list`` of :class:`VolumeSnapshot` - """ - raise NotImplementedError( - 'list_volume_snapshots not implemented for this driver') - - def create_volume(self, size, name, location=None, snapshot=None): - """ - Create a new volume. - - :param size: Size of volume in gigabytes (required) - :type size: ``int`` - - :param name: Name of the volume to be created - :type name: ``str`` - - :param location: Which data center to create a volume in. If - empty, undefined behavior will be selected. - (optional) - :type location: :class:`.NodeLocation` - - :param snapshot: Snapshot from which to create the new - volume. (optional) - :type snapshot: :class:`.VolumeSnapshot` - - :return: The newly created volume. - :rtype: :class:`StorageVolume` - """ - raise NotImplementedError( - 'create_volume not implemented for this driver') - - def create_volume_snapshot(self, volume, name=None): - """ - Creates a snapshot of the storage volume. - - :param volume: The StorageVolume to create a VolumeSnapshot from - :type volume: :class:`.VolumeSnapshot` - - :param name: Name of created snapshot (optional) - :type name: `str` - - :rtype: :class:`VolumeSnapshot` - """ - raise NotImplementedError( - 'create_volume_snapshot not implemented for this driver') - - def attach_volume(self, node, volume, device=None): - """ - Attaches volume to node. - - :param node: Node to attach volume to. - :type node: :class:`.Node` - - :param volume: Volume to attach. - :type volume: :class:`.StorageVolume` - - :param device: Where the device is exposed, e.g. '/dev/sdb' - :type device: ``str`` - - :rytpe: ``bool`` - """ - raise NotImplementedError('attach not implemented for this driver') - - def detach_volume(self, volume): - """ - Detaches a volume from a node. - - :param volume: Volume to be detached - :type volume: :class:`.StorageVolume` - - :rtype: ``bool`` - """ - - raise NotImplementedError('detach not implemented for this driver') - - def destroy_volume(self, volume): - """ - Destroys a storage volume. - - :param volume: Volume to be destroyed - :type volume: :class:`StorageVolume` - - :rtype: ``bool`` - """ - - raise NotImplementedError( - 'destroy_volume not implemented for this driver') - - def destroy_volume_snapshot(self, snapshot): - """ - Destroys a snapshot. - - :param snapshot: The snapshot to delete - :type snapshot: :class:`VolumeSnapshot` - - :rtype: :class:`bool` - """ - raise NotImplementedError( - 'destroy_volume_snapshot not implemented for this driver') - - ## - # Image management methods - ## - - def list_images(self, location=None): - """ - List images on a provider. - - :param location: The location at which to list images. - :type location: :class:`.NodeLocation` - - :return: list of node image objects. - :rtype: ``list`` of :class:`.NodeImage` - """ - raise NotImplementedError( - 'list_images not implemented for this driver') - - def create_image(self, node, name, description=None): - """ - Creates an image from a node object. - - :param node: Node to run the task on. - :type node: :class:`.Node` - - :param name: name for new image. - :type name: ``str`` - - :param description: description for new image. - :type name: ``description`` - - :rtype: :class:`.NodeImage`: - :return: NodeImage instance on success. - - """ - raise NotImplementedError( - 'create_image not implemented for this driver') - - def delete_image(self, node_image): - """ - Deletes a node image from a provider. - - :param node_image: Node image object. - :type node_image: :class:`.NodeImage` - - :return: ``True`` if delete_image was successful, ``False`` otherwise. - :rtype: ``bool`` - """ - - raise NotImplementedError( - 'delete_image not implemented for this driver') - - def get_image(self, image_id): - """ - Returns a single node image from a provider. - - :param image_id: Node to run the task on. - :type image_id: ``str`` - - :rtype :class:`.NodeImage`: - :return: NodeImage instance on success. - """ - raise NotImplementedError( - 'get_image not implemented for this driver') - - def copy_image(self, source_region, node_image, name, description=None): - """ - Copies an image from a source region to the current region. - - :param source_region: Region to copy the node from. - :type source_region: ``str`` - - :param node_image: NodeImage to copy. - :type node_image: :class:`.NodeImage`: - - :param name: name for new image. - :type name: ``str`` - - :param description: description for new image. - :type name: ``str`` - - :rtype: :class:`.NodeImage`: - :return: NodeImage instance on success. - """ - raise NotImplementedError( - 'copy_image not implemented for this driver') - - ## - # SSH key pair management methods - ## - - def list_key_pairs(self): - """ - List all the available key pair objects. - - :rtype: ``list`` of :class:`.KeyPair` objects - """ - raise NotImplementedError( - 'list_key_pairs not implemented for this driver') - - def get_key_pair(self, name): - """ - Retrieve a single key pair. - - :param name: Name of the key pair to retrieve. - :type name: ``str`` - - :rtype: :class:`.KeyPair` - """ - raise NotImplementedError( - 'get_key_pair not implemented for this driver') - - def create_key_pair(self, name): - """ - Create a new key pair object. - - :param name: Key pair name. - :type name: ``str`` - """ - raise NotImplementedError( - 'create_key_pair not implemented for this driver') - - def import_key_pair_from_string(self, name, key_material): - """ - Import a new public key from string. - - :param name: Key pair name. - :type name: ``str`` - - :param key_material: Public key material. - :type key_material: ``str`` - - :rtype: :class:`.KeyPair` object - """ - raise NotImplementedError( - 'import_key_pair_from_string not implemented for this driver') - - def import_key_pair_from_file(self, name, key_file_path): - """ - Import a new public key from string. - - :param name: Key pair name. - :type name: ``str`` - - :param key_file_path: Path to the public key file. - :type key_file_path: ``str`` - - :rtype: :class:`.KeyPair` object - """ - key_file_path = os.path.expanduser(key_file_path) - - with open(key_file_path, 'r') as fp: - key_material = fp.read() - - return self.import_key_pair_from_string(name=name, - key_material=key_material) - - def delete_key_pair(self, key_pair): - """ - Delete an existing key pair. - - :param key_pair: Key pair object. - :type key_pair: :class:`.KeyPair` - """ - raise NotImplementedError( - 'delete_key_pair not implemented for this driver') - - def wait_until_running(self, nodes, wait_period=3, - timeout=600, ssh_interface='public_ips', - force_ipv4=True, ex_list_nodes_kwargs=None): - """ - Block until the provided nodes are considered running. - - Node is considered running when it's state is "running" and when it has - at least one IP address assigned. - - :param nodes: List of nodes to wait for. - :type nodes: ``list`` of :class:`.Node` - - :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`` - - :param ssh_interface: Which attribute on the node to use to obtain - an IP address. Valid options: public_ips, - private_ips. Default is public_ips. - :type ssh_interface: ``str`` - - :param force_ipv4: Ignore IPv6 addresses (default is True). - :type force_ipv4: ``bool`` - - :param ex_list_nodes_kwargs: Optional driver-specific keyword arguments - which are passed to the ``list_nodes`` - method. - :type ex_list_nodes_kwargs: ``dict`` - - :return: ``[(Node, ip_addresses)]`` list of tuple of Node instance and - list of ip_address on success. - :rtype: ``list`` of ``tuple`` - """ - ex_list_nodes_kwargs = ex_list_nodes_kwargs or {} - - def is_supported(address): - """ - Return True for supported address. - """ - if force_ipv4 and not is_valid_ip_address(address=address, - family=socket.AF_INET): - return False - return True - - def filter_addresses(addresses): - """ - Return list of supported addresses. - """ - return [address for address in addresses if is_supported(address)] - - if ssh_interface not in ['public_ips', 'private_ips']: - raise ValueError('ssh_interface argument must either be' + - 'public_ips or private_ips') - - start = time.time() - end = start + timeout - - uuids = set([node.uuid for node in nodes]) - - while time.time() < end: - all_nodes = self.list_nodes(**ex_list_nodes_kwargs) - matching_nodes = list([node for node in all_nodes - if node.uuid in uuids]) - - if len(matching_nodes) > len(uuids): - found_uuids = [node.uuid for node in matching_nodes] - msg = ('Unable to match specified uuids ' + - '(%s) with existing nodes. Found ' % (uuids) + - 'multiple nodes with same uuid: (%s)' % (found_uuids)) - raise LibcloudError(value=msg, driver=self) - - running_nodes = [node for node in matching_nodes - if node.state == NodeState.RUNNING] - addresses = [filter_addresses(getattr(node, ssh_interface)) - for node in running_nodes] - - if len(running_nodes) == len(uuids) == len(addresses): - return list(zip(running_nodes, addresses)) - else: - time.sleep(wait_period) - continue - - raise LibcloudError(value='Timed out after %s seconds' % (timeout), - driver=self) - - def _get_and_check_auth(self, auth): - """ - Helper function for providers supporting :class:`.NodeAuthPassword` or - :class:`.NodeAuthSSHKey` - - Validates that only a supported object type is passed to the auth - parameter and raises an exception if it is not. - - If no :class:`.NodeAuthPassword` object is provided but one is expected - then a password is automatically generated. - """ - - if isinstance(auth, NodeAuthPassword): - if 'password' in self.features['create_node']: - return auth - raise LibcloudError( - 'Password provided as authentication information, but password' - 'not supported', driver=self) - - if isinstance(auth, NodeAuthSSHKey): - if 'ssh_key' in self.features['create_node']: - return auth - raise LibcloudError( - 'SSH Key provided as authentication information, but SSH Key' - 'not supported', driver=self) - - if 'password' in self.features['create_node']: - value = os.urandom(16) - value = binascii.hexlify(value).decode('ascii') - - # Some providers require password to also include uppercase - # characters so convert some characters to uppercase - password = '' - for char in value: - if not char.isdigit() and char.islower(): - if random.randint(0, 1) == 1: - char = char.upper() - - password += char - - return NodeAuthPassword(password, generated=True) - - if auth: - raise LibcloudError( - '"auth" argument provided, but it was not a NodeAuthPassword' - 'or NodeAuthSSHKey object', driver=self) - - def _wait_until_running(self, node, wait_period=3, timeout=600, - ssh_interface='public_ips', force_ipv4=True): - # This is here for backward compatibility and will be removed in the - # next major release - return self.wait_until_running(nodes=[node], wait_period=wait_period, - timeout=timeout, - ssh_interface=ssh_interface, - force_ipv4=force_ipv4) - - def _ssh_client_connect(self, ssh_client, wait_period=1.5, timeout=300): - """ - Try to connect to the remote SSH server. If a connection times out or - is refused it is retried up to timeout number of seconds. - - :param ssh_client: A configured SSHClient instance - :type ssh_client: ``SSHClient`` - - :param wait_period: How many seconds to wait between each loop - iteration. (default is 1.5) - :type wait_period: ``int`` - - :param timeout: How many seconds to wait before giving up. - (default is 300) - :type timeout: ``int`` - - :return: ``SSHClient`` on success - """ - start = time.time() - end = start + timeout - - while time.time() < end: - try: - ssh_client.connect() - except SSH_TIMEOUT_EXCEPTION_CLASSES: - e = sys.exc_info()[1] - message = str(e).lower() - expected_msg = 'no such file or directory' - - if isinstance(e, IOError) and expected_msg in message: - # Propagate (key) file doesn't exist errors - raise e - - # Retry if a connection is refused, timeout occurred, - # or the connection fails due to failed authentication. - ssh_client.close() - time.sleep(wait_period) - continue - else: - return ssh_client - - raise LibcloudError(value='Could not connect to the remote SSH ' + - 'server. Giving up.', driver=self) - - def _connect_and_run_deployment_script(self, task, node, ssh_hostname, - ssh_port, ssh_username, - ssh_password, ssh_key_file, - ssh_timeout, timeout, max_tries): - """ - Establish an SSH connection to the node and run the provided deployment - task. - - :rtype: :class:`.Node`: - :return: Node instance on success. - """ - ssh_client = SSHClient(hostname=ssh_hostname, - port=ssh_port, username=ssh_username, - password=ssh_password, - key_files=ssh_key_file, - timeout=ssh_timeout) - - ssh_client = self._ssh_client_connect(ssh_client=ssh_client, - timeout=timeout) - - # Execute the deployment task - node = self._run_deployment_script(task=task, node=node, - ssh_client=ssh_client, - max_tries=max_tries) - return node - - def _run_deployment_script(self, task, node, ssh_client, max_tries=3): - """ - Run the deployment script on the provided node. At this point it is - assumed that SSH connection has already been established. - - :param task: Deployment task to run. - :type task: :class:`Deployment` - - :param node: Node to run the task on. - :type node: ``Node`` - - :param ssh_client: A configured and connected SSHClient instance. - :type ssh_client: :class:`SSHClient` - - :param max_tries: How many times to retry if a deployment fails - before giving up. (default is 3) - :type max_tries: ``int`` - - :rtype: :class:`.Node` - :return: ``Node`` Node instance on success. - """ - tries = 0 - - while tries < max_tries: - try: - node = task.run(node, ssh_client) - except Exception: - tries += 1 - - if tries >= max_tries: - e = sys.exc_info()[1] - raise LibcloudError(value='Failed after %d tries: %s' - % (max_tries, str(e)), driver=self) - else: - # Deployment succeeded - ssh_client.close() - return node - - def _get_size_price(self, size_id): - """ - Return pricing information for the provided size id. - """ - return get_size_price(driver_type='compute', - driver_name=self.api_name, - size_id=size_id) - - -if __name__ == '__main__': - import doctest - doctest.testmod() http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/deployment.py ---------------------------------------------------------------------- diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/deployment.py b/apache-libcloud-1.0.0rc2/libcloud/compute/deployment.py deleted file mode 100644 index d5f7eec..0000000 --- a/apache-libcloud-1.0.0rc2/libcloud/compute/deployment.py +++ /dev/null @@ -1,263 +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. - -""" -Provides generic deployment steps for machines post boot. -""" - -from __future__ import with_statement - -import os -import binascii - -from libcloud.utils.py3 import basestring, PY3 - - -class Deployment(object): - """ - Base class for deployment tasks. - """ - - def run(self, node, client): - """ - Runs this deployment task on node using the client provided. - - :type node: :class:`Node` - :keyword node: Node to operate one - - :type client: :class:`BaseSSHClient` - :keyword client: Connected SSH client to use. - - :return: :class:`Node` - """ - raise NotImplementedError( - 'run not implemented for this deployment') - - def _get_string_value(self, argument_name, argument_value): - if not isinstance(argument_value, basestring) and \ - not hasattr(argument_value, 'read'): - raise TypeError('%s argument must be a string or a file-like ' - 'object' % (argument_name)) - - if hasattr(argument_value, 'read'): - argument_value = argument_value.read() - - return argument_value - - -class SSHKeyDeployment(Deployment): - """ - Installs a public SSH Key onto a server. - """ - - def __init__(self, key): - """ - :type key: ``str`` or :class:`File` object - :keyword key: Contents of the public key write or a file object which - can be read. - """ - self.key = self._get_string_value(argument_name='key', - argument_value=key) - - def run(self, node, client): - """ - Installs SSH key into ``.ssh/authorized_keys`` - - See also :class:`Deployment.run` - """ - client.put(".ssh/authorized_keys", contents=self.key, mode='a') - return node - - -class FileDeployment(Deployment): - """ - Installs a file on the server. - """ - - def __init__(self, source, target): - """ - :type source: ``str`` - :keyword source: Local path of file to be installed - - :type target: ``str`` - :keyword target: Path to install file on node - """ - self.source = source - self.target = target - - def run(self, node, client): - """ - Upload the file, retaining permissions. - - See also :class:`Deployment.run` - """ - perms = int(oct(os.stat(self.source).st_mode)[4:], 8) - - with open(self.source, 'rb') as fp: - content = fp.read() - - client.put(path=self.target, chmod=perms, - contents=content) - return node - - -class ScriptDeployment(Deployment): - """ - Runs an arbitrary shell script on the server. - - This step works by first writing the content of the shell script (script - argument) in a \*.sh file on a remote server and then running that file. - - If you are running a non-shell script, make sure to put the appropriate - shebang to the top of the script. You are also advised to do that even if - you are running a plan shell script. - """ - - def __init__(self, script, args=None, name=None, delete=False): - """ - :type script: ``str`` - :keyword script: Contents of the script to run. - - :type args: ``list`` - :keyword args: Optional command line arguments which get passed to the - deployment script file. - - :type name: ``str`` - :keyword name: Name of the script to upload it as, if not specified, - a random name will be chosen. - - :type delete: ``bool`` - :keyword delete: Whether to delete the script on completion. - """ - script = self._get_string_value(argument_name='script', - argument_value=script) - - self.script = script - self.args = args or [] - self.stdout = None - self.stderr = None - self.exit_status = None - self.delete = delete - self.name = name - - if self.name is None: - # File is put under user's home directory - # (~/libcloud_deployment_<random_string>.sh) - random_string = binascii.hexlify(os.urandom(4)) - random_string = random_string.decode('ascii') - self.name = 'libcloud_deployment_%s.sh' % (random_string) - - def run(self, node, client): - """ - Uploads the shell script and then executes it. - - See also :class:`Deployment.run` - """ - file_path = client.put(path=self.name, chmod=int('755', 8), - contents=self.script) - - # Pre-pend cwd if user specified a relative path - if self.name[0] != '/': - base_path = os.path.dirname(file_path) - name = os.path.join(base_path, self.name) - else: - name = self.name - - cmd = name - - if self.args: - # Append arguments to the command - cmd = '%s %s' % (name, ' '.join(self.args)) - else: - cmd = name - - self.stdout, self.stderr, self.exit_status = client.run(cmd) - - if self.delete: - client.delete(self.name) - - return node - - -class ScriptFileDeployment(ScriptDeployment): - """ - Runs an arbitrary shell script from a local file on the server. Same as - ScriptDeployment, except that you can pass in a path to the file instead of - the script content. - """ - - def __init__(self, script_file, args=None, name=None, delete=False): - """ - :type script_file: ``str`` - :keyword script_file: Path to a file containing the script to run. - - :type args: ``list`` - :keyword args: Optional command line arguments which get passed to the - deployment script file. - - - :type name: ``str`` - :keyword name: Name of the script to upload it as, if not specified, - a random name will be chosen. - - :type delete: ``bool`` - :keyword delete: Whether to delete the script on completion. - """ - with open(script_file, 'rb') as fp: - content = fp.read() - - if PY3: - content = content.decode('utf-8') - - super(ScriptFileDeployment, self).__init__(script=content, - args=args, - name=name, - delete=delete) - - -class MultiStepDeployment(Deployment): - """ - Runs a chain of Deployment steps. - """ - def __init__(self, add=None): - """ - :type add: ``list`` - :keyword add: Deployment steps to add. - """ - self.steps = [] - self.add(add) - - def add(self, add): - """ - Add a deployment to this chain. - - :type add: Single :class:`Deployment` or a ``list`` of - :class:`Deployment` - :keyword add: Adds this deployment to the others already in this - object. - """ - if add is not None: - add = add if isinstance(add, (list, tuple)) else [add] - self.steps.extend(add) - - def run(self, node, client): - """ - Run each deployment that has been added. - - See also :class:`Deployment.run` - """ - for s in self.steps: - node = s.run(node, client) - return node http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/deprecated.py ---------------------------------------------------------------------- diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/deprecated.py b/apache-libcloud-1.0.0rc2/libcloud/compute/deprecated.py deleted file mode 100644 index d68e47f..0000000 --- a/apache-libcloud-1.0.0rc2/libcloud/compute/deprecated.py +++ /dev/null @@ -1,50 +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. -""" -Database of deprecated drivers -""" - -from libcloud.compute.types import Provider - -DEPRECATED_DRIVERS = { - Provider.OPSOURCE: { - 'reason': 'OpSource cloud is now part of Dimension Data, ' - 'use the DIMENSIONDATA provider instead.', - 'url': 'http://www.ntt.co.jp/news2011/1107e/110701a.html' - }, - Provider.NINEFOLD: { - 'reason': 'We will shortly notify our customers that we ' - 'will be sunsetting our Public Cloud Computing ' - '(Server) platform, the last day of operation ' - 'being January 30, 2016', - 'url': 'https://ninefold.com/news/' - }, - Provider.IBM: { - 'reason': 'IBM SmartCloud Enterprise has been deprecated ' - 'in favour of IBM SoftLayer Public Cloud, please' - ' use the SOFTLAYER provider.', - 'url': 'http://www.ibm.com/midmarket/us/en/article_cloud6_1310.html' - }, - Provider.HPCLOUD: { - 'reason': 'HP Helion Public Cloud was shut down in January 2016.', - 'url': 'http://libcloud.apache.org/blog/' - '2016/02/16/new-drivers-deprecated-drivers.html' - }, - Provider.CLOUDFRAMES: { - 'reason': 'The CloudFrames Provider is no longer supported', - 'url': 'http://libcloud.apache.org/blog/2016/02/16/new-drivers-' - 'deprecated-drivers.html' - } -} http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/__init__.py ---------------------------------------------------------------------- diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/__init__.py b/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/__init__.py deleted file mode 100644 index d7c26ed..0000000 --- a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/__init__.py +++ /dev/null @@ -1,44 +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. - -""" -Drivers for working with different providers -""" - -__all__ = [ - 'abiquo', - 'brightbox', - 'bluebox', - 'dimensiondata', - 'dummy', - 'ec2', - 'ecp', - 'elasticstack', - 'elastichosts', - 'cloudsigma', - 'gce', - 'gogrid', - 'hostvirtual', - 'ibm_sce', - 'linode', - 'opennebula', - 'rackspace', - 'rimuhosting', - 'softlayer', - 'vcloud', - 'voxel', - 'vpsnet', - 'onapp', -]