mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
This includes test related fixes and code review fixes based on reviews from @rafaelweingartner, @marcaurele, @wido and @DaanHoogland. This also includes VMware disk-resize limitation bug fix based on comments from @sateesh-chodapuneedi and @priyankparihar. This also includes the final changes to systemvmtemplate and fixes to code based on issues found via test failures. Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1577 lines
60 KiB
Python
1577 lines
60 KiB
Python
# 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.
|
|
""" Tests for VPN in VPC
|
|
"""
|
|
# Import Local Modules
|
|
from marvin.codes import PASS, FAILED
|
|
from marvin.cloudstackTestCase import cloudstackTestCase
|
|
from marvin.lib.utils import (validateList,
|
|
cleanup_resources,
|
|
get_process_status,
|
|
wait_until)
|
|
|
|
from marvin.lib.base import (Domain,
|
|
Account,
|
|
Configurations,
|
|
VPC,
|
|
VpcOffering,
|
|
ServiceOffering,
|
|
NetworkOffering,
|
|
Network,
|
|
PublicIPAddress,
|
|
NATRule,
|
|
NetworkACL,
|
|
NetworkACLList,
|
|
LoadBalancerRule,
|
|
ApplicationLoadBalancer,
|
|
VirtualMachine,
|
|
Template,
|
|
FireWallRule,
|
|
StaticNATRule,
|
|
Vpn,
|
|
VpnCustomerGateway,
|
|
VpnUser
|
|
)
|
|
|
|
from marvin.sshClient import SshClient
|
|
|
|
|
|
from marvin.lib.common import (get_zone,
|
|
get_domain,
|
|
get_test_template,
|
|
list_network_offerings)
|
|
|
|
from nose.plugins.attrib import attr
|
|
|
|
import logging
|
|
import time
|
|
|
|
|
|
class Services:
|
|
|
|
"""Test VPC VPN Services.
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.services = {
|
|
"account": {
|
|
"email": "test@test.com",
|
|
"firstname": "Test",
|
|
"lastname": "User",
|
|
"username": "test",
|
|
"password": "password",
|
|
},
|
|
"host1": None,
|
|
"host2": None,
|
|
"compute_offering": {
|
|
"name": "Tiny Instance",
|
|
"displaytext": "Tiny Instance",
|
|
"cpunumber": 1,
|
|
"cpuspeed": 100,
|
|
"memory": 128,
|
|
},
|
|
"network_offering": {
|
|
"name": 'VPC Network offering',
|
|
"displaytext": 'VPC Network',
|
|
"guestiptype": 'Isolated',
|
|
"supportedservices": 'Vpn,Dhcp,Dns,SourceNat,Lb,PortForwarding,UserData,StaticNat,NetworkACL',
|
|
"traffictype": 'GUEST',
|
|
"availability": 'Optional',
|
|
"useVpc": 'on',
|
|
"serviceProviderList": {
|
|
"Vpn": 'VpcVirtualRouter',
|
|
"Dhcp": 'VpcVirtualRouter',
|
|
"Dns": 'VpcVirtualRouter',
|
|
"SourceNat": 'VpcVirtualRouter',
|
|
"Lb": 'VpcVirtualRouter',
|
|
"PortForwarding": 'VpcVirtualRouter',
|
|
"UserData": 'VpcVirtualRouter',
|
|
"StaticNat": 'VpcVirtualRouter',
|
|
"NetworkACL": 'VpcVirtualRouter'
|
|
},
|
|
},
|
|
"network_offering_internal_lb": {
|
|
"name": 'VPC Network Internal Lb offering',
|
|
"displaytext": 'VPC Network internal lb',
|
|
"guestiptype": 'Isolated',
|
|
"supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL,Lb',
|
|
"traffictype": 'GUEST',
|
|
"availability": 'Optional',
|
|
"useVpc": 'on',
|
|
"serviceCapabilityList": {
|
|
"Lb": {
|
|
"SupportedLbIsolation": 'dedicated',
|
|
"lbSchemes": 'internal'
|
|
}
|
|
},
|
|
"serviceProviderList": {
|
|
"Dhcp": 'VpcVirtualRouter',
|
|
"Dns": 'VpcVirtualRouter',
|
|
"SourceNat": 'VpcVirtualRouter',
|
|
"PortForwarding": 'VpcVirtualRouter',
|
|
"UserData": 'VpcVirtualRouter',
|
|
"StaticNat": 'VpcVirtualRouter',
|
|
"NetworkACL": 'VpcVirtualRouter',
|
|
"Lb": 'InternalLbVm'
|
|
},
|
|
"egress_policy": "true",
|
|
},
|
|
"vpc_offering": {
|
|
"name": 'VPC off',
|
|
"displaytext": 'VPC off',
|
|
"supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat',
|
|
},
|
|
"redundant_vpc_offering": {
|
|
"name": 'Redundant VPC off',
|
|
"displaytext": 'Redundant VPC off',
|
|
"supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat',
|
|
"serviceProviderList": {
|
|
"Vpn": 'VpcVirtualRouter',
|
|
"Dhcp": 'VpcVirtualRouter',
|
|
"Dns": 'VpcVirtualRouter',
|
|
"SourceNat": 'VpcVirtualRouter',
|
|
"PortForwarding": 'VpcVirtualRouter',
|
|
"Lb": 'VpcVirtualRouter',
|
|
"UserData": 'VpcVirtualRouter',
|
|
"StaticNat": 'VpcVirtualRouter',
|
|
"NetworkACL": 'VpcVirtualRouter'
|
|
},
|
|
"serviceCapabilityList": {
|
|
"SourceNat": {
|
|
"RedundantRouter": 'true'
|
|
}
|
|
},
|
|
},
|
|
"vpc": {
|
|
"name": "TestVPC",
|
|
"displaytext": "TestVPC",
|
|
"cidr": '10.1.0.0/16'
|
|
},
|
|
"vpc1": {
|
|
"name": "TestVPC",
|
|
"displaytext": "VPC1",
|
|
"cidr": '10.1.0.0/16'
|
|
},
|
|
"vpc2": {
|
|
"name": "TestVPC",
|
|
"displaytext": "VPC2",
|
|
"cidr": '10.3.0.0/16'
|
|
},
|
|
"network_1": {
|
|
"name": "Test Network",
|
|
"displaytext": "Test Network",
|
|
"netmask": '255.255.255.0',
|
|
"gateway": "10.1.1.1"
|
|
},
|
|
"network_2": {
|
|
"name": "Test Network",
|
|
"displaytext": "Test Network",
|
|
"netmask": '255.255.255.0',
|
|
"gateway": "10.3.1.1"
|
|
},
|
|
"vpn": {
|
|
"vpn_user": "root",
|
|
"vpn_pass": "Md1sdc",
|
|
"vpn_pass_fail": "abc!123", # too short
|
|
"iprange": "10.3.2.1-10.3.2.10",
|
|
"fordisplay": "true"
|
|
},
|
|
"vpncustomergateway": {
|
|
"esppolicy": "3des-md5;modp1536",
|
|
"ikepolicy": "3des-md5;modp1536",
|
|
"ipsecpsk": "ipsecpsk"
|
|
},
|
|
"natrule": {
|
|
"protocol": "TCP",
|
|
"cidrlist": '0.0.0.0/0',
|
|
},
|
|
"http_rule": {
|
|
"privateport": 80,
|
|
"publicport": 80,
|
|
"startport": 80,
|
|
"endport": 80,
|
|
"cidrlist": '0.0.0.0/0',
|
|
"protocol": "TCP"
|
|
},
|
|
"virtual_machine": {
|
|
"displayname": "Test VM",
|
|
"username": "root",
|
|
"password": "password",
|
|
"ssh_port": 22,
|
|
"privateport": 22,
|
|
"publicport": 22,
|
|
"protocol": 'TCP',
|
|
}
|
|
}
|
|
|
|
|
|
class TestVpcRemoteAccessVpn(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
|
|
cls.logger = logging.getLogger('TestVPCRemoteAccessVPN')
|
|
cls.stream_handler = logging.StreamHandler()
|
|
cls.logger.setLevel(logging.DEBUG)
|
|
cls.logger.addHandler(cls.stream_handler)
|
|
|
|
testClient = super(TestVpcRemoteAccessVpn, cls).getClsTestClient()
|
|
cls.apiclient = testClient.getApiClient()
|
|
cls.services = Services().services
|
|
|
|
cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
|
|
cls.domain = get_domain(cls.apiclient)
|
|
|
|
cls.compute_offering = ServiceOffering.create(
|
|
cls.apiclient,
|
|
cls.services["compute_offering"]
|
|
)
|
|
cls.account = Account.create(
|
|
cls.apiclient, services=cls.services["account"])
|
|
|
|
cls.hypervisor = testClient.getHypervisorInfo()
|
|
|
|
cls.template = get_test_template(cls.apiclient, cls.zone.id, cls.hypervisor)
|
|
if cls.template == FAILED:
|
|
assert False, "get_test_template() failed to return template"
|
|
|
|
cls.logger.debug("Successfully created account: %s, id: \
|
|
%s" % (cls.account.name,
|
|
cls.account.id))
|
|
|
|
cls.cleanup = [cls.account, cls.compute_offering]
|
|
return
|
|
|
|
@attr(tags=["advanced"], required_hardware="true")
|
|
def test_01_vpc_remote_access_vpn(self):
|
|
"""Test Remote Access VPN in VPC"""
|
|
|
|
self.logger.debug("Starting test: test_01_vpc_remote_access_vpn")
|
|
|
|
# 0) Get the default network offering for VPC
|
|
self.logger.debug("Retrieving default VPC offering")
|
|
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, name="Default VPC offering")
|
|
self.assert_(vpcOffering is not None and len(
|
|
vpcOffering) > 0, "No VPC offerings found")
|
|
|
|
vpc = None
|
|
try:
|
|
vpc = VPC.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["vpc"],
|
|
networkDomain="vpc.vpn",
|
|
vpcofferingid=vpcOffering[0].id,
|
|
zoneid=self.zone.id,
|
|
account=self.account.name,
|
|
domainid=self.domain.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vpc is not None, "VPC creation failed")
|
|
self.logger.debug("VPC %s created" % (vpc.id))
|
|
|
|
try:
|
|
# 2) Create network in VPC
|
|
ntwk = Network.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["network_1"],
|
|
accountid=self.account.name,
|
|
domainid=self.domain.id,
|
|
networkofferingid=networkOffering[0].id,
|
|
zoneid=self.zone.id,
|
|
vpcid=vpc.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assertIsNotNone(ntwk, "Network failed to create")
|
|
self.logger.debug(
|
|
"Network %s created in VPC %s" % (ntwk.id, vpc.id))
|
|
|
|
try:
|
|
# 3) Deploy a vm
|
|
vm = 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.compute_offering.id,
|
|
networkids=ntwk.id,
|
|
hypervisor=self.hypervisor
|
|
)
|
|
self.assert_(vm is not None, "VM failed to deploy")
|
|
self.assert_(vm.state == 'Running', "VM is not running")
|
|
self.debug("VM %s deployed in VPC %s" % (vm.id, vpc.id))
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.logger.debug("Deployed virtual machine: OK")
|
|
|
|
try:
|
|
# 4) Enable VPN for VPC
|
|
src_nat_list = PublicIPAddress.list(
|
|
self.apiclient,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid,
|
|
listall=True,
|
|
issourcenat=True,
|
|
vpcid=vpc.id
|
|
)
|
|
ip = src_nat_list[0]
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.logger.debug("Acquired public ip address: OK")
|
|
|
|
vpn = None
|
|
try:
|
|
vpn = Vpn.create(self.apiclient,
|
|
publicipid=ip.id,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid,
|
|
iprange=self.services["vpn"]["iprange"],
|
|
fordisplay=self.services["vpn"]["fordisplay"]
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assertIsNotNone(vpn, "Failed to create Remote Access VPN")
|
|
self.logger.debug("Created Remote Access VPN: OK")
|
|
|
|
vpnUser = None
|
|
# 5) Add VPN user for VPC
|
|
try:
|
|
vpnUser = VpnUser.create(self.apiclient,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid,
|
|
username=self.services["vpn"]["vpn_user"],
|
|
password=self.services["vpn"]["vpn_pass"]
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assertIsNotNone(
|
|
vpnUser, "Failed to create Remote Access VPN User")
|
|
self.logger.debug("Created VPN User: OK")
|
|
|
|
# TODO: Add an actual remote vpn connection test from a remote vpc
|
|
|
|
try:
|
|
# 9) Disable VPN for VPC
|
|
vpn.delete(self.apiclient)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.logger.debug("Deleted the Remote Access VPN: OK")
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
|
|
try:
|
|
cls.logger.debug("Cleaning up resources")
|
|
cleanup_resources(cls.apiclient, cls.cleanup)
|
|
except Exception, e:
|
|
raise Exception("Cleanup failed with %s" % e)
|
|
|
|
|
|
class TestVpcSite2SiteVpn(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.logger = logging.getLogger('TestVPCSite2SiteVPN')
|
|
cls.stream_handler = logging.StreamHandler()
|
|
cls.logger.setLevel(logging.DEBUG)
|
|
cls.logger.addHandler(cls.stream_handler)
|
|
|
|
testClient = super(TestVpcSite2SiteVpn, cls).getClsTestClient()
|
|
cls.apiclient = testClient.getApiClient()
|
|
cls.services = Services().services
|
|
|
|
cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
|
|
cls.domain = get_domain(cls.apiclient)
|
|
|
|
cls.compute_offering = ServiceOffering.create(
|
|
cls.apiclient,
|
|
cls.services["compute_offering"]
|
|
)
|
|
|
|
cls.account = Account.create(
|
|
cls.apiclient, services=cls.services["account"])
|
|
|
|
cls.hypervisor = testClient.getHypervisorInfo()
|
|
|
|
cls.template = get_test_template(cls.apiclient, cls.zone.id, cls.hypervisor)
|
|
if cls.template == FAILED:
|
|
assert False, "get_test_template() failed to return template"
|
|
|
|
cls.logger.debug("Successfully created account: %s, id: \
|
|
%s" % (cls.account.name,
|
|
cls.account.id))
|
|
|
|
cls.cleanup = [cls.account, cls.compute_offering]
|
|
return
|
|
|
|
def _get_ssh_client(self, virtual_machine, services, retries):
|
|
""" Setup ssh client connection and return connection
|
|
vm requires attributes public_ip, public_port, username, password """
|
|
|
|
try:
|
|
ssh_client = SshClient(
|
|
virtual_machine.public_ip,
|
|
services["virtual_machine"]["ssh_port"],
|
|
services["virtual_machine"]["username"],
|
|
services["virtual_machine"]["password"],
|
|
retries)
|
|
|
|
except Exception as e:
|
|
self.fail("Unable to create ssh connection: " % e)
|
|
|
|
self.assertIsNotNone(
|
|
ssh_client, "Failed to setup ssh connection to vm=%s on public_ip=%s" % (virtual_machine.name, virtual_machine.public_ip))
|
|
|
|
return ssh_client
|
|
|
|
def _create_natrule(self, vpc, vm, public_port, private_port, public_ip, network, services=None):
|
|
self.logger.debug("Creating NAT rule in network for vm with public IP")
|
|
if not services:
|
|
self.services["natrule"]["privateport"] = private_port
|
|
self.services["natrule"]["publicport"] = public_port
|
|
self.services["natrule"]["startport"] = public_port
|
|
self.services["natrule"]["endport"] = public_port
|
|
services = self.services["natrule"]
|
|
|
|
nat_rule = NATRule.create(
|
|
apiclient=self.apiclient,
|
|
services=services,
|
|
ipaddressid=public_ip.ipaddress.id,
|
|
virtual_machine=vm,
|
|
networkid=network.id
|
|
)
|
|
self.assertIsNotNone(
|
|
nat_rule, "Failed to create NAT Rule for %s" % public_ip.ipaddress.ipaddress)
|
|
self.logger.debug(
|
|
"Adding NetworkACL rules to make NAT rule accessible")
|
|
|
|
vm.ssh_ip = nat_rule.ipaddress
|
|
vm.public_ip = nat_rule.ipaddress
|
|
vm.public_port = int(public_port)
|
|
return nat_rule
|
|
|
|
def _validate_vpc_offering(self, vpc_offering):
|
|
|
|
self.logger.debug("Check if the VPC offering is created successfully?")
|
|
vpc_offs = VpcOffering.list(
|
|
self.apiclient,
|
|
id=vpc_offering.id
|
|
)
|
|
offering_list = validateList(vpc_offs)
|
|
self.assertEqual(offering_list[0],
|
|
PASS,
|
|
"List VPC offerings should return a valid list"
|
|
)
|
|
self.assertEqual(
|
|
vpc_offering.name,
|
|
vpc_offs[0].name,
|
|
"Name of the VPC offering should match with listVPCOff data"
|
|
)
|
|
self.logger.debug(
|
|
"VPC offering is created successfully - %s" %
|
|
vpc_offering.name)
|
|
return
|
|
|
|
def _create_vpc_offering(self, offering_name):
|
|
|
|
vpc_off = None
|
|
if offering_name is not None:
|
|
|
|
self.logger.debug("Creating VPC offering: %s", offering_name)
|
|
vpc_off = VpcOffering.create(
|
|
self.apiclient,
|
|
self.services[offering_name]
|
|
)
|
|
|
|
self._validate_vpc_offering(vpc_off)
|
|
self.cleanup.append(vpc_off)
|
|
|
|
return vpc_off
|
|
|
|
@attr(tags=["advanced"], required_hardware="true")
|
|
def test_01_vpc_site2site_vpn(self):
|
|
"""Test Site 2 Site VPN Across VPCs"""
|
|
self.logger.debug("Starting test: test_01_vpc_site2site_vpn")
|
|
# 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")
|
|
|
|
# Create and Enable VPC offering
|
|
vpc_offering = self._create_vpc_offering('vpc_offering')
|
|
self.assert_(vpc_offering is not None, "Failed to create VPC Offering")
|
|
vpc_offering.update(self.apiclient, state='Enabled')
|
|
|
|
vpc1 = None
|
|
# Create VPC 1
|
|
try:
|
|
vpc1 = VPC.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["vpc"],
|
|
networkDomain="vpc1.vpn",
|
|
vpcofferingid=vpc_offering.id,
|
|
zoneid=self.zone.id,
|
|
account=self.account.name,
|
|
domainid=self.domain.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vpc1 is not None, "VPC1 creation failed")
|
|
|
|
self.logger.debug("VPC1 %s created" % vpc1.id)
|
|
|
|
vpc2 = None
|
|
# Create VPC 2
|
|
try:
|
|
vpc2 = VPC.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["vpc2"],
|
|
networkDomain="vpc2.vpn",
|
|
vpcofferingid=vpc_offering.id,
|
|
zoneid=self.zone.id,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vpc2 is not None, "VPC2 creation failed")
|
|
|
|
self.logger.debug("VPC2 %s created" % vpc2.id)
|
|
|
|
default_acl = NetworkACLList.list(
|
|
self.apiclient, name="default_allow")[0]
|
|
|
|
ntwk1 = None
|
|
# Create network in VPC 1
|
|
try:
|
|
ntwk1 = Network.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["network_1"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=networkOffering[0].id,
|
|
zoneid=self.zone.id,
|
|
vpcid=vpc1.id,
|
|
aclid=default_acl.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assertIsNotNone(ntwk1, "Network failed to create")
|
|
|
|
self.logger.debug("Network %s created in VPC %s" % (ntwk1.id, vpc1.id))
|
|
|
|
ntwk2 = None
|
|
# Create network in VPC 2
|
|
try:
|
|
ntwk2 = Network.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["network_2"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=networkOffering[0].id,
|
|
zoneid=self.zone.id,
|
|
vpcid=vpc2.id,
|
|
aclid=default_acl.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assertIsNotNone(ntwk2, "Network failed to create")
|
|
|
|
self.logger.debug("Network %s created in VPC %s" % (ntwk2.id, vpc2.id))
|
|
|
|
vm1 = None
|
|
# Deploy a vm in network 2
|
|
try:
|
|
vm1 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
zoneid=self.zone.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.compute_offering.id,
|
|
networkids=ntwk1.id,
|
|
hypervisor=self.hypervisor
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vm1 is not None, "VM failed to deploy")
|
|
self.assert_(vm1.state == 'Running', "VM is not running")
|
|
|
|
self.logger.debug("VM %s deployed in VPC %s" % (vm1.id, vpc1.id))
|
|
|
|
vm2 = None
|
|
# Deploy a vm in network 2
|
|
try:
|
|
vm2 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
zoneid=self.zone.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.compute_offering.id,
|
|
networkids=ntwk2.id,
|
|
hypervisor=self.hypervisor
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
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
|
|
vpn1_response = Vpn.createVpnGateway(self.apiclient, vpc1.id)
|
|
self.assert_(
|
|
vpn1_response is not None, "Failed to enable VPN Gateway 1")
|
|
self.logger.debug("VPN gateway for VPC %s enabled" % vpc1.id)
|
|
|
|
vpn2_response = Vpn.createVpnGateway(self.apiclient, vpc2.id)
|
|
self.assert_(
|
|
vpn2_response is not None, "Failed to enable VPN Gateway 2")
|
|
self.logger.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]
|
|
|
|
services = self.services["vpncustomergateway"]
|
|
customer1_response = VpnCustomerGateway.create(
|
|
self.apiclient, services, "Peer VPC1", ip1.ipaddress, vpc1.cidr, self.account.name, self.domain.id)
|
|
self.debug("VPN customer gateway added for VPC %s enabled" % vpc1.id)
|
|
self.logger.debug(vars(customer1_response))
|
|
|
|
customer2_response = VpnCustomerGateway.create(
|
|
self.apiclient, services, "Peer VPC2", ip2.ipaddress, vpc2.cidr, self.account.name, self.domain.id)
|
|
self.debug("VPN customer gateway added for VPC %s enabled" % vpc2.id)
|
|
self.logger.debug(vars(customer2_response))
|
|
|
|
# 6) Connect two VPCs
|
|
vpnconn1_response = Vpn.createVpnConnection(
|
|
self.apiclient, customer1_response.id, vpn2_response['id'], True)
|
|
self.debug("VPN passive connection created for VPC %s" % vpc2.id)
|
|
|
|
vpnconn2_response = Vpn.createVpnConnection(
|
|
self.apiclient, customer2_response.id, vpn1_response['id'])
|
|
self.debug("VPN connection created for VPC %s" % vpc1.id)
|
|
|
|
def checkVpnConnected():
|
|
connections = Vpn.listVpnConnection(
|
|
self.apiclient,
|
|
listall='true',
|
|
vpcid=vpc2.id)
|
|
if isinstance(connections, list):
|
|
return connections[0].state == 'Connected', None
|
|
return False, None
|
|
|
|
# Wait up to 60 seconds for passive connection to show up as Connected
|
|
res, _ = wait_until(2, 30, checkVpnConnected)
|
|
if not res:
|
|
self.fail("Failed to connect between VPCs, see VPN state as Connected")
|
|
|
|
# acquire an extra ip address to use to ssh into vm2
|
|
try:
|
|
vm2.public_ip = PublicIPAddress.create(
|
|
apiclient=self.apiclient,
|
|
accountid=self.account.name,
|
|
zoneid=self.zone.id,
|
|
domainid=self.account.domainid,
|
|
services=self.services,
|
|
networkid=ntwk2.id,
|
|
vpcid=vpc2.id)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(
|
|
vm2.public_ip is not None, "Failed to aqcuire public ip for vm2")
|
|
|
|
natrule = None
|
|
# Create port forward to be able to ssh into vm2
|
|
try:
|
|
natrule = self._create_natrule(
|
|
vpc2, vm2, 22, 22, vm2.public_ip, ntwk2)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(
|
|
natrule is not None, "Failed to create portforward for vm2")
|
|
time.sleep(20)
|
|
|
|
# setup ssh connection to vm2
|
|
ssh_client = self._get_ssh_client(vm2, self.services, 10)
|
|
|
|
if ssh_client:
|
|
# run ping test
|
|
packet_loss = ssh_client.execute("/bin/ping -c 3 -t 10 " + vm1.nic[0].ipaddress + " | grep packet | sed 's/.*received, //g' | sed 's/[% ]*packet.*//g'")[0]
|
|
# during startup, some packets may not reply due to link/ipsec-route setup
|
|
self.assert_(int(packet_loss) < 50, "Ping did not succeed")
|
|
else:
|
|
self.fail("Failed to setup ssh connection to %s" % vm2.public_ip)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
cleanup_resources(cls.apiclient, cls.cleanup)
|
|
except Exception, e:
|
|
raise Exception("Cleanup failed with %s" % e)
|
|
|
|
|
|
class TestRVPCSite2SiteVpn(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.logger = logging.getLogger('TestRVPCSite2SiteVPN')
|
|
cls.stream_handler = logging.StreamHandler()
|
|
cls.logger.setLevel(logging.DEBUG)
|
|
cls.logger.addHandler(cls.stream_handler)
|
|
|
|
testClient = super(TestRVPCSite2SiteVpn, cls).getClsTestClient()
|
|
cls.apiclient = testClient.getApiClient()
|
|
cls.services = Services().services
|
|
|
|
cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
|
|
cls.domain = get_domain(cls.apiclient)
|
|
|
|
cls.compute_offering = ServiceOffering.create(
|
|
cls.apiclient,
|
|
cls.services["compute_offering"]
|
|
)
|
|
|
|
cls.account = Account.create(
|
|
cls.apiclient, services=cls.services["account"])
|
|
|
|
cls.hypervisor = testClient.getHypervisorInfo()
|
|
|
|
cls.template = get_test_template(cls.apiclient, cls.zone.id, cls.hypervisor)
|
|
if cls.template == FAILED:
|
|
assert False, "get_test_template() failed to return template"
|
|
|
|
cls.logger.debug("Successfully created account: %s, id: \
|
|
%s" % (cls.account.name,
|
|
cls.account.id))
|
|
|
|
cls.cleanup = [cls.account, cls.compute_offering]
|
|
return
|
|
|
|
def _validate_vpc_offering(self, vpc_offering):
|
|
|
|
self.logger.debug("Check if the VPC offering is created successfully?")
|
|
vpc_offs = VpcOffering.list(
|
|
self.apiclient,
|
|
id=vpc_offering.id
|
|
)
|
|
offering_list = validateList(vpc_offs)
|
|
self.assertEqual(offering_list[0],
|
|
PASS,
|
|
"List VPC offerings should return a valid list"
|
|
)
|
|
self.assertEqual(
|
|
vpc_offering.name,
|
|
vpc_offs[0].name,
|
|
"Name of the VPC offering should match with listVPCOff data"
|
|
)
|
|
self.logger.debug(
|
|
"VPC offering is created successfully - %s" %
|
|
vpc_offering.name)
|
|
return
|
|
|
|
def _create_vpc_offering(self, offering_name):
|
|
|
|
vpc_off = None
|
|
if offering_name is not None:
|
|
|
|
self.logger.debug("Creating VPC offering: %s", offering_name)
|
|
vpc_off = VpcOffering.create(
|
|
self.apiclient,
|
|
self.services[offering_name]
|
|
)
|
|
|
|
self._validate_vpc_offering(vpc_off)
|
|
self.cleanup.append(vpc_off)
|
|
|
|
return vpc_off
|
|
|
|
def _get_ssh_client(self, virtual_machine, services, retries):
|
|
""" Setup ssh client connection and return connection
|
|
vm requires attributes public_ip, public_port, username, password """
|
|
|
|
try:
|
|
ssh_client = SshClient(
|
|
virtual_machine.public_ip,
|
|
services["virtual_machine"]["ssh_port"],
|
|
services["virtual_machine"]["username"],
|
|
services["virtual_machine"]["password"],
|
|
retries)
|
|
|
|
except Exception as e:
|
|
self.fail("Unable to create ssh connection: %s" % e)
|
|
|
|
self.assertIsNotNone(
|
|
ssh_client, "Failed to setup ssh connection to vm=%s on public_ip=%s" % (virtual_machine.name, virtual_machine.public_ip))
|
|
|
|
return ssh_client
|
|
|
|
def _create_natrule(self, vpc, vm, public_port, private_port, public_ip, network, services=None):
|
|
self.logger.debug("Creating NAT rule in network for vm with public IP")
|
|
if not services:
|
|
self.services["natrule"]["privateport"] = private_port
|
|
self.services["natrule"]["publicport"] = public_port
|
|
self.services["natrule"]["startport"] = public_port
|
|
self.services["natrule"]["endport"] = public_port
|
|
services = self.services["natrule"]
|
|
|
|
nat_rule = NATRule.create(
|
|
apiclient=self.apiclient,
|
|
services=services,
|
|
ipaddressid=public_ip.ipaddress.id,
|
|
virtual_machine=vm,
|
|
networkid=network.id
|
|
)
|
|
self.assertIsNotNone(
|
|
nat_rule, "Failed to create NAT Rule for %s" % public_ip.ipaddress.ipaddress)
|
|
self.logger.debug(
|
|
"Adding NetworkACL rules to make NAT rule accessible")
|
|
|
|
vm.ssh_ip = nat_rule.ipaddress
|
|
vm.public_ip = nat_rule.ipaddress
|
|
vm.public_port = int(public_port)
|
|
return nat_rule
|
|
|
|
@attr(tags=["advanced"], required_hardware="true")
|
|
def test_01_redundant_vpc_site2site_vpn(self):
|
|
"""Test Site 2 Site VPN Across redundant VPCs"""
|
|
self.logger.debug("Starting test: test_02_redundant_vpc_site2site_vpn")
|
|
|
|
# 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")
|
|
|
|
# Create and enable redundant VPC offering
|
|
redundant_vpc_offering = self._create_vpc_offering(
|
|
'redundant_vpc_offering')
|
|
self.assert_(redundant_vpc_offering is not None,
|
|
"Failed to create redundant VPC Offering")
|
|
|
|
redundant_vpc_offering.update(self.apiclient, state='Enabled')
|
|
|
|
# Create VPC 1
|
|
vpc1 = None
|
|
try:
|
|
vpc1 = VPC.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["vpc"],
|
|
networkDomain="vpc1.vpn",
|
|
vpcofferingid=redundant_vpc_offering.id,
|
|
zoneid=self.zone.id,
|
|
account=self.account.name,
|
|
domainid=self.domain.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vpc1 is not None, "VPC1 creation failed")
|
|
|
|
self.logger.debug("VPC1 %s created" % vpc1.id)
|
|
|
|
# Create VPC 2
|
|
vpc2 = None
|
|
try:
|
|
vpc2 = VPC.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["vpc2"],
|
|
networkDomain="vpc2.vpn",
|
|
vpcofferingid=redundant_vpc_offering.id,
|
|
zoneid=self.zone.id,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vpc2 is not None, "VPC2 creation failed")
|
|
|
|
self.logger.debug("VPC2 %s created" % vpc2.id)
|
|
|
|
default_acl = NetworkACLList.list(
|
|
self.apiclient, name="default_allow")[0]
|
|
|
|
# Create network in VPC 1
|
|
ntwk1 = None
|
|
try:
|
|
ntwk1 = Network.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["network_1"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=networkOffering[0].id,
|
|
zoneid=self.zone.id,
|
|
vpcid=vpc1.id,
|
|
aclid=default_acl.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assertIsNotNone(ntwk1, "Network failed to create")
|
|
|
|
self.logger.debug("Network %s created in VPC %s" % (ntwk1.id, vpc1.id))
|
|
|
|
# Create network in VPC 2
|
|
ntwk2 = None
|
|
try:
|
|
ntwk2 = Network.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["network_2"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=networkOffering[0].id,
|
|
zoneid=self.zone.id,
|
|
vpcid=vpc2.id,
|
|
aclid=default_acl.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assertIsNotNone(ntwk2, "Network failed to create")
|
|
|
|
self.logger.debug("Network %s created in VPC %s" % (ntwk2.id, vpc2.id))
|
|
|
|
# Deploy a vm in network 2
|
|
vm1 = None
|
|
try:
|
|
vm1 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
zoneid=self.zone.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.compute_offering.id,
|
|
networkids=ntwk1.id,
|
|
hypervisor=self.hypervisor
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vm1 is not None, "VM failed to deploy")
|
|
self.assert_(vm1.state == 'Running', "VM is not running")
|
|
|
|
self.logger.debug("VM %s deployed in VPC %s" % (vm1.id, vpc1.id))
|
|
|
|
# Deploy a vm in network 2
|
|
vm2 = None
|
|
try:
|
|
vm2 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
zoneid=self.zone.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.compute_offering.id,
|
|
networkids=ntwk2.id,
|
|
hypervisor=self.hypervisor
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
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
|
|
vpn1_response = Vpn.createVpnGateway(self.apiclient, vpc1.id)
|
|
self.assert_(
|
|
vpn1_response is not None, "Failed to enable VPN Gateway 1")
|
|
self.logger.debug("VPN gateway for VPC %s enabled" % vpc1.id)
|
|
|
|
vpn2_response = Vpn.createVpnGateway(self.apiclient, vpc2.id)
|
|
self.assert_(
|
|
vpn2_response is not None, "Failed to enable VPN Gateway 2")
|
|
self.logger.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]
|
|
|
|
services = self.services["vpncustomergateway"]
|
|
customer1_response = VpnCustomerGateway.create(
|
|
self.apiclient, services, "Peer VPC1", ip1.ipaddress, vpc1.cidr, self.account.name, self.domain.id)
|
|
self.debug("VPN customer gateway added for VPC %s enabled" % vpc1.id)
|
|
self.logger.debug(vars(customer1_response))
|
|
|
|
customer2_response = VpnCustomerGateway.create(
|
|
self.apiclient, services, "Peer VPC2", ip2.ipaddress, vpc2.cidr, self.account.name, self.domain.id)
|
|
self.debug("VPN customer gateway added for VPC %s enabled" % vpc2.id)
|
|
self.logger.debug(vars(customer2_response))
|
|
|
|
# 6) Connect two VPCs
|
|
vpnconn1_response = Vpn.createVpnConnection(
|
|
self.apiclient, customer1_response.id, vpn2_response['id'], True)
|
|
self.debug("VPN passive connection created for VPC %s" % vpc2.id)
|
|
|
|
vpnconn2_response = Vpn.createVpnConnection(
|
|
self.apiclient, customer2_response.id, vpn1_response['id'])
|
|
self.debug("VPN connection created for VPC %s" % vpc1.id)
|
|
|
|
def checkVpnConnected():
|
|
connections = Vpn.listVpnConnection(
|
|
self.apiclient,
|
|
listall='true',
|
|
vpcid=vpc2.id)
|
|
if isinstance(connections, list):
|
|
return connections[0].state == 'Connected', None
|
|
return False, None
|
|
|
|
# Wait up to 60 seconds for passive connection to show up as Connected
|
|
res, _ = wait_until(2, 30, checkVpnConnected)
|
|
if not res:
|
|
self.fail("Failed to connect between VPCs, see VPN state as Connected")
|
|
|
|
# acquire an extra ip address to use to ssh into vm2
|
|
try:
|
|
vm2.public_ip = PublicIPAddress.create(
|
|
apiclient=self.apiclient,
|
|
accountid=self.account.name,
|
|
zoneid=self.zone.id,
|
|
domainid=self.account.domainid,
|
|
services=self.services,
|
|
networkid=ntwk2.id,
|
|
vpcid=vpc2.id)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(
|
|
vm2.public_ip is not None, "Failed to aqcuire public ip for vm2")
|
|
|
|
# Create port forward to be able to ssh into vm2
|
|
natrule = None
|
|
try:
|
|
natrule = self._create_natrule(
|
|
vpc2, vm2, 22, 22, vm2.public_ip, ntwk2)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(
|
|
natrule is not None, "Failed to create portforward for vm2")
|
|
time.sleep(20)
|
|
|
|
# setup ssh connection to vm2
|
|
ssh_client = self._get_ssh_client(vm2, self.services, 10)
|
|
|
|
if ssh_client:
|
|
# run ping test
|
|
packet_loss = ssh_client.execute("/bin/ping -c 3 -t 10 " + vm1.nic[0].ipaddress + " | grep packet | sed 's/.*received, //g' | sed 's/[% ]*packet.*//g'")[0]
|
|
self.assert_(int(packet_loss) < 50, "Ping did not succeed")
|
|
else:
|
|
self.fail("Failed to setup ssh connection to %s" % vm2.public_ip)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
cleanup_resources(cls.apiclient, cls.cleanup)
|
|
except Exception, e:
|
|
raise Exception("Cleanup failed with %s" % e)
|
|
|
|
|
|
class TestVPCSite2SiteVPNMultipleOptions(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.logger = logging.getLogger('TestVPCSite2SiteVPNMultipleOptions')
|
|
cls.stream_handler = logging.StreamHandler()
|
|
cls.logger.setLevel(logging.DEBUG)
|
|
cls.logger.addHandler(cls.stream_handler)
|
|
|
|
testClient = super(TestVPCSite2SiteVPNMultipleOptions, cls).getClsTestClient()
|
|
cls.apiclient = testClient.getApiClient()
|
|
cls.services = Services().services
|
|
|
|
cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
|
|
cls.domain = get_domain(cls.apiclient)
|
|
|
|
cls.compute_offering = ServiceOffering.create(
|
|
cls.apiclient,
|
|
cls.services["compute_offering"]
|
|
)
|
|
|
|
cls.account = Account.create(
|
|
cls.apiclient, services=cls.services["account"])
|
|
|
|
cls.hypervisor = testClient.getHypervisorInfo()
|
|
|
|
cls.template = get_test_template(cls.apiclient, cls.zone.id, cls.hypervisor)
|
|
if cls.template == FAILED:
|
|
assert False, "get_test_template() failed to return template"
|
|
|
|
cls.logger.debug("Successfully created account: %s, id: \
|
|
%s" % (cls.account.name,
|
|
cls.account.id))
|
|
|
|
cls.cleanup = [cls.account, cls.compute_offering]
|
|
return
|
|
|
|
def _get_ssh_client(self, virtual_machine, services, retries):
|
|
""" Setup ssh client connection and return connection
|
|
vm requires attributes public_ip, public_port, username, password """
|
|
|
|
try:
|
|
ssh_client = SshClient(
|
|
virtual_machine.public_ip,
|
|
services["virtual_machine"]["ssh_port"],
|
|
services["virtual_machine"]["username"],
|
|
services["virtual_machine"]["password"],
|
|
retries)
|
|
|
|
except Exception as e:
|
|
self.fail("Unable to create ssh connection: " % e)
|
|
|
|
self.assertIsNotNone(
|
|
ssh_client, "Failed to setup ssh connection to vm=%s on public_ip=%s" % (virtual_machine.name, virtual_machine.public_ip))
|
|
|
|
return ssh_client
|
|
|
|
def _create_natrule(self, vpc, vm, public_port, private_port, public_ip, network, services=None):
|
|
self.logger.debug("Creating NAT rule in network for vm with public IP")
|
|
if not services:
|
|
self.services["natrule"]["privateport"] = private_port
|
|
self.services["natrule"]["publicport"] = public_port
|
|
self.services["natrule"]["startport"] = public_port
|
|
self.services["natrule"]["endport"] = public_port
|
|
services = self.services["natrule"]
|
|
|
|
nat_rule = NATRule.create(
|
|
apiclient=self.apiclient,
|
|
services=services,
|
|
ipaddressid=public_ip.ipaddress.id,
|
|
virtual_machine=vm,
|
|
networkid=network.id
|
|
)
|
|
self.assertIsNotNone(
|
|
nat_rule, "Failed to create NAT Rule for %s" % public_ip.ipaddress.ipaddress)
|
|
self.logger.debug(
|
|
"Adding NetworkACL rules to make NAT rule accessible")
|
|
|
|
vm.ssh_ip = nat_rule.ipaddress
|
|
vm.public_ip = nat_rule.ipaddress
|
|
vm.public_port = int(public_port)
|
|
return nat_rule
|
|
|
|
def _validate_vpc_offering(self, vpc_offering):
|
|
|
|
self.logger.debug("Check if the VPC offering is created successfully?")
|
|
vpc_offs = VpcOffering.list(
|
|
self.apiclient,
|
|
id=vpc_offering.id
|
|
)
|
|
offering_list = validateList(vpc_offs)
|
|
self.assertEqual(offering_list[0],
|
|
PASS,
|
|
"List VPC offerings should return a valid list"
|
|
)
|
|
self.assertEqual(
|
|
vpc_offering.name,
|
|
vpc_offs[0].name,
|
|
"Name of the VPC offering should match with listVPCOff data"
|
|
)
|
|
self.logger.debug(
|
|
"VPC offering is created successfully - %s" %
|
|
vpc_offering.name)
|
|
return
|
|
|
|
def _create_vpc_offering(self, offering_name):
|
|
|
|
vpc_off = None
|
|
if offering_name is not None:
|
|
|
|
self.logger.debug("Creating VPC offering: %s", offering_name)
|
|
vpc_off = VpcOffering.create(
|
|
self.apiclient,
|
|
self.services[offering_name]
|
|
)
|
|
|
|
self._validate_vpc_offering(vpc_off)
|
|
self.cleanup.append(vpc_off)
|
|
|
|
return vpc_off
|
|
|
|
@attr(tags=["advanced"], required_hardware="true")
|
|
def test_01_vpc_site2site_vpn_multiple_options(self):
|
|
"""Test Site 2 Site VPN Across VPCs"""
|
|
self.logger.debug("Starting test: test_01_vpc_site2site_vpn_multiple_options")
|
|
# 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")
|
|
|
|
# Create and Enable VPC offering
|
|
vpc_offering = self._create_vpc_offering('vpc_offering')
|
|
self.assert_(vpc_offering is not None, "Failed to create VPC Offering")
|
|
vpc_offering.update(self.apiclient, state='Enabled')
|
|
|
|
vpc1 = None
|
|
# Create VPC 1
|
|
try:
|
|
vpc1 = VPC.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["vpc"],
|
|
networkDomain="vpc1.vpn",
|
|
vpcofferingid=vpc_offering.id,
|
|
zoneid=self.zone.id,
|
|
account=self.account.name,
|
|
domainid=self.domain.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vpc1 is not None, "VPC1 creation failed")
|
|
|
|
self.logger.debug("VPC1 %s created" % vpc1.id)
|
|
|
|
vpc2 = None
|
|
# Create VPC 2
|
|
try:
|
|
vpc2 = VPC.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["vpc2"],
|
|
networkDomain="vpc2.vpn",
|
|
vpcofferingid=vpc_offering.id,
|
|
zoneid=self.zone.id,
|
|
account=self.account.name,
|
|
domainid=self.domain.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vpc2 is not None, "VPC2 creation failed")
|
|
|
|
self.logger.debug("VPC2 %s created" % vpc2.id)
|
|
|
|
default_acl = NetworkACLList.list(
|
|
self.apiclient, name="default_allow")[0]
|
|
|
|
ntwk1 = None
|
|
# Create network in VPC 1
|
|
try:
|
|
ntwk1 = Network.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["network_1"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=networkOffering[0].id,
|
|
zoneid=self.zone.id,
|
|
vpcid=vpc1.id,
|
|
aclid=default_acl.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assertIsNotNone(ntwk1, "Network failed to create")
|
|
|
|
self.logger.debug("Network %s created in VPC %s" % (ntwk1.id, vpc1.id))
|
|
|
|
ntwk2 = None
|
|
# Create network in VPC 2
|
|
try:
|
|
ntwk2 = Network.create(
|
|
apiclient=self.apiclient,
|
|
services=self.services["network_2"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=networkOffering[0].id,
|
|
zoneid=self.zone.id,
|
|
vpcid=vpc2.id,
|
|
aclid=default_acl.id
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assertIsNotNone(ntwk2, "Network failed to create")
|
|
|
|
self.logger.debug("Network %s created in VPC %s" % (ntwk2.id, vpc2.id))
|
|
|
|
vm1 = None
|
|
# Deploy a vm in network 2
|
|
try:
|
|
vm1 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
zoneid=self.zone.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.compute_offering.id,
|
|
networkids=ntwk1.id,
|
|
hypervisor=self.hypervisor
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(vm1 is not None, "VM failed to deploy")
|
|
self.assert_(vm1.state == 'Running', "VM is not running")
|
|
|
|
self.logger.debug("VM %s deployed in VPC %s" % (vm1.id, vpc1.id))
|
|
|
|
vm2 = None
|
|
# Deploy a vm in network 2
|
|
try:
|
|
vm2 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
zoneid=self.zone.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.compute_offering.id,
|
|
networkids=ntwk2.id,
|
|
hypervisor=self.hypervisor
|
|
)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
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))
|
|
|
|
# default config
|
|
config = {
|
|
'ike_enc' :'aes128',
|
|
'ike_hash' :'sha1',
|
|
'ike_dh' :'modp1536',
|
|
'esp_enc' :'aes128',
|
|
'esp_hash' :'sha1',
|
|
'esp_pfs' :'modp1536',
|
|
'psk' :'secreatKey',
|
|
'ike_life' :86400,
|
|
'esp_life' :3600,
|
|
'dpd' :True,
|
|
'force_encap' :False,
|
|
'passive_1' :False,
|
|
'passive_2' :False
|
|
}
|
|
test_confs = [
|
|
{}, # default
|
|
{'force_encap': True},
|
|
{'ike_life': ''},
|
|
{'esp_life': ''},
|
|
{'ike_life': '', 'esp_life': ''},
|
|
{'passive_1': True, 'passive_2': True},
|
|
{'passive_1': False, 'passive_2': True},
|
|
{'passive_1': True, 'passive_2': False},
|
|
{'passive_1': False, 'passive_2': False, 'dpd': False},
|
|
{'passive_1': True, 'passive_2': True, 'dpd': False},
|
|
{'passive_1': True, 'passive_2': False, 'dpd': False},
|
|
{'passive_1': False, 'passive_2': True, 'dpd': False},
|
|
{'passive_1': True, 'passive_2': False, 'esp_pfs': ''},
|
|
{'ike_dh': 'modp3072', 'ike_hash': 'sha256', 'esp_pfs': 'modp2048', 'esp_hash':'sha384'},
|
|
{'ike_dh': 'modp4096', 'ike_hash': 'sha384', 'esp_pfs': 'modp6144', 'esp_hash':'sha512'},
|
|
{'ike_dh': 'modp8192', 'ike_hash': 'sha512', 'esp_pfs': 'modp8192', 'esp_hash':'sha384'}
|
|
]
|
|
|
|
# 4) Enable Site-to-Site VPN for VPC
|
|
vpn1_response = Vpn.createVpnGateway(self.apiclient, vpc1.id)
|
|
self.assert_(
|
|
vpn1_response is not None, "Failed to enable VPN Gateway 1")
|
|
self.logger.debug("VPN gateway for VPC %s enabled" % vpc1.id)
|
|
|
|
vpn2_response = Vpn.createVpnGateway(self.apiclient, vpc2.id)
|
|
self.assert_(
|
|
vpn2_response is not None, "Failed to enable VPN Gateway 2")
|
|
self.logger.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]
|
|
|
|
# acquire an extra ip address to use to ssh into vm2
|
|
try:
|
|
vm2.public_ip = PublicIPAddress.create(
|
|
apiclient=self.apiclient,
|
|
accountid=self.account.name,
|
|
zoneid=self.zone.id,
|
|
domainid=self.account.domainid,
|
|
services=self.services,
|
|
networkid=ntwk2.id,
|
|
vpcid=vpc2.id)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(
|
|
vm2.public_ip is not None, "Failed to aqcuire public ip for vm2")
|
|
|
|
natrule = None
|
|
# Create port forward to be able to ssh into vm2
|
|
try:
|
|
natrule = self._create_natrule(
|
|
vpc2, vm2, 22, 22, vm2.public_ip, ntwk2)
|
|
except Exception as e:
|
|
self.fail(e)
|
|
finally:
|
|
self.assert_(
|
|
natrule is not None, "Failed to create portforward for vm2")
|
|
time.sleep(20)
|
|
|
|
# setup ssh connection to vm2
|
|
ssh_client = self._get_ssh_client(vm2, self.services, 10)
|
|
if not ssh_client:
|
|
self.fail("Failed to setup ssh connection to %s" % vm2.public_ip)
|
|
|
|
for test_c in test_confs:
|
|
c = config.copy()
|
|
c.update(test_c)
|
|
services = self._get_vpn_config(c)
|
|
self.logger.debug(services)
|
|
customer1_response = VpnCustomerGateway.create(
|
|
self.apiclient,
|
|
services,
|
|
"Peer VPC1",
|
|
ip1.ipaddress,
|
|
vpc1.cidr,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid)
|
|
self.logger.debug("VPN customer gateway added for VPC %s enabled" % vpc1.id)
|
|
|
|
customer2_response = VpnCustomerGateway.create(
|
|
self.apiclient,
|
|
services,
|
|
"Peer VPC2",
|
|
ip2.ipaddress,
|
|
vpc2.cidr,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid)
|
|
self.logger.debug("VPN customer gateway added for VPC %s enabled" % vpc2.id)
|
|
|
|
# 6) Connect two VPCs
|
|
vpnconn1_response = Vpn.createVpnConnection(
|
|
self.apiclient, customer1_response.id, vpn2_response['id'], c['passive_1'])
|
|
self.logger.debug("VPN connection created for VPC %s" % vpc2.id)
|
|
time.sleep(5)
|
|
vpnconn2_response = Vpn.createVpnConnection(
|
|
self.apiclient, customer2_response.id, vpn1_response['id'], c['passive_2'])
|
|
self.logger.debug("VPN connection created for VPC %s" % vpc1.id)
|
|
|
|
def checkVpnConnected():
|
|
connections = Vpn.listVpnConnection(
|
|
self.apiclient,
|
|
listall='true',
|
|
vpcid=vpc2.id)
|
|
if isinstance(connections, list):
|
|
return connections[0].state == 'Connected', None
|
|
return False, None
|
|
|
|
# Wait up to 60 seconds for passive connection to show up as Connected
|
|
res, _ = wait_until(2, 30, checkVpnConnected)
|
|
if not res:
|
|
self.logger.debug("Failed to see VPN state as Connected, we'll attempt ssh+pinging")
|
|
|
|
# run ping test
|
|
packet_loss = ssh_client.execute("/bin/ping -c 3 -t 10 " + vm1.nic[0].ipaddress + " | grep packet | sed 's/.*received, //g' | sed 's/[% ]*packet.*//g'")[0]
|
|
self.logger.debug("Packet loss %s" % packet_loss)
|
|
self.assert_(int(packet_loss) < 50, "Ping did not succeed")
|
|
|
|
# Cleanup
|
|
Vpn.deleteVpnConnection(self.apiclient, vpnconn1_response['id'])
|
|
Vpn.deleteVpnConnection(self.apiclient, vpnconn2_response['id'])
|
|
customer1_response.delete(self.apiclient)
|
|
customer2_response.delete(self.apiclient)
|
|
|
|
def _get_vpn_config(self, c):
|
|
ike_policy = '%s-%s;%s' % (c['ike_enc'], c['ike_hash'], c['ike_dh']) if c['ike_dh'] else '%s-%s' % (c['ike_enc'], c['ike_hash'])
|
|
esp_policy = '%s-%s;%s' % (c['esp_enc'], c['esp_hash'], c['esp_pfs']) if c['esp_pfs'] else '%s-%s' % (c['esp_enc'], c['esp_hash'])
|
|
out = {
|
|
'ipsecpsk': c['psk'],
|
|
'ikepolicy':ike_policy,
|
|
'esppolicy':esp_policy,
|
|
'dpd':c['dpd'],
|
|
'forceencap':c['force_encap']
|
|
}
|
|
if c['ike_life']:
|
|
out['ikelifetime'] = c['ike_life']
|
|
if c['esp_life']:
|
|
out['esplifetime'] = c['esp_life']
|
|
return out
|
|
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
cleanup_resources(cls.apiclient, cls.cleanup)
|
|
except Exception, e:
|
|
raise Exception("Cleanup failed with %s" % e)
|