CLOUDSTACK-730: Site-to-site VPN between VPC VR to VR

Now VPN connection can be created as "passive", which would enable the ability
of remote peer initiate the connection. So it's possible for VPC VR to
establish the connection to another VPC VR of CloudStack.

Test case also included.

The test case would create 2 vpcs and using VPN to connect them.
This commit is contained in:
Sheng Yang 2013-10-30 16:08:33 -07:00
parent 1460196496
commit 3205cd42b5
15 changed files with 304 additions and 39 deletions

View File

@ -35,4 +35,5 @@ public interface Site2SiteVpnConnection extends ControlledEntity, InternalIdenti
public State getState(); public State getState();
public Date getCreated(); public Date getCreated();
public Date getRemoved(); public Date getRemoved();
public boolean isPassive();
} }

View File

@ -524,6 +524,7 @@ public class ApiConstants {
public static final String RESOURCE_DETAILS = "resourcedetails"; public static final String RESOURCE_DETAILS = "resourcedetails";
public static final String EXPUNGE = "expunge"; public static final String EXPUNGE = "expunge";
public static final String FOR_DISPLAY = "fordisplay"; public static final String FOR_DISPLAY = "fordisplay";
public static final String PASSIVE = "passive";
public enum HostDetails { public enum HostDetails {
all, capacity, events, stats, min; all, capacity, events, stats, min;

View File

@ -53,6 +53,9 @@ public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd {
required=true, description="id of the customer gateway") required=true, description="id of the customer gateway")
private Long customerGatewayId; private Long customerGatewayId;
@Parameter(name=ApiConstants.PASSIVE, type=CommandType.BOOLEAN, required=false, description="connection is passive or not")
private Boolean passive;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////////// Accessors /////////////////////// /////////////////// Accessors ///////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -66,6 +69,13 @@ public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd {
return customerGatewayId; return customerGatewayId;
} }
public boolean isPassive() {
if (passive == null) {
return false;
}
return passive;
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////

View File

@ -68,6 +68,9 @@ public class Site2SiteVpnConnectionResponse extends BaseResponse implements Cont
@SerializedName(ApiConstants.STATE) @Param(description="State of vpn connection") @SerializedName(ApiConstants.STATE) @Param(description="State of vpn connection")
private String state; private String state;
@SerializedName(ApiConstants.PASSIVE) @Param(description="State of vpn connection")
private boolean passive;
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the owner") @SerializedName(ApiConstants.ACCOUNT) @Param(description="the owner")
private String accountName; private String accountName;
@ -141,6 +144,10 @@ public class Site2SiteVpnConnectionResponse extends BaseResponse implements Cont
this.state = state; this.state = state;
} }
public void setPassive(boolean passive) {
this.passive = passive;
}
public void setCreated(Date created) { public void setCreated(Date created) {
this.created = created; this.created = created;
} }

View File

@ -30,6 +30,7 @@ public class Site2SiteVpnCfgCommand extends NetworkElementCommand {
private long ikeLifetime; private long ikeLifetime;
private long espLifetime; private long espLifetime;
private boolean dpd; private boolean dpd;
private boolean passive;
@Override @Override
public boolean executeInSequence() { public boolean executeInSequence() {
@ -41,7 +42,7 @@ public class Site2SiteVpnCfgCommand extends NetworkElementCommand {
} }
public Site2SiteVpnCfgCommand (boolean create, String localPublicIp, String localPublicGateway, String localGuestCidr, String peerGatewayIp, public Site2SiteVpnCfgCommand (boolean create, String localPublicIp, String localPublicGateway, String localGuestCidr, String peerGatewayIp,
String peerGuestCidrList, String ikePolicy, String espPolicy, String ipsecPsk, Long ikeLifetime, Long espLifetime, Boolean dpd) { String peerGuestCidrList, String ikePolicy, String espPolicy, String ipsecPsk, Long ikeLifetime, Long espLifetime, Boolean dpd, boolean passive) {
this.create = create; this.create = create;
this.setLocalPublicIp(localPublicIp); this.setLocalPublicIp(localPublicIp);
this.setLocalPublicGateway(localPublicGateway); this.setLocalPublicGateway(localPublicGateway);
@ -54,6 +55,7 @@ public class Site2SiteVpnCfgCommand extends NetworkElementCommand {
this.ikeLifetime = ikeLifetime; this.ikeLifetime = ikeLifetime;
this.espLifetime = espLifetime; this.espLifetime = espLifetime;
this.dpd = dpd; this.dpd = dpd;
this.passive = passive;
} }
public boolean isCreate() { public boolean isCreate() {
@ -151,4 +153,12 @@ public class Site2SiteVpnCfgCommand extends NetworkElementCommand {
public void setPeerGuestCidrList(String peerGuestCidrList) { public void setPeerGuestCidrList(String peerGuestCidrList) {
this.peerGuestCidrList = peerGuestCidrList; this.peerGuestCidrList = peerGuestCidrList;
} }
public boolean isPassive() {
return passive;
}
public void setPassive(boolean passive) {
this.passive = passive;
}
} }

View File

@ -761,6 +761,9 @@ public class VirtualRoutingResource implements Manager {
} else { } else {
args += "0"; args += "0";
} }
if (cmd.isPassive()) {
args += " -p ";
}
} else { } else {
args = "-D"; args = "-D";
args += " -r "; args += " -r ";

View File

@ -66,15 +66,19 @@ public class Site2SiteVpnConnectionVO implements Site2SiteVpnConnection, Interna
@Column(name=GenericDao.REMOVED_COLUMN) @Column(name=GenericDao.REMOVED_COLUMN)
private Date removed; private Date removed;
@Column(name="passive")
private boolean passive;
public Site2SiteVpnConnectionVO() { } public Site2SiteVpnConnectionVO() { }
public Site2SiteVpnConnectionVO(long accountId, long domainId, long vpnGatewayId, long customerGatewayId) { public Site2SiteVpnConnectionVO(long accountId, long domainId, long vpnGatewayId, long customerGatewayId, boolean passive) {
this.uuid = UUID.randomUUID().toString(); this.uuid = UUID.randomUUID().toString();
this.setVpnGatewayId(vpnGatewayId); this.setVpnGatewayId(vpnGatewayId);
this.setCustomerGatewayId(customerGatewayId); this.setCustomerGatewayId(customerGatewayId);
this.setState(State.Pending); this.setState(State.Pending);
this.accountId = accountId; this.accountId = accountId;
this.domainId = domainId; this.domainId = domainId;
this.passive = passive;
} }
@Override @Override
@ -140,4 +144,12 @@ public class Site2SiteVpnConnectionVO implements Site2SiteVpnConnection, Interna
public long getAccountId() { public long getAccountId() {
return accountId; return accountId;
} }
public boolean isPassive() {
return passive;
}
public void setPassive(boolean passive) {
this.passive = passive;
}
} }

View File

@ -1559,6 +1559,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
} else { } else {
args += "0"; args += "0";
} }
if (cmd.isPassive()) {
args += " -p ";
}
} else { } else {
args += " -D"; args += " -D";
args += " -r "; args += " -r ";

View File

@ -8519,6 +8519,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} else { } else {
args += "0"; args += "0";
} }
if (cmd.isPassive()) {
args += " -p ";
}
} else { } else {
args += " -D"; args += " -D";
args += " -r "; args += " -r ";

View File

@ -3195,6 +3195,7 @@ public class ApiResponseHelper implements ResponseGenerator {
public Site2SiteVpnConnectionResponse createSite2SiteVpnConnectionResponse(Site2SiteVpnConnection result) { public Site2SiteVpnConnectionResponse createSite2SiteVpnConnectionResponse(Site2SiteVpnConnection result) {
Site2SiteVpnConnectionResponse response = new Site2SiteVpnConnectionResponse(); Site2SiteVpnConnectionResponse response = new Site2SiteVpnConnectionResponse();
response.setId(result.getUuid()); response.setId(result.getUuid());
response.setPassive(result.isPassive());
Long vpnGatewayId = result.getVpnGatewayId(); Long vpnGatewayId = result.getVpnGatewayId();
if (vpnGatewayId != null) { if (vpnGatewayId != null) {

View File

@ -1122,7 +1122,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian
Boolean dpd = gw.getDpd(); Boolean dpd = gw.getDpd();
Site2SiteVpnCfgCommand cmd = new Site2SiteVpnCfgCommand(isCreate, localPublicIp, localPublicGateway, localGuestCidr, Site2SiteVpnCfgCommand cmd = new Site2SiteVpnCfgCommand(isCreate, localPublicIp, localPublicGateway, localGuestCidr,
peerGatewayIp, peerGuestCidrList, ikePolicy, espPolicy, ipsecPsk, ikeLifetime, espLifetime, dpd); peerGatewayIp, peerGuestCidrList, ikePolicy, espPolicy, ipsecPsk, ikeLifetime, espLifetime, dpd, conn.isPassive());
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId()));
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId()));
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());

View File

@ -290,7 +290,7 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
} }
} }
Site2SiteVpnConnectionVO conn = new Site2SiteVpnConnectionVO(owner.getAccountId(), owner.getDomainId(), vpnGatewayId, customerGatewayId); Site2SiteVpnConnectionVO conn = new Site2SiteVpnConnectionVO(owner.getAccountId(), owner.getDomainId(), vpnGatewayId, customerGatewayId, cmd.isPassive());
conn.setState(State.Pending); conn.setState(State.Pending);
_vpnConnectionDao.persist(conn); _vpnConnectionDao.persist(conn);
return conn; return conn;
@ -317,7 +317,11 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
} }
if (result) { if (result) {
conn.setState(State.Connected); if (conn.isPassive()) {
conn.setState(State.Disconnected);
} else {
conn.setState(State.Connected);
}
_vpnConnectionDao.persist(conn); _vpnConnectionDao.persist(conn);
return conn; return conn;
} }

View File

@ -119,6 +119,8 @@ UPDATE `cloud`.`vm_template` SET `removed`=NULL;
ALTER TABLE `cloud`.`remote_access_vpn` MODIFY COLUMN `network_id` bigint unsigned; ALTER TABLE `cloud`.`remote_access_vpn` MODIFY COLUMN `network_id` bigint unsigned;
ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `vpc_id` bigint unsigned default NULL; ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `vpc_id` bigint unsigned default NULL;
ALTER TABLE `cloud`.`s2s_vpn_connection` ADD COLUMN `passive` int(1) unsigned NOT NULL DEFAULT 0;
DROP VIEW IF EXISTS `cloud`.`disk_offering_view`; DROP VIEW IF EXISTS `cloud`.`disk_offering_view`;
CREATE VIEW `cloud`.`disk_offering_view` AS CREATE VIEW `cloud`.`disk_offering_view` AS
select select

View File

@ -30,7 +30,7 @@ vpnoutmark="0x525"
vpninmark="0x524" vpninmark="0x524"
usage() { usage() {
printf "Usage: %s: (-A|-D) -l <left-side vpn peer> -n <left-side guest cidr> -g <left-side gateway> -r <right-side vpn peer> -N <right-side private subnets> -e <esp policy> -i <ike policy> -t <ike lifetime> -T <esp lifetime> -s <pre-shared secret> -d <dpd 0 or 1> \n" $(basename $0) >&2 printf "Usage: %s: (-A|-D) -l <left-side vpn peer> -n <left-side guest cidr> -g <left-side gateway> -r <right-side vpn peer> -N <right-side private subnets> -e <esp policy> -i <ike policy> -t <ike lifetime> -T <esp lifetime> -s <pre-shared secret> -d <dpd 0 or 1> [ -p <passive or not> ]\n" $(basename $0) >&2
} }
#set -x #set -x
@ -173,29 +173,35 @@ ipsec_tunnel_add() {
sudo ipsec auto --rereadall sudo ipsec auto --rereadall
sudo ipsec auto --add vpn-$rightpeer sudo ipsec auto --add vpn-$rightpeer
sudo ipsec auto --up vpn-$rightpeer
logger -t cloud "$(basename $0): done ipsec tunnel entry for right peer=$rightpeer right networks=$rightnets" logger -t cloud "$(basename $0): done ipsec tunnel entry for right peer=$rightpeer right networks=$rightnets"
#5 seconds for checking if it's ready result=0
for i in {1..5}
do if [ $passive -eq 0 ]
logger -t cloud "$(basename $0): checking connection status..." then
/opt/cloud/bin/checks2svpn.sh $rightpeer sudo ipsec auto --up vpn-$rightpeer
result=$?
#5 seconds for checking if it's ready
for i in {1..5}
do
logger -t cloud "$(basename $0): checking connection status..."
/opt/cloud/bin/checks2svpn.sh $rightpeer
result=$?
if [ $result -eq 0 ]
then
break
fi
sleep 1
done
if [ $result -eq 0 ] if [ $result -eq 0 ]
then then
break logger -t cloud "$(basename $0): connect to remote successful"
else
logger -t cloud "$(basename $0): fail to connect to remote, status code: $result"
logger -t cloud "$(basename $0): would stop site-to-site VPN connection"
ipsec_tunnel_del
fi fi
sleep 1
done
if [ $result -eq 0 ]
then
logger -t cloud "$(basename $0): connect to remote successful"
else
logger -t cloud "$(basename $0): fail to connect to remote, status code: $result"
logger -t cloud "$(basename $0): would stop site-to-site VPN connection"
ipsec_tunnel_del
fi fi
return $result return $result
} }
@ -208,9 +214,10 @@ lflag=
iflag= iflag=
Iflag= Iflag=
sflag= sflag=
passive=0
op="" op=""
while getopts 'ADl:n:g:r:N:e:i:t:T:s:d:' OPTION while getopts 'ADpl:n:g:r:N:e:i:t:T:s:d:' OPTION
do do
case $OPTION in case $OPTION in
A) opflag=1 A) opflag=1
@ -252,6 +259,8 @@ do
d) dflag=1 d) dflag=1
dpd="$OPTARG" dpd="$OPTARG"
;; ;;
p) passive=1
;;
?) usage ?) usage
unlock_exit 2 $lock $locked unlock_exit 2 $lock $locked
;; ;;

View File

@ -24,6 +24,8 @@ from marvin.integration.lib.base import *
from marvin.integration.lib.common import * from marvin.integration.lib.common import *
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
import time
class Services: class Services:
def __init__(self): def __init__(self):
self.services = { self.services = {
@ -77,15 +79,37 @@ class Services:
"vpn_user": { "vpn_user": {
"username": "test", "username": "test",
"password": "password", "password": "password",
},
"vpc": {
"name": "vpc_vpn",
"displaytext": "vpc-vpn",
"cidr": "10.1.1.0/24"
},
"ntwk": {
"name": "tier1",
"displaytext": "vpc-tier1",
"gateway" : "10.1.1.1",
"netmask" : "255.255.255.192"
},
"vpc2": {
"name": "vpc2_vpn",
"displaytext": "vpc2-vpn",
"cidr": "10.2.1.0/24"
},
"ntwk2": {
"name": "tier2",
"displaytext": "vpc-tier2",
"gateway" : "10.2.1.1",
"netmask" : "255.255.255.192"
} }
} }
class TestVpcVpn(cloudstackTestCase): class TestVpcRemoteAccessVpn(cloudstackTestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
cls.apiclient = super(TestVpcVpn, cls).getClsTestClient().getApiClient() cls.apiclient = super(TestVpcRemoteAccessVpn, cls).getClsTestClient().getApiClient()
cls.services = Services().services cls.services = Services().services
cls.zone = get_zone(cls.apiclient, cls.services) cls.zone = get_zone(cls.apiclient, cls.services)
cls.domain = get_domain(cls.apiclient) cls.domain = get_domain(cls.apiclient)
@ -102,7 +126,7 @@ class TestVpcVpn(cloudstackTestCase):
cls.cleanup = [cls.account] cls.cleanup = [cls.account]
@attr(tags=["advanced"]) @attr(tags=["advanced"])
def test_vpc_vpn(self): def test_vpc_remote_access_vpn(self):
"""Test VPN in VPC""" """Test VPN in VPC"""
# 0) Get the default network offering for VPC # 0) Get the default network offering for VPC
@ -112,10 +136,6 @@ class TestVpcVpn(cloudstackTestCase):
# 1) Create VPC # 1) Create VPC
vpcOffering = VpcOffering.list(self.apiclient,isdefault=True) vpcOffering = VpcOffering.list(self.apiclient,isdefault=True)
self.assert_(vpcOffering is not None and len(vpcOffering)>0, "No VPC offerings found") self.assert_(vpcOffering is not None and len(vpcOffering)>0, "No VPC offerings found")
self.services["vpc"] = {}
self.services["vpc"]["name"] = "vpc-vpn"
self.services["vpc"]["displaytext"] = "vpc-vpn"
self.services["vpc"]["cidr"] = "10.1.1.0/24"
vpc = VPC.create( vpc = VPC.create(
apiclient=self.apiclient, apiclient=self.apiclient,
services=self.services["vpc"], services=self.services["vpc"],
@ -126,33 +146,29 @@ class TestVpcVpn(cloudstackTestCase):
domainid=self.domain.id domainid=self.domain.id
) )
self.assert_(vpc is not None, "VPC creation failed") self.assert_(vpc is not None, "VPC creation failed")
self.debug("VPC %s created" %(vpc.id))
# 2) Create network in VPC # 2) Create network in VPC
self.services["vpcnetwork"] = {}
self.services["vpcnetwork"]["name"] = "vpcntwk"
self.services["vpcnetwork"]["displaytext"] = "vpcntwk"
ntwk = Network.create( ntwk = Network.create(
apiclient=self.apiclient, apiclient=self.apiclient,
services=self.services["vpcnetwork"], services=self.services["ntwk"],
accountid=self.account.name, accountid=self.account.name,
domainid=self.domain.id, domainid=self.domain.id,
networkofferingid=networkOffering[0].id, networkofferingid=networkOffering[0].id,
zoneid=self.zone.id, zoneid=self.zone.id,
vpcid=vpc.id, vpcid=vpc.id
gateway="10.1.1.1",
netmask="255.255.255.192"
) )
self.assertIsNotNone(ntwk, "Network failed to create") self.assertIsNotNone(ntwk, "Network failed to create")
self.debug("Network %s created in VPC %s" %(ntwk.id, vpc.id)) self.debug("Network %s created in VPC %s" %(ntwk.id, vpc.id))
# 3) Deploy a vm # 3) Deploy a vm
self.services["virtual_machine"]["networkids"] = ntwk.id
vm = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"], vm = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
templateid=self.template.id, templateid=self.template.id,
zoneid=self.zone.id, zoneid=self.zone.id,
accountid=self.account.name, accountid=self.account.name,
domainid= self.domain.id, domainid= self.domain.id,
serviceofferingid=self.service_offering.id, serviceofferingid=self.service_offering.id,
networkids=ntwk.id
) )
self.assert_(vm is not None, "VM failed to deploy") self.assert_(vm is not None, "VM failed to deploy")
self.assert_(vm.state == 'Running', "VM is not running") self.assert_(vm.state == 'Running', "VM is not running")
@ -190,3 +206,186 @@ class TestVpcVpn(cloudstackTestCase):
cleanup_resources(cls.apiclient, cls.cleanup) cleanup_resources(cls.apiclient, cls.cleanup)
except Exception, e: except Exception, e:
raise Exception("Cleanup failed with %s" % e) raise Exception("Cleanup failed with %s" % e)
class TestVpcSite2SiteVpn(cloudstackTestCase):
@classmethod
def setUpClass(cls):
cls.apiclient = super(TestVpcSite2SiteVpn, cls).getClsTestClient().getApiClient()
cls.services = Services().services
cls.zone = get_zone(cls.apiclient, cls.services)
cls.domain = get_domain(cls.apiclient)
cls.service_offering = ServiceOffering.create(
cls.apiclient,
cls.services["service_offering"]
)
cls.account = Account.create(cls.apiclient, services=cls.services["account"])
cls.template = get_template(
cls.apiclient,
cls.zone.id,
cls.services["ostype"]
)
cls.cleanup = [cls.account]
@attr(tags=["advanced"])
def test_vpc_site2site_vpn(self):
"""Test VPN in VPC"""
# 0) Get the default network offering for VPC
networkOffering = NetworkOffering.list(self.apiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks")
self.assert_(networkOffering is not None and len(networkOffering) > 0, "No VPC based network offering")
# 1) Create VPC
vpcOffering = VpcOffering.list(self.apiclient,isdefault=True)
self.assert_(vpcOffering is not None and len(vpcOffering)>0, "No VPC offerings found")
vpc1 = VPC.create(
apiclient=self.apiclient,
services=self.services["vpc"],
networkDomain="vpc1.vpn",
vpcofferingid=vpcOffering[0].id,
zoneid=self.zone.id,
account=self.account.name,
domainid=self.domain.id
)
self.assert_(vpc1 is not None, "VPC creation failed")
self.debug("VPC1 %s created" %(vpc1.id))
vpc2 = VPC.create(
apiclient=self.apiclient,
services=self.services["vpc2"],
networkDomain="vpc2.vpn",
vpcofferingid=vpcOffering[0].id,
zoneid=self.zone.id,
account=self.account.name,
domainid=self.domain.id
)
self.assert_(vpc2 is not None, "VPC2 creation failed")
self.debug("VPC2 %s created" %(vpc1.id))
# 2) Create network in VPC
ntwk1 = Network.create(
apiclient=self.apiclient,
services=self.services["ntwk"],
accountid=self.account.name,
domainid=self.domain.id,
networkofferingid=networkOffering[0].id,
zoneid=self.zone.id,
vpcid=vpc1.id
)
self.assertIsNotNone(ntwk1, "Network failed to create")
self.debug("Network %s created in VPC %s" %(ntwk1.id, vpc1.id))
ntwk2 = Network.create(
apiclient=self.apiclient,
services=self.services["ntwk2"],
accountid=self.account.name,
domainid=self.domain.id,
networkofferingid=networkOffering[0].id,
zoneid=self.zone.id,
vpcid=vpc2.id
)
self.assertIsNotNone(ntwk2, "Network failed to create")
self.debug("Network %s created in VPC %s" %(ntwk2.id, vpc2.id))
# 3) Deploy a vm
vm1 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
templateid=self.template.id,
zoneid=self.zone.id,
accountid=self.account.name,
domainid= self.domain.id,
serviceofferingid=self.service_offering.id,
networkids=ntwk1.id
)
self.assert_(vm1 is not None, "VM failed to deploy")
self.assert_(vm1.state == 'Running', "VM is not running")
self.debug("VM %s deployed in VPC %s" %(vm1.id, vpc1.id))
vm2 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
templateid=self.template.id,
zoneid=self.zone.id,
accountid=self.account.name,
domainid= self.domain.id,
serviceofferingid=self.service_offering.id,
networkids=ntwk2.id
)
self.assert_(vm2 is not None, "VM failed to deploy")
self.assert_(vm2.state == 'Running', "VM is not running")
self.debug("VM %s deployed in VPC %s" %(vm2.id, vpc2.id))
# 4) Enable Site-to-Site VPN for VPC
cmd=createVpnGateway.createVpnGatewayCmd()
cmd.vpcid=vpc1.id
vpn1_response = self.apiclient.createVpnGateway(cmd)
self.debug("VPN gateway for VPC %s enabled" % (vpc1.id))
cmd=createVpnGateway.createVpnGatewayCmd()
cmd.vpcid=vpc2.id
vpn2_response = self.apiclient.createVpnGateway(cmd)
self.debug("VPN gateway for VPC %s enabled" %(vpc2.id))
# 5) Add VPN Customer gateway info
src_nat_list = PublicIPAddress.list(
self.apiclient,
account=self.account.name,
domainid=self.account.domainid,
listall=True,
issourcenat=True,
vpcid=vpc1.id
)
ip1 = src_nat_list[0]
src_nat_list = PublicIPAddress.list(
self.apiclient,
account=self.account.name,
domainid=self.account.domainid,
listall=True,
issourcenat=True,
vpcid=vpc2.id
)
ip2 = src_nat_list[0]
cmd=createVpnCustomerGateway.createVpnCustomerGatewayCmd()
cmd.esppolicy="3des-md5;modp1536"
cmd.ikepolicy="3des-md5;modp1536"
cmd.domainid=self.account.domainid
cmd.account=self.account.name
cmd.ipsecpsk="ipsecpsk"
cmd.name="Peer VPC1"
cmd.gateway=ip1.ipaddress
cmd.cidrlist=vpc1.cidr
customer1_response = self.apiclient.createVpnCustomerGateway(cmd)
self.debug("VPN customer gateway added for VPC %s enabled" %(vpc1.id))
cmd.name="Peer VPC2"
cmd.gateway=ip2.ipaddress
cmd.cidrlist=vpc2.cidr
customer2_response = self.apiclient.createVpnCustomerGateway(cmd)
self.debug("VPN customer gateway added for VPC %s enabled" %(vpc2.id))
# 6) Connect two VPCs
cmd = createVpnConnection.createVpnConnectionCmd()
cmd.s2svpngatewayid = vpn2_response.id
cmd.s2scustomergatewayid = customer1_response.id
cmd.passive="true"
vpnconn1_response = self.apiclient.createVpnConnection(cmd)
self.debug("VPN passive connection created for VPC %s" %(vpc2.id))
cmd = createVpnConnection.createVpnConnectionCmd()
cmd.s2svpngatewayid = vpn1_response.id
cmd.s2scustomergatewayid = customer2_response.id
vpnconn2_response = self.apiclient.createVpnConnection(cmd)
self.debug("VPN connection created for VPC %s" %(vpc1.id))
self.assertEqual(vpnconn2_response.state, "Connected", "Failed to connect between VPCs!")
@classmethod
def tearDownClass(cls):
try:
cleanup_resources(cls.apiclient, cls.cleanup)
except Exception, e:
raise Exception("Cleanup failed with %s" % e)