ec2-api/ec2api/tests/functional/obsolete/thirdparty/scenario/aws_compat/test_vpc_scenario.py

380 lines
16 KiB
Python

# Copyright 2014
# The Cloudscaling Group, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import netaddr
import tempest.cloudscaling.thirdparty.scenario.aws_compat.base as aws_base
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils.linux import remote_client
from tempest import test
import logging
logging.getLogger('boto').setLevel(logging.CRITICAL)
class VPC_Scenario(aws_base.BaseAWSTest):
"""
Reproduce 'VPC with Public and Private Subnets' scenario
(http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Scenario2.html)
"""
class Context(object):
vpc = None
internet_gateway = None
web_subnet = None
db_subnet = None
main_route_table = None
custom_route_table = None
web_security_group = None
nat_security_group = None
db_security_group = None
web_instance = None
db_instance = None
nat_instance = None
@classmethod
@test.safe_setup
def setUpClass(cls):
super(VPC_Scenario, cls).setUpClass()
cls.ctx = cls.Context()
cls.zone = cls.config.boto.aws_zone
cfg = cls.config.cloudscaling
cls.ssh_user = cfg.general_ssh_user_name
cls.vpc_cidr = netaddr.IPNetwork(cfg.vpc_cidr)
cls.web_subnet, cls.db_subnet = cls.vpc_cidr.subnet(
cfg.vpc_subnet_prefix, 2)
cls.test_client_cidr = netaddr.IPNetwork(cfg.test_client_cidr)
cls.image_id = cls._prepare_image_id(cfg.general_image_name)
cls.keypair = cls._prepare_key_pair()
@classmethod
def tearDownClass(cls):
if cls.ctx is not None:
for group in [cls.ctx.web_security_group,
cls.ctx.nat_security_group,
cls.ctx.db_security_group]:
if not group:
continue
try:
cls._revoke_security_group_linked_rules(group)
except Exception:
pass
super(VPC_Scenario, cls).tearDownClass()
@classmethod
def _revoke_security_group_linked_rules(cls, group):
groups = cls.vpc_client.get_all_security_groups(group_ids=[group.id])
if len(groups) == 0:
return
sg = groups[0]
for rule in sg.rules:
for grant in rule.grants:
if not grant.cidr_ip:
cls.vpc_client.revoke_security_group(
group_id=sg.id,
ip_protocol=rule.ip_protocol,
from_port=rule.from_port,
to_port=rule.to_port,
src_security_group_group_id=grant.groupId)
for rule in sg.rules_egress:
for grant in rule.grants:
if not grant.cidr_ip:
cls.vpc_client.revoke_security_group_egress(
sg.id,
rule.ip_protocol,
from_port=rule.from_port,
to_port=rule.to_port,
src_group_id=grant.groupId)
def test_000_create_vpc(self):
"""Create VPC"""
vpc = self.vpc_client.create_vpc(str(self.vpc_cidr))
self.assertIsNotNone(vpc)
self.assertTrue(vpc.id)
self.addResourceCleanUp(self.vpc_client.delete_vpc, vpc.id)
self.ctx.vpc = vpc
def test_001_create_internet_gateway(self):
"""Create internet gateway"""
ig = self.vpc_client.create_internet_gateway()
self.assertIsNotNone(ig)
self.assertTrue(ig.id)
self.addResourceCleanUp(self._destroy_internet_gateway, ig)
status = self.vpc_client.attach_internet_gateway(ig.id,
self.ctx.vpc.id)
self.assertTrue(status)
self.ctx.internet_gateway = ig
def test_010_create_subnets(self):
"""Create subnets"""
sn = self.vpc_client.create_subnet(self.ctx.vpc.id,
str(self.web_subnet),
self.zone)
self.assertIsNotNone(sn)
self.assertTrue(sn.id)
self.addResourceCleanUp(self.vpc_client.delete_subnet, sn.id)
self.ctx.web_subnet = sn
sn = self.vpc_client.create_subnet(self.ctx.vpc.id,
str(self.db_subnet),
self.zone)
self.assertIsNotNone(sn)
self.assertTrue(sn.id)
self.addResourceCleanUp(self.vpc_client.delete_subnet, sn.id)
self.ctx.db_subnet = sn
def test_020_get_main_route_table(self):
"""Describe auto created route table"""
rtables = self.vpc_client.get_all_route_tables(
filters=[("vpc-id", self.ctx.vpc.id)])
self.assertIsNotNone(rtables)
self.assertEqual(1, len(rtables))
self.ctx.main_route_table = rtables[0]
def test_025_create_custom_route_table(self):
"""Create route table for web servers"""
rtable = self.vpc_client.create_route_table(self.ctx.vpc.id)
self.assertIsNotNone(rtable)
self.assertTrue(rtable.id)
self.addResourceCleanUp(self.vpc_client.delete_route_table, rtable.id)
ig = self.ctx.internet_gateway
status = self.vpc_client.create_route(rtable.id, "0.0.0.0/0",
gateway_id=ig.id)
self.assertTrue(status)
association_id = self.vpc_client.associate_route_table(
rtable.id, self.ctx.web_subnet.id)
self.assertTrue(association_id)
self.addResourceCleanUp(self.vpc_client.disassociate_route_table,
association_id)
self.ctx.custom_route_table = rtable
def test_050_create_security_groups(self):
"""Create and tune security groups"""
sg = self.vpc_client.create_security_group(
data_utils.rand_name("WebServerSG-"),
data_utils.rand_name("description "),
self.ctx.vpc.id)
self.assertIsNotNone(sg)
self.assertTrue(sg.id)
self.addResourceCleanUp(self._destroy_security_group_wait, sg)
self.ctx.web_security_group = sg
sg = self.vpc_client.create_security_group(
data_utils.rand_name("NATSG-"),
data_utils.rand_name("description "),
self.ctx.vpc.id)
self.assertIsNotNone(sg)
self.assertTrue(sg.id)
self.addResourceCleanUp(self._destroy_security_group_wait, sg)
self.ctx.nat_security_group = sg
sg = self.vpc_client.create_security_group(
data_utils.rand_name("DBServerSG-"),
data_utils.rand_name("description "),
self.ctx.vpc.id)
self.assertIsNotNone(sg)
self.assertTrue(sg.id)
self.addResourceCleanUp(self._destroy_security_group_wait, sg)
self.ctx.db_security_group = sg
sg = self.ctx.web_security_group
status = self.vpc_client.revoke_security_group_egress(
sg.id, "-1", cidr_ip="0.0.0.0/0")
self.assertTrue(status)
status = self.vpc_client.authorize_security_group_egress(
sg.id, "tcp", 1433, 1433,
src_group_id=self.ctx.db_security_group.id)
self.assertTrue(status)
status = self.vpc_client.authorize_security_group_egress(
sg.id, "tcp", 3306, 3306,
src_group_id=self.ctx.db_security_group.id)
self.assertTrue(status)
# NOTE(ft): especially for connectivity test
status = self.vpc_client.authorize_security_group_egress(
sg.id, "tcp", 80, 80, cidr_ip="0.0.0.0/0")
self.assertTrue(status)
# NOTE(ft): especially for connectivity test
status = self.vpc_client.authorize_security_group_egress(
sg.id, "tcp", 22, 22,
src_group_id=self.ctx.db_security_group.id)
self.assertTrue(status)
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp", from_port=80, to_port=80,
cidr_ip="0.0.0.0/0")
self.assertTrue(status)
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp", from_port=443, to_port=443,
cidr_ip="0.0.0.0/0")
self.assertTrue(status)
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp", from_port=22, to_port=22,
cidr_ip=str(self.test_client_cidr))
self.assertTrue(status)
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp", from_port=3389,
to_port=3389, cidr_ip=str(self.test_client_cidr))
self.assertTrue(status)
sg = self.ctx.nat_security_group
status = self.vpc_client.revoke_security_group_egress(
sg.id, "-1", cidr_ip="0.0.0.0/0")
self.assertTrue(status)
status = self.vpc_client.authorize_security_group_egress(
sg.id, "tcp", 80, 80, cidr_ip="0.0.0.0/0")
self.assertTrue(status)
status = self.vpc_client.authorize_security_group_egress(
sg.id, "tcp", 443, 443, cidr_ip="0.0.0.0/0")
self.assertTrue(status)
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp", from_port=80, to_port=80,
cidr_ip=str(self.db_subnet))
self.assertTrue(status)
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp", from_port=443, to_port=443,
cidr_ip=str(self.db_subnet))
self.assertTrue(status)
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp", from_port=22, to_port=22,
cidr_ip=str(self.test_client_cidr))
self.assertTrue(status)
sg = self.ctx.db_security_group
status = self.vpc_client.revoke_security_group_egress(
sg.id, "-1", cidr_ip="0.0.0.0/0")
self.assertTrue(status)
status = self.vpc_client.authorize_security_group_egress(
sg.id, "tcp", 80, 80, cidr_ip="0.0.0.0/0")
self.assertTrue(status)
status = self.vpc_client.authorize_security_group_egress(
sg.id, "tcp", 443, 443, cidr_ip="0.0.0.0/0")
self.assertTrue(status)
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp",
from_port=1433,
to_port=1433,
src_security_group_group_id=self.ctx.web_security_group.id)
self.assertTrue(status)
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp",
from_port=3306,
to_port=3306,
src_security_group_group_id=self.ctx.web_security_group.id)
self.assertTrue(status)
# NOTE(ft): especially for connectivity test
status = self.vpc_client.authorize_security_group(
group_id=sg.id, ip_protocol="tcp",
from_port=22,
to_port=22,
src_security_group_group_id=self.ctx.web_security_group.id)
self.assertTrue(status)
def test_100_launch_nat_instance(self):
"""Launch instances for NAT server"""
reservation = self.vpc_client.run_instances(
self.image_id,
key_name=self.keypair.name,
security_group_ids=[self.ctx.nat_security_group.id],
instance_type=self.instance_type,
placement=self.zone,
subnet_id=self.ctx.web_subnet.id)
self.assertIsNotNone(reservation)
self.addResourceCleanUp(self.destroy_reservation, reservation)
self.assertEqual(1, len(reservation.instances))
instance = reservation.instances[0]
if instance.state != "running":
self.assertInstanceStateWait(instance, "running")
self._prepare_public_ip(instance)
status = self.vpc_client.modify_instance_attribute(
instance.id, 'sourceDestCheck', False)
self.assertTrue(status)
rtable = self.ctx.main_route_table
status = self.vpc_client.create_route(rtable.id, "0.0.0.0/0",
instance_id=instance.id)
self.assertTrue(status)
self.ctx.nat_instance = instance
def test_101_launch_instances(self):
"""Launch instances for web server and db server"""
reservation = self.vpc_client.run_instances(
self.image_id,
key_name=self.keypair.name,
security_group_ids=[self.ctx.web_security_group.id],
instance_type=self.instance_type,
placement=self.zone,
subnet_id=self.ctx.web_subnet.id)
self.assertIsNotNone(reservation)
self.addResourceCleanUp(self.destroy_reservation, reservation)
self.assertEqual(1, len(reservation.instances))
instance = reservation.instances[0]
if instance.state != "running":
self.assertInstanceStateWait(instance, "running")
self._prepare_public_ip(instance)
self.ctx.web_instance = instance
reservation = self.vpc_client.run_instances(
self.image_id,
key_name=self.keypair.name,
security_group_ids=[self.ctx.db_security_group.id],
instance_type=self.instance_type,
placement=self.zone,
subnet_id=self.ctx.db_subnet.id)
self.assertIsNotNone(reservation)
self.addResourceCleanUp(self.destroy_reservation, reservation)
self.assertEqual(1, len(reservation.instances))
instance = reservation.instances[0]
if instance.state != "running":
self.assertInstanceStateWait(instance, "running")
self.ctx.db_instance = instance
def test_102_tune_nat_instance(self):
"""Tune NAT in NAT instance"""
instance = self.ctx.nat_instance
address = instance.ip_address
ssh = remote_client.RemoteClient(address,
self.ssh_user,
pkey=self.keypair.material)
# NOTE(ft): We must use tty mode, because some images (like Amazon
# Linux) has restrictions (requiretty flag in /etc/sudoers)
ssh_conn = ssh.ssh_client._get_ssh_connection()
chan = ssh_conn.get_transport().open_session()
chan.get_pty()
chan.exec_command("sudo iptables -t nat -A POSTROUTING -s %s "
"-o eth0 -j MASQUERADE" % str(self.vpc_cidr))
chan.close()
chan = ssh_conn.get_transport().open_session()
chan.get_pty()
chan.exec_command("sudo sysctl -w net.ipv4.ip_forward=1")
chan.close()
ssh_conn.close()
def test_200_check_connectivity(self):
"""Check inside and outside connectivities"""
web_ip = self.ctx.web_instance.ip_address
db_ip = self.ctx.db_instance.private_ip_address
ssh = remote_client.RemoteClient(web_ip,
self.ssh_user,
pkey=self.keypair.material)
ssh.exec_command("curl -s http://google.com")
ssh_conn = ssh.ssh_client._get_ssh_connection()
sftp = ssh_conn.open_sftp()
fr = sftp.file("key.pem", 'wb')
fr.set_pipelined(True)
fr.write(self.keypair.material)
fr.close()
ssh_conn.close()
ssh.exec_command('chmod 400 key.pem')
ssh.exec_command("ssh -i key.pem -o UserKnownHostsFile=/dev/null "
"-o StrictHostKeyChecking=no %(user)s@%(ip)s "
"curl -s http://google.com" %
{"user": self.ssh_user, "ip": db_ip})