You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by se...@apache.org on 2015/02/25 21:32:48 UTC

libcloud git commit: Adds Site to Site VPN functionality for CloudStack.

Repository: libcloud
Updated Branches:
  refs/heads/trunk 968425c62 -> 62864f52e


Adds Site to Site VPN functionality for CloudStack.

Signed-off-by: Sebastien Goasguen <ru...@gmail.com>

This closes #465


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/62864f52
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/62864f52
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/62864f52

Branch: refs/heads/trunk
Commit: 62864f52ed661a45f781b4a81d865cb681be269f
Parents: 968425c
Author: Avi Nanhkoesingh <an...@schubergphilis.com>
Authored: Thu Feb 19 14:26:26 2015 +0100
Committer: Sebastien Goasguen <ru...@gmail.com>
Committed: Wed Feb 25 15:32:05 2015 -0500

----------------------------------------------------------------------
 CHANGES.rst                                     |   4 +
 libcloud/compute/drivers/cloudstack.py          | 708 +++++++++++++++++++
 .../cloudstack/createVpnConnection_default.json |   5 +
 .../createVpnCustomerGateway_default.json       |   5 +
 .../cloudstack/createVpnGateway_default.json    |   6 +
 .../cloudstack/deleteVpnConnection_default.json |   1 +
 .../deleteVpnCustomerGateway_default.json       |   5 +
 .../cloudstack/deleteVpnGateway_default.json    |   1 +
 .../cloudstack/listVpnConnections_default.json  |  27 +
 .../listVpnCustomerGateways_default.json        |  22 +
 .../cloudstack/listVpnGateways_default.json     |  15 +
 ...queryAsyncJobResult_createVpnConnection.json |  35 +
 ...AsyncJobResult_createVpnCustomerGateway.json |  30 +
 .../queryAsyncJobResult_createVpnGateway.json   |  23 +
 ...queryAsyncJobResult_deleteVpnConnection.json |  16 +
 ...AsyncJobResult_deleteVpnCustomerGateway.json |  16 +
 .../queryAsyncJobResult_deleteVpnGateway.json   |  16 +
 libcloud/test/compute/test_cloudstack.py        |  87 +++
 18 files changed, 1022 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index d5ff01e..7c410c2 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -38,6 +38,10 @@ Compute
   (LIBCLOUD-663, GITHUB-450)
   [Allard Hoeve]
 
+- Add Site to Site VPN functionality to CloudStack driver.
+  (GITHUB-465)
+  [Avi Nanhkoesingh]
+
 DNS
 ~~~
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/compute/drivers/cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/cloudstack.py b/libcloud/compute/drivers/cloudstack.py
index 5f8af35..ef3b4d3 100644
--- a/libcloud/compute/drivers/cloudstack.py
+++ b/libcloud/compute/drivers/cloudstack.py
@@ -312,6 +312,80 @@ RESOURCE_EXTRA_ATTRIBUTES_MAP = {
             'key_name': 'secondaryip',
             'transform_func': list
         }
+    },
+    'vpngateway': {
+        'for_display': {
+            'key_name': 'fordisplay',
+            'transform_func': str
+        },
+        'project': {
+            'key_name': 'project',
+            'transform_func': str
+        },
+        'project_id': {
+            'key_name': 'projectid',
+            'transform_func': str
+        },
+        'removed': {
+            'key_name': 'removed',
+            'transform_func': str
+        }
+    },
+    'vpncustomergateway': {
+        'account': {
+            'key_name': 'account',
+            'transform_func': str
+        },
+        'domain': {
+            'key_name': 'domain',
+            'transform_func': str
+        },
+        'domain_id': {
+            'key_name': 'domainid',
+            'transform_func': str
+        },
+        'dpd': {
+            'key_name': 'dpd',
+            'transform_func': bool
+        },
+        'esp_lifetime': {
+            'key_name': 'esplifetime',
+            'transform_func': int
+        },
+        'ike_lifetime': {
+            'key_name': 'ikelifetime',
+            'transform_func': int
+        },
+        'name': {
+            'key_name': 'name',
+            'transform_func': str
+        }
+    },
+    'vpnconnection': {
+        'account': {
+            'key_name': 'account',
+            'transform_func': str
+        },
+        'domain': {
+            'key_name': 'domain',
+            'transform_func': str
+        },
+        'domain_id': {
+            'key_name': 'domainid',
+            'transform_func': str
+        },
+        'for_display': {
+            'key_name': 'fordisplay',
+            'transform_func': str
+        },
+        'project': {
+            'key_name': 'project',
+            'transform_func': str
+        },
+        'project_id': {
+            'key_name': 'projectid',
+            'transform_func': str
+        }
     }
 }
 
@@ -847,6 +921,109 @@ class CloudStackVPCOffering(object):
                    self.driver.name))
 
 
+class CloudStackVpnGateway(object):
+    """
+    Class representing a CloudStack VPN Gateway.
+    """
+    def __init__(self, id, account, domain, domain_id,
+                 public_ip, vpc_id, driver, extra=None):
+        self.id = id
+        self.account = account
+        self.domain = domain
+        self.domain_id = domain_id
+        self.public_ip = public_ip
+        self.vpc_id = vpc_id
+        self.driver = driver
+        self.extra = extra or {}
+
+    @property
+    def vpc(self):
+        for vpc in self.ex_list_vpcs():
+            if self.vpc_id == vpc.id:
+                break
+        else:
+            raise LibcloudError('VPC with id=%s not found' % self.vpc_id)
+
+    def delete(self):
+        return self.driver.ex_delete_vpn_gateway(vpn_gateway=self)
+
+    def __repr__(self):
+        return (('<CloudStackVpnGateway: account=%s, domain=%s, '
+                 'domain_id=%s, id=%s, public_ip=%s, vpc_id=%s, '
+                 'driver=%s>')
+                % (self.account, self.domain, self.domain_id,
+                   self.id, self.public_ip, self.vpc_id, self.driver.name))
+
+
+class CloudStackVpnCustomerGateway(object):
+    """
+    Class representing a CloudStack VPN Customer Gateway.
+    """
+    def __init__(self, id, cidr_list, esp_policy, gateway,
+                 ike_policy, ipsec_psk, driver, extra=None):
+        self.id = id
+        self.cidr_list = cidr_list
+        self.esp_policy = esp_policy
+        self.gateway = gateway
+        self.ike_policy = ike_policy
+        self.ipsec_psk = ipsec_psk
+        self.driver = driver
+        self.extra = extra or {}
+
+    def delete(self):
+        return self.driver.ex_delete_vpn_customer_gateway(
+            vpn_customer_gateway=self)
+
+    def __repr__(self):
+        return (('<CloudStackVpnCustomerGateway: id=%s, cidr_list=%s, '
+                 'esp_policy=%s, gateway=%s, ike_policy=%s, ipsec_psk=%s, '
+                 'driver=%s>')
+                % (self.id, self.cidr_list, self.esp_policy, self.gateway,
+                   self.ike_policy, self.ipsec_psk, self.driver.name))
+
+
+class CloudStackVpnConnection(object):
+    """
+    Class representing a CloudStack VPN Connection.
+    """
+    def __init__(self, id, passive, vpn_customer_gateway_id,
+                 vpn_gateway_id, state, driver, extra=None):
+        self.id = id
+        self.passive = passive
+        self.vpn_customer_gateway_id = vpn_customer_gateway_id
+        self.vpn_gateway_id = vpn_gateway_id
+        self.state = state
+        self.driver = driver
+        self.extra = extra or {}
+
+    @property
+    def vpn_customer_gateway(self):
+        try:
+            return self.driver.ex_list_vpn_customer_gateways(
+                id=self.vpn_customer_gateway_id)[0]
+        except IndexError:
+            raise LibcloudError('VPN Customer Gateway with id=%s not found' %
+                                self.vpn_customer_gateway_id)
+
+    @property
+    def vpn_gateway(self):
+        try:
+            return self.driver.ex_list_vpn_gateways(id=self.vpn_gateway_id)[0]
+        except IndexError:
+            raise LibcloudError('VPN Gateway with id=%s not found' %
+                                self.vpn_gateway_id)
+
+    def delete(self):
+        return self.driver.ex_delete_vpn_connection(vpn_connection=self)
+
+    def __repr__(self):
+        return (('<CloudStackVpnConnection: id=%s, passive=%s, '
+                 'vpn_customer_gateway_id=%s, vpn_gateway_id=%s, state=%s, '
+                 'driver=%s>')
+                % (self.id, self.passive, self.vpn_customer_gateway_id,
+                   self.vpn_gateway_id, self.state, self.driver.name))
+
+
 class CloudStackRouter(object):
     """
     Class representing a CloudStack Router.
@@ -3226,6 +3403,537 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
 
         return True
 
+    def ex_list_vpn_gateways(self, account=None, domain_id=None,
+                             for_display=None, id=None, is_recursive=None,
+                             keyword=None, list_all=None, page=None,
+                             page_size=None, project_id=None, vpc_id=None):
+        """
+        List VPN Gateways.
+
+        :param   account: List resources by account (must be
+                          used with the domain_id parameter).
+        :type    account: ``str``
+
+        :param   domain_id: List only resources belonging
+                            to the domain specified.
+        :type    domain_id: ``str``
+
+        :param   for_display: List resources by display flag (only root
+                              admin is eligible to pass this parameter).
+        :type    for_display: ``bool``
+
+        :param   id: ID of the VPN Gateway.
+        :type    id: ``str``
+
+        :param   is_recursive: Defaults to False, but if true, lists all
+                               resources from the parent specified by the
+                               domain ID till leaves.
+        :type    is_recursive: ``bool``
+
+        :param   keyword: List by keyword.
+        :type    keyword: ``str``
+
+        :param   list_all: If set to False, list only resources belonging to
+                           the command's caller; if set to True - list
+                           resources that the caller is authorized to see.
+                           Default value is False.
+        :type    list_all: ``str``
+
+        :param   page: Start from page.
+        :type    page: ``int``
+
+        :param   page_size: Items per page.
+        :type    page_size: ``int``
+
+        :param   project_id: List objects by project.
+        :type    project_id: ``str``
+
+        :param   vpc_id: List objects by VPC.
+        :type    vpc_id: ``str``
+
+        :rtype: ``list`` of :class:`CloudStackVpnGateway`
+        """
+        args = {}
+
+        if account is not None:
+            args['account'] = account
+
+        if domain_id is not None:
+            args['domainid'] = domain_id
+
+        if for_display is not None:
+            args['fordisplay'] = for_display
+
+        if id is not None:
+            args['id'] = id
+
+        if is_recursive is not None:
+            args['isrecursive'] = is_recursive
+
+        if keyword is not None:
+            args['keyword'] = keyword
+
+        if list_all is not None:
+            args['listall'] = list_all
+
+        if page is not None:
+            args['page'] = page
+
+        if page_size is not None:
+            args['pagesize'] = page_size
+
+        if project_id is not None:
+            args['projectid'] = project_id
+
+        if vpc_id is not None:
+            args['vpcid'] = vpc_id
+
+        res = self._sync_request(command='listVpnGateways',
+                                 params=args,
+                                 method='GET')
+
+        items = res.get('vpngateway', [])
+        vpn_gateways = []
+        extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpngateway']
+
+        for item in items:
+            extra = self._get_extra_dict(item, extra_map)
+
+            vpn_gateways.append(CloudStackVpnGateway(
+                id=item['id'],
+                account=item['account'],
+                domain=item['domain'],
+                domain_id=item['domainid'],
+                public_ip=item['publicip'],
+                vpc_id=item['vpcid'],
+                driver=self,
+                extra=extra))
+
+        return vpn_gateways
+
+    def ex_create_vpn_gateway(self, vpc, for_display=None):
+        """
+        Creates a VPN Gateway.
+
+        :param vpc: VPC to create the Gateway for (required).
+        :type  vpc: :class: `CloudStackVPC`
+
+        :param for_display: Display the VPC to the end user or not.
+        :type  for_display: ``bool``
+
+        :rtype: :class: `CloudStackVpnGateway`
+        """
+        args = {
+            'vpcid': vpc.id,
+        }
+
+        if for_display is not None:
+            args['fordisplay'] = for_display
+
+        res = self._async_request(command='createVpnGateway',
+                                  params=args,
+                                  method='GET')
+
+        item = res['vpngateway']
+        extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpngateway']
+
+        return CloudStackVpnGateway(id=item['id'],
+                                    account=item['account'],
+                                    domain=item['domain'],
+                                    domain_id=item['domainid'],
+                                    public_ip=item['publicip'],
+                                    vpc_id=vpc.id,
+                                    driver=self,
+                                    extra=self._get_extra_dict(item,
+                                                               extra_map))
+
+    def ex_delete_vpn_gateway(self, vpn_gateway):
+        """
+        Deletes a VPN Gateway.
+
+        :param vpn_gateway: The VPN Gateway (required).
+        :type  vpn_gateway: :class:`CloudStackVpnGateway`
+
+        :rtype: ``bool``
+        """
+        res = self._async_request(command='deleteVpnGateway',
+                                  params={'id': vpn_gateway.id},
+                                  method='GET')
+
+        return res['success']
+
+    def ex_list_vpn_customer_gateways(self, account=None, domain_id=None,
+                                      id=None, is_recursive=None,
+                                      keyword=None, list_all=None,
+                                      page=None, page_size=None,
+                                      project_id=None):
+        """
+        List VPN Customer Gateways.
+
+        :param   account: List resources by account (must be
+                          used with the domain_id parameter).
+        :type    account: ``str``
+
+        :param   domain_id: List only resources belonging
+                            to the domain specified.
+        :type    domain_id: ``str``
+
+        :param   id: ID of the VPN Customer Gateway.
+        :type    id: ``str``
+
+        :param   is_recursive: Defaults to False, but if true, lists all
+                               resources from the parent specified by the
+                               domain_id till leaves.
+        :type    is_recursive: ``bool``
+
+        :param   keyword: List by keyword.
+        :type    keyword: ``str``
+
+        :param   list_all: If set to False, list only resources belonging to
+                           the command's caller; if set to True - list
+                           resources that the caller is authorized to see.
+                           Default value is False.
+        :type    list_all: ``str``
+
+        :param   page: Start from page.
+        :type    page: ``int``
+
+        :param   page_size: Items per page.
+        :type    page_size: ``int``
+
+        :param   project_id: List objects by project.
+        :type    project_id: ``str``
+
+        :rtype: ``list`` of :class:`CloudStackVpnCustomerGateway`
+        """
+        args = {}
+
+        if account is not None:
+            args['account'] = account
+
+        if domain_id is not None:
+            args['domainid'] = domain_id
+
+        if id is not None:
+            args['id'] = id
+
+        if is_recursive is not None:
+            args['isrecursive'] = is_recursive
+
+        if keyword is not None:
+            args['keyword'] = keyword
+
+        if list_all is not None:
+            args['listall'] = list_all
+
+        if page is not None:
+            args['page'] = page
+
+        if page_size is not None:
+            args['pagesize'] = page_size
+
+        if project_id is not None:
+            args['projectid'] = project_id
+
+        res = self._sync_request(command='listVpnCustomerGateways',
+                                 params=args,
+                                 method='GET')
+
+        items = res.get('vpncustomergateway', [])
+        vpn_customer_gateways = []
+        extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpncustomergateway']
+
+        for item in items:
+            extra = self._get_extra_dict(item, extra_map)
+
+            vpn_customer_gateways.append(CloudStackVpnCustomerGateway(
+                id=item['id'],
+                cidr_list=item['cidrlist'],
+                esp_policy=item['esppolicy'],
+                gateway=item['gateway'],
+                ike_policy=item['ikepolicy'],
+                ipsec_psk=item['ipsecpsk'],
+                driver=self,
+                extra=extra))
+
+        return vpn_customer_gateways
+
+    def ex_create_vpn_customer_gateway(self, cidr_list, esp_policy, gateway,
+                                       ike_policy, ipsec_psk, account=None,
+                                       domain_id=None, dpd=None,
+                                       esp_lifetime=None, ike_lifetime=None,
+                                       name=None):
+        """
+        Creates a VPN Customer Gateway.
+
+        :param cidr_list: Guest CIDR list of the Customer Gateway (required).
+        :type  cidr_list: ``str``
+
+        :param esp_policy: ESP policy of the Customer Gateway (required).
+        :type  esp_policy: ``str``
+
+        :param gateway: Public IP address of the Customer Gateway (required).
+        :type  gateway: ``str``
+
+        :param ike_policy: IKE policy of the Customer Gateway (required).
+        :type  ike_policy: ``str``
+
+        :param ipsec_psk: IPsec preshared-key of the Customer Gateway
+                          (required).
+        :type  ipsec_psk: ``str``
+
+        :param account: The associated account with the Customer Gateway
+                        (must be used with the domain_id param).
+        :type  account: ``str``
+
+        :param domain_id: The domain ID associated with the Customer Gateway.
+                          If used with the account parameter returns the
+                          gateway associated with the account for the
+                          specified domain.
+        :type  domain_id: ``str``
+
+        :param dpd: If DPD is enabled for the VPN connection.
+        :type  dpd: ``bool``
+
+        :param esp_lifetime: Lifetime of phase 2 VPN connection to the
+                             Customer Gateway, in seconds.
+        :type  esp_lifetime: ``int``
+
+        :param ike_lifetime: Lifetime of phase 1 VPN connection to the
+                             Customer Gateway, in seconds.
+        :type  ike_lifetime: ``int``
+
+        :param name: Name of the Customer Gateway.
+        :type  name: ``str``
+
+        :rtype: :class: `CloudStackVpnCustomerGateway`
+        """
+        args = {
+            'cidrlist': cidr_list,
+            'esppolicy': esp_policy,
+            'gateway': gateway,
+            'ikepolicy': ike_policy,
+            'ipsecpsk': ipsec_psk
+        }
+
+        if account is not None:
+            args['account'] = account
+
+        if domain_id is not None:
+            args['domainid'] = domain_id
+
+        if dpd is not None:
+            args['dpd'] = dpd
+
+        if esp_lifetime is not None:
+            args['esplifetime'] = esp_lifetime
+
+        if ike_lifetime is not None:
+            args['ikelifetime'] = ike_lifetime
+
+        if name is not None:
+            args['name'] = name
+
+        res = self._async_request(command='createVpnCustomerGateway',
+                                  params=args,
+                                  method='GET')
+
+        item = res['vpncustomergateway']
+        extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpncustomergateway']
+
+        return CloudStackVpnCustomerGateway(id=item['id'],
+                                            cidr_list=cidr_list,
+                                            esp_policy=esp_policy,
+                                            gateway=gateway,
+                                            ike_policy=ike_policy,
+                                            ipsec_psk=ipsec_psk,
+                                            driver=self,
+                                            extra=self._get_extra_dict(
+                                                item, extra_map))
+
+    def ex_delete_vpn_customer_gateway(self, vpn_customer_gateway):
+        """
+        Deletes a VPN Customer Gateway.
+
+        :param vpn_customer_gateway: The VPN Customer Gateway (required).
+        :type  vpn_customer_gateway: :class:`CloudStackVpnCustomerGateway`
+
+        :rtype: ``bool``
+        """
+        res = self._async_request(command='deleteVpnCustomerGateway',
+                                  params={'id': vpn_customer_gateway.id},
+                                  method='GET')
+
+        return res['success']
+
+    def ex_list_vpn_connections(self, account=None, domain_id=None,
+                                for_display=None, id=None, is_recursive=None,
+                                keyword=None, list_all=None, page=None,
+                                page_size=None, project_id=None, vpc_id=None):
+        """
+        List VPN Connections.
+
+        :param   account: List resources by account (must be
+                          used with the domain_id parameter).
+        :type    account: ``str``
+
+        :param   domain_id: List only resources belonging
+                            to the domain specified.
+        :type    domain_id: ``str``
+
+        :param   for_display: List resources by display flag (only root
+                              admin is eligible to pass this parameter).
+        :type    for_display: ``bool``
+
+        :param   id: ID of the VPN Connection.
+        :type    id: ``str``
+
+        :param   is_recursive: Defaults to False, but if true, lists all
+                               resources from the parent specified by the
+                               domain_id till leaves.
+        :type    is_recursive: ``bool``
+
+        :param   keyword: List by keyword.
+        :type    keyword: ``str``
+
+        :param   list_all: If set to False, list only resources belonging to
+                           the command's caller; if set to True - list
+                           resources that the caller is authorized to see.
+                           Default value is False.
+        :type    list_all: ``str``
+
+        :param   page: Start from page.
+        :type    page: ``int``
+
+        :param   page_size: Items per page.
+        :type    page_size: ``int``
+
+        :param   project_id: List objects by project.
+        :type    project_id: ``str``
+
+        :param   vpc_id: List objects by VPC.
+        :type    vpc_id: ``str``
+
+        :rtype: ``list`` of :class:`CloudStackVpnConnection`
+        """
+        args = {}
+
+        if account is not None:
+            args['account'] = account
+
+        if domain_id is not None:
+            args['domainid'] = domain_id
+
+        if for_display is not None:
+            args['fordisplay'] = for_display
+
+        if id is not None:
+            args['id'] = id
+
+        if is_recursive is not None:
+            args['isrecursive'] = is_recursive
+
+        if keyword is not None:
+            args['keyword'] = keyword
+
+        if list_all is not None:
+            args['listall'] = list_all
+
+        if page is not None:
+            args['page'] = page
+
+        if page_size is not None:
+            args['pagesize'] = page_size
+
+        if project_id is not None:
+            args['projectid'] = project_id
+
+        if vpc_id is not None:
+            args['vpcid'] = vpc_id
+
+        res = self._sync_request(command='listVpnConnections',
+                                 params=args,
+                                 method='GET')
+
+        items = res.get('vpnconnection', [])
+        vpn_connections = []
+        extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpnconnection']
+
+        for item in items:
+            extra = self._get_extra_dict(item, extra_map)
+
+            vpn_connections.append(CloudStackVpnConnection(
+                id=item['id'],
+                passive=item['passive'],
+                vpn_customer_gateway_id=item['s2scustomergatewayid'],
+                vpn_gateway_id=item['s2svpngatewayid'],
+                state=item['state'],
+                driver=self,
+                extra=extra))
+
+        return vpn_connections
+
+    def ex_create_vpn_connection(self, vpn_customer_gateway, vpn_gateway,
+                                 for_display=None, passive=None):
+        """
+        Creates a VPN Connection.
+
+        :param   vpn_customer_gateway: The VPN Customer Gateway (required).
+        :type    vpn_customer_gateway: :class:`CloudStackVpnCustomerGateway`
+
+        :param   vpn_gateway: The VPN Gateway (required).
+        :type    vpn_gateway: :class:`CloudStackVpnGateway`
+
+        :param   for_display: Display the Connection to the end user or not.
+        :type    for_display: ``str``
+
+        :param   passive: If True, sets the connection to be passive.
+        :type    passive: ``bool``
+
+        :rtype: :class: `CloudStackVpnConnection`
+        """
+        args = {
+            's2scustomergatewayid': vpn_customer_gateway.id,
+            's2svpngatewayid': vpn_gateway.id,
+        }
+
+        if for_display is not None:
+            args['fordisplay'] = for_display
+
+        if passive is not None:
+            args['passive'] = passive
+
+        res = self._async_request(command='createVpnConnection',
+                                  params=args,
+                                  method='GET')
+
+        item = res['vpnconnection']
+        extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpnconnection']
+
+        return CloudStackVpnConnection(
+            id=item['id'],
+            passive=item['passive'],
+            vpn_customer_gateway_id=vpn_customer_gateway.id,
+            vpn_gateway_id=vpn_gateway.id,
+            state=item['state'],
+            driver=self,
+            extra=self._get_extra_dict(item, extra_map))
+
+    def ex_delete_vpn_connection(self, vpn_connection):
+        """
+        Deletes a VPN Connection.
+
+        :param vpn_connection: The VPN Connection (required).
+        :type  vpn_connection: :class:`CloudStackVpnConnection`
+
+        :rtype: ``bool``
+        """
+        res = self._async_request(command='deleteVpnConnection',
+                                  params={'id': vpn_connection.id},
+                                  method='GET')
+
+        return res['success']
+
     def _to_snapshot(self, data):
         """
         Create snapshot object from data

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/createVpnConnection_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/createVpnConnection_default.json b/libcloud/test/compute/fixtures/cloudstack/createVpnConnection_default.json
new file mode 100644
index 0000000..500528e
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/createVpnConnection_default.json
@@ -0,0 +1,5 @@
+{
+   "createvpnconnectionresponse" : {
+      "jobid" : "createVpnConnection"
+   }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/createVpnCustomerGateway_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/createVpnCustomerGateway_default.json b/libcloud/test/compute/fixtures/cloudstack/createVpnCustomerGateway_default.json
new file mode 100644
index 0000000..5129ac9
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/createVpnCustomerGateway_default.json
@@ -0,0 +1,5 @@
+{
+   "createvpncustomergatewayresponse" : {
+      "jobid" : "createVpnCustomerGateway"
+   }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/createVpnGateway_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/createVpnGateway_default.json b/libcloud/test/compute/fixtures/cloudstack/createVpnGateway_default.json
new file mode 100644
index 0000000..81d220b
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/createVpnGateway_default.json
@@ -0,0 +1,6 @@
+{
+    "createvpngatewayresponse": {
+        "id": "5ef6794e-cec8-4018-9fef-c4dacbadee14",
+        "jobid": "createVpnGateway"
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/deleteVpnConnection_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/deleteVpnConnection_default.json b/libcloud/test/compute/fixtures/cloudstack/deleteVpnConnection_default.json
new file mode 100644
index 0000000..e38a797
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/deleteVpnConnection_default.json
@@ -0,0 +1 @@
+{ "deletevpnconnectionresponse" : {"jobid":"deleteVpnConnection"} }

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/deleteVpnCustomerGateway_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/deleteVpnCustomerGateway_default.json b/libcloud/test/compute/fixtures/cloudstack/deleteVpnCustomerGateway_default.json
new file mode 100644
index 0000000..5768715
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/deleteVpnCustomerGateway_default.json
@@ -0,0 +1,5 @@
+{
+   "deletevpncustomergatewayresponse" : {
+      "jobid" : "deleteVpnCustomerGateway"
+   }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/deleteVpnGateway_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/deleteVpnGateway_default.json b/libcloud/test/compute/fixtures/cloudstack/deleteVpnGateway_default.json
new file mode 100644
index 0000000..5f7ed1a
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/deleteVpnGateway_default.json
@@ -0,0 +1 @@
+{ "deletevpngatewayresponse" : {"jobid":"deleteVpnGateway"} }

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/listVpnConnections_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/listVpnConnections_default.json b/libcloud/test/compute/fixtures/cloudstack/listVpnConnections_default.json
new file mode 100644
index 0000000..1d099d9
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/listVpnConnections_default.json
@@ -0,0 +1,27 @@
+{
+    "listvpnconnectionsresponse": {
+        "count": 1,
+        "vpnconnection": [
+            {
+                "account": "some_admin",
+                "cidrlist": "10.2.2.0/24",
+                "created": "2015-02-20T13:32:58+0100",
+                "domain": "some_domain",
+                "domainid": "9b397dea-25ef-4c5d-b47d-627eaebe8ed8",
+                "dpd": false,
+                "esplifetime": 3600,
+                "esppolicy": "3des-md5",
+                "gateway": "10.2.2.1",
+                "id": "8f482d9a-6cee-453b-9e78-b0e1338ffce9",
+                "ikelifetime": 86400,
+                "ikepolicy": "3des-md5",
+                "ipsecpsk": "xxx",
+                "passive": false,
+                "publicip": "1.2.3.4",
+                "s2scustomergatewayid": "ea67eaae-1c2a-4e65-b910-441e77f69bea",
+                "s2svpngatewayid": "cffa0cab-d1da-42a7-92f6-41379267a29f",
+                "state": "Connected"
+            }
+        ]
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/listVpnCustomerGateways_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/listVpnCustomerGateways_default.json b/libcloud/test/compute/fixtures/cloudstack/listVpnCustomerGateways_default.json
new file mode 100644
index 0000000..58aaeca
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/listVpnCustomerGateways_default.json
@@ -0,0 +1,22 @@
+{
+    "listvpncustomergatewaysresponse": {
+        "count": 1,
+        "vpncustomergateway": [
+            {
+                "account": "some_account",
+                "cidrlist": "10.2.2.0/24",
+                "domain": "some_domain",
+                "domainid": "9b397dea-25ef-4c5d-b47d-627eaebe8ed8",
+                "dpd": false,
+                "esplifetime": 3600,
+                "esppolicy": "3des-md5",
+                "gateway": "10.2.2.1",
+                "id": "ea67eaae-1c2a-4e65-b910-441e77f69bea",
+                "ikelifetime": 86400,
+                "ikepolicy": "3des-md5",
+                "ipsecpsk": "some_psk",
+                "name": "some_name"
+            }
+        ]
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/listVpnGateways_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/listVpnGateways_default.json b/libcloud/test/compute/fixtures/cloudstack/listVpnGateways_default.json
new file mode 100644
index 0000000..33d8116
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/listVpnGateways_default.json
@@ -0,0 +1,15 @@
+{
+    "listvpngatewaysresponse": {
+        "count": 1,
+        "vpngateway": [
+            {
+                "account": "some_account",
+                "domain": "some_domain",
+                "domainid": "9b397dea-25ef-4c5d-b47d-627eaebe8ed8",
+                "id": "cffa0cab-d1da-42a7-92f6-41379267a29f",
+                "publicip": "1.2.3.4",
+                "vpcid": "4d25e181-8850-4d52-8ecb-a6f35bbbabde"
+            }
+        ]
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnConnection.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnConnection.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnConnection.json
new file mode 100644
index 0000000..f156b18
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnConnection.json
@@ -0,0 +1,35 @@
+{
+   "queryasyncjobresultresponse" : {
+      "cmd" : "org.apache.cloudstack.api.command.user.vpn.CreateVpnConnectionCmd",
+      "jobid" : "createVpnConnection",
+      "userid" : "user_id",
+      "accountid" : "account_id",
+      "jobprocstatus" : 0,
+      "created" : "2015-02-23T08:36:09+0100",
+      "jobstatus" : 1,
+      "jobresult" : {
+         "vpnconnection" : {
+            "esplifetime" : 3600,
+            "cidrlist" : "10.0.0.0/24",
+            "gateway" : "10.0.0.1",
+            "ikelifetime" : 86400,
+            "state" : "Connected",
+            "ikepolicy" : "3des-md5",
+            "domain" : "domain",
+            "dpd" : false,
+            "id" : "f45c3af8-f909-4f16-9d40-ed4409c575f8",
+            "s2svpngatewayid" : "515aefbc-448b-484b-8d6a-ff3b67637bf1",
+            "s2scustomergatewayid" : "201fc1d1-05e1-4e9c-a025-d72e954dd856",
+            "account" : "account",
+            "domainid" : "domain_id",
+            "esppolicy" : "3des-md5",
+            "created" : "2015-02-23T08:36:09+0100",
+            "passive" : false,
+            "ipsecpsk" : "ipsecpsk",
+            "publicip" : "1.2.3.4"
+         }
+      },
+      "jobresultcode" : 0,
+      "jobresulttype" : "object"
+   }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnCustomerGateway.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnCustomerGateway.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnCustomerGateway.json
new file mode 100644
index 0000000..1746885
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnCustomerGateway.json
@@ -0,0 +1,30 @@
+{
+   "queryasyncjobresultresponse" : {
+      "cmd" : "org.apache.cloudstack.api.command.user.vpn.CreateVpnCustomerGatewayCmd",
+      "jobid" : "createVpnCustomerGateway",
+      "userid" : "user_id",
+      "accountid" : "account_id",
+      "jobprocstatus" : 0,
+      "created" : "2015-02-23T08:25:01+0100",
+      "jobstatus" : 1,
+      "jobresult" : {
+         "vpncustomergateway" : {
+            "esplifetime" : 3600,
+            "cidrlist" : "10.0.0.0/24",
+            "account" : "account",
+            "gateway" : "10.0.0.1",
+            "ikelifetime" : 86400,
+            "name" : "VPN-10.0.0.1",
+            "domainid" : "domain_id",
+            "esppolicy" : "3des-md5",
+            "ikepolicy" : "3des-md5",
+            "domain" : "domain",
+            "dpd" : false,
+            "id" : "cef3c766-116a-4e83-9844-7d08ab7d3fd4",
+            "ipsecpsk" : "ipsecpsk"
+         }
+      },
+      "jobresultcode" : 0,
+      "jobresulttype" : "object"
+   }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnGateway.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnGateway.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnGateway.json
new file mode 100644
index 0000000..b695cbd
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnGateway.json
@@ -0,0 +1,23 @@
+{
+    "queryasyncjobresultresponse" : {
+        "cmd" : "org.apache.cloudstack.api.command.user.vpn.CreateVpnGatewayCmd",
+        "jobid" : "b26272a4-f5e4-4ebe-a7d3-eaaf3ec8280c",
+        "userid" : "2f517f5b-cac9-48b5-aafc-e9d7ca879784",
+        "accountid" : "4009e75e-5311-43f2-bc92-b92676455eed",
+        "jobprocstatus" : 0,
+        "created" : "2015-02-20T15:53:54+0100",
+        "jobstatus" : 1,
+        "jobresult" : {
+            "vpngateway" : {
+                "domain" : "some_domain",
+                "vpcid" : "4d25e181-8850-4d52-8ecb-a6f35bbbabde",
+                "account" : "some_account",
+                "domainid" : "9b397dea-25ef-4c5d-b47d-627eaebe8ed8",
+                "id" : "5ef6794e-cec8-4018-9fef-c4dacbadee14",
+                "publicip" : "2.3.4.5"
+            }
+        },
+        "jobresultcode" : 0,
+        "jobresulttype" : "object"
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnConnection.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnConnection.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnConnection.json
new file mode 100644
index 0000000..9e4baa9
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnConnection.json
@@ -0,0 +1,16 @@
+{
+   "queryasyncjobresultresponse" : {
+      "cmd" : "org.apache.cloudstack.api.command.user.vpn.DeleteVpnConnectionCmd",
+      "jobid" : "deleteVpnConnection",
+      "userid" : "user_id",
+      "accountid" : "account_id",
+      "jobprocstatus" : 0,
+      "created" : "2015-02-23T08:17:41+0100",
+      "jobstatus" : 1,
+      "jobresult" : {
+         "success" : true
+      },
+      "jobresultcode" : 0,
+      "jobresulttype" : "object"
+   }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnCustomerGateway.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnCustomerGateway.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnCustomerGateway.json
new file mode 100644
index 0000000..e8f5628
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnCustomerGateway.json
@@ -0,0 +1,16 @@
+{
+   "queryasyncjobresultresponse" : {
+      "cmd" : "org.apache.cloudstack.api.command.user.vpn.DeleteVpnCustomerGatewayCmd",
+      "jobid" : "deleteVpnCustomerGateway",
+      "userid" : "user_id",
+      "accountid" : "account_id",
+      "jobprocstatus" : 0,
+      "created" : "2015-02-23T08:20:47+0100",
+      "jobstatus" : 1,
+      "jobresult" : {
+         "success" : true
+      },
+      "jobresultcode" : 0,
+      "jobresulttype" : "object"
+   }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnGateway.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnGateway.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnGateway.json
new file mode 100644
index 0000000..93feb0a
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnGateway.json
@@ -0,0 +1,16 @@
+{
+    "queryasyncjobresultresponse": {
+        "accountid": "4009e75e-5311-43f2-bc92-b92676455eed",
+        "cmd": "org.apache.cloudstack.api.command.user.vpn.DeleteVpnGatewayCmd",
+        "created": "2015-02-20T16:32:40+0100",
+        "jobid": "0648122e-fb16-495b-96d0-86e16b742557",
+        "jobprocstatus": 0,
+        "jobresult": {
+            "success": true
+        },
+        "jobresultcode": 0,
+        "jobresulttype": "object",
+        "jobstatus": 1,
+        "userid": "2f517f5b-cac9-48b5-aafc-e9d7ca879784"
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/62864f52/libcloud/test/compute/test_cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudstack.py b/libcloud/test/compute/test_cloudstack.py
index 413bdcd..5726a75 100644
--- a/libcloud/test/compute/test_cloudstack.py
+++ b/libcloud/test/compute/test_cloudstack.py
@@ -992,6 +992,93 @@ class CloudStackCommonTestCase(TestCaseMixin):
         self.assertEqual(os_types[0]['oscategoryid'], 7)
         self.assertEqual(os_types[0]['description'], "Asianux 3(32-bit)")
 
+    def test_ex_list_vpn_gateways(self):
+        vpn_gateways = self.driver.ex_list_vpn_gateways()
+
+        self.assertEqual(len(vpn_gateways), 1)
+
+        self.assertEqual(vpn_gateways[0].id, 'cffa0cab-d1da-42a7-92f6-41379267a29f')
+        self.assertEqual(vpn_gateways[0].account, 'some_account')
+        self.assertEqual(vpn_gateways[0].domain, 'some_domain')
+        self.assertEqual(vpn_gateways[0].domain_id, '9b397dea-25ef-4c5d-b47d-627eaebe8ed8')
+        self.assertEqual(vpn_gateways[0].public_ip, '1.2.3.4')
+        self.assertEqual(vpn_gateways[0].vpc_id, '4d25e181-8850-4d52-8ecb-a6f35bbbabde')
+
+    def test_ex_create_vpn_gateway(self):
+        vpc = self.driver.ex_list_vpcs()[0]
+
+        vpn_gateway = self.driver.ex_create_vpn_gateway(vpc)
+
+        self.assertEqual(vpn_gateway.id, '5ef6794e-cec8-4018-9fef-c4dacbadee14')
+        self.assertEqual(vpn_gateway.account, 'some_account')
+        self.assertEqual(vpn_gateway.domain, 'some_domain')
+        self.assertEqual(vpn_gateway.domain_id, '9b397dea-25ef-4c5d-b47d-627eaebe8ed8')
+        self.assertEqual(vpn_gateway.public_ip, '2.3.4.5')
+        self.assertEqual(vpn_gateway.vpc_id, vpc.id)
+
+    def test_ex_delete_vpn_gateway(self):
+        vpn_gateway = self.driver.ex_list_vpn_gateways()[0]
+        self.assertTrue(vpn_gateway.delete())
+
+    def test_ex_list_vpn_customer_gateways(self):
+        vpn_customer_gateways = self.driver.ex_list_vpn_customer_gateways()
+
+        self.assertEqual(len(vpn_customer_gateways), 1)
+
+        self.assertEqual(vpn_customer_gateways[0].id, 'ea67eaae-1c2a-4e65-b910-441e77f69bea')
+        self.assertEqual(vpn_customer_gateways[0].cidr_list, '10.2.2.0/24')
+        self.assertEqual(vpn_customer_gateways[0].esp_policy, '3des-md5')
+        self.assertEqual(vpn_customer_gateways[0].gateway, '10.2.2.1')
+        self.assertEqual(vpn_customer_gateways[0].ike_policy, '3des-md5')
+        self.assertEqual(vpn_customer_gateways[0].ipsec_psk, 'some_psk')
+
+    def test_ex_create_vpn_customer_gateway(self):
+        vpn_customer_gateway = self.driver.ex_create_vpn_customer_gateway(
+            cidr_list='10.0.0.0/24',
+            esp_policy='3des-md5',
+            gateway='10.0.0.1',
+            ike_policy='3des-md5',
+            ipsec_psk='ipsecpsk')
+
+        self.assertEqual(vpn_customer_gateway.id, 'cef3c766-116a-4e83-9844-7d08ab7d3fd4')
+        self.assertEqual(vpn_customer_gateway.esp_policy, '3des-md5')
+        self.assertEqual(vpn_customer_gateway.gateway, '10.0.0.1')
+        self.assertEqual(vpn_customer_gateway.ike_policy, '3des-md5')
+        self.assertEqual(vpn_customer_gateway.ipsec_psk, 'ipsecpsk')
+
+    def test_ex_ex_delete_vpn_customer_gateway(self):
+        vpn_customer_gateway = self.driver.ex_list_vpn_customer_gateways()[0]
+        self.assertTrue(vpn_customer_gateway.delete())
+
+    def test_ex_list_vpn_connections(self):
+        vpn_connections = self.driver.ex_list_vpn_connections()
+
+        self.assertEqual(len(vpn_connections), 1)
+
+        self.assertEqual(vpn_connections[0].id, '8f482d9a-6cee-453b-9e78-b0e1338ffce9')
+        self.assertEqual(vpn_connections[0].passive, False)
+        self.assertEqual(vpn_connections[0].vpn_customer_gateway_id, 'ea67eaae-1c2a-4e65-b910-441e77f69bea')
+        self.assertEqual(vpn_connections[0].vpn_gateway_id, 'cffa0cab-d1da-42a7-92f6-41379267a29f')
+        self.assertEqual(vpn_connections[0].state, 'Connected')
+
+    def test_ex_create_vpn_connection(self):
+        vpn_customer_gateway = self.driver.ex_list_vpn_customer_gateways()[0]
+        vpn_gateway = self.driver.ex_list_vpn_gateways()[0]
+
+        vpn_connection = self.driver.ex_create_vpn_connection(
+            vpn_customer_gateway,
+            vpn_gateway)
+
+        self.assertEqual(vpn_connection.id, 'f45c3af8-f909-4f16-9d40-ed4409c575f8')
+        self.assertEqual(vpn_connection.passive, False)
+        self.assertEqual(vpn_connection.vpn_customer_gateway_id, 'ea67eaae-1c2a-4e65-b910-441e77f69bea')
+        self.assertEqual(vpn_connection.vpn_gateway_id, 'cffa0cab-d1da-42a7-92f6-41379267a29f')
+        self.assertEqual(vpn_connection.state, 'Connected')
+
+    def test_ex_delete_vpn_connection(self):
+        vpn_connection = self.driver.ex_list_vpn_connections()[0]
+        self.assertTrue(vpn_connection.delete())
+
 
 class CloudStackTestCase(CloudStackCommonTestCase, unittest.TestCase):
     def test_driver_instantiation(self):