Pass tempest list_server_filters test
Change the following to pass tempest list_server_filters test: (1) Change response body of Nova API gateway image controller (2) Add network controller (3) Add server list filters support (4) Change response body of server list Change-Id: I96013e2a3c871640b530611e36fa0a219c5e0516
This commit is contained in:
parent
353ebcddb1
commit
e43c4bc656
@ -30,10 +30,11 @@ NONE_DONE = 2 # neither router nor bottom resources exists
|
||||
|
||||
|
||||
def get_or_create_route(t_ctx, q_ctx,
|
||||
project_id, pod, _id, _type, list_ele_method):
|
||||
project_id, pod, ele, _type, list_ele_method):
|
||||
# use configuration option later
|
||||
route_expire_threshold = 30
|
||||
|
||||
_id = ele['id']
|
||||
with t_ctx.session.begin():
|
||||
routes = core.query_resource(
|
||||
t_ctx, models.ResourceRouting,
|
||||
@ -53,7 +54,7 @@ def get_or_create_route(t_ctx, q_ctx,
|
||||
# a race here that other worker is updating this route, we
|
||||
# need to check if the corresponding element has been
|
||||
# created by other worker
|
||||
eles = list_ele_method(t_ctx, q_ctx, pod, _id, _type)
|
||||
eles = list_ele_method(t_ctx, q_ctx, pod, ele, _type)
|
||||
if eles:
|
||||
route['bottom_id'] = eles[0]['id']
|
||||
core.update_resource(t_ctx,
|
||||
@ -92,7 +93,7 @@ def get_or_create_element(t_ctx, q_ctx,
|
||||
max_tries = 5
|
||||
for _ in xrange(max_tries):
|
||||
route, status = get_or_create_route(
|
||||
t_ctx, q_ctx, project_id, pod, ele['id'], _type, list_ele_method)
|
||||
t_ctx, q_ctx, project_id, pod, ele, _type, list_ele_method)
|
||||
if not route:
|
||||
eventlet.sleep(0)
|
||||
continue
|
||||
@ -101,7 +102,7 @@ def get_or_create_element(t_ctx, q_ctx,
|
||||
break
|
||||
if status == NONE_DONE:
|
||||
try:
|
||||
ele = create_ele_method(t_ctx, q_ctx, pod, body, _type)
|
||||
new_ele = create_ele_method(t_ctx, q_ctx, pod, body, _type)
|
||||
except Exception:
|
||||
with t_ctx.session.begin():
|
||||
try:
|
||||
@ -118,7 +119,7 @@ def get_or_create_element(t_ctx, q_ctx,
|
||||
# NOTE(zhiyuan) it's safe to update route, the bottom network
|
||||
# has been successfully created, so other worker will not
|
||||
# delete this route
|
||||
route['bottom_id'] = ele['id']
|
||||
route['bottom_id'] = new_ele['id']
|
||||
core.update_resource(t_ctx, models.ResourceRouting,
|
||||
route['id'], route)
|
||||
break
|
||||
|
@ -112,3 +112,7 @@ def check_string_length(value, name=None, min_len=0, max_len=None):
|
||||
msg = _("%(name)s has more than %(max_length)s "
|
||||
"characters.") % {'name': name, 'max_length': max_len}
|
||||
raise t_exceptions.InvalidInput(message=msg)
|
||||
|
||||
|
||||
def get_bottom_network_name(network):
|
||||
return '%s#%s' % (network['id'], network['name'])
|
||||
|
@ -49,6 +49,7 @@ import tricircle.common.exceptions as t_exceptions
|
||||
from tricircle.common.i18n import _
|
||||
from tricircle.common.i18n import _LI
|
||||
import tricircle.common.lock_handle as t_lock
|
||||
from tricircle.common import utils
|
||||
from tricircle.common import xrpcapi
|
||||
import tricircle.db.api as db_api
|
||||
from tricircle.db import core
|
||||
@ -629,9 +630,9 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
|
||||
def _prepare_top_element(self, t_ctx, q_ctx,
|
||||
project_id, pod, ele, _type, body):
|
||||
def list_resources(t_ctx_, q_ctx_, pod_, _id_, _type_):
|
||||
def list_resources(t_ctx_, q_ctx_, pod_, ele_, _type_):
|
||||
return getattr(self, 'get_%ss' % _type_)(
|
||||
q_ctx_, filters={'name': _id_})
|
||||
q_ctx_, filters={'name': ele_['id']})
|
||||
|
||||
def create_resources(t_ctx_, q_ctx_, pod_, body_, _type_):
|
||||
return getattr(self, 'create_%s' % _type_)(q_ctx_, body_)
|
||||
@ -643,11 +644,15 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
|
||||
def _prepare_bottom_element(self, t_ctx,
|
||||
project_id, pod, ele, _type, body):
|
||||
def list_resources(t_ctx_, q_ctx, pod_, _id_, _type_):
|
||||
def list_resources(t_ctx_, q_ctx, pod_, ele_, _type_):
|
||||
client = self._get_client(pod_['pod_name'])
|
||||
return client.list_resources(_type_, t_ctx_, [{'key': 'name',
|
||||
'comparator': 'eq',
|
||||
'value': _id_}])
|
||||
if _type_ == t_constants.RT_NETWORK:
|
||||
value = utils.get_bottom_network_name(ele_)
|
||||
else:
|
||||
value = ele_['id']
|
||||
return client.list_resources(_type_, t_ctx_,
|
||||
[{'key': 'name', 'comparator': 'eq',
|
||||
'value': value}])
|
||||
|
||||
def create_resources(t_ctx_, q_ctx, pod_, body_, _type_):
|
||||
client = self._get_client(pod_['pod_name'])
|
||||
@ -753,7 +758,7 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
net_body = {
|
||||
'network': {
|
||||
'tenant_id': project_id,
|
||||
'name': t_net['id'],
|
||||
'name': utils.get_bottom_network_name(t_net),
|
||||
'admin_state_up': True
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,52 @@
|
||||
import pecan
|
||||
from pecan import expose
|
||||
from pecan import rest
|
||||
import re
|
||||
import urlparse
|
||||
|
||||
import tricircle.common.client as t_client
|
||||
from tricircle.common import constants
|
||||
import tricircle.common.context as t_context
|
||||
import tricircle.db.api as db_api
|
||||
|
||||
|
||||
def url_join(*parts):
|
||||
"""Convenience method for joining parts of a URL
|
||||
|
||||
Any leading and trailing '/' characters are removed, and the parts joined
|
||||
together with '/' as a separator. If last element of 'parts' is an empty
|
||||
string, the returned URL will have a trailing slash.
|
||||
"""
|
||||
parts = parts or ['']
|
||||
clean_parts = [part.strip('/') for part in parts if part]
|
||||
if not parts[-1]:
|
||||
# Empty last element should add a trailing slash
|
||||
clean_parts.append('')
|
||||
return '/'.join(clean_parts)
|
||||
|
||||
|
||||
def remove_trailing_version_from_href(href):
|
||||
"""Removes the api version from the href.
|
||||
|
||||
Given: 'http://www.nova.com/compute/v1.1'
|
||||
Returns: 'http://www.nova.com/compute'
|
||||
|
||||
Given: 'http://www.nova.com/v1.1'
|
||||
Returns: 'http://www.nova.com'
|
||||
|
||||
"""
|
||||
parsed_url = urlparse.urlsplit(href)
|
||||
url_parts = parsed_url.path.rsplit('/', 1)
|
||||
|
||||
# NOTE: this should match vX.X or vX
|
||||
expression = re.compile(r'^v([0-9]+|[0-9]+\.[0-9]+)(/.*|$)')
|
||||
if not expression.match(url_parts.pop()):
|
||||
raise ValueError('URL %s does not contain version' % href)
|
||||
|
||||
new_path = url_join(*url_parts)
|
||||
parsed_url = list(parsed_url)
|
||||
parsed_url[2] = new_path
|
||||
return urlparse.urlunsplit(parsed_url)
|
||||
|
||||
|
||||
class ImageController(rest.RestController):
|
||||
@ -27,6 +70,72 @@ class ImageController(rest.RestController):
|
||||
self.project_id = project_id
|
||||
self.client = t_client.Client()
|
||||
|
||||
def _get_links(self, context, image):
|
||||
nova_url = self.client.get_endpoint(
|
||||
context, db_api.get_top_pod(context)['pod_id'],
|
||||
constants.ST_NOVA)
|
||||
nova_url = nova_url.replace('/$(tenant_id)s', '')
|
||||
self_link = url_join(nova_url, self.project_id, 'images', image['id'])
|
||||
bookmark_link = url_join(
|
||||
remove_trailing_version_from_href(nova_url),
|
||||
self.project_id, 'images', image['id'])
|
||||
glance_url = self.client.get_endpoint(
|
||||
context, db_api.get_top_pod(context)['pod_id'],
|
||||
constants.ST_GLANCE)
|
||||
alternate_link = '/'.join([glance_url, 'images', image['id']])
|
||||
return [{'rel': 'self', 'href': self_link},
|
||||
{'rel': 'bookmark', 'href': bookmark_link},
|
||||
{'rel': 'alternate',
|
||||
'type': 'application/vnd.openstack.image',
|
||||
'href': alternate_link}]
|
||||
|
||||
@staticmethod
|
||||
def _format_date(dt):
|
||||
"""Return standard format for a given datetime string."""
|
||||
if dt is not None:
|
||||
date_string = dt.split('.')[0]
|
||||
date_string += 'Z'
|
||||
return date_string
|
||||
|
||||
@staticmethod
|
||||
def _get_status(image):
|
||||
"""Update the status field to standardize format."""
|
||||
return {
|
||||
'active': 'ACTIVE',
|
||||
'queued': 'SAVING',
|
||||
'saving': 'SAVING',
|
||||
'deleted': 'DELETED',
|
||||
'pending_delete': 'DELETED',
|
||||
'killed': 'ERROR',
|
||||
}.get(image.get('status'), 'UNKNOWN')
|
||||
|
||||
@staticmethod
|
||||
def _get_progress(image):
|
||||
return {
|
||||
'queued': 25,
|
||||
'saving': 50,
|
||||
'active': 100,
|
||||
}.get(image.get('status'), 0)
|
||||
|
||||
def _construct_list_image_entry(self, context, image):
|
||||
return {'id': image['id'],
|
||||
'name': image.get('name'),
|
||||
'links': self._get_links(context, image)}
|
||||
|
||||
def _construct_show_image_entry(self, context, image):
|
||||
return {
|
||||
'id': image['id'],
|
||||
'name': image.get('name'),
|
||||
'minRam': int(image.get('min_ram') or 0),
|
||||
'minDisk': int(image.get('min_disk') or 0),
|
||||
'metadata': image.get('properties', {}),
|
||||
'created': self._format_date(image.get('created_at')),
|
||||
'updated': self._format_date(image.get('updated_at')),
|
||||
'status': self._get_status(image),
|
||||
'progress': self._get_progress(image),
|
||||
'links': self._get_links(context, image)
|
||||
}
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
def get_one(self, _id):
|
||||
context = t_context.extract_context_from_environ()
|
||||
@ -34,10 +143,12 @@ class ImageController(rest.RestController):
|
||||
if not image:
|
||||
pecan.abort(404, 'Image not found')
|
||||
return
|
||||
return {'image': image}
|
||||
return {'image': self._construct_show_image_entry(context, image)}
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
def get_all(self):
|
||||
context = t_context.extract_context_from_environ()
|
||||
images = self.client.list_images(context)
|
||||
return {'images': images}
|
||||
ret_images = [self._construct_list_image_entry(
|
||||
context, image) for image in images]
|
||||
return {'images': ret_images}
|
||||
|
50
tricircle/nova_apigw/controllers/network.py
Normal file
50
tricircle/nova_apigw/controllers/network.py
Normal file
@ -0,0 +1,50 @@
|
||||
# Copyright (c) 2015 Huawei Tech. Co., Ltd.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 pecan
|
||||
from pecan import expose
|
||||
from pecan import rest
|
||||
|
||||
import tricircle.common.client as t_client
|
||||
import tricircle.common.context as t_context
|
||||
|
||||
|
||||
class NetworkController(rest.RestController):
|
||||
|
||||
def __init__(self, project_id):
|
||||
self.project_id = project_id
|
||||
self.client = t_client.Client()
|
||||
|
||||
@staticmethod
|
||||
def _construct_network_entry(network):
|
||||
network['uuid'] = network['id']
|
||||
network['label'] = network['name']
|
||||
return network
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
def get_one(self, _id):
|
||||
context = t_context.extract_context_from_environ()
|
||||
network = self.client.get_networks(context, _id)
|
||||
if not network:
|
||||
pecan.abort(404, 'Network not found')
|
||||
return
|
||||
return {'network': self._construct_network_entry(network)}
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
def get_all(self):
|
||||
context = t_context.extract_context_from_environ()
|
||||
networks = self.client.list_networks(context)
|
||||
return {'networks': [self._construct_network_entry(
|
||||
network) for network in networks]}
|
@ -29,6 +29,7 @@ from tricircle.nova_apigw.controllers import action
|
||||
from tricircle.nova_apigw.controllers import aggregate
|
||||
from tricircle.nova_apigw.controllers import flavor
|
||||
from tricircle.nova_apigw.controllers import image
|
||||
from tricircle.nova_apigw.controllers import network
|
||||
from tricircle.nova_apigw.controllers import quota_sets
|
||||
from tricircle.nova_apigw.controllers import server
|
||||
from tricircle.nova_apigw.controllers import volume
|
||||
@ -94,6 +95,7 @@ class V21Controller(object):
|
||||
'images': image.ImageController,
|
||||
'os-quota-sets': quota_sets.QuotaSetsController,
|
||||
'limits': quota_sets.LimitsController,
|
||||
'os-networks': network.NetworkController
|
||||
}
|
||||
self.server_sub_controller = {
|
||||
'os-volume_attachments': volume.VolumeController,
|
||||
|
@ -56,24 +56,45 @@ class ServerController(rest.RestController):
|
||||
self.clients[pod_name] = t_client.Client(pod_name)
|
||||
return self.clients[pod_name]
|
||||
|
||||
def _get_all(self, context):
|
||||
def _get_all(self, context, params):
|
||||
filters = [{'key': key,
|
||||
'comparator': 'eq',
|
||||
'value': value} for key, value in params.iteritems()]
|
||||
ret = []
|
||||
pods = db_api.list_pods(context)
|
||||
for pod in pods:
|
||||
if not pod['az_name']:
|
||||
continue
|
||||
client = self._get_client(pod['pod_name'])
|
||||
servers = client.list_servers(context)
|
||||
servers = client.list_servers(context, filters=filters)
|
||||
self._remove_fip_info(servers)
|
||||
ret.extend(servers)
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def _construct_brief_server_entry(server):
|
||||
return {'id': server['id'],
|
||||
'name': server.get('name'),
|
||||
'links': server.get('links')}
|
||||
|
||||
@staticmethod
|
||||
def _transform_network_name(server):
|
||||
if 'addresses' not in server:
|
||||
return
|
||||
keys = [key for key in server['addresses'].iterkeys()]
|
||||
for key in keys:
|
||||
value = server['addresses'].pop(key)
|
||||
network_name = key.split('#')[1]
|
||||
server['addresses'][network_name] = value
|
||||
return server
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
def get_one(self, _id):
|
||||
def get_one(self, _id, **kwargs):
|
||||
context = t_context.extract_context_from_environ()
|
||||
|
||||
if _id == 'detail':
|
||||
return {'servers': self._get_all(context)}
|
||||
return {'servers': [self._transform_network_name(
|
||||
server) for server in self._get_all(context, kwargs)]}
|
||||
|
||||
mappings = db_api.get_bottom_mappings_by_top_id(
|
||||
context, _id, constants.RT_SERVER)
|
||||
@ -88,12 +109,14 @@ class ServerController(rest.RestController):
|
||||
pecan.abort(404, 'Server not found')
|
||||
return
|
||||
else:
|
||||
self._transform_network_name(server)
|
||||
return {'server': server}
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
def get_all(self):
|
||||
def get_all(self, **kwargs):
|
||||
context = t_context.extract_context_from_environ()
|
||||
return {'servers': self._get_all(context)}
|
||||
return {'servers': [self._construct_brief_server_entry(
|
||||
server) for server in self._get_all(context, kwargs)]}
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
def post(self, **kw):
|
||||
@ -216,6 +239,7 @@ class ServerController(rest.RestController):
|
||||
'pod_id': pod['pod_id'],
|
||||
'project_id': self.project_id,
|
||||
'resource_type': constants.RT_SERVER})
|
||||
pecan.response.status = 202
|
||||
return {'server': server}
|
||||
|
||||
@expose(generic=True, template='json')
|
||||
@ -265,21 +289,21 @@ class ServerController(rest.RestController):
|
||||
return pecan.response
|
||||
|
||||
def _get_or_create_route(self, context, pod, _id, _type):
|
||||
def list_resources(t_ctx, q_ctx, pod_, _id_, _type_):
|
||||
def list_resources(t_ctx, q_ctx, pod_, ele, _type_):
|
||||
client = self._get_client(pod_['pod_name'])
|
||||
return client.list_resources(_type_, t_ctx, [{'key': 'name',
|
||||
'comparator': 'eq',
|
||||
'value': _id_}])
|
||||
'value': ele['id']}])
|
||||
|
||||
return t_lock.get_or_create_route(context, None,
|
||||
self.project_id, pod, _id, _type,
|
||||
list_resources)
|
||||
self.project_id, pod, {'id': _id},
|
||||
_type, list_resources)
|
||||
|
||||
def _get_create_network_body(self, network):
|
||||
body = {
|
||||
'network': {
|
||||
'tenant_id': self.project_id,
|
||||
'name': network['id'],
|
||||
'name': utils.get_bottom_network_name(network),
|
||||
'admin_state_up': True
|
||||
}
|
||||
}
|
||||
@ -342,11 +366,16 @@ class ServerController(rest.RestController):
|
||||
return body
|
||||
|
||||
def _prepare_neutron_element(self, context, pod, ele, _type, body):
|
||||
def list_resources(t_ctx, q_ctx, pod_, _id_, _type_):
|
||||
def list_resources(t_ctx, q_ctx, pod_, ele_, _type_):
|
||||
client = self._get_client(pod_['pod_name'])
|
||||
return client.list_resources(_type_, t_ctx, [{'key': 'name',
|
||||
'comparator': 'eq',
|
||||
'value': _id_}])
|
||||
if _type_ == constants.RT_NETWORK:
|
||||
value = utils.get_bottom_network_name(ele_)
|
||||
else:
|
||||
value = ele_['id']
|
||||
return client.list_resources(
|
||||
_type_, t_ctx,
|
||||
[{'key': 'name', 'comparator': 'eq',
|
||||
'value': value}])
|
||||
|
||||
def create_resources(t_ctx, q_ctx, pod_, body_, _type_):
|
||||
client = self._get_client(pod_['pod_name'])
|
||||
|
@ -52,8 +52,9 @@ BOTTOM_NETS = BOTTOM1_NETS
|
||||
BOTTOM_SUBNETS = BOTTOM1_SUBNETS
|
||||
BOTTOM_PORTS = BOTTOM1_PORTS
|
||||
BOTTOM_SGS = BOTTOM1_SGS
|
||||
BOTTOM_SERVERS = []
|
||||
|
||||
RES_LIST = [TOP_NETS, TOP_SUBNETS, TOP_PORTS, TOP_SGS,
|
||||
RES_LIST = [TOP_NETS, TOP_SUBNETS, TOP_PORTS, TOP_SGS, BOTTOM_SERVERS,
|
||||
BOTTOM1_NETS, BOTTOM1_SUBNETS, BOTTOM1_PORTS, BOTTOM1_SGS,
|
||||
BOTTOM2_NETS, BOTTOM2_SUBNETS, BOTTOM2_PORTS, BOTTOM2_SGS]
|
||||
|
||||
@ -90,7 +91,8 @@ class FakeClient(object):
|
||||
'bottom': {'network': BOTTOM_NETS,
|
||||
'subnet': BOTTOM_SUBNETS,
|
||||
'port': BOTTOM_PORTS,
|
||||
'security_group': BOTTOM_SGS},
|
||||
'security_group': BOTTOM_SGS,
|
||||
'server': BOTTOM_SERVERS},
|
||||
'bottom2': {'network': BOTTOM2_NETS,
|
||||
'subnet': BOTTOM2_SUBNETS,
|
||||
'port': BOTTOM2_PORTS,
|
||||
@ -224,9 +226,34 @@ class FakeClient(object):
|
||||
'subnet', ctx,
|
||||
[{'key': 'id', 'comparator': 'eq', 'value': subnet_id}])[0]
|
||||
|
||||
def create_servers(self, ctx, body):
|
||||
# do nothing here since it will be mocked
|
||||
pass
|
||||
def create_servers(self, ctx, **body):
|
||||
body['id'] = uuidutils.generate_uuid()
|
||||
BOTTOM_SERVERS.append(body)
|
||||
return body
|
||||
|
||||
def list_servers(self, ctx, filters):
|
||||
ret_servers = []
|
||||
for b_server in self.list_resources('server', ctx, filters):
|
||||
ret_server = copy.deepcopy(b_server)
|
||||
for nic in ret_server['nics']:
|
||||
ports = self.list_ports(
|
||||
ctx, [{'key': 'id', 'comparator': 'eq',
|
||||
'value': nic['port-id']}])
|
||||
nets = self.list_resources(
|
||||
'network', ctx, [{'key': 'id', 'comparator': 'eq',
|
||||
'value': ports[0]['network_id']}])
|
||||
ret_server['addresses'] = {
|
||||
nets[0]['name']: [
|
||||
{'OS-EXT-IPS-MAC:mac_addr': ports[0]['mac_address'],
|
||||
'version': 4,
|
||||
'addr': ports[0]['fixed_ips'][0]['ip_address'],
|
||||
'OS-EXT-IPS:type': 'fixed'}]}
|
||||
ret_servers.append(ret_server)
|
||||
return ret_servers
|
||||
|
||||
def get_servers(self, ctx, server_id):
|
||||
return self.list_servers(
|
||||
ctx, [{'key': 'id', 'comparator': 'eq', 'value': server_id}])[0]
|
||||
|
||||
def get_security_groups(self, ctx, sg_id):
|
||||
sg = self.list_resources(
|
||||
@ -399,7 +426,7 @@ class ServerTest(unittest.TestCase):
|
||||
|
||||
def test_handle_network(self):
|
||||
t_pod, b_pod = self._prepare_pod()
|
||||
net = {'id': 'top_net_id'}
|
||||
net = {'id': 'top_net_id', 'name': 'net'}
|
||||
subnet = {'id': 'top_subnet_id',
|
||||
'network_id': 'top_net_id',
|
||||
'ip_version': 4,
|
||||
@ -415,7 +442,7 @@ class ServerTest(unittest.TestCase):
|
||||
|
||||
def test_handle_port(self):
|
||||
t_pod, b_pod = self._prepare_pod()
|
||||
net = {'id': 'top_net_id'}
|
||||
net = {'id': 'top_net_id', 'name': 'net'}
|
||||
subnet = {'id': 'top_subnet_id',
|
||||
'network_id': 'top_net_id',
|
||||
'ip_version': 4,
|
||||
@ -444,7 +471,7 @@ class ServerTest(unittest.TestCase):
|
||||
bottom_net_id = 'bottom_net_id'
|
||||
top_subnet_id = 'top_subnet_id'
|
||||
bottom_subnet_id = 'bottom_subnet_id'
|
||||
t_net = {'id': top_net_id}
|
||||
t_net = {'id': top_net_id, 'name': 'net'}
|
||||
b_net = {'id': bottom_net_id}
|
||||
t_subnet = {'id': top_subnet_id,
|
||||
'network_id': top_net_id,
|
||||
@ -498,6 +525,7 @@ class ServerTest(unittest.TestCase):
|
||||
def test_handle_network_dhcp_port_exist_diff_ip(self):
|
||||
self._test_handle_network_dhcp_port('10.0.0.4')
|
||||
|
||||
@patch.object(pecan, 'response', new=FakeResponse)
|
||||
@patch.object(pecan, 'abort')
|
||||
@patch.object(FakeClient, 'create_servers')
|
||||
@patch.object(context, 'extract_context_from_environ')
|
||||
@ -506,7 +534,7 @@ class ServerTest(unittest.TestCase):
|
||||
top_net_id = 'top_net_id'
|
||||
top_subnet_id = 'top_subnet_id'
|
||||
top_sg_id = 'top_sg_id'
|
||||
t_net = {'id': top_net_id}
|
||||
t_net = {'id': top_net_id, 'name': 'net'}
|
||||
t_subnet = {'id': top_subnet_id,
|
||||
'network_id': top_net_id,
|
||||
'ip_version': 4,
|
||||
@ -569,6 +597,7 @@ class ServerTest(unittest.TestCase):
|
||||
calls = [mock.call(400, msg), mock.call(400, msg)]
|
||||
mock_abort.assert_has_calls(calls)
|
||||
|
||||
@patch.object(pecan, 'response', new=FakeResponse)
|
||||
@patch.object(FakeClient, 'create_servers')
|
||||
@patch.object(context, 'extract_context_from_environ')
|
||||
def test_post(self, mock_ctx, mock_create):
|
||||
@ -577,7 +606,7 @@ class ServerTest(unittest.TestCase):
|
||||
top_subnet_id = 'top_subnet_id'
|
||||
top_sg_id = 'top_sg_id'
|
||||
|
||||
t_net = {'id': top_net_id}
|
||||
t_net = {'id': top_net_id, 'name': 'net'}
|
||||
t_subnet = {'id': top_subnet_id,
|
||||
'network_id': top_net_id,
|
||||
'ip_version': 4,
|
||||
@ -641,6 +670,7 @@ class ServerTest(unittest.TestCase):
|
||||
if rule['ethertype'] == 'IPv4' and rule['direction'] == 'ingress':
|
||||
self.assertIsNone(rule['remote_group_id'])
|
||||
self.assertEqual('10.0.0.0/24', rule['remote_ip_prefix'])
|
||||
|
||||
with self.context.session.begin():
|
||||
routes = core.query_resource(self.context, models.ResourceRouting,
|
||||
[{'key': 'resource_type',
|
||||
@ -663,6 +693,7 @@ 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, 'response', new=FakeResponse)
|
||||
@patch.object(FakeClient, 'create_servers')
|
||||
@patch.object(context, 'extract_context_from_environ')
|
||||
def test_post_exception_retry(self, mock_ctx, mock_server):
|
||||
@ -671,7 +702,7 @@ class ServerTest(unittest.TestCase):
|
||||
top_subnet_id = 'top_subnet_id'
|
||||
top_sg_id = 'top_sg_id'
|
||||
|
||||
t_net = {'id': top_net_id}
|
||||
t_net = {'id': top_net_id, 'name': 'net'}
|
||||
t_subnet = {'id': top_subnet_id,
|
||||
'network_id': top_net_id,
|
||||
'ip_version': 4,
|
||||
@ -750,6 +781,7 @@ class ServerTest(unittest.TestCase):
|
||||
nics=[{'port-id': bottom_port_id}],
|
||||
security_groups=[bottom_sg['id']])
|
||||
|
||||
@patch.object(pecan, 'response', new=FakeResponse)
|
||||
@patch.object(FakeClient, 'create_servers')
|
||||
@patch.object(context, 'extract_context_from_environ')
|
||||
def test_post_across_pods(self, mock_ctx, mock_create):
|
||||
@ -761,7 +793,7 @@ class ServerTest(unittest.TestCase):
|
||||
top_subnet2_id = 'top_subnet2_id'
|
||||
top_sg_id = 'top_sg_id'
|
||||
|
||||
t_net1 = {'id': top_net1_id}
|
||||
t_net1 = {'id': top_net1_id, 'name': 'net1'}
|
||||
t_subnet1 = {'id': top_subnet1_id,
|
||||
'tenant_id': self.project_id,
|
||||
'network_id': top_net1_id,
|
||||
@ -771,7 +803,7 @@ class ServerTest(unittest.TestCase):
|
||||
'allocation_pools': {'start': '10.0.1.2',
|
||||
'end': '10.0.1.254'},
|
||||
'enable_dhcp': True}
|
||||
t_net2 = {'id': top_net2_id}
|
||||
t_net2 = {'id': top_net2_id, 'name': 'net2'}
|
||||
t_subnet2 = {'id': top_subnet2_id,
|
||||
'tenant_id': self.project_id,
|
||||
'network_id': top_net2_id,
|
||||
@ -1109,6 +1141,72 @@ class ServerTest(unittest.TestCase):
|
||||
calls = [mock.call(400, msg)]
|
||||
mock_abort.assert_has_calls(calls)
|
||||
|
||||
@patch.object(pecan, 'response', new=FakeResponse)
|
||||
@patch.object(context, 'extract_context_from_environ')
|
||||
def test_get(self, mock_ctx):
|
||||
t_pod, b_pod = self._prepare_pod()
|
||||
top_net_id = 'top_net_id'
|
||||
top_subnet_id = 'top_subnet_id'
|
||||
top_sg_id = 'top_sg_id'
|
||||
|
||||
t_net = {'id': top_net_id, 'name': 'net'}
|
||||
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}
|
||||
t_sg = {'id': top_sg_id, 'name': 'default', 'description': '',
|
||||
'tenant_id': self.project_id,
|
||||
'security_group_rules': [
|
||||
{'remote_group_id': top_sg_id,
|
||||
'direction': 'ingress',
|
||||
'remote_ip_prefix': None,
|
||||
'protocol': None,
|
||||
'port_range_max': None,
|
||||
'port_range_min': None,
|
||||
'ethertype': 'IPv4'},
|
||||
{'remote_group_id': None,
|
||||
'direction': 'egress',
|
||||
'remote_ip_prefix': None,
|
||||
'protocol': None,
|
||||
'port_range_max': None,
|
||||
'port_range_min': None,
|
||||
'ethertype': 'IPv4'},
|
||||
]}
|
||||
TOP_NETS.append(t_net)
|
||||
TOP_SUBNETS.append(t_subnet)
|
||||
TOP_SGS.append(t_sg)
|
||||
|
||||
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_ctx.return_value = self.context
|
||||
|
||||
server_dict = self.controller.post(**body)['server']
|
||||
ret_server = self.controller.get_one(server_dict['id'])['server']
|
||||
self.assertEqual(server_name, ret_server['name'])
|
||||
self.assertEqual(image_id, ret_server['image'])
|
||||
self.assertEqual(flavor_id, ret_server['flavor'])
|
||||
self.assertEqual(t_net['name'], ret_server['addresses'].keys()[0])
|
||||
|
||||
ret_server = self.controller.get_one('detail')['servers'][0]
|
||||
self.assertEqual(server_name, ret_server['name'])
|
||||
self.assertEqual(image_id, ret_server['image'])
|
||||
self.assertEqual(flavor_id, ret_server['flavor'])
|
||||
self.assertEqual(t_net['name'], ret_server['addresses'].keys()[0])
|
||||
|
||||
def tearDown(self):
|
||||
core.ModelBase.metadata.drop_all(core.get_engine())
|
||||
for res in RES_LIST:
|
||||
|
Loading…
x
Reference in New Issue
Block a user