Merge "remove personality extension"

This commit is contained in:
Jenkins 2016-06-26 14:14:07 +00:00 committed by Gerrit Code Review
commit 4862c41120
12 changed files with 81 additions and 193 deletions

View File

@ -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

View File

@ -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', []))

View File

@ -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

View File

@ -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,
}
}
}

View File

@ -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,

View File

@ -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:

View File

@ -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,
}
}

View File

@ -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(),

View File

@ -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

View File

@ -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",

View File

@ -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.

View File

@ -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