Merge "Use skip_checks instead of skipUnless in TestShelveInstance"
diff --git a/.gitignore b/.gitignore
index e96deb1..9292dbb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 AUTHORS
 ChangeLog
 *.pyc
+__pycache__/
 etc/tempest.conf
 etc/tempest.conf.sample
 etc/logging.conf
diff --git a/doc/source/test-removal.rst b/doc/source/test-removal.rst
index 6570bb7..79a5846 100644
--- a/doc/source/test-removal.rst
+++ b/doc/source/test-removal.rst
@@ -31,7 +31,7 @@
 
  #. The tests proposed for removal must have equiv. coverage in a different
     project's test suite (whether this is another gating test project, or an in
-    tree funcitonal test suite) For API tests preferably the other project will
+    tree functional test suite). For API tests preferably the other project will
     have a similar source of friction in place to prevent breaking api changes
     so that we don't regress and let breaking api changes slip through the
     gate.
@@ -62,7 +62,7 @@
 
 SELECT * from tests where test_id like "%test_id%";
 (where $test_id is the full test_id, but truncated to the class because of
-setupclass or teardownclass failures)
+setupClass or tearDownClass failures)
 
 You can access the infra mysql subunit2sql db w/ read-only permissions with:
 
@@ -113,7 +113,7 @@
 well ahead of the scheduled meeting. Since the meeting time will be well known
 ahead of time anyone who depends on the tests will have ample time beforehand
 to outline any concerns on the before the meeting. To give ample time for
-people to respond to removal proposals please add things to the agend by the
+people to respond to removal proposals please add things to the agenda by the
 Monday before the meeting.
 
 The other option is to raise the removal on the openstack-dev mailing list.
@@ -163,6 +163,6 @@
 anything that lives in tempest which doesn't test one of these projects can be
 removed assuming there is equivalent testing elsewhere. Preferably using the
 `tempest plugin mechanism`_
-to mantain continuity after migrating the tests out of tempest
+to maintain continuity after migrating the tests out of tempest.
 
 .. _tempest plugin mechanism: http://docs.openstack.org/developer/tempest/plugin.html
diff --git a/tempest/cmd/list_plugins.py b/tempest/cmd/list_plugins.py
index 5f6b3e6..36e45a5 100644
--- a/tempest/cmd/list_plugins.py
+++ b/tempest/cmd/list_plugins.py
@@ -19,13 +19,10 @@
 """
 
 from cliff import command
-from oslo_log import log as logging
 import prettytable
 
 from tempest.test_discover.plugins import TempestTestPluginManager
 
-LOG = logging.getLogger(__name__)
-
 
 class TempestListPlugins(command.Command):
     def take_action(self, parsed_args):
diff --git a/tempest/cmd/run.py b/tempest/cmd/run.py
index 2eb122e..b6b70d7 100644
--- a/tempest/cmd/run.py
+++ b/tempest/cmd/run.py
@@ -88,7 +88,6 @@
 from cliff import command
 from os_testr import regex_builder
 from os_testr import subunit_trace
-from oslo_log import log as logging
 from testrepository.commands import run_argv
 
 from tempest.cmd import init
@@ -96,7 +95,6 @@
 from tempest import config
 
 
-LOG = logging.getLogger(__name__)
 CONF = config.CONF
 
 
diff --git a/tempest/cmd/workspace.py b/tempest/cmd/workspace.py
index 6e4b9b4..b36cf4e 100644
--- a/tempest/cmd/workspace.py
+++ b/tempest/cmd/workspace.py
@@ -53,13 +53,11 @@
 
 from cliff import command
 from oslo_concurrency import lockutils
-from oslo_log import log as logging
 import prettytable
 import yaml
 
 from tempest import config
 
-LOG = logging.getLogger(__name__)
 CONF = config.CONF
 
 
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index c290b57..a2edcdc 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -40,11 +40,20 @@
     :param clients: Client manager which provides OpenStack Tempest clients.
     :param validatable: Whether the server will be pingable or sshable.
     :param validation_resources: Resources created for the connection to the
-    server. Include a keypair, a security group and an IP.
+        server. Include a keypair, a security group and an IP.
     :param tenant_network: Tenant network to be used for creating a server.
     :param wait_until: Server status to wait for the server to reach after
-    its creation.
+        its creation.
     :param volume_backed: Whether the instance is volume backed or not.
+    :param name: Name of the server to be provisioned. If not defined a random
+        string ending with '-instance' will be generated.
+    :param flavor: Flavor of the server to be provisioned. If not defined,
+        CONF.compute.flavor_ref will be used instead.
+    :param image_id: ID of the image to be used to provision the server. If not
+        defined, CONF.compute.image_ref will be used instead.
+    :param delete_vol_on_termination: Controls whether the backing volume
+        should be deleted when the server is deleted. Only applies to volume
+        backed servers.
     :returns: a tuple
     """
 
diff --git a/tempest/lib/base.py b/tempest/lib/base.py
index 227ac37..f687343 100644
--- a/tempest/lib/base.py
+++ b/tempest/lib/base.py
@@ -13,14 +13,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
 import os
 
 import fixtures
 import testtools
 
-LOG = logging.getLogger(__name__)
-
 
 class BaseTestCase(testtools.testcase.WithAttributes, testtools.TestCase):
     setUpClassCalled = False
diff --git a/tempest/lib/services/network/metering_labels_client.py b/tempest/lib/services/network/metering_labels_client.py
old mode 100644
new mode 100755
index 2350ecd..12a5834
--- a/tempest/lib/services/network/metering_labels_client.py
+++ b/tempest/lib/services/network/metering_labels_client.py
@@ -16,18 +16,41 @@
 class MeteringLabelsClient(base.BaseNetworkClient):
 
     def create_metering_label(self, **kwargs):
+        """Creates an L3 metering label.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#
+                              createMeteringLabel
+        """
         uri = '/metering/metering-labels'
         post_data = {'metering_label': kwargs}
         return self.create_resource(uri, post_data)
 
     def show_metering_label(self, metering_label_id, **fields):
+        """Shows details for a metering label.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#showMeteringLabel
+        """
         uri = '/metering/metering-labels/%s' % metering_label_id
         return self.show_resource(uri, **fields)
 
     def delete_metering_label(self, metering_label_id):
+        """Deletes an L3 metering label.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#
+                              deleteMeteringLabel
+        """
         uri = '/metering/metering-labels/%s' % metering_label_id
         return self.delete_resource(uri)
 
     def list_metering_labels(self, **filters):
+        """Lists all L3 metering labels that belong to the tenant.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#
+                              listMeteringLabels
+        """
         uri = '/metering/metering-labels'
         return self.list_resources(uri, **filters)
diff --git a/tempest/lib/services/network/ports_client.py b/tempest/lib/services/network/ports_client.py
old mode 100644
new mode 100755
index eba11d3..71f1103
--- a/tempest/lib/services/network/ports_client.py
+++ b/tempest/lib/services/network/ports_client.py
@@ -17,24 +17,49 @@
 class PortsClient(base.BaseNetworkClient):
 
     def create_port(self, **kwargs):
+        """Creates a port on a network.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2.html#createPort
+        """
         uri = '/ports'
         post_data = {'port': kwargs}
         return self.create_resource(uri, post_data)
 
     def update_port(self, port_id, **kwargs):
+        """Updates a port.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2.html#updatePort
+        """
         uri = '/ports/%s' % port_id
         post_data = {'port': kwargs}
         return self.update_resource(uri, post_data)
 
     def show_port(self, port_id, **fields):
+        """Shows details for a port.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2.html#showPort
+        """
         uri = '/ports/%s' % port_id
         return self.show_resource(uri, **fields)
 
     def delete_port(self, port_id):
+        """Deletes a port.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2.html#removePort
+        """
         uri = '/ports/%s' % port_id
         return self.delete_resource(uri)
 
     def list_ports(self, **filters):
+        """Lists ports to which the tenant has access.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2.html#listPorts
+        """
         uri = '/ports'
         return self.list_resources(uri, **filters)
 
diff --git a/tempest/lib/services/network/security_groups_client.py b/tempest/lib/services/network/security_groups_client.py
old mode 100644
new mode 100755
index 0e25339..5c89a6f
--- a/tempest/lib/services/network/security_groups_client.py
+++ b/tempest/lib/services/network/security_groups_client.py
@@ -16,23 +16,48 @@
 class SecurityGroupsClient(base.BaseNetworkClient):
 
     def create_security_group(self, **kwargs):
+        """Creates an OpenStack Networking security group.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#createSecGroup
+        """
         uri = '/security-groups'
         post_data = {'security_group': kwargs}
         return self.create_resource(uri, post_data)
 
     def update_security_group(self, security_group_id, **kwargs):
+        """Updates a security group.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#updateSecGroup
+        """
         uri = '/security-groups/%s' % security_group_id
         post_data = {'security_group': kwargs}
         return self.update_resource(uri, post_data)
 
     def show_security_group(self, security_group_id, **fields):
+        """Shows details for a security group.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#showSecGroup
+        """
         uri = '/security-groups/%s' % security_group_id
         return self.show_resource(uri, **fields)
 
     def delete_security_group(self, security_group_id):
+        """Deletes an OpenStack Networking security group.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#deleteSecGroup
+        """
         uri = '/security-groups/%s' % security_group_id
         return self.delete_resource(uri)
 
     def list_security_groups(self, **filters):
+        """Lists OpenStack Networking security groups.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#listSecGroups
+        """
         uri = '/security-groups'
         return self.list_resources(uri, **filters)
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 446c87a..b58479d 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -81,22 +81,42 @@
                                                   'verify metadata on server. '
                                                   '%s is empty.' % md_url)
 
+    def _mount_config_drive(self):
+        cmd_blkid = 'blkid | grep -i config-2'
+        result = self.ssh_client.exec_command(cmd_blkid)
+        dev_name = re.match('([^:]+)', result).group()
+        self.ssh_client.exec_command('sudo mount %s /mnt' % dev_name)
+
+    def _unmount_config_drive(self):
+        self.ssh_client.exec_command('sudo umount /mnt')
+
     def verify_metadata_on_config_drive(self):
         if self.run_ssh and CONF.compute_feature_enabled.config_drive:
             # Verify metadata on config_drive
-            cmd_blkid = 'blkid | grep -i config-2'
-            result = self.ssh_client.exec_command(cmd_blkid)
-            dev_name = re.match('([^:]+)', result).group()
-            self.ssh_client.exec_command('sudo mount %s /mnt' % dev_name)
+            self._mount_config_drive()
             cmd_md = 'sudo cat /mnt/openstack/latest/meta_data.json'
             result = self.ssh_client.exec_command(cmd_md)
-            self.ssh_client.exec_command('sudo umount /mnt')
+            self._unmount_config_drive()
             result = json.loads(result)
             self.assertIn('meta', result)
             msg = ('Failed while verifying metadata on config_drive on server.'
                    ' Result of command "%s" is NOT "%s".' % (cmd_md, self.md))
             self.assertEqual(self.md, result['meta'], msg)
 
+    def verify_networkdata_on_config_drive(self):
+        if self.run_ssh and CONF.compute_feature_enabled.config_drive:
+            # Verify network data on config_drive
+            self._mount_config_drive()
+            cmd_md = 'sudo cat /mnt/openstack/latest/network_data.json'
+            result = self.ssh_client.exec_command(cmd_md)
+            self._unmount_config_drive()
+            result = json.loads(result)
+            self.assertIn('services', result)
+            self.assertIn('links', result)
+            self.assertIn('networks', result)
+            # TODO(clarkb) construct network_data from known network
+            # instance info and do direct comparison.
+
     @test.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
     @test.attr(type='smoke')
     @test.services('compute', 'network')
@@ -116,4 +136,5 @@
         self.verify_ssh(keypair)
         self.verify_metadata()
         self.verify_metadata_on_config_drive()
+        self.verify_networkdata_on_config_drive()
         self.servers_client.delete_server(self.instance['id'])
diff --git a/tempest/services/volume/base/base_snapshots_client.py b/tempest/services/volume/base/base_snapshots_client.py
index da7bb01..6d3f03b 100644
--- a/tempest/services/volume/base/base_snapshots_client.py
+++ b/tempest/services/volume/base/base_snapshots_client.py
@@ -10,7 +10,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 from oslo_serialization import jsonutils as json
 from six.moves.urllib import parse as urllib
 
@@ -18,9 +17,6 @@
 from tempest.lib import exceptions as lib_exc
 
 
-LOG = logging.getLogger(__name__)
-
-
 class BaseSnapshotsClient(rest_client.RestClient):
     """Base Client class to send CRUD Volume API requests."""