--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/python/novaclient/patches/03-launchpad-1446850.patch Tue Jul 12 11:21:14 2016 -0600
@@ -0,0 +1,216 @@
+This upstream patch has been addressed in Liberty but has not yet been
+addressed in Kilo.
+
+From 098116d6a574b8dede101b257db2ff22d269c6c7 Mon Sep 17 00:00:00 2001
+From: melanie witt <[email protected]>
+Date: Tue, 21 Apr 2015 21:32:33 +0000
+Subject: Revert "nova flavor-show command is inconsistent"
+
+This reverts commit 4e79285b45ec1490c8e923f724cbaf4d42fe81c4.
+
+The aforementioned commit broke flavor-show for mixed case flavorids.
+The reason is a bit complex. On the nova api side, there is caching of
+db items for flavors, keyed off the flavorid retrieved from the db,
+case sensitive, unlike the db query itself. Attempts to flavor-show
+a flavor with flavorid composed of letters will fail with a 400 if
+the capitalization doesn't match.
+
+For the flavor names, they work in lowercase because the find_resource
+function falls back on a search by "human_id" after failing every other
+attempt to find the flavor, because "human_id" is a oslo-slugified
+string (all lowercase, non-word characters removed, spaces converted
+to hyphens).
+
+Closes-Bug: #1446850
+
+Change-Id: I73247b50f5a6918167c071ccc13cd676aa2c7fec
+---
+ novaclient/tests/unit/test_base.py | 2 +-
+ novaclient/tests/unit/v2/fakes.py | 20 ++++++++++----------
+ novaclient/tests/unit/v2/test_flavors.py | 4 ++--
+ novaclient/tests/unit/v2/test_shell.py | 16 ++++++++--------
+ novaclient/v2/shell.py | 11 -----------
+ 5 files changed, 21 insertions(+), 32 deletions(-)
+
+diff --git a/novaclient/tests/unit/test_base.py b/novaclient/tests/unit/test_base.py
+index 1ba1d32..b7bceb7 100644
+--- a/novaclient/tests/unit/test_base.py
++++ b/novaclient/tests/unit/test_base.py
+@@ -36,7 +36,7 @@ class BaseTest(utils.TestCase):
+
+ def test_resource_lazy_getattr(self):
+ f = flavors.Flavor(cs.flavors, {'id': 1})
+- self.assertEqual('256 mb server', f.name)
++ self.assertEqual('256 MB Server', f.name)
+ cs.assert_called('GET', '/flavors/1')
+
+ # Missing stuff still fails after a second get
+diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py
+index 343c421..40cd471 100644
+--- a/novaclient/tests/unit/v2/fakes.py
++++ b/novaclient/tests/unit/v2/fakes.py
+@@ -258,7 +258,7 @@ class FakeHTTPClient(base_client.HTTPClient):
+ },
+ "flavor": {
+ "id": 1,
+- "name": "256 mb server",
++ "name": "256 MB Server",
+ },
+ "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0",
+ "status": "BUILD",
+@@ -299,7 +299,7 @@ class FakeHTTPClient(base_client.HTTPClient):
+ },
+ "flavor": {
+ "id": 1,
+- "name": "256 mb server",
++ "name": "256 MB Server",
+ },
+ "hostId": "9e107d9d372bb6826bd81d3542a419d6",
+ "status": "ACTIVE",
+@@ -340,7 +340,7 @@ class FakeHTTPClient(base_client.HTTPClient):
+ "image": "",
+ "flavor": {
+ "id": 1,
+- "name": "256 mb server",
++ "name": "256 MB Server",
+ },
+ "hostId": "9e107d9d372bb6826bd81d3542a419d6",
+ "status": "ACTIVE",
+@@ -672,19 +672,19 @@ class FakeHTTPClient(base_client.HTTPClient):
+
+ def get_flavors_detail(self, **kw):
+ flavors = {'flavors': [
+- {'id': 1, 'name': '256 mb server', 'ram': 256, 'disk': 10,
++ {'id': 1, 'name': '256 MB Server', 'ram': 256, 'disk': 10,
+ 'OS-FLV-EXT-DATA:ephemeral': 10,
+ 'os-flavor-access:is_public': True,
+ 'links': {}},
+- {'id': 2, 'name': '512 mb server', 'ram': 512, 'disk': 20,
++ {'id': 2, 'name': '512 MB Server', 'ram': 512, 'disk': 20,
+ 'OS-FLV-EXT-DATA:ephemeral': 20,
+ 'os-flavor-access:is_public': False,
+ 'links': {}},
+- {'id': 4, 'name': '1024 mb server', 'ram': 1024, 'disk': 10,
++ {'id': 4, 'name': '1024 MB Server', 'ram': 1024, 'disk': 10,
+ 'OS-FLV-EXT-DATA:ephemeral': 10,
+ 'os-flavor-access:is_public': True,
+ 'links': {}},
+- {'id': 'aa1', 'name': '128 mb server', 'ram': 128, 'disk': 0,
++ {'id': 'aa1', 'name': '128 MB Server', 'ram': 128, 'disk': 0,
+ 'OS-FLV-EXT-DATA:ephemeral': 0,
+ 'os-flavor-access:is_public': True,
+ 'links': {}}
+@@ -736,16 +736,16 @@ class FakeHTTPClient(base_client.HTTPClient):
+ {},
+ {'flavor': {
+ 'id': 3,
+- 'name': '256 mb server',
++ 'name': '256 MB Server',
+ 'ram': 256,
+ 'disk': 10,
+ }},
+ )
+
+- def get_flavors_512_mb_server(self, **kw):
++ def get_flavors_512_MB_Server(self, **kw):
+ raise exceptions.NotFound('404')
+
+- def get_flavors_128_mb_server(self, **kw):
++ def get_flavors_128_MB_Server(self, **kw):
+ raise exceptions.NotFound('404')
+
+ def get_flavors_aa1(self, **kw):
+diff --git a/novaclient/tests/unit/v2/test_flavors.py b/novaclient/tests/unit/v2/test_flavors.py
+index 5045902..4fe43c1 100644
+--- a/novaclient/tests/unit/v2/test_flavors.py
++++ b/novaclient/tests/unit/v2/test_flavors.py
+@@ -93,10 +93,10 @@ class FlavorsTest(utils.TestCase):
+ def test_find(self):
+ f = self.cs.flavors.find(ram=256)
+ self.cs.assert_called('GET', '/flavors/detail')
+- self.assertEqual('256 mb server', f.name)
++ self.assertEqual('256 MB Server', f.name)
+
+ f = self.cs.flavors.find(disk=0)
+- self.assertEqual('128 mb server', f.name)
++ self.assertEqual('128 MB Server', f.name)
+
+ self.assertRaises(exceptions.NotFound, self.cs.flavors.find,
+ disk=12345)
+diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py
+index b1b9b80..3e7462c 100644
+--- a/novaclient/tests/unit/v2/test_shell.py
++++ b/novaclient/tests/unit/v2/test_shell.py
+@@ -668,10 +668,10 @@ class ShellTest(utils.TestCase):
+
+ def test_boot_named_flavor(self):
+ self.run_command(["boot", "--image", "1",
+- "--flavor", "512 mb server",
++ "--flavor", "512 MB Server",
+ "--max-count", "3", "server"])
+ self.assert_called('GET', '/images/1', pos=0)
+- self.assert_called('GET', '/flavors/512 mb server', pos=1)
++ self.assert_called('GET', '/flavors/512 MB Server', pos=1)
+ self.assert_called('GET', '/flavors?is_public=None', pos=2)
+ self.assert_called('GET', '/flavors/2', pos=3)
+ self.assert_called(
+@@ -708,15 +708,15 @@ class ShellTest(utils.TestCase):
+ self.assert_called_anytime('GET', '/flavors/aa1')
+
+ def test_flavor_show_by_name(self):
+- self.run_command(['flavor-show', '128 mb server'])
+- self.assert_called('GET', '/flavors/128 mb server', pos=0)
++ self.run_command(['flavor-show', '128 MB Server'])
++ self.assert_called('GET', '/flavors/128 MB Server', pos=0)
+ self.assert_called('GET', '/flavors?is_public=None', pos=1)
+ self.assert_called('GET', '/flavors/aa1', pos=2)
+ self.assert_called('GET', '/flavors/aa1/os-extra_specs', pos=3)
+
+ def test_flavor_show_by_name_priv(self):
+- self.run_command(['flavor-show', '512 mb server'])
+- self.assert_called('GET', '/flavors/512 mb server', pos=0)
++ self.run_command(['flavor-show', '512 MB Server'])
++ self.assert_called('GET', '/flavors/512 MB Server', pos=0)
+ self.assert_called('GET', '/flavors?is_public=None', pos=1)
+ self.assert_called('GET', '/flavors/2', pos=2)
+ self.assert_called('GET', '/flavors/2/os-extra_specs', pos=3)
+@@ -753,7 +753,7 @@ class ShellTest(utils.TestCase):
+ {'addTenantAccess': {'tenant': 'proj2'}})
+
+ def test_flavor_access_add_by_name(self):
+- self.run_command(['flavor-access-add', '512 mb server', 'proj2'])
++ self.run_command(['flavor-access-add', '512 MB Server', 'proj2'])
+ self.assert_called('POST', '/flavors/2/action',
+ {'addTenantAccess': {'tenant': 'proj2'}})
+
+@@ -763,7 +763,7 @@ class ShellTest(utils.TestCase):
+ {'removeTenantAccess': {'tenant': 'proj2'}})
+
+ def test_flavor_access_remove_by_name(self):
+- self.run_command(['flavor-access-remove', '512 mb server', 'proj2'])
++ self.run_command(['flavor-access-remove', '512 MB Server', 'proj2'])
+ self.assert_called('POST', '/flavors/2/action',
+ {'removeTenantAccess': {'tenant': 'proj2'}})
+
+diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py
+index 33653a1..f8b1a10 100644
+--- a/novaclient/v2/shell.py
++++ b/novaclient/v2/shell.py
+@@ -1898,17 +1898,6 @@ def _find_image(cs, image):
+ def _find_flavor(cs, flavor):
+ """Get a flavor by name, ID, or RAM size."""
+ try:
+- # isinstance() is being used to check if flavor is an instance of
+- # integer. It will help us to check if the user has entered flavor
+- # name or flavorid. If flavor name has been entered it is being
+- # converted to lowercase using lower(). Incase it is an ID the user
+- # has passed it will not go through the "flavor = flavor.lower()"
+- # code.The reason for checking if it is a flavor name or flavorid is
+- # that int has no lower() so it will give an error.
+- if isinstance(flavor, six.integer_types):
+- pass
+- else:
+- flavor = flavor.lower()
+ return utils.find_resource(cs.flavors, flavor, is_public=None)
+ except exceptions.NotFound:
+ return cs.flavors.find(ram=flavor)