Pull in changes from stacktester.
diff --git a/kong/tests/test_server_actions.py b/kong/tests/test_server_actions.py
index e2190cf..f995c67 100644
--- a/kong/tests/test_server_actions.py
+++ b/kong/tests/test_server_actions.py
@@ -23,21 +23,22 @@
         self.flavor_ref = self.os.config.env.flavor_ref
         self.flavor_ref_alt = self.os.config.env.flavor_ref_alt
         self.ssh_timeout = self.os.config.nova.ssh_timeout
+        self.build_timeout = self.os.config.nova.build_timeout
 
         self.server_password = 'testpwd'
-        self.server_name = 'testserver'
+        self.server_name = 'stacktester1'
 
         expected_server = {
-            'name' : self.server_name,
-            'imageRef' : self.image_ref,
-            'flavorRef' : self.flavor_ref,
-            'adminPass' : self.server_password,
+            'name': self.server_name,
+            'imageRef': self.image_ref,
+            'flavorRef': self.flavor_ref,
+            'adminPass': self.server_password,
         }
 
         created_server = self.os.nova.create_server(expected_server)
 
         self.server_id = created_server['id']
-        self._wait_for_status(self.server_id, 'ACTIVE')
+        self._wait_for_server_status(self.server_id, 'ACTIVE')
 
         server = self.os.nova.get_server(self.server_id)
 
@@ -59,9 +60,10 @@
         client = self._get_ssh_client(_password)
         self.assertTrue(client.test_connection_auth())
 
-    def _wait_for_status(self, server_id, status):
+    def _wait_for_server_status(self, server_id, status):
         try:
-            self.os.nova.wait_for_server_status(server_id, status)
+            self.os.nova.wait_for_server_status(server_id, status,
+                                                timeout=self.build_timeout)
         except exceptions.TimeoutException:
             self.fail("Server failed to change status to %s" % status)
 
@@ -71,14 +73,18 @@
         uptime = float(output.split().pop(0))
         return time.time() - uptime
 
-    def _write_file(self, filename, contents):
-        return self._exec_command("echo -n %s > %s" % (contents, filename))
+    def _write_file(self, filename, contents, password=None):
+        command = "echo -n %s > %s" % (contents, filename)
+        return self._exec_command(command, password)
 
-    def _read_file(self, filename):
-        return self._exec_command("cat %s" % filename)
+    def _read_file(self, filename, password=None):
+        command = "cat %s" % filename
+        return self._exec_command(command, password)
 
-    def _exec_command(self, command):
-        client = self._get_ssh_client(self.server_password)
+    def _exec_command(self, command, password=None):
+        if password is None:
+            password = self.server_password
+        client = self._get_ssh_client(password)
         return client.exec_command(command)
 
     def test_reboot_server_soft(self):
@@ -88,21 +94,17 @@
         initial_time_started = self._get_boot_time()
 
         # Make reboot request
-        post_body = json.dumps({
-            'reboot' : {
-                'type' : 'SOFT',
-            }
-        })
+        post_body = json.dumps({'reboot': {'type': 'SOFT'}})
         url = "/servers/%s/action" % self.server_id
         response, body = self.os.nova.request('POST', url, body=post_body)
         self.assertEqual(response['status'], '202')
 
         # Assert status transition
         # KNOWN-ISSUE
-        #self.os.nova.wait_for_server_status(self.server_id, 'REBOOT')
+        #self._wait_for_server_status(self.server_id, 'REBOOT')
         ssh_client = self._get_ssh_client(self.server_password)
         ssh_client.connect_until_closed()
-        self.os.nova.wait_for_server_status(self.server_id, 'ACTIVE')
+        self._wait_for_server_status(self.server_id, 'ACTIVE')
 
         # SSH and verify uptime is less than before
         post_reboot_time_started = self._get_boot_time()
@@ -115,21 +117,17 @@
         initial_time_started = self._get_boot_time()
 
         # Make reboot request
-        post_body = json.dumps({
-            'reboot' : {
-                'type' : 'HARD',
-            }
-        })
+        post_body = json.dumps({'reboot': {'type': 'HARD'}})
         url = "/servers/%s/action" % self.server_id
         response, body = self.os.nova.request('POST', url, body=post_body)
         self.assertEqual(response['status'], '202')
 
         # Assert status transition
         # KNOWN-ISSUE
-        #self.os.nova.wait_for_server_status(self.server_id, 'HARD_REBOOT')
+        #self._wait_for_server_status(self.server_id, 'HARD_REBOOT')
         ssh_client = self._get_ssh_client(self.server_password)
         ssh_client.connect_until_closed()
-        self.os.nova.wait_for_server_status(self.server_id, 'ACTIVE')
+        self._wait_for_server_status(self.server_id, 'ACTIVE')
 
         # SSH and verify uptime is less than before
         post_reboot_time_started = self._get_boot_time()
@@ -142,46 +140,44 @@
         self._assert_ssh_password()
 
         # Change server password
-        post_body = json.dumps({
-            'changePassword' : {
-                'adminPass' : 'test123',
-            }
-        })
+        post_body = json.dumps({'changePassword': {'adminPass': 'test123'}})
         url = '/servers/%s/action' % self.server_id
         response, body = self.os.nova.request('POST', url, body=post_body)
 
         # Assert status transition
         self.assertEqual('202', response['status'])
         # KNOWN-ISSUE
-        #self.os.nova.wait_for_server_status(self.server_id, 'PASSWORD')
-        self.os.nova.wait_for_server_status(self.server_id, 'ACTIVE')
+        self._wait_for_server_status(self.server_id, 'PASSWORD')
+        self._wait_for_server_status(self.server_id, 'ACTIVE')
 
         # SSH into server using new password
         self._assert_ssh_password('test123')
 
-    def test_rebuild_server(self):
+    def test_rebuild(self):
         """Rebuild a server"""
 
-        filename = '/tmp/testfile'
-        contents = 'WORDS'
-        self._write_file(filename, contents)
-        self.assertEqual(self._read_file(filename), contents)
+        FILENAME = '/tmp/testfile'
+        CONTENTS = 'WORDS'
+
+        # write file to server
+        self._write_file(FILENAME, CONTENTS)
+        self.assertEqual(self._read_file(FILENAME), CONTENTS)
 
         # Make rebuild request
-        post_body = json.dumps({
-            'rebuild' : {
-                'imageRef' : self.image_ref_alt,
-            }
-        })
+        post_body = json.dumps({'rebuild': {'imageRef': self.image_ref_alt}})
         url = '/servers/%s/action' % self.server_id
         response, body = self.os.nova.request('POST', url, body=post_body)
 
-        # Ensure correct status transition
+        # check output
         self.assertEqual('202', response['status'])
+        rebuilt_server = json.loads(body)['server']
+        generated_password = rebuilt_server['adminPass']
+
+        # Ensure correct status transition
         # KNOWN-ISSUE
-        #self.os.nova.wait_for_server_status(self.server_id, 'REBUILD')
-        self.os.nova.wait_for_server_status(self.server_id, 'BUILD')
-        self.os.nova.wait_for_server_status(self.server_id, 'ACTIVE')
+        #self._wait_for_server_status(self.server_id, 'REBUILD')
+        self._wait_for_server_status(self.server_id, 'BUILD')
+        self._wait_for_server_status(self.server_id, 'ACTIVE')
 
         # Treats an issue where we ssh'd in too soon after rebuild
         time.sleep(30)
@@ -193,28 +189,67 @@
         self.assertTrue(ref_match or id_match)
 
         # SSH into the server to ensure it came back up
-        self._assert_ssh_password()
+        self._assert_ssh_password(generated_password)
 
         # make sure file is gone
-        self.assertEqual(self._read_file(filename), '')
+        self.assertEqual(self._read_file(FILENAME, generated_password), '')
+
+        # test again with a specified password
+        self._write_file(FILENAME, CONTENTS, generated_password)
+        _contents = self._read_file(FILENAME, generated_password)
+        self.assertEqual(_contents, CONTENTS)
+
+        specified_password = 'some_password'
+
+        # Make rebuild request
+        post_body = json.dumps({
+            'rebuild': {
+                'imageRef': self.image_ref,
+                'adminPass': specified_password,
+            }
+        })
+        url = '/servers/%s/action' % self.server_id
+        response, body = self.os.nova.request('POST', url, body=post_body)
+
+        # check output
+        self.assertEqual('202', response['status'])
+        rebuilt_server = json.loads(body)['server']
+        self.assertEqual(rebuilt_server['adminPass'], specified_password)
+
+        # Ensure correct status transition
+        # KNOWN-ISSUE
+        #self._wait_for_server_status(self.server_id, 'REBUILD')
+        self._wait_for_server_status(self.server_id, 'BUILD')
+        self._wait_for_server_status(self.server_id, 'ACTIVE')
+
+        # Treats an issue where we ssh'd in too soon after rebuild
+        time.sleep(30)
+
+        # Check that the instance's imageRef matches the new imageRef
+        server = self.os.nova.get_server(self.server_id)
+        ref_match = self.image_ref == server['image']['links'][0]['href']
+        id_match = self.image_ref == server['image']['id']
+        self.assertTrue(ref_match or id_match)
+
+        # SSH into the server to ensure it came back up
+        self._assert_ssh_password(specified_password)
+
+        # make sure file is gone
+        self.assertEqual(self._read_file(FILENAME, specified_password), '')
 
     @unittest.skipIf(not multi_node, 'Multiple compute nodes required')
     def test_resize_server_confirm(self):
         """Resize a server"""
         # Make resize request
-        post_body = json.dumps({
-            'resize' : {
-                'flavorRef': self.flavor_ref_alt,
-            }
-        })
+        post_body = json.dumps({'resize': {'flavorRef': self.flavor_ref_alt}})
         url = '/servers/%s/action' % self.server_id
         response, body = self.os.nova.request('POST', url, body=post_body)
 
         # Wait for status transition
         self.assertEqual('202', response['status'])
         # KNOWN-ISSUE
-        #self.os.nova.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
-        self.os.nova.wait_for_server_status(self.server_id, 'RESIZE-CONFIRM')
+        #self._wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
+        self._wait_for_server_status(self.server_id, 'RESIZE-CONFIRM')
 
         # Ensure API reports new flavor
         server = self.os.nova.get_server(self.server_id)
@@ -224,15 +259,13 @@
         self._assert_ssh_password()
 
         # Make confirmResize request
-        post_body = json.dumps({
-            'confirmResize' : 'null'
-        })
+        post_body = json.dumps({'confirmResize': 'null'})
         url = '/servers/%s/action' % self.server_id
         response, body = self.os.nova.request('POST', url, body=post_body)
 
         # Wait for status transition
         self.assertEqual('204', response['status'])
-        self.os.nova.wait_for_server_status(self.server_id, 'ACTIVE')
+        self._wait_for_server_status(self.server_id, 'ACTIVE')
 
         # Ensure API still reports new flavor
         server = self.os.nova.get_server(self.server_id)
@@ -243,19 +276,15 @@
         """Resize a server, then revert"""
 
         # Make resize request
-        post_body = json.dumps({
-            'resize' : {
-                'flavorRef': self.flavor_ref_alt,
-            }
-        })
+        post_body = json.dumps({'resize': {'flavorRef': self.flavor_ref_alt}})
         url = '/servers/%s/action' % self.server_id
         response, body = self.os.nova.request('POST', url, body=post_body)
 
         # Wait for status transition
         self.assertEqual('202', response['status'])
         # KNOWN-ISSUE
-        #self.os.nova.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
-        self.os.nova.wait_for_server_status(self.server_id, 'RESIZE-CONFIRM')
+        #self._wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
+        self._wait_for_server_status(self.server_id, 'RESIZE-CONFIRM')
 
         # SSH into the server to ensure it came back up
         self._assert_ssh_password()
@@ -265,15 +294,13 @@
         self.assertEqual(self.flavor_ref_alt, server['flavor']['id'])
 
         # Make revertResize request
-        post_body = json.dumps({
-            'revertResize' : 'null'
-        })
+        post_body = json.dumps({'revertResize': 'null'})
         url = '/servers/%s/action' % self.server_id
         response, body = self.os.nova.request('POST', url, body=post_body)
 
         # Assert status transition
         self.assertEqual('202', response['status'])
-        self.os.nova.wait_for_server_status(self.server_id, 'ACTIVE')
+        self._wait_for_server_status(self.server_id, 'ACTIVE')
 
         # Ensure flavor ref was reverted to original
         server = self.os.nova.get_server(self.server_id)
@@ -288,13 +315,14 @@
         self.image_ref = self.os.config.env.image_ref
         self.flavor_ref = self.os.config.env.flavor_ref
         self.ssh_timeout = self.os.config.nova.ssh_timeout
+        self.build_timeout = self.os.config.nova.build_timeout
 
-        self.server_name = 'testserver'
+        self.server_name = 'stacktester1'
 
         expected_server = {
-            'name' : self.server_name,
-            'imageRef' : self.image_ref,
-            'flavorRef' : self.flavor_ref,
+            'name': self.server_name,
+            'imageRef': self.image_ref,
+            'flavorRef': self.flavor_ref,
         }
 
         created_server = self.os.nova.create_server(expected_server)
@@ -303,9 +331,10 @@
     def tearDown(self):
         self.os.nova.delete_server(self.server_id)
 
-    def _wait_for_status(self, server_id, status):
+    def _wait_for_server_status(self, server_id, status):
         try:
-            self.os.nova.wait_for_server_status(server_id, status)
+            self.os.nova.wait_for_server_status(server_id, status,
+                                                timeout=self.build_timeout)
         except exceptions.TimeoutException:
             self.fail("Server failed to change status to %s" % status)
 
@@ -313,19 +342,17 @@
         """Create image from an existing server"""
 
         # Wait for server to come up before running this test
-        self._wait_for_status(self.server_id, 'ACTIVE')
+        self._wait_for_server_status(self.server_id, 'ACTIVE')
 
         # Create snapshot
-        image_data = {'name' : 'backup'}
+        image_data = {'name': 'backup'}
         req_body = json.dumps({'createImage': image_data})
         url = '/servers/%s/action' % self.server_id
         response, body = self.os.nova.request('POST', url, body=req_body)
-        print response
-        print body
 
         self.assertEqual(response['status'], '202')
         image_ref = response['location']
-        snapshot_id = image_ref.rsplit('/',1)[1]
+        snapshot_id = image_ref.rsplit('/', 1)[1]
 
         # Get snapshot and check its attributes
         resp, body = self.os.nova.request('GET', '/images/%s' % snapshot_id)
@@ -344,7 +371,7 @@
         """Ensure inability to snapshot server in BUILD state"""
 
         # Create snapshot
-        req_body = json.dumps({'createImage': {'name' : 'backup'}})
+        req_body = json.dumps({'createImage': {'name': 'backup'}})
         url = '/servers/%s/action' % self.server_id
         response, body = self.os.nova.request('POST', url, body=req_body)