Adds test_update_all_metadata_field_not_included negative test

Adds test_update_all_metadata_field_not_included negative test
which checks a BadRequest is returned when attempting to
set the server metadata and not include the metadata field

Collapses all of the negative tests into one testcase as they
should not have any side effects and it will slightly reduce
setup overhead.

Change-Id: Iab221d23e896fb22bbe351bb20c0378ebaa60add
Closes-Bug: 1131536
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index 5ea3cbf..15c3e6b 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -81,14 +81,6 @@
 
         # no teardown - all creates should fail
 
-    @attr(type=['negative', 'gate'])
-    def test_create_metadata_key_error(self):
-        # Blank key should trigger an error.
-        meta = {'': 'data1'}
-        self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
-                          meta=meta)
-
     @attr(type='gate')
     def test_update_server_metadata(self):
         # The server's metadata values should be updated to the
@@ -147,62 +139,48 @@
         self.assertEqual(expected, resp_metadata)
 
     @attr(type=['negative', 'gate'])
-    def test_get_nonexistant_server_metadata_item(self):
-        # Negative test: GET on a non-existent server should not succeed
+    def test_server_metadata_negative(self):
+        # Blank key should trigger an error.
+        meta = {'': 'data1'}
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_server,
+                          meta=meta)
+
+        # GET on a non-existent server should not succeed
         self.assertRaises(exceptions.NotFound,
                           self.client.get_server_metadata_item, 999, 'test2')
 
-    @attr(type=['negative', 'gate'])
-    def test_list_nonexistant_server_metadata(self):
-        # Negative test:List metadata on a non-existent server should
-        # not succeed
+        # List metadata on a non-existent server should not succeed
         self.assertRaises(exceptions.NotFound,
                           self.client.list_server_metadata, 999)
 
-    @attr(type=['negative', 'gate'])
-    def test_set_server_metadata_item_incorrect_uri_key(self):
         # Raise BadRequest if key in uri does not match
         # the key passed in body.
-
         meta = {'testkey': 'testvalue'}
         self.assertRaises(exceptions.BadRequest,
                           self.client.set_server_metadata_item,
                           self.server_id, 'key', meta)
 
-    @attr(type=['negative', 'gate'])
-    def test_set_nonexistant_server_metadata(self):
-        # Negative test: Set metadata on a non-existent server should not
-        # succeed
+        # Set metadata on a non-existent server should not succeed
         meta = {'meta1': 'data1'}
         self.assertRaises(exceptions.NotFound,
                           self.client.set_server_metadata, 999, meta)
 
-    @attr(type=['negative', 'gate'])
-    def test_update_nonexistant_server_metadata(self):
-        # Negative test: An update should not happen for a non-existent image
+        # An update should not happen for a non-existent image
         meta = {'key1': 'value1', 'key2': 'value2'}
         self.assertRaises(exceptions.NotFound,
                           self.client.update_server_metadata, 999, meta)
 
-    @attr(type=['negative', 'gate'])
-    def test_update_metadata_key_error(self):
-        # Blank key should trigger an error.
+        # Blank key should trigger an error
         meta = {'': 'data1'}
         self.assertRaises(exceptions.BadRequest,
                           self.client.update_server_metadata,
                           self.server_id, meta=meta)
 
-    @attr(type=['negative', 'gate'])
-    def test_delete_nonexistant_server_metadata_item(self):
-        # Negative test: Should not be able to delete metadata item from a
-        #  non-existent server
-
-        # Delete the metadata item
+        # Should not be able to delete metadata item from a non-existent server
         self.assertRaises(exceptions.NotFound,
                           self.client.delete_server_metadata_item, 999, 'd')
 
-    @attr(type=['negative', 'gate'])
-    def test_set_server_metadata_too_long(self):
         # Raise a 413 OverLimit exception while exceeding metadata items limit
         # for tenant.
         _, quota_set = self.quotas.get_quota_set(self.tenant_id)
@@ -214,21 +192,12 @@
                           self.client.set_server_metadata,
                           self.server_id, req_metadata)
 
-    @attr(type=['negative', 'gate'])
-    def test_update_server_metadata_too_long(self):
         # Raise a 413 OverLimit exception while exceeding metadata items limit
-        # for tenant.
-        _, quota_set = self.quotas.get_quota_set(self.tenant_id)
-        quota_metadata = quota_set['metadata_items']
-        req_metadata = {}
-        for num in range(1, quota_metadata + 2):
-            req_metadata['key' + str(num)] = 'val' + str(num)
+        # for tenant (update).
         self.assertRaises(exceptions.OverLimit,
                           self.client.update_server_metadata,
                           self.server_id, req_metadata)
 
-    @attr(type=['negative', 'gate'])
-    def test_update_all_metadata_field_error(self):
         # Raise a bad request error for blank key.
         # set_server_metadata will replace all metadata with new value
         meta = {'': 'data1'}
@@ -236,6 +205,13 @@
                           self.client.set_server_metadata,
                           self.server_id, meta=meta)
 
+        # Raise a bad request error for a missing metadata field
+        # set_server_metadata will replace all metadata with new value
+        meta = {'meta1': 'data1'}
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.set_server_metadata,
+                          self.server_id, meta=meta, no_metadata_field=True)
+
 
 class ServerMetadataTestXML(ServerMetadataTestJSON):
     _interface = 'xml'
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 990c986..851041b 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -236,8 +236,11 @@
         body = json.loads(body)
         return resp, body['metadata']
 
-    def set_server_metadata(self, server_id, meta):
-        post_body = json.dumps({'metadata': meta})
+    def set_server_metadata(self, server_id, meta, no_metadata_field=False):
+        if no_metadata_field:
+            post_body = ""
+        else:
+            post_body = json.dumps({'metadata': meta})
         resp, body = self.put('servers/%s/metadata' % str(server_id),
                               post_body, self.headers)
         body = json.loads(body)
diff --git a/tempest/services/compute/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index bf72bdc..da993ab 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -482,14 +482,15 @@
         body = self._parse_key_value(etree.fromstring(body))
         return resp, body
 
-    def set_server_metadata(self, server_id, meta):
+    def set_server_metadata(self, server_id, meta, no_metadata_field=False):
         doc = Document()
-        metadata = Element("metadata")
-        doc.append(metadata)
-        for k, v in meta.items():
-            meta_element = Element("meta", key=k)
-            meta_element.append(Text(v))
-            metadata.append(meta_element)
+        if not no_metadata_field:
+            metadata = Element("metadata")
+            doc.append(metadata)
+            for k, v in meta.items():
+                meta_element = Element("meta", key=k)
+                meta_element.append(Text(v))
+                metadata.append(meta_element)
         resp, body = self.put('servers/%s/metadata' % str(server_id),
                               str(doc), self.headers)
         return resp, xml_to_json(etree.fromstring(body))