Enhance tests for flavor_extra_spec API

1) Test for GET {flavor_id}/os-extra_specs/{key_id}
2) Add a negative test to test extra spec key update

Change-Id: I0d424005586f0bcc27642fa9124c7e35a99f8724
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 403a946..6101332 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -26,7 +26,7 @@
 
     """
     Tests Flavor Extra Spec API extension.
-    SET, UNSET Flavor Extra specs require admin privileges.
+    SET, UNSET, UPDATE Flavor Extra specs require admin privileges.
     GET Flavor Extra specs can be performed even by without admin privileges.
     """
 
@@ -87,13 +87,6 @@
         self.assertEqual(update_resp.status, 200)
         self.assertEqual({"key1": "value"}, update_body)
 
-        # GET a key value and verify
-        show_resp, get_body = \
-            self.client.get_flavor_extra_spec_with_key(self.flavor['id'],
-                                                       "key1")
-        self.assertEqual(show_resp.status, 200)
-        self.assertEqual(get_body, 'value')
-
         # GET extra specs and verify the value of the key2
         # is the same as before
         get_resp, get_body = \
@@ -110,7 +103,7 @@
         self.assertEqual(unset_resp.status, 200)
 
     @attr(type='gate')
-    def test_flavor_non_admin_get_all_keys_and_specified_key(self):
+    def test_flavor_non_admin_get_all_keys(self):
         specs = {"key1": "value1", "key2": "value2"}
         set_resp, set_body = self.client.set_flavor_extra_spec(
             self.flavor['id'], specs)
@@ -121,12 +114,19 @@
         for key in specs:
             self.assertEqual(body[key], specs[key])
 
-        get_resp, get_body = \
-            self.flavors_client.get_flavor_extra_spec_with_key(
-                self.flavor['id'],
-                "key1")
-        self.assertEqual(get_resp.status, 200)
-        self.assertEqual("value1", get_body)
+    @attr(type='gate')
+    def test_flavor_non_admin_get_specific_key(self):
+        specs = {"key1": "value1", "key2": "value2"}
+        resp, body = self.client.set_flavor_extra_spec(
+            self.flavor['id'], specs)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(body['key1'], 'value1')
+        self.assertIn('key2', body)
+        resp, body = self.flavors_client.get_flavor_extra_spec_with_key(
+            self.flavor['id'], 'key1')
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(body['key1'], 'value1')
+        self.assertNotIn('key2', body)
 
 
 class FlavorsExtraSpecsTestXML(FlavorsExtraSpecsTestJSON):
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index 8d62a2a..223c902 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -25,7 +25,11 @@
 
 
 class FlavorsExtraSpecsNegativeTestJSON(base.BaseV2ComputeAdminTest):
-    """the Negative tests for FlavorsExtraSpecs."""
+
+    """
+    Negative Tests Flavor Extra Spec API extension.
+    SET, UNSET, UPDATE Flavor Extra specs require admin privileges.
+    """
 
     _interface = 'json'
 
@@ -69,6 +73,21 @@
                           specs)
 
     @attr(type=['negative', 'gate'])
+    def test_flavor_non_admin_update_specific_key(self):
+        # non admin user is not allowed to update flavor extra spec
+        specs = {"key1": "value1", "key2": "value2"}
+        resp, body = self.client.set_flavor_extra_spec(
+            self.flavor['id'], specs)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(body['key1'], 'value1')
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.
+                          update_flavor_extra_spec,
+                          self.flavor['id'],
+                          'key1',
+                          key1='value1_new')
+
+    @attr(type=['negative', 'gate'])
     def test_flavor_non_admin_unset_keys(self):
         specs = {"key1": "value1", "key2": "value2"}
         set_resp, set_body = self.client.set_flavor_extra_spec(
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index 588e5cd..00d6f8a 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -103,14 +103,14 @@
         return resp, body['extra_specs']
 
     def get_flavor_extra_spec_with_key(self, flavor_id, key):
-        """Gets a specified key value for the mentioned flavor."""
+        """Gets extra Specs key-value of the mentioned flavor and key."""
         resp, body = self.get('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
                               key))
         body = json.loads(body)
-        return resp, body[key]
+        return resp, body
 
     def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
-        """Gets specified extra Specs details of the mentioned flavor."""
+        """Update specified extra Specs of the mentioned flavor and key."""
         resp, body = self.put('flavors/%s/os-extra_specs/%s' %
                               (flavor_id, key),
                               json.dumps(kwargs), self.headers)
diff --git a/tempest/services/compute/xml/flavors_client.py b/tempest/services/compute/xml/flavors_client.py
index d4c456e..363c1a8 100644
--- a/tempest/services/compute/xml/flavors_client.py
+++ b/tempest/services/compute/xml/flavors_client.py
@@ -154,14 +154,17 @@
         return resp, body
 
     def get_flavor_extra_spec_with_key(self, flavor_id, key):
-        """Gets a specified key detail for the mentioned flavor."""
-        resp, body = self.get('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
-                              key), self.headers)
-        body = xml_to_json(etree.fromstring(body))
+        """Gets extra Specs key-value of the mentioned flavor and key."""
+        resp, xml_body = self.get('flavors/%s/os-extra_specs/%s' %
+                                  (str(flavor_id), key), self.headers)
+        body = {}
+        element = etree.fromstring(xml_body)
+        key = element.get('key')
+        body[key] = xml_to_json(element)
         return resp, body
 
     def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
-        """Gets specified extra Specs details of the mentioned flavor."""
+        """Update extra Specs details of the mentioned flavor and key."""
         doc = Document()
         for (k, v) in kwargs.items():
             element = Element(k)