diff options
| author | ivan-zhu <bozhu@linux.vnet.ibm.com> | 2013-06-05 13:52:23 +0800 |
|---|---|---|
| committer | ivan-zhu <bozhu@linux.vnet.ibm.com> | 2013-06-13 13:07:46 +0800 |
| commit | cf472da18aac737ab0616bb5d9b9e104d2714279 (patch) | |
| tree | c1d2dc07507f75585c8a6a215f485167564eda0f | |
| parent | 7a475d3cd606e68090075c1a8944e3aeb7898b87 (diff) | |
| download | nova-cf472da18aac737ab0616bb5d9b9e104d2714279.tar.gz nova-cf472da18aac737ab0616bb5d9b9e104d2714279.tar.xz nova-cf472da18aac737ab0616bb5d9b9e104d2714279.zip | |
port agent API into v3 part1
This changeset only copies the v2 files into the appropriate v3
directories unchanged. The copy as-is will not be loaded by either
the v2 or v3 extension loaders. The second changeset will then
make the changes required for it to work as a v3 extension.
This is being tried in order to make reviewing of extension
porting easier as gerrit will display only what is actually
changed for v3 rather than entirely new files.
Partially implements: bp v3-api-extension-versioning
Change-Id: Ib7c489769d9b07797366be5920cc23ab2074a768
| -rw-r--r-- | nova/api/openstack/compute/plugins/v3/agents.py | 168 | ||||
| -rw-r--r-- | nova/tests/api/openstack/compute/plugins/v3/test_agents.py | 181 |
2 files changed, 349 insertions, 0 deletions
diff --git a/nova/api/openstack/compute/plugins/v3/agents.py b/nova/api/openstack/compute/plugins/v3/agents.py new file mode 100644 index 000000000..02e752dac --- /dev/null +++ b/nova/api/openstack/compute/plugins/v3/agents.py @@ -0,0 +1,168 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# 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 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 + + +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=ex.format_message()) + + 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=ex.format_message()) + + 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 diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_agents.py b/nova/tests/api/openstack/compute/plugins/v3/test_agents.py new file mode 100644 index 000000000..0154ada9e --- /dev/null +++ b/nova/tests/api/openstack/compute/plugins/v3/test_agents.py @@ -0,0 +1,181 @@ +# 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. + + +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 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) |
