remove os-disk-config part 4

There are no test changes as all new code is tested by the
extension_info functional tests, and should we want to eliminate the
extension_info portion of our API later, new tests would just make
this much harder to tear down.

This modifies default policy to drop os-disk-config as well as
modifying extension tests to pass even though we're injecting
additional hardcoded items into the list for compatibility.

Part of bp:api-no-more-extensions

Change-Id: I0192ccef7e858fd0ff15c339f683abaabbdc09b7
This commit is contained in:
Sean Dague 2016-06-15 16:38:06 -04:00
parent fbc3c5ab3c
commit 525285eb1c
11 changed files with 138 additions and 87 deletions

View File

@ -65,8 +65,6 @@
"os_compute_api:os-create-backup": "rule:admin_or_owner", "os_compute_api:os-create-backup": "rule:admin_or_owner",
"os_compute_api:os-deferred-delete": "rule:admin_or_owner", "os_compute_api:os-deferred-delete": "rule:admin_or_owner",
"os_compute_api:os-deferred-delete:discoverable": "@", "os_compute_api:os-deferred-delete:discoverable": "@",
"os_compute_api:os-disk-config": "rule:admin_or_owner",
"os_compute_api:os-disk-config:discoverable": "@",
"os_compute_api:os-evacuate": "rule:admin_api", "os_compute_api:os-evacuate": "rule:admin_api",
"os_compute_api:os-evacuate:discoverable": "@", "os_compute_api:os-evacuate:discoverable": "@",
"os_compute_api:os-extended-server-attributes": "rule:admin_api", "os_compute_api:os-extended-server-attributes": "rule:admin_api",

View File

@ -1,53 +0,0 @@
# Copyright 2011 OpenStack Foundation
#
# 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.
"""Disk Config extension."""
from webob import exc
from nova.api.openstack import extensions
from nova.i18n import _
ALIAS = 'os-disk-config'
API_DISK_CONFIG = "OS-DCF:diskConfig"
INTERNAL_DISK_CONFIG = "auto_disk_config"
authorize = extensions.os_compute_soft_authorizer(ALIAS)
def disk_config_to_api(value):
return 'AUTO' if value else 'MANUAL'
def disk_config_from_api(value):
if value == 'AUTO':
return True
elif value == 'MANUAL':
return False
else:
msg = _("%s must be either 'MANUAL' or 'AUTO'.") % API_DISK_CONFIG
raise exc.HTTPBadRequest(explanation=msg)
class DiskConfig(extensions.V21APIExtensionBase):
"""Disk Management Extension."""
name = "DiskConfig"
alias = ALIAS
version = 1
def get_controller_extensions(self):
return []
def get_resources(self):
return []

View File

@ -99,6 +99,18 @@ v21_to_v2_alias_mapping = {
'os-instance-usage-audit-log': 'os-instance_usage_audit_log', 'os-instance-usage-audit-log': 'os-instance_usage_audit_log',
} }
# NOTE(sdague): this is the list of extension metadata that we display
# to the user for features that we provide. This exists for legacy
# purposes because applications were once asked to look for these
# things to decide if a feature is enabled. As we remove extensions
# completely from the code we're going to have a static list here to
# keep the surface metadata the same.
hardcoded_extensions = [
{'name': 'DiskConfig',
'alias': 'os-disk-config',
'description': 'Disk Management Extension.'}
]
# V2.1 does not support XML but we need to keep an entry in the # V2.1 does not support XML but we need to keep an entry in the
# /extensions information returned to the user for backwards # /extensions information returned to the user for backwards
# compatibility # compatibility
@ -107,10 +119,10 @@ FAKE_UPDATED_DATE = "2014-12-03T00:00:00Z"
class FakeExtension(object): class FakeExtension(object):
def __init__(self, name, alias): def __init__(self, name, alias, description=""):
self.name = name self.name = name
self.alias = alias self.alias = alias
self.__doc__ = "" self.__doc__ = description
self.version = -1 self.version = -1
@ -129,8 +141,8 @@ class ExtensionInfoController(wsgi.Controller):
ext_data["links"] = [] ext_data["links"] = []
return ext_data return ext_data
def _create_fake_ext(self, alias, name): def _create_fake_ext(self, name, alias, description=""):
return FakeExtension(alias, name) return FakeExtension(name, alias, description)
def _add_vif_extension(self, discoverable_extensions): def _add_vif_extension(self, discoverable_extensions):
vif_extension = {} vif_extension = {}
@ -144,6 +156,14 @@ class ExtensionInfoController(wsgi.Controller):
"""Filter extensions list based on policy.""" """Filter extensions list based on policy."""
discoverable_extensions = dict() discoverable_extensions = dict()
for item in hardcoded_extensions:
discoverable_extensions[item['alias']] = self._create_fake_ext(
item['name'],
item['alias'],
item['description']
)
for alias, ext in six.iteritems(self.extension_info.get_extensions()): for alias, ext in six.iteritems(self.extension_info.get_extensions()):
authorize = extensions.os_compute_soft_authorizer(alias) authorize = extensions.os_compute_soft_authorizer(alias)
if authorize(context, action='discoverable'): if authorize(context, action='discoverable'):

View File

@ -0,0 +1,61 @@
# Copyright 2016 HPE, Inc.
#
# 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 webob import exc
from nova.i18n import _
API_DISK_CONFIG = "OS-DCF:diskConfig"
def disk_config_from_api(value):
if value == 'AUTO':
return True
elif value == 'MANUAL':
return False
else:
msg = _("%s must be either 'MANUAL' or 'AUTO'.") % API_DISK_CONFIG
raise exc.HTTPBadRequest(explanation=msg)
def translate_attributes(server_dict, operation_kwargs):
"""Translate REST attributes on create to server object kwargs.
Our REST API is relatively fixed, but internal representations
change over time, this is a translator for inbound REST request
attributes that modifies the server dict that we get and adds
appropriate attributes to ``operation_kwargs`` that will be passed
down to instance objects later.
It's done in a common function as this is used for create / resize
/ rebuild / update
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.
During actions, such as ``rebuild`` and ``resize`` this will be
the attributes passed to the action object during the
operation. This is equivalent to the ``server`` object.
Not all operations support all attributes listed here. Which is
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)
if auto_disk_config_raw is not None:
auto_disk_config = disk_config_from_api(auto_disk_config_raw)
operation_kwargs['auto_disk_config'] = auto_disk_config

View File

@ -29,7 +29,7 @@ from webob import exc
from nova.api.openstack import api_version_request from nova.api.openstack import api_version_request
from nova.api.openstack import common from nova.api.openstack import common
from nova.api.openstack.compute import disk_config from nova.api.openstack.compute import helpers
from nova.api.openstack.compute.schemas import servers as schema_servers from nova.api.openstack.compute.schemas import servers as schema_servers
from nova.api.openstack.compute.views import servers as views_servers from nova.api.openstack.compute.views import servers as views_servers
from nova.api.openstack import extensions from nova.api.openstack import extensions
@ -55,16 +55,6 @@ CONF = nova.conf.CONF
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
def translate_attributes(server_dict, server_kwargs):
# Disk config
# Translate create kwargs to internal representation
auto_disk_config_raw = server_dict.pop("OS-DCF:diskConfig", None)
if auto_disk_config_raw is not None:
auto_disk_config = disk_config.disk_config_from_api(
auto_disk_config_raw)
server_kwargs['auto_disk_config'] = auto_disk_config
class ServersController(wsgi.Controller): class ServersController(wsgi.Controller):
"""The Server API base controller class for the OpenStack API.""" """The Server API base controller class for the OpenStack API."""
@ -567,7 +557,7 @@ class ServersController(wsgi.Controller):
availability_zone = create_kwargs.pop("availability_zone", None) availability_zone = create_kwargs.pop("availability_zone", None)
translate_attributes(server_dict, create_kwargs) helpers.translate_attributes(server_dict, create_kwargs)
target = { target = {
'project_id': context.project_id, 'project_id': context.project_id,
@ -815,7 +805,7 @@ class ServersController(wsgi.Controller):
self.update_extension_manager.map(self._update_extension_point, self.update_extension_manager.map(self._update_extension_point,
body['server'], update_dict) body['server'], update_dict)
translate_attributes(body['server'], update_dict) helpers.translate_attributes(body['server'], update_dict)
instance = self._get_server(ctxt, req, id, is_detail=True) instance = self._get_server(ctxt, req, id, is_detail=True)
try: try:
@ -980,7 +970,7 @@ class ServersController(wsgi.Controller):
flavor_ref = str(resize_dict["flavorRef"]) flavor_ref = str(resize_dict["flavorRef"])
resize_kwargs = {} resize_kwargs = {}
translate_attributes(resize_dict, resize_kwargs) helpers.translate_attributes(resize_dict, resize_kwargs)
self._resize(req, id, flavor_ref, **resize_kwargs) self._resize(req, id, flavor_ref, **resize_kwargs)
@ -1015,7 +1005,7 @@ class ServersController(wsgi.Controller):
self.rebuild_extension_manager.map(self._rebuild_extension_point, self.rebuild_extension_manager.map(self._rebuild_extension_point,
rebuild_dict, rebuild_kwargs) rebuild_dict, rebuild_kwargs)
translate_attributes(rebuild_dict, rebuild_kwargs) helpers.translate_attributes(rebuild_dict, rebuild_kwargs)
for request_attribute, instance_attribute in attr_map.items(): for request_attribute, instance_attribute in attr_map.items():
try: try:

View File

@ -17,7 +17,6 @@
from oslo_utils import strutils from oslo_utils import strutils
from nova.api.openstack import common from nova.api.openstack import common
from nova.api.openstack.compute import disk_config
from nova.image import glance from nova.image import glance
from nova import utils from nova import utils
@ -76,8 +75,8 @@ class ViewBuilder(common.ViewBuilder):
auto_disk_config = image_dict['metadata'].get("auto_disk_config", None) auto_disk_config = image_dict['metadata'].get("auto_disk_config", None)
if auto_disk_config is not None: if auto_disk_config is not None:
value = strutils.bool_from_string(auto_disk_config) value = strutils.bool_from_string(auto_disk_config)
image_dict["OS-DCF:diskConfig"] = \ image_dict["OS-DCF:diskConfig"] = (
disk_config.disk_config_to_api(value) 'AUTO' if value else 'MANUAL')
return dict(image=image_dict) return dict(image=image_dict)

View File

@ -25,6 +25,10 @@ from nova.tests.unit.api.openstack import fakes
FAKE_UPDATED_DATE = extension_info.FAKE_UPDATED_DATE FAKE_UPDATED_DATE = extension_info.FAKE_UPDATED_DATE
# NOTE(sdague): this whole test module is short term while we shift
# the extensions into main path code. Some short cuts are taken in the
# interim to keep these extension tests.
class fake_extension(object): class fake_extension(object):
def __init__(self, name, alias, description, version): def __init__(self, name, alias, description, version):
@ -76,8 +80,15 @@ class ExtensionInfoTest(test.NoDBTestCase):
self.stubs.Set(policy, 'enforce', fake_policy_enforce) self.stubs.Set(policy, 'enforce', fake_policy_enforce)
req = fakes.HTTPRequestV21.blank('/extensions') req = fakes.HTTPRequestV21.blank('/extensions')
res_dict = self.controller.index(req) res_dict = self.controller.index(req)
self.assertEqual(3, len(res_dict['extensions'])) # NOTE(sdague): because of hardcoded extensions the count is
for e in res_dict['extensions']: # going to grow, and that's fine. We'll just check that it's
# greater than the 3 that we inserted.
self.assertGreaterEqual(len(res_dict['extensions']), 3)
# NOTE(sdague): filter the extension list by only ones that
# are the fake alias names, otherwise we get errors as we
# migrate extensions into the hardcoded list.
for e in [x for x in res_dict['extensions'] if '-alias' in x['alias']]:
self.assertIn(e['alias'], fake_extensions) self.assertIn(e['alias'], fake_extensions)
self.assertEqual(e['name'], fake_extensions[e['alias']].name) self.assertEqual(e['name'], fake_extensions[e['alias']].name)
self.assertEqual(e['alias'], fake_extensions[e['alias']].alias) self.assertEqual(e['alias'], fake_extensions[e['alias']].alias)
@ -106,8 +117,15 @@ class ExtensionInfoTest(test.NoDBTestCase):
self.stubs.Set(policy, 'enforce', fake_policy_enforce_selective) self.stubs.Set(policy, 'enforce', fake_policy_enforce_selective)
req = fakes.HTTPRequestV21.blank('/extensions') req = fakes.HTTPRequestV21.blank('/extensions')
res_dict = self.controller.index(req) res_dict = self.controller.index(req)
self.assertEqual(2, len(res_dict['extensions'])) # NOTE(sdague): because of hardcoded extensions the count is
for e in res_dict['extensions']: # going to grow, and that's fine. We'll just check that it's
# greater than the 2 that we inserted.
self.assertGreaterEqual(len(res_dict['extensions']), 2)
# NOTE(sdague): filter the extension list by only ones that
# are the fake alias names, otherwise we get errors as we
# migrate extensions into the hardcoded list.
for e in [x for x in res_dict['extensions'] if '-alias' in x['alias']]:
self.assertNotEqual('ext1-alias', e['alias']) self.assertNotEqual('ext1-alias', e['alias'])
self.assertIn(e['alias'], fake_extensions) self.assertIn(e['alias'], fake_extensions)
self.assertEqual(e['name'], fake_extensions[e['alias']].name) self.assertEqual(e['name'], fake_extensions[e['alias']].name)
@ -131,7 +149,10 @@ class ExtensionInfoV21Test(test.NoDBTestCase):
def test_extension_info_list(self): def test_extension_info_list(self):
req = fakes.HTTPRequest.blank('/extensions') req = fakes.HTTPRequest.blank('/extensions')
res_dict = self.controller.index(req) res_dict = self.controller.index(req)
self.assertEqual(12, len(res_dict['extensions'])) # NOTE(sdague): because of hardcoded extensions the count is
# going to grow, and that's fine. We'll just check that it's
# greater than the 12 that we inserted.
self.assertGreaterEqual(len(res_dict['extensions']), 12)
expected_output = copy.deepcopy(simulated_extension_list) expected_output = copy.deepcopy(simulated_extension_list)
del expected_output['images'] del expected_output['images']
@ -155,7 +176,10 @@ class ExtensionInfoV21Test(test.NoDBTestCase):
expected_output['os-server-start-stop'] = fake_extension( expected_output['os-server-start-stop'] = fake_extension(
'ServerStartStop', 'os-server-start-stop', '', -1) 'ServerStartStop', 'os-server-start-stop', '', -1)
for e in res_dict['extensions']: # NOTE(sdague): filter the extension list by only ones that
# are the fake alias names, otherwise we get errors as we
# migrate extensions into the hardcoded list.
for e in [x for x in res_dict['extensions'] if '-alias' in x['alias']]:
self.assertIn(e['alias'], expected_output) self.assertIn(e['alias'], expected_output)
self.assertEqual(e['name'], expected_output[e['alias']].name) self.assertEqual(e['name'], expected_output[e['alias']].name)
self.assertEqual(e['alias'], expected_output[e['alias']].alias) self.assertEqual(e['alias'], expected_output[e['alias']].alias)

View File

@ -59,7 +59,6 @@ policy_data = """
"os_compute_api:os-consoles:show": "", "os_compute_api:os-consoles:show": "",
"os_compute_api:os-create-backup": "", "os_compute_api:os-create-backup": "",
"os_compute_api:os-deferred-delete": "", "os_compute_api:os-deferred-delete": "",
"os_compute_api:os-disk-config": "",
"os_compute_api:os-evacuate": "is_admin:True", "os_compute_api:os-evacuate": "is_admin:True",
"os_compute_api:os-extended-server-attributes": "", "os_compute_api:os-extended-server-attributes": "",
"os_compute_api:os-extended-status": "", "os_compute_api:os-extended-status": "",

View File

@ -376,7 +376,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"os_compute_api:os-console-output", "os_compute_api:os-console-output",
"os_compute_api:os-remote-consoles", "os_compute_api:os-remote-consoles",
"os_compute_api:os-deferred-delete", "os_compute_api:os-deferred-delete",
"os_compute_api:os-disk-config",
"os_compute_api:os-extended-status", "os_compute_api:os-extended-status",
"os_compute_api:os-extended-availability-zone", "os_compute_api:os-extended-availability-zone",
"os_compute_api:os-extended-volumes", "os_compute_api:os-extended-volumes",
@ -435,7 +434,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"os_compute_api:os-remote-consoles:discoverable", "os_compute_api:os-remote-consoles:discoverable",
"os_compute_api:os-create-backup:discoverable", "os_compute_api:os-create-backup:discoverable",
"os_compute_api:os-deferred-delete:discoverable", "os_compute_api:os-deferred-delete:discoverable",
"os_compute_api:os-disk-config:discoverable",
"os_compute_api:os-evacuate:discoverable", "os_compute_api:os-evacuate:discoverable",
"os_compute_api:os-extended-server-attributes:discoverable", "os_compute_api:os-extended-server-attributes:discoverable",
"os_compute_api:os-extended-status:discoverable", "os_compute_api:os-extended-status:discoverable",

View File

@ -0,0 +1,16 @@
---
upgrade:
- |
The following policy enforcement points have been removed as part
of the restructuring of the Nova API code. The attributes that
could have been hidden with these policy points will now always be
shown / accepted.
* os_compute_api:os-disk-config - show / accept
``OS-DCF:diskConfig`` parameter
The following entry points have been removed
* nova.api.v21.extensions.server.resize - allowed accepting
additional parameters on resize requests.

View File

@ -84,7 +84,6 @@ nova.api.v21.extensions =
consoles = nova.api.openstack.compute.consoles:Consoles consoles = nova.api.openstack.compute.consoles:Consoles
create_backup = nova.api.openstack.compute.create_backup:CreateBackup create_backup = nova.api.openstack.compute.create_backup:CreateBackup
deferred_delete = nova.api.openstack.compute.deferred_delete:DeferredDelete deferred_delete = nova.api.openstack.compute.deferred_delete:DeferredDelete
disk_config = nova.api.openstack.compute.disk_config:DiskConfig
evacuate = nova.api.openstack.compute.evacuate:Evacuate evacuate = nova.api.openstack.compute.evacuate:Evacuate
extended_availability_zone = nova.api.openstack.compute.extended_availability_zone:ExtendedAvailabilityZone extended_availability_zone = nova.api.openstack.compute.extended_availability_zone:ExtendedAvailabilityZone
extended_server_attributes = nova.api.openstack.compute.extended_server_attributes:ExtendedServerAttributes extended_server_attributes = nova.api.openstack.compute.extended_server_attributes:ExtendedServerAttributes