Merge "Add agent build API support for list/create/delete/modify agent build"
This commit is contained in:
commit
2804b01a6b
@ -64,6 +64,14 @@
|
||||
"namespace": "http://docs.openstack.org/compute/ext/admin-actions/api/v1.1",
|
||||
"updated": "2011-09-20T00:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"alias": "os-agents",
|
||||
"description": "Agents support",
|
||||
"links": [],
|
||||
"name": "Agents",
|
||||
"namespace": "http://docs.openstack.org/compute/ext/agents/api/v2",
|
||||
"updated": "2012-10-28T00:00:00-00:00"
|
||||
},
|
||||
{
|
||||
"alias": "os-aggregates",
|
||||
"description": "Admin-only aggregate administration",
|
||||
|
@ -28,6 +28,9 @@
|
||||
resetNetwork, injectNetworkInfo, lock, unlock, createBackup
|
||||
</description>
|
||||
</extension>
|
||||
<extension alias="os-agents" updated="2012-10-28T00:00:00-00:00" namespace="http://docs.openstack.org/compute/ext/agents/api/v2" name="Agents">
|
||||
<description>Agents support</description>
|
||||
</extension>
|
||||
<extension alias="os-aggregates" updated="2012-01-12T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/aggregates/api/v1.1" name="Aggregates">
|
||||
<description>Admin-only aggregate administration</description>
|
||||
</extension>
|
||||
|
10
doc/api_samples/os-agents/agent-post-req.json
Normal file
10
doc/api_samples/os-agents/agent-post-req.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"agent": {
|
||||
"hypervisor": "hypervisor",
|
||||
"os": "os",
|
||||
"architecture": "x86",
|
||||
"version": "8.0",
|
||||
"md5hash": "add6bb58e139be103324d04d82d8f545",
|
||||
"url": "xxxxxxxxxxxx"
|
||||
}
|
||||
}
|
9
doc/api_samples/os-agents/agent-post-req.xml
Normal file
9
doc/api_samples/os-agents/agent-post-req.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<agent>
|
||||
<hypervisor>hypervisor</hypervisor>
|
||||
<os>os</os>
|
||||
<architecture>x86</architecture>
|
||||
<version>8.0</version>
|
||||
<md5hash>add6bb58e139be103324d04d82d8f545</md5hash>
|
||||
<url>xxxxxxxxxxxx</url>
|
||||
</agent>
|
11
doc/api_samples/os-agents/agent-post-resp.json
Normal file
11
doc/api_samples/os-agents/agent-post-resp.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"agent": {
|
||||
"agent_id": "1",
|
||||
"architecture": "x86",
|
||||
"hypervisor": "hypervisor",
|
||||
"md5hash": "add6bb58e139be103324d04d82d8f545",
|
||||
"os": "os",
|
||||
"url": "xxxxxxxxxxxx",
|
||||
"version": "8.0"
|
||||
}
|
||||
}
|
10
doc/api_samples/os-agents/agent-post-resp.xml
Normal file
10
doc/api_samples/os-agents/agent-post-resp.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<agent>
|
||||
<url>xxxxxxxxxxxx</url>
|
||||
<hypervisor>hypervisor</hypervisor>
|
||||
<md5hash>add6bb58e139be103324d04d82d8f545</md5hash>
|
||||
<version>8.0</version>
|
||||
<architecture>x86</architecture>
|
||||
<os>os</os>
|
||||
<agent_id>1</agent_id>
|
||||
</agent>
|
7
doc/api_samples/os-agents/agent-update-put-req.json
Normal file
7
doc/api_samples/os-agents/agent-update-put-req.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"para": {
|
||||
"url": "xxx://xxxx/xxx/xxx",
|
||||
"md5hash": "add6bb58e139be103324d04d82d8f545",
|
||||
"version": "7.0"
|
||||
}
|
||||
}
|
6
doc/api_samples/os-agents/agent-update-put-req.xml
Normal file
6
doc/api_samples/os-agents/agent-update-put-req.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<para>
|
||||
<version>7.0</version>
|
||||
<url>xxx://xxxx/xxx/xxx</url>
|
||||
<md5hash>add6bb58e139be103324d04d82d8f545</md5hash>
|
||||
</para>
|
8
doc/api_samples/os-agents/agent-update-put-resp.json
Normal file
8
doc/api_samples/os-agents/agent-update-put-resp.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"agent": {
|
||||
"agent_id": "1",
|
||||
"md5hash": "add6bb58e139be103324d04d82d8f545",
|
||||
"url": "xxx://xxxx/xxx/xxx",
|
||||
"version": "7.0"
|
||||
}
|
||||
}
|
7
doc/api_samples/os-agents/agent-update-put-resp.xml
Normal file
7
doc/api_samples/os-agents/agent-update-put-resp.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<agent>
|
||||
<url>xxx://xxxx/xxx/xxx</url>
|
||||
<version>7.0</version>
|
||||
<agent_id>1</agent_id>
|
||||
<md5hash>add6bb58e139be103324d04d82d8f545</md5hash>
|
||||
</agent>
|
13
doc/api_samples/os-agents/agents-get-resp.json
Normal file
13
doc/api_samples/os-agents/agents-get-resp.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"agents": [
|
||||
{
|
||||
"agent_id": "1",
|
||||
"architecture": "x86",
|
||||
"hypervisor": "hypervisor",
|
||||
"md5hash": "add6bb58e139be103324d04d82d8f545",
|
||||
"os": "os",
|
||||
"url": "xxxxxxxxxxxx",
|
||||
"version": "8.0"
|
||||
}
|
||||
]
|
||||
}
|
4
doc/api_samples/os-agents/agents-get-resp.xml
Normal file
4
doc/api_samples/os-agents/agents-get-resp.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<agents>
|
||||
<agent url="xxxxxxxxxxxx" hypervisor="hypervisor" md5hash="add6bb58e139be103324d04d82d8f545" version="8.0" architecture="x86" os="os" agent_id="1"/>
|
||||
</agents>
|
@ -28,6 +28,7 @@
|
||||
"compute_extension:admin_actions:resetState": "rule:admin_api",
|
||||
"compute_extension:admin_actions:migrate": "rule:admin_api",
|
||||
"compute_extension:aggregates": "rule:admin_api",
|
||||
"compute_extension:agents": "rule:admin_api",
|
||||
"compute_extension:certificates": "",
|
||||
"compute_extension:cloudpipe": "rule:admin_api",
|
||||
"compute_extension:cloudpipe_update": "rule:admin_api",
|
||||
|
171
nova/api/openstack/compute/contrib/agents.py
Normal file
171
nova/api/openstack/compute/contrib/agents.py
Normal file
@ -0,0 +1,171 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 IBM
|
||||
# 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 webob.exc
|
||||
|
||||
from nova.api.openstack import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api.openstack import xmlutil
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
authorize = extensions.extension_authorizer('compute', 'agents')
|
||||
|
||||
|
||||
class AgentsIndexTemplate(xmlutil.TemplateBuilder):
|
||||
def construct(self):
|
||||
root = xmlutil.TemplateElement('agents')
|
||||
elem = xmlutil.SubTemplateElement(root, 'agent', selector='agents')
|
||||
elem.set('hypervisor')
|
||||
elem.set('os')
|
||||
elem.set('architecture')
|
||||
elem.set('version')
|
||||
elem.set('md5hash')
|
||||
elem.set('agent_id')
|
||||
elem.set('url')
|
||||
|
||||
return xmlutil.MasterTemplate(root, 1)
|
||||
|
||||
|
||||
class AgentController(object):
|
||||
"""
|
||||
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).
|
||||
|
||||
You can find the design of agent update in this link:
|
||||
http://wiki.openstack.org/AgentUpdate
|
||||
and find the code in nova.virt.xenapi.vmops.VMOps._boot_new_instance.
|
||||
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
|
||||
"""
|
||||
@wsgi.serializers(xml=AgentsIndexTemplate)
|
||||
def index(self, req):
|
||||
"""
|
||||
Return a list of all agent builds. Filter by hypervisor.
|
||||
"""
|
||||
context = req.environ['nova.context']
|
||||
authorize(context)
|
||||
hypervisor = None
|
||||
agents = []
|
||||
if 'hypervisor' in req.GET:
|
||||
hypervisor = req.GET['hypervisor']
|
||||
|
||||
for agent_build in db.agent_build_get_all(context, hypervisor):
|
||||
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}
|
||||
|
||||
def update(self, req, id, body):
|
||||
"""Update an existing agent build."""
|
||||
context = req.environ['nova.context']
|
||||
authorize(context)
|
||||
|
||||
try:
|
||||
para = body['para']
|
||||
url = para['url']
|
||||
md5hash = para['md5hash']
|
||||
version = para['version']
|
||||
except (TypeError, KeyError):
|
||||
raise webob.exc.HTTPUnprocessableEntity()
|
||||
|
||||
try:
|
||||
db.agent_build_update(context, id,
|
||||
{'version': version,
|
||||
'url': url,
|
||||
'md5hash': md5hash})
|
||||
except exception.AgentBuildNotFound as ex:
|
||||
raise webob.exc.HTTPNotFound(explanation=str(ex))
|
||||
|
||||
return {"agent": {'agent_id': id, 'version': version,
|
||||
'url': url, 'md5hash': md5hash}}
|
||||
|
||||
def delete(self, req, id):
|
||||
"""Deletes an existing agent build."""
|
||||
context = req.environ['nova.context']
|
||||
authorize(context)
|
||||
|
||||
try:
|
||||
db.agent_build_destroy(context, id)
|
||||
except exception.AgentBuildNotFound as ex:
|
||||
raise webob.exc.HTTPNotFound(explanation=str(ex))
|
||||
|
||||
def create(self, req, body):
|
||||
"""Creates a new agent build."""
|
||||
context = req.environ['nova.context']
|
||||
authorize(context)
|
||||
|
||||
try:
|
||||
agent = body['agent']
|
||||
hypervisor = agent['hypervisor']
|
||||
os = agent['os']
|
||||
architecture = agent['architecture']
|
||||
version = agent['version']
|
||||
url = agent['url']
|
||||
md5hash = agent['md5hash']
|
||||
except (TypeError, KeyError):
|
||||
raise webob.exc.HTTPUnprocessableEntity()
|
||||
|
||||
try:
|
||||
agent_build_ref = db.agent_build_create(context,
|
||||
{'hypervisor': hypervisor,
|
||||
'os': os,
|
||||
'architecture': architecture,
|
||||
'version': version,
|
||||
'url': url,
|
||||
'md5hash': md5hash})
|
||||
agent['agent_id'] = agent_build_ref.id
|
||||
except Exception as ex:
|
||||
raise webob.exc.HTTPServerError(str(ex))
|
||||
return {'agent': agent}
|
||||
|
||||
|
||||
class Agents(extensions.ExtensionDescriptor):
|
||||
"""Agents support"""
|
||||
|
||||
name = "Agents"
|
||||
alias = "os-agents"
|
||||
namespace = "http://docs.openstack.org/compute/ext/agents/api/v2"
|
||||
updated = "2012-10-28T00:00:00-00:00"
|
||||
|
||||
def get_resources(self):
|
||||
resources = []
|
||||
resource = extensions.ResourceExtension('os-agents',
|
||||
AgentController())
|
||||
resources.append(resource)
|
||||
return resources
|
@ -1372,9 +1372,9 @@ def agent_build_get_by_triple(context, hypervisor, os, architecture):
|
||||
architecture)
|
||||
|
||||
|
||||
def agent_build_get_all(context):
|
||||
def agent_build_get_all(context, hypervisor=None):
|
||||
"""Get all agent builds."""
|
||||
return IMPL.agent_build_get_all(context)
|
||||
return IMPL.agent_build_get_all(context, hypervisor)
|
||||
|
||||
|
||||
def agent_build_destroy(context, agent_update_id):
|
||||
|
@ -3968,8 +3968,13 @@ def agent_build_get_by_triple(context, hypervisor, os, architecture,
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def agent_build_get_all(context):
|
||||
return model_query(context, models.AgentBuild, read_deleted="no").\
|
||||
def agent_build_get_all(context, hypervisor=None):
|
||||
if hypervisor:
|
||||
return model_query(context, models.AgentBuild, read_deleted="no").\
|
||||
filter_by(hypervisor=hypervisor).\
|
||||
all()
|
||||
else:
|
||||
return model_query(context, models.AgentBuild, read_deleted="no").\
|
||||
all()
|
||||
|
||||
|
||||
@ -3977,12 +3982,15 @@ def agent_build_get_all(context):
|
||||
def agent_build_destroy(context, agent_build_id):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
model_query(context, models.AgentBuild, session=session,
|
||||
read_deleted="yes").\
|
||||
agent_build_ref = model_query(context, models.AgentBuild,
|
||||
session=session, read_deleted="yes").\
|
||||
filter_by(id=agent_build_id).\
|
||||
update({'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')})
|
||||
first()
|
||||
if not agent_build_ref:
|
||||
raise exception.AgentBuildNotFound(id=agent_build_id)
|
||||
agent_build_ref.update({'deleted': True,
|
||||
'deleted_at': timeutils.utcnow(),
|
||||
'updated_at': literal_column('updated_at')})
|
||||
|
||||
|
||||
@require_admin_context
|
||||
@ -3993,7 +4001,8 @@ def agent_build_update(context, agent_build_id, values):
|
||||
session=session, read_deleted="yes").\
|
||||
filter_by(id=agent_build_id).\
|
||||
first()
|
||||
|
||||
if not agent_build_ref:
|
||||
raise exception.AgentBuildNotFound(id=agent_build_id)
|
||||
agent_build_ref.update(values)
|
||||
agent_build_ref.save(session=session)
|
||||
|
||||
|
@ -412,6 +412,10 @@ class NotFound(NovaException):
|
||||
code = 404
|
||||
|
||||
|
||||
class AgentBuildNotFound(NotFound):
|
||||
message = _("No agent-build associated with id %(id)s.")
|
||||
|
||||
|
||||
class VolumeNotFound(NotFound):
|
||||
message = _("Volume %(volume_id)s could not be found.")
|
||||
|
||||
|
185
nova/tests/api/openstack/compute/contrib/test_agents.py
Normal file
185
nova/tests/api/openstack/compute/contrib/test_agents.py
Normal file
@ -0,0 +1,185 @@
|
||||
# Copyright 2012 IBM
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from nova.api.openstack.compute.contrib import agents
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova.db.sqlalchemy import models
|
||||
from nova import test
|
||||
|
||||
fake_agents_list = [{'hypervisor': 'kvm', 'os': 'win',
|
||||
'architecture': 'x86',
|
||||
'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545',
|
||||
'id': 1},
|
||||
{'hypervisor': 'kvm', 'os': 'linux',
|
||||
'architecture': 'x86',
|
||||
'version': '16.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx1',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f546',
|
||||
'id': 2},
|
||||
{'hypervisor': 'xen', 'os': 'linux',
|
||||
'architecture': 'x86',
|
||||
'version': '16.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx2',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f547',
|
||||
'id': 3},
|
||||
{'hypervisor': 'xen', 'os': 'win',
|
||||
'architecture': 'power',
|
||||
'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx3',
|
||||
'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 FakeRequest(object):
|
||||
environ = {"nova.context": context.get_admin_context()}
|
||||
GET = {}
|
||||
|
||||
|
||||
class FakeRequestWithHypervisor(object):
|
||||
environ = {"nova.context": context.get_admin_context()}
|
||||
GET = {'hypervisor': 'kvm'}
|
||||
|
||||
|
||||
class AgentsTest(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(AgentsTest, self).setUp()
|
||||
|
||||
self.stubs.Set(db, "agent_build_get_all",
|
||||
fake_agent_build_get_all)
|
||||
self.stubs.Set(db, "agent_build_update",
|
||||
fake_agent_build_update)
|
||||
self.stubs.Set(db, "agent_build_destroy",
|
||||
fake_agent_build_destroy)
|
||||
self.stubs.Set(db, "agent_build_create",
|
||||
fake_agent_build_create)
|
||||
self.context = context.get_admin_context()
|
||||
self.controller = agents.AgentController()
|
||||
|
||||
def tearDown(self):
|
||||
super(AgentsTest, self).tearDown()
|
||||
|
||||
def test_agents_create(self):
|
||||
req = FakeRequest()
|
||||
body = {'agent': {'hypervisor': 'kvm',
|
||||
'os': 'win',
|
||||
'architecture': 'x86',
|
||||
'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545'}}
|
||||
response = {'agent': {'hypervisor': 'kvm',
|
||||
'os': 'win',
|
||||
'architecture': 'x86',
|
||||
'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545',
|
||||
'agent_id': 1}}
|
||||
res_dict = self.controller.create(req, body)
|
||||
self.assertEqual(res_dict, response)
|
||||
|
||||
def test_agents_delete(self):
|
||||
req = FakeRequest()
|
||||
self.controller.delete(req, 1)
|
||||
|
||||
def test_agents_list(self):
|
||||
req = FakeRequest()
|
||||
res_dict = self.controller.index(req)
|
||||
agents_list = [{'hypervisor': 'kvm', 'os': 'win',
|
||||
'architecture': 'x86',
|
||||
'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545',
|
||||
'agent_id': 1},
|
||||
{'hypervisor': 'kvm', 'os': 'linux',
|
||||
'architecture': 'x86',
|
||||
'version': '16.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx1',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f546',
|
||||
'agent_id': 2},
|
||||
{'hypervisor': 'xen', 'os': 'linux',
|
||||
'architecture': 'x86',
|
||||
'version': '16.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx2',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f547',
|
||||
'agent_id': 3},
|
||||
{'hypervisor': 'xen', 'os': 'win',
|
||||
'architecture': 'power',
|
||||
'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx3',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f548',
|
||||
'agent_id': 4},
|
||||
]
|
||||
self.assertEqual(res_dict, {'agents': agents_list})
|
||||
|
||||
def test_agents_list_with_hypervisor(self):
|
||||
req = FakeRequestWithHypervisor()
|
||||
res_dict = self.controller.index(req)
|
||||
response = [{'hypervisor': 'kvm', 'os': 'win',
|
||||
'architecture': 'x86',
|
||||
'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545',
|
||||
'agent_id': 1},
|
||||
{'hypervisor': 'kvm', 'os': 'linux',
|
||||
'architecture': 'x86',
|
||||
'version': '16.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx1',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f546',
|
||||
'agent_id': 2},
|
||||
]
|
||||
self.assertEqual(res_dict, {'agents': response})
|
||||
|
||||
def test_agents_update(self):
|
||||
req = FakeRequest()
|
||||
body = {'para': {'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545'}}
|
||||
response = {'agent': {'agent_id': 1,
|
||||
'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545'}}
|
||||
res_dict = self.controller.update(req, 1, body)
|
||||
self.assertEqual(res_dict, response)
|
@ -158,6 +158,7 @@ class ExtensionControllerTest(ExtensionTestCase):
|
||||
"AdminActions",
|
||||
"Aggregates",
|
||||
"AvailabilityZone",
|
||||
"Agents",
|
||||
"Certificates",
|
||||
"Cloudpipe",
|
||||
"CloudpipeUpdate",
|
||||
|
@ -103,6 +103,7 @@ policy_data = """
|
||||
"compute_extension:admin_actions:resetState": "",
|
||||
"compute_extension:admin_actions:migrate": "",
|
||||
"compute_extension:aggregates": "",
|
||||
"compute_extension:agents": "",
|
||||
"compute_extension:certificates": "",
|
||||
"compute_extension:cloudpipe": "",
|
||||
"compute_extension:cloudpipe_update": "",
|
||||
|
@ -72,6 +72,14 @@
|
||||
"namespace": "http://docs.openstack.org/compute/ext/aggregates/api/v1.1",
|
||||
"updated": "%(timestamp)s"
|
||||
},
|
||||
{
|
||||
"alias": "os-agents",
|
||||
"description": "%(text)s",
|
||||
"links": [],
|
||||
"name": "Agents",
|
||||
"namespace": "http://docs.openstack.org/compute/ext/agents/api/v2",
|
||||
"updated": "%(timestamp)s"
|
||||
},
|
||||
{
|
||||
"alias": "os-availability-zone",
|
||||
"description": "%(text)s",
|
||||
|
@ -30,6 +30,9 @@
|
||||
<extension alias="os-availability-zone" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1" name="AvailabilityZone">
|
||||
<description>%(text)s</description>
|
||||
</extension>
|
||||
<extension alias="os-agents" name="Agents" namespace="http://docs.openstack.org/compute/ext/agents/api/v2" updated="%(timestamp)s">
|
||||
<description>%(text)s</description>
|
||||
</extension>
|
||||
<extension alias="os-certificates" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/certificates/api/v1.1" name="Certificates">
|
||||
<description>%(text)s</description>
|
||||
</extension>
|
||||
|
@ -0,0 +1,10 @@
|
||||
{
|
||||
"agent": {
|
||||
"hypervisor": "%(hypervisor)s",
|
||||
"os": "%(os)s",
|
||||
"architecture": "%(architecture)s",
|
||||
"version": "%(version)s",
|
||||
"md5hash": "%(md5hash)s",
|
||||
"url": "%(url)s"
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<agent>
|
||||
<hypervisor>%(hypervisor)s</hypervisor>
|
||||
<os>%(os)s</os>
|
||||
<architecture>%(architecture)s</architecture>
|
||||
<version>%(version)s</version>
|
||||
<md5hash>%(md5hash)s</md5hash>
|
||||
<url>%(url)s</url>
|
||||
</agent>
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"agent": {
|
||||
"hypervisor": "%(hypervisor)s",
|
||||
"os": "%(os)s",
|
||||
"architecture": "%(architecture)s",
|
||||
"version": "%(version)s",
|
||||
"md5hash": "%(md5hash)s",
|
||||
"url": "%(url)s",
|
||||
"agent_id": "%(agent_id)d"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<agent>
|
||||
<url>%(url)s</url>
|
||||
<hypervisor>%(hypervisor)s</hypervisor>
|
||||
<md5hash>%(md5hash)s</md5hash>
|
||||
<version>%(version)s</version>
|
||||
<architecture>%(architecture)s</architecture>
|
||||
<os>%(os)s</os>
|
||||
<agent_id>%(agent_id)d</agent_id>
|
||||
</agent>
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"para": {
|
||||
"url": "%(url)s",
|
||||
"md5hash": "%(md5hash)s",
|
||||
"version": "%(version)s"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<para>
|
||||
<version>%(version)s</version>
|
||||
<url>%(url)s</url>
|
||||
<md5hash>%(md5hash)s</md5hash>
|
||||
</para>
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"agent": {
|
||||
"agent_id": "%(agent_id)d",
|
||||
"url": "%(url)s",
|
||||
"md5hash": "%(md5hash)s",
|
||||
"version": "%(version)s"
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<agent>
|
||||
<agent_id>%(agent_id)d</agent_id>
|
||||
<version>%(version)s</version>
|
||||
<url>%(url)s</url>
|
||||
<md5hash>%(md5hash)s</md5hash>
|
||||
</agent>
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"agents": [
|
||||
{
|
||||
"hypervisor": "%(hypervisor)s",
|
||||
"os": "%(os)s",
|
||||
"architecture": "%(architecture)s",
|
||||
"version": "%(version)s",
|
||||
"md5hash": "%(md5hash)s",
|
||||
"url": "%(url)s",
|
||||
"agent_id": "%(agent_id)d"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<agents>
|
||||
<agent hypervisor="%(hypervisor)s" os="%(os)s" architecture="%(architecture)s" version="%(version)s" md5hash="%(md5hash)s" url="%(url)s" agent_id="%(agent_id)d"/>
|
||||
</agents>
|
@ -26,6 +26,7 @@ from nova.cloudpipe.pipelib import CloudPipe
|
||||
from nova.compute import api
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova.db.sqlalchemy import models
|
||||
from nova.network.manager import NetworkManager
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import importutils
|
||||
@ -1284,6 +1285,109 @@ class CloudPipeUpdateXmlTest(CloudPipeUpdateJsonTest):
|
||||
ctype = "xml"
|
||||
|
||||
|
||||
class AgentsJsonTest(ApiSampleTestBase):
|
||||
extension_name = "nova.api.openstack.compute.contrib.agents.Agents"
|
||||
|
||||
def _get_flags(self):
|
||||
f = super(AgentsJsonTest, self)._get_flags()
|
||||
f['osapi_compute_extension'] = CONF.osapi_compute_extension[:]
|
||||
return f
|
||||
|
||||
def setUp(self):
|
||||
super(AgentsJsonTest, self).setUp()
|
||||
|
||||
fake_agents_list = [{'url': 'xxxxxxxxxxxx',
|
||||
'hypervisor': 'hypervisor',
|
||||
'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.stubs.Set(db, "agent_build_create",
|
||||
fake_agent_build_create)
|
||||
self.stubs.Set(db, "agent_build_get_all",
|
||||
fake_agent_build_get_all)
|
||||
self.stubs.Set(db, "agent_build_update",
|
||||
fake_agent_build_update)
|
||||
self.stubs.Set(db, "agent_build_destroy",
|
||||
fake_agent_build_destroy)
|
||||
|
||||
def test_agent_create(self):
|
||||
"""Creates a new agent build."""
|
||||
project = {'url': 'xxxxxxxxxxxx',
|
||||
'hypervisor': 'hypervisor',
|
||||
'architecture': 'x86',
|
||||
'os': 'os',
|
||||
'version': '8.0',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545'
|
||||
}
|
||||
response = self._do_post('os-agents', 'agent-post-req',
|
||||
project)
|
||||
self.assertEqual(response.status, 200)
|
||||
project['agent_id'] = 1
|
||||
self._verify_response('agent-post-resp', project, response)
|
||||
return project
|
||||
|
||||
def test_agent_list(self):
|
||||
""" Return a list of all agent builds."""
|
||||
response = self._do_get('os-agents')
|
||||
self.assertEqual(response.status, 200)
|
||||
project = {'url': 'xxxxxxxxxxxx',
|
||||
'hypervisor': 'hypervisor',
|
||||
'architecture': 'x86',
|
||||
'os': 'os',
|
||||
'version': '8.0',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545',
|
||||
'agent_id': 1
|
||||
}
|
||||
return self._verify_response('agents-get-resp', project, response)
|
||||
|
||||
def test_agent_update(self):
|
||||
"""Update an existing agent build."""
|
||||
agent_id = 1
|
||||
subs = {'version': '7.0',
|
||||
'url': 'xxx://xxxx/xxx/xxx',
|
||||
'md5hash': 'add6bb58e139be103324d04d82d8f545'}
|
||||
response = self._do_put('os-agents/%s' % agent_id,
|
||||
'agent-update-put-req', subs)
|
||||
self.assertEqual(response.status, 200)
|
||||
subs['agent_id'] = 1
|
||||
return self._verify_response('agent-update-put-resp', subs, response)
|
||||
|
||||
def test_agent_delete(self):
|
||||
"""Deletes an existing agent build."""
|
||||
agent_id = 1
|
||||
response = self._do_delete('os-agents/%s' % agent_id)
|
||||
self.assertEqual(response.status, 200)
|
||||
|
||||
|
||||
class AgentsXmlTest(AgentsJsonTest):
|
||||
ctype = "xml"
|
||||
|
||||
|
||||
class AggregatesSampleJsonTest(ServersSampleBase):
|
||||
extension_name = "nova.api.openstack.compute.contrib" + \
|
||||
".aggregates.Aggregates"
|
||||
|
Loading…
Reference in New Issue
Block a user