Merge "remove personality extension"
This commit is contained in:
commit
4862c41120
@ -115,7 +115,10 @@ hardcoded_extensions = [
|
||||
{'name': 'PreserveEphemeralOnRebuild',
|
||||
'description': ('Allow preservation of the '
|
||||
'ephemeral partition on rebuild.'),
|
||||
'alias': 'os-preserve-ephemeral-rebuild'}
|
||||
'alias': 'os-preserve-ephemeral-rebuild'},
|
||||
{'name': 'Personality',
|
||||
'description': 'Personality support.',
|
||||
'alias': 'os-personality'},
|
||||
]
|
||||
|
||||
# V2.1 does not support XML but we need to keep an entry in the
|
||||
|
@ -22,6 +22,12 @@ API_DISK_CONFIG = "OS-DCF:diskConfig"
|
||||
API_ACCESS_V4 = "accessIPv4"
|
||||
API_ACCESS_V6 = "accessIPv6"
|
||||
|
||||
# possible ops
|
||||
CREATE = 'create'
|
||||
UPDATE = 'update'
|
||||
REBUILD = 'rebuild'
|
||||
RESIZE = 'resize'
|
||||
|
||||
|
||||
def disk_config_from_api(value):
|
||||
if value == 'AUTO':
|
||||
@ -33,7 +39,20 @@ def disk_config_from_api(value):
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
|
||||
def translate_attributes(server_dict, operation_kwargs):
|
||||
def get_injected_files(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
|
||||
|
||||
|
||||
def translate_attributes(op, server_dict, operation_kwargs):
|
||||
"""Translate REST attributes on create to server object kwargs.
|
||||
|
||||
Our REST API is relatively fixed, but internal representations
|
||||
@ -45,6 +64,10 @@ def translate_attributes(server_dict, operation_kwargs):
|
||||
It's done in a common function as this is used for create / resize
|
||||
/ rebuild / update
|
||||
|
||||
The ``op`` is the operation that we are transforming, because
|
||||
there are times when we translate differently for different
|
||||
operations. (Yes, it's a little nuts, but legacy... )
|
||||
|
||||
The ``server_dict`` is a representation of the server in
|
||||
question. During ``create`` and ``update`` operations this will
|
||||
actually be the ``server`` element of the request body.
|
||||
@ -57,6 +80,7 @@ def translate_attributes(server_dict, operation_kwargs):
|
||||
why it's important to only set operation_kwargs if there is
|
||||
something to set. Input validation will ensure that we are only
|
||||
operating on appropriate attributes for each operation.
|
||||
|
||||
"""
|
||||
# Disk config
|
||||
auto_disk_config_raw = server_dict.pop(API_DISK_CONFIG, None)
|
||||
@ -72,7 +96,21 @@ def translate_attributes(server_dict, operation_kwargs):
|
||||
# This is only ever expected during rebuild operations, and only
|
||||
# does anything with Ironic driver. It also demonstrates the lack
|
||||
# of understanding of the word ephemeral.
|
||||
if 'preserve_ephemeral' in server_dict:
|
||||
if 'preserve_ephemeral' in server_dict and op == REBUILD:
|
||||
preserve = strutils.bool_from_string(
|
||||
server_dict.pop('preserve_ephemeral'), strict=True)
|
||||
operation_kwargs['preserve_ephemeral'] = preserve
|
||||
|
||||
# yes, we use different kwargs, this goes all the way back to
|
||||
# commit cebc98176926f57016a508d5c59b11f55dfcf2b3.
|
||||
if 'personality' in server_dict:
|
||||
if op == REBUILD:
|
||||
operation_kwargs['files_to_inject'] = get_injected_files(
|
||||
server_dict.pop('personality'))
|
||||
# NOTE(sdague): the deprecated hooks infrastructure doesn't
|
||||
# function if injected files is not defined as a list. Once hooks
|
||||
# are removed, this should go back inside the personality
|
||||
# conditional above.
|
||||
if op == CREATE:
|
||||
operation_kwargs['injected_files'] = get_injected_files(
|
||||
server_dict.pop('personality', []))
|
||||
|
@ -1,69 +0,0 @@
|
||||
# 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 import personality
|
||||
from nova.api.openstack import extensions
|
||||
|
||||
ALIAS = "os-personality"
|
||||
|
||||
|
||||
class Personality(extensions.V21APIExtensionBase):
|
||||
"""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
|
||||
|
||||
# Extend server in both create & rebuild
|
||||
#
|
||||
# TODO(sdague): it looks weird that server_create is different
|
||||
# than server_rebuild, right? Well you can totally blame hooks for
|
||||
# that. By accident this means that server personalities are
|
||||
# always creating the injected_files kwarg, even if there is
|
||||
# nothing in it. Hooks totally needs injected_files to be a
|
||||
# thing. Once hooks are removed from tree, this function can be
|
||||
# made to look like the rebuild one.
|
||||
def server_create(self, server_dict, create_kwargs, body_deprecated):
|
||||
create_kwargs['injected_files'] = self._get_injected_files(
|
||||
server_dict.get('personality', []))
|
||||
|
||||
def server_rebuild(self, server_dict, create_kwargs):
|
||||
if 'personality' in server_dict:
|
||||
create_kwargs['files_to_inject'] = self._get_injected_files(
|
||||
server_dict['personality'])
|
||||
|
||||
# Extend schema with the new allowed parameters
|
||||
def get_server_create_schema(self, version):
|
||||
return personality.server_create
|
||||
|
||||
def get_server_rebuild_schema(self, version):
|
||||
return personality.server_create
|
@ -1,30 +0,0 @@
|
||||
# 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,
|
||||
}
|
||||
}
|
||||
}
|
@ -46,6 +46,7 @@ base_create = {
|
||||
'OS-DCF:diskConfig': parameter_types.disk_config,
|
||||
'accessIPv4': parameter_types.accessIPv4,
|
||||
'accessIPv6': parameter_types.accessIPv6,
|
||||
'personality': parameter_types.personality,
|
||||
},
|
||||
'required': ['name', 'flavorRef'],
|
||||
'additionalProperties': False,
|
||||
@ -107,6 +108,7 @@ base_rebuild = {
|
||||
'OS-DCF:diskConfig': parameter_types.disk_config,
|
||||
'accessIPv4': parameter_types.accessIPv4,
|
||||
'accessIPv6': parameter_types.accessIPv6,
|
||||
'personality': parameter_types.personality,
|
||||
},
|
||||
'required': ['imageRef'],
|
||||
'additionalProperties': False,
|
||||
|
@ -60,8 +60,6 @@ class ServersController(wsgi.Controller):
|
||||
|
||||
EXTENSION_CREATE_NAMESPACE = 'nova.api.v21.extensions.server.create'
|
||||
|
||||
EXTENSION_REBUILD_NAMESPACE = 'nova.api.v21.extensions.server.rebuild'
|
||||
|
||||
_view_builder_class = views_servers.ViewBuilderV21
|
||||
|
||||
schema_server_create = schema_servers.base_create
|
||||
@ -159,17 +157,6 @@ class ServersController(wsgi.Controller):
|
||||
if not list(self.create_extension_manager):
|
||||
LOG.debug("Did not find any server create extensions")
|
||||
|
||||
# Look for implementation of extension point of server rebuild
|
||||
self.rebuild_extension_manager = \
|
||||
stevedore.enabled.EnabledExtensionManager(
|
||||
namespace=self.EXTENSION_REBUILD_NAMESPACE,
|
||||
check_func=_check_load_extension('server_rebuild'),
|
||||
invoke_on_load=True,
|
||||
invoke_kwds={"extension_info": self.extension_info},
|
||||
propagate_map_exceptions=True)
|
||||
if not list(self.rebuild_extension_manager):
|
||||
LOG.debug("Did not find any server rebuild extensions")
|
||||
|
||||
# Look for API schema of server create extension
|
||||
self.create_schema_manager = \
|
||||
stevedore.enabled.EnabledExtensionManager(
|
||||
@ -190,26 +177,6 @@ class ServersController(wsgi.Controller):
|
||||
else:
|
||||
LOG.debug("Did not find any server create schemas")
|
||||
|
||||
# Look for API schema of server rebuild extension
|
||||
self.rebuild_schema_manager = \
|
||||
stevedore.enabled.EnabledExtensionManager(
|
||||
namespace=self.EXTENSION_REBUILD_NAMESPACE,
|
||||
check_func=_check_load_extension('get_server_rebuild_schema'),
|
||||
invoke_on_load=True,
|
||||
invoke_kwds={"extension_info": self.extension_info},
|
||||
propagate_map_exceptions=True)
|
||||
if list(self.rebuild_schema_manager):
|
||||
self.rebuild_schema_manager.map(self._rebuild_extension_schema,
|
||||
self.schema_server_rebuild_v219,
|
||||
'2.19')
|
||||
self.rebuild_schema_manager.map(self._rebuild_extension_schema,
|
||||
self.schema_server_rebuild, '2.1')
|
||||
self.rebuild_schema_manager.map(self._rebuild_extension_schema,
|
||||
self.schema_server_rebuild_v20,
|
||||
'2.0')
|
||||
else:
|
||||
LOG.debug("Did not find any server rebuild schemas")
|
||||
|
||||
@extensions.expected_errors((400, 403))
|
||||
def index(self, req):
|
||||
"""Returns a list of server names and ids for a given user."""
|
||||
@ -524,7 +491,8 @@ class ServersController(wsgi.Controller):
|
||||
|
||||
availability_zone = create_kwargs.pop("availability_zone", None)
|
||||
|
||||
helpers.translate_attributes(server_dict, create_kwargs)
|
||||
helpers.translate_attributes(helpers.CREATE,
|
||||
server_dict, create_kwargs)
|
||||
|
||||
target = {
|
||||
'project_id': context.project_id,
|
||||
@ -748,15 +716,17 @@ class ServersController(wsgi.Controller):
|
||||
update_dict = {}
|
||||
ctxt.can(server_policies.SERVERS % 'update')
|
||||
|
||||
if 'name' in body['server']:
|
||||
server = body['server']
|
||||
|
||||
if 'name' in server:
|
||||
update_dict['display_name'] = common.normalize_name(
|
||||
body['server']['name'])
|
||||
server['name'])
|
||||
|
||||
if 'description' in body['server']:
|
||||
if 'description' in server:
|
||||
# This is allowed to be None (remove description)
|
||||
update_dict['display_description'] = body['server']['description']
|
||||
update_dict['display_description'] = server['description']
|
||||
|
||||
helpers.translate_attributes(body['server'], update_dict)
|
||||
helpers.translate_attributes(helpers.UPDATE, server, update_dict)
|
||||
|
||||
instance = self._get_server(ctxt, req, id, is_detail=True)
|
||||
try:
|
||||
@ -920,10 +890,10 @@ class ServersController(wsgi.Controller):
|
||||
resize_dict = body['resize']
|
||||
flavor_ref = str(resize_dict["flavorRef"])
|
||||
|
||||
resize_kwargs = {}
|
||||
helpers.translate_attributes(resize_dict, resize_kwargs)
|
||||
kwargs = {}
|
||||
helpers.translate_attributes(helpers.RESIZE, resize_dict, kwargs)
|
||||
|
||||
self._resize(req, id, flavor_ref, **resize_kwargs)
|
||||
self._resize(req, id, flavor_ref, **kwargs)
|
||||
|
||||
@wsgi.response(202)
|
||||
@extensions.expected_errors((400, 403, 404, 409))
|
||||
@ -950,21 +920,17 @@ class ServersController(wsgi.Controller):
|
||||
'metadata': 'metadata',
|
||||
}
|
||||
|
||||
rebuild_kwargs = {}
|
||||
kwargs = {}
|
||||
|
||||
if list(self.rebuild_extension_manager):
|
||||
self.rebuild_extension_manager.map(self._rebuild_extension_point,
|
||||
rebuild_dict, rebuild_kwargs)
|
||||
|
||||
helpers.translate_attributes(rebuild_dict, rebuild_kwargs)
|
||||
helpers.translate_attributes(helpers.REBUILD, rebuild_dict, kwargs)
|
||||
|
||||
for request_attribute, instance_attribute in attr_map.items():
|
||||
try:
|
||||
if request_attribute == 'name':
|
||||
rebuild_kwargs[instance_attribute] = common.normalize_name(
|
||||
kwargs[instance_attribute] = common.normalize_name(
|
||||
rebuild_dict[request_attribute])
|
||||
else:
|
||||
rebuild_kwargs[instance_attribute] = rebuild_dict[
|
||||
kwargs[instance_attribute] = rebuild_dict[
|
||||
request_attribute]
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
@ -974,7 +940,7 @@ class ServersController(wsgi.Controller):
|
||||
instance,
|
||||
image_href,
|
||||
password,
|
||||
**rebuild_kwargs)
|
||||
**kwargs)
|
||||
except exception.InstanceIsLocked as e:
|
||||
raise exc.HTTPConflict(explanation=e.format_message())
|
||||
except exception.InstanceInvalidState as state_error:
|
||||
|
@ -377,3 +377,18 @@ flavor_param_positive = copy.deepcopy(volume_size)
|
||||
|
||||
flavor_param_non_negative = copy.deepcopy(volume_size)
|
||||
flavor_param_non_negative['minimum'] = 0
|
||||
|
||||
personality = {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'path': {'type': 'string'},
|
||||
'contents': {
|
||||
'type': 'string',
|
||||
'format': 'base64'
|
||||
}
|
||||
},
|
||||
'additionalProperties': False,
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,6 @@ from nova.policies import networks
|
||||
from nova.policies import networks_associate
|
||||
from nova.policies import pause_server
|
||||
from nova.policies import pci
|
||||
from nova.policies import personality
|
||||
from nova.policies import quota_class_sets
|
||||
from nova.policies import quota_sets
|
||||
from nova.policies import remote_consoles
|
||||
@ -154,7 +153,6 @@ def list_rules():
|
||||
networks_associate.list_rules(),
|
||||
pause_server.list_rules(),
|
||||
pci.list_rules(),
|
||||
personality.list_rules(),
|
||||
quota_class_sets.list_rules(),
|
||||
quota_sets.list_rules(),
|
||||
remote_consoles.list_rules(),
|
||||
|
@ -1,32 +0,0 @@
|
||||
# Copyright 2016 Cloudbase Solutions Srl
|
||||
# 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 oslo_policy import policy
|
||||
|
||||
from nova.policies import base
|
||||
|
||||
|
||||
POLICY_ROOT = 'os_compute_api:os-personality:%s'
|
||||
|
||||
|
||||
personality_policies = [
|
||||
policy.RuleDefault(
|
||||
name=POLICY_ROOT % 'discoverable',
|
||||
check_str=base.RULE_ANY),
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return personality_policies
|
@ -466,7 +466,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
|
||||
"os_compute_api:os-networks-associate:discoverable",
|
||||
"os_compute_api:os-pause-server:discoverable",
|
||||
"os_compute_api:os-pci:discoverable",
|
||||
"os_compute_api:os-personality:discoverable",
|
||||
"os_compute_api:os-quota-sets:discoverable",
|
||||
"os_compute_api:os-quota-class-sets:discoverable",
|
||||
"os_compute_api:os-rescue:discoverable",
|
||||
|
@ -20,3 +20,6 @@ upgrade:
|
||||
|
||||
* nova.api.v21.extensions.server.update - allowed accepting
|
||||
additional parameters on server update requests.
|
||||
|
||||
* nova.api.v21.extensions.server.rebuild - allowed accepting
|
||||
additional parameters on server rebuild requests.
|
||||
|
@ -122,7 +122,6 @@ nova.api.v21.extensions =
|
||||
# NOTE(cyeoh): this is intentionally disabled until microversions is active.
|
||||
# See https://bugs.launchpad.net/nova/+bug/1426241
|
||||
# pci = nova.api.openstack.compute.pci:Pci
|
||||
personality = nova.api.openstack.compute.personality:Personality
|
||||
quota_classes = nova.api.openstack.compute.quota_classes:QuotaClasses
|
||||
quota_sets = nova.api.openstack.compute.quota_sets:QuotaSets
|
||||
remote_consoles = nova.api.openstack.compute.remote_consoles:RemoteConsoles
|
||||
@ -157,14 +156,10 @@ nova.api.v21.extensions.server.create =
|
||||
config_drive = nova.api.openstack.compute.config_drive:ConfigDrive
|
||||
keypairs_create = nova.api.openstack.compute.keypairs:Keypairs
|
||||
multiple_create = nova.api.openstack.compute.multiple_create:MultipleCreate
|
||||
personality = nova.api.openstack.compute.personality:Personality
|
||||
scheduler_hints = nova.api.openstack.compute.scheduler_hints:SchedulerHints
|
||||
security_groups = nova.api.openstack.compute.security_groups:SecurityGroups
|
||||
user_data = nova.api.openstack.compute.user_data:UserData
|
||||
|
||||
nova.api.v21.extensions.server.rebuild =
|
||||
personality = nova.api.openstack.compute.personality:Personality
|
||||
|
||||
nova.api.v21.test_extensions =
|
||||
basic = nova.tests.unit.api.openstack.compute.basic:Basic
|
||||
microversions = nova.tests.unit.api.openstack.compute.microversions:Microversions
|
||||
|
Loading…
x
Reference in New Issue
Block a user