Repository: libcloud Updated Branches: refs/heads/trunk b09c1bef7 -> 054f29a94
Add new driver for VMware vSphere. Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/054f29a9 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/054f29a9 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/054f29a9 Branch: refs/heads/trunk Commit: 054f29a94eef433fe208641b5f63ca2f0c613672 Parents: b09c1be Author: Tomaz Muraus <[email protected]> Authored: Mon Jul 28 18:52:44 2014 +0200 Committer: Tomaz Muraus <[email protected]> Committed: Tue Jul 29 14:51:40 2014 +0200 ---------------------------------------------------------------------- CHANGES.rst | 4 + .../images/provider_logos/vmware_vsphere.png | Bin 0 -> 71341 bytes .../_supported_methods_block_storage.rst | 2 + .../_supported_methods_image_management.rst | 2 + .../_supported_methods_key_pair_management.rst | 2 + docs/compute/_supported_methods_main.rst | 2 + docs/compute/_supported_providers.rst | 2 + docs/compute/drivers/vsphere.rst | 76 ++++ docs/examples/compute/vsphere/connect_host.py | 8 + docs/examples/compute/vsphere/connect_url.py | 8 + .../compute/vsphere/connect_url_custom_port.py | 8 + libcloud/compute/drivers/vsphere.py | 349 +++++++++++++++++++ libcloud/compute/providers.py | 2 + libcloud/compute/types.py | 1 + libcloud/utils/decorators.py | 57 +++ 15 files changed, 523 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/CHANGES.rst ---------------------------------------------------------------------- diff --git a/CHANGES.rst b/CHANGES.rst index 4d7842e..5282f0b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,10 @@ Changes with Apache Libcloud in development Compute ~~~~~~~ +- Add new driver for VMware vSphere (http://www.vmware.com/products/vsphere/) + based clouds. + [Tomaz Muraus] + - Add two new default node states - ``NodeState.SUSPENDED`` and ``NodeState.ERROR``. [Tomaz Muraus] http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/_static/images/provider_logos/vmware_vsphere.png ---------------------------------------------------------------------- diff --git a/docs/_static/images/provider_logos/vmware_vsphere.png b/docs/_static/images/provider_logos/vmware_vsphere.png new file mode 100644 index 0000000..152c733 Binary files /dev/null and b/docs/_static/images/provider_logos/vmware_vsphere.png differ http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/compute/_supported_methods_block_storage.rst ---------------------------------------------------------------------- diff --git a/docs/compute/_supported_methods_block_storage.rst b/docs/compute/_supported_methods_block_storage.rst index 1776d0a..bc7f9e9 100644 --- a/docs/compute/_supported_methods_block_storage.rst +++ b/docs/compute/_supported_methods_block_storage.rst @@ -62,6 +62,7 @@ Provider list volumes create volume destroy volume `vCloud`_ no no no no no no no `Voxel VoxCLOUD`_ no no no no no no no `vps.net`_ no no no no no no no +`VMware vSphere`_ no no no no no no no ===================================== ============ ============= ============== ============= ============= ============== =============== .. _`Abiquo`: http://www.abiquo.com/ @@ -125,3 +126,4 @@ Provider list volumes create volume destroy volume .. _`vCloud`: http://www.vmware.com/products/vcloud/ .. _`Voxel VoxCLOUD`: http://www.voxel.net/ .. _`vps.net`: http://vps.net/ +.. _`VMware vSphere`: http://www.vmware.com/products/vsphere/ http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/compute/_supported_methods_image_management.rst ---------------------------------------------------------------------- diff --git a/docs/compute/_supported_methods_image_management.rst b/docs/compute/_supported_methods_image_management.rst index 0734374..03d104b 100644 --- a/docs/compute/_supported_methods_image_management.rst +++ b/docs/compute/_supported_methods_image_management.rst @@ -62,6 +62,7 @@ Provider list images get image create image delete `vCloud`_ yes no no no no `Voxel VoxCLOUD`_ yes no no no no `vps.net`_ yes no no no no +`VMware vSphere`_ no no no no no ===================================== =========== ========= ============ ============ ========== .. _`Abiquo`: http://www.abiquo.com/ @@ -125,3 +126,4 @@ Provider list images get image create image delete .. _`vCloud`: http://www.vmware.com/products/vcloud/ .. _`Voxel VoxCLOUD`: http://www.voxel.net/ .. _`vps.net`: http://vps.net/ +.. _`VMware vSphere`: http://www.vmware.com/products/vsphere/ http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/compute/_supported_methods_key_pair_management.rst ---------------------------------------------------------------------- diff --git a/docs/compute/_supported_methods_key_pair_management.rst b/docs/compute/_supported_methods_key_pair_management.rst index f474959..8941a8b 100644 --- a/docs/compute/_supported_methods_key_pair_management.rst +++ b/docs/compute/_supported_methods_key_pair_management.rst @@ -62,6 +62,7 @@ Provider list key pairs get key pair create key pai `vCloud`_ no no no no no no `Voxel VoxCLOUD`_ no no no no no no `vps.net`_ no no no no no no +`VMware vSphere`_ no no no no no no ===================================== ============== ============ =============== ============================= =========================== =============== .. _`Abiquo`: http://www.abiquo.com/ @@ -125,3 +126,4 @@ Provider list key pairs get key pair create key pai .. _`vCloud`: http://www.vmware.com/products/vcloud/ .. _`Voxel VoxCLOUD`: http://www.voxel.net/ .. _`vps.net`: http://vps.net/ +.. _`VMware vSphere`: http://www.vmware.com/products/vsphere/ http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/compute/_supported_methods_main.rst ---------------------------------------------------------------------- diff --git a/docs/compute/_supported_methods_main.rst b/docs/compute/_supported_methods_main.rst index 5fab349..216e1bb 100644 --- a/docs/compute/_supported_methods_main.rst +++ b/docs/compute/_supported_methods_main.rst @@ -62,6 +62,7 @@ Provider list nodes create node reboot node destroy `vCloud`_ yes yes yes yes yes yes yes `Voxel VoxCLOUD`_ yes yes yes yes yes yes no `vps.net`_ yes yes yes yes yes yes no +`VMware vSphere`_ yes no yes yes no no no ===================================== ========== =========== =========== ============ =========== ========== =========== .. _`Abiquo`: http://www.abiquo.com/ @@ -125,3 +126,4 @@ Provider list nodes create node reboot node destroy .. _`vCloud`: http://www.vmware.com/products/vcloud/ .. _`Voxel VoxCLOUD`: http://www.voxel.net/ .. _`vps.net`: http://vps.net/ +.. _`VMware vSphere`: http://www.vmware.com/products/vsphere/ http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/compute/_supported_providers.rst ---------------------------------------------------------------------- diff --git a/docs/compute/_supported_providers.rst b/docs/compute/_supported_providers.rst index 53c7099..fa24076 100644 --- a/docs/compute/_supported_providers.rst +++ b/docs/compute/_supported_providers.rst @@ -62,6 +62,7 @@ Provider Documentation `vCloud`_ :doc:`Click </compute/drivers/vcloud>` VCLOUD :mod:`libcloud.compute.drivers.vcloud` :class:`VCloudNodeDriver` `Voxel VoxCLOUD`_ VOXEL :mod:`libcloud.compute.drivers.voxel` :class:`VoxelNodeDriver` `vps.net`_ VPSNET :mod:`libcloud.compute.drivers.vpsnet` :class:`VPSNetNodeDriver` +`VMware vSphere`_ :doc:`Click </compute/drivers/vsphere>` VSPHERE :mod:`libcloud.compute.drivers.vsphere` :class:`VSphereNodeDriver` ===================================== ============================================ =================== ============================================== ==================================== .. _`Abiquo`: http://www.abiquo.com/ @@ -125,3 +126,4 @@ Provider Documentation .. _`vCloud`: http://www.vmware.com/products/vcloud/ .. _`Voxel VoxCLOUD`: http://www.voxel.net/ .. _`vps.net`: http://vps.net/ +.. _`VMware vSphere`: http://www.vmware.com/products/vsphere/ http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/compute/drivers/vsphere.rst ---------------------------------------------------------------------- diff --git a/docs/compute/drivers/vsphere.rst b/docs/compute/drivers/vsphere.rst new file mode 100644 index 0000000..9f42316 --- /dev/null +++ b/docs/compute/drivers/vsphere.rst @@ -0,0 +1,76 @@ +VMware vSphere Compute Driver Documentation +=========================================== + +`VMware vSphere`_ is VMware's cloud computing operating system which allows +you to run your own private cloud. + +.. figure:: /_static/images/provider_logos/vmware_vsphere.png + :align: center + :width: 200 + :target: http://www.vmware.com/products/vsphere/ + +Requirements +------------ + +VMware vSphere driver depends on the `pysphere`_ Python library which needs to +be installed for the driver to work. + +This library can be installed using pip as shown bellow: + +.. sourcecode:: bash + + pip install pysphere + +Connecting to vSphere installation +---------------------------------- + +To connect to the vSphere installation you need to pass the following arguments +to the driver constructor + +* ``host`` - hostname or IP address of your vSphere installation. Note: if your + installation is using or accessible via a different port, you should use the + ``url`` argument which is described bellow instead. +* ``url`` - full URL to your vSphere installation client endpoint - e.g. + ``https://<host>/sdk/``. Note: This argument is mutually exclusive with + ``host`` argument which means you need to provide either ``host`` or ``url`` + argument, but not both. +* ``username`` - username used to log in +* ``password`` - password used to log in + +Examples +-------- + +1. Connect by specfiying a host +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: /examples/compute/vsphere/connect_host.py + :language: python + +2. Connect by specifying a url +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: /examples/compute/vsphere/connect_url.py + :language: python + +3. Connect by specifying a url (custom port) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: /examples/compute/vsphere/connect_url_custom_port.py + :language: python + +Troubleshooting +--------------- + +How do I know if I'm connecting to the correct URL? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are connecting by provider ``url`` argument and you get the +``Response is "text", not "text/xml"`` or similar error back, this most likely +means you have specified an invalid URL (e.g. you forgot to specify a path). + +You can test if the url you are using is valid by adding ``/vimService.wsdl`` +to it (e.g. ``https://<host>/sdk/vimService.wsdl``). When you visit this page, +you should get an XML response back. + +.. _`VMware vSphere`: http://www.vmware.com/products/vsphere/ +.. _`pysphere`: https://pypi.python.org/pypi/pysphere http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/examples/compute/vsphere/connect_host.py ---------------------------------------------------------------------- diff --git a/docs/examples/compute/vsphere/connect_host.py b/docs/examples/compute/vsphere/connect_host.py new file mode 100644 index 0000000..da587b7 --- /dev/null +++ b/docs/examples/compute/vsphere/connect_host.py @@ -0,0 +1,8 @@ +from libcloud.compute.types import Provider +from libcloud.compute.providers import get_driver + +cls = get_driver(Provider.VSPHERE) +driver = cls(host='192.168.1.100', + username='admin', password='admin') +print(driver.list_nodes()) +# ... http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/examples/compute/vsphere/connect_url.py ---------------------------------------------------------------------- diff --git a/docs/examples/compute/vsphere/connect_url.py b/docs/examples/compute/vsphere/connect_url.py new file mode 100644 index 0000000..de48298 --- /dev/null +++ b/docs/examples/compute/vsphere/connect_url.py @@ -0,0 +1,8 @@ +from libcloud.compute.types import Provider +from libcloud.compute.providers import get_driver + +cls = get_driver(Provider.VSPHERE) +driver = cls(url='https://192.168.1.100/sdk/', + username='admin', password='admin') +print(driver.list_nodes()) +# ... http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/docs/examples/compute/vsphere/connect_url_custom_port.py ---------------------------------------------------------------------- diff --git a/docs/examples/compute/vsphere/connect_url_custom_port.py b/docs/examples/compute/vsphere/connect_url_custom_port.py new file mode 100644 index 0000000..0f5a0dc --- /dev/null +++ b/docs/examples/compute/vsphere/connect_url_custom_port.py @@ -0,0 +1,8 @@ +from libcloud.compute.types import Provider +from libcloud.compute.providers import get_driver + +cls = get_driver(Provider.VSPHERE) +driver = cls(url='https://192.168.1.100:8080/sdk/', + username='admin', password='admin') +print(driver.list_nodes()) +# ... http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/libcloud/compute/drivers/vsphere.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/vsphere.py b/libcloud/compute/drivers/vsphere.py new file mode 100644 index 0000000..aa9ddd5 --- /dev/null +++ b/libcloud/compute/drivers/vsphere.py @@ -0,0 +1,349 @@ +# 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. + +""" +VMware vSphere driver supporting vSphere v5.5. + +Note: This driver requires pysphere package +(https://pypi.python.org/pypi/pysphere) which can be installed using pip. For +more information, please refer to the official documentation. +""" + +import os +import sys +import atexit + +try: + import pysphere + pysphere +except ImportError: + raise ImportError('Missing "pysphere" dependency. You can install it ' + 'using pip - pip install pysphere') + +from pysphere import VIServer +from pysphere.vi_task import VITask +from pysphere.resources import VimService_services as VI + +from libcloud.utils.decorators import wrap_non_libcloud_exceptions +from libcloud.common.base import ConnectionUserAndKey +from libcloud.common.types import LibcloudError +from libcloud.common.types import InvalidCredsError +from libcloud.compute.base import NodeDriver +from libcloud.compute.base import NodeLocation +from libcloud.compute.base import Node +from libcloud.compute.types import NodeState, Provider +from libcloud.utils.networking import is_public_subnet + +__all__ = [ + 'VSphereNodeDriver', + 'VSphere_5_5_NodeDriver' +] + +DEFAULT_API_VERSION = '5.5' +DEFAULT_CONNECTION_TIMEOUT = 5 # default connection timeout in seconds + + +class VSphereConnection(ConnectionUserAndKey): + def __init__(self, user_id, key, secure=True, + host=None, port=None, url=None, timeout=None): + if host and url: + raise ValueError('host and url arguments are mutally exclusive') + + if host: + host_or_url = host + elif url: + host_or_url = url + else: + raise ValueError('Either "host" or "url" argument must be ' + 'provided') + + self.host_or_url = host_or_url + self.client = None + super(VSphereConnection, self).__init__(user_id=user_id, + key=key, secure=secure, + host=host, port=port, + url=url, timeout=timeout) + + def connect(self): + self.client = VIServer() + + trace_file = os.environ.get('LIBCLOUD_DEBUG', None) + + try: + self.client.connect(host=self.host_or_url, user=self.user_id, + password=self.key, + sock_timeout=DEFAULT_CONNECTION_TIMEOUT, + trace_file=trace_file) + except Exception: + e = sys.exc_info()[1] + message = e.message + fault = getattr(e, 'fault', None) + + if fault == 'InvalidLoginFault': + raise InvalidCredsError(message) + + raise LibcloudError(value=message, driver=self.driver) + + atexit.register(self.disconnect) + + def disconnect(self): + if not self.client: + return + + try: + self.client.disconnect() + except Exception: + # Ignore all the disconnect errors + pass + + def run_client_method(self, method_name, **method_kwargs): + method = getattr(self.client, method_name, None) + return method(**method_kwargs) + + +class VSphereNodeDriver(NodeDriver): + name = 'VMware vSphere' + website = 'http://www.vmware.com/products/vsphere/' + type = Provider.VSPHERE + connectionCls = VSphereConnection + + NODE_STATE_MAP = { + 'POWERED ON': NodeState.RUNNING, + 'POWERED OFF': NodeState.STOPPED, + 'SUSPENDED': NodeState.SUSPENDED, + 'POWERING ON': NodeState.PENDING, + 'POWERING OFF': NodeState.PENDING, + 'SUSPENDING': NodeState.PENDING, + 'RESETTING': NodeState.PENDING, + 'BLOCKED ON MSG': NodeState.ERROR, + 'REVERTING TO SNAPSHOT': NodeState.PENDING + } + + def __new__(cls, username, password, secure=True, host=None, port=None, + url=None, api_version=DEFAULT_API_VERSION, **kwargs): + if cls is VSphereNodeDriver: + if api_version == '5.5': + cls = VSphere_5_5_NodeDriver + else: + raise NotImplementedError('Unsupported API version: %s' % + (api_version)) + return super(VSphereNodeDriver, cls).__new__(cls) + + def __init__(self, username, password, secure=True, + host=None, port=None, url=None, timeout=None): + self.url = url + super(VSphereNodeDriver, self).__init__(key=username, secret=password, + secure=secure, host=host, + port=port, url=url) + + @wrap_non_libcloud_exceptions + def list_locations(self): + """ + List available locations. + + In vSphere case, a location represents a datacenter. + """ + datacenters = self.connection.client.get_datacenters() + + locations = [] + for id, name in datacenters.items(): + location = NodeLocation(id=id, name=name, country=None, + driver=self) + locations.append(location) + + return locations + + @wrap_non_libcloud_exceptions + def list_nodes(self): + vm_paths = self.connection.client.get_registered_vms() + nodes = self._to_nodes(vm_paths=vm_paths) + + return nodes + + @wrap_non_libcloud_exceptions + def reboot_node(self, node): + vm = self._get_vm_for_node(node=node) + vm.reset() + + return True + + @wrap_non_libcloud_exceptions + def destroy_node(self, node, ex_remove_files=True): + """ + :param ex_remove_files: Remove all the files from the datastore. + :type ex_remove_files: ``bool`` + """ + ex_remove_files = False + vm = self._get_vm_for_node(node=node) + + server = self.connection.client + + # Based on code from + # https://pypi.python.org/pypi/pyxenter + if ex_remove_files: + request = VI.Destroy_TaskRequestMsg() + + _this = request.new__this(vm._mor) + _this.set_attribute_type(vm._mor.get_attribute_type()) + request.set_element__this(_this) + ret = server._proxy.Destroy_Task(request)._returnval + task = VITask(ret, server) + + # Wait for the task to finish + status = task.wait_for_state([task.STATE_SUCCESS, + task.STATE_ERROR]) + + if status == task.STATE_ERROR: + raise LibcloudError('Error destroying node: %s' % + (task.get_error_message())) + else: + request = VI.UnregisterVMRequestMsg() + + _this = request.new__this(vm._mor) + _this.set_attribute_type(vm._mor.get_attribute_type()) + request.set_element__this(_this) + ret = server._proxy.UnregisterVM(request) + task = VITask(ret, server) + + return True + + @wrap_non_libcloud_exceptions + def ex_stop_node(self, node): + vm = self._get_vm_for_node(node=node) + vm.power_off() + + return True + + @wrap_non_libcloud_exceptions + def ex_start_node(self, node): + vm = self._get_vm_for_node(node=node) + vm.power_on() + + return True + + @wrap_non_libcloud_exceptions + def ex_suspend_node(self, node): + vm = self._get_vm_for_node(node=node) + vm.suspend() + + return True + + @wrap_non_libcloud_exceptions + def ex_get_node_by_path(self, path): + """ + Retrieve Node object for a VM with a provided path. + + :type path: ``str`` + :rtype: :class:`Node` + """ + node = self._to_node(vm_path=path) + return node + + @wrap_non_libcloud_exceptions + def ex_get_server_type(self): + """ + Return VMware installation type. + + :rtype: ``str`` + """ + return self.connection.client.get_server_type() + + @wrap_non_libcloud_exceptions + def ex_get_api_version(self): + """ + Return API version of the vmware provider. + + :rtype: ``str`` + """ + return self.connection.client.get_api_version() + + def _to_nodes(self, vm_paths): + nodes = [] + for vm_path in vm_paths: + node = self._to_node(vm_path=vm_path) + nodes.append(node) + + return nodes + + def _to_node(self, vm_path): + vm = self.connection.client.get_vm_by_path(vm_path) + + properties = vm.get_properties() + status = vm.get_status() + + id = properties['path'] + name = properties['name'] + public_ips = [] + private_ips = [] + + state = self.NODE_STATE_MAP.get(status, NodeState.UNKNOWN) + ip_address = properties.get('ip_address', None) + net = properties.get('net', []) + + extra = { + 'path': properties['path'], + 'hostname': properties.get('hostname', None), + 'guest_id': properties['guest_id'], + 'devices': properties.get('devices', {}), + 'disks': properties.get('disks', []), + 'net': net + } + + # Add primary IP + if ip_address: + if is_public_subnet(ip_address): + public_ips.append(ip_address) + else: + private_ips.append(ip_address) + + # Add other IP addresses + for nic in net: + ip_addresses = nic['ip_addresses'] + for ip_address in ip_addresses: + try: + is_public = is_public_subnet(ip_address) + except Exception: + # TODO: Better support for IPv6 + is_public = False + + if is_public: + public_ips.append(ip_address) + else: + private_ips.append(ip_address) + + # Remove duplicate IPs + public_ips = list(set(public_ips)) + private_ips = list(set(private_ips)) + + node = Node(id=id, name=name, state=state, public_ips=public_ips, + private_ips=private_ips, driver=self, extra=extra) + return node + + def _get_vm_for_node(self, node): + vm_path = node.id + vm = self.connection.client.get_vm_by_path(vm_path) + + return vm + + def _ex_connection_class_kwargs(self): + kwargs = { + 'url': self.url + } + + return kwargs + + +class VSphere_5_5_NodeDriver(VSphereNodeDriver): + name = 'VMware vSphere v5.5' http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/libcloud/compute/providers.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/providers.py b/libcloud/compute/providers.py index 87b3f32..5c19f61 100644 --- a/libcloud/compute/providers.py +++ b/libcloud/compute/providers.py @@ -147,6 +147,8 @@ DRIVERS = { ('libcloud.compute.drivers.ec2', 'OutscaleSASNodeDriver'), Provider.OUTSCALE_INC: ('libcloud.compute.drivers.ec2', 'OutscaleINCNodeDriver'), + Provider.VSPHERE: + ('libcloud.compute.drivers.vsphere', 'VSphereNodeDriver'), # Deprecated Provider.CLOUDSIGMA_US: http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/libcloud/compute/types.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/types.py b/libcloud/compute/types.py index 602d8e8..e296172 100644 --- a/libcloud/compute/types.py +++ b/libcloud/compute/types.py @@ -121,6 +121,7 @@ class Provider(object): IKOULA = 'ikoula' OUTSCALE_SAS = 'outscale_sas' OUTSCALE_INC = 'outscale_inc' + VSPHERE = 'vsphere' # OpenStack based providers HPCLOUD = 'hpcloud' http://git-wip-us.apache.org/repos/asf/libcloud/blob/054f29a9/libcloud/utils/decorators.py ---------------------------------------------------------------------- diff --git a/libcloud/utils/decorators.py b/libcloud/utils/decorators.py new file mode 100644 index 0000000..3c39511 --- /dev/null +++ b/libcloud/utils/decorators.py @@ -0,0 +1,57 @@ +# 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. + +import sys +from functools import wraps + +from libcloud.common.types import LibcloudError + +__all__ = [ + 'wrap_non_libcloud_exceptions' +] + + +def wrap_non_libcloud_exceptions(func): + """ + Decorators function which catches non LibcloudError exceptions, wraps them + in LibcloudError class and re-throws the wrapped exception. + + Note: This function should only be used to wrap methods on the driver + classes. + """ + @wraps(func) + def decorated_function(*args, **kwargs): + try: + return func(*args, **kwargs) + except Exception: + e = sys.exc_info()[1] + + if isinstance(e, LibcloudError): + raise e + + if len(args) >= 1: + driver = args[0] + else: + driver = None + + fault = getattr(e, 'fault', None) + + if fault and getattr(fault, 'string', None): + message = fault.string + else: + message = e.message + + raise LibcloudError(value=message, driver=driver) + return decorated_function
