create default vpc

check if default vpc exists, create if not,
use it in describe_vpcs function,
fix unit test
add unit tests for default vpc creation

Change-Id: I32411c55a9877854ef11e52f082496bb6656291f
This commit is contained in:
tikitavi 2016-12-16 19:26:51 +03:00
parent 4bbd243f47
commit 449f7c741c
4 changed files with 104 additions and 27 deletions

View File

@ -482,6 +482,18 @@ def get_attached_gateway(context, vpc_id, gateway_kind):
if gw['vpc_id'] == vpc_id), None)
_check_and_create_default_vpc = None
def check_and_create_default_vpc(context):
return _check_and_create_default_vpc(context)
def set_check_and_create_default_vpc(check_and_create_default_vpc):
global _check_and_create_default_vpc
_check_and_create_default_vpc = check_and_create_default_vpc
# NOTE(ft): following functions are copied from various parts of Nova
_ephemeral = re.compile('^ephemeral(\d|[1-9]\d+)$')

View File

@ -40,27 +40,11 @@ LOG = logging.getLogger(__name__)
Validator = common.Validator
DEFAULT_VPC_CIDR_BLOCK = '172.31.0.0/16'
def create_vpc(context, cidr_block, instance_tenancy='default'):
neutron = clients.neutron(context)
with common.OnCrashCleaner() as cleaner:
os_router_body = {'router': {}}
try:
os_router = neutron.create_router(os_router_body)['router']
except neutron_exception.OverQuotaClient:
raise exception.VpcLimitExceeded()
cleaner.addCleanup(neutron.delete_router, os_router['id'])
vpc = db_api.add_item(context, 'vpc',
{'os_id': os_router['id'],
'cidr_block': cidr_block})
cleaner.addCleanup(db_api.delete_item, context, vpc['id'])
route_table = route_table_api._create_route_table(context, vpc)
cleaner.addCleanup(route_table_api._delete_route_table,
context, route_table['id'])
vpc['route_table_id'] = route_table['id']
db_api.update_item(context, vpc)
neutron.update_router(os_router['id'], {'router': {'name': vpc['id']}})
security_group_api._create_default_security_group(context, vpc)
vpc = _create_vpc(context, cidr_block)
return {'vpc': _format_vpc(vpc)}
@ -130,15 +114,49 @@ class VpcDescriber(common.TaggableItemsDescriber,
def describe_vpcs(context, vpc_id=None, filter=None):
_check_and_create_default_vpc(context)
formatted_vpcs = VpcDescriber().describe(
context, ids=vpc_id, filter=filter)
return {'vpcSet': formatted_vpcs}
def _create_vpc(context, cidr_block, is_default=False):
neutron = clients.neutron(context)
with common.OnCrashCleaner() as cleaner:
os_router_body = {'router': {}}
try:
os_router = neutron.create_router(os_router_body)['router']
except neutron_exception.OverQuotaClient:
raise exception.VpcLimitExceeded()
cleaner.addCleanup(neutron.delete_router, os_router['id'])
vpc = db_api.add_item(context, 'vpc',
{'os_id': os_router['id'],
'cidr_block': cidr_block,
'is_default': is_default})
cleaner.addCleanup(db_api.delete_item, context, vpc['id'])
route_table = route_table_api._create_route_table(context, vpc)
cleaner.addCleanup(route_table_api._delete_route_table,
context, route_table['id'])
vpc['route_table_id'] = route_table['id']
db_api.update_item(context, vpc)
neutron.update_router(os_router['id'], {'router': {'name': vpc['id']}})
security_group_api._create_default_security_group(context, vpc)
return vpc
def _check_and_create_default_vpc(context):
if not any(vpc.get('is_default')
for vpc in db_api.get_items(context, 'vpc')):
_create_vpc(context, DEFAULT_VPC_CIDR_BLOCK, is_default=True)
ec2utils.set_check_and_create_default_vpc(_check_and_create_default_vpc)
def _format_vpc(vpc):
return {'vpcId': vpc['id'],
'state': "available",
'cidrBlock': vpc['cidr_block'],
'isDefault': False,
'isDefault': vpc.get('is_default', False),
'dhcpOptionsId': vpc.get('dhcp_options_id', 'default'),
}

View File

@ -53,11 +53,14 @@ TIME_ATTACH_NETWORK_INTERFACE = timeutils.isotime(None, True)
MAC_ADDRESS = 'fb:10:2e:b2:ba:b7'
# vpc constants
ID_EC2_VPC_DEFAULT = random_ec2_id('vpc')
ID_EC2_VPC_1 = random_ec2_id('vpc')
ID_EC2_VPC_2 = random_ec2_id('vpc')
ID_OS_ROUTER_DEFAULT = random_os_id()
ID_OS_ROUTER_1 = random_os_id()
ID_OS_ROUTER_2 = random_os_id()
CIDR_VPC_DEFAULT = '172.31.0.0/16'
CIDR_VPC_1 = '10.10.0.0/16'
CIDR_VPC_2 = '10.20.0.0/16'
ID_OS_PUBLIC_NETWORK = random_os_id()
@ -156,6 +159,7 @@ NAME_DEFAULT_OS_SECURITY_GROUP = 'default'
# route table constants
ID_EC2_ROUTE_TABLE_DEFAULT = random_ec2_id('rtb')
ID_EC2_ROUTE_TABLE_1 = random_ec2_id('rtb')
ID_EC2_ROUTE_TABLE_2 = random_ec2_id('rtb')
ID_EC2_ROUTE_TABLE_3 = random_ec2_id('rtb')
@ -377,9 +381,16 @@ CUSTOMER_GATEWAY_CONFIGURATION_2 = etree.tostring(
# vpc objects
# 2 vpcs in normal state
DB_VPC_DEFAULT = {'id': ID_EC2_VPC_DEFAULT,
'os_id': ID_OS_ROUTER_DEFAULT,
'vpc_id': None,
'is_default': True,
'cidr_block': CIDR_VPC_DEFAULT,
'route_table_id': ID_EC2_ROUTE_TABLE_DEFAULT}
DB_VPC_1 = {'id': ID_EC2_VPC_1,
'os_id': ID_OS_ROUTER_1,
'vpc_id': None,
'is_default': False,
'cidr_block': CIDR_VPC_1,
'route_table_id': ID_EC2_ROUTE_TABLE_1}
DB_VPC_2 = {'id': ID_EC2_VPC_2,
@ -387,6 +398,11 @@ DB_VPC_2 = {'id': ID_EC2_VPC_2,
'vpc_id': None,
'cidr_block': CIDR_VPC_2}
EC2_VPC_DEFAULT = {'vpcId': ID_EC2_VPC_DEFAULT,
'cidrBlock': CIDR_VPC_DEFAULT,
'isDefault': True,
'state': 'available',
'dhcpOptionsId': 'default'}
EC2_VPC_1 = {'vpcId': ID_EC2_VPC_1,
'cidrBlock': CIDR_VPC_1,
'isDefault': False,
@ -398,6 +414,9 @@ EC2_VPC_2 = {'vpcId': ID_EC2_VPC_2,
'state': 'available',
'dhcpOptionsId': 'default'}
OS_ROUTER_DEFAULT = {'id': ID_OS_ROUTER_DEFAULT,
'name': ID_EC2_VPC_DEFAULT,
'external_gateway_info': None}
OS_ROUTER_1 = {'id': ID_OS_ROUTER_1,
'name': ID_EC2_VPC_1,
'external_gateway_info': {
@ -1159,6 +1178,13 @@ EC2_NOVA_SECURITY_GROUP_2 = {
# route table objects
DB_ROUTE_TABLE_DEFAULT = {
'id': ID_EC2_ROUTE_TABLE_DEFAULT,
'vpc_id': ID_EC2_VPC_DEFAULT,
'routes': [{'destination_cidr_block': CIDR_VPC_DEFAULT,
'gateway_id': None}],
}
DB_ROUTE_TABLE_1 = {
'id': ID_EC2_ROUTE_TABLE_1,
'vpc_id': ID_EC2_VPC_1,

View File

@ -218,14 +218,16 @@ class VpcTestCase(base.ApiTestCase):
def test_describe_vpcs(self):
self.neutron.list_routers.return_value = (
{'routers': [fakes.OS_ROUTER_1, fakes.OS_ROUTER_2]})
self.set_mock_db_items(fakes.DB_VPC_1, fakes.DB_VPC_2)
{'routers': [fakes.OS_ROUTER_DEFAULT,
fakes.OS_ROUTER_1, fakes.OS_ROUTER_2]})
self.set_mock_db_items(fakes.DB_VPC_DEFAULT,
fakes.DB_VPC_1, fakes.DB_VPC_2)
resp = self.execute('DescribeVpcs', {})
self.assertThat(resp['vpcSet'],
matchers.ListMatches([fakes.EC2_VPC_1,
matchers.ListMatches([fakes.EC2_VPC_DEFAULT,
fakes.EC2_VPC_1,
fakes.EC2_VPC_2]))
self.db_api.get_items.assert_called_once_with(mock.ANY, 'vpc')
resp = self.execute('DescribeVpcs',
{'VpcId.1': fakes.ID_EC2_VPC_1})
@ -247,10 +249,29 @@ class VpcTestCase(base.ApiTestCase):
def test_describe_vpcs_no_router(self):
self.neutron.list_routers.return_value = {'routers': []}
self.set_mock_db_items(fakes.DB_VPC_1)
self.set_mock_db_items(fakes.DB_VPC_DEFAULT, fakes.DB_VPC_1)
resp = self.execute('DescribeVpcs', {})
self.assertThat(resp['vpcSet'],
matchers.ListMatches([fakes.EC2_VPC_1]))
self.db_api.get_items.assert_called_once_with(mock.ANY, 'vpc')
matchers.ListMatches([fakes.EC2_VPC_DEFAULT,
fakes.EC2_VPC_1]))
@mock.patch('ec2api.api.vpc._check_and_create_default_vpc')
def test_describe_vpcs_no_default_vpc(self, check_and_create):
def mock_check_and_create(context):
self.set_mock_db_items(fakes.DB_VPC_DEFAULT)
check_and_create.side_effect = mock_check_and_create
resp = self.execute('DescribeVpcs', {})
self.assertEqual(resp['vpcSet'], [fakes.EC2_VPC_DEFAULT])
check_and_create.assert_called_once_with(mock.ANY)
def test_describe_vpcs_with_default_vpc(self):
self.set_mock_db_items(fakes.DB_VPC_DEFAULT)
resp = self.execute('DescribeVpcs', {})
self.assertEqual(resp['vpcSet'], [fakes.EC2_VPC_DEFAULT])
self.db_api.add_item.assert_not_called()