Merge "Removed unnecessary commented code"
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 1ac34eb..8fe24c7 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -245,7 +245,7 @@
 
     @test.idempotent_id('3e48f95d-e660-4fa9-85e0-5a3d85594384')
     def test_trust_expire_invalid(self):
-        # Test case to check we can check an invlaid expiry time
+        # Test case to check we can check an invalid expiry time
         # is rejected with the correct error
         # with an expiry specified
         expires_str = 'bad.123Z'
diff --git a/tempest/clients.py b/tempest/clients.py
index b3fb8a8..7cb4347 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -243,8 +243,8 @@
         # with identity v2
         if CONF.identity_feature_enabled.api_v2 and \
                 CONF.identity.auth_version == 'v2':
-            # EC2 and S3 clients, if used, will check onfigured AWS credentials
-            # and generate new ones if needed
+            # EC2 and S3 clients, if used, will check configured AWS
+            # credentials and generate new ones if needed
             self.ec2api_client = botoclients.APIClientEC2(self.identity_client)
             self.s3_client = botoclients.ObjectClientS3(self.identity_client)
 
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 30fb38c..aef42be 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -503,7 +503,7 @@
     def check_telemetry(self):
         """Check that ceilometer provides a sane sample.
 
-        Confirm that there are more than one sample and that they have the
+        Confirm that there is more than one sample and that they have the
         expected metadata.
 
         If in check mode confirm that the oldest sample available is from
@@ -680,7 +680,7 @@
 
         response = _get_image_by_name(client, image['name'])
         if not response:
-            LOG.info("Image '%s' does not exists" % image['name'])
+            LOG.info("Image '%s' does not exist" % image['name'])
             continue
         client.images.delete_image(response['id'])
 
@@ -729,7 +729,7 @@
         # only create a network if the name isn't here
         body = client.networks.list_networks()
         if any(item['name'] == network['name'] for item in body['networks']):
-            LOG.warning("Dupplicated network name: %s" % network['name'])
+            LOG.warning("Duplicated network name: %s" % network['name'])
             continue
 
         client.networks.create_network(name=network['name'])
@@ -781,7 +781,7 @@
         # only create a router if the name isn't here
         body = client.networks.list_routers()
         if any(item['name'] == router['name'] for item in body['routers']):
-            LOG.warning("Dupplicated router name: %s" % router['name'])
+            LOG.warning("Duplicated router name: %s" % router['name'])
             continue
 
         client.networks.create_router(router['name'])
@@ -813,7 +813,7 @@
             # connect routers to their subnets
             client.networks.add_router_interface_with_subnet_id(router_id,
                                                                 subnet_id)
-        # connect routers to exteral network if set to "gateway"
+        # connect routers to external network if set to "gateway"
         if router['gateway']:
             if CONF.network.public_network_id:
                 ext_net = CONF.network.public_network_id
@@ -871,7 +871,7 @@
             server['name'], image_id, flavor_id, **kwargs)
         server_id = body['id']
         client.servers.wait_for_server_status(server_id, 'ACTIVE')
-        # create to security group(s) after server spawning
+        # create security group(s) after server spawning
         for secgroup in server['secgroups']:
             client.servers.add_security_group(server_id, secgroup)
         if CONF.compute.use_floatingip_for_ssh:
@@ -995,7 +995,7 @@
 def create_resources():
     LOG.info("Creating Resources")
     # first create keystone level resources, and we need to be admin
-    # for those.
+    # for this.
     create_tenants(RES['tenants'])
     create_users(RES['users'])
     collect_users(RES['users'])
@@ -1015,7 +1015,7 @@
     create_volumes(RES['volumes'])
 
     # Only attempt attaching the volumes if servers are defined in the
-    # resourcefile
+    # resource file
     if 'servers' in RES:
         create_servers(RES['servers'])
         attach_volumes(RES['volumes'])
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 93c2c10..a567c6a 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -106,7 +106,8 @@
 
     def get_nic_name(self, address):
         cmd = "ip -o addr | awk '/%s/ {print $2}'" % address
-        return self.exec_command(cmd)
+        nic = self.exec_command(cmd)
+        return nic.strip().strip(":").lower()
 
     def get_ip_list(self):
         cmd = "ip address"
@@ -144,7 +145,6 @@
         """Renews DHCP lease via udhcpc client. """
         file_path = '/var/run/udhcpc.'
         nic_name = self.get_nic_name(fixed_ip)
-        nic_name = nic_name.strip().lower()
         pid = self.exec_command('cat {path}{nic}.pid'.
                                 format(path=file_path, nic=nic_name))
         pid = pid.strip()
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index da4ebbe..89b0842 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -663,14 +663,18 @@
     def _get_server_port_id_and_ip4(self, server, ip_addr=None):
         ports = self._list_ports(device_id=server['id'],
                                  fixed_ip=ip_addr)
-        self.assertEqual(len(ports), 1,
-                         "Unable to determine which port to target.")
         # it might happen here that this port has more then one ip address
         # as in case of dual stack- when this port is created on 2 subnets
-        for ip46 in ports[0]['fixed_ips']:
-            ip = ip46['ip_address']
-            if netaddr.valid_ipv4(ip):
-                return ports[0]['id'], ip
+        port_map = [(p["id"], fxip["ip_address"])
+                    for p in ports
+                    for fxip in p["fixed_ips"]
+                    if netaddr.valid_ipv4(fxip["ip_address"])]
+
+        self.assertEqual(len(port_map), 1,
+                         "Found multiple IPv4 addresses: %s. "
+                         "Unable to determine which port to target."
+                         % port_map)
+        return port_map[0]
 
     def _get_network_by_name(self, network_name):
         net = self._list_networks(name=network_name)
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 9481e58..a9394cb 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -69,13 +69,18 @@
             'key_name': self.keypair['name'],
             'security_groups': [{'name': self.sec_grp['name']}]}
 
-    def prepare_network(self, address6_mode, n_subnets6=1):
+    def prepare_network(self, address6_mode, n_subnets6=1, dualnet=False):
         """Creates network with
          given number of IPv6 subnets in the given mode and
          one IPv4 subnet
          Creates router with ports on all subnets
+         if dualnet - create IPv6 subnets on a different network
+         :return: list of created networks
         """
         self.network = self._create_network(tenant_id=self.tenant_id)
+        if dualnet:
+            self.network_v6 = self._create_network(tenant_id=self.tenant_id)
+
         sub4 = self._create_subnet(network=self.network,
                                    namestart='sub4',
                                    ip_version=4)
@@ -86,7 +91,8 @@
 
         self.subnets_v6 = []
         for _ in range(n_subnets6):
-            sub6 = self._create_subnet(network=self.network,
+            net6 = self.network_v6 if dualnet else self.network
+            sub6 = self._create_subnet(network=net6,
                                        namestart='sub6',
                                        ip_version=6,
                                        ipv6_ra_mode=address6_mode,
@@ -96,6 +102,8 @@
             self.addCleanup(sub6.delete)
             self.subnets_v6.append(sub6)
 
+        return [self.network, self.network_v6] if dualnet else [self.network]
+
     @staticmethod
     def define_server_ips(srv):
         ips = {'4': None, '6': []}
@@ -107,11 +115,12 @@
                     ips['4'] = nic['addr']
         return ips
 
-    def prepare_server(self):
+    def prepare_server(self, networks=None):
         username = CONF.compute.image_ssh_user
 
         create_kwargs = self.srv_kwargs
-        create_kwargs['networks'] = [{'uuid': self.network.id}]
+        networks = networks or [self.network]
+        create_kwargs['networks'] = [{'uuid': n.id} for n in networks]
 
         srv = self.create_server(create_kwargs=create_kwargs)
         fip = self.create_floating_ip(thing=srv)
@@ -119,18 +128,42 @@
         ssh = self.get_remote_client(
             server_or_ip=fip.floating_ip_address,
             username=username)
-        return ssh, ips
+        return ssh, ips, srv["id"]
 
-    def _prepare_and_test(self, address6_mode, n_subnets6=1):
-        self.prepare_network(address6_mode=address6_mode,
-                             n_subnets6=n_subnets6)
+    def turn_nic6_on(self, ssh, sid):
+        """Turns the IPv6 vNIC on
 
-        sshv4_1, ips_from_api_1 = self.prepare_server()
-        sshv4_2, ips_from_api_2 = self.prepare_server()
+        Required because guest images usually set only the first vNIC on boot.
+        Searches for the IPv6 vNIC's MAC and brings it up.
+
+        @param ssh: RemoteClient ssh instance to server
+        @param sid: server uuid
+        """
+        ports = [p["mac_address"] for p in
+                 self._list_ports(device_id=sid,
+                                  network_id=self.network_v6.id)]
+        self.assertEqual(1, len(ports),
+                         message="Multiple IPv6 ports found on network %s"
+                         % self.network_v6)
+        mac6 = ports[0]
+        ssh.turn_nic_on(ssh.get_nic_name(mac6))
+
+    def _prepare_and_test(self, address6_mode, n_subnets6=1, dualnet=False):
+        net_list = self.prepare_network(address6_mode=address6_mode,
+                                        n_subnets6=n_subnets6,
+                                        dualnet=dualnet)
+
+        sshv4_1, ips_from_api_1, sid1 = self.prepare_server(networks=net_list)
+        sshv4_2, ips_from_api_2, sid2 = self.prepare_server(networks=net_list)
 
         def guest_has_address(ssh, addr):
             return addr in ssh.get_ip_list()
 
+        # Turn on 2nd NIC for Cirros when dualnet
+        if dualnet:
+            self.turn_nic6_on(sshv4_1, sid1)
+            self.turn_nic6_on(sshv4_2, sid2)
+
         # get addresses assigned to vNIC as reported by 'ip address' utility
         ips_from_ip_1 = sshv4_1.get_ip_list()
         ips_from_ip_2 = sshv4_2.get_ip_list()
@@ -196,3 +229,25 @@
     @test.services('compute', 'network')
     def test_multi_prefix_slaac(self):
         self._prepare_and_test(address6_mode='slaac', n_subnets6=2)
+
+    @test.idempotent_id('b6399d76-4438-4658-bcf5-0d6c8584fde2')
+    @test.services('compute', 'network')
+    def test_dualnet_slaac_from_os(self):
+        self._prepare_and_test(address6_mode='slaac', dualnet=True)
+
+    @test.idempotent_id('76f26acd-9688-42b4-bc3e-cd134c4cb09e')
+    @test.services('compute', 'network')
+    def test_dualnet_dhcp6_stateless_from_os(self):
+        self._prepare_and_test(address6_mode='dhcpv6-stateless', dualnet=True)
+
+    @test.idempotent_id('cf1c4425-766b-45b8-be35-e2959728eb00')
+    @test.services('compute', 'network')
+    def test_dualnet_multi_prefix_dhcpv6_stateless(self):
+        self._prepare_and_test(address6_mode='dhcpv6-stateless', n_subnets6=2,
+                               dualnet=True)
+
+    @test.idempotent_id('9178ad42-10e4-47e9-8987-e02b170cc5cd')
+    @test.services('compute', 'network')
+    def test_dualnet_multi_prefix_slaac(self):
+        self._prepare_and_test(address6_mode='slaac', n_subnets6=2,
+                               dualnet=True)
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index 0e0141f..c89985c 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -165,7 +165,7 @@
         if not self.new_server:
             self.new_server_ops()
 
-    # now we just test is number of partition increased or decrised
+    # now we just test that the number of partitions has increased or decreased
     def part_wait(self, num_match):
         def _part_state():
             self.partitions = self.remote_client.get_partitions().split('\n')
@@ -205,7 +205,7 @@
         self.manager.volumes_client.wait_for_volume_status(self.volume['id'],
                                                            'available')
         if self.enable_ssh_verify:
-            self.logger.info("Scanning for block device disapperance on %s"
+            self.logger.info("Scanning for block device disappearance on %s"
                              % self.server_id)
             self.part_wait(self.detach_match_count)
         if self.new_volume: