diff --git a/doc/api_samples/all_extensions/extensions-get-resp.json b/doc/api_samples/all_extensions/extensions-get-resp.json
index 399d937a7667..cf3d66a761bb 100644
--- a/doc/api_samples/all_extensions/extensions-get-resp.json
+++ b/doc/api_samples/all_extensions/extensions-get-resp.json
@@ -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",
diff --git a/doc/api_samples/all_extensions/extensions-get-resp.xml b/doc/api_samples/all_extensions/extensions-get-resp.xml
index e4d3b8cc3106..44816c09cb1e 100644
--- a/doc/api_samples/all_extensions/extensions-get-resp.xml
+++ b/doc/api_samples/all_extensions/extensions-get-resp.xml
@@ -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>
diff --git a/doc/api_samples/os-agents/agent-post-req.json b/doc/api_samples/os-agents/agent-post-req.json
new file mode 100644
index 000000000000..217993b17f72
--- /dev/null
+++ b/doc/api_samples/os-agents/agent-post-req.json
@@ -0,0 +1,10 @@
+{
+    "agent": {
+        "hypervisor": "hypervisor",
+        "os": "os",
+        "architecture": "x86",
+        "version": "8.0",
+        "md5hash": "add6bb58e139be103324d04d82d8f545",
+        "url": "xxxxxxxxxxxx"
+    }
+}
\ No newline at end of file
diff --git a/doc/api_samples/os-agents/agent-post-req.xml b/doc/api_samples/os-agents/agent-post-req.xml
new file mode 100644
index 000000000000..be93e97ce432
--- /dev/null
+++ b/doc/api_samples/os-agents/agent-post-req.xml
@@ -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>
\ No newline at end of file
diff --git a/doc/api_samples/os-agents/agent-post-resp.json b/doc/api_samples/os-agents/agent-post-resp.json
new file mode 100644
index 000000000000..418d11f5042f
--- /dev/null
+++ b/doc/api_samples/os-agents/agent-post-resp.json
@@ -0,0 +1,11 @@
+{
+    "agent": {
+        "agent_id": "1",
+        "architecture": "x86",
+        "hypervisor": "hypervisor",
+        "md5hash": "add6bb58e139be103324d04d82d8f545",
+        "os": "os",
+        "url": "xxxxxxxxxxxx",
+        "version": "8.0"
+    }
+}
\ No newline at end of file
diff --git a/doc/api_samples/os-agents/agent-post-resp.xml b/doc/api_samples/os-agents/agent-post-resp.xml
new file mode 100644
index 000000000000..79f62b7fb92a
--- /dev/null
+++ b/doc/api_samples/os-agents/agent-post-resp.xml
@@ -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>
\ No newline at end of file
diff --git a/doc/api_samples/os-agents/agent-update-put-req.json b/doc/api_samples/os-agents/agent-update-put-req.json
new file mode 100644
index 000000000000..e4eaf535256f
--- /dev/null
+++ b/doc/api_samples/os-agents/agent-update-put-req.json
@@ -0,0 +1,7 @@
+{
+    "para": {
+        "url": "xxx://xxxx/xxx/xxx",
+        "md5hash": "add6bb58e139be103324d04d82d8f545",
+        "version": "7.0"
+    }
+}
\ No newline at end of file
diff --git a/doc/api_samples/os-agents/agent-update-put-req.xml b/doc/api_samples/os-agents/agent-update-put-req.xml
new file mode 100644
index 000000000000..f759880c1728
--- /dev/null
+++ b/doc/api_samples/os-agents/agent-update-put-req.xml
@@ -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>
\ No newline at end of file
diff --git a/doc/api_samples/os-agents/agent-update-put-resp.json b/doc/api_samples/os-agents/agent-update-put-resp.json
new file mode 100644
index 000000000000..6b67222c8c23
--- /dev/null
+++ b/doc/api_samples/os-agents/agent-update-put-resp.json
@@ -0,0 +1,8 @@
+{
+    "agent": {
+        "agent_id": "1",
+        "md5hash": "add6bb58e139be103324d04d82d8f545",
+        "url": "xxx://xxxx/xxx/xxx",
+        "version": "7.0"
+    }
+}
\ No newline at end of file
diff --git a/doc/api_samples/os-agents/agent-update-put-resp.xml b/doc/api_samples/os-agents/agent-update-put-resp.xml
new file mode 100644
index 000000000000..badf2750ea5d
--- /dev/null
+++ b/doc/api_samples/os-agents/agent-update-put-resp.xml
@@ -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>
\ No newline at end of file
diff --git a/doc/api_samples/os-agents/agents-get-resp.json b/doc/api_samples/os-agents/agents-get-resp.json
new file mode 100644
index 000000000000..36eac4ced7ba
--- /dev/null
+++ b/doc/api_samples/os-agents/agents-get-resp.json
@@ -0,0 +1,13 @@
+{
+    "agents": [
+        {
+            "agent_id": "1",
+            "architecture": "x86",
+            "hypervisor": "hypervisor",
+            "md5hash": "add6bb58e139be103324d04d82d8f545",
+            "os": "os",
+            "url": "xxxxxxxxxxxx",
+            "version": "8.0"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/doc/api_samples/os-agents/agents-get-resp.xml b/doc/api_samples/os-agents/agents-get-resp.xml
new file mode 100644
index 000000000000..4194f62c965a
--- /dev/null
+++ b/doc/api_samples/os-agents/agents-get-resp.xml
@@ -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>
\ No newline at end of file
diff --git a/etc/nova/policy.json b/etc/nova/policy.json
index 778203e756fc..942b74f66522 100644
--- a/etc/nova/policy.json
+++ b/etc/nova/policy.json
@@ -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",
diff --git a/nova/api/openstack/compute/contrib/agents.py b/nova/api/openstack/compute/contrib/agents.py
new file mode 100644
index 000000000000..218f06b52324
--- /dev/null
+++ b/nova/api/openstack/compute/contrib/agents.py
@@ -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
diff --git a/nova/db/api.py b/nova/db/api.py
index ad928f5852e6..cfa6a6487711 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -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):
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index f2d8049858d6..f7c0373e67a3 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -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)
 
diff --git a/nova/exception.py b/nova/exception.py
index 7629db9fe441..7477d9c63819 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -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.")
 
diff --git a/nova/tests/api/openstack/compute/contrib/test_agents.py b/nova/tests/api/openstack/compute/contrib/test_agents.py
new file mode 100644
index 000000000000..60659b3c6aba
--- /dev/null
+++ b/nova/tests/api/openstack/compute/contrib/test_agents.py
@@ -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)
diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py
index eab55f95e0a4..66dac3febe8a 100644
--- a/nova/tests/api/openstack/compute/test_extensions.py
+++ b/nova/tests/api/openstack/compute/test_extensions.py
@@ -158,6 +158,7 @@ class ExtensionControllerTest(ExtensionTestCase):
             "AdminActions",
             "Aggregates",
             "AvailabilityZone",
+            "Agents",
             "Certificates",
             "Cloudpipe",
             "CloudpipeUpdate",
diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py
index b3ae0fa177df..7813cddc0d03 100644
--- a/nova/tests/fake_policy.py
+++ b/nova/tests/fake_policy.py
@@ -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": "",
diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
index 65cbb4889731..0b27896fd6a5 100644
--- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl
@@ -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",
diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
index bdef0266cfea..fec850997e1f 100644
--- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
+++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl
@@ -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>
diff --git a/nova/tests/integrated/api_samples/os-agents/agent-post-req.json.tpl b/nova/tests/integrated/api_samples/os-agents/agent-post-req.json.tpl
new file mode 100644
index 000000000000..6dbd2f17cbb5
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agent-post-req.json.tpl
@@ -0,0 +1,10 @@
+{
+    "agent": {
+        "hypervisor": "%(hypervisor)s",
+        "os": "%(os)s",
+        "architecture": "%(architecture)s",
+        "version": "%(version)s",
+        "md5hash": "%(md5hash)s",
+        "url": "%(url)s"
+    }
+}
diff --git a/nova/tests/integrated/api_samples/os-agents/agent-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-agents/agent-post-req.xml.tpl
new file mode 100644
index 000000000000..5c777749a21d
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agent-post-req.xml.tpl
@@ -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>
diff --git a/nova/tests/integrated/api_samples/os-agents/agent-post-resp.json.tpl b/nova/tests/integrated/api_samples/os-agents/agent-post-resp.json.tpl
new file mode 100644
index 000000000000..abe83564f72b
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agent-post-resp.json.tpl
@@ -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"
+    }
+}
+
diff --git a/nova/tests/integrated/api_samples/os-agents/agent-post-resp.xml.tpl b/nova/tests/integrated/api_samples/os-agents/agent-post-resp.xml.tpl
new file mode 100644
index 000000000000..ecf97b91e958
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agent-post-resp.xml.tpl
@@ -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>
diff --git a/nova/tests/integrated/api_samples/os-agents/agent-update-put-req.json.tpl b/nova/tests/integrated/api_samples/os-agents/agent-update-put-req.json.tpl
new file mode 100644
index 000000000000..d447350e0dfb
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agent-update-put-req.json.tpl
@@ -0,0 +1,7 @@
+{
+    "para": {
+        "url": "%(url)s",
+        "md5hash": "%(md5hash)s",
+        "version": "%(version)s"
+    }
+}
diff --git a/nova/tests/integrated/api_samples/os-agents/agent-update-put-req.xml.tpl b/nova/tests/integrated/api_samples/os-agents/agent-update-put-req.xml.tpl
new file mode 100644
index 000000000000..19751dc80720
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agent-update-put-req.xml.tpl
@@ -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>
diff --git a/nova/tests/integrated/api_samples/os-agents/agent-update-put-resp.json.tpl b/nova/tests/integrated/api_samples/os-agents/agent-update-put-resp.json.tpl
new file mode 100644
index 000000000000..110e52cd3317
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agent-update-put-resp.json.tpl
@@ -0,0 +1,8 @@
+{
+    "agent": {
+        "agent_id": "%(agent_id)d",
+        "url": "%(url)s",
+        "md5hash": "%(md5hash)s",
+        "version": "%(version)s"
+     }
+}
diff --git a/nova/tests/integrated/api_samples/os-agents/agent-update-put-resp.xml.tpl b/nova/tests/integrated/api_samples/os-agents/agent-update-put-resp.xml.tpl
new file mode 100644
index 000000000000..2c9e50572cf7
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agent-update-put-resp.xml.tpl
@@ -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>
diff --git a/nova/tests/integrated/api_samples/os-agents/agents-get-resp.json.tpl b/nova/tests/integrated/api_samples/os-agents/agents-get-resp.json.tpl
new file mode 100644
index 000000000000..dac1f76ffb6f
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agents-get-resp.json.tpl
@@ -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"
+        }
+    ]
+}
diff --git a/nova/tests/integrated/api_samples/os-agents/agents-get-resp.xml.tpl b/nova/tests/integrated/api_samples/os-agents/agents-get-resp.xml.tpl
new file mode 100644
index 000000000000..fbbbdad28850
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-agents/agents-get-resp.xml.tpl
@@ -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>
diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py
index 1fbf16fd3231..4142e058f1f9 100644
--- a/nova/tests/integrated/test_api_samples.py
+++ b/nova/tests/integrated/test_api_samples.py
@@ -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"