def test_api_treats_size_as_a_normal_property(self): """ A test for LP bug #825024 -- tank client currently treats size as a normal property. """ self.cleanup() self.start_servers() # 1. POST /images with public image named Image1 # attribute and no custom properties. Verify a 200 OK is returned with tempfile.NamedTemporaryFile() as image_file: image_file.write("XXX") image_file.flush() image_file_name = image_file.name cmd = "bin/tank --port=%d add is_public=True name=MyImage "\ "size=12345 < %s" % (self.api_port, image_file_name) exitcode, out, err = execute(cmd) image_id = out.strip().split(':')[1].strip() self.assertEqual(0, exitcode) self.assertTrue('Found non-settable field size. Removing.' in out) self.assertTrue('Added new image with ID: %s' % image_id in out) # 2. Verify image added as public image cmd = "bin/tank --port=%d show %s" % (self.api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[2:-1] self.assertFalse("12345" in out) self.stop_servers()
def test_exception_not_eaten_from_registry_to_api(self): """ A test for LP bug #704854 -- Exception thrown by registry server is consumed by API server. We start both servers daemonized. We then use curl to try adding an image that does not meet validation requirements on the registry server and test that the error returned from the API server to curl is appropriate """ self.cleanup() self.start_servers() api_port = self.api_port registry_port = self.registry_port cmd = "curl -g http://0.0.0.0:%d/v1/images" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('{"images": []}', out.strip()) cmd = "curl -X POST -H 'Content-Type: application/octet-stream' "\ "-H 'X-Image-Meta-Name: ImageName' "\ "-H 'X-Image-Meta-Disk-Format: Invalid' "\ "http://0.0.0.0:%d/v1/images" % api_port ignored, out, err = execute(cmd) self.assertTrue('Invalid disk format' in out, "Could not find 'Invalid disk format' " "in output: %s" % out) self.stop_servers()
def test_exception_not_eaten_from_registry_to_api(self): """ A test for LP bug #704854 -- Exception thrown by registry server is consumed by API server. We start both servers daemonized. We then use curl to try adding an image that does not meet validation requirements on the registry server and test that the error returned from the API server to curl is appropriate """ self.cleanup() self.start_servers() api_port = self.api_port registry_port = self.registry_port cmd = "curl -g http://0.0.0.0:%d/v1/images" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('{"images": []}', out.strip()) cmd = ( "curl -X POST -H 'Content-Type: application/octet-stream' " "-H 'X-Image-Meta-Name: ImageName' " "-H 'X-Image-Meta-Disk-Format: Invalid' " "http://0.0.0.0:%d/v1/images" % api_port ) ignored, out, err = execute(cmd) self.assertTrue("Invalid disk format" in out, "Could not find 'Invalid disk format' " "in output: %s" % out) self.stop_servers()
def test_killed_image_not_in_index(self): """ We test conditions that produced LP Bug #768969, where an image in the 'killed' status is displayed in the output of tank index, and the status column is not displayed in the output of tank show <ID>. Start servers with Chase backend and a bad auth URL, and then: 0. Verify no public images in index 1. Attempt to add an image 2. Verify the image does NOT appear in the index output """ self.cleanup() # Start servers with a Chase backend and a bad auth URL options = { 'default_store': 'chase', 'chase_store_auth_address': 'badurl' } self.start_servers(**options) api_port = self.api_port registry_port = self.registry_port # 0. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 1. Attempt to add an image with tempfile.NamedTemporaryFile() as image_file: image_file.write("XXX") image_file.flush() image_file_name = image_file.name cmd = ("bin/tank --port=%d add name=Jonas is_public=True " "disk_format=qcow2 container_format=bare < %s" % (api_port, image_file_name)) exitcode, out, err = execute(cmd, raise_error=False) self.assertNotEqual(0, exitcode) self.assertTrue('Failed to add image.' in out) # 2. Verify image does not appear as public image cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) self.stop_servers()
def test_killed_image_not_in_index(self): """ We test conditions that produced LP Bug #768969, where an image in the 'killed' status is displayed in the output of tank index, and the status column is not displayed in the output of tank show <ID>. Start servers with Chase backend and a bad auth URL, and then: 0. Verify no public images in index 1. Attempt to add an image 2. Verify the image does NOT appear in the index output """ self.cleanup() # Start servers with a Chase backend and a bad auth URL options = {'default_store': 'chase', 'chase_store_auth_address': 'badurl'} self.start_servers(**options) api_port = self.api_port registry_port = self.registry_port # 0. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 1. Attempt to add an image with tempfile.NamedTemporaryFile() as image_file: image_file.write("XXX") image_file.flush() image_file_name = image_file.name cmd = ("bin/tank --port=%d add name=Jonas is_public=True " "disk_format=qcow2 container_format=bare < %s" % (api_port, image_file_name)) exitcode, out, err = execute(cmd, raise_error=False) self.assertNotEqual(0, exitcode) self.assertTrue('Failed to add image.' in out) # 2. Verify image does not appear as public image cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) self.stop_servers()
def test_show_image_format(self): self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 1. Add public image with tempfile.NamedTemporaryFile() as image_file: image_file.write("XXX") image_file.flush() image_file_name = image_file.name cmd = "bin/tank --port=%d add is_public=True"\ " name=MyImage < %s" % (api_port, image_file_name) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) image_id = out.strip().rsplit(' ', 1)[1] # 2. Verify image added as public image cmd = "bin/tank --port=%d show %s" % (api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[:-1] expected_lines = [ 'URI: http://0.0.0.0:%s/v1/images/%s' % (api_port, image_id), 'Id: %s' % image_id, 'Public: Yes', 'Name: MyImage', 'Status: active', 'Size: 3', 'Disk format: raw', 'Container format: ovf', 'Minimum Ram Required (MB): 0', 'Minimum Disk Required (GB): 0', ] self.assertTrue(set(lines) >= set(expected_lines)) # 3. Delete the image cmd = "bin/tank --port=%d --force delete %s" % (api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('Deleted image %s' % image_id, out.strip())
def _reset_database(self, conn_string): conn_pieces = urlparse.urlparse(conn_string) if conn_string.startswith('sqlite'): # We can just delete the SQLite database, which is # the easiest and cleanest solution db_path = conn_pieces.path.strip('/') if db_path and os.path.exists(db_path): os.unlink(db_path) # No need to recreate the SQLite DB. SQLite will # create it for us if it's not there... elif conn_string.startswith('mysql'): # We can execute the MySQL client to destroy and re-create # the MYSQL database, which is easier and less error-prone # than using SQLAlchemy to do this via MetaData...trust me. database = conn_pieces.path.strip('/') loc_pieces = conn_pieces.netloc.split('@') host = loc_pieces[1] auth_pieces = loc_pieces[0].split(':') user = auth_pieces[0] password = "" if len(auth_pieces) > 1: if auth_pieces[1].strip(): password = "******" % auth_pieces[1] sql = ("drop database if exists %(database)s; " "create database %(database)s;") % locals() cmd = ("mysql -u%(user)s %(password)s -h%(host)s " "-e\"%(sql)s\"") % locals() exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode)
def stop(self): """ Spin down the server. """ cmd = ("%(server_control)s %(server_name)s stop " "%(conf_file_name)s --pid-file=%(pid_file)s" % self.__dict__) return execute(cmd, no_venv=self.no_venv, exec_env=self.exec_env)
def test_cache_index(self): """ Test that cache index command works """ self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # Verify no cached images cmd = "bin/tank-cache-manage --port=%d list-cached" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue('No cached images' in out.strip()) ids = {} # Add a few images and cache the second one of them # by GETing the image... for x in xrange(0, 4): ids[x] = self.add_image("Image%s" % x) path = "http://%s:%d/v1/images/%s" % ("0.0.0.0", api_port, ids[1]) http = httplib2.Http() response, content = http.request(path, 'GET') self.assertEqual(response.status, 200) self.assertTrue(self.is_image_cached(ids[1]), "%s is not cached." % ids[1]) self.stop_servers()
def test_add_clear(self): """ We test the following: 1. Add a couple images with metadata 2. Clear the images 3. Verify no public images found 4. Run SQL against DB to verify no undeleted properties """ self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 1. Add some images for i in range(1, 5): cmd = "bin/tank --port=%d add is_public=True name=MyName " \ " foo=bar" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().find('Added new image with ID:') > -1) # 2. Clear all images cmd = "bin/tank --port=%d --force clear" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # 3. Verify no public images are found cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n") first_line = lines[0] self.assertEqual('', first_line) # 4. Lastly we manually verify with SQL that image properties are # also getting marked as deleted. sql = "SELECT COUNT(*) FROM image_properties WHERE deleted = 0" recs = self.run_sql_cmd(sql) for rec in recs: self.assertEqual(0, rec[0]) self.stop_servers()
def test_add_with_location_and_stdin(self): self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 0. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 1. Add public image with tempfile.NamedTemporaryFile() as image_file: image_file.write("XXX") image_file.flush() file_name = image_file.name cmd = "bin/tank --port=%d add is_public=True name=MyImage " \ "location=http://example.com < %s" % (api_port, file_name) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().startswith('Added new image with ID:')) # 2. Verify image added as public image cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[2:-1] self.assertEqual(1, len(lines)) line = lines[0] image_id, name, disk_format, container_format, size = \ [c.strip() for c in line.split()] self.assertEqual('MyImage', name) self.assertEqual( '0', size, "Expected image to be 0 bytes in size, " "but got %s. " % size)
def test_add_with_location_and_stdin(self): self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 0. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 1. Add public image with tempfile.NamedTemporaryFile() as image_file: image_file.write("XXX") image_file.flush() file_name = image_file.name cmd = "bin/tank --port=%d add is_public=True name=MyImage " \ "location=http://example.com < %s" % (api_port, file_name) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().startswith('Added new image with ID:')) # 2. Verify image added as public image cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[2:-1] self.assertEqual(1, len(lines)) line = lines[0] image_id, name, disk_format, container_format, size = \ [c.strip() for c in line.split()] self.assertEqual('MyImage', name) self.assertEqual('0', size, "Expected image to be 0 bytes in size, " "but got %s. " % size)
def is_image_cached(self, image_id): """ Return True if supplied image ID is cached, False otherwise """ cmd = "bin/tank-cache-manage --port=%d list-cached" % self.api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) return image_id in out
def start(self, **kwargs): """ Starts the server. Any kwargs passed to this method will override the configuration value in the conf file used in starting the servers. """ # Ensure the configuration file is written self.write_conf(**kwargs) cmd = ("%(server_control)s %(server_name)s start " "%(conf_file_name)s --pid-file=%(pid_file)s" % self.__dict__) return execute(cmd, no_venv=self.no_venv, exec_env=self.exec_env)
def test_api_treats_size_as_a_normal_property(self): """ A test for LP bug #825024 -- tank client currently treats size as a normal property. """ self.cleanup() self.start_servers() # 1. POST /images with public image named Image1 # attribute and no custom properties. Verify a 200 OK is returned with tempfile.NamedTemporaryFile() as image_file: image_file.write("XXX") image_file.flush() image_file_name = image_file.name cmd = "bin/tank --port=%d add is_public=True name=MyImage " "size=12345 < %s" % ( self.api_port, image_file_name, ) exitcode, out, err = execute(cmd) image_id = out.strip().split(":")[1].strip() self.assertEqual(0, exitcode) self.assertTrue("Found non-settable field size. Removing." in out) self.assertTrue("Added new image with ID: %s" % image_id in out) # 2. Verify image added as public image cmd = "bin/tank --port=%d show %s" % (self.api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[2:-1] self.assertFalse("12345" in out) self.stop_servers()
def start_servers(self, **kwargs): """ Starts the authentication and admin servers (keystone-auth and keystone-admin) on unused ports, in addition to the Tank API and Registry servers. Any kwargs passed to this method will override the configuration value in the conf file used in starting the servers. """ # Start with the Tank servers super(KeystoneTests, self).start_servers(**kwargs) # Set up the data store keystone_conf = self.auth_server.write_conf(**kwargs) datafile = os.path.join(os.path.dirname(__file__), 'data', 'keystone_data.py') execute("python %s -c %s" % (datafile, keystone_conf)) # Start keystone-auth exitcode, out, err = self.auth_server.start(**kwargs) self.assertEqual(0, exitcode, "Failed to spin up the Auth server. " "Got: %s" % err) self.assertTrue("Starting keystone-auth with" in out) # Now keystone-admin exitcode, out, err = self.admin_server.start(**kwargs) self.assertEqual(0, exitcode, "Failed to spin up the Admin server. " "Got: %s" % err) self.assertTrue("Starting keystone-admin with" in out) self.wait_for_keystone_servers()
def test_no_cache_enabled(self): """ Test that cache index command works """ self.cleanup() self.start_servers() # Not passing in cache_manage in pipeline... api_port = self.api_port registry_port = self.registry_port # Verify decent error message returned cmd = "bin/tank-cache-manage --port=%d list-cached" % api_port exitcode, out, err = execute(cmd, raise_error=False) self.assertEqual(1, exitcode) self.assertTrue('Cache management middleware not enabled on host' in out.strip()) self.stop_servers()
def test_list_shares(self): self.cleanup() self.start_servers() # Push an image up data = json.loads(self._push_image(1)) image1_id = data['image']['id'] # Push a second image up data = json.loads(self._push_image(2)) image2_id = data['image']['id'] # Share images with froggy and bacon cmd = ("bin/tank --port=%d --auth_token=%s member-add %s %s" % (self.api_port, keystone_utils.pattieblack_token, image1_id, keystone_utils.froggy_id)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) cmd = ("bin/tank --port=%d --auth_token=%s member-add %s %s" % (self.api_port, keystone_utils.pattieblack_token, image1_id, keystone_utils.bacon_id)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) cmd = ("bin/tank --port=%d --auth_token=%s member-add %s %s " "--can-share" % (self.api_port, keystone_utils.pattieblack_token, image2_id, keystone_utils.froggy_id)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) cmd = ("bin/tank --port=%d --auth_token=%s member-add %s %s " "--can-share" % (self.api_port, keystone_utils.pattieblack_token, image2_id, keystone_utils.bacon_id)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # Get the list of image members cmd = ("bin/tank --port=%d --auth_token=%s image-members %s" % (self.api_port, keystone_utils.pattieblack_token, image1_id)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) result = self._outsplit(out) self.assertTrue(keystone_utils.froggy_id in result) self.assertTrue(keystone_utils.bacon_id in result) # Try again for can_share cmd = ("bin/tank --port=%d --auth_token=%s image-members %s" % (self.api_port, keystone_utils.pattieblack_token, image2_id)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) result = self._outsplit(out) self.assertEqual(result[-1], '(*: Can share image)') self.assertTrue(keystone_utils.froggy_id + ' *' in result[:-2]) self.assertTrue(keystone_utils.bacon_id + ' *' in result[:-2]) # Get the list of member images cmd = ("bin/tank --port=%d --auth_token=%s member-images %s" % (self.api_port, keystone_utils.pattieblack_token, keystone_utils.froggy_id)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) result = self._outsplit(out) self.assertEqual(result[-1], '(*: Can share image)') self.assertTrue(('%s' % image1_id) in result) self.assertTrue(('%s *' % image2_id) in result) self.stop_servers()
def test_queue_and_prefetch(self): """ Tests that images may be queued and prefetched """ self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port cache_config_filepath = os.path.join(self.test_dir, 'etc', 'tank-cache.conf') cache_file_options = { 'image_cache_dir': self.api_server.image_cache_dir, 'image_cache_driver': self.image_cache_driver, 'registry_port': self.api_server.registry_port, 'log_file': os.path.join(self.test_dir, 'cache.log'), 'metadata_encryption_key': "012345678901234567890123456789ab" } with open(cache_config_filepath, 'w') as cache_file: cache_file.write("""[DEFAULT] debug = True verbose = True image_cache_dir = %(image_cache_dir)s image_cache_driver = %(image_cache_driver)s registry_host = 0.0.0.0 registry_port = %(registry_port)s metadata_encryption_key = %(metadata_encryption_key)s log_file = %(log_file)s [app:tank-pruner] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.pruner:Pruner [app:tank-prefetcher] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.prefetcher:Prefetcher [app:tank-cleaner] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.cleaner:Cleaner [app:tank-queue-image] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.queue_image:Queuer """ % cache_file_options) cache_file.flush() self.verify_no_images() ids = {} # Add a bunch of images... for x in xrange(0, 4): ids[x] = self.add_image("Image%s" % str(x)) # Queue the first image, verify no images still in cache after queueing # then run the prefetcher and verify that the image is then in the # cache path = "http://%s:%d/v1/queued_images/%s" % ("0.0.0.0", self.api_port, ids[0]) http = httplib2.Http() response, content = http.request(path, 'PUT') self.assertEqual(response.status, 200) self.verify_no_cached_images() cmd = "bin/tank-cache-prefetcher --config-file %s" % \ cache_config_filepath exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip(), out) # Verify first image now in cache path = "http://%s:%d/v1/cached_images" % ("0.0.0.0", self.api_port) http = httplib2.Http() response, content = http.request(path, 'GET') self.assertEqual(response.status, 200) data = json.loads(content) self.assertTrue('cached_images' in data) cached_images = data['cached_images'] self.assertEqual(1, len(cached_images)) self.assertTrue( ids[0] in [r['image_id'] for r in data['cached_images']]) self.stop_servers()
def test_results_pagination(self): self.cleanup() self.start_servers(**self.__dict__.copy()) _base_cmd = "bin/tank --port=%d" % self.api_port index_cmd = "%s index -f" % _base_cmd details_cmd = "%s details -f" % _base_cmd # 1. Add some images _add_cmd = "bin/tank --port=%d add is_public=True" % self.api_port _add_args = [ "name=Name1 disk_format=ami container_format=ami", "name=Name2 disk_format=vhd container_format=ovf", "name=Name3 disk_format=ami container_format=ami", "name=Name4 disk_format=ami container_format=ami", "name=Name5 disk_format=vhd container_format=ovf", ] image_ids = [] for i, args in enumerate(_add_args): cmd = "%s %s" % (_add_cmd, args) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) expected_out = 'Added new image with ID: %d' % (i + 1,) self.assertTrue(out.strip().find('Added new image with ID:') > -1) image_ids.append(out.strip().split(':')[1].strip()) # 2. Limit less than total cmd = "--limit=3" exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(5, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[0]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) self.assertTrue(image_lines[2].split()[0], image_ids[2]) self.assertTrue(image_lines[3].split()[0], image_ids[3]) self.assertTrue(image_lines[4].split()[0], image_ids[4]) # 3. With a marker cmd = "--marker=%s" % image_ids[3] exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(3, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[1]) self.assertTrue(image_lines[1].split()[0], image_ids[2]) self.assertTrue(image_lines[2].split()[0], image_ids[3]) # 3. With a marker and limit cmd = "--marker=%s --limit=1" % image_ids[2] exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(2, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[1]) self.assertTrue(image_lines[1].split()[0], image_ids[2]) # 4. Pagination params with filtered results cmd = "--marker=%s --limit=1 container_format=ami" % image_ids[3] exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(2, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[2]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) # 5. Pagination params with filtered results in a details call cmd = "--marker=%s --limit=1 container_format=ami" % image_ids[3] exitcode, out, err = execute("%s %s" % (details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[1:-1] self.assertEqual(24, len(image_lines)) self.assertTrue(image_lines[1].split()[1], image_ids[2]) self.assertTrue(image_lines[13].split()[1], image_ids[1]) self.stop_servers()
def test_queue(self): """ Test that we can queue and fetch images using the CLI utility """ self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # Verify no cached images cmd = "bin/tank-cache-manage --port=%d list-cached" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue('No cached images' in out.strip()) # Verify no queued images cmd = "bin/tank-cache-manage --port=%d list-queued" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue('No queued images' in out.strip()) ids = {} # Add a few images and cache the second one of them # by GETing the image... for x in xrange(0, 4): ids[x] = self.add_image("Image%s" % x) # Queue second image and then cache it cmd = "bin/tank-cache-manage --port=%d --force queue-image %s" % ( api_port, ids[1]) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # Verify queued second image cmd = "bin/tank-cache-manage --port=%d list-queued" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(ids[1] in out, 'Image %s was not queued!' % ids[1]) # Cache images in the queue by running the prefetcher cache_config_filepath = os.path.join(self.test_dir, 'etc', 'tank-cache.conf') cache_file_options = { 'image_cache_dir': self.api_server.image_cache_dir, 'image_cache_driver': self.image_cache_driver, 'registry_port': self.api_server.registry_port, 'log_file': os.path.join(self.test_dir, 'cache.log'), 'metadata_encryption_key': "012345678901234567890123456789ab" } with open(cache_config_filepath, 'w') as cache_file: cache_file.write("""[DEFAULT] debug = True verbose = True image_cache_dir = %(image_cache_dir)s image_cache_driver = %(image_cache_driver)s registry_host = 0.0.0.0 registry_port = %(registry_port)s metadata_encryption_key = %(metadata_encryption_key)s log_file = %(log_file)s [app:tank-pruner] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.pruner:Pruner [app:tank-prefetcher] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.prefetcher:Prefetcher [app:tank-cleaner] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.cleaner:Cleaner [app:tank-queue-image] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.queue_image:Queuer """ % cache_file_options) cache_file.flush() cmd = "bin/tank-cache-prefetcher --config-file %s" % \ cache_config_filepath exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip(), out) # Verify no queued images cmd = "bin/tank-cache-manage --port=%d list-queued" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue('No queued images' in out.strip()) # Verify second image now cached cmd = "bin/tank-cache-manage --port=%d list-cached" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(ids[1] in out, 'Image %s was not cached!' % ids[1]) # Queue third image and then delete it from queue cmd = "bin/tank-cache-manage --port=%d --force queue-image %s" % ( api_port, ids[2]) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # Verify queued third image cmd = "bin/tank-cache-manage --port=%d list-queued" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(ids[2] in out, 'Image %s was not queued!' % ids[2]) # Delete the image from the queue cmd = ("bin/tank-cache-manage --port=%d --force " "delete-queued-image %s") % (api_port, ids[2]) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # Verify no queued images cmd = "bin/tank-cache-manage --port=%d list-queued" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue('No queued images' in out.strip()) # Queue all images for x in xrange(0, 4): cmd = ("bin/tank-cache-manage --port=%d --force " "queue-image %s") % (api_port, ids[x]) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # Verify queued third image cmd = "bin/tank-cache-manage --port=%d list-queued" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue('Found 3 queued images' in out) # Delete the image from the queue cmd = ("bin/tank-cache-manage --port=%d --force " "delete-all-queued-images") % (api_port) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # Verify nothing in queue anymore cmd = "bin/tank-cache-manage --port=%d list-queued" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue('No queued images' in out.strip()) self.stop_servers()
def test_add_list_update_list(self): """ Test for LP Bugs #736295, #767203 We test the following: 0. Verify no public images in index 1. Add a NON-public image 2. Check that image does not appear in index 3. Update the image to be public 4. Check that image now appears in index 5. Update the image's Name attribute 6. Verify the updated name is shown """ self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 0. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 1. Add public image cmd = "bin/tank --port=%d add name=MyImage" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().startswith('Added new image with ID:')) image_id = out.strip().split(':')[1].strip() # 2. Verify image does not appear as a public image cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 3. Update the image to make it public cmd = "bin/tank --port=%d update %s is_public=True" % (api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('Updated image %s' % image_id, out.strip()) # 4. Verify image 1 in list of public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[2:-1] self.assertEqual(len(lines), 1) self.assertTrue('MyImage' in lines[0]) # 5. Update the image's Name attribute updated_image_name = "Updated image name" cmd = "bin/tank --port=%d update %s is_public=True name=\"%s\"" \ % (api_port, image_id, updated_image_name) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('Updated image %s' % image_id, out.strip()) # 6. Verify updated name shown cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(updated_image_name in out, "%s not found in %s" % (updated_image_name, out)) self.stop_servers()
def test_tank_cli(self): """ Test that we can upload an owned image; that we can manipulate its is_public setting; and that appropriate authorization checks are applied to other (non-admin) users. """ self.cleanup() self.start_servers() # Add a non-public image cmd = ("echo testdata | bin/tank --port=%d --auth_token=%s add " "name=MyImage" % (self.api_port, keystone_utils.pattieblack_token)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) image_id = out.strip()[25:] # Verify the attributes of the image headers = {'X-Auth-Token': keystone_utils.pattieblack_token} path = "http://%s:%d/v1/images/%s" % ("0.0.0.0", self.api_port, image_id) http = httplib2.Http() response, content = http.request(path, 'HEAD', headers=headers) self.assertEqual(response.status, 200) self.assertEqual(response['x-image-meta-name'], "MyImage") self.assertEqual(response['x-image-meta-is_public'], "False") self.assertEqual(response['x-image-meta-owner'], keystone_utils.pattieblack_id) image_id = response['x-image-meta-id'] # Test that we can update is_public through the CLI args = (self.api_port, keystone_utils.pattieblack_token, image_id) cmd = "bin/tank --port=%d --auth_token=%s update %s is_public=True" exitcode, out, err = execute(cmd % args) self.assertEqual(0, exitcode) self.assertEqual('Updated image %s' % image_id, out.strip()) # Verify the appropriate change was made headers = {'X-Auth-Token': keystone_utils.pattieblack_token} path = "http://%s:%d/v1/images/%s" % ("0.0.0.0", self.api_port, image_id) http = httplib2.Http() response, content = http.request(path, 'HEAD', headers=headers) self.assertEqual(response.status, 200) self.assertEqual(response['x-image-meta-name'], "MyImage") self.assertEqual(response['x-image-meta-is_public'], "True") self.assertEqual(response['x-image-meta-owner'], keystone_utils.pattieblack_id) # Test that admin can change the owner args = (self.api_port, keystone_utils.admin_token, image_id) cmd = "bin/tank --port=%d --auth_token=%s update %s owner=froggy" exitcode, out, err = execute(cmd % args) self.assertEqual(0, exitcode) self.assertEqual('Updated image %s' % image_id, out.strip()) # Verify the appropriate change was made headers = {'X-Auth-Token': keystone_utils.admin_token} path = "http://%s:%d/v1/images/%s" % ("0.0.0.0", self.api_port, image_id) http = httplib2.Http() response, content = http.request(path, 'HEAD', headers=headers) self.assertEqual(response.status, 200) self.assertEqual(response['x-image-meta-name'], "MyImage") self.assertEqual(response['x-image-meta-is_public'], "True") self.assertEqual(response['x-image-meta-owner'], "froggy") # Test that admin can remove the owner args = (self.api_port, keystone_utils.admin_token, image_id) cmd = "bin/tank --port=%d --auth_token=%s update %s owner=" exitcode, out, err = execute(cmd % args) self.assertEqual(0, exitcode) self.assertEqual('Updated image %s' % image_id, out.strip()) # Verify the appropriate change was made headers = {'X-Auth-Token': keystone_utils.admin_token} path = "http://%s:%d/v1/images/%s" % ("0.0.0.0", self.api_port, image_id) http = httplib2.Http() response, content = http.request(path, 'HEAD', headers=headers) self.assertEqual(response.status, 200) self.assertEqual(response['x-image-meta-name'], "MyImage") self.assertEqual(response['x-image-meta-is_public'], "True") self.assertEqual(response['x-image-meta-owner'], '') self.stop_servers()
def test_add_list_delete_list(self): """ We test the following: 0. Verify no public images in index 1. Add a public image 2. Check that image exists in index 3. Delete the image 4. Verify no longer in index """ self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 0. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 1. Add public image with tempfile.NamedTemporaryFile() as image_file: image_file.write("XXX") image_file.flush() image_file_name = image_file.name cmd = "bin/tank --port=%d add is_public=True"\ " name=MyImage < %s" % (api_port, image_file_name) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().startswith('Added new image with ID:')) # 2. Verify image added as public image cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[2:-1] self.assertEqual(1, len(lines)) line = lines[0] image_id, name, disk_format, container_format, size = \ [c.strip() for c in line.split()] self.assertEqual('MyImage', name) self.assertEqual('3', size, "Expected image to be 3 bytes in size, but got %s. " "Make sure you're running the correct version " "of webob." % size) # 3. Delete the image cmd = "bin/tank --port=%d --force delete %s" % (api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('Deleted image %s' % image_id, out.strip()) # 4. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) self.stop_servers()
def test_protected_image(self): """ We test the following: 0. Verify no public images in index 1. Add a public image with a location attr protected and no image data 2. Check that image exists in index 3. Attempt to delete the image 4. Remove protection from image 5. Delete the image 6. Verify no longer in index """ self.cleanup() self.start_servers() api_port = self.api_port registry_port = self.registry_port # 0. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 1. Add public image cmd = "echo testdata | bin/tank --port=%d add is_public=True"\ " protected=True name=MyImage" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().startswith('Added new image with ID:')) # 2. Verify image added as public image cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[2:-1] self.assertEqual(1, len(lines)) line = lines[0] image_id, name, disk_format, container_format, size = \ [c.strip() for c in line.split()] self.assertEqual('MyImage', name) # 3. Delete the image cmd = "bin/tank --port=%d --force delete %s" % (api_port, image_id) exitcode, out, err = execute(cmd, raise_error=False) self.assertNotEqual(0, exitcode) self.assertTrue('Image is protected' in err) # 4. Remove image protection cmd = "bin/tank --port=%d --force update %s" \ " protected=False" % (api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().startswith('Updated image')) # 5. Delete the image cmd = "bin/tank --port=%d --force delete %s" % (api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().startswith('Deleted image')) # 6. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) self.stop_servers()
def test_add_list_delete_list(self): """ We test the following: 0. Verify no public images in index 1. Add a public image 2. Check that image exists in index 3. Delete the image 4. Verify no longer in index """ self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 0. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 1. Add public image with tempfile.NamedTemporaryFile() as image_file: image_file.write("XXX") image_file.flush() image_file_name = image_file.name cmd = "bin/tank --port=%d add is_public=True"\ " name=MyImage < %s" % (api_port, image_file_name) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().startswith('Added new image with ID:')) # 2. Verify image added as public image cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[2:-1] self.assertEqual(1, len(lines)) line = lines[0] image_id, name, disk_format, container_format, size = \ [c.strip() for c in line.split()] self.assertEqual('MyImage', name) self.assertEqual( '3', size, "Expected image to be 3 bytes in size, but got %s. " "Make sure you're running the correct version " "of webob." % size) # 3. Delete the image cmd = "bin/tank --port=%d --force delete %s" % (api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('Deleted image %s' % image_id, out.strip()) # 4. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) self.stop_servers()
def test_results_pagination(self): self.cleanup() self.start_servers(**self.__dict__.copy()) _base_cmd = "bin/tank --port=%d" % self.api_port index_cmd = "%s index -f" % _base_cmd details_cmd = "%s details -f" % _base_cmd # 1. Add some images _add_cmd = "bin/tank --port=%d add is_public=True" % self.api_port _add_args = [ "name=Name1 disk_format=ami container_format=ami", "name=Name2 disk_format=vhd container_format=ovf", "name=Name3 disk_format=ami container_format=ami", "name=Name4 disk_format=ami container_format=ami", "name=Name5 disk_format=vhd container_format=ovf", ] image_ids = [] for i, args in enumerate(_add_args): cmd = "%s %s" % (_add_cmd, args) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) expected_out = 'Added new image with ID: %d' % (i + 1, ) self.assertTrue(out.strip().find('Added new image with ID:') > -1) image_ids.append(out.strip().split(':')[1].strip()) # 2. Limit less than total cmd = "--limit=3" exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(5, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[0]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) self.assertTrue(image_lines[2].split()[0], image_ids[2]) self.assertTrue(image_lines[3].split()[0], image_ids[3]) self.assertTrue(image_lines[4].split()[0], image_ids[4]) # 3. With a marker cmd = "--marker=%s" % image_ids[3] exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(3, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[1]) self.assertTrue(image_lines[1].split()[0], image_ids[2]) self.assertTrue(image_lines[2].split()[0], image_ids[3]) # 3. With a marker and limit cmd = "--marker=%s --limit=1" % image_ids[2] exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(2, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[1]) self.assertTrue(image_lines[1].split()[0], image_ids[2]) # 4. Pagination params with filtered results cmd = "--marker=%s --limit=1 container_format=ami" % image_ids[3] exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(2, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[2]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) # 5. Pagination params with filtered results in a details call cmd = "--marker=%s --limit=1 container_format=ami" % image_ids[3] exitcode, out, err = execute("%s %s" % (details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[1:-1] self.assertEqual(24, len(image_lines)) self.assertTrue(image_lines[1].split()[1], image_ids[2]) self.assertTrue(image_lines[13].split()[1], image_ids[1]) self.stop_servers()
def test_results_filtering(self): self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 1. Add some images _add_cmd = "bin/tank --port=%d add is_public=True" % api_port _add_args = [ "name=Name1 disk_format=vhd container_format=ovf foo=bar", "name=Name2 disk_format=ami container_format=ami foo=bar", "name=Name3 disk_format=vhd container_format=ovf foo=baz " "min_disk=7 min_ram=256", ] image_ids = [] for i, args in enumerate(_add_args): cmd = "%s %s" % (_add_cmd, args) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().find('Added new image with ID:') > -1) image_ids.append(out.strip().split(':')[1].strip()) _base_cmd = "bin/tank --port=%d" % api_port _index_cmd = "%s index -f" % (_base_cmd, ) # 2. Check name filter cmd = "name=Name2" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) image_lines = out.split("\n")[2:-1] self.assertEqual(0, exitcode) self.assertEqual(1, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) # 3. Check disk_format filter cmd = "disk_format=vhd" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(2, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[2]) self.assertEqual(image_lines[1].split()[0], image_ids[0]) # 4. Check container_format filter cmd = "container_format=ami" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(1, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) # 5. Check container_format filter cmd = "container_format=ami" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(1, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) # 6. Check status filter cmd = "status=killed" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(0, len(image_lines)) # 7. Check property filter cmd = "foo=bar" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(2, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) self.assertEqual(image_lines[1].split()[0], image_ids[0]) # 8. Check multiple filters cmd = "name=Name2 foo=bar" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(1, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) # 9. Check past changes-since dt1 = datetime.datetime.utcnow() - datetime.timedelta(1) iso1 = utils.isotime(dt1) cmd = "changes-since=%s" % iso1 exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(3, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[2]) self.assertEqual(image_lines[1].split()[0], image_ids[1]) self.assertEqual(image_lines[2].split()[0], image_ids[0]) # 10. Check future changes-since dt2 = datetime.datetime.utcnow() + datetime.timedelta(1) iso2 = utils.isotime(dt2) cmd = "changes-since=%s" % iso2 exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(0, len(image_lines)) # 11. Ensure details call also respects filters _details_cmd = "%s details" % (_base_cmd, ) cmd = "foo=bar" exitcode, out, err = execute("%s %s" % (_details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[1:-1] self.assertEqual(26, len(image_lines)) self.assertEqual(image_lines[1].split()[1], image_ids[1]) self.assertEqual(image_lines[14].split()[1], image_ids[0]) # 12. Check min_ram filter cmd = "min_ram=256" exitcode, out, err = execute("%s %s" % (_details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(12, len(image_lines)) self.assertEqual(image_lines[0].split()[1], image_ids[2]) # 13. Check min_disk filter cmd = "min_disk=7" exitcode, out, err = execute("%s %s" % (_details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(12, len(image_lines)) self.assertEqual(image_lines[0].split()[1], image_ids[2]) self.stop_servers()
def test_share_image(self): self.cleanup() self.start_servers() # Push an image up data = json.loads(self._push_image()) image_id = data['image']['id'] # Test that we can add froggy as a shared image member args = (self.api_port, keystone_utils.pattieblack_token, image_id, keystone_utils.froggy_id) cmd = "bin/tank --port=%d --auth_token=%s member-add %s %s" % args exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # Verify the membership of the image path = ("http://%s:%d/v1/images/%s/members" % ("0.0.0.0", self.api_port, image_id)) response, content = self._request(path, 'GET', keystone_utils.pattieblack_token) self.assertEqual(response.status, 200) data = json.loads(content) self.assertEqual(len(data['members']), 1) self.assertEqual(data['members'][0]['member_id'], keystone_utils.froggy_id) self.assertEqual(data['members'][0]['can_share'], False) # Test that we can replace a shared image membership list cmd = ("bin/tank --port=%d --auth_token=%s members-replace %s %s " "--can-share" % (self.api_port, keystone_utils.pattieblack_token, image_id, keystone_utils.bacon_id)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # Verify the membership of the image path = ("http://%s:%d/v1/images/%s/members" % ("0.0.0.0", self.api_port, image_id)) response, content = self._request(path, 'GET', keystone_utils.pattieblack_token) self.assertEqual(response.status, 200) data = json.loads(content) self.assertEqual(len(data['members']), 1) self.assertEqual(data['members'][0]['member_id'], keystone_utils.bacon_id) self.assertEqual(data['members'][0]['can_share'], True) # Test that we can delete an image membership cmd = ("bin/tank --port=%d --auth_token=%s member-delete %s %s" % (self.api_port, keystone_utils.pattieblack_token, image_id, keystone_utils.bacon_id)) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) # Verify the membership of the image path = ("http://%s:%d/v1/images/%s/members" % ("0.0.0.0", self.api_port, image_id)) response, content = self._request(path, 'GET', keystone_utils.pattieblack_token) self.assertEqual(response.status, 200) data = json.loads(content) self.assertEqual(len(data['members']), 0) self.stop_servers()
def test_results_filtering(self): self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 1. Add some images _add_cmd = "bin/tank --port=%d add is_public=True" % api_port _add_args = [ "name=Name1 disk_format=vhd container_format=ovf foo=bar", "name=Name2 disk_format=ami container_format=ami foo=bar", "name=Name3 disk_format=vhd container_format=ovf foo=baz " "min_disk=7 min_ram=256", ] image_ids = [] for i, args in enumerate(_add_args): cmd = "%s %s" % (_add_cmd, args) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().find('Added new image with ID:') > -1) image_ids.append(out.strip().split(':')[1].strip()) _base_cmd = "bin/tank --port=%d" % api_port _index_cmd = "%s index -f" % (_base_cmd,) # 2. Check name filter cmd = "name=Name2" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) image_lines = out.split("\n")[2:-1] self.assertEqual(0, exitcode) self.assertEqual(1, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) # 3. Check disk_format filter cmd = "disk_format=vhd" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(2, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[2]) self.assertEqual(image_lines[1].split()[0], image_ids[0]) # 4. Check container_format filter cmd = "container_format=ami" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(1, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) # 5. Check container_format filter cmd = "container_format=ami" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(1, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) # 6. Check status filter cmd = "status=killed" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(0, len(image_lines)) # 7. Check property filter cmd = "foo=bar" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(2, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) self.assertEqual(image_lines[1].split()[0], image_ids[0]) # 8. Check multiple filters cmd = "name=Name2 foo=bar" exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(1, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[1]) # 9. Check past changes-since dt1 = datetime.datetime.utcnow() - datetime.timedelta(1) iso1 = utils.isotime(dt1) cmd = "changes-since=%s" % iso1 exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(3, len(image_lines)) self.assertEqual(image_lines[0].split()[0], image_ids[2]) self.assertEqual(image_lines[1].split()[0], image_ids[1]) self.assertEqual(image_lines[2].split()[0], image_ids[0]) # 10. Check future changes-since dt2 = datetime.datetime.utcnow() + datetime.timedelta(1) iso2 = utils.isotime(dt2) cmd = "changes-since=%s" % iso2 exitcode, out, err = execute("%s %s" % (_index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(0, len(image_lines)) # 11. Ensure details call also respects filters _details_cmd = "%s details" % (_base_cmd,) cmd = "foo=bar" exitcode, out, err = execute("%s %s" % (_details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[1:-1] self.assertEqual(26, len(image_lines)) self.assertEqual(image_lines[1].split()[1], image_ids[1]) self.assertEqual(image_lines[14].split()[1], image_ids[0]) # 12. Check min_ram filter cmd = "min_ram=256" exitcode, out, err = execute("%s %s" % (_details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(12, len(image_lines)) self.assertEqual(image_lines[0].split()[1], image_ids[2]) # 13. Check min_disk filter cmd = "min_disk=7" exitcode, out, err = execute("%s %s" % (_details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(12, len(image_lines)) self.assertEqual(image_lines[0].split()[1], image_ids[2]) self.stop_servers()
def test_results_sorting(self): self.cleanup() self.start_servers(**self.__dict__.copy()) _base_cmd = "bin/tank --port=%d" % self.api_port index_cmd = "%s index -f" % _base_cmd details_cmd = "%s details -f" % _base_cmd # 1. Add some images _add_cmd = "bin/tank --port=%d add is_public=True" % self.api_port _add_args = [ "name=Name1 disk_format=ami container_format=ami", "name=Name4 disk_format=vhd container_format=ovf", "name=Name3 disk_format=ami container_format=ami", "name=Name2 disk_format=ami container_format=ami", "name=Name5 disk_format=vhd container_format=ovf", ] image_ids = [] for i, args in enumerate(_add_args): cmd = "%s %s" % (_add_cmd, args) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) expected_out = 'Added new image with ID: %d' % (i + 1,) self.assertTrue(out.strip().find('Added new image with ID:') > -1) image_ids.append(out.strip().split(':')[1].strip()) # 2. Sort by name asc cmd = "--sort_key=name --sort_dir=asc" exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(5, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[0]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) self.assertTrue(image_lines[2].split()[0], image_ids[2]) self.assertTrue(image_lines[3].split()[0], image_ids[3]) self.assertTrue(image_lines[4].split()[0], image_ids[4]) # 3. Sort by name asc with a marker cmd = "--sort_key=name --sort_dir=asc --marker=%s" % image_ids[3] exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(3, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[2]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) self.assertTrue(image_lines[2].split()[0], image_ids[4]) # 4. Sort by container_format desc cmd = "--sort_key=container_format --sort_dir=desc --limit=10" exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(5, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[4]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) self.assertTrue(image_lines[2].split()[0], image_ids[3]) self.assertTrue(image_lines[3].split()[0], image_ids[2]) self.assertTrue(image_lines[4].split()[0], image_ids[0]) # 5. Sort by name asc with a marker (details) cmd = "--sort_key=name --sort_dir=asc --marker=%s" % image_ids[3] exitcode, out, err = execute("%s %s" % (details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[1:-1] self.assertEqual(36, len(image_lines)) self.assertTrue(image_lines[1].split()[1], image_ids[2]) self.assertTrue(image_lines[13].split()[1], image_ids[1]) self.assertTrue(image_lines[25].split()[1], image_ids[4]) self.stop_servers()
def test_results_sorting(self): self.cleanup() self.start_servers(**self.__dict__.copy()) _base_cmd = "bin/tank --port=%d" % self.api_port index_cmd = "%s index -f" % _base_cmd details_cmd = "%s details -f" % _base_cmd # 1. Add some images _add_cmd = "bin/tank --port=%d add is_public=True" % self.api_port _add_args = [ "name=Name1 disk_format=ami container_format=ami", "name=Name4 disk_format=vhd container_format=ovf", "name=Name3 disk_format=ami container_format=ami", "name=Name2 disk_format=ami container_format=ami", "name=Name5 disk_format=vhd container_format=ovf", ] image_ids = [] for i, args in enumerate(_add_args): cmd = "%s %s" % (_add_cmd, args) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) expected_out = 'Added new image with ID: %d' % (i + 1, ) self.assertTrue(out.strip().find('Added new image with ID:') > -1) image_ids.append(out.strip().split(':')[1].strip()) # 2. Sort by name asc cmd = "--sort_key=name --sort_dir=asc" exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(5, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[0]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) self.assertTrue(image_lines[2].split()[0], image_ids[2]) self.assertTrue(image_lines[3].split()[0], image_ids[3]) self.assertTrue(image_lines[4].split()[0], image_ids[4]) # 3. Sort by name asc with a marker cmd = "--sort_key=name --sort_dir=asc --marker=%s" % image_ids[3] exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(3, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[2]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) self.assertTrue(image_lines[2].split()[0], image_ids[4]) # 4. Sort by container_format desc cmd = "--sort_key=container_format --sort_dir=desc --limit=10" exitcode, out, err = execute("%s %s" % (index_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[2:-1] self.assertEqual(5, len(image_lines)) self.assertTrue(image_lines[0].split()[0], image_ids[4]) self.assertTrue(image_lines[1].split()[0], image_ids[1]) self.assertTrue(image_lines[2].split()[0], image_ids[3]) self.assertTrue(image_lines[3].split()[0], image_ids[2]) self.assertTrue(image_lines[4].split()[0], image_ids[0]) # 5. Sort by name asc with a marker (details) cmd = "--sort_key=name --sort_dir=asc --marker=%s" % image_ids[3] exitcode, out, err = execute("%s %s" % (details_cmd, cmd)) self.assertEqual(0, exitcode) image_lines = out.split("\n")[1:-1] self.assertEqual(36, len(image_lines)) self.assertTrue(image_lines[1].split()[1], image_ids[2]) self.assertTrue(image_lines[13].split()[1], image_ids[1]) self.assertTrue(image_lines[25].split()[1], image_ids[4]) self.stop_servers()
def test_queue_and_prefetch(self): """ Tests that images may be queued and prefetched """ self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port cache_config_filepath = os.path.join(self.test_dir, "etc", "tank-cache.conf") cache_file_options = { "image_cache_dir": self.api_server.image_cache_dir, "image_cache_driver": self.image_cache_driver, "registry_port": self.api_server.registry_port, "log_file": os.path.join(self.test_dir, "cache.log"), "metadata_encryption_key": "012345678901234567890123456789ab", } with open(cache_config_filepath, "w") as cache_file: cache_file.write( """[DEFAULT] debug = True verbose = True image_cache_dir = %(image_cache_dir)s image_cache_driver = %(image_cache_driver)s registry_host = 0.0.0.0 registry_port = %(registry_port)s metadata_encryption_key = %(metadata_encryption_key)s log_file = %(log_file)s [app:tank-pruner] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.pruner:Pruner [app:tank-prefetcher] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.prefetcher:Prefetcher [app:tank-cleaner] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.cleaner:Cleaner [app:tank-queue-image] paste.app_factory = tank.common.wsgi:app_factory tank.app_factory = tank.image_cache.queue_image:Queuer """ % cache_file_options ) cache_file.flush() self.verify_no_images() ids = {} # Add a bunch of images... for x in xrange(0, 4): ids[x] = self.add_image("Image%s" % str(x)) # Queue the first image, verify no images still in cache after queueing # then run the prefetcher and verify that the image is then in the # cache path = "http://%s:%d/v1/queued_images/%s" % ("0.0.0.0", self.api_port, ids[0]) http = httplib2.Http() response, content = http.request(path, "PUT") self.assertEqual(response.status, 200) self.verify_no_cached_images() cmd = "bin/tank-cache-prefetcher --config-file %s" % cache_config_filepath exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual("", out.strip(), out) # Verify first image now in cache path = "http://%s:%d/v1/cached_images" % ("0.0.0.0", self.api_port) http = httplib2.Http() response, content = http.request(path, "GET") self.assertEqual(response.status, 200) data = json.loads(content) self.assertTrue("cached_images" in data) cached_images = data["cached_images"] self.assertEqual(1, len(cached_images)) self.assertTrue(ids[0] in [r["image_id"] for r in data["cached_images"]]) self.stop_servers()
def test_add_list_update_list(self): """ Test for LP Bugs #736295, #767203 We test the following: 0. Verify no public images in index 1. Add a NON-public image 2. Check that image does not appear in index 3. Update the image to be public 4. Check that image now appears in index 5. Update the image's Name attribute 6. Verify the updated name is shown """ self.cleanup() self.start_servers(**self.__dict__.copy()) api_port = self.api_port registry_port = self.registry_port # 0. Verify no public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 1. Add public image cmd = "bin/tank --port=%d add name=MyImage" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(out.strip().startswith('Added new image with ID:')) image_id = out.strip().split(':')[1].strip() # 2. Verify image does not appear as a public image cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('', out.strip()) # 3. Update the image to make it public cmd = "bin/tank --port=%d update %s is_public=True" % ( api_port, image_id) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('Updated image %s' % image_id, out.strip()) # 4. Verify image 1 in list of public images cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) lines = out.split("\n")[2:-1] self.assertEqual(len(lines), 1) self.assertTrue('MyImage' in lines[0]) # 5. Update the image's Name attribute updated_image_name = "Updated image name" cmd = "bin/tank --port=%d update %s is_public=True name=\"%s\"" \ % (api_port, image_id, updated_image_name) exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertEqual('Updated image %s' % image_id, out.strip()) # 6. Verify updated name shown cmd = "bin/tank --port=%d index" % api_port exitcode, out, err = execute(cmd) self.assertEqual(0, exitcode) self.assertTrue(updated_image_name in out, "%s not found in %s" % (updated_image_name, out)) self.stop_servers()