Implement 'personality' plugin for V2.1
User can specify 'personality' attribute while server creation & rebuild to inject files into server. This patch implement this as separate plugin for V2.1 API. Also define the schema and unit tests for the same. Partially implements blueprint v2-on-v3-api Change-Id: Ia0c527539af7fe33eba4999822476653e1b96bc6
This commit is contained in:
parent
b40ea7c0ec
commit
d99b308e6d
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"rebuild": {
|
||||||
|
"imageRef": "http://glance.openstack.example.com/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||||
|
"name": "new-server-test",
|
||||||
|
"metadata": {
|
||||||
|
"meta_var": "meta_val"
|
||||||
|
},
|
||||||
|
"personality": [
|
||||||
|
{
|
||||||
|
"path": "/etc/banner.txt",
|
||||||
|
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"addresses": {
|
||||||
|
"private": [
|
||||||
|
{
|
||||||
|
"addr": "192.168.0.3",
|
||||||
|
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||||
|
"OS-EXT-IPS:type": "fixed",
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"adminPass": "99WHAxN8gpvg",
|
||||||
|
"created": "2013-11-06T07:51:09Z",
|
||||||
|
"flavor": {
|
||||||
|
"id": "1",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "http://openstack.example.com/flavors/1",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hostId": "5c8072dbcda8ce3f26deb6662bd7718e1a6d349bdf2296911d1be4ac",
|
||||||
|
"id": "53a63a19-c145-47f8-9ae5-b39d6bff33ec",
|
||||||
|
"image": {
|
||||||
|
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "http://openstack.example.com/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "http://openstack.example.com/v3/servers/53a63a19-c145-47f8-9ae5-b39d6bff33ec",
|
||||||
|
"rel": "self"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": "http://openstack.example.com/servers/53a63a19-c145-47f8-9ae5-b39d6bff33ec",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"meta_var": "meta_val"
|
||||||
|
},
|
||||||
|
"name": "new-server-test",
|
||||||
|
"progress": 0,
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"tenant_id": "openstack",
|
||||||
|
"updated": "2013-11-06T07:51:11Z",
|
||||||
|
"user_id": "fake"
|
||||||
|
}
|
||||||
|
}
|
16
doc/v3/api_samples/os-personality/server-post-req.json
Normal file
16
doc/v3/api_samples/os-personality/server-post-req.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"name": "new-server-test",
|
||||||
|
"imageRef": "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b",
|
||||||
|
"flavorRef": "http://openstack.example.com/openstack/flavors/1",
|
||||||
|
"metadata": {
|
||||||
|
"My Server Name": "Apache1"
|
||||||
|
},
|
||||||
|
"personality": [
|
||||||
|
{
|
||||||
|
"path": "/etc/banner.txt",
|
||||||
|
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
16
doc/v3/api_samples/os-personality/server-post-resp.json
Normal file
16
doc/v3/api_samples/os-personality/server-post-resp.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"adminPass": "n7JGBda664QG",
|
||||||
|
"id": "934760e1-2b0b-4f9e-a916-eac1e69839dc",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "http://openstack.example.com/v3/servers/934760e1-2b0b-4f9e-a916-eac1e69839dc",
|
||||||
|
"rel": "self"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": "http://openstack.example.com/servers/934760e1-2b0b-4f9e-a916-eac1e69839dc",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -230,6 +230,7 @@
|
|||||||
"compute_extension:v3:os-pci:index": "rule:admin_api",
|
"compute_extension:v3:os-pci:index": "rule:admin_api",
|
||||||
"compute_extension:v3:os-pci:detail": "rule:admin_api",
|
"compute_extension:v3:os-pci:detail": "rule:admin_api",
|
||||||
"compute_extension:v3:os-pci:show": "rule:admin_api",
|
"compute_extension:v3:os-pci:show": "rule:admin_api",
|
||||||
|
"compute_extension:v3:os-personality:discoverable": "",
|
||||||
"compute_extension:quotas:show": "",
|
"compute_extension:quotas:show": "",
|
||||||
"compute_extension:quotas:update": "rule:admin_api",
|
"compute_extension:quotas:update": "rule:admin_api",
|
||||||
"compute_extension:quotas:delete": "rule:admin_api",
|
"compute_extension:quotas:delete": "rule:admin_api",
|
||||||
|
65
nova/api/openstack/compute/plugins/v3/personality.py
Normal file
65
nova/api/openstack/compute/plugins/v3/personality.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# Copyright 2014 NEC Corporation. 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.
|
||||||
|
|
||||||
|
from nova.api.openstack.compute.schemas.v3 import personality
|
||||||
|
from nova.api.openstack import extensions
|
||||||
|
|
||||||
|
ALIAS = "os-personality"
|
||||||
|
|
||||||
|
|
||||||
|
class Personality(extensions.V3APIExtensionBase):
|
||||||
|
"""Personality support."""
|
||||||
|
|
||||||
|
name = "Personality"
|
||||||
|
alias = ALIAS
|
||||||
|
version = 1
|
||||||
|
|
||||||
|
def get_controller_extensions(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_resources(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def _get_injected_files(self, personality):
|
||||||
|
"""Create a list of injected files from the personality attribute.
|
||||||
|
|
||||||
|
At this time, injected_files must be formatted as a list of
|
||||||
|
(file_path, file_content) pairs for compatibility with the
|
||||||
|
underlying compute service.
|
||||||
|
"""
|
||||||
|
injected_files = []
|
||||||
|
for item in personality:
|
||||||
|
injected_files.append((item['path'], item['contents']))
|
||||||
|
return injected_files
|
||||||
|
|
||||||
|
# NOTE(gmann): This function is not supposed to use 'body_deprecated_param'
|
||||||
|
# parameter as this is placed to handle scheduler_hint extension for V2.1.
|
||||||
|
# making 'body_deprecated_param' as optional to avoid changes for
|
||||||
|
# server_update & server_rebuild
|
||||||
|
def server_create(self, server_dict, create_kwargs,
|
||||||
|
body_deprecated_param=None):
|
||||||
|
if 'personality' in server_dict:
|
||||||
|
create_kwargs['injected_files'] = self._get_injected_files(
|
||||||
|
server_dict['personality'])
|
||||||
|
|
||||||
|
def server_rebuild(self, server_dict, create_kwargs,
|
||||||
|
body_deprecated_param=None):
|
||||||
|
if 'personality' in server_dict:
|
||||||
|
create_kwargs['files_to_inject'] = self._get_injected_files(
|
||||||
|
server_dict['personality'])
|
||||||
|
|
||||||
|
def get_server_create_schema(self):
|
||||||
|
return personality.server_create
|
||||||
|
|
||||||
|
get_server_rebuild_schema = get_server_create_schema
|
30
nova/api/openstack/compute/schemas/v3/personality.py
Normal file
30
nova/api/openstack/compute/schemas/v3/personality.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Copyright 2014 NEC Corporation. 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.
|
||||||
|
|
||||||
|
server_create = {
|
||||||
|
'personality': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'path': {'type': 'string'},
|
||||||
|
'contents': {
|
||||||
|
'type': 'string',
|
||||||
|
'format': 'base64'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'additionalProperties': False,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"rebuild": {
|
||||||
|
"imageRef": "%(glance_host)s/images/%(image_id)s",
|
||||||
|
"name": "new-server-test",
|
||||||
|
"metadata": {
|
||||||
|
"meta_var": "meta_val"
|
||||||
|
},
|
||||||
|
"personality": [
|
||||||
|
{
|
||||||
|
"path": "/etc/banner.txt",
|
||||||
|
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"addresses": {
|
||||||
|
"private": [
|
||||||
|
{
|
||||||
|
"addr": "%(ip)s",
|
||||||
|
"version": 4,
|
||||||
|
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
|
||||||
|
"OS-EXT-IPS:type": "fixed"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"adminPass": "%(password)s",
|
||||||
|
"created": "%(isotime)s",
|
||||||
|
"flavor": {
|
||||||
|
"id": "1",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "%(host)s/flavors/1",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hostId": "%(hostid)s",
|
||||||
|
"id": "%(uuid)s",
|
||||||
|
"image": {
|
||||||
|
"id": "%(image_id)s",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "%(host)s/images/%(image_id)s",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "%(host)s/v3/servers/%(uuid)s",
|
||||||
|
"rel": "self"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": "%(host)s/servers/%(uuid)s",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"meta_var": "meta_val"
|
||||||
|
},
|
||||||
|
"name": "new-server-test",
|
||||||
|
"progress": 0,
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"tenant_id": "openstack",
|
||||||
|
"updated": "%(isotime)s",
|
||||||
|
"user_id": "fake"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"name": "new-server-test",
|
||||||
|
"imageRef": "%(host)s/openstack/images/%(image_id)s",
|
||||||
|
"flavorRef": "%(host)s/openstack/flavors/1",
|
||||||
|
"metadata": {
|
||||||
|
"My Server Name": "Apache1"
|
||||||
|
},
|
||||||
|
"personality": [
|
||||||
|
{
|
||||||
|
"path": "/etc/banner.txt",
|
||||||
|
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"adminPass": "%(password)s",
|
||||||
|
"id": "%(id)s",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "http://openstack.example.com/v3/servers/%(uuid)s",
|
||||||
|
"rel": "self"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": "http://openstack.example.com/servers/%(uuid)s",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
45
nova/tests/functional/v3/test_personality.py
Normal file
45
nova/tests/functional/v3/test_personality.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Copyright 2014 NEC Corporation. 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.
|
||||||
|
|
||||||
|
from nova.tests.functional.v3 import api_sample_base
|
||||||
|
from nova.tests.unit.image import fake
|
||||||
|
|
||||||
|
|
||||||
|
class PersonalitySampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
|
||||||
|
extension_name = 'os-personality'
|
||||||
|
|
||||||
|
def _servers_post(self, subs):
|
||||||
|
response = self._do_post('servers', 'server-post-req', subs)
|
||||||
|
subs.update(self._get_regexes())
|
||||||
|
return self._verify_response('server-post-resp', subs, response, 202)
|
||||||
|
|
||||||
|
def test_servers_post(self):
|
||||||
|
subs = {
|
||||||
|
'image_id': fake.get_valid_image_id(),
|
||||||
|
'host': self._get_host()
|
||||||
|
}
|
||||||
|
self._servers_post(subs)
|
||||||
|
|
||||||
|
def test_servers_rebuild(self):
|
||||||
|
subs = {
|
||||||
|
'image_id': fake.get_valid_image_id(),
|
||||||
|
'host': self._get_host()
|
||||||
|
}
|
||||||
|
uuid = self._servers_post(subs)
|
||||||
|
response = self._do_post('servers/%s/action' % uuid,
|
||||||
|
'server-action-rebuild-req', subs)
|
||||||
|
subs['hostid'] = '[a-f0-9]+'
|
||||||
|
subs['id'] = uuid
|
||||||
|
self._verify_response('server-action-rebuild-resp',
|
||||||
|
subs, response, 202)
|
@ -1530,6 +1530,37 @@ class ServersControllerRebuildInstanceTest(ControllerTest):
|
|||||||
self.controller._action_rebuild,
|
self.controller._action_rebuild,
|
||||||
self.req, FAKE_UUID, body=self.body)
|
self.req, FAKE_UUID, body=self.body)
|
||||||
|
|
||||||
|
def test_rebuild_bad_personality(self):
|
||||||
|
body = {
|
||||||
|
"rebuild": {
|
||||||
|
"imageRef": self.image_href,
|
||||||
|
"personality": [{
|
||||||
|
"path": "/path/to/file",
|
||||||
|
"contents": "INVALID b64",
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertRaises(exception.ValidationError,
|
||||||
|
self.controller._action_rebuild,
|
||||||
|
self.req, FAKE_UUID, body=body)
|
||||||
|
|
||||||
|
def test_rebuild_personality(self):
|
||||||
|
body = {
|
||||||
|
"rebuild": {
|
||||||
|
"imageRef": self.image_href,
|
||||||
|
"personality": [{
|
||||||
|
"path": "/path/to/file",
|
||||||
|
"contents": base64.b64encode("Test String"),
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
body = self.controller._action_rebuild(self.req, FAKE_UUID,
|
||||||
|
body=body).obj
|
||||||
|
|
||||||
|
self.assertNotIn('personality', body['server'])
|
||||||
|
|
||||||
def test_start(self):
|
def test_start(self):
|
||||||
self.mox.StubOutWithMock(compute_api.API, 'start')
|
self.mox.StubOutWithMock(compute_api.API, 'start')
|
||||||
compute_api.API.start(mox.IgnoreArg(), mox.IgnoreArg())
|
compute_api.API.start(mox.IgnoreArg(), mox.IgnoreArg())
|
||||||
@ -1946,8 +1977,14 @@ class ServersControllerCreateTest(test.TestCase):
|
|||||||
'hello': 'world',
|
'hello': 'world',
|
||||||
'open': 'stack',
|
'open': 'stack',
|
||||||
},
|
},
|
||||||
},
|
'personality': [
|
||||||
}
|
{
|
||||||
|
"path": "/etc/banner.txt",
|
||||||
|
"contents": "MQ==",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
self.bdm = [{'delete_on_termination': 1,
|
self.bdm = [{'delete_on_termination': 1,
|
||||||
'device_name': 123,
|
'device_name': 123,
|
||||||
'volume_size': 1,
|
'volume_size': 1,
|
||||||
@ -2646,6 +2683,40 @@ class ServersControllerCreateTest(test.TestCase):
|
|||||||
self.controller.create,
|
self.controller.create,
|
||||||
self.req, body=self.body)
|
self.req, body=self.body)
|
||||||
|
|
||||||
|
@mock.patch.object(compute_api.API, 'create')
|
||||||
|
def test_create_instance_invalid_personality(self, mock_create):
|
||||||
|
codec = 'utf8'
|
||||||
|
content = 'b25zLiINCg0KLVJpY2hhcmQgQ$$%QQmFjaA=='
|
||||||
|
start_position = 19
|
||||||
|
end_position = 20
|
||||||
|
msg = 'invalid start byte'
|
||||||
|
mock_create.side_effect = UnicodeDecodeError(codec, content,
|
||||||
|
start_position,
|
||||||
|
end_position, msg)
|
||||||
|
|
||||||
|
self.body['server']['personality'] = [
|
||||||
|
{
|
||||||
|
"path": "/etc/banner.txt",
|
||||||
|
"contents": "b25zLiINCg0KLVJpY2hhcmQgQ$$%QQmFjaA==",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
self.req.body = jsonutils.dumps(self.body)
|
||||||
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||||
|
self.controller.create, self.req, body=self.body)
|
||||||
|
|
||||||
|
def test_create_instance_with_extra_personality_arg(self):
|
||||||
|
self.body['server']['personality'] = [
|
||||||
|
{
|
||||||
|
"path": "/etc/banner.txt",
|
||||||
|
"contents": "b25zLiINCg0KLVJpY2hhcmQgQ$$%QQmFjaA==",
|
||||||
|
"extra_arg": "extra value"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
self.assertRaises(exception.ValidationError,
|
||||||
|
self.controller.create,
|
||||||
|
self.req, body=self.body)
|
||||||
|
|
||||||
|
|
||||||
class ServersControllerCreateTestWithMock(test.TestCase):
|
class ServersControllerCreateTestWithMock(test.TestCase):
|
||||||
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
|
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
|
||||||
|
@ -111,6 +111,7 @@ nova.api.v3.extensions =
|
|||||||
networks_associate = nova.api.openstack.compute.plugins.v3.networks_associate:NetworksAssociate
|
networks_associate = nova.api.openstack.compute.plugins.v3.networks_associate:NetworksAssociate
|
||||||
pause_server = nova.api.openstack.compute.plugins.v3.pause_server:PauseServer
|
pause_server = nova.api.openstack.compute.plugins.v3.pause_server:PauseServer
|
||||||
pci = nova.api.openstack.compute.plugins.v3.pci:Pci
|
pci = nova.api.openstack.compute.plugins.v3.pci:Pci
|
||||||
|
personality = nova.api.openstack.compute.plugins.v3.personality:Personality
|
||||||
quota_classes = nova.api.openstack.compute.plugins.v3.quota_classes:QuotaClasses
|
quota_classes = nova.api.openstack.compute.plugins.v3.quota_classes:QuotaClasses
|
||||||
quota_sets = nova.api.openstack.compute.plugins.v3.quota_sets:QuotaSets
|
quota_sets = nova.api.openstack.compute.plugins.v3.quota_sets:QuotaSets
|
||||||
remote_consoles = nova.api.openstack.compute.plugins.v3.remote_consoles:RemoteConsoles
|
remote_consoles = nova.api.openstack.compute.plugins.v3.remote_consoles:RemoteConsoles
|
||||||
@ -143,6 +144,7 @@ nova.api.v3.extensions.server.create =
|
|||||||
disk_config = nova.api.openstack.compute.plugins.v3.disk_config:DiskConfig
|
disk_config = nova.api.openstack.compute.plugins.v3.disk_config:DiskConfig
|
||||||
keypairs_create = nova.api.openstack.compute.plugins.v3.keypairs:Keypairs
|
keypairs_create = nova.api.openstack.compute.plugins.v3.keypairs:Keypairs
|
||||||
multiple_create = nova.api.openstack.compute.plugins.v3.multiple_create:MultipleCreate
|
multiple_create = nova.api.openstack.compute.plugins.v3.multiple_create:MultipleCreate
|
||||||
|
personality = nova.api.openstack.compute.plugins.v3.personality:Personality
|
||||||
scheduler_hints = nova.api.openstack.compute.plugins.v3.scheduler_hints:SchedulerHints
|
scheduler_hints = nova.api.openstack.compute.plugins.v3.scheduler_hints:SchedulerHints
|
||||||
security_groups = nova.api.openstack.compute.plugins.v3.security_groups:SecurityGroups
|
security_groups = nova.api.openstack.compute.plugins.v3.security_groups:SecurityGroups
|
||||||
user_data = nova.api.openstack.compute.plugins.v3.user_data:UserData
|
user_data = nova.api.openstack.compute.plugins.v3.user_data:UserData
|
||||||
@ -150,6 +152,7 @@ nova.api.v3.extensions.server.create =
|
|||||||
nova.api.v3.extensions.server.rebuild =
|
nova.api.v3.extensions.server.rebuild =
|
||||||
access_ips = nova.api.openstack.compute.plugins.v3.access_ips:AccessIPs
|
access_ips = nova.api.openstack.compute.plugins.v3.access_ips:AccessIPs
|
||||||
disk_config = nova.api.openstack.compute.plugins.v3.disk_config:DiskConfig
|
disk_config = nova.api.openstack.compute.plugins.v3.disk_config:DiskConfig
|
||||||
|
personality = nova.api.openstack.compute.plugins.v3.personality:Personality
|
||||||
|
|
||||||
nova.api.v3.extensions.server.update =
|
nova.api.v3.extensions.server.update =
|
||||||
access_ips = nova.api.openstack.compute.plugins.v3.access_ips:AccessIPs
|
access_ips = nova.api.openstack.compute.plugins.v3.access_ips:AccessIPs
|
||||||
|
Loading…
Reference in New Issue
Block a user