Merge "Add a NotLockingAccounts credentials provider"
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index b31c19a..c491169 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -127,3 +127,44 @@
         msg = ('If admin credentials are available tenant_isolation should be'
                ' used instead')
         raise NotImplementedError(msg)
+
+
+class NotLockingAccounts(Accounts):
+    """Credentials provider which always returns the first and second
+    configured accounts as primary and alt users.
+    This credential provider can be used in case of serial test execution
+    to preserve the current behaviour of the serial tempest run.
+    """
+
+    def get_creds(self, id):
+        try:
+            # No need to sort the dict as within the same python process
+            # the HASH seed won't change, so subsequent calls to keys()
+            # will return the same result
+            _hash = self.hash_dict.keys()[id]
+        except IndexError:
+            msg = 'Insufficient number of users provided'
+            raise exceptions.InvalidConfiguration(msg)
+        return self.hash_dict[_hash]
+
+    def get_primary_creds(self):
+        if self.isolated_creds.get('primary'):
+            return self.isolated_creds.get('primary')
+        creds = self.get_creds(0)
+        primary_credential = auth.get_credentials(**creds)
+        self.isolated_creds['primary'] = primary_credential
+        return primary_credential
+
+    def get_alt_creds(self):
+        if self.isolated_creds.get('alt'):
+            return self.isolated_creds.get('alt')
+        creds = self.get_creds(1)
+        alt_credential = auth.get_credentials(**creds)
+        self.isolated_creds['alt'] = alt_credential
+        return alt_credential
+
+    def clear_isolated_creds(self):
+        self.isolated_creds = {}
+
+    def get_admin_creds(self):
+        return auth.get_default_credentials("identity_admin", fill_in=False)
diff --git a/tempest/tests/common/test_accounts.py b/tempest/tests/common/test_accounts.py
index feafbf5..a0b3496 100644
--- a/tempest/tests/common/test_accounts.py
+++ b/tempest/tests/common/test_accounts.py
@@ -197,3 +197,36 @@
             return_value=self.test_accounts))
         test_accounts_class = accounts.Accounts('test_name')
         self.assertFalse(test_accounts_class.is_multi_user())
+
+
+class TestNotLockingAccount(base.TestCase):
+
+    def setUp(self):
+        super(TestNotLockingAccount, self).setUp()
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+        self.temp_dir = tempfile.mkdtemp()
+        cfg.CONF.set_default('lock_path', self.temp_dir)
+        self.addCleanup(os.rmdir, self.temp_dir)
+        self.test_accounts = [
+            {'username': 'test_user1', 'tenant_name': 'test_tenant1',
+             'password': 'p'},
+            {'username': 'test_user2', 'tenant_name': 'test_tenant2',
+             'password': 'p'},
+            {'username': 'test_user3', 'tenant_name': 'test_tenant3',
+             'password': 'p'},
+        ]
+        self.useFixture(mockpatch.Patch(
+            'tempest.common.accounts.read_accounts_yaml',
+            return_value=self.test_accounts))
+        cfg.CONF.set_default('test_accounts_file', '', group='auth')
+
+    def test_get_creds(self):
+        test_accounts_class = accounts.NotLockingAccounts('test_name')
+        for i in xrange(len(self.test_accounts)):
+            creds = test_accounts_class.get_creds(i)
+            msg = "Empty credentials returned for ID %s" % str(i)
+            self.assertIsNotNone(creds, msg)
+        self.assertRaises(exceptions.InvalidConfiguration,
+                          test_accounts_class.get_creds,
+                          id=len(self.test_accounts))
\ No newline at end of file