Merge "create default vpc"
This commit is contained in:
commit
e9775c4047
|
@ -482,6 +482,18 @@ def get_attached_gateway(context, vpc_id, gateway_kind):
|
||||||
if gw['vpc_id'] == vpc_id), None)
|
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
|
# NOTE(ft): following functions are copied from various parts of Nova
|
||||||
|
|
||||||
_ephemeral = re.compile('^ephemeral(\d|[1-9]\d+)$')
|
_ephemeral = re.compile('^ephemeral(\d|[1-9]\d+)$')
|
||||||
|
|
|
@ -40,27 +40,11 @@ LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
Validator = common.Validator
|
Validator = common.Validator
|
||||||
|
|
||||||
|
DEFAULT_VPC_CIDR_BLOCK = '172.31.0.0/16'
|
||||||
|
|
||||||
|
|
||||||
def create_vpc(context, cidr_block, instance_tenancy='default'):
|
def create_vpc(context, cidr_block, instance_tenancy='default'):
|
||||||
neutron = clients.neutron(context)
|
vpc = _create_vpc(context, cidr_block)
|
||||||
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)
|
|
||||||
return {'vpc': _format_vpc(vpc)}
|
return {'vpc': _format_vpc(vpc)}
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,15 +114,49 @@ class VpcDescriber(common.TaggableItemsDescriber,
|
||||||
|
|
||||||
|
|
||||||
def describe_vpcs(context, vpc_id=None, filter=None):
|
def describe_vpcs(context, vpc_id=None, filter=None):
|
||||||
|
_check_and_create_default_vpc(context)
|
||||||
formatted_vpcs = VpcDescriber().describe(
|
formatted_vpcs = VpcDescriber().describe(
|
||||||
context, ids=vpc_id, filter=filter)
|
context, ids=vpc_id, filter=filter)
|
||||||
return {'vpcSet': formatted_vpcs}
|
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):
|
def _format_vpc(vpc):
|
||||||
return {'vpcId': vpc['id'],
|
return {'vpcId': vpc['id'],
|
||||||
'state': "available",
|
'state': "available",
|
||||||
'cidrBlock': vpc['cidr_block'],
|
'cidrBlock': vpc['cidr_block'],
|
||||||
'isDefault': False,
|
'isDefault': vpc.get('is_default', False),
|
||||||
'dhcpOptionsId': vpc.get('dhcp_options_id', 'default'),
|
'dhcpOptionsId': vpc.get('dhcp_options_id', 'default'),
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,11 +53,14 @@ TIME_ATTACH_NETWORK_INTERFACE = timeutils.isotime(None, True)
|
||||||
MAC_ADDRESS = 'fb:10:2e:b2:ba:b7'
|
MAC_ADDRESS = 'fb:10:2e:b2:ba:b7'
|
||||||
|
|
||||||
# vpc constants
|
# vpc constants
|
||||||
|
ID_EC2_VPC_DEFAULT = random_ec2_id('vpc')
|
||||||
ID_EC2_VPC_1 = random_ec2_id('vpc')
|
ID_EC2_VPC_1 = random_ec2_id('vpc')
|
||||||
ID_EC2_VPC_2 = 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_1 = random_os_id()
|
||||||
ID_OS_ROUTER_2 = 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_1 = '10.10.0.0/16'
|
||||||
CIDR_VPC_2 = '10.20.0.0/16'
|
CIDR_VPC_2 = '10.20.0.0/16'
|
||||||
ID_OS_PUBLIC_NETWORK = random_os_id()
|
ID_OS_PUBLIC_NETWORK = random_os_id()
|
||||||
|
@ -156,6 +159,7 @@ NAME_DEFAULT_OS_SECURITY_GROUP = 'default'
|
||||||
|
|
||||||
|
|
||||||
# route table constants
|
# 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_1 = random_ec2_id('rtb')
|
||||||
ID_EC2_ROUTE_TABLE_2 = random_ec2_id('rtb')
|
ID_EC2_ROUTE_TABLE_2 = random_ec2_id('rtb')
|
||||||
ID_EC2_ROUTE_TABLE_3 = 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
|
# vpc objects
|
||||||
# 2 vpcs in normal state
|
# 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,
|
DB_VPC_1 = {'id': ID_EC2_VPC_1,
|
||||||
'os_id': ID_OS_ROUTER_1,
|
'os_id': ID_OS_ROUTER_1,
|
||||||
'vpc_id': None,
|
'vpc_id': None,
|
||||||
|
'is_default': False,
|
||||||
'cidr_block': CIDR_VPC_1,
|
'cidr_block': CIDR_VPC_1,
|
||||||
'route_table_id': ID_EC2_ROUTE_TABLE_1}
|
'route_table_id': ID_EC2_ROUTE_TABLE_1}
|
||||||
DB_VPC_2 = {'id': ID_EC2_VPC_2,
|
DB_VPC_2 = {'id': ID_EC2_VPC_2,
|
||||||
|
@ -387,6 +398,11 @@ DB_VPC_2 = {'id': ID_EC2_VPC_2,
|
||||||
'vpc_id': None,
|
'vpc_id': None,
|
||||||
'cidr_block': CIDR_VPC_2}
|
'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,
|
EC2_VPC_1 = {'vpcId': ID_EC2_VPC_1,
|
||||||
'cidrBlock': CIDR_VPC_1,
|
'cidrBlock': CIDR_VPC_1,
|
||||||
'isDefault': False,
|
'isDefault': False,
|
||||||
|
@ -398,6 +414,9 @@ EC2_VPC_2 = {'vpcId': ID_EC2_VPC_2,
|
||||||
'state': 'available',
|
'state': 'available',
|
||||||
'dhcpOptionsId': 'default'}
|
'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,
|
OS_ROUTER_1 = {'id': ID_OS_ROUTER_1,
|
||||||
'name': ID_EC2_VPC_1,
|
'name': ID_EC2_VPC_1,
|
||||||
'external_gateway_info': {
|
'external_gateway_info': {
|
||||||
|
@ -1159,6 +1178,13 @@ EC2_NOVA_SECURITY_GROUP_2 = {
|
||||||
|
|
||||||
|
|
||||||
# route table objects
|
# 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 = {
|
DB_ROUTE_TABLE_1 = {
|
||||||
'id': ID_EC2_ROUTE_TABLE_1,
|
'id': ID_EC2_ROUTE_TABLE_1,
|
||||||
'vpc_id': ID_EC2_VPC_1,
|
'vpc_id': ID_EC2_VPC_1,
|
||||||
|
|
|
@ -218,14 +218,16 @@ class VpcTestCase(base.ApiTestCase):
|
||||||
|
|
||||||
def test_describe_vpcs(self):
|
def test_describe_vpcs(self):
|
||||||
self.neutron.list_routers.return_value = (
|
self.neutron.list_routers.return_value = (
|
||||||
{'routers': [fakes.OS_ROUTER_1, fakes.OS_ROUTER_2]})
|
{'routers': [fakes.OS_ROUTER_DEFAULT,
|
||||||
self.set_mock_db_items(fakes.DB_VPC_1, fakes.DB_VPC_2)
|
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', {})
|
resp = self.execute('DescribeVpcs', {})
|
||||||
self.assertThat(resp['vpcSet'],
|
self.assertThat(resp['vpcSet'],
|
||||||
matchers.ListMatches([fakes.EC2_VPC_1,
|
matchers.ListMatches([fakes.EC2_VPC_DEFAULT,
|
||||||
|
fakes.EC2_VPC_1,
|
||||||
fakes.EC2_VPC_2]))
|
fakes.EC2_VPC_2]))
|
||||||
self.db_api.get_items.assert_called_once_with(mock.ANY, 'vpc')
|
|
||||||
|
|
||||||
resp = self.execute('DescribeVpcs',
|
resp = self.execute('DescribeVpcs',
|
||||||
{'VpcId.1': fakes.ID_EC2_VPC_1})
|
{'VpcId.1': fakes.ID_EC2_VPC_1})
|
||||||
|
@ -247,10 +249,29 @@ class VpcTestCase(base.ApiTestCase):
|
||||||
|
|
||||||
def test_describe_vpcs_no_router(self):
|
def test_describe_vpcs_no_router(self):
|
||||||
self.neutron.list_routers.return_value = {'routers': []}
|
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', {})
|
resp = self.execute('DescribeVpcs', {})
|
||||||
|
|
||||||
self.assertThat(resp['vpcSet'],
|
self.assertThat(resp['vpcSet'],
|
||||||
matchers.ListMatches([fakes.EC2_VPC_1]))
|
matchers.ListMatches([fakes.EC2_VPC_DEFAULT,
|
||||||
self.db_api.get_items.assert_called_once_with(mock.ANY, 'vpc')
|
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()
|
||||||
|
|
Loading…
Reference in New Issue