Merge "Use unittest2.TestSuite with py26"
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index d7df6b2..0085cd6 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -115,13 +115,13 @@
         """Wrapper utility that returns a test network."""
         network_name = network_name or data_utils.rand_name('test-network-')
 
-        resp, body = cls.client.create_network(network_name)
+        resp, body = cls.client.create_network(name=network_name)
         network = body['network']
         cls.networks.append(network)
         return network
 
     @classmethod
-    def create_subnet(cls, network):
+    def create_subnet(cls, network, ip_version=4):
         """Wrapper utility that returns a test subnet."""
         cidr = netaddr.IPNetwork(cls.network_cfg.tenant_network_cidr)
         mask_bits = cls.network_cfg.tenant_network_mask_bits
@@ -130,8 +130,10 @@
         failure = None
         for subnet_cidr in cidr.subnet(mask_bits):
             try:
-                resp, body = cls.client.create_subnet(network['id'],
-                                                      str(subnet_cidr))
+                resp, body = cls.client.create_subnet(
+                    network_id=network['id'],
+                    cidr=str(subnet_cidr),
+                    ip_version=ip_version)
                 break
             except exceptions.BadRequest as e:
                 is_overlapping_cidr = 'overlaps with another subnet' in str(e)
@@ -150,7 +152,7 @@
     @classmethod
     def create_port(cls, network):
         """Wrapper utility that returns a test port."""
-        resp, body = cls.client.create_port(network['id'])
+        resp, body = cls.client.create_port(network_id=network['id'])
         port = body['port']
         cls.ports.append(port)
         return port
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index e050c17..a7c1bd2 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -112,7 +112,7 @@
         # Create a floating IP
         created_floating_ip = self.create_floating_ip(self.ext_net_id)
         # Create a port
-        resp, port = self.client.create_port(self.network['id'])
+        resp, port = self.client.create_port(network_id=self.network['id'])
         created_port = port['port']
         resp, floating_ip = self.client.update_floating_ip(
             created_floating_ip['id'], port_id=created_port['id'])
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 4269644..b1f4608 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -65,13 +65,13 @@
     def test_create_update_delete_network_subnet(self):
         # Creates a network
         name = data_utils.rand_name('network-')
-        resp, body = self.client.create_network(name)
+        resp, body = self.client.create_network(name=name)
         self.assertEqual('201', resp['status'])
         network = body['network']
         net_id = network['id']
         # Verification of network update
         new_name = "New_network"
-        resp, body = self.client.update_network(net_id, new_name)
+        resp, body = self.client.update_network(net_id, name=new_name)
         self.assertEqual('200', resp['status'])
         updated_net = body['network']
         self.assertEqual(updated_net['name'], new_name)
@@ -80,8 +80,10 @@
         mask_bits = self.network_cfg.tenant_network_mask_bits
         for subnet_cidr in cidr.subnet(mask_bits):
             try:
-                resp, body = self.client.create_subnet(net_id,
-                                                       str(subnet_cidr))
+                resp, body = self.client.create_subnet(
+                    network_id=net_id,
+                    cidr=str(subnet_cidr),
+                    ip_version=4)
                 break
             except exceptions.BadRequest as e:
                 is_overlapping_cidr = 'overlaps with another subnet' in str(e)
@@ -92,7 +94,8 @@
         subnet_id = subnet['id']
         # Verification of subnet update
         new_subnet = "New_subnet"
-        resp, body = self.client.update_subnet(subnet_id, new_subnet)
+        resp, body = self.client.update_subnet(subnet_id,
+                                               name=new_subnet)
         self.assertEqual('200', resp['status'])
         updated_subnet = body['subnet']
         self.assertEqual(updated_subnet['name'], new_subnet)
@@ -179,12 +182,13 @@
     @attr(type='smoke')
     def test_create_update_delete_port(self):
         # Verify that successful port creation, update & deletion
-        resp, body = self.client.create_port(self.network['id'])
+        resp, body = self.client.create_port(
+            network_id=self.network['id'])
         self.assertEqual('201', resp['status'])
         port = body['port']
         # Verification of port update
         new_port = "New_Port"
-        resp, body = self.client.update_port(port['id'], new_port)
+        resp, body = self.client.update_port(port['id'], name=new_port)
         self.assertEqual('200', resp['status'])
         updated_port = body['port']
         self.assertEqual(updated_port['name'], new_port)
@@ -241,7 +245,7 @@
 
         bulk network creation
         bulk subnet creation
-        bulk subnet creation
+        bulk port creation
         list tenant's networks
 
     v2.0 of the Neutron API is assumed. It is also assumed that the following
diff --git a/tempest/api/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index 67306e9..89c8a9f 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -45,7 +45,7 @@
     def test_update_non_existent_network(self):
         non_exist_id = data_utils.rand_name('network')
         self.assertRaises(exceptions.NotFound, self.client.update_network,
-                          non_exist_id, "new_name")
+                          non_exist_id, name="new_name")
 
     @attr(type=['negative', 'smoke'])
     def test_delete_non_existent_network(self):
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index e746597..426273c 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -94,7 +94,8 @@
         network = self.create_network()
         self.create_subnet(network)
         router = self.create_router(data_utils.rand_name('router-'))
-        resp, port_body = self.client.create_port(network['id'])
+        resp, port_body = self.client.create_port(
+            network_id=network['id'])
         # add router interface to port created above
         resp, interface = self.client.add_router_interface_with_port_id(
             router['id'], port_body['port']['id'])
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 95d12c1..ea614c3 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -237,7 +237,7 @@
     def _create_network(self, name, tenant_id):
         if self.tempest_client:
             resp, resp_body = self.network_admin_client.create_network(
-                name, tenant_id=tenant_id)
+                name=name, tenant_id=tenant_id)
         else:
             body = {'network': {'tenant_id': tenant_id, 'name': name}}
             resp_body = self.network_admin_client.create_network(body)
@@ -257,15 +257,18 @@
                     if self.network_resources:
                         resp, resp_body = self.network_admin_client.\
                             create_subnet(
-                                network_id, str(subnet_cidr),
+                                network_id=network_id, cidr=str(subnet_cidr),
                                 name=subnet_name,
                                 tenant_id=tenant_id,
-                                enable_dhcp=self.network_resources['dhcp'])
+                                enable_dhcp=self.network_resources['dhcp'],
+                                ip_version=4)
                     else:
                         resp, resp_body = self.network_admin_client.\
-                            create_subnet(network_id, str(subnet_cidr),
+                            create_subnet(network_id=network_id,
+                                          cidr=str(subnet_cidr),
                                           name=subnet_name,
-                                          tenant_id=tenant_id)
+                                          tenant_id=tenant_id,
+                                          ip_version=4)
                 else:
                     body['subnet']['cidr'] = str(subnet_cidr)
                     resp_body = self.network_admin_client.create_subnet(body)
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 81ebd4b..a90c924 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -280,7 +280,8 @@
                            " (auth URL is '%s'), the response status is %s" %
                            (req_url, resp.status))
             raise exceptions.AuthenticationFailure(user=user,
-                                                   password=password)
+                                                   password=password,
+                                                   tenant=project_name)
 
     def expected_success(self, expected_code, read_code):
         assert_msg = ("This function only allowed to use for HTTP status"
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 8cb74a9..47c20d2 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -47,50 +47,8 @@
     def serialize(self, data):
         return json.dumps(data)
 
-    def create_network(self, name, **kwargs):
-        post_body = {'network': kwargs}
-        post_body['network']['name'] = name
-        body = json.dumps(post_body)
-        uri = '%s/networks' % (self.uri_prefix)
-        resp, body = self.post(uri, body)
-        body = json.loads(body)
-        return resp, body
-
-    def create_bulk_network(self, count, names):
-        network_list = list()
-        for i in range(count):
-            network_list.append({'name': names[i]})
-        post_body = {'networks': network_list}
-        body = json.dumps(post_body)
-        uri = '%s/networks' % (self.uri_prefix)
-        resp, body = self.post(uri, body)
-        body = json.loads(body)
-        return resp, body
-
-    def create_subnet(self, net_uuid, cidr, ip_version=4, **kwargs):
-        post_body = {'subnet': kwargs}
-        post_body['subnet']['ip_version'] = ip_version
-        post_body['subnet']['network_id'] = net_uuid
-        post_body['subnet']['cidr'] = cidr
-        body = json.dumps(post_body)
-        uri = '%s/subnets' % (self.uri_prefix)
-        resp, body = self.post(uri, body)
-        body = json.loads(body)
-        return resp, body
-
-    def create_port(self, network_id, **kwargs):
-        post_body = {
-            'port': {
-                'network_id': network_id,
-            }
-        }
-        for key, val in kwargs.items():
-            post_body['port'][key] = val
-        body = json.dumps(post_body)
-        uri = '%s/ports' % (self.uri_prefix)
-        resp, body = self.post(uri, body)
-        body = json.loads(body)
-        return resp, body
+    def serialize_list(self, data, root=None, item=None):
+        return self.serialize(data)
 
     def update_quotas(self, tenant_id, **kwargs):
         put_body = {'quota': kwargs}
@@ -105,42 +63,6 @@
         resp, body = self.delete(uri)
         return resp, body
 
-    def update_subnet(self, subnet_id, new_name):
-        put_body = {
-            'subnet': {
-                'name': new_name,
-            }
-        }
-        body = json.dumps(put_body)
-        uri = '%s/subnets/%s' % (self.uri_prefix, subnet_id)
-        resp, body = self.put(uri, body)
-        body = json.loads(body)
-        return resp, body
-
-    def update_port(self, port_id, new_name):
-        put_body = {
-            'port': {
-                'name': new_name,
-            }
-        }
-        body = json.dumps(put_body)
-        uri = '%s/ports/%s' % (self.uri_prefix, port_id)
-        resp, body = self.put(uri, body)
-        body = json.loads(body)
-        return resp, body
-
-    def update_network(self, network_id, new_name):
-        put_body = {
-            "network": {
-                "name": new_name,
-            }
-        }
-        body = json.dumps(put_body)
-        uri = '%s/networks/%s' % (self.uri_prefix, network_id)
-        resp, body = self.put(uri, body)
-        body = json.loads(body)
-        return resp, body
-
     def create_router(self, name, admin_state_up=True, **kwargs):
         post_body = {'router': kwargs}
         post_body['router']['name'] = name
@@ -272,22 +194,6 @@
         body = json.loads(body)
         return resp, body
 
-    def create_bulk_subnet(self, subnet_list):
-        post_body = {'subnets': subnet_list}
-        body = json.dumps(post_body)
-        uri = '%s/subnets' % (self.uri_prefix)
-        resp, body = self.post(uri, body)
-        body = json.loads(body)
-        return resp, body
-
-    def create_bulk_port(self, port_list):
-        post_body = {'ports': port_list}
-        body = json.dumps(post_body)
-        uri = '%s/ports' % (self.uri_prefix)
-        resp, body = self.post(uri, body)
-        body = json.loads(body)
-        return resp, body
-
     def create_vip(self, name, protocol, protocol_port, subnet_id, pool_id):
         post_body = {
             "vip": {
diff --git a/tempest/services/network/network_client_base.py b/tempest/services/network/network_client_base.py
index 57b0ebb..f4a012f 100644
--- a/tempest/services/network/network_client_base.py
+++ b/tempest/services/network/network_client_base.py
@@ -156,3 +156,31 @@
             if name[:prefix_len] == prefix:
                 return method_functors[index](name[prefix_len:])
         raise AttributeError(name)
+
+    # Common methods that are hard to automate
+    def create_bulk_network(self, count, names):
+        network_list = list()
+        for i in range(count):
+            network_list.append({'name': names[i]})
+        post_data = {'networks': network_list}
+        body = self.serialize_list(post_data, "networks", "network")
+        uri = self.get_uri("networks")
+        resp, body = self.post(uri, body)
+        body = {'networks': self.deserialize_list(body)}
+        return resp, body
+
+    def create_bulk_subnet(self, subnet_list):
+        post_data = {'subnets': subnet_list}
+        body = self.serialize_list(post_data, 'subnets', 'subnet')
+        uri = self.get_uri('subnets')
+        resp, body = self.post(uri, body)
+        body = {'subnets': self.deserialize_list(body)}
+        return resp, body
+
+    def create_bulk_port(self, port_list):
+        post_data = {'ports': port_list}
+        body = self.serialize_list(post_data, 'ports', 'port')
+        uri = self.get_uri('ports')
+        resp, body = self.post(uri, body)
+        body = {'ports': self.deserialize_list(body)}
+        return resp, body
diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py
index ebb2d00..b8e39ad 100644
--- a/tempest/services/network/xml/network_client.py
+++ b/tempest/services/network/xml/network_client.py
@@ -33,6 +33,12 @@
         return RestClientXML(config, username, password,
                              auth_url, tenant_name)
 
+    def _parse_array(self, node):
+        array = []
+        for child in node.getchildren():
+            array.append(xml_to_json(child))
+        return array
+
     def deserialize_list(self, body):
         return parse_array(etree.fromstring(body), self.PLURALS)
 
@@ -44,84 +50,34 @@
         # expecting the dict with single key
         root = body.keys()[0]
         post_body = Element(root)
+        post_body.add_attr('xmlns:xsi',
+                           'http://www.w3.org/2001/XMLSchema-instance')
         for name, attr in body[root].items():
-            elt = Element(name, attr)
+            elt = self._get_element(name, attr)
             post_body.append(elt)
         return str(Document(post_body))
 
-    def create_network(self, name):
-        uri = '%s/networks' % (self.uri_prefix)
-        post_body = Element("network")
-        p2 = Element("name", name)
-        post_body.append(p2)
-        resp, body = self.post(uri, str(Document(post_body)))
-        body = _root_tag_fetcher_and_xml_to_json_parse(body)
-        return resp, body
+    def serialize_list(self, body, root_name=None, item_name=None):
+        # expecting dict in form
+        # body = {'resources': [res_dict1, res_dict2, ...]
+        post_body = Element(root_name)
+        post_body.add_attr('xmlns:xsi',
+                           'http://www.w3.org/2001/XMLSchema-instance')
+        for item in body[body.keys()[0]]:
+            elt = Element(item_name)
+            for name, attr in item.items():
+                elt_content = self._get_element(name, attr)
+                elt.append(elt_content)
+            post_body.append(elt)
+        return str(Document(post_body))
 
-    def create_bulk_network(self, count, names):
-        uri = '%s/networks' % (self.uri_prefix)
-        post_body = Element("networks")
-        for i in range(count):
-                p1 = Element("network")
-                p2 = Element("name", names[i])
-                p1.append(p2)
-                post_body.append(p1)
-        resp, body = self.post(uri, str(Document(post_body)))
-        networks = parse_array(etree.fromstring(body))
-        networks = {"networks": networks}
-        return resp, networks
-
-    def create_subnet(self, net_uuid, cidr):
-        uri = '%s/subnets' % (self.uri_prefix)
-        subnet = Element("subnet")
-        p2 = Element("network_id", net_uuid)
-        p3 = Element("cidr", cidr)
-        p4 = Element("ip_version", 4)
-        subnet.append(p2)
-        subnet.append(p3)
-        subnet.append(p4)
-        resp, body = self.post(uri, str(Document(subnet)))
-        body = _root_tag_fetcher_and_xml_to_json_parse(body)
-        return resp, body
-
-    def create_port(self, net_uuid, **kwargs):
-        uri = '%s/ports' % (self.uri_prefix)
-        port = Element("port")
-        p1 = Element('network_id', net_uuid)
-        port.append(p1)
-        for key, val in kwargs.items():
-            key = Element(key, val)
-            port.append(key)
-        resp, body = self.post(uri, str(Document(port)))
-        body = _root_tag_fetcher_and_xml_to_json_parse(body)
-        return resp, body
-
-    def update_port(self, port_id, name):
-        uri = '%s/ports/%s' % (self.uri_prefix, str(port_id))
-        port = Element("port")
-        p2 = Element("name", name)
-        port.append(p2)
-        resp, body = self.put(uri, str(Document(port)))
-        body = _root_tag_fetcher_and_xml_to_json_parse(body)
-        return resp, body
-
-    def update_subnet(self, subnet_id, name):
-        uri = '%s/subnets/%s' % (self.uri_prefix, str(subnet_id))
-        subnet = Element("subnet")
-        p2 = Element("name", name)
-        subnet.append(p2)
-        resp, body = self.put(uri, str(Document(subnet)))
-        body = _root_tag_fetcher_and_xml_to_json_parse(body)
-        return resp, body
-
-    def update_network(self, net_id, name):
-        uri = '%s/networks/%s' % (self.uri_prefix, str(net_id))
-        network = Element("network")
-        p2 = Element("name", name)
-        network.append(p2)
-        resp, body = self.put(uri, str(Document(network)))
-        body = _root_tag_fetcher_and_xml_to_json_parse(body)
-        return resp, body
+    def _get_element(self, name, value):
+        if value is None:
+            xml_elem = Element(name)
+            xml_elem.add_attr("xsi:nil", "true")
+            return xml_elem
+        else:
+            return Element(name, value)
 
     def create_security_group(self, name):
         uri = '%s/security-groups' % (self.uri_prefix)
@@ -147,36 +103,6 @@
         body = _root_tag_fetcher_and_xml_to_json_parse(body)
         return resp, body
 
-    def create_bulk_subnet(self, subnet_list):
-        uri = '%s/subnets' % (self.uri_prefix)
-        post_body = Element("subnets")
-        for i in range(len(subnet_list)):
-            v = subnet_list[i]
-            p1 = Element("subnet")
-            for k, kv in v.iteritems():
-                p2 = Element(k, kv)
-                p1.append(p2)
-            post_body.append(p1)
-        resp, body = self.post(uri, str(Document(post_body)))
-        subnets = parse_array(etree.fromstring(body))
-        subnets = {"subnets": subnets}
-        return resp, subnets
-
-    def create_bulk_port(self, port_list):
-        uri = '%s/ports' % (self.uri_prefix)
-        post_body = Element("ports")
-        for i in range(len(port_list)):
-            v = port_list[i]
-            p1 = Element("port")
-            for k, kv in v.iteritems():
-                p2 = Element(k, kv)
-                p1.append(p2)
-            post_body.append(p1)
-        resp, body = self.post(uri, str(Document(post_body)))
-        ports = parse_array(etree.fromstring(body))
-        ports = {"ports": ports}
-        return resp, ports
-
     def create_vip(self, name, protocol, protocol_port, subnet_id, pool_id):
         uri = '%s/lb/vips' % (self.uri_prefix)
         post_body = Element("vip")