Merge "api: Add response body schemas for remaining server action APIs"
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
"flavor_access": [
|
||||
{
|
||||
"flavor_id": "10",
|
||||
"tenant_id": "fake_tenant"
|
||||
"tenant_id": "6f70656e737461636b20342065766572"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"flavor_access": [
|
||||
{
|
||||
"flavor_id": "10",
|
||||
"tenant_id": "fake_tenant"
|
||||
"tenant_id": "6f70656e737461636b20342065766572"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
"extra_specs": {
|
||||
"hw:numa_nodes": "2"
|
||||
},
|
||||
"projects": ["fake_tenant"],
|
||||
"projects": ["6f70656e737461636b20342065766572"],
|
||||
"swap": 0,
|
||||
"rxtx_factor": 2.0,
|
||||
"is_public": false,
|
||||
|
||||
@@ -19,7 +19,7 @@ import re
|
||||
import webob
|
||||
|
||||
from nova.api.openstack import common
|
||||
from nova.api.openstack.compute.schemas import console_output
|
||||
from nova.api.openstack.compute.schemas import console_output as schema
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api import validation
|
||||
from nova.compute import api as compute
|
||||
@@ -34,7 +34,8 @@ class ConsoleOutputController(wsgi.Controller):
|
||||
|
||||
@wsgi.expected_errors((404, 409, 501))
|
||||
@wsgi.action('os-getConsoleOutput')
|
||||
@validation.schema(console_output.get_console_output)
|
||||
@validation.schema(schema.get_console_output)
|
||||
@validation.response_body_schema(schema.get_console_output_response)
|
||||
def get_console_output(self, req, id, body):
|
||||
"""Get text console output."""
|
||||
context = req.environ['nova.context']
|
||||
|
||||
@@ -17,7 +17,7 @@ import webob
|
||||
|
||||
from nova.api.openstack import api_version_request
|
||||
from nova.api.openstack import common
|
||||
from nova.api.openstack.compute.schemas import create_backup
|
||||
from nova.api.openstack.compute.schemas import create_backup as schema
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api import validation
|
||||
from nova.compute import api as compute
|
||||
@@ -33,8 +33,14 @@ class CreateBackupController(wsgi.Controller):
|
||||
@wsgi.response(202)
|
||||
@wsgi.expected_errors((400, 403, 404, 409))
|
||||
@wsgi.action('createBackup')
|
||||
@validation.schema(create_backup.create_backup_v20, '2.0', '2.0')
|
||||
@validation.schema(create_backup.create_backup, '2.1')
|
||||
@validation.schema(schema.create_backup_v20, '2.0', '2.0')
|
||||
@validation.schema(schema.create_backup, '2.1')
|
||||
@validation.response_body_schema(
|
||||
schema.create_backup_response, '2.1', '2.44',
|
||||
)
|
||||
@validation.response_body_schema(
|
||||
schema.create_backup_response_v245, '2.45'
|
||||
)
|
||||
def _create_backup(self, req, id, body):
|
||||
"""Backup a server instance.
|
||||
|
||||
|
||||
@@ -80,9 +80,13 @@ class EvacuateController(wsgi.Controller):
|
||||
@wsgi.action('evacuate')
|
||||
@validation.schema(evacuate.evacuate, "2.0", "2.13")
|
||||
@validation.schema(evacuate.evacuate_v214, "2.14", "2.28")
|
||||
@validation.schema(evacuate.evacuate_v2_29, "2.29", "2.67")
|
||||
@validation.schema(evacuate.evacuate_v2_68, "2.68", "2.94")
|
||||
@validation.schema(evacuate.evacuate_v2_95, "2.95")
|
||||
@validation.schema(evacuate.evacuate_v229, "2.29", "2.67")
|
||||
@validation.schema(evacuate.evacuate_v268, "2.68", "2.94")
|
||||
@validation.schema(evacuate.evacuate_v295, "2.95")
|
||||
@validation.response_body_schema(
|
||||
evacuate.evacuate_response, "2.0", "2.13"
|
||||
)
|
||||
@validation.response_body_schema(evacuate.evacuate_response_v214, "2.14")
|
||||
def _evacuate(self, req, id, body):
|
||||
"""Permit admins to evacuate a server from a failed host
|
||||
to a new one.
|
||||
|
||||
@@ -63,6 +63,7 @@ class FlavorActionController(wsgi.Controller):
|
||||
@wsgi.expected_errors((400, 403, 404, 409))
|
||||
@wsgi.action("addTenantAccess")
|
||||
@validation.schema(schema.add_tenant_access)
|
||||
@validation.response_body_schema(schema.add_tenant_access_response)
|
||||
def _add_tenant_access(self, req, id, body):
|
||||
context = req.environ['nova.context']
|
||||
context.can(fa_policies.POLICY_ROOT % "add_tenant_access", target={})
|
||||
@@ -88,6 +89,7 @@ class FlavorActionController(wsgi.Controller):
|
||||
@wsgi.expected_errors((400, 403, 404))
|
||||
@wsgi.action("removeTenantAccess")
|
||||
@validation.schema(schema.remove_tenant_access)
|
||||
@validation.response_body_schema(schema.remove_tenant_access_response)
|
||||
def _remove_tenant_access(self, req, id, body):
|
||||
context = req.environ['nova.context']
|
||||
context.can(
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
import webob
|
||||
|
||||
from nova.api.openstack import common
|
||||
from nova.api.openstack.compute.schemas import remote_consoles
|
||||
from nova.api.openstack.compute.schemas import remote_consoles as schema
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api import validation
|
||||
from nova.compute import api as compute
|
||||
@@ -40,7 +40,8 @@ class RemoteConsolesController(wsgi.Controller):
|
||||
@wsgi.Controller.api_version("2.1", "2.5")
|
||||
@wsgi.expected_errors((400, 404, 409, 501))
|
||||
@wsgi.action('os-getVNCConsole')
|
||||
@validation.schema(remote_consoles.get_vnc_console)
|
||||
@validation.schema(schema.get_vnc_console)
|
||||
@validation.response_body_schema(schema.get_vnc_console_response)
|
||||
def get_vnc_console(self, req, id, body):
|
||||
"""Get text console output."""
|
||||
context = req.environ['nova.context']
|
||||
@@ -71,7 +72,8 @@ class RemoteConsolesController(wsgi.Controller):
|
||||
@wsgi.Controller.api_version("2.1", "2.5")
|
||||
@wsgi.expected_errors((400, 404, 409, 501))
|
||||
@wsgi.action('os-getSPICEConsole')
|
||||
@validation.schema(remote_consoles.get_spice_console)
|
||||
@validation.schema(schema.get_spice_console)
|
||||
@validation.response_body_schema(schema.get_spice_console_response)
|
||||
def get_spice_console(self, req, id, body):
|
||||
"""Get text console output."""
|
||||
context = req.environ['nova.context']
|
||||
@@ -100,7 +102,7 @@ class RemoteConsolesController(wsgi.Controller):
|
||||
@wsgi.expected_errors((400, 404, 409, 501))
|
||||
@wsgi.action('os-getRDPConsole')
|
||||
@wsgi.removed('29.0.0', _rdp_console_removal_reason)
|
||||
@validation.schema(remote_consoles.get_rdp_console)
|
||||
@validation.schema(schema.get_rdp_console)
|
||||
def get_rdp_console(self, req, id, body):
|
||||
"""RDP console was available only for HyperV driver which has been
|
||||
removed from Nova in 29.0.0 (Caracal) release.
|
||||
@@ -110,7 +112,8 @@ class RemoteConsolesController(wsgi.Controller):
|
||||
@wsgi.Controller.api_version("2.1", "2.5")
|
||||
@wsgi.expected_errors((400, 404, 409, 501))
|
||||
@wsgi.action('os-getSerialConsole')
|
||||
@validation.schema(remote_consoles.get_serial_console)
|
||||
@validation.schema(schema.get_serial_console)
|
||||
@validation.response_body_schema(schema.get_serial_console_response)
|
||||
def get_serial_console(self, req, id, body):
|
||||
"""Get connection to a serial console."""
|
||||
context = req.environ['nova.context']
|
||||
@@ -139,8 +142,8 @@ class RemoteConsolesController(wsgi.Controller):
|
||||
|
||||
@wsgi.Controller.api_version("2.6")
|
||||
@wsgi.expected_errors((400, 404, 409, 501))
|
||||
@validation.schema(remote_consoles.create_v26, "2.6", "2.7")
|
||||
@validation.schema(remote_consoles.create_v28, "2.8")
|
||||
@validation.schema(schema.create_v26, "2.6", "2.7")
|
||||
@validation.schema(schema.create_v28, "2.8")
|
||||
def create(self, req, server_id, body):
|
||||
context = req.environ['nova.context']
|
||||
instance = common.get_instance(self.compute_api, context, server_id)
|
||||
|
||||
@@ -34,3 +34,12 @@ get_console_output = {
|
||||
'required': ['os-getConsoleOutput'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
get_console_output_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'output': {'type': 'string'},
|
||||
},
|
||||
'required': ['output'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
@@ -41,5 +41,19 @@ create_backup = {
|
||||
|
||||
create_backup_v20 = copy.deepcopy(create_backup)
|
||||
create_backup_v20['properties'][
|
||||
'createBackup']['properties']['name'] = (parameter_types.
|
||||
name_with_leading_trailing_spaces)
|
||||
'createBackup']['properties']['name'] = (
|
||||
parameter_types.name_with_leading_trailing_spaces)
|
||||
|
||||
|
||||
create_backup_response = {
|
||||
'type': 'null',
|
||||
}
|
||||
|
||||
create_backup_response_v245 = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'image_id': {'type': 'string', 'format': 'uuid'},
|
||||
},
|
||||
'required': ['image_id'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
@@ -39,14 +39,31 @@ evacuate_v214 = copy.deepcopy(evacuate)
|
||||
del evacuate_v214['properties']['evacuate']['properties']['onSharedStorage']
|
||||
del evacuate_v214['properties']['evacuate']['required']
|
||||
|
||||
evacuate_v2_29 = copy.deepcopy(evacuate_v214)
|
||||
evacuate_v2_29['properties']['evacuate']['properties'][
|
||||
evacuate_v229 = copy.deepcopy(evacuate_v214)
|
||||
evacuate_v229['properties']['evacuate']['properties'][
|
||||
'force'] = parameter_types.boolean
|
||||
|
||||
# v2.68 removes the 'force' parameter added in v2.29, meaning it is identical
|
||||
# to v2.14
|
||||
evacuate_v2_68 = copy.deepcopy(evacuate_v214)
|
||||
evacuate_v268 = copy.deepcopy(evacuate_v214)
|
||||
|
||||
# v2.95 keeps the same schema, evacuating an instance will now result its state
|
||||
# to be stopped at destination.
|
||||
evacuate_v2_95 = copy.deepcopy(evacuate_v2_68)
|
||||
evacuate_v295 = copy.deepcopy(evacuate_v268)
|
||||
|
||||
evacuate_response = {
|
||||
'type': ['object', 'null'],
|
||||
'properties': {
|
||||
'adminPass': {
|
||||
'type': ['null', 'string'],
|
||||
}
|
||||
},
|
||||
# adminPass is a rare-example of configuration-driven API behavior: the
|
||||
# value depends on '[api] enable_instance_password'
|
||||
'required': [],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
evacuate_response_v214 = {
|
||||
'type': 'null',
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
add_tenant_access = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
@@ -31,7 +33,6 @@ add_tenant_access = {
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
|
||||
remove_tenant_access = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
@@ -57,3 +58,27 @@ index_query = {
|
||||
'properties': {},
|
||||
'additionalProperties': True,
|
||||
}
|
||||
|
||||
_common_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'flavor_access': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'flavor_id': {'type': 'string'},
|
||||
'tenant_id': {'type': 'string', 'format': 'uuid'},
|
||||
},
|
||||
'required': ['flavor_id', 'tenant_id'],
|
||||
'additionalProperties': True,
|
||||
},
|
||||
},
|
||||
},
|
||||
'required': ['flavor_access'],
|
||||
'additionalProperties': True,
|
||||
}
|
||||
|
||||
add_tenant_access_response = copy.deepcopy(_common_response)
|
||||
|
||||
remove_tenant_access_response = copy.deepcopy(_common_response)
|
||||
|
||||
@@ -119,3 +119,78 @@ create_v28 = {
|
||||
'required': ['remote_console'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
get_vnc_console_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'console': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'type': {
|
||||
'type': 'string',
|
||||
'enum': ['novnc', 'xvpvnc'],
|
||||
'description': '',
|
||||
},
|
||||
'url': {
|
||||
'type': 'string',
|
||||
'format': 'uri',
|
||||
'description': '',
|
||||
},
|
||||
},
|
||||
'required': ['type', 'url'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['console'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
get_spice_console_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'console': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'type': {
|
||||
'type': 'string',
|
||||
'enum': ['spice-html5'],
|
||||
'description': '',
|
||||
},
|
||||
'url': {
|
||||
'type': 'string',
|
||||
'format': 'uri',
|
||||
'description': '',
|
||||
},
|
||||
},
|
||||
'required': ['type', 'url'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['console'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
get_serial_console_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'console': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'type': {
|
||||
'type': 'string',
|
||||
'enum': ['serial'],
|
||||
'description': '',
|
||||
},
|
||||
'url': {
|
||||
'type': 'string',
|
||||
'format': 'uri',
|
||||
'description': '',
|
||||
},
|
||||
},
|
||||
'required': ['type', 'url'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['console'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
@@ -238,8 +238,9 @@ create_v20['properties']['server']['properties'][
|
||||
'security_groups']['items']['properties']['name'] = (
|
||||
parameter_types.name_with_leading_trailing_spaces)
|
||||
create_v20['properties']['server']['properties']['user_data'] = {
|
||||
'oneOf': [{'type': 'string', 'format': 'base64', 'maxLength': 65535},
|
||||
{'type': 'null'},
|
||||
'oneOf': [
|
||||
{'type': 'string', 'format': 'base64', 'maxLength': 65535},
|
||||
{'type': 'null'},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -282,45 +283,49 @@ create_v237 = copy.deepcopy(create_v233)
|
||||
create_v237['properties']['server']['required'].append('networks')
|
||||
create_v237['properties']['server']['properties']['networks'] = {
|
||||
'oneOf': [
|
||||
{'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'fixed_ip': parameter_types.ip_address,
|
||||
'port': {
|
||||
'oneOf': [{'type': 'string', 'format': 'uuid'},
|
||||
{'type': 'null'}]
|
||||
},
|
||||
'uuid': {'type': 'string', 'format': 'uuid'},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
{
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'fixed_ip': parameter_types.ip_address,
|
||||
'port': {
|
||||
'oneOf': [{'type': 'string', 'format': 'uuid'},
|
||||
{'type': 'null'}]
|
||||
},
|
||||
'uuid': {'type': 'string', 'format': 'uuid'},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
{'type': 'string', 'enum': ['none', 'auto']},
|
||||
]}
|
||||
],
|
||||
}
|
||||
|
||||
# 2.42 builds on 2.37 and re-introduces the tag field to the list of network
|
||||
# objects.
|
||||
create_v242 = copy.deepcopy(create_v237)
|
||||
create_v242['properties']['server']['properties']['networks'] = {
|
||||
'oneOf': [
|
||||
{'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'fixed_ip': parameter_types.ip_address,
|
||||
'port': {
|
||||
'oneOf': [{'type': 'string', 'format': 'uuid'},
|
||||
{'type': 'null'}]
|
||||
},
|
||||
'uuid': {'type': 'string', 'format': 'uuid'},
|
||||
'tag': parameter_types.tag,
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
{
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'fixed_ip': parameter_types.ip_address,
|
||||
'port': {
|
||||
'oneOf': [{'type': 'string', 'format': 'uuid'},
|
||||
{'type': 'null'}]
|
||||
},
|
||||
'uuid': {'type': 'string', 'format': 'uuid'},
|
||||
'tag': parameter_types.tag,
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
{'type': 'string', 'enum': ['none', 'auto']},
|
||||
]}
|
||||
],
|
||||
}
|
||||
create_v242['properties']['server'][
|
||||
'properties']['block_device_mapping_v2']['items'][
|
||||
'properties']['tag'] = parameter_types.tag
|
||||
@@ -465,7 +470,6 @@ rebuild_v294 = copy.deepcopy(rebuild_v290)
|
||||
rebuild_v294['properties']['rebuild']['properties'][
|
||||
'hostname'] = parameter_types.fqdn
|
||||
|
||||
|
||||
resize = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
@@ -771,3 +775,458 @@ stop_server_response = {
|
||||
trigger_crash_dump_response = {
|
||||
'type': 'null',
|
||||
}
|
||||
|
||||
create_image_response = {
|
||||
'type': 'null',
|
||||
}
|
||||
|
||||
create_image_response_v245 = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'image_id': {'type': 'string', 'format': 'uuid'},
|
||||
},
|
||||
'required': ['image_id'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
rebuild_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'server': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'accessIPv4': {
|
||||
'type': 'string',
|
||||
'oneOf': [
|
||||
{'format': 'ipv4'},
|
||||
{'const': ''},
|
||||
],
|
||||
},
|
||||
'accessIPv6': {
|
||||
'type': 'string',
|
||||
'oneOf': [
|
||||
{'format': 'ipv6'},
|
||||
{'const': ''},
|
||||
],
|
||||
},
|
||||
'addresses': {
|
||||
'type': 'object',
|
||||
'patternProperties': {
|
||||
'^.+$': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'addr': {
|
||||
'type': 'string',
|
||||
'oneOf': [
|
||||
{'format': 'ipv4'},
|
||||
{'format': 'ipv6'},
|
||||
],
|
||||
},
|
||||
'version': {
|
||||
'type': 'number',
|
||||
'enum': [4, 6],
|
||||
},
|
||||
},
|
||||
'required': [
|
||||
'addr',
|
||||
'version'
|
||||
],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
'adminPass': {'type': ['null', 'string']},
|
||||
'created': {'type': 'string', 'format': 'date-time'},
|
||||
'fault': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'code': {'type': 'integer'},
|
||||
'created': {'type': 'string', 'format': 'date-time'},
|
||||
'details': {'type': 'string'},
|
||||
'message': {'type': 'string'},
|
||||
},
|
||||
'required': ['code', 'created', 'message'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
'flavor': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'id': {
|
||||
'type': 'string',
|
||||
},
|
||||
'links': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'href': {
|
||||
'type': 'string',
|
||||
'format': 'uri',
|
||||
},
|
||||
'rel': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
'required': [
|
||||
'href',
|
||||
'rel'
|
||||
],
|
||||
"additionalProperties": False,
|
||||
},
|
||||
},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
'hostId': {'type': 'string'},
|
||||
'id': {'type': 'string'},
|
||||
'image': {
|
||||
'oneOf': [
|
||||
{
|
||||
'type': 'string',
|
||||
'const': '',
|
||||
},
|
||||
{
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'id': {
|
||||
'type': 'string'
|
||||
},
|
||||
'links': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'href': {
|
||||
'type': 'string',
|
||||
'format': 'uri',
|
||||
},
|
||||
'rel': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
'required': [
|
||||
'href',
|
||||
'rel'
|
||||
],
|
||||
"additionalProperties": False,
|
||||
},
|
||||
},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
],
|
||||
},
|
||||
'links': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'href': {
|
||||
'type': 'string',
|
||||
'format': 'uri',
|
||||
},
|
||||
'rel': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
'required': [
|
||||
'href',
|
||||
'rel'
|
||||
],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'metadata': {
|
||||
'type': 'object',
|
||||
'patternProperties': {
|
||||
'^.+$': {
|
||||
'type': 'string'
|
||||
},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
'name': {'type': ['string', 'null']},
|
||||
'progress': {'type': ['null', 'number']},
|
||||
'status': {'type': 'string'},
|
||||
'tenant_id': {'type': 'string', 'format': 'uuid'},
|
||||
'updated': {'type': 'string', 'format': 'date-time'},
|
||||
'user_id': {'type': 'string'},
|
||||
'OS-DCF:diskConfig': {'type': 'string'},
|
||||
},
|
||||
'required': [
|
||||
'accessIPv4',
|
||||
'accessIPv6',
|
||||
'addresses',
|
||||
'created',
|
||||
'flavor',
|
||||
'hostId',
|
||||
'id',
|
||||
'image',
|
||||
'links',
|
||||
'metadata',
|
||||
'name',
|
||||
'progress',
|
||||
'status',
|
||||
'tenant_id',
|
||||
'updated',
|
||||
'user_id',
|
||||
'OS-DCF:diskConfig',
|
||||
],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': [
|
||||
'server'
|
||||
],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
rebuild_response_v29 = copy.deepcopy(rebuild_response)
|
||||
rebuild_response_v29['properties']['server']['properties']['locked'] = {
|
||||
'type': 'boolean',
|
||||
}
|
||||
rebuild_response_v29['properties']['server']['required'].append('locked')
|
||||
|
||||
rebuild_response_v219 = copy.deepcopy(rebuild_response_v29)
|
||||
rebuild_response_v219['properties']['server']['properties']['description'] = {
|
||||
'type': ['null', 'string'],
|
||||
}
|
||||
rebuild_response_v219['properties']['server']['required'].append('description')
|
||||
|
||||
rebuild_response_v226 = copy.deepcopy(rebuild_response_v219)
|
||||
rebuild_response_v226['properties']['server']['properties']['tags'] = {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'string',
|
||||
},
|
||||
'maxItems': 50,
|
||||
}
|
||||
rebuild_response_v226['properties']['server']['required'].append('tags')
|
||||
|
||||
# NOTE(stephenfin): We overwrite rather than extend 'flavor', since we now
|
||||
# embed the flavor in this version
|
||||
rebuild_response_v246 = copy.deepcopy(rebuild_response_v226)
|
||||
rebuild_response_v246['properties']['server']['properties']['flavor'] = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'vcpus': {
|
||||
'type': 'integer',
|
||||
},
|
||||
'ram': {
|
||||
'type': 'integer',
|
||||
},
|
||||
'disk': {
|
||||
'type': 'integer',
|
||||
},
|
||||
'ephemeral': {
|
||||
'type': 'integer',
|
||||
},
|
||||
'swap': {
|
||||
'type': 'integer',
|
||||
},
|
||||
'original_name': {
|
||||
'type': 'string',
|
||||
},
|
||||
'extra_specs': {
|
||||
'type': 'object',
|
||||
'patternProperties': {
|
||||
'^.+$': {
|
||||
'type': 'string'
|
||||
},
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['vcpus', 'ram', 'disk', 'ephemeral', 'swap', 'original_name'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
rebuild_response_v254 = copy.deepcopy(rebuild_response_v246)
|
||||
rebuild_response_v254['properties']['server']['properties']['key_name'] = {
|
||||
'type': ['null', 'string'],
|
||||
}
|
||||
rebuild_response_v254['properties']['server']['required'].append('key_name')
|
||||
|
||||
rebuild_response_v257 = copy.deepcopy(rebuild_response_v254)
|
||||
rebuild_response_v257['properties']['server']['properties']['user_data'] = {
|
||||
'oneOf': [
|
||||
{'type': 'string', 'format': 'base64', 'maxLength': 65535},
|
||||
{'type': 'null'},
|
||||
],
|
||||
}
|
||||
rebuild_response_v257['properties']['server']['required'].append('user_data')
|
||||
|
||||
rebuild_response_v263 = copy.deepcopy(rebuild_response_v257)
|
||||
rebuild_response_v263['properties']['server']['properties'].update(
|
||||
{
|
||||
'trusted_image_certificates': {
|
||||
'type': ['array', 'null'],
|
||||
'items': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
rebuild_response_v263['properties']['server']['required'].append(
|
||||
'trusted_image_certificates'
|
||||
)
|
||||
|
||||
rebuild_response_v271 = copy.deepcopy(rebuild_response_v263)
|
||||
rebuild_response_v271['properties']['server']['properties'].update(
|
||||
{
|
||||
'server_groups': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'string',
|
||||
'format': 'uuid',
|
||||
},
|
||||
'maxLength': 1,
|
||||
},
|
||||
},
|
||||
)
|
||||
rebuild_response_v271['properties']['server']['required'].append(
|
||||
'server_groups'
|
||||
)
|
||||
|
||||
rebuild_response_v273 = copy.deepcopy(rebuild_response_v271)
|
||||
rebuild_response_v273['properties']['server']['properties'].update(
|
||||
{
|
||||
'locked_reason': {
|
||||
'type': ['null', 'string'],
|
||||
},
|
||||
},
|
||||
)
|
||||
rebuild_response_v273['properties']['server']['required'].append(
|
||||
'locked_reason'
|
||||
)
|
||||
|
||||
rebuild_response_v275 = copy.deepcopy(rebuild_response_v273)
|
||||
rebuild_response_v275['properties']['server']['properties'].update(
|
||||
{
|
||||
'config_drive': {
|
||||
# TODO(stephenfin): Our tests return null but this shouldn't happen
|
||||
# in practice, apparently?
|
||||
'type': ['string', 'boolean', 'null'],
|
||||
},
|
||||
'OS-EXT-AZ:availability_zone': {
|
||||
'type': 'string',
|
||||
},
|
||||
'OS-EXT-SRV-ATTR:host': {
|
||||
'type': ['string', 'null'],
|
||||
},
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname': {
|
||||
'type': ['string', 'null'],
|
||||
},
|
||||
'OS-EXT-SRV-ATTR:instance_name': {
|
||||
'type': 'string',
|
||||
},
|
||||
'OS-EXT-STS:power_state': {
|
||||
'type': 'integer',
|
||||
'enum': [0, 1, 3, 4, 6, 7],
|
||||
},
|
||||
'OS-EXT-STS:task_state': {
|
||||
'type': ['null', 'string'],
|
||||
},
|
||||
'OS-EXT-STS:vm_state': {
|
||||
'type': 'string',
|
||||
},
|
||||
'OS-EXT-SRV-ATTR:hostname': {
|
||||
'type': 'string',
|
||||
},
|
||||
'OS-EXT-SRV-ATTR:reservation_id': {
|
||||
'type': ['string', 'null'],
|
||||
},
|
||||
'OS-EXT-SRV-ATTR:launch_index': {
|
||||
'type': 'integer',
|
||||
},
|
||||
'OS-EXT-SRV-ATTR:kernel_id': {
|
||||
'type': ['string', 'null'],
|
||||
},
|
||||
'OS-EXT-SRV-ATTR:ramdisk_id': {
|
||||
'type': ['string', 'null'],
|
||||
},
|
||||
'OS-EXT-SRV-ATTR:root_device_name': {
|
||||
'type': ['string', 'null'],
|
||||
},
|
||||
'os-extended-volumes:volumes_attached': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'id': {
|
||||
'type': 'string',
|
||||
},
|
||||
'delete_on_termination': {
|
||||
'type': 'boolean',
|
||||
'default': False,
|
||||
},
|
||||
},
|
||||
'required': ['id', 'delete_on_termination'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'OS-SRV-USG:launched_at': {
|
||||
'oneOf': [
|
||||
{'type': 'null'},
|
||||
{'type': 'string', 'format': 'date-time'},
|
||||
],
|
||||
},
|
||||
'OS-SRV-USG:terminated_at': {
|
||||
'oneOf': [
|
||||
{'type': 'null'},
|
||||
{'type': 'string', 'format': 'date-time'},
|
||||
],
|
||||
},
|
||||
'security_groups': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'name': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
'required': ['name'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'host_status': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
)
|
||||
rebuild_response_v275['properties']['server']['required'].extend([
|
||||
'config_drive',
|
||||
'OS-EXT-AZ:availability_zone',
|
||||
'OS-EXT-STS:power_state',
|
||||
'OS-EXT-STS:task_state',
|
||||
'OS-EXT-STS:vm_state',
|
||||
'os-extended-volumes:volumes_attached',
|
||||
'OS-SRV-USG:launched_at',
|
||||
'OS-SRV-USG:terminated_at',
|
||||
])
|
||||
rebuild_response_v275['properties']['server']['properties']['addresses'][
|
||||
'patternProperties'
|
||||
]['^.+$']['items']['properties'].update({
|
||||
'OS-EXT-IPS-MAC:mac_addr': {'type': 'string', 'format': 'mac-address'},
|
||||
'OS-EXT-IPS:type': {'type': 'string', 'enum': ['fixed', 'floating']},
|
||||
})
|
||||
rebuild_response_v275['properties']['server']['properties']['addresses'][
|
||||
'patternProperties'
|
||||
]['^.+$']['items']['required'].extend([
|
||||
'OS-EXT-IPS-MAC:mac_addr', 'OS-EXT-IPS:type'
|
||||
])
|
||||
|
||||
rebuild_response_v296 = copy.deepcopy(rebuild_response_v275)
|
||||
rebuild_response_v296['properties']['server']['properties'].update({
|
||||
'pinned_availability_zone': {
|
||||
'type': ['null', 'string'],
|
||||
},
|
||||
})
|
||||
rebuild_response_v296['properties']['server']['required'].append(
|
||||
'pinned_availability_zone'
|
||||
)
|
||||
|
||||
@@ -1163,6 +1163,29 @@ class ServersController(wsgi.Controller):
|
||||
@validation.schema(schema.rebuild_v263, '2.63', '2.89')
|
||||
@validation.schema(schema.rebuild_v290, '2.90', '2.93')
|
||||
@validation.schema(schema.rebuild_v294, '2.94')
|
||||
@validation.response_body_schema(schema.rebuild_response, '2.0', '2.8')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v29, '2.9', '2.18')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v219, '2.19', '2.25')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v226, '2.26', '2.45')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v246, '2.46', '2.53')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v254, '2.54', '2.56')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v257, '2.57', '2.62')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v263, '2.63', '2.70')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v271, '2.71', '2.72')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v273, '2.73', '2.74')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v275, '2.75', '2.95')
|
||||
@validation.response_body_schema(
|
||||
schema.rebuild_response_v296, '2.96')
|
||||
def _action_rebuild(self, req, id, body):
|
||||
"""Rebuild an instance with the given attributes."""
|
||||
rebuild_dict = body['rebuild']
|
||||
@@ -1333,6 +1356,9 @@ class ServersController(wsgi.Controller):
|
||||
@wsgi.action('createImage')
|
||||
@validation.schema(schema.create_image, '2.0', '2.0')
|
||||
@validation.schema(schema.create_image, '2.1')
|
||||
@validation.response_body_schema(
|
||||
schema.create_image_response, '2.0', '2.44')
|
||||
@validation.response_body_schema(schema.create_image_response_v245, '2.45')
|
||||
def _action_create_image(self, req, id, body):
|
||||
"""Snapshot a server instance."""
|
||||
context = req.environ['nova.context']
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"flavor_access": [
|
||||
{
|
||||
"flavor_id": "%(flavor_id)s",
|
||||
"tenant_id": "fake_tenant"
|
||||
"tenant_id": "%(tenant_id)s"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from nova.tests.functional.api_sample_tests import api_sample_base
|
||||
|
||||
|
||||
@@ -21,7 +20,7 @@ class FlavorAccessTestsBase(api_sample_base.ApiSampleTestBaseV21):
|
||||
|
||||
def _add_tenant(self):
|
||||
subs = {
|
||||
'tenant_id': 'fake_tenant',
|
||||
'tenant_id': self.api.project_id,
|
||||
'flavor_id': '10',
|
||||
}
|
||||
response = self._do_post('flavors/10/action',
|
||||
@@ -49,7 +48,7 @@ class FlavorAccessSampleJsonTests(FlavorAccessTestsBase):
|
||||
response = self._do_get('flavors/%s/os-flavor-access' % flavor_id)
|
||||
subs = {
|
||||
'flavor_id': flavor_id,
|
||||
'tenant_id': 'fake_tenant',
|
||||
'tenant_id': self.api.project_id,
|
||||
}
|
||||
self._verify_response('flavor-access-list-resp', subs, response, 200)
|
||||
|
||||
@@ -61,7 +60,7 @@ class FlavorAccessSampleJsonTests(FlavorAccessTestsBase):
|
||||
self._create_flavor()
|
||||
self._add_tenant()
|
||||
subs = {
|
||||
'tenant_id': 'fake_tenant',
|
||||
'tenant_id': self.api.project_id,
|
||||
}
|
||||
response = self._do_post('flavors/10/action',
|
||||
"flavor-access-remove-tenant-req",
|
||||
@@ -88,7 +87,7 @@ class FlavorAccessV27SampleJsonTests(FlavorAccessTestsBase):
|
||||
|
||||
subs = {
|
||||
'flavor_id': '10',
|
||||
'tenant_id': 'fake_tenant'
|
||||
'tenant_id': self.api.project_id
|
||||
}
|
||||
# Version 2.7+ will return HTTPConflict (409)
|
||||
# if the flavor is public
|
||||
|
||||
@@ -75,7 +75,7 @@ class TestFlavorNotificationSample(
|
||||
|
||||
body = {
|
||||
"addTenantAccess": {
|
||||
"tenant": "fake_tenant"
|
||||
"tenant": "6f70656e737461636b20342065766572"
|
||||
}
|
||||
}
|
||||
self.admin_api.api_post(
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from oslo_utils.fixture import uuidsentinel as uuids
|
||||
from oslo_utils import timeutils
|
||||
import webob
|
||||
|
||||
from nova.api.openstack import common
|
||||
from nova.api.openstack.compute import create_backup \
|
||||
as create_backup_v21
|
||||
from nova.api.openstack.compute import create_backup
|
||||
from nova.compute import api
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova import exception
|
||||
@@ -32,7 +32,7 @@ from nova.tests.unit import fake_instance
|
||||
|
||||
class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
test.NoDBTestCase):
|
||||
create_backup = create_backup_v21
|
||||
create_backup = create_backup
|
||||
controller_name = 'CreateBackupController'
|
||||
validation_error = exception.ValidationError
|
||||
|
||||
@@ -54,7 +54,7 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
},
|
||||
}
|
||||
|
||||
image = dict(id='fake-image-id', status='ACTIVE', name='Backup 1',
|
||||
image = dict(id=uuids.image_id, status='ACTIVE', name='Backup 1',
|
||||
properties=metadata)
|
||||
|
||||
instance = fake_instance.fake_instance_obj(self.context)
|
||||
@@ -70,7 +70,7 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
extra_properties=metadata)
|
||||
|
||||
self.assertEqual(202, res.status_int)
|
||||
self.assertIn('fake-image-id', res.headers['Location'])
|
||||
self.assertIn(uuids.image_id, res.headers['Location'])
|
||||
|
||||
def test_create_backup_no_name(self):
|
||||
# Name is required for backups.
|
||||
@@ -107,7 +107,7 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
'rotation': 1,
|
||||
},
|
||||
}
|
||||
image = dict(id='fake-image-id', status='ACTIVE', name='Backup 1',
|
||||
image = dict(id=uuids.image_id, status='ACTIVE', name='Backup 1',
|
||||
properties={})
|
||||
instance = fake_instance.fake_instance_obj(self.context)
|
||||
self.mock_get.return_value = instance
|
||||
@@ -217,7 +217,7 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
},
|
||||
}
|
||||
|
||||
image = dict(id='fake-image-id', status='ACTIVE', name='Backup 1',
|
||||
image = dict(id=uuids.image_id, status='ACTIVE', name='Backup 1',
|
||||
properties={})
|
||||
instance = fake_instance.fake_instance_obj(self.context)
|
||||
self.mock_get.return_value = instance
|
||||
@@ -246,7 +246,7 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
},
|
||||
}
|
||||
|
||||
image = dict(id='fake-image-id', status='ACTIVE', name='Backup 1',
|
||||
image = dict(id=uuids.image_id, status='ACTIVE', name='Backup 1',
|
||||
properties={})
|
||||
instance = fake_instance.fake_instance_obj(self.context)
|
||||
self.mock_get.return_value = instance
|
||||
@@ -261,7 +261,7 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
extra_properties={})
|
||||
|
||||
self.assertEqual(202, res.status_int)
|
||||
self.assertIn('fake-image-id', res.headers['Location'])
|
||||
self.assertIn(uuids.image_id, res.headers['Location'])
|
||||
|
||||
@mock.patch.object(common, 'check_img_metadata_properties_quota')
|
||||
@mock.patch.object(api.API, 'backup')
|
||||
@@ -275,7 +275,7 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
},
|
||||
}
|
||||
|
||||
image = dict(id='fake-image-id', status='ACTIVE', name='Backup 1',
|
||||
image = dict(id=uuids.image_id, status='ACTIVE', name='Backup 1',
|
||||
properties={})
|
||||
instance = fake_instance.fake_instance_obj(self.context)
|
||||
self.mock_get.return_value = instance
|
||||
@@ -289,11 +289,11 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
'daily', 1,
|
||||
extra_properties={})
|
||||
self.assertEqual(202, res.status_int)
|
||||
self.assertIn('fake-image-id', res.headers['Location'])
|
||||
self.assertIn(uuids.image_id, res.headers['Location'])
|
||||
|
||||
@mock.patch.object(common, 'check_img_metadata_properties_quota')
|
||||
@mock.patch.object(api.API, 'backup', return_value=dict(
|
||||
id='fake-image-id', status='ACTIVE', name='Backup 1', properties={}))
|
||||
id=uuids.image_id, status='ACTIVE', name='Backup 1', properties={}))
|
||||
def test_create_backup_v2_45(self, mock_backup, mock_check_image):
|
||||
"""Tests the 2.45 microversion to ensure the Location header is not
|
||||
in the response.
|
||||
@@ -310,7 +310,7 @@ class CreateBackupTestsV21(admin_only_action_common.CommonMixin,
|
||||
req = fakes.HTTPRequest.blank('', version='2.45')
|
||||
res = self.controller._create_backup(req, instance['uuid'], body=body)
|
||||
self.assertIsInstance(res, dict)
|
||||
self.assertEqual('fake-image-id', res['image_id'])
|
||||
self.assertEqual(uuids.image_id, res['image_id'])
|
||||
|
||||
@mock.patch.object(common, 'check_img_metadata_properties_quota')
|
||||
@mock.patch.object(api.API, 'backup')
|
||||
@@ -396,7 +396,7 @@ class CreateBackupTestsV239(test.NoDBTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(CreateBackupTestsV239, self).setUp()
|
||||
self.controller = create_backup_v21.CreateBackupController()
|
||||
self.controller = create_backup.CreateBackupController()
|
||||
self.req = fakes.HTTPRequest.blank('', version='2.39')
|
||||
|
||||
@mock.patch.object(common, 'check_img_metadata_properties_quota')
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
import datetime
|
||||
from unittest import mock
|
||||
|
||||
from oslo_utils.fixture import uuidsentinel as uuids
|
||||
from webob import exc
|
||||
|
||||
from nova.api.openstack import api_version_request as api_version
|
||||
from nova.api.openstack.compute import flavor_access \
|
||||
as flavor_access_v21
|
||||
from nova.api.openstack.compute import flavor_access
|
||||
from nova.api.openstack.compute import flavors as flavors_api
|
||||
from nova import context
|
||||
from nova import exception
|
||||
@@ -57,9 +57,9 @@ FLAVORS = {
|
||||
|
||||
|
||||
ACCESS_LIST = [
|
||||
{'flavor_id': '2', 'project_id': 'proj2'},
|
||||
{'flavor_id': '2', 'project_id': 'proj3'},
|
||||
{'flavor_id': '3', 'project_id': 'proj3'},
|
||||
{'flavor_id': '2', 'project_id': uuids.proj2},
|
||||
{'flavor_id': '2', 'project_id': uuids.proj3},
|
||||
{'flavor_id': '3', 'project_id': uuids.proj3},
|
||||
]
|
||||
|
||||
|
||||
@@ -126,8 +126,8 @@ def fake_get_flavor_projects_from_db(context, flavorid):
|
||||
|
||||
class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
api_version = "2.1"
|
||||
FlavorAccessController = flavor_access_v21.FlavorAccessController
|
||||
FlavorActionController = flavor_access_v21.FlavorActionController
|
||||
FlavorAccessController = flavor_access.FlavorAccessController
|
||||
FlavorActionController = flavor_access.FlavorActionController
|
||||
_prefix = "/v2/%s" % fakes.FAKE_PROJECT_ID
|
||||
validation_ex = exception.ValidationError
|
||||
|
||||
@@ -175,8 +175,8 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
req.environ = {"nova.context": context.RequestContext(
|
||||
'fake_user', fakes.FAKE_PROJECT_ID)}
|
||||
expected = {'flavor_access': [
|
||||
{'flavor_id': '2', 'tenant_id': 'proj2'},
|
||||
{'flavor_id': '2', 'tenant_id': 'proj3'}]}
|
||||
{'flavor_id': '2', 'tenant_id': uuids.proj2},
|
||||
{'flavor_id': '2', 'tenant_id': uuids.proj3}]}
|
||||
result = self.flavor_access_controller.index(req, '2')
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
@@ -192,7 +192,7 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
expected = {'flavors': [{'id': '0'}, {'id': '1'}, {'id': '2'}]}
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors',
|
||||
use_admin_context=True)
|
||||
req.environ['nova.context'].project_id = 'proj2'
|
||||
req.environ['nova.context'].project_id = uuids.proj2
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
@@ -217,7 +217,7 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
url = self._prefix + '/flavors?is_public=false'
|
||||
req = fakes.HTTPRequest.blank(url,
|
||||
use_admin_context=True)
|
||||
req.environ['nova.context'].project_id = 'proj2'
|
||||
req.environ['nova.context'].project_id = uuids.proj2
|
||||
result = self.flavor_controller.index(req)
|
||||
self._verify_flavor_list(result['flavors'], expected['flavors'])
|
||||
|
||||
@@ -264,12 +264,13 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
def test_add_tenant_access(self):
|
||||
def stub_add_flavor_access(context, flavor_id, projectid):
|
||||
self.assertEqual(3, flavor_id, "flavor_id")
|
||||
self.assertEqual("proj2", projectid, "projectid")
|
||||
self.assertEqual(uuids.proj2, projectid, "projectid")
|
||||
self.stub_out('nova.objects.Flavor._flavor_add_project',
|
||||
stub_add_flavor_access)
|
||||
expected = {'flavor_access':
|
||||
[{'flavor_id': '3', 'tenant_id': 'proj3'}]}
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
expected = {
|
||||
'flavor_access': [{'flavor_id': '3', 'tenant_id': uuids.proj3}]
|
||||
}
|
||||
body = {'addTenantAccess': {'tenant': uuids.proj2}}
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
|
||||
@@ -280,7 +281,7 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
@mock.patch('nova.objects.Flavor.get_by_flavor_id',
|
||||
side_effect=exception.FlavorNotFound(flavor_id='1'))
|
||||
def test_add_tenant_access_with_flavor_not_found(self, mock_get):
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
body = {'addTenantAccess': {'tenant': uuids.proj2}}
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
@@ -290,7 +291,7 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
def test_add_tenant_access_with_no_tenant(self):
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
body = {'addTenantAccess': {'foo': 'proj2'}}
|
||||
body = {'addTenantAccess': {'foo': uuids.proj2}}
|
||||
self.assertRaises(self.validation_ex,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '2', body=body)
|
||||
@@ -309,7 +310,7 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
self._prefix + '/flavors/3/os-flavor-access')
|
||||
req.environ = {"nova.context": context.RequestContext(
|
||||
'fake_user', fakes.FAKE_PROJECT_ID)}
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
body = {'addTenantAccess': {'tenant': uuids.proj2}}
|
||||
self.assertRaises(exc.HTTPConflict,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '3', body=body)
|
||||
@@ -320,7 +321,7 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
project_id=projectid)
|
||||
self.stub_out('nova.objects.Flavor._flavor_del_project',
|
||||
stub_remove_flavor_access)
|
||||
body = {'removeTenantAccess': {'tenant': 'proj2'}}
|
||||
body = {'removeTenantAccess': {'tenant': uuids.proj2}}
|
||||
req = fakes.HTTPRequest.blank(
|
||||
self._prefix + '/flavors/3/os-flavor-access')
|
||||
req.environ = {"nova.context": context.RequestContext(
|
||||
@@ -330,7 +331,7 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
req, '3', body=body)
|
||||
|
||||
def test_add_tenant_access_is_public(self):
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
body = {'addTenantAccess': {'tenant': uuids.proj2}}
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
req.api_version_request = api_version.APIVersionRequest('2.7')
|
||||
@@ -343,7 +344,7 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
def test_delete_tenant_access_with_no_tenant(self, mock_api_get):
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
body = {'removeTenantAccess': {'foo': 'proj2'}}
|
||||
body = {'removeTenantAccess': {'foo': uuids.proj2}}
|
||||
self.assertRaises(self.validation_ex,
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '2', body=body)
|
||||
@@ -359,30 +360,32 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
"""Tests the case that the tenant does not exist in Keystone."""
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
body = {'addTenantAccess': {'tenant': 'proj2'}}
|
||||
body = {'addTenantAccess': {'tenant': uuids.proj2}}
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._add_tenant_access,
|
||||
req, '2', body=body)
|
||||
mock_verify.assert_called_once_with(
|
||||
req.environ['nova.context'], 'proj2')
|
||||
req.environ['nova.context'], uuids.proj2)
|
||||
|
||||
@mock.patch('nova.objects.Flavor.remove_access')
|
||||
@mock.patch('nova.api.openstack.identity.verify_project_id',
|
||||
side_effect=exc.HTTPBadRequest(
|
||||
explanation="Project ID proj2 is not a valid project."))
|
||||
@mock.patch('nova.api.openstack.identity.verify_project_id')
|
||||
def test_remove_tenant_access_with_invalid_tenant(self,
|
||||
mock_verify,
|
||||
mock_remove_access):
|
||||
"""Tests the case that the tenant does not exist in Keystone."""
|
||||
mock_verify.side_effect = exc.HTTPBadRequest(explanation=(
|
||||
f"Project ID {uuids.proj2} is not a valid project."
|
||||
))
|
||||
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
body = {'removeTenantAccess': {'tenant': 'proj2'}}
|
||||
body = {'removeTenantAccess': {'tenant': uuids.proj2}}
|
||||
|
||||
self.flavor_action_controller._remove_tenant_access(
|
||||
req, '2', body=body)
|
||||
mock_verify.assert_called_once_with(
|
||||
req.environ['nova.context'], 'proj2')
|
||||
mock_remove_access.assert_called_once_with('proj2')
|
||||
req.environ['nova.context'], uuids.proj2)
|
||||
mock_remove_access.assert_called_once_with(uuids.proj2)
|
||||
|
||||
@mock.patch('nova.api.openstack.identity.verify_project_id',
|
||||
side_effect=exc.HTTPBadRequest(
|
||||
@@ -395,10 +398,10 @@ class FlavorAccessTestV21(test.NoDBTestCase):
|
||||
"""
|
||||
req = fakes.HTTPRequest.blank(self._prefix + '/flavors/2/action',
|
||||
use_admin_context=True)
|
||||
body = {'removeTenantAccess': {'tenant': 'proj2'}}
|
||||
body = {'removeTenantAccess': {'tenant': uuids.proj2}}
|
||||
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.flavor_action_controller._remove_tenant_access,
|
||||
req, '2', body=body)
|
||||
mock_verify.assert_called_once_with(
|
||||
req.environ['nova.context'], 'proj2')
|
||||
req.environ['nova.context'], uuids.proj2)
|
||||
|
||||
@@ -395,7 +395,7 @@ class KeypairsTestV210(KeypairsTestV22):
|
||||
with mock.patch.object(self.controller.api, 'get_key_pairs') as mock_g:
|
||||
self.controller.index(req)
|
||||
userid = mock_g.call_args_list[0][0][1]
|
||||
self.assertEqual('fake_user', userid)
|
||||
self.assertEqual(fakes.FAKE_USER_ID, userid)
|
||||
|
||||
|
||||
class KeypairsTestV235(test.TestCase):
|
||||
@@ -421,7 +421,7 @@ class KeypairsTestV235(test.TestCase):
|
||||
res_dict = self.controller.index(req)
|
||||
|
||||
mock_kp_get.assert_called_once_with(
|
||||
req.environ['nova.context'], 'fake_user',
|
||||
req.environ['nova.context'], fakes.FAKE_USER_ID,
|
||||
limit=3, marker='fake_marker')
|
||||
response = {'keypairs': [{'keypair': dict(keypair_data, name='FAKE',
|
||||
type='ssh')}]}
|
||||
@@ -458,7 +458,7 @@ class KeypairsTestV235(test.TestCase):
|
||||
self.controller.index(req)
|
||||
|
||||
mock_kp_get.assert_called_once_with(
|
||||
req.environ['nova.context'], 'fake_user',
|
||||
req.environ['nova.context'], fakes.FAKE_USER_ID,
|
||||
limit=None, marker=None)
|
||||
|
||||
|
||||
|
||||
@@ -1002,12 +1002,15 @@ class ServerActionsControllerTestV21(test.TestCase):
|
||||
response = self.controller._action_create_image(self.req, FAKE_UUID,
|
||||
body=body)
|
||||
|
||||
location = response.headers['Location']
|
||||
self.assertEqual(self.image_url + '123' if self.image_url else
|
||||
self.image_api.generate_image_url('123', self.context),
|
||||
location)
|
||||
if self.image_url:
|
||||
expected_location = self.image_url + uuids.snapshot_id
|
||||
else:
|
||||
expected_location = self.image_api.generate_image_url(
|
||||
uuids.snapshot_id, self.context
|
||||
)
|
||||
self.assertEqual(response.headers['Location'], expected_location)
|
||||
|
||||
def test_create_image_v2_45(self):
|
||||
def test_create_image_v245(self):
|
||||
"""Tests the createImage server action API with the 2.45 microversion
|
||||
where there is a response body but no Location header.
|
||||
"""
|
||||
@@ -1020,7 +1023,7 @@ class ServerActionsControllerTestV21(test.TestCase):
|
||||
response = self.controller._action_create_image(req, FAKE_UUID,
|
||||
body=body)
|
||||
self.assertIsInstance(response, dict)
|
||||
self.assertEqual('123', response['image_id'])
|
||||
self.assertEqual(uuids.snapshot_id, response['image_id'])
|
||||
|
||||
def test_create_image_name_too_long(self):
|
||||
long_name = 'a' * 260
|
||||
@@ -1254,9 +1257,13 @@ class ServerActionsControllerTestV21(test.TestCase):
|
||||
response = self.controller._action_create_image(self.req, FAKE_UUID,
|
||||
body=body)
|
||||
|
||||
location = response.headers['Location']
|
||||
self.assertEqual(self.image_url + '123' if self.image_url else
|
||||
self.image_api.generate_image_url('123', self.context), location)
|
||||
if self.image_url:
|
||||
expected_location = self.image_url + uuids.snapshot_id
|
||||
else:
|
||||
expected_location = self.image_api.generate_image_url(
|
||||
uuids.snapshot_id, self.context
|
||||
)
|
||||
self.assertEqual(response.headers['Location'], expected_location)
|
||||
|
||||
def test_create_image_with_too_much_metadata(self):
|
||||
body = {
|
||||
|
||||
@@ -171,7 +171,7 @@ def fake_get_inst_mappings_by_instance_uuids_from_db(*args, **kwargs):
|
||||
'transport_url': 'fake://nowhere/', 'updated_at': None,
|
||||
'database_connection': uuids.cell1, 'created_at': None,
|
||||
'disabled': False},
|
||||
'project_id': 'fake-project'
|
||||
'project_id': fakes.FAKE_PROJECT_ID,
|
||||
}]
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@ class _ServersControllerTest(ControllerTest):
|
||||
return {
|
||||
"server": {
|
||||
"id": uuid,
|
||||
"user_id": "fake_user",
|
||||
"user_id": fakes.FAKE_USER_ID,
|
||||
"created": "2010-10-10T12:00:00Z",
|
||||
"updated": "2010-11-11T11:00:00Z",
|
||||
"progress": progress,
|
||||
@@ -3767,6 +3767,21 @@ class ServersControllerRebuildTestV275(ControllerTest):
|
||||
microversion = '2.75'
|
||||
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
mock_rebuild = mock.patch(
|
||||
'nova.compute.api.API.rebuild', return_value=None)
|
||||
self.mock_rebuild = mock_rebuild.start()
|
||||
self.addCleanup(mock_rebuild.stop)
|
||||
|
||||
self.mock_get_instance_host_status = self.useFixture(
|
||||
fixtures.MockPatchObject(
|
||||
compute_api.API, 'get_instance_host_status',
|
||||
return_value='UP'
|
||||
)
|
||||
).mock
|
||||
|
||||
def test_rebuild_response_no_show_server_only_attributes_old_version(self):
|
||||
# There are some old server attributes which were added only for
|
||||
# GET server APIs not for Rebuild. GET server and Rebuild server share
|
||||
@@ -3799,11 +3814,29 @@ class ServersControllerRebuildTestV275(ControllerTest):
|
||||
req = fakes.HTTPRequest.blank(self.path_with_query % 'unknown=1',
|
||||
use_admin_context=True,
|
||||
version=self.microversion)
|
||||
fake_get = fakes.fake_compute_get(
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2,
|
||||
display_description="",
|
||||
uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1",
|
||||
launch_index=0,
|
||||
kernel_id=UUID1,
|
||||
ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
host='host',
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova',
|
||||
launched_at=None,
|
||||
terminated_at=None,
|
||||
task_state="ACTIVE",
|
||||
vm_state=vm_states.ACTIVE,
|
||||
power_state=1,
|
||||
project_id=req.environ['nova.context'].project_id,
|
||||
user_id=req.environ['nova.context'].user_id)
|
||||
self.mock_get.side_effect = fake_get
|
||||
|
||||
res_dict = self.controller._action_rebuild(req, FAKE_UUID,
|
||||
body=body).obj
|
||||
for field in GET_ONLY_FIELDS:
|
||||
@@ -3829,6 +3862,13 @@ class ServersControllerRebuildTestV290(ControllerTest):
|
||||
self.mock_rebuild = mock_rebuild.start()
|
||||
self.addCleanup(mock_rebuild.stop)
|
||||
|
||||
self.mock_get_instance_host_status = self.useFixture(
|
||||
fixtures.MockPatchObject(
|
||||
compute_api.API, 'get_instance_host_status',
|
||||
return_value='UP'
|
||||
)
|
||||
).mock
|
||||
|
||||
def _get_request(self, body=None):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
self.path_action % FAKE_UUID,
|
||||
@@ -3851,6 +3891,29 @@ class ServersControllerRebuildTestV290(ControllerTest):
|
||||
}
|
||||
req = self._get_request(body)
|
||||
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2,
|
||||
display_description="",
|
||||
uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1",
|
||||
launch_index=0,
|
||||
kernel_id=UUID1,
|
||||
ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
host='host',
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova',
|
||||
launched_at=None,
|
||||
terminated_at=None,
|
||||
task_state="ACTIVE",
|
||||
vm_state=vm_states.ACTIVE,
|
||||
power_state=1,
|
||||
project_id=req.environ['nova.context'].project_id,
|
||||
user_id=req.environ['nova.context'].user_id)
|
||||
|
||||
# There's nothing to check here from the return value since the
|
||||
# 'rebuild' API is a cast and we immediately fetch the instance from
|
||||
# the database after this cast...which returns a mocked Instance
|
||||
@@ -5826,7 +5889,7 @@ class ServersControllerCreateTest(_ServersControllerCreateTest):
|
||||
mock_count.return_value = count
|
||||
mock_get_all_p.return_value = {'project_id': fakes.FAKE_PROJECT_ID}
|
||||
mock_get_all_pu.return_value = {'project_id': fakes.FAKE_PROJECT_ID,
|
||||
'user_id': 'fake_user'}
|
||||
'user_id': fakes.FAKE_USER_ID}
|
||||
if resource in db.PER_PROJECT_QUOTAS:
|
||||
mock_get_all_p.return_value[resource] = quota
|
||||
else:
|
||||
@@ -7235,7 +7298,7 @@ class ServersControllerCreateTestV274(_ServersControllerCreateTest):
|
||||
def setUp(self):
|
||||
super(ServersControllerCreateTestV274, self).setUp()
|
||||
self.req.environ['nova.context'] = fakes.FakeRequestContext(
|
||||
user_id='fake_user',
|
||||
user_id=fakes.FAKE_USER_ID,
|
||||
project_id=self.project_id,
|
||||
is_admin=True)
|
||||
self.mock_get = self.useFixture(
|
||||
@@ -7533,8 +7596,8 @@ class ServersViewBuilderTest(_ServersViewBuilderTest):
|
||||
expected_server = {
|
||||
"server": {
|
||||
"id": self.uuid,
|
||||
"user_id": "fake_user",
|
||||
"tenant_id": "fake_project",
|
||||
"user_id": fakes.FAKE_USER_ID,
|
||||
"tenant_id": fakes.FAKE_PROJECT_ID,
|
||||
"updated": "2010-11-11T11:00:00Z",
|
||||
"created": "2010-10-10T12:00:00Z",
|
||||
"progress": 0,
|
||||
@@ -7552,12 +7615,12 @@ class ServersViewBuilderTest(_ServersViewBuilderTest):
|
||||
},
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": flavor_bookmark,
|
||||
},
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": flavor_bookmark,
|
||||
},
|
||||
],
|
||||
},
|
||||
"addresses": {
|
||||
'test1': [
|
||||
@@ -7623,8 +7686,8 @@ class ServersViewBuilderTest(_ServersViewBuilderTest):
|
||||
expected_server = {
|
||||
"server": {
|
||||
"id": self.uuid,
|
||||
"user_id": "fake_user",
|
||||
"tenant_id": "fake_project",
|
||||
"user_id": fakes.FAKE_USER_ID,
|
||||
"tenant_id": fakes.FAKE_PROJECT_ID,
|
||||
"updated": "2010-11-11T11:00:00Z",
|
||||
"created": "2010-10-10T12:00:00Z",
|
||||
"name": "test_server",
|
||||
@@ -7641,12 +7704,12 @@ class ServersViewBuilderTest(_ServersViewBuilderTest):
|
||||
},
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": flavor_bookmark,
|
||||
},
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": flavor_bookmark,
|
||||
},
|
||||
],
|
||||
},
|
||||
"addresses": {
|
||||
'test1': [
|
||||
@@ -7822,8 +7885,8 @@ class ServersViewBuilderTest(_ServersViewBuilderTest):
|
||||
expected_server = {
|
||||
"server": {
|
||||
"id": self.uuid,
|
||||
"user_id": "fake_user",
|
||||
"tenant_id": "fake_project",
|
||||
"user_id": fakes.FAKE_USER_ID,
|
||||
"tenant_id": fakes.FAKE_PROJECT_ID,
|
||||
"updated": "2010-11-11T11:00:00Z",
|
||||
"created": "2010-10-10T12:00:00Z",
|
||||
"progress": 100,
|
||||
@@ -7841,12 +7904,12 @@ class ServersViewBuilderTest(_ServersViewBuilderTest):
|
||||
},
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": flavor_bookmark,
|
||||
},
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": flavor_bookmark,
|
||||
},
|
||||
],
|
||||
},
|
||||
"addresses": {
|
||||
'test1': [
|
||||
@@ -7914,8 +7977,8 @@ class ServersViewBuilderTest(_ServersViewBuilderTest):
|
||||
expected_server = {
|
||||
"server": {
|
||||
"id": self.uuid,
|
||||
"user_id": "fake_user",
|
||||
"tenant_id": "fake_project",
|
||||
"user_id": fakes.FAKE_USER_ID,
|
||||
"tenant_id": fakes.FAKE_PROJECT_ID,
|
||||
"updated": "2010-11-11T11:00:00Z",
|
||||
"created": "2010-10-10T12:00:00Z",
|
||||
"progress": 0,
|
||||
@@ -7934,7 +7997,7 @@ class ServersViewBuilderTest(_ServersViewBuilderTest):
|
||||
"flavor": {
|
||||
"id": "1",
|
||||
"links": [
|
||||
{
|
||||
{
|
||||
"rel": "bookmark",
|
||||
"href": flavor_bookmark,
|
||||
},
|
||||
@@ -8042,8 +8105,8 @@ class ServersViewBuilderTestV269(_ServersViewBuilderTest):
|
||||
expected = {
|
||||
"servers": [{
|
||||
"id": self.uuid,
|
||||
"user_id": "fake_user",
|
||||
"tenant_id": "fake_project",
|
||||
"user_id": fakes.FAKE_USER_ID,
|
||||
"tenant_id": fakes.FAKE_PROJECT_ID,
|
||||
"updated": "2010-11-11T11:00:00Z",
|
||||
"created": "2010-10-10T12:00:00Z",
|
||||
"progress": 0,
|
||||
@@ -8225,8 +8288,8 @@ class ServersViewBuilderTestV269(_ServersViewBuilderTest):
|
||||
expected = {
|
||||
"server": {
|
||||
"id": self.uuid,
|
||||
"user_id": "fake_user",
|
||||
"tenant_id": "fake_project",
|
||||
"user_id": fakes.FAKE_USER_ID,
|
||||
"tenant_id": fakes.FAKE_PROJECT_ID,
|
||||
"created": '1955-11-05T00:00:00Z',
|
||||
"status": "UNKNOWN",
|
||||
"image": {
|
||||
@@ -8288,7 +8351,7 @@ class ServersViewBuilderTestV269(_ServersViewBuilderTest):
|
||||
"server": {
|
||||
"id": self.uuid,
|
||||
"user_id": "UNKNOWN",
|
||||
"tenant_id": "fake_project",
|
||||
"tenant_id": fakes.FAKE_PROJECT_ID,
|
||||
"created": '1955-11-05T00:00:00Z',
|
||||
"status": "UNKNOWN",
|
||||
"image": "",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import datetime
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils.fixture import uuidsentinel as uuids
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import uuidutils
|
||||
import routes
|
||||
@@ -139,8 +140,10 @@ def stub_out_compute_api_snapshot(test):
|
||||
# emulate glance rejecting image names which are too long
|
||||
if len(name) > 256:
|
||||
raise exc.Invalid
|
||||
return dict(id='123', status='ACTIVE', name=name,
|
||||
properties=extra_properties)
|
||||
return {
|
||||
'id': uuids.snapshot_id, 'status': 'ACTIVE', 'name': name,
|
||||
'properties': extra_properties,
|
||||
}
|
||||
|
||||
test.stub_out('nova.compute.api.API.snapshot', snapshot)
|
||||
|
||||
@@ -154,10 +157,12 @@ class stub_out_compute_api_backup(object):
|
||||
def backup(self, context, instance, name, backup_type, rotation,
|
||||
extra_properties=None):
|
||||
self.extra_props_last_call = extra_properties
|
||||
props = dict(backup_type=backup_type,
|
||||
rotation=rotation)
|
||||
props = {'backup_type': backup_type, 'rotation': rotation}
|
||||
props.update(extra_properties or {})
|
||||
return dict(id='123', status='ACTIVE', name=name, properties=props)
|
||||
return {
|
||||
'id': uuids.backup_id, 'status': 'ACTIVE', 'name': name,
|
||||
'properties': props,
|
||||
}
|
||||
|
||||
|
||||
def stub_out_nw_api(test, cls=None, private=None, publics=None):
|
||||
@@ -244,11 +249,12 @@ class HTTPRequest(os_wsgi.Request):
|
||||
if use_admin_context:
|
||||
roles.append('admin')
|
||||
project_id = kwargs.pop('project_id', FAKE_PROJECT_ID)
|
||||
user_id = kwargs.pop('user_id', FAKE_USER_ID)
|
||||
version = kwargs.pop('version', os_wsgi.DEFAULT_API_VERSION)
|
||||
defaults.update(kwargs)
|
||||
out = super(HTTPRequest, cls).blank(*args, **defaults)
|
||||
out.environ['nova.context'] = FakeRequestContext(
|
||||
user_id='fake_user',
|
||||
user_id=user_id,
|
||||
project_id=project_id,
|
||||
is_admin=use_admin_context,
|
||||
roles=roles)
|
||||
@@ -434,9 +440,9 @@ def stub_instance(id=1, user_id=None, project_id=None, host=None,
|
||||
services=None, trusted_certs=None, hidden=False,
|
||||
compute_id=None):
|
||||
if user_id is None:
|
||||
user_id = 'fake_user'
|
||||
user_id = FAKE_USER_ID
|
||||
if project_id is None:
|
||||
project_id = 'fake_project'
|
||||
project_id = FAKE_PROJECT_ID
|
||||
|
||||
if metadata:
|
||||
metadata = [{'key': k, 'value': v} for k, v in metadata.items()]
|
||||
|
||||
@@ -20,6 +20,7 @@ from oslo_utils import timeutils
|
||||
from nova.api.openstack.compute import migrate_server
|
||||
from nova.api.openstack.compute import servers
|
||||
from nova.compute import api as compute
|
||||
from nova.compute import power_state
|
||||
from nova.compute import vm_states
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
@@ -63,14 +64,18 @@ class ServersPolicyTest(base.BasePolicyTest):
|
||||
self.controller._view_builder._add_security_grps = mock.MagicMock()
|
||||
self.controller._view_builder._get_metadata = mock.MagicMock()
|
||||
self.controller._view_builder._get_addresses = mock.MagicMock()
|
||||
self.controller._view_builder._get_host_id = mock.MagicMock()
|
||||
self.controller._view_builder._get_host_id = mock.MagicMock(
|
||||
return_value=''
|
||||
)
|
||||
self.controller._view_builder._get_fault = mock.MagicMock()
|
||||
|
||||
self.instance = fake_instance.fake_instance_obj(
|
||||
self.project_member_context,
|
||||
id=1, uuid=uuids.fake_id, project_id=self.project_id,
|
||||
user_id=user_id, vm_state=vm_states.ACTIVE,
|
||||
system_metadata={}, expected_attrs=['system_metadata'])
|
||||
self.project_member_context,
|
||||
id=1, uuid=uuids.fake_id, project_id=self.project_id,
|
||||
user_id=user_id, vm_state=vm_states.ACTIVE,
|
||||
system_metadata={}, expected_attrs=['system_metadata'],
|
||||
task_state=None, power_state=power_state.SHUTDOWN,
|
||||
hostname='foo', launch_index=0)
|
||||
|
||||
self.mock_flavor = self.useFixture(
|
||||
fixtures.MockPatch('nova.compute.flavors.get_flavor_by_flavor_id'
|
||||
@@ -912,7 +917,8 @@ class ServersPolicyTest(base.BasePolicyTest):
|
||||
self.assertNotIn(attr, resp['server'])
|
||||
|
||||
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
|
||||
@mock.patch('nova.compute.api.API.get_instance_host_status')
|
||||
@mock.patch('nova.compute.api.API.get_instance_host_status',
|
||||
return_value=fields.HostStatus.UP)
|
||||
@mock.patch('nova.compute.api.API.rebuild')
|
||||
def test_server_rebuild_with_extended_attr_policy(self, mock_rebuild,
|
||||
mock_get, mock_bdm):
|
||||
@@ -1011,7 +1017,8 @@ class ServersPolicyTest(base.BasePolicyTest):
|
||||
self.assertNotIn('host_status', resp['server'])
|
||||
|
||||
@mock.patch('nova.objects.BlockDeviceMappingList.bdms_by_instance_uuid')
|
||||
@mock.patch('nova.compute.api.API.get_instance_host_status')
|
||||
@mock.patch('nova.compute.api.API.get_instance_host_status',
|
||||
return_value=fields.HostStatus.UP)
|
||||
@mock.patch('nova.compute.api.API.rebuild')
|
||||
def test_server_rebuild_with_host_status_policy(self, mock_rebuild,
|
||||
mock_status, mock_bdm):
|
||||
|
||||
Reference in New Issue
Block a user