[openstack-nova] sync with patches from essex/stable

Pádraig Brady pbrady at fedoraproject.org
Thu Apr 19 16:55:52 UTC 2012


commit 6f183fd17cbf1aad6410d1d5a8d9c3e5382309b7
Author: Pádraig Brady <P at draigBrady.com>
Date:   Wed Apr 18 18:34:48 2012 +0100

    sync with patches from essex/stable

 ...here-nova-ignores-glance-host-in-imageref.patch |    2 +-
 ...-libvirt-test-from-deleting-instances-dir.patch |    2 +-
 ...vileged-RADOS-users-to-access-rbd-volumes.patch |  169 +++++++++++
 0004-Fixed-bug-962840-added-a-test-case.patch      |   17 +-
 0005-Fix-errors-in-os-networks-extension.patch     |  306 ++++++++++++++++++++
 ...mpute.api.BaseAPI-for-compute-APIs-to-use.patch |  146 ++++++++++
 ...te-image-properties-with-project_id-again.patch |   50 ++++
 ...Use-project_id-in-ec2.cloud._format_image.patch |   28 ++
 ...tomic-manipulation-of-libvirt-disk-images.patch |   12 +-
 ...e-don-t-access-the-net-when-building-docs.patch |    2 +-
 ...0011-fix-useexisting-deprecation-warnings.patch |    2 +-
 openstack-nova.spec                                |   21 +-
 12 files changed, 732 insertions(+), 25 deletions(-)
---
diff --git a/0001-fix-bug-where-nova-ignores-glance-host-in-imageref.patch b/0001-fix-bug-where-nova-ignores-glance-host-in-imageref.patch
index f5ff810..fe2481e 100644
--- a/0001-fix-bug-where-nova-ignores-glance-host-in-imageref.patch
+++ b/0001-fix-bug-where-nova-ignores-glance-host-in-imageref.patch
@@ -1,4 +1,4 @@
-From 59c4ef7d2fc30b42b0c8fcf4a118409772cbf336 Mon Sep 17 00:00:00 2001
+From 155c7b2a8f05e75a9b08764bb4f9404c26036f99 Mon Sep 17 00:00:00 2001
 From: Mike Lundy <mike at pistoncloud.com>
 Date: Wed, 4 Apr 2012 11:38:54 -0700
 Subject: [PATCH] fix bug where nova ignores glance host in imageref
diff --git a/0002-Stop-libvirt-test-from-deleting-instances-dir.patch b/0002-Stop-libvirt-test-from-deleting-instances-dir.patch
index e9eeabf..7889d57 100644
--- a/0002-Stop-libvirt-test-from-deleting-instances-dir.patch
+++ b/0002-Stop-libvirt-test-from-deleting-instances-dir.patch
@@ -1,4 +1,4 @@
-From b11b54b6afa5ff1091e59155971abf8bfb9df6cb Mon Sep 17 00:00:00 2001
+From 4acfab6a7b368d34295afdace678563e1c3fa058 Mon Sep 17 00:00:00 2001
 From: Vishvananda Ishaya <vishvananda at gmail.com>
 Date: Thu, 5 Apr 2012 17:00:25 -0700
 Subject: [PATCH] Stop libvirt test from deleting instances dir
diff --git a/0003-Allow-unprivileged-RADOS-users-to-access-rbd-volumes.patch b/0003-Allow-unprivileged-RADOS-users-to-access-rbd-volumes.patch
new file mode 100644
index 0000000..5fc6c9a
--- /dev/null
+++ b/0003-Allow-unprivileged-RADOS-users-to-access-rbd-volumes.patch
@@ -0,0 +1,169 @@
+From d4e96fe0294bd3d6e84a1d0a7e754662b23f8d13 Mon Sep 17 00:00:00 2001
+From: Josh Durgin <josh.durgin at dreamhost.com>
+Date: Wed, 4 Apr 2012 00:38:59 -0700
+Subject: [PATCH] Allow unprivileged RADOS users to access rbd volumes.
+
+This makes it possible to access rbd volumes with RADOS users with
+restricted privileges. Previously, the admin user was always used.
+
+This requires libvirt 0.9.8 or higher.
+
+This is a backport of commit 01f24caba86c987b0109f743979a4e99e8afed11
+from master.
+
+Fixes bug 975335.
+
+Change-Id: I3fbb2c03e5f63940c3a42f2d4f8d03ee16b30f7e
+---
+ .mailmap                    |    1 +
+ Authors                     |    2 +-
+ nova/tests/test_libvirt.py  |   51 +++++++++++++++++++++++++++++++++++++++++++
+ nova/virt/libvirt/volume.py |   24 ++++++++++++++++----
+ nova/volume/driver.py       |   15 +++++++++++-
+ 5 files changed, 85 insertions(+), 8 deletions(-)
+
+diff --git a/.mailmap b/.mailmap
+index 4f9e4e6..7fd6cb6 100644
+diff --git a/Authors b/Authors
+index e1a947c..a229313 100644
+--- a/Authors
++++ b/Authors
+@@ -98,7 +98,7 @@ Jonathan Bryce <jbryce at jbryce.com>
+ Jordan Rinke <jordan at openstack.org>
+ Joseph Suh <jsuh at isi.edu>
+ Joseph W. Breu <breu at breu.org>
+-Josh Durgin <joshd at hq.newdream.net>
++Josh Durgin <josh.durgin at dreamhost.com>
+ Josh Kearney <josh at jk0.org>
+ Josh Kleinpeter <josh at kleinpeter.org>
+ Joshua Harlow <harlowja at yahoo-inc.com>
+diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
+index 4ce91cb..ad4bb06 100644
+--- a/nova/tests/test_libvirt.py
++++ b/nova/tests/test_libvirt.py
+@@ -240,6 +240,57 @@ class LibvirtVolumeTestCase(test.TestCase):
+         self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
+         rbd_name = '%s/%s' % (FLAGS.rbd_pool, name)
+         self.assertEqual(tree.find('./source').get('name'), rbd_name)
++        self.assertEqual(tree.find('./source/auth'), None)
++        libvirt_driver.disconnect_volume(connection_info, mount_device)
++        connection_info = vol_driver.terminate_connection(vol, self.connr)
++
++    def test_libvirt_rbd_driver_auth_enabled(self):
++        vol_driver = volume_driver.RBDDriver()
++        libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
++        name = 'volume-00000001'
++        vol = {'id': 1, 'name': name}
++        connection_info = vol_driver.initialize_connection(vol, self.connr)
++        uuid = '875a8070-d0b9-4949-8b31-104d125c9a64'
++        user = 'foo'
++        secret_type = 'ceph'
++        connection_info['data']['auth_enabled'] = True
++        connection_info['data']['auth_username'] = user
++        connection_info['data']['secret_type'] = secret_type
++        connection_info['data']['secret_uuid'] = uuid
++        mount_device = "vde"
++        xml = libvirt_driver.connect_volume(connection_info, mount_device)
++        tree = ElementTree.fromstring(xml)
++        self.assertEqual(tree.get('type'), 'network')
++        self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
++        rbd_name = '%s/%s' % (FLAGS.rbd_pool, name)
++        self.assertEqual(tree.find('./source').get('name'), rbd_name)
++        self.assertEqual(tree.find('./auth').get('username'), user)
++        self.assertEqual(tree.find('./auth/secret').get('type'), secret_type)
++        self.assertEqual(tree.find('./auth/secret').get('uuid'), uuid)
++        libvirt_driver.disconnect_volume(connection_info, mount_device)
++        connection_info = vol_driver.terminate_connection(vol, self.connr)
++
++    def test_libvirt_rbd_driver_auth_disabled(self):
++        vol_driver = volume_driver.RBDDriver()
++        libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn)
++        name = 'volume-00000001'
++        vol = {'id': 1, 'name': name}
++        connection_info = vol_driver.initialize_connection(vol, self.connr)
++        uuid = '875a8070-d0b9-4949-8b31-104d125c9a64'
++        user = 'foo'
++        secret_type = 'ceph'
++        connection_info['data']['auth_enabled'] = False
++        connection_info['data']['auth_username'] = user
++        connection_info['data']['secret_type'] = secret_type
++        connection_info['data']['secret_uuid'] = uuid
++        mount_device = "vde"
++        xml = libvirt_driver.connect_volume(connection_info, mount_device)
++        tree = ElementTree.fromstring(xml)
++        self.assertEqual(tree.get('type'), 'network')
++        self.assertEqual(tree.find('./source').get('protocol'), 'rbd')
++        rbd_name = '%s/%s' % (FLAGS.rbd_pool, name)
++        self.assertEqual(tree.find('./source').get('name'), rbd_name)
++        self.assertEqual(tree.find('./auth'), None)
+         libvirt_driver.disconnect_volume(connection_info, mount_device)
+         connection_info = vol_driver.terminate_connection(vol, self.connr)
+ 
+diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py
+index 784867e..10338c2 100644
+--- a/nova/virt/libvirt/volume.py
++++ b/nova/virt/libvirt/volume.py
+@@ -76,11 +76,25 @@ class LibvirtNetVolumeDriver(LibvirtVolumeDriver):
+         driver = self._pick_volume_driver()
+         protocol = connection_info['driver_volume_type']
+         name = connection_info['data']['name']
+-        xml = """<disk type='network'>
+-                     <driver name='%s' type='raw' cache='none'/>
+-                     <source protocol='%s' name='%s'/>
+-                     <target dev='%s' bus='virtio'/>
+-                 </disk>""" % (driver, protocol, name, mount_device)
++        if connection_info['data'].get('auth_enabled'):
++            username = connection_info['data']['auth_username']
++            secret_type = connection_info['data']['secret_type']
++            secret_uuid = connection_info['data']['secret_uuid']
++            xml = """<disk type='network'>
++                         <driver name='%s' type='raw' cache='none'/>
++                         <source protocol='%s' name='%s'/>
++                         <auth username='%s'>
++                             <secret type='%s' uuid='%s'/>
++                         </auth>
++                         <target dev='%s' bus='virtio'/>
++                     </disk>""" % (driver, protocol, name, username,
++                                   secret_type, secret_uuid, mount_device)
++        else:
++            xml = """<disk type='network'>
++                         <driver name='%s' type='raw' cache='none'/>
++                         <source protocol='%s' name='%s'/>
++                         <target dev='%s' bus='virtio'/>
++                     </disk>""" % (driver, protocol, name, mount_device)
+         return xml
+ 
+ 
+diff --git a/nova/volume/driver.py b/nova/volume/driver.py
+index ffdd1f5..8b316be 100644
+--- a/nova/volume/driver.py
++++ b/nova/volume/driver.py
+@@ -56,7 +56,14 @@ volume_opts = [
+                help='The port that the iSCSI daemon is listening on'),
+     cfg.StrOpt('rbd_pool',
+                default='rbd',
+-               help='the rbd pool in which volumes are stored'),
++               help='the RADOS pool in which rbd volumes are stored'),
++    cfg.StrOpt('rbd_user',
++               default=None,
++               help='the RADOS client name for accessing rbd volumes'),
++    cfg.StrOpt('rbd_secret_uuid',
++               default=None,
++               help='the libvirt uuid of the secret for the rbd_user'
++                    'volumes'),
+     ]
+ 
+ FLAGS = flags.FLAGS
+@@ -546,7 +553,11 @@ class RBDDriver(VolumeDriver):
+         return {
+             'driver_volume_type': 'rbd',
+             'data': {
+-                'name': '%s/%s' % (FLAGS.rbd_pool, volume['name'])
++                'name': '%s/%s' % (FLAGS.rbd_pool, volume['name']),
++                'auth_enabled': FLAGS.rbd_secret_uuid is not None,
++                'auth_username': FLAGS.rbd_user,
++                'secret_type': 'ceph',
++                'secret_uuid': FLAGS.rbd_secret_uuid,
+             }
+         }
+ 
diff --git a/0004-Fixed-bug-962840-added-a-test-case.patch b/0004-Fixed-bug-962840-added-a-test-case.patch
index c5e2690..6d3cf1b 100644
--- a/0004-Fixed-bug-962840-added-a-test-case.patch
+++ b/0004-Fixed-bug-962840-added-a-test-case.patch
@@ -1,4 +1,4 @@
-From 9653d687f4a388273964c610a6c8cbb34052f7c7 Mon Sep 17 00:00:00 2001
+From 3b14c746910abf95e8136e409085873fd6ac970d Mon Sep 17 00:00:00 2001
 From: Yun Mao <yunmao at gmail.com>
 Date: Tue, 3 Apr 2012 11:17:50 -0400
 Subject: [PATCH] Fixed bug 962840, added a test case.
@@ -8,20 +8,16 @@ or __repr__() calls. See bug #962840 for details.
 We perform a monkey patch to replace those two instance methods.
 
 Change-Id: Ia51bbd3e71cad7df45da5b3b27eef70f9d9e9002
-
-Conflicts:
-
-	nova/tests/test_libvirt.py
 ---
- nova/tests/test_libvirt.py      |   19 +++++++++++++++++++
+ nova/tests/test_libvirt.py      |   18 ++++++++++++++++++
  nova/virt/libvirt/connection.py |   18 ++++++++++++++++++
- 2 files changed, 37 insertions(+), 0 deletions(-)
+ 2 files changed, 36 insertions(+), 0 deletions(-)
 
 diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
-index 4ce91cb..5a476a4 100644
+index ad4bb06..cdc9121 100644
 --- a/nova/tests/test_libvirt.py
 +++ b/nova/tests/test_libvirt.py
-@@ -2369,3 +2369,22 @@ class LibvirtConnectionTestCase(test.TestCase):
+@@ -2420,3 +2420,21 @@ class LibvirtConnectionTestCase(test.TestCase):
  
              ref = self.libvirtconnection.finish_revert_migration(ins_ref, None)
              self.assertTrue(isinstance(ref, eventlet.event.Event))
@@ -43,9 +39,8 @@ index 4ce91cb..5a476a4 100644
 +        import nova.virt.libvirt.connection
 +        connection = nova.virt.libvirt.connection.get_connection('')
 +        utils.to_primitive(connection._conn, convert_instances=True)
-+>>>>>>> bc173ec... Fixed bug 962840, added a test case.
 diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
-index 0c78453..2ade19a 100644
+index 5379eac..888be92 100644
 --- a/nova/virt/libvirt/connection.py
 +++ b/nova/virt/libvirt/connection.py
 @@ -170,6 +170,24 @@ flags.DECLARE('live_migration_retry_count', 'nova.compute.manager')
diff --git a/0005-Fix-errors-in-os-networks-extension.patch b/0005-Fix-errors-in-os-networks-extension.patch
new file mode 100644
index 0000000..cfd06eb
--- /dev/null
+++ b/0005-Fix-errors-in-os-networks-extension.patch
@@ -0,0 +1,306 @@
+From 84db03cf67e8708cfaeac29508d805115c582cc6 Mon Sep 17 00:00:00 2001
+From: Vishvananda Ishaya <vishvananda at gmail.com>
+Date: Mon, 9 Apr 2012 22:11:10 -0700
+Subject: [PATCH] Fix errors in os-networks extension
+
+ * Makes sure the uuid is returned as id if it exists
+ * Simplifies db get for manager.get_networks
+ * Removes direct db access from manager which was breaking test
+ * Updates tests to verify the new logic
+ * Makes sure Remote NotFounds are turned into 404s
+   (The RemoteError blocks can be removed once
+    https://review.openstack.org/5749 lands)
+ * Fixes bug 977712
+ * Fixes bug 977723
+
+Change-Id: I6aa815960782c7ae5165aeebd83bdaaa62c19b04
+---
+ nova/api/openstack/compute/contrib/networks.py     |   21 +++++++++++-
+ nova/network/manager.py                            |   17 +++------
+ .../api/openstack/compute/contrib/test_networks.py |   34 +++++++++++++-------
+ nova/tests/fake_network.py                         |    3 ++
+ nova/tests/network/test_manager.py                 |   28 ++++++++--------
+ 5 files changed, 65 insertions(+), 38 deletions(-)
+
+diff --git a/nova/api/openstack/compute/contrib/networks.py b/nova/api/openstack/compute/contrib/networks.py
+index 32a4af5..ac99c8c 100644
+--- a/nova/api/openstack/compute/contrib/networks.py
++++ b/nova/api/openstack/compute/contrib/networks.py
+@@ -24,6 +24,7 @@ from nova import exception
+ from nova import flags
+ from nova import log as logging
+ import nova.network.api
++from nova.rpc import common
+ 
+ 
+ FLAGS = flags.FLAGS
+@@ -40,7 +41,10 @@ def network_dict(network):
+                   'netmask', 'injected', 'cidr', 'vpn_public_address',
+                   'multi_host', 'dns1', 'host', 'gateway_v6', 'netmask_v6',
+                   'created_at')
+-        return dict((field, network[field]) for field in fields)
++        result = dict((field, network[field]) for field in fields)
++        if 'uuid' in network:
++            result['id'] = network['uuid']
++        return result
+     else:
+         return {}
+ 
+@@ -72,6 +76,11 @@ class NetworkController(object):
+             self.network_api.disassociate(context, network_id)
+         except exception.NetworkNotFound:
+             raise exc.HTTPNotFound(_("Network not found"))
++        except common.RemoteError as ex:
++            if ex.exc_type in ["NetworkNotFound", "NetworkNotFoundForUUID"]:
++                raise exc.HTTPNotFound(_("Network not found"))
++            else:
++                raise
+         return exc.HTTPAccepted()
+ 
+     def index(self, req):
+@@ -89,6 +98,11 @@ class NetworkController(object):
+             network = self.network_api.get(context, id)
+         except exception.NetworkNotFound:
+             raise exc.HTTPNotFound(_("Network not found"))
++        except common.RemoteError as ex:
++            if ex.exc_type in ["NetworkNotFound", "NetworkNotFoundForUUID"]:
++                raise exc.HTTPNotFound(_("Network not found"))
++            else:
++                raise
+         return {'network': network_dict(network)}
+ 
+     def delete(self, req, id):
+@@ -99,6 +113,11 @@ class NetworkController(object):
+             self.network_api.delete(context, id)
+         except exception.NetworkNotFound:
+             raise exc.HTTPNotFound(_("Network not found"))
++        except common.RemoteError as ex:
++            if ex.exc_type in ["NetworkNotFound", "NetworkNotFoundForUUID"]:
++                raise exc.HTTPNotFound(_("Network not found"))
++            else:
++                raise
+         return exc.HTTPAccepted()
+ 
+     def create(self, req, id, body=None):
+diff --git a/nova/network/manager.py b/nova/network/manager.py
+index 8b89e26..9ecc6e2 100644
+--- a/nova/network/manager.py
++++ b/nova/network/manager.py
+@@ -55,7 +55,6 @@ import netaddr
+ 
+ from nova.compute import api as compute_api
+ from nova import context
+-from nova import db
+ from nova import exception
+ from nova import flags
+ from nova import ipv6
+@@ -1414,15 +1413,16 @@ class NetworkManager(manager.SchedulerDependentManager):
+             require_disassociated=True):
+ 
+         # Prefer uuid but we'll also take cidr for backwards compatibility
++        elevated = context.elevated()
+         if uuid:
+-            network = db.network_get_by_uuid(context.elevated(), uuid)
++            network = self.db.network_get_by_uuid(elevated, uuid)
+         elif fixed_range:
+-            network = db.network_get_by_cidr(context.elevated(), fixed_range)
++            network = self.db.network_get_by_cidr(elevated, fixed_range)
+ 
+         if require_disassociated and network.project_id is not None:
+             raise ValueError(_('Network must be disassociated from project %s'
+                                ' before delete') % network.project_id)
+-        db.network_delete_safe(context, network.id)
++        self.db.network_delete_safe(context, network.id)
+ 
+     @property
+     def _bottom_reserved_ips(self):  # pylint: disable=R0201
+@@ -1559,12 +1559,7 @@ class NetworkManager(manager.SchedulerDependentManager):
+ 
+     @wrap_check_policy
+     def get_network(self, context, network_uuid):
+-        networks = self._get_networks_by_uuids(context, [network_uuid])
+-        try:
+-            network = networks[0]
+-        except (IndexError, TypeError):
+-            raise exception.NetworkNotFound(network_id=network_uuid)
+-
++        network = self.db.network_get_by_uuid(context.elevated(), network_uuid)
+         return dict(network.iteritems())
+ 
+     @wrap_check_policy
+@@ -1848,7 +1843,7 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
+             net = {}
+             address = FLAGS.vpn_ip
+             net['vpn_public_address'] = address
+-            network = db.network_update(context, network['id'], net)
++            network = self.db.network_update(context, network['id'], net)
+         else:
+             address = network['vpn_public_address']
+         network['dhcp_server'] = self._get_dhcp_ip(context, network)
+diff --git a/nova/tests/api/openstack/compute/contrib/test_networks.py b/nova/tests/api/openstack/compute/contrib/test_networks.py
+index 78c8ad3..c0580c6 100644
+--- a/nova/tests/api/openstack/compute/contrib/test_networks.py
++++ b/nova/tests/api/openstack/compute/contrib/test_networks.py
+@@ -20,6 +20,7 @@ import webob
+ 
+ from nova.api.openstack.compute.contrib import networks
+ from nova import exception
++from nova.rpc import common
+ from nova import test
+ from nova.tests.api.openstack import fakes
+ 
+@@ -28,7 +29,8 @@ FAKE_NETWORKS = [
+     {
+         'bridge': 'br100', 'vpn_public_port': 1000,
+         'dhcp_start': '10.0.0.3', 'bridge_interface': 'eth0',
+-        'updated_at': '2011-08-16 09:26:13.048257', 'id': 1,
++        'updated_at': '2011-08-16 09:26:13.048257',
++        'id': 1, 'uuid': '20c8acc0-f747-4d71-a389-46d078ebf047',
+         'cidr_v6': None, 'deleted_at': None,
+         'gateway': '10.0.0.1', 'label': 'mynet_0',
+         'project_id': '1234',
+@@ -68,21 +70,21 @@ class FakeNetworkAPI(object):
+             if network['id'] == network_id:
+                 del self.networks[0]
+                 return True
+-        raise exception.NetworkNotFound()
++        raise exception.NetworkNotFoundForUUID()
+ 
+     #NOTE(bcwaldon): this does nothing other than check for existance
+     def disassociate(self, context, network_id):
+         for i, network in enumerate(self.networks):
+-            if network['id'] == network_id:
++            if network.get('uuid') == network_id:
+                 return True
+-        raise exception.NetworkNotFound()
++        raise common.RemoteError(type(exception.NetworkNotFound()).__name__)
+ 
+     def get_all(self, context):
+         return self.networks
+ 
+     def get(self, context, network_id):
+         for network in self.networks:
+-            if network['id'] == network_id:
++            if network.get('uuid') == network_id:
+                 return network
+         raise exception.NetworkNotFound()
+ 
+@@ -99,11 +101,15 @@ class NetworksTest(test.TestCase):
+     def test_network_list_all(self):
+         req = fakes.HTTPRequest.blank('/v2/1234/os-networks')
+         res_dict = self.controller.index(req)
+-        self.assertEquals(res_dict, {'networks': FAKE_NETWORKS})
++        expected = copy.deepcopy(FAKE_NETWORKS)
++        expected[0]['id'] = expected[0]['uuid']
++        del expected[0]['uuid']
++        self.assertEquals(res_dict, {'networks': expected})
+ 
+     def test_network_disassociate(self):
+-        req = fakes.HTTPRequest.blank('/v2/1234/os-networks/1/action')
+-        res = self.controller.action(req, 1, {'disassociate': None})
++        uuid = FAKE_NETWORKS[0]['uuid']
++        req = fakes.HTTPRequest.blank('/v2/1234/os-networks/%s/action' % uuid)
++        res = self.controller.action(req, uuid, {'disassociate': None})
+         self.assertEqual(res.status_int, 202)
+ 
+     def test_network_disassociate_not_found(self):
+@@ -113,9 +119,12 @@ class NetworksTest(test.TestCase):
+                           req, 100, {'disassociate': None})
+ 
+     def test_network_get(self):
+-        req = fakes.HTTPRequest.blank('/v2/1234/os-networks/1')
+-        res_dict = self.controller.show(req, 1)
+-        expected = {'network': FAKE_NETWORKS[0]}
++        uuid = FAKE_NETWORKS[0]['uuid']
++        req = fakes.HTTPRequest.blank('/v2/1234/os-networks/%s' % uuid)
++        res_dict = self.controller.show(req, uuid)
++        expected = {'network': copy.deepcopy(FAKE_NETWORKS[0])}
++        expected['network']['id'] = expected['network']['uuid']
++        del expected['network']['uuid']
+         self.assertEqual(res_dict, expected)
+ 
+     def test_network_get_not_found(self):
+@@ -124,7 +133,8 @@ class NetworksTest(test.TestCase):
+                           self.controller.show, req, 100)
+ 
+     def test_network_delete(self):
+-        req = fakes.HTTPRequest.blank('/v2/1234/os-networks/1')
++        uuid = FAKE_NETWORKS[0]['uuid']
++        req = fakes.HTTPRequest.blank('/v2/1234/os-networks/%s' % uuid)
+         res = self.controller.delete(req, 1)
+         self.assertEqual(res.status_int, 202)
+ 
+diff --git a/nova/tests/fake_network.py b/nova/tests/fake_network.py
+index 9d0a5b9..03ad472 100644
+--- a/nova/tests/fake_network.py
++++ b/nova/tests/fake_network.py
+@@ -120,6 +120,9 @@ class FakeNetworkManager(network_manager.NetworkManager):
+         def network_get(self, context, network_id):
+             return {'cidr_v6': '2001:db8:69:%x::/64' % network_id}
+ 
++        def network_get_by_uuid(self, context, network_uuid):
++            raise exception.NetworkNotFoundForUUID()
++
+         def network_get_all(self, context):
+             raise exception.NoNetworksFound()
+ 
+diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py
+index 50d49b1..3b33296 100644
+--- a/nova/tests/network/test_manager.py
++++ b/nova/tests/network/test_manager.py
+@@ -1266,10 +1266,9 @@ class CommonNetworkTestCase(test.TestCase):
+     def test_get_network(self):
+         manager = fake_network.FakeNetworkManager()
+         fake_context = context.RequestContext('user', 'project')
+-        self.mox.StubOutWithMock(manager.db, 'network_get_all_by_uuids')
+-        manager.db.network_get_all_by_uuids(
+-                mox.IgnoreArg(),
+-                mox.IgnoreArg()).AndReturn(networks)
++        self.mox.StubOutWithMock(manager.db, 'network_get_by_uuid')
++        manager.db.network_get_by_uuid(mox.IgnoreArg(),
++                                       mox.IgnoreArg()).AndReturn(networks[0])
+         self.mox.ReplayAll()
+         uuid = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
+         network = manager.get_network(fake_context, uuid)
+@@ -1278,9 +1277,10 @@ class CommonNetworkTestCase(test.TestCase):
+     def test_get_network_not_found(self):
+         manager = fake_network.FakeNetworkManager()
+         fake_context = context.RequestContext('user', 'project')
+-        self.mox.StubOutWithMock(manager.db, 'network_get_all_by_uuids')
+-        manager.db.network_get_all_by_uuids(mox.IgnoreArg(),
+-                                            mox.IgnoreArg()).AndReturn([])
++        self.mox.StubOutWithMock(manager.db, 'network_get_by_uuid')
++        manager.db.network_get_by_uuid(
++                mox.IgnoreArg(),
++                mox.IgnoreArg()).AndRaise(exception.NetworkNotFoundForUUID)
+         self.mox.ReplayAll()
+         uuid = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
+         self.assertRaises(exception.NetworkNotFound,
+@@ -1302,10 +1302,9 @@ class CommonNetworkTestCase(test.TestCase):
+     def test_disassociate_network(self):
+         manager = fake_network.FakeNetworkManager()
+         fake_context = context.RequestContext('user', 'project')
+-        self.mox.StubOutWithMock(manager.db, 'network_get_all_by_uuids')
+-        manager.db.network_get_all_by_uuids(
+-                mox.IgnoreArg(),
+-                mox.IgnoreArg()).AndReturn(networks)
++        self.mox.StubOutWithMock(manager.db, 'network_get_by_uuid')
++        manager.db.network_get_by_uuid(mox.IgnoreArg(),
++                                       mox.IgnoreArg()).AndReturn(networks[0])
+         self.mox.ReplayAll()
+         uuid = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
+         manager.disassociate_network(fake_context, uuid)
+@@ -1313,9 +1312,10 @@ class CommonNetworkTestCase(test.TestCase):
+     def test_disassociate_network_not_found(self):
+         manager = fake_network.FakeNetworkManager()
+         fake_context = context.RequestContext('user', 'project')
+-        self.mox.StubOutWithMock(manager.db, 'network_get_all_by_uuids')
+-        manager.db.network_get_all_by_uuids(mox.IgnoreArg(),
+-                                            mox.IgnoreArg()).AndReturn([])
++        self.mox.StubOutWithMock(manager.db, 'network_get_by_uuid')
++        manager.db.network_get_by_uuid(
++                mox.IgnoreArg(),
++                mox.IgnoreArg()).AndRaise(exception.NetworkNotFoundForUUID)
+         self.mox.ReplayAll()
+         uuid = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
+         self.assertRaises(exception.NetworkNotFound,
diff --git a/0006-Create-compute.api.BaseAPI-for-compute-APIs-to-use.patch b/0006-Create-compute.api.BaseAPI-for-compute-APIs-to-use.patch
new file mode 100644
index 0000000..220241d
--- /dev/null
+++ b/0006-Create-compute.api.BaseAPI-for-compute-APIs-to-use.patch
@@ -0,0 +1,146 @@
+From d0b32e693eadf6fdc9e885dbe09656a69d5e3662 Mon Sep 17 00:00:00 2001
+From: Chris Behrens <cbehrens at codestud.com>
+Date: Mon, 9 Apr 2012 19:23:03 +0000
+Subject: [PATCH] Create compute.api.BaseAPI for compute APIs to use
+
+Fixes bug 960226 where compute.api.HostAPI called non-existent methods
+
+Regression was introduced here:
+https://review.openstack.org/#change,5252
+
+Added tests for HostAPI
+
+Change-Id: Id17927bc608ff638ea9b0b5509f0f0bb14503f85
+---
+ nova/compute/api.py        |   36 ++++++++++++++++++--------------
+ nova/tests/test_compute.py |   48 +++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 67 insertions(+), 17 deletions(-)
+
+diff --git a/nova/compute/api.py b/nova/compute/api.py
+index 6edfefd..92adea1 100644
+--- a/nova/compute/api.py
++++ b/nova/compute/api.py
+@@ -106,17 +106,10 @@ def check_policy(context, action, target):
+     nova.policy.enforce(context, _action, target)
+ 
+ 
+-class API(base.Base):
+-    """API for interacting with the compute manager."""
+-
+-    def __init__(self, image_service=None, network_api=None, volume_api=None,
+-                 **kwargs):
+-        self.image_service = (image_service or
+-                              nova.image.get_default_image_service())
+-
+-        self.network_api = network_api or network.API()
+-        self.volume_api = volume_api or volume.API()
+-        super(API, self).__init__(**kwargs)
++class BaseAPI(base.Base):
++    """Base API class."""
++    def __init__(self, **kwargs):
++        super(BaseAPI, self).__init__(**kwargs)
+ 
+     def _cast_or_call_compute_message(self, rpc_method, compute_method,
+             context, instance=None, host=None, params=None):
+@@ -157,10 +150,24 @@ class API(base.Base):
+         """Generic handler for RPC calls to compute."""
+         return self._cast_or_call_compute_message(rpc.call, *args, **kwargs)
+ 
+-    def _cast_scheduler_message(self, context, args):
++    @staticmethod
++    def _cast_scheduler_message(context, args):
+         """Generic handler for RPC calls to the scheduler."""
+         rpc.cast(context, FLAGS.scheduler_topic, args)
+ 
++
++class API(BaseAPI):
++    """API for interacting with the compute manager."""
++
++    def __init__(self, image_service=None, network_api=None, volume_api=None,
++                 **kwargs):
++        self.image_service = (image_service or
++                              nova.image.get_default_image_service())
++
++        self.network_api = network_api or network.API()
++        self.volume_api = volume_api or volume.API()
++        super(API, self).__init__(**kwargs)
++
+     def _check_injected_file_quota(self, context, injected_files):
+         """Enforce quota limits on injected files.
+ 
+@@ -1677,11 +1684,8 @@ class API(base.Base):
+         return self.db.instance_fault_get_by_instance_uuids(context, uuids)
+ 
+ 
+-class HostAPI(base.Base):
++class HostAPI(BaseAPI):
+     """Sub-set of the Compute Manager API for managing host operations."""
+-    def __init__(self, **kwargs):
+-        super(HostAPI, self).__init__(**kwargs)
+-
+     def set_host_enabled(self, context, host, enabled):
+         """Sets the specified host's ability to accept new instances."""
+         # NOTE(comstud): No instance_uuid argument to this compute manager
+diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
+index 305282c..2e7e7de 100644
+--- a/nova/tests/test_compute.py
++++ b/nova/tests/test_compute.py
+@@ -24,7 +24,6 @@ import sys
+ import time
+ 
+ import mox
+-import webob.exc
+ 
+ import nova
+ import nova.common.policy
+@@ -3643,3 +3642,50 @@ class ComputePolicyTestCase(BaseTestCase):
+         self.assertRaises(exception.PolicyNotAuthorized,
+                           self.compute_api.get_instance_faults,
+                           self.context, instances)
++
++
++class ComputeHostAPITestCase(BaseTestCase):
++    def setUp(self):
++        super(ComputeHostAPITestCase, self).setUp()
++        self.host_api = compute_api.HostAPI()
++
++    def _rpc_call_stub(self, call_info):
++        def fake_rpc_call(context, topic, msg):
++            call_info['context'] = context
++            call_info['topic'] = topic
++            call_info['msg'] = msg
++        self.stubs.Set(rpc, 'call', fake_rpc_call)
++
++    def test_set_host_enabled(self):
++        ctxt = context.RequestContext('fake', 'fake')
++        call_info = {}
++        self._rpc_call_stub(call_info)
++
++        self.host_api.set_host_enabled(ctxt, 'fake_host', 'fake_enabled')
++        self.assertEqual(call_info['context'], ctxt)
++        self.assertEqual(call_info['topic'], 'compute.fake_host')
++        self.assertEqual(call_info['msg'],
++                {'method': 'set_host_enabled',
++                 'args': {'enabled': 'fake_enabled'}})
++
++    def test_host_power_action(self):
++        ctxt = context.RequestContext('fake', 'fake')
++        call_info = {}
++        self._rpc_call_stub(call_info)
++        self.host_api.host_power_action(ctxt, 'fake_host', 'fake_action')
++        self.assertEqual(call_info['context'], ctxt)
++        self.assertEqual(call_info['topic'], 'compute.fake_host')
++        self.assertEqual(call_info['msg'],
++                {'method': 'host_power_action',
++                 'args': {'action': 'fake_action'}})
++
++    def test_set_host_maintenance(self):
++        ctxt = context.RequestContext('fake', 'fake')
++        call_info = {}
++        self._rpc_call_stub(call_info)
++        self.host_api.set_host_maintenance(ctxt, 'fake_host', 'fake_mode')
++        self.assertEqual(call_info['context'], ctxt)
++        self.assertEqual(call_info['topic'], 'compute.fake_host')
++        self.assertEqual(call_info['msg'],
++                {'method': 'host_maintenance_mode',
++                 'args': {'host': 'fake_host', 'mode': 'fake_mode'}})
diff --git a/0007-Populate-image-properties-with-project_id-again.patch b/0007-Populate-image-properties-with-project_id-again.patch
new file mode 100644
index 0000000..3b96d35
--- /dev/null
+++ b/0007-Populate-image-properties-with-project_id-again.patch
@@ -0,0 +1,50 @@
+From 6e988ed75c5ba507d79818bc24a1bd2f8250ce2b Mon Sep 17 00:00:00 2001
+From: Adam Gandelman <adamg at canonical.com>
+Date: Tue, 10 Apr 2012 16:44:27 -0700
+Subject: [PATCH] Populate image properties with project_id again
+
+This allows ec2 image publishing to function on Essex for users
+who are still using deprecated auth.  This isn't targetted toward
+master and is proposed to stable/essex for the sake of aiding
+users transition to Keystone during upgrades from diablo +
+deprecated_auth.
+
+Fixes bug 977765
+
+Change-Id: I809b669e88fe25234569d0c744d14aff6bbd4713
+---
+ nova/api/ec2/cloud.py |    6 +++++-
+ nova/image/s3.py      |    3 +++
+ 2 files changed, 8 insertions(+), 1 deletions(-)
+
+diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
+index 8e187d6..88590db 100644
+--- a/nova/api/ec2/cloud.py
++++ b/nova/api/ec2/cloud.py
+@@ -1398,7 +1398,11 @@ class CloudController(object):
+         ramdisk_id = image['properties'].get('ramdisk_id')
+         if ramdisk_id:
+             i['ramdiskId'] = ec2utils.image_ec2_id(ramdisk_id, 'ari')
+-        i['imageOwnerId'] = image.get('owner')
++
++        if FLAGS.auth_strategy == 'deprecated':
++            i['imageOwnerId'] = image['properties'].get('owner_id')
++        else:
++            i['imageOwnerId'] = image.get('owner')
+ 
+         img_loc = image['properties'].get('image_location')
+         if img_loc:
+diff --git a/nova/image/s3.py b/nova/image/s3.py
+index fdf9555..36cf818 100644
+--- a/nova/image/s3.py
++++ b/nova/image/s3.py
+@@ -232,6 +232,9 @@ class S3ImageService(object):
+         properties = metadata['properties']
+         properties['architecture'] = arch
+ 
++        if FLAGS.auth_strategy == 'deprecated':
++            properties['project_id'] = context.project_id
++
+         def _translate_dependent_image_id(image_key, image_id):
+             image_uuid = ec2utils.ec2_id_to_glance_id(context, image_id)
+             properties[image_key] = image_uuid
diff --git a/0008-Use-project_id-in-ec2.cloud._format_image.patch b/0008-Use-project_id-in-ec2.cloud._format_image.patch
new file mode 100644
index 0000000..a4846da
--- /dev/null
+++ b/0008-Use-project_id-in-ec2.cloud._format_image.patch
@@ -0,0 +1,28 @@
+From b1d11b8d517733c052c524319c9a153fbb495153 Mon Sep 17 00:00:00 2001
+From: Adam Gandelman <adamg at canonical.com>
+Date: Wed, 11 Apr 2012 15:12:51 -0700
+Subject: [PATCH] Use project_id in ec2.cloud._format_image()
+
+The previous change (2f8250ce2b) reverted an earlier change verbatim
+that broke image publication using deprecated auth.  As it turns out,
+image metadata formatting in EC2 should use project_id with
+deprecated_auth, not owner_id as it once was in the past.
+
+Change-Id: I0e3bad0149577e71a97916398f665566b529a696
+---
+ nova/api/ec2/cloud.py |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
+index 88590db..16df626 100644
+--- a/nova/api/ec2/cloud.py
++++ b/nova/api/ec2/cloud.py
+@@ -1400,7 +1400,7 @@ class CloudController(object):
+             i['ramdiskId'] = ec2utils.image_ec2_id(ramdisk_id, 'ari')
+ 
+         if FLAGS.auth_strategy == 'deprecated':
+-            i['imageOwnerId'] = image['properties'].get('owner_id')
++            i['imageOwnerId'] = image['properties'].get('project_id')
+         else:
+             i['imageOwnerId'] = image.get('owner')
+ 
diff --git a/0003-ensure-atomic-manipulation-of-libvirt-disk-images.patch b/0009-ensure-atomic-manipulation-of-libvirt-disk-images.patch
similarity index 95%
rename from 0003-ensure-atomic-manipulation-of-libvirt-disk-images.patch
rename to 0009-ensure-atomic-manipulation-of-libvirt-disk-images.patch
index 2eae6fa..ed791d7 100644
--- a/0003-ensure-atomic-manipulation-of-libvirt-disk-images.patch
+++ b/0009-ensure-atomic-manipulation-of-libvirt-disk-images.patch
@@ -1,4 +1,4 @@
-From 3e4b550eca091904f73f3dd4602f40e7fe3ae888 Mon Sep 17 00:00:00 2001
+From 5f41789556eb850732ebaa2fe3f175209ce2c198 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
 Date: Fri, 16 Mar 2012 03:43:49 +0000
 Subject: [PATCH] ensure atomic manipulation of libvirt disk images
@@ -169,10 +169,10 @@ index 1e0ae0a..626f3ff 100644
  
      return metadata
 diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
-index 5379eac..0c78453 100644
+index 888be92..2ade19a 100644
 --- a/nova/virt/libvirt/connection.py
 +++ b/nova/virt/libvirt/connection.py
-@@ -1076,7 +1076,8 @@ class LibvirtConnection(driver.ComputeDriver):
+@@ -1094,7 +1094,8 @@ class LibvirtConnection(driver.ComputeDriver):
              @utils.synchronized(fname)
              def call_if_not_exists(base, fn, *args, **kwargs):
                  if not os.path.exists(base):
@@ -182,7 +182,7 @@ index 5379eac..0c78453 100644
  
              if cow or not generating:
                  call_if_not_exists(base, fn, *args, **kwargs)
-@@ -1092,8 +1093,9 @@ class LibvirtConnection(driver.ComputeDriver):
+@@ -1110,8 +1111,9 @@ class LibvirtConnection(driver.ComputeDriver):
                          size_gb = size / (1024 * 1024 * 1024)
                          cow_base += "_%d" % size_gb
                          if not os.path.exists(cow_base):
@@ -194,7 +194,7 @@ index 5379eac..0c78453 100644
                      libvirt_utils.create_cow_image(cow_base, target)
                  elif not generating:
                      libvirt_utils.copy_image(base, target)
-@@ -1103,7 +1105,8 @@ class LibvirtConnection(driver.ComputeDriver):
+@@ -1121,7 +1123,8 @@ class LibvirtConnection(driver.ComputeDriver):
                      if size:
                          disk.extend(target, size)
  
@@ -204,7 +204,7 @@ index 5379eac..0c78453 100644
  
      @staticmethod
      def _create_local(target, local_size, unit='G',
-@@ -1273,8 +1276,9 @@ class LibvirtConnection(driver.ComputeDriver):
+@@ -1291,8 +1294,9 @@ class LibvirtConnection(driver.ComputeDriver):
                                project_id=instance['project_id'],)
          elif config_drive:
              label = 'config'
diff --git a/0005-Ensure-we-don-t-access-the-net-when-building-docs.patch b/0010-Ensure-we-don-t-access-the-net-when-building-docs.patch
similarity index 94%
rename from 0005-Ensure-we-don-t-access-the-net-when-building-docs.patch
rename to 0010-Ensure-we-don-t-access-the-net-when-building-docs.patch
index 112b86f..df40317 100644
--- a/0005-Ensure-we-don-t-access-the-net-when-building-docs.patch
+++ b/0010-Ensure-we-don-t-access-the-net-when-building-docs.patch
@@ -1,4 +1,4 @@
-From 013d88f18b4482cff75779da4fae0bf571db78d1 Mon Sep 17 00:00:00 2001
+From 3057a7b6d56a6ad26d70af516fd28ee55938eb64 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
 Date: Fri, 6 Jan 2012 12:16:34 +0000
 Subject: [PATCH] Ensure we don't access the net when building docs
diff --git a/0006-fix-useexisting-deprecation-warnings.patch b/0011-fix-useexisting-deprecation-warnings.patch
similarity index 97%
rename from 0006-fix-useexisting-deprecation-warnings.patch
rename to 0011-fix-useexisting-deprecation-warnings.patch
index c8a0edc..856cd7a 100644
--- a/0006-fix-useexisting-deprecation-warnings.patch
+++ b/0011-fix-useexisting-deprecation-warnings.patch
@@ -1,4 +1,4 @@
-From 11b750a44399f42a6cf6d4e94ee72752fa098021 Mon Sep 17 00:00:00 2001
+From a2760a769da807184deb0f45ea6ec5f84afd5251 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
 Date: Thu, 8 Mar 2012 16:32:30 +0000
 Subject: [PATCH] fix useexisting deprecation warnings
diff --git a/openstack-nova.spec b/openstack-nova.spec
index 5b84972..d6e0b2e 100644
--- a/openstack-nova.spec
+++ b/openstack-nova.spec
@@ -2,7 +2,7 @@
 
 Name:             openstack-nova
 Version:          2012.1
-Release:          1%{?dist}
+Release:          2%{?dist}
 Summary:          OpenStack Compute (nova)
 
 Group:            Applications/System
@@ -32,10 +32,15 @@ Source23:         openstack-nova-db-setup
 #
 Patch0001: 0001-fix-bug-where-nova-ignores-glance-host-in-imageref.patch
 Patch0002: 0002-Stop-libvirt-test-from-deleting-instances-dir.patch
-Patch0003: 0003-ensure-atomic-manipulation-of-libvirt-disk-images.patch
+Patch0003: 0003-Allow-unprivileged-RADOS-users-to-access-rbd-volumes.patch
 Patch0004: 0004-Fixed-bug-962840-added-a-test-case.patch
-Patch0005: 0005-Ensure-we-don-t-access-the-net-when-building-docs.patch
-Patch0006: 0006-fix-useexisting-deprecation-warnings.patch
+Patch0005: 0005-Fix-errors-in-os-networks-extension.patch
+Patch0006: 0006-Create-compute.api.BaseAPI-for-compute-APIs-to-use.patch
+Patch0007: 0007-Populate-image-properties-with-project_id-again.patch
+Patch0008: 0008-Use-project_id-in-ec2.cloud._format_image.patch
+Patch0009: 0009-ensure-atomic-manipulation-of-libvirt-disk-images.patch
+Patch0010: 0010-Ensure-we-don-t-access-the-net-when-building-docs.patch
+Patch0011: 0011-fix-useexisting-deprecation-warnings.patch
 
 BuildArch:        noarch
 BuildRequires:    intltool
@@ -177,6 +182,11 @@ This package contains documentation files for nova.
 %patch0004 -p1
 %patch0005 -p1
 %patch0006 -p1
+%patch0007 -p1
+%patch0008 -p1
+%patch0009 -p1
+%patch0010 -p1
+%patch0011 -p1
 
 find . \( -name .gitignore -o -name .placeholder \) -delete
 
@@ -375,6 +385,9 @@ fi
 %endif
 
 %changelog
+* Wed Apr 18 2012 Pádraig Brady <P at draigBrady.com> - 2012.1-2
+- Sync up with Essex stable branch
+
 * Sun Apr  8 2012 Pádraig Brady <P at draigBrady.com> - 2012.1-1
 - Update to Essex release
 


More information about the scm-commits mailing list