Ensure network AZ and server AZ are the same

Check whether network AZ and server AZ are the same when booting
server if the network is created with AZ specified. API gateway
returns 400 error if the two AZs are different.

Change-Id: Ib43f431a8747915b32d844c3252760c107c9b0d3
Closes-Bug: #1533940
This commit is contained in:
zhiyuan_cai 2016-03-07 15:37:03 +08:00
parent 6ffbcbf5d0
commit 1946cd8544
2 changed files with 74 additions and 0 deletions

View File

@ -294,6 +294,20 @@ class ServerController(rest.RestController):
if remove_index >= 0:
del addresses[remove_index]
@staticmethod
def _check_network_server_the_same_az(network, server_az):
az_hints = 'availability_zone_hints'
# if neutron az not assigned, server az is used
if not network.get(az_hints):
return True
# temporally not support cross-pod network
if len(network[az_hints]) > 1:
return False
if network[az_hints][0] == server_az:
return True
else:
return False
def _get_all(self, context):
ret = []
pods = db_api.list_pods(context)
@ -362,6 +376,13 @@ class ServerController(rest.RestController):
if not network:
pecan.abort(400, 'Network not found')
return
if not self._check_network_server_the_same_az(
network, kw['server']['availability_zone']):
pecan.abort(400, 'Network and server not in the same '
'availability zone')
return
subnets = top_client.list_subnets(
context, [{'key': 'network_id',
'comparator': 'eq',

View File

@ -14,7 +14,9 @@
# under the License.
import datetime
import mock
from mock import patch
import pecan
import unittest
from oslo_utils import uuidutils
@ -433,6 +435,57 @@ class ServerTest(unittest.TestCase):
self.assertEqual(b_pod['pod_id'], routes[0]['pod_id'])
self.assertEqual(self.project_id, routes[0]['project_id'])
@patch.object(pecan, 'abort')
@patch.object(FakeClient, 'create_servers')
@patch.object(context, 'extract_context_from_environ')
def test_post_with_network_az(self, mock_ctx, mock_create, mock_abort):
t_pod, b_pod = self._prepare_pod()
top_net_id = 'top_net_id'
top_subnet_id = 'top_subnet_id'
t_net = {'id': top_net_id}
t_subnet = {'id': top_subnet_id,
'network_id': top_net_id,
'ip_version': 4,
'cidr': '10.0.0.0/24',
'gateway_ip': '10.0.0.1',
'allocation_pools': {'start': '10.0.0.2',
'end': '10.0.0.254'},
'enable_dhcp': True}
TOP_NETS.append(t_net)
TOP_SUBNETS.append(t_subnet)
server_name = 'test_server'
image_id = 'image_id'
flavor_id = 1
body = {
'server': {
'name': server_name,
'imageRef': image_id,
'flavorRef': flavor_id,
'availability_zone': b_pod['az_name'],
'networks': [{'uuid': top_net_id}]
}
}
mock_create.return_value = {'id': 'bottom_server_id'}
mock_ctx.return_value = self.context
# update top net for test purpose, correct az
TOP_NETS[0]['availability_zone_hints'] = ['b_az']
self.controller.post(**body)
# update top net for test purpose, wrong az
TOP_NETS[0]['availability_zone_hints'] = ['fake_az']
self.controller.post(**body)
# update top net for test purpose, correct az and wrong az
TOP_NETS[0]['availability_zone_hints'] = ['b_az', 'fake_az']
self.controller.post(**body)
msg = 'Network and server not in the same availability zone'
# abort two times
calls = [mock.call(400, msg), mock.call(400, msg)]
mock_abort.assert_has_calls(calls)
def tearDown(self):
core.ModelBase.metadata.drop_all(core.get_engine())
for res in RES_LIST: