api: Remove 'os-agents' API
This was only useful with XenAPI and can therefore be removed. Change-Id: I9512f605dd2b3b0e88c951ed086250d57056303d Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
8aea747c97
commit
7ac52e643c
@ -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
|
||||
-------
|
||||
|
@ -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()
|
||||
|
@ -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
|
@ -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'
|
||||
|
@ -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(),
|
||||
|
@ -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
|
@ -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])
|
||||
|
@ -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)
|
@ -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": "",
|
||||
|
@ -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())
|
@ -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",
|
||||
|
@ -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``
|
||||
|
Loading…
x
Reference in New Issue
Block a user