Add agent build API support for list/create/delete/modify agent build

This adds an extension that provides REST API for list/create/delete/
modify agent build. The interface is accessed via

GET /v2/{tenant_id}/os-agents
PUT /v2/{tenant_id}/os-agents/id
POST /v2/{tenant_id}/os-agents
DELETE /v2/{tenant_id}/os-agents

And this patch also create tests to get agent build API Samples.
DocImpact
Implements one workitem of blueprint apis-for-nova-manage

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

DocImpact
Change-Id: I5830388a894efce5b13680fc6916e0cd81a16624
This commit is contained in:
ivan-zhu 2012-11-21 15:37:52 +08:00
parent 255692feea
commit 82042ac276
33 changed files with 679 additions and 10 deletions

View File

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

View File

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

View File

@ -0,0 +1,10 @@
{
"agent": {
"hypervisor": "hypervisor",
"os": "os",
"architecture": "x86",
"version": "8.0",
"md5hash": "add6bb58e139be103324d04d82d8f545",
"url": "xxxxxxxxxxxx"
}
}

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

View File

@ -0,0 +1,11 @@
{
"agent": {
"agent_id": "1",
"architecture": "x86",
"hypervisor": "hypervisor",
"md5hash": "add6bb58e139be103324d04d82d8f545",
"os": "os",
"url": "xxxxxxxxxxxx",
"version": "8.0"
}
}

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

View File

@ -0,0 +1,7 @@
{
"para": {
"url": "xxx://xxxx/xxx/xxx",
"md5hash": "add6bb58e139be103324d04d82d8f545",
"version": "7.0"
}
}

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

View File

@ -0,0 +1,8 @@
{
"agent": {
"agent_id": "1",
"md5hash": "add6bb58e139be103324d04d82d8f545",
"url": "xxx://xxxx/xxx/xxx",
"version": "7.0"
}
}

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

View File

@ -0,0 +1,13 @@
{
"agents": [
{
"agent_id": "1",
"architecture": "x86",
"hypervisor": "hypervisor",
"md5hash": "add6bb58e139be103324d04d82d8f545",
"os": "os",
"url": "xxxxxxxxxxxx",
"version": "8.0"
}
]
}

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

View File

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

View 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

View File

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

View File

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

View File

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

View 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)

View File

@ -158,6 +158,7 @@ class ExtensionControllerTest(ExtensionTestCase):
"AdminActions",
"Aggregates",
"AvailabilityZone",
"Agents",
"Certificates",
"Cloudpipe",
"CloudpipeUpdate",

View File

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

View File

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

View File

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

View File

@ -0,0 +1,10 @@
{
"agent": {
"hypervisor": "%(hypervisor)s",
"os": "%(os)s",
"architecture": "%(architecture)s",
"version": "%(version)s",
"md5hash": "%(md5hash)s",
"url": "%(url)s"
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,7 @@
{
"para": {
"url": "%(url)s",
"md5hash": "%(md5hash)s",
"version": "%(version)s"
}
}

View File

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

View File

@ -0,0 +1,8 @@
{
"agent": {
"agent_id": "%(agent_id)d",
"url": "%(url)s",
"md5hash": "%(md5hash)s",
"version": "%(version)s"
}
}

View File

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

View File

@ -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"
}
]
}

View File

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

View File

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