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

Reply via email to