From 7ac52e643c176ed306fe19be51247c9110387290 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 1 Sep 2020 11:38:47 +0100 Subject: [PATCH] api: Remove 'os-agents' API This was only useful with XenAPI and can therefore be removed. Change-Id: I9512f605dd2b3b0e88c951ed086250d57056303d Signed-off-by: Stephen Finucane --- api-ref/source/os-agents.inc | 17 +- nova/api/openstack/compute/agents.py | 147 +----- nova/api/openstack/compute/schemas/agents.py | 100 ---- nova/objects/agent.py | 4 + nova/policies/__init__.py | 2 - nova/policies/agents.py | 108 ----- .../api_sample_tests/test_agents.py | 71 +-- .../unit/api/openstack/compute/test_agents.py | 431 ------------------ nova/tests/unit/fake_policy.py | 4 - nova/tests/unit/policies/test_agents.py | 212 --------- nova/tests/unit/test_policy.py | 4 - ...remove-xenapi-driver-194756049f22dc9e.yaml | 23 +- 12 files changed, 51 insertions(+), 1072 deletions(-) delete mode 100644 nova/api/openstack/compute/schemas/agents.py delete mode 100644 nova/policies/agents.py delete mode 100644 nova/tests/unit/api/openstack/compute/test_agents.py delete mode 100644 nova/tests/unit/policies/test_agents.py diff --git a/api-ref/source/os-agents.inc b/api-ref/source/os-agents.inc index 33bd9fbd3a76..f9ab86a62c3d 100644 --- a/api-ref/source/os-agents.inc +++ b/api-ref/source/os-agents.inc @@ -11,6 +11,12 @@ hypervisor-specific extension is currently only for the Xen driver. Use of guest agents is possible only if the underlying service provider uses the Xen driver. +.. warning:: + + These APIs only works with the Xen virt driver, which was deprecated in the + 20.0.0 (Train) release. + They were removed in the 22.0.0 (Victoria) release. + List Agent Builds ================= @@ -20,7 +26,7 @@ Lists agent builds. Normal response codes: 200 -Error response codes: unauthorized(401), forbidden(403) +Error response codes: unauthorized(401), forbidden(403), gone(410) Request ------- @@ -58,7 +64,8 @@ Creates an agent build. Normal response codes: 200 -Error response codes: badRequest(400), unauthorized(401), forbidden(403), conflict(409) +Error response codes: badRequest(400), unauthorized(401), forbidden(403), +conflict(409), gone(410) Request ------- @@ -106,7 +113,8 @@ Updates an agent build. Normal response codes: 200 -Error response codes: badRequest(400), unauthorized(401), forbidden(403), itemNotFound(404) +Error response codes: badRequest(400), unauthorized(401), forbidden(403), +itemNotFound(404), gone(410) Request ------- @@ -150,7 +158,8 @@ Deletes an existing agent build. Normal response codes: 200 -Error response codes: badRequest(400), unauthorized(401), forbidden(403), itemNotFound(404) +Error response codes: badRequest(400), unauthorized(401), forbidden(403), +itemNotFound(404), gone(410) Request ------- diff --git a/nova/api/openstack/compute/agents.py b/nova/api/openstack/compute/agents.py index 3edc63eb3145..38e690b59e47 100644 --- a/nova/api/openstack/compute/agents.py +++ b/nova/api/openstack/compute/agents.py @@ -13,153 +13,28 @@ # under the License. -import webob.exc +from webob import exc -from nova.api.openstack.compute.schemas import agents as schema from nova.api.openstack import wsgi -from nova.api import validation -from nova import exception -from nova import objects -from nova.policies import agents as agents_policies -from nova import utils class AgentController(wsgi.Controller): - """The agent is talking about guest agent.The host can use this for - things like accessing files on the disk, configuring networking, - or running other applications/scripts in the guest while it is - running. Typically this uses some hypervisor-specific transport - to avoid being dependent on a working network configuration. - Xen, VMware, and VirtualBox have guest agents,although the Xen - driver is the only one with an implementation for managing them - in openstack. KVM doesn't really have a concept of a guest agent - (although one could be written). + """(Removed) Controller for agent resources. - You can find the design of agent update in this link: - http://wiki.openstack.org/AgentUpdate - In this design We need update agent in guest from host, so we need - some interfaces to update the agent info in host. - - You can find more information about the design of the GuestAgent in - the following link: - http://wiki.openstack.org/GuestAgent - http://wiki.openstack.org/GuestAgentXenStoreCommunication + This was removed during the Victoria release along with the XenAPI driver. """ - @validation.query_schema(schema.index_query_275, '2.75') - @validation.query_schema(schema.index_query, '2.0', '2.74') - @wsgi.expected_errors(()) + @wsgi.expected_errors(410) def index(self, req): - """Return a list of all agent builds. Filter by hypervisor.""" - context = req.environ['nova.context'] - context.can(agents_policies.BASE_POLICY_NAME % 'list', target={}) - hypervisor = None - agents = [] - if 'hypervisor' in req.GET: - hypervisor = req.GET['hypervisor'] + raise exc.HTTPGone() - builds = objects.AgentList.get_all(context, hypervisor=hypervisor) - for agent_build in builds: - agents.append({'hypervisor': agent_build.hypervisor, - 'os': agent_build.os, - 'architecture': agent_build.architecture, - 'version': agent_build.version, - 'md5hash': agent_build.md5hash, - 'agent_id': agent_build.id, - 'url': agent_build.url}) - - return {'agents': agents} - - @wsgi.expected_errors((400, 404)) - @validation.schema(schema.update) + @wsgi.expected_errors(410) def update(self, req, id, body): - """Update an existing agent build.""" - context = req.environ['nova.context'] - context.can(agents_policies.BASE_POLICY_NAME % 'update', target={}) + raise exc.HTTPGone() - # TODO(oomichi): This parameter name "para" is different from the ones - # of the other APIs. Most other names are resource names like "server" - # etc. This name should be changed to "agent" for consistent naming - # with v2.1+microversions. - para = body['para'] - - url = para['url'] - md5hash = para['md5hash'] - version = para['version'] - - try: - utils.validate_integer(id, 'id') - except exception.InvalidInput as exc: - raise webob.exc.HTTPBadRequest(explanation=exc.format_message()) - - agent = objects.Agent(context=context, id=id) - agent.obj_reset_changes() - agent.version = version - agent.url = url - agent.md5hash = md5hash - try: - agent.save() - except exception.AgentBuildNotFound as ex: - raise webob.exc.HTTPNotFound(explanation=ex.format_message()) - - # TODO(alex_xu): The agent_id should be integer that consistent with - # create/index actions. But parameter 'id' is string type that parsed - # from url. This is a bug, but because back-compatibility, it can't be - # fixed for v2 API. This will be fixed in v2.1 API by Microversions in - # the future. lp bug #1333494 - return {"agent": {'agent_id': id, 'version': version, - 'url': url, 'md5hash': md5hash}} - - # TODO(oomichi): Here should be 204(No Content) instead of 200 by v2.1 - # +microversions because the resource agent has been deleted completely - # when returning a response. - @wsgi.expected_errors((400, 404)) - @wsgi.response(200) + @wsgi.expected_errors(410) def delete(self, req, id): - """Deletes an existing agent build.""" - context = req.environ['nova.context'] - context.can(agents_policies.BASE_POLICY_NAME % 'delete', target={}) + raise exc.HTTPGone() - try: - utils.validate_integer(id, 'id') - except exception.InvalidInput as exc: - raise webob.exc.HTTPBadRequest(explanation=exc.format_message()) - - try: - agent = objects.Agent(context=context, id=id) - agent.destroy() - except exception.AgentBuildNotFound as ex: - raise webob.exc.HTTPNotFound(explanation=ex.format_message()) - - # TODO(oomichi): Here should be 201(Created) instead of 200 by v2.1 - # +microversions because the creation of a resource agent finishes - # when returning a response. - @wsgi.expected_errors(409) - @wsgi.response(200) - @validation.schema(schema.create) + @wsgi.expected_errors(410) def create(self, req, body): - """Creates a new agent build.""" - context = req.environ['nova.context'] - context.can(agents_policies.BASE_POLICY_NAME % 'create', target={}) - - agent = body['agent'] - hypervisor = agent['hypervisor'] - os = agent['os'] - architecture = agent['architecture'] - version = agent['version'] - url = agent['url'] - md5hash = agent['md5hash'] - - agent_obj = objects.Agent(context=context) - agent_obj.hypervisor = hypervisor - agent_obj.os = os - agent_obj.architecture = architecture - agent_obj.version = version - agent_obj.url = url - agent_obj.md5hash = md5hash - - try: - agent_obj.create() - agent['agent_id'] = agent_obj.id - except exception.AgentBuildExists as ex: - raise webob.exc.HTTPConflict(explanation=ex.format_message()) - return {'agent': agent} + raise exc.HTTPGone() diff --git a/nova/api/openstack/compute/schemas/agents.py b/nova/api/openstack/compute/schemas/agents.py deleted file mode 100644 index 54add72d0fbb..000000000000 --- a/nova/api/openstack/compute/schemas/agents.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2013 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. - -import copy - -from nova.api.validation import parameter_types - -create = { - 'type': 'object', - 'properties': { - 'agent': { - 'type': 'object', - 'properties': { - 'hypervisor': { - 'type': 'string', 'minLength': 0, 'maxLength': 255, - 'pattern': '^[a-zA-Z0-9-._ ]*$' - }, - 'os': { - 'type': 'string', 'minLength': 0, 'maxLength': 255, - 'pattern': '^[a-zA-Z0-9-._ ]*$' - }, - 'architecture': { - 'type': 'string', 'minLength': 0, 'maxLength': 255, - 'pattern': '^[a-zA-Z0-9-._ ]*$' - }, - 'version': { - 'type': 'string', 'minLength': 0, 'maxLength': 255, - 'pattern': '^[a-zA-Z0-9-._ ]*$' - }, - 'url': { - 'type': 'string', 'minLength': 0, 'maxLength': 255, - 'format': 'uri' - }, - 'md5hash': { - 'type': 'string', 'minLength': 0, 'maxLength': 255, - 'pattern': '^[a-fA-F0-9]*$' - }, - }, - 'required': ['hypervisor', 'os', 'architecture', 'version', - 'url', 'md5hash'], - 'additionalProperties': False, - }, - }, - 'required': ['agent'], - 'additionalProperties': False, -} - - -update = { - 'type': 'object', - 'properties': { - 'para': { - 'type': 'object', - 'properties': { - 'version': { - 'type': 'string', 'minLength': 0, 'maxLength': 255, - 'pattern': '^[a-zA-Z0-9-._ ]*$' - }, - 'url': { - 'type': 'string', 'minLength': 0, 'maxLength': 255, - 'format': 'uri' - }, - 'md5hash': { - 'type': 'string', 'minLength': 0, 'maxLength': 255, - 'pattern': '^[a-fA-F0-9]*$' - }, - }, - 'required': ['version', 'url', 'md5hash'], - 'additionalProperties': False, - }, - }, - 'required': ['para'], - 'additionalProperties': False, -} - -index_query = { - 'type': 'object', - 'properties': { - 'hypervisor': parameter_types.common_query_param - }, - # NOTE(gmann): This is kept True to keep backward compatibility. - # As of now Schema validation stripped out the additional parameters and - # does not raise 400. In microversion 2.75, we have blocked the additional - # parameters. - 'additionalProperties': True -} - -index_query_275 = copy.deepcopy(index_query) -index_query_275['additionalProperties'] = False diff --git a/nova/objects/agent.py b/nova/objects/agent.py index 9f5884453d9c..9bea1df40683 100644 --- a/nova/objects/agent.py +++ b/nova/objects/agent.py @@ -19,6 +19,8 @@ from nova.objects import base from nova.objects import fields +# TODO(stephenfin): Remove this object; it's not necessary since the removal of +# XenAPI @base.NovaObjectRegistry.register class Agent(base.NovaPersistentObject, base.NovaObject): VERSION = '1.0' @@ -69,6 +71,8 @@ class Agent(base.NovaPersistentObject, base.NovaObject): self.obj_reset_changes() +# TODO(stephenfin): Remove this object; it's not necessary since the removal of +# XenAPI @base.NovaObjectRegistry.register class AgentList(base.ObjectListBase, base.NovaObject): VERSION = '1.0' diff --git a/nova/policies/__init__.py b/nova/policies/__init__.py index 91362d26064f..d5c485cfa3da 100644 --- a/nova/policies/__init__.py +++ b/nova/policies/__init__.py @@ -15,7 +15,6 @@ import itertools from nova.policies import admin_actions from nova.policies import admin_password -from nova.policies import agents from nova.policies import aggregates from nova.policies import assisted_volume_snapshots from nova.policies import attach_interfaces @@ -75,7 +74,6 @@ def list_rules(): base.list_rules(), admin_actions.list_rules(), admin_password.list_rules(), - agents.list_rules(), aggregates.list_rules(), assisted_volume_snapshots.list_rules(), attach_interfaces.list_rules(), diff --git a/nova/policies/agents.py b/nova/policies/agents.py deleted file mode 100644 index eb420b8dca1b..000000000000 --- a/nova/policies/agents.py +++ /dev/null @@ -1,108 +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 - - -BASE_POLICY_NAME = 'os_compute_api:os-agents:%s' - -DEPRECATED_AGENTS_POLICY = policy.DeprecatedRule( - 'os_compute_api:os-agents', - base.RULE_ADMIN_API, -) - -DEPRECATED_REASON = """ -Nova API policies are introducing new default roles with scope_type -capabilities. Old policies are deprecated and silently going to be ignored -in nova 23.0.0 release. -""" - -agents_policies = [ - policy.DocumentedRuleDefault( - name=BASE_POLICY_NAME % 'list', - check_str=base.SYSTEM_READER, - description="""List guest agent builds -This is XenAPI driver specific. -It is used to force the upgrade of the XenAPI guest agent on instance boot. -""", - operations=[ - { - 'path': '/os-agents', - 'method': 'GET' - }, - ], - scope_types=['system'], - deprecated_rule=DEPRECATED_AGENTS_POLICY, - deprecated_reason=DEPRECATED_REASON, - deprecated_since='21.0.0'), - policy.DocumentedRuleDefault( - name=BASE_POLICY_NAME % 'create', - check_str=base.SYSTEM_ADMIN, - description="""Create guest agent builds -This is XenAPI driver specific. -It is used to force the upgrade of the XenAPI guest agent on instance boot. -""", - operations=[ - - { - 'path': '/os-agents', - 'method': 'POST' - }, - ], - scope_types=['system'], - deprecated_rule=DEPRECATED_AGENTS_POLICY, - deprecated_reason=DEPRECATED_REASON, - deprecated_since='21.0.0'), - policy.DocumentedRuleDefault( - name=BASE_POLICY_NAME % 'update', - check_str=base.SYSTEM_ADMIN, - description="""Update guest agent builds -This is XenAPI driver specific. -It is used to force the upgrade of the XenAPI guest agent on instance boot. -""", - operations=[ - { - 'path': '/os-agents/{agent_build_id}', - 'method': 'PUT' - }, - ], - scope_types=['system'], - deprecated_rule=DEPRECATED_AGENTS_POLICY, - deprecated_reason=DEPRECATED_REASON, - deprecated_since='21.0.0'), - policy.DocumentedRuleDefault( - name=BASE_POLICY_NAME % 'delete', - check_str=base.SYSTEM_ADMIN, - description="""Delete guest agent builds -This is XenAPI driver specific. -It is used to force the upgrade of the XenAPI guest agent on instance boot. -""", - operations=[ - { - 'path': '/os-agents/{agent_build_id}', - 'method': 'DELETE' - } - ], - scope_types=['system'], - deprecated_rule=DEPRECATED_AGENTS_POLICY, - deprecated_reason=DEPRECATED_REASON, - deprecated_since='21.0.0'), -] - - -def list_rules(): - return agents_policies diff --git a/nova/tests/functional/api_sample_tests/test_agents.py b/nova/tests/functional/api_sample_tests/test_agents.py index 6702a1092d9f..894a0b8e9032 100644 --- a/nova/tests/functional/api_sample_tests/test_agents.py +++ b/nova/tests/functional/api_sample_tests/test_agents.py @@ -13,86 +13,23 @@ # License for the specific language governing permissions and limitations # under the License. -from nova.db.sqlalchemy import models from nova.tests.functional.api_sample_tests import api_sample_base class AgentsJsonTest(api_sample_base.ApiSampleTestBaseV21): - ADMIN_API = True - sample_dir = "os-agents" - - def setUp(self): - super(AgentsJsonTest, self).setUp() - - fake_agents_list = [{'url': 'http://example.com/path/to/resource', - 'hypervisor': 'xen', - 'architecture': 'x86', - 'os': 'os', - 'version': '8.0', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'id': 1}] - - def fake_agent_build_create(context, values): - values['id'] = 1 - agent_build_ref = models.AgentBuild() - agent_build_ref.update(values) - return agent_build_ref - - def fake_agent_build_get_all(context, hypervisor): - agent_build_all = [] - for agent in fake_agents_list: - if hypervisor and hypervisor != agent['hypervisor']: - continue - agent_build_ref = models.AgentBuild() - agent_build_ref.update(agent) - agent_build_all.append(agent_build_ref) - return agent_build_all - - def fake_agent_build_update(context, agent_build_id, values): - pass - - def fake_agent_build_destroy(context, agent_update_id): - pass - - self.stub_out("nova.db.api.agent_build_create", - fake_agent_build_create) - self.stub_out("nova.db.api.agent_build_get_all", - fake_agent_build_get_all) - self.stub_out("nova.db.api.agent_build_update", - fake_agent_build_update) - self.stub_out("nova.db.api.agent_build_destroy", - fake_agent_build_destroy) def test_agent_create(self): # Creates a new agent build. - project = {'url': 'http://example.com/path/to/resource', - 'hypervisor': 'xen', - 'architecture': 'x86', - 'os': 'os', - 'version': '8.0', - 'md5hash': 'add6bb58e139be103324d04d82d8f545' - } - response = self._do_post('os-agents', 'agent-post-req', - project) - self._verify_response('agent-post-resp', project, response, 200) + self.api.api_post('/os-agents', {}, check_response_status=[410]) def test_agent_list(self): # Return a list of all agent builds. - response = self._do_get('os-agents') - self._verify_response('agents-get-resp', {}, response, 200) + self.api.api_get('/os-agents', check_response_status=[410]) def test_agent_update(self): # Update an existing agent build. - agent_id = 1 - subs = {'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'} - response = self._do_put('os-agents/%s' % agent_id, - 'agent-update-put-req', subs) - self._verify_response('agent-update-put-resp', subs, response, 200) + self.api.api_put('/os-agents/1', {}, check_response_status=[410]) def test_agent_delete(self): # Deletes an existing agent build. - agent_id = 1 - response = self._do_delete('os-agents/%s' % agent_id) - self.assertEqual(200, response.status_code) + self.api.api_delete('/os-agents/1', check_response_status=[410]) diff --git a/nova/tests/unit/api/openstack/compute/test_agents.py b/nova/tests/unit/api/openstack/compute/test_agents.py deleted file mode 100644 index bed4fc31066d..000000000000 --- a/nova/tests/unit/api/openstack/compute/test_agents.py +++ /dev/null @@ -1,431 +0,0 @@ -# Copyright 2012 IBM Corp. -# -# 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. - -import mock -import webob.exc - -from nova.api.openstack.compute import agents as agents_v21 -from nova.db import api as db -from nova.db.sqlalchemy import models -from nova import exception -from nova import test -from nova.tests.unit.api.openstack import fakes - -fake_agents_list = [{'hypervisor': 'kvm', 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'id': 1}, - {'hypervisor': 'kvm', 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'http://example.com/path/to/resource1', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'id': 2}, - {'hypervisor': 'xen', 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'http://example.com/path/to/resource2', - 'md5hash': 'add6bb58e139be103324d04d82d8f547', - 'id': 3}, - {'hypervisor': 'xen', 'os': 'win', - 'architecture': 'power', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource3', - 'md5hash': 'add6bb58e139be103324d04d82d8f548', - 'id': 4}, - ] - - -def fake_agent_build_get_all(context, hypervisor): - agent_build_all = [] - for agent in fake_agents_list: - if hypervisor and hypervisor != agent['hypervisor']: - continue - agent_build_ref = models.AgentBuild() - agent_build_ref.update(agent) - agent_build_all.append(agent_build_ref) - return agent_build_all - - -def fake_agent_build_update(context, agent_build_id, values): - pass - - -def fake_agent_build_destroy(context, agent_update_id): - pass - - -def fake_agent_build_create(context, values): - values['id'] = 1 - agent_build_ref = models.AgentBuild() - agent_build_ref.update(values) - return agent_build_ref - - -class AgentsTestV21(test.NoDBTestCase): - controller = agents_v21.AgentController() - validation_error = exception.ValidationError - microversion = '2.1' - - def setUp(self): - super(AgentsTestV21, self).setUp() - - self.stub_out("nova.db.api.agent_build_get_all", - fake_agent_build_get_all) - self.stub_out("nova.db.api.agent_build_update", - fake_agent_build_update) - self.stub_out("nova.db.api.agent_build_destroy", - fake_agent_build_destroy) - self.stub_out("nova.db.api.agent_build_create", - fake_agent_build_create) - self.req = self._get_http_request() - - def _get_http_request(self): - return fakes.HTTPRequest.blank('', version=self.microversion) - - def test_agents_create(self): - body = {'agent': {'hypervisor': 'kvm', - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - response = {'agent': {'hypervisor': 'kvm', - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'agent_id': 1}} - res_dict = self.controller.create(self.req, body=body) - self.assertEqual(res_dict, response) - - def _test_agents_create_key_error(self, key): - body = {'agent': {'hypervisor': 'kvm', - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'xxx://xxxx/xxx/xxx', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - body['agent'].pop(key) - self.assertRaises(self.validation_error, - self.controller.create, self.req, body=body) - - def test_agents_create_without_hypervisor(self): - self._test_agents_create_key_error('hypervisor') - - def test_agents_create_without_os(self): - self._test_agents_create_key_error('os') - - def test_agents_create_without_architecture(self): - self._test_agents_create_key_error('architecture') - - def test_agents_create_without_version(self): - self._test_agents_create_key_error('version') - - def test_agents_create_without_url(self): - self._test_agents_create_key_error('url') - - def test_agents_create_without_md5hash(self): - self._test_agents_create_key_error('md5hash') - - def test_agents_create_with_wrong_type(self): - body = {'agent': None} - self.assertRaises(self.validation_error, - self.controller.create, self.req, body=body) - - def test_agents_create_with_empty_type(self): - body = {} - self.assertRaises(self.validation_error, - self.controller.create, self.req, body=body) - - def test_agents_create_with_existed_agent(self): - def fake_agent_build_create_with_exited_agent(context, values): - raise exception.AgentBuildExists(**values) - - self.stub_out('nova.db.api.agent_build_create', - fake_agent_build_create_with_exited_agent) - body = {'agent': {'hypervisor': 'kvm', - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'xxx://xxxx/xxx/xxx', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - self.assertRaises(webob.exc.HTTPConflict, self.controller.create, - self.req, body=body) - - def _test_agents_create_with_invalid_length(self, key): - body = {'agent': {'hypervisor': 'kvm', - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - body['agent'][key] = 'x' * 256 - self.assertRaises(self.validation_error, - self.controller.create, self.req, body=body) - - def test_agents_create_with_invalid_length_hypervisor(self): - self._test_agents_create_with_invalid_length('hypervisor') - - def test_agents_create_with_invalid_length_os(self): - self._test_agents_create_with_invalid_length('os') - - def test_agents_create_with_invalid_length_architecture(self): - self._test_agents_create_with_invalid_length('architecture') - - def test_agents_create_with_invalid_length_version(self): - self._test_agents_create_with_invalid_length('version') - - def test_agents_create_with_invalid_length_url(self): - self._test_agents_create_with_invalid_length('url') - - def test_agents_create_with_invalid_length_md5hash(self): - self._test_agents_create_with_invalid_length('md5hash') - - def test_agents_delete(self): - self.controller.delete(self.req, 1) - - def test_agents_delete_with_id_not_found(self): - with mock.patch.object(db, 'agent_build_destroy', - side_effect=exception.AgentBuildNotFound(id=1)): - self.assertRaises(webob.exc.HTTPNotFound, - self.controller.delete, self.req, 1) - - def test_agents_delete_string_id(self): - self.assertRaises(webob.exc.HTTPBadRequest, - self.controller.delete, self.req, 'string_id') - - def _test_agents_list(self, query_string=None): - req = fakes.HTTPRequest.blank('', use_admin_context=True, - query_string=query_string, - version=self.microversion) - res_dict = self.controller.index(req) - agents_list = [{'hypervisor': 'kvm', 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'agent_id': 1}, - {'hypervisor': 'kvm', 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'http://example.com/path/to/resource1', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'agent_id': 2}, - {'hypervisor': 'xen', 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'http://example.com/path/to/resource2', - 'md5hash': 'add6bb58e139be103324d04d82d8f547', - 'agent_id': 3}, - {'hypervisor': 'xen', 'os': 'win', - 'architecture': 'power', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource3', - 'md5hash': 'add6bb58e139be103324d04d82d8f548', - 'agent_id': 4}, - ] - self.assertEqual(res_dict, {'agents': agents_list}) - - def test_agents_list(self): - self._test_agents_list() - - def test_agents_list_with_hypervisor(self): - req = fakes.HTTPRequest.blank('', use_admin_context=True, - query_string='hypervisor=kvm', - version=self.microversion) - res_dict = self.controller.index(req) - response = [{'hypervisor': 'kvm', 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'agent_id': 1}, - {'hypervisor': 'kvm', 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'http://example.com/path/to/resource1', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'agent_id': 2}, - ] - self.assertEqual(res_dict, {'agents': response}) - - def test_agents_list_with_multi_hypervisor_filter(self): - query_string = 'hypervisor=xen&hypervisor=kvm' - req = fakes.HTTPRequest.blank('', use_admin_context=True, - query_string=query_string, - version=self.microversion) - res_dict = self.controller.index(req) - response = [{'hypervisor': 'kvm', 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'agent_id': 1}, - {'hypervisor': 'kvm', 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'http://example.com/path/to/resource1', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'agent_id': 2}, - ] - self.assertEqual(res_dict, {'agents': response}) - - def test_agents_list_query_allow_negative_int_as_string(self): - req = fakes.HTTPRequest.blank('', use_admin_context=True, - query_string='hypervisor=-1', - version=self.microversion) - res_dict = self.controller.index(req) - self.assertEqual(res_dict, {'agents': []}) - - def test_agents_list_query_allow_int_as_string(self): - req = fakes.HTTPRequest.blank('', use_admin_context=True, - query_string='hypervisor=1', - version=self.microversion) - res_dict = self.controller.index(req) - self.assertEqual(res_dict, {'agents': []}) - - def test_agents_list_with_unknown_filter(self): - query_string = 'unknown_filter=abc' - self._test_agents_list(query_string=query_string) - - def test_agents_list_with_hypervisor_and_additional_filter(self): - req = fakes.HTTPRequest.blank( - '', use_admin_context=True, - query_string='hypervisor=kvm&additional_filter=abc', - version=self.microversion) - res_dict = self.controller.index(req) - response = [{'hypervisor': 'kvm', 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'agent_id': 1}, - {'hypervisor': 'kvm', 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'http://example.com/path/to/resource1', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'agent_id': 2}, - ] - self.assertEqual(res_dict, {'agents': response}) - - def test_agents_update(self): - body = {'para': {'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - response = {'agent': {'agent_id': 1, - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - res_dict = self.controller.update(self.req, 1, body=body) - self.assertEqual(res_dict, response) - - def _test_agents_update_key_error(self, key): - body = {'para': {'version': '7.0', - 'url': 'xxx://xxxx/xxx/xxx', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - body['para'].pop(key) - self.assertRaises(self.validation_error, - self.controller.update, self.req, 1, body=body) - - def test_agents_update_without_version(self): - self._test_agents_update_key_error('version') - - def test_agents_update_without_url(self): - self._test_agents_update_key_error('url') - - def test_agents_update_without_md5hash(self): - self._test_agents_update_key_error('md5hash') - - def test_agents_update_with_wrong_type(self): - body = {'agent': None} - self.assertRaises(self.validation_error, - self.controller.update, self.req, 1, body=body) - - def test_agents_update_with_empty(self): - body = {} - self.assertRaises(self.validation_error, - self.controller.update, self.req, 1, body=body) - - def test_agents_update_value_error(self): - body = {'para': {'version': '7.0', - 'url': 1111, - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - self.assertRaises(self.validation_error, - self.controller.update, self.req, 1, body=body) - - def test_agents_update_with_string_id(self): - body = {'para': {'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - self.assertRaises(webob.exc.HTTPBadRequest, - self.controller.update, self.req, - 'string_id', body=body) - - def _test_agents_update_with_invalid_length(self, key): - body = {'para': {'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - body['para'][key] = 'x' * 256 - self.assertRaises(self.validation_error, - self.controller.update, self.req, 1, body=body) - - def test_agents_update_with_invalid_length_version(self): - self._test_agents_update_with_invalid_length('version') - - def test_agents_update_with_invalid_length_url(self): - self._test_agents_update_with_invalid_length('url') - - def test_agents_update_with_invalid_length_md5hash(self): - self._test_agents_update_with_invalid_length('md5hash') - - def test_agents_update_with_id_not_found(self): - with mock.patch.object(db, 'agent_build_update', - side_effect=exception.AgentBuildNotFound(id=1)): - body = {'para': {'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - self.assertRaises(webob.exc.HTTPNotFound, - self.controller.update, self.req, 1, body=body) - - -class AgentsTestV275(AgentsTestV21): - microversion = '2.75' - - def test_agents_list_additional_filter_old_version(self): - req = fakes.HTTPRequest.blank( - '', use_admin_context=True, - query_string='additional_filter=abc', - version='2.74') - self.controller.index(req) - - def test_agents_list_with_unknown_filter(self): - req = fakes.HTTPRequest.blank( - '', use_admin_context=True, - query_string='unknown_filter=abc', - version=self.microversion) - self.assertRaises(exception.ValidationError, - self.controller.index, req) - - def test_agents_list_with_hypervisor_and_additional_filter(self): - req = fakes.HTTPRequest.blank( - '', use_admin_context=True, - query_string='hypervisor=kvm&additional_filter=abc', - version=self.microversion) - self.assertRaises(exception.ValidationError, - self.controller.index, req) diff --git a/nova/tests/unit/fake_policy.py b/nova/tests/unit/fake_policy.py index 5efe00211060..9f19d29ef0e5 100644 --- a/nova/tests/unit/fake_policy.py +++ b/nova/tests/unit/fake_policy.py @@ -54,10 +54,6 @@ policy_data = """ "os_compute_api:os-admin-actions:reset_network": "", "os_compute_api:os-admin-actions:reset_state": "", "os_compute_api:os-admin-password": "", - "os_compute_api:os-agents:list": "", - "os_compute_api:os-agents:create": "", - "os_compute_api:os-agents:update": "", - "os_compute_api:os-agents:delete": "", "os_compute_api:os-aggregates:set_metadata": "", "os_compute_api:os-aggregates:remove_host": "", "os_compute_api:os-aggregates:add_host": "", diff --git a/nova/tests/unit/policies/test_agents.py b/nova/tests/unit/policies/test_agents.py deleted file mode 100644 index d4c5f28b31c9..000000000000 --- a/nova/tests/unit/policies/test_agents.py +++ /dev/null @@ -1,212 +0,0 @@ -# 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. - -import mock - -from nova.api.openstack.compute import agents -from nova.db.sqlalchemy import models -from nova import exception -from nova.policies import base as base_policy -from nova.tests.unit.api.openstack import fakes -from nova.tests.unit.policies import base -from nova.tests.unit import policy_fixture - - -class AgentsPolicyTest(base.BasePolicyTest): - """Test os-agents APIs policies with all possible context. - This class defines the set of context with different roles - which are allowed and not allowed to pass the policy checks. - With those set of context, it will call the API operation and - verify the expected behaviour. - """ - - def setUp(self): - super(AgentsPolicyTest, self).setUp() - self.controller = agents.AgentController() - self.req = fakes.HTTPRequest.blank('') - # Check that admin is able to perform the CRUD operation - # on agents. - self.admin_authorized_contexts = [ - self.legacy_admin_context, self.system_admin_context, - self.project_admin_context] - # Check that non-admin is not able to perform the CRUD operation - # on agents. - self.admin_unauthorized_contexts = [ - self.system_member_context, self.system_reader_context, - self.system_foo_context, self.project_member_context, - self.other_project_member_context, - self.other_project_reader_context, - self.project_foo_context, self.project_reader_context - ] - - # Check that system scoped admin, member and reader are able to - # read the agent data. - # NOTE(gmann): Until old default rule which is admin_api is - # deprecated and not removed, project admin and legacy admin - # will be able to read the agent data. This make sure that existing - # tokens will keep working even we have changed this policy defaults - # to reader role. - self.reader_authorized_contexts = [ - self.system_admin_context, self.system_member_context, - self.system_reader_context, self.legacy_admin_context, - self.project_admin_context] - # Check that non-system-reader are not able to read the agent - # data - self.reader_unauthorized_contexts = [ - self.system_foo_context, self.other_project_member_context, - self.project_foo_context, self.project_member_context, - self.project_reader_context, self.other_project_reader_context, - ] - - @mock.patch('nova.db.api.agent_build_destroy') - def test_delete_agent_policy(self, mock_delete): - rule_name = "os_compute_api:os-agents:delete" - self.common_policy_check(self.admin_authorized_contexts, - self.admin_unauthorized_contexts, - rule_name, self.controller.delete, - self.req, 1) - - @mock.patch('nova.db.api.agent_build_get_all') - def test_index_agents_policy(self, mock_get): - rule_name = "os_compute_api:os-agents:list" - self.common_policy_check(self.reader_authorized_contexts, - self.reader_unauthorized_contexts, - rule_name, self.controller.index, - self.req) - - @mock.patch('nova.db.api.agent_build_update') - def test_update_agent_policy(self, mock_update): - rule_name = "os_compute_api:os-agents:update" - body = {'para': {'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - - self.common_policy_check(self.admin_authorized_contexts, - self.admin_unauthorized_contexts, - rule_name, self.controller.update, - self.req, 1, body=body) - - def test_create_agent_policy(self): - rule_name = "os_compute_api:os-agents:create" - body = {'agent': {'hypervisor': 'kvm', - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'http://example.com/path/to/resource', - 'md5hash': 'add6bb58e139be103324d04d82d8f545'}} - - def fake_agent_build_create(context, values): - values['id'] = 1 - agent_build_ref = models.AgentBuild() - agent_build_ref.update(values) - return agent_build_ref - - self.stub_out("nova.db.api.agent_build_create", - fake_agent_build_create) - - self.common_policy_check(self.admin_authorized_contexts, - self.admin_unauthorized_contexts, - rule_name, self.controller.create, - self.req, body=body) - - -class AgentsScopeTypePolicyTest(AgentsPolicyTest): - """Test os-agents APIs policies with system scope enabled. - This class set the nova.conf [oslo_policy] enforce_scope to True - so that we can switch on the scope checking on oslo policy side. - It defines the set of context with scoped token - which are allowed and not allowed to pass the policy checks. - With those set of context, it will run the API operation and - verify the expected behaviour. - """ - - def setUp(self): - super(AgentsScopeTypePolicyTest, self).setUp() - self.flags(enforce_scope=True, group="oslo_policy") - - # Check that system admin is able to perform the CRUD operation - # on agents. - self.admin_authorized_contexts = [ - self.system_admin_context] - # Check that non-system or non-admin is not able to perform the CRUD - # operation on agents. - self.admin_unauthorized_contexts = [ - self.legacy_admin_context, self.system_member_context, - self.system_reader_context, self.project_admin_context, - self.system_foo_context, self.project_member_context, - self.other_project_member_context, - self.project_foo_context, self.project_reader_context, - self.other_project_reader_context, - ] - - # Check that system admin, member and reader are able to read the - # agent data - self.reader_authorized_contexts = [ - self.system_admin_context, self.system_member_context, - self.system_reader_context] - # Check that non-system or non-reader are not able to read the agent - # data - self.reader_unauthorized_contexts = [ - self.system_foo_context, self.legacy_admin_context, - self.project_admin_context, self.project_member_context, - self.other_project_member_context, - self.project_foo_context, self.project_reader_context, - self.other_project_reader_context, - ] - - -class AgentsDeprecatedPolicyTest(base.BasePolicyTest): - """Test os-agents APIs Deprecated policies. - This class checks if deprecated policy rules are - overridden by user on policy.yaml file then they - still work because oslo.policy add deprecated rules - in logical OR condition and enforce them for policy - checks if overridden. - """ - - def setUp(self): - super(AgentsDeprecatedPolicyTest, self).setUp() - self.controller = agents.AgentController() - self.admin_req = fakes.HTTPRequest.blank('') - self.admin_req.environ['nova.context'] = self.project_admin_context - self.reader_req = fakes.HTTPRequest.blank('') - self.reader_req.environ['nova.context'] = self.project_reader_context - self.deprecated_policy = "os_compute_api:os-agents" - # Overridde rule with different checks than defaults so that we can - # verify the rule overridden case. - override_rules = {self.deprecated_policy: base_policy.RULE_ADMIN_API} - # NOTE(gmann): Only override the deprecated rule in policy file so - # that we can verify if overridden checks are considered by - # oslo.policy. Oslo.policy will consider the overridden rules if: - # 1. overridden deprecated rule's checks are different than defaults - # 2. new rules are not present in policy file - self.policy = self.useFixture(policy_fixture.OverridePolicyFixture( - rules_in_file=override_rules)) - - def test_deprecated_policy_overridden_rule_is_checked(self): - # Test to verify if deprecatd overridden policy is working. - - # check for success as admin role. Deprecated rule - # has been overridden with admin checks in policy.yaml - # If admin role pass it means overridden rule is enforced by - # olso.policy because new default is system reader and the old - # default is admin. - with mock.patch('nova.db.api.agent_build_get_all'): - self.controller.index(self.admin_req) - - # check for failure with reader context. - exc = self.assertRaises(exception.PolicyNotAuthorized, - self.controller.index, self.reader_req) - self.assertEqual( - "Policy doesn't allow os_compute_api:os-agents:list to be" - " performed.", - exc.format_message()) diff --git a/nova/tests/unit/test_policy.py b/nova/tests/unit/test_policy.py index 31fee0be7461..aae8e6346f06 100644 --- a/nova/tests/unit/test_policy.py +++ b/nova/tests/unit/test_policy.py @@ -337,9 +337,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase): "os_compute_api:os-aggregates:add_host", "os_compute_api:os-aggregates:remove_host", "os_compute_api:os-aggregates:set_metadata", -"os_compute_api:os-agents:create", -"os_compute_api:os-agents:update", -"os_compute_api:os-agents:delete", "os_compute_api:os-evacuate", "os_compute_api:os-extended-server-attributes", "os_compute_api:os-flavor-access:remove_tenant_access", @@ -484,7 +481,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase): "os_compute_api:os-instance-actions:events:details", "os_compute_api:os-instance-usage-audit-log:list", "os_compute_api:os-instance-usage-audit-log:show", -"os_compute_api:os-agents:list", "os_compute_api:os-hosts:list", "os_compute_api:os-hosts:show", "os_compute_api:os-hypervisors:list", diff --git a/releasenotes/notes/remove-xenapi-driver-194756049f22dc9e.yaml b/releasenotes/notes/remove-xenapi-driver-194756049f22dc9e.yaml index 25f82ce1e8b3..a09b29b24d28 100644 --- a/releasenotes/notes/remove-xenapi-driver-194756049f22dc9e.yaml +++ b/releasenotes/notes/remove-xenapi-driver-194756049f22dc9e.yaml @@ -3,10 +3,25 @@ upgrade: - | The ``XenAPI`` driver, which was deprecated in the 20.0.0 (Train), has now been removed. - - | - The following config options only apply when using the ``XenAPI`` virt - driver which has now been removed. The config options have therefore been - removed also. + + A number of APIs that only worked with the ``XenAPI`` driver have been + removed along with their related policy rules. Calling these APIs will now + result in a ``410 (Gone)`` error response. + + * ``GET /os-agents`` + * ``POST /os-agents`` + * ``PUT /os-agents/{agent_id}`` + * ``DELETE /os-agents/{agent_id}`` + + The ``XenAPI`` specific policies have been removed: + + * ``os_compute_api:os-agents`` + * ``os_compute_api:os-agents:list`` + * ``os_compute_api:os-agents:create`` + * ``os_compute_api:os-agents:update`` + * ``os_compute_api:os-agents:delete`` + + The ``XenAPI`` specific configuration options have been removed. * ``[xenserver] agent_timeout`` * ``[xenserver] agent_version_timeout``