Example #1
0
class ServerTestSuite(BurninTests):
    """Generate and run the GeneratedServerTestSuite

    We will generate as many testsuites as the number of images given.
    Each of these testsuites will use the given flavors at will (random).

    """
    avail_images = Proper(value=None)
    avail_flavors = Proper(value=None)
    gen_classes = Proper(value=None)

    def test_001_images_to_use(self):
        """Find images to be used by GeneratedServerTestSuite"""
        if self.images is None:
            self.info("No --images given. Will use the default %s",
                      "^Debian Base$")
            filters = ["name:^Debian Base$"]
        else:
            filters = self.images

        self.avail_images = self._find_images(filters)
        self.info("Found %s images. Let's create an equal number of tests",
                  len(self.avail_images))

    def test_002_flavors_to_use(self):
        """Find flavors to be used by GeneratedServerTestSuite"""
        flavors = self._get_list_of_flavors(detail=True)

        if self.flavors is None:
            self.info("No --flavors given. Will use all of them")
            self.avail_flavors = flavors
        else:
            self.avail_flavors = self._find_flavors(self.flavors,
                                                    flavors=flavors)
        self.info("Found %s flavors to choose from", len(self.avail_flavors))

    def test_003_create_testsuites(self):
        """Generate the GeneratedServerTestSuite tests"""
        gen_classes = []
        for img in self.avail_images:
            name = (str("GeneratedServerTestSuite_(%s)" % img['name']).replace(
                " ", "_"))
            self.info("Constructing class %s", name)
            class_dict = {
                'use_image': Proper(value=img),
                'avail_flavors': Proper(value=self.avail_flavors)
            }
            cls = type(name, (GeneratedServerTestSuite, ), class_dict)
            # Make sure the class can be pickled, by listing it among
            # the attributes of __main__. A PicklingError is raised otherwise.
            thismodule = sys.modules[__name__]
            setattr(thismodule, name, cls)
            # Append the generated class
            gen_classes.append(cls)

        self.gen_classes = gen_classes

    def test_004_run_testsuites(self):
        """Run the generated tests"""
        self._run_tests(self.gen_classes)
Example #2
0
class KeypairsTestSuite(CycladesTests):

    server = Proper(value=None)
    generated_keypair = Proper(value=None)
    uploaded_keypair = Proper(value=None)

    def test_001_create_keypair(self):
        self.generated_keypair = self._generate_keypair()
        keypairs = self._get_keypairs()
        keypair_added = False
        for keypair in keypairs:
            if keypair['name'] == self.generated_keypair['name']:
                keypair_added = True
                break
        self.assertTrue(keypair_added)

    def test_002_upload_keypair(self):
        paramiko_keypair = paramiko.RSAKey.generate(2048)
        self.uploaded_keypair = self._upload_keypair(
            public_key="ssh-rsa %s" % paramiko_keypair.get_base64())
        keypairs = self._get_keypairs()
        keypair_added = False
        for keypair in keypairs:
            if keypair['name'] == self.uploaded_keypair['name']:
                keypair_added = True
                break
        self.assertTrue(keypair_added)

    def test_003_create_server_with_ssh_keypairs(self):
        use_flavor = random.choice(self._parse_flavors())
        use_image = random.choice(self._parse_images())
        self.server = self._create_server(
            use_image,
            use_flavor,
            key_name=self.generated_keypair['name'],
            network=True)
        self._insist_on_server_transition(self.server, ["BUILD"], "ACTIVE")

    def test_004_ssh_to_server_with_generated_key(self):
        self._insist_on_ip_attached(self.server)
        ipv4 = self._get_server_details(self.server)['attachments'][0]['ipv4']
        self._insist_get_hostname_over_ssh(
            ipv4,
            username="******",
            private_key=self.generated_keypair['private_key'])

    def test_005_clean_up(self):
        self._delete_keypair(self.generated_keypair)
        self._delete_keypair(self.uploaded_keypair)
        self._delete_servers([self.server])
Example #3
0
class AstakosTestSuite(BurninTests):
    """Test Astakos functionality"""
    details = Proper(value=None)

    def test_001_unauthorized_access(self):
        """Test that access without a valid token fails"""
        false_token = "12345"
        self.info("Will use token %s", false_token)
        client = ComputeClient(self.clients.compute_url, false_token)
        client.CONNECTION_RETRY_LIMIT = self.clients.retry

        with self.assertRaises(ClientError) as cl_error:
            client.list_servers()
            self.assertEqual(cl_error.exception.status, 401)

    def test_002_name2uuid(self):
        """Test that usernames2uuids and uuids2usernames are complementary"""
        our_uuid = self._get_uuid()

        given_name = self.clients.astakos.get_usernames([our_uuid])
        self.info("uuids2usernames returned %s", given_name)
        self.assertIn(our_uuid, given_name)

        given_uuid = self.clients.astakos.get_uuids([given_name[our_uuid]])
        self.info("usernames2uuids returned %s", given_uuid)
        self.assertIn(given_name[our_uuid], given_uuid)

        self.assertEqual(given_uuid[given_name[our_uuid]], our_uuid)

    def test_005_authenticate(self):
        """Test astakos.authenticate"""
        astakos = self.clients.astakos
        self.details = astakos.authenticate()
        self.info('Check result integrity')
        self.assertIn('access', self.details)
        access = self.details['access']
        self.assertEqual(set(('user', 'token', 'serviceCatalog')), set(access))
        self.info('Top-level keys are correct')
        self.assertEqual(self.clients.token, access['token']['id'])
        self.info('Token is correct')
        self.assertEqual(
            set(['roles', 'name', 'id', 'roles_links', 'projects']),
            set(astakos.user_info))
        self.info('User section is correct')

    def test_010_get_service_endpoints(self):
        """Test endpoints integrity"""
        scat = self.details['access']['serviceCatalog']
        types = ('compute', 'object-store', 'identity', 'account', 'image',
                 'volume', 'network', 'astakos_weblogin', 'admin', 'vmapi',
                 'astakos_auth')
        self.assertEqual(set(types), set([s['type'] for s in scat]))
        self.info('All expected endpoint types (and only them) found')

        astakos = self.clients.astakos
        for etype in types:
            endpoint = [s for s in scat
                        if s['type'] == etype][0]['endpoints'][0]
            self.assertEqual(endpoint, astakos.get_service_endpoints(etype))
        self.info('Endpoint call results match original results')
Example #4
0
class StaleFloatingIPsTestSuite(CycladesTests):
    """Handle stale Floating IPs"""
    stale_ips = Proper(value=None)

    def test_001_show_stale_ips(self):
        """Show staled floating IPs"""
        floating_ips = self.clients.network.list_floatingips()
        # We consider all the floating ips that are not attached
        # anywhere as stale ips.
        self.stale_ips = [
            ip for ip in floating_ips if ip['instance_id'] is None
        ]

        len_stale = len(self.stale_ips)
        if len_stale == 0:
            self.info("No stale floating IPs found")
            return

        self.info("Found %s stale floating IPs:", len_stale)
        for stl in self.stale_ips:
            self.info("  Floating IP %s with id %s",
                      stl['floating_ip_address'], stl['id'])

    def test_002_delete_stale_ips(self):
        """Delete staled floating IPs"""
        len_stale = len(self.stale_ips)
        if not self.delete_stale and len_stale != 0:
            self.fail("Use --delete-stale flag to delete stale floating IPs")
        elif len_stale == 0:
            self.info("No stale floating IPs found")
        else:
            self.info("Deleting %s stale floating IPs", len_stale)
            self._delete_floating_ips(self.stale_ips)
Example #5
0
class StaleServersTestSuite(CycladesTests):
    """Handle stale Servers"""
    stale_servers = Proper(value=None)

    def test_001_show_stale_servers(self):
        """Show staled servers (servers left from previous runs)"""
        servers = self._get_list_of_servers(detail=True)
        self.stale_servers = [
            s for s in servers if s['name'].startswith(SNF_TEST_PREFIX)
        ]

        len_stale = len(self.stale_servers)
        if len_stale == 0:
            self.info("No stale servers found")
            return

        self.info("Found %s stale servers:", len_stale)
        for stl in self.stale_servers:
            self.info("  Server \"%s\" with id %s", stl['name'], stl['id'])

    def test_002_delete_stale_servers(self):
        """Delete staled servers (servers left from previous runs)"""
        len_stale = len(self.stale_servers)
        if not self.delete_stale and len_stale != 0:
            self.fail("Use --delete-stale flag to delete stale servers")
        elif len_stale == 0:
            self.info("No stale servers found")
        else:
            self.info("Deleting %s stale servers", len_stale)
            self._delete_servers(self.stale_servers, error=True)
Example #6
0
class StaleNetworksTestSuite(CycladesTests):
    """Handle stale Networks"""
    stale_networks = Proper(value=None)

    def test_001_show_stale_networks(self):
        """Show staled networks (networks left from previous runs)"""
        networks = self._get_list_of_networks()
        self.stale_networks = [
            n for n in networks if n['name'].startswith(SNF_TEST_PREFIX)
        ]

        len_stale = len(self.stale_networks)
        if len_stale == 0:
            self.info("No stale networks found")
            return

        self.info("Found %s stale networks:", len_stale)
        for stl in self.stale_networks:
            self.info("  Network \"%s\" with id %s", stl['name'], stl['id'])

    def test_002_delete_stale_networks(self):
        """Delete staled networks (networks left from previous runs)"""
        len_stale = len(self.stale_networks)
        if not self.delete_stale and len_stale != 0:
            self.fail("Use --delete-stale flag to delete stale networks")
        elif len_stale == 0:
            self.info("No stale networks found")
        else:
            self.info("Deleting %s stale networks", len_stale)
            self._delete_networks(self.stale_networks)
Example #7
0
class ServerTestSuite(CycladesTests):
    """Generate and run the GeneratedServerTestSuite

    We will generate as many testsuites as the number of images given.
    Each of these testsuites will use the given flavors at will (random).

    """
    avail_images = Proper(value=None)
    avail_flavors = Proper(value=None)
    gen_classes = Proper(value=None)

    def test_001_images_to_use(self):
        """Find images to be used by GeneratedServerTestSuite"""
        self.avail_images = self._parse_images()

    def test_002_flavors_to_use(self):
        """Find flavors to be used by GeneratedServerTestSuite"""
        self.avail_flavors = self._parse_flavors()

    def test_003_create_testsuites(self):
        """Generate the GeneratedServerTestSuite tests"""
        gen_classes = []
        for img in self.avail_images:
            name = (str("GeneratedServerTestSuite_(%s)" % img['name']).replace(
                " ", "_"))
            self.info("Constructing class %s", name)
            class_dict = {
                'use_image': Proper(value=img),
                'avail_flavors': Proper(value=self.avail_flavors)
            }
            cls = type(name, (GeneratedServerTestSuite, ), class_dict)
            # Make sure the class can be pickled, by listing it among
            # the attributes of __main__. A PicklingError is raised otherwise.
            thismodule = sys.modules[__name__]
            setattr(thismodule, name, cls)
            # Append the generated class
            gen_classes.append(cls)

        self.gen_classes = gen_classes

    def test_004_run_testsuites(self):
        """Run the generated tests"""
        self._run_tests(self.gen_classes)
Example #8
0
    def test_003_create_testsuites(self):
        """Generate the GeneratedServerTestSuite tests"""
        gen_classes = []
        for img in self.avail_images:
            name = (str("GeneratedServerTestSuite_(%s)" % img['name']).replace(
                " ", "_"))
            self.info("Constructing class %s", name)
            class_dict = {
                'use_image': Proper(value=img),
                'avail_flavors': Proper(value=self.avail_flavors)
            }
            cls = type(name, (GeneratedServerTestSuite, ), class_dict)
            # Make sure the class can be pickled, by listing it among
            # the attributes of __main__. A PicklingError is raised otherwise.
            thismodule = sys.modules[__name__]
            setattr(thismodule, name, cls)
            # Append the generated class
            gen_classes.append(cls)

        self.gen_classes = gen_classes
Example #9
0
class FlavorsTestSuite(BurninTests):
    """Test flavor lists for consistency"""
    simple_flavors = Proper(value=None)
    detailed_flavors = Proper(value=None)
    simple_names = Proper(value=None)

    def test_001_simple_flavors(self):
        """Test flavor list actually returns flavors"""
        self.simple_flavors = self._get_list_of_flavors(detail=False)
        self.assertGreater(len(self.simple_flavors), 0)

    def test_002_get_detailed_flavors(self):
        """Test detailed flavor list is the same length as list"""
        self.detailed_flavors = self._get_list_of_flavors(detail=True)
        self.assertEquals(len(self.simple_flavors), len(self.detailed_flavors))

    def test_003_same_flavor_names(self):
        """Test detailed and simple flavor list contain same names"""
        names = sorted([flv['name'] for flv in self.simple_flavors])
        self.simple_names = names
        detailed_names = sorted([flv['name'] for flv in self.detailed_flavors])
        self.assertEqual(self.simple_names, detailed_names)

    def test_004_unique_flavor_names(self):
        """Test flavors have unique names"""
        self.assertEqual(sorted(list(set(self.simple_names))),
                         self.simple_names)

    def test_005_well_formed_names(self):
        """Test flavors have well formed names

        Test flavors have names of the form CxxRyyDzz, where xx is vCPU count,
        yy is RAM in MiB, zz is Disk in GiB

        """
        for flv in self.detailed_flavors:
            flavor = (flv['vcpus'], flv['ram'], flv['disk'],
                      flv['SNF:disk_template'])
            self.assertEqual("C%dR%dD%d%s" % flavor, flv['name'],
                             "Flavor %s doesn't match its specs" % flv['name'])
Example #10
0
class NetworkTestSuite(CycladesTests):
    """Test Networking in Cyclades"""
    avail_images = Proper(value=None)
    avail_flavors = Proper(value=None)
    server_a = Proper(value=None)
    server_b = Proper(value=None)
    network = Proper(value=None)

    def test_001_images_to_use(self):
        """Find images to be used to create our machines"""
        self.avail_images = self._parse_images()

    def test_002_flavors_to_use(self):
        """Find flavors to be used to create our machines"""
        self.avail_flavors = self._parse_flavors()

    def test_003_submit_create_server_a(self):
        """Submit create server request for server A"""
        use_image = random.choice(self.avail_images)
        use_flavor = random.choice(self.avail_flavors)
        server = self._create_server(use_image, use_flavor, network=True)

        self.server_a = {}
        self.server_a['server'] = server
        self.server_a['image'] = use_image
        self.server_a['flavor'] = use_flavor
        self.server_a['username'] = self._get_connection_username(server)
        self.server_a['password'] = server['adminPass']

    def test_004_submit_create_server_b(self):
        """Submit create server request for server B"""
        use_image = random.choice(self.avail_images)
        use_flavor = random.choice(self.avail_flavors)
        server = self._create_server(use_image, use_flavor, network=True)

        self.server_b = {}
        self.server_b['server'] = server
        self.server_b['image'] = use_image
        self.server_b['flavor'] = use_flavor
        self.server_b['username'] = self._get_connection_username(server)
        self.server_b['password'] = server['adminPass']

    def test_005_server_a_active(self):
        """Test that server A becomes ACTIVE"""
        self._insist_on_server_transition(self.server_a['server'], ["BUILD"],
                                          "ACTIVE")

    def test_005_server_b_active(self):
        """Test that server B becomes ACTIVE"""
        self._insist_on_server_transition(self.server_b['server'], ["BUILD"],
                                          "ACTIVE")

    def test_006_create_network(self):
        """Submit a create network request"""
        self.network = self._create_network(gateway_ip='')

        self._insist_on_network_transition(self.network, ["BUILD"], "ACTIVE")

    def test_007_connect_to_network(self):
        """Connect the two VMs to the newly created network"""
        self._create_port(self.network['id'], self.server_a['server']['id'])
        self._create_port(self.network['id'], self.server_b['server']['id'])

        # Update servers
        self.server_a['server'] = self._get_server_details(
            self.server_a['server'])
        self.server_b['server'] = self._get_server_details(
            self.server_b['server'])

        # Check that servers got private IPs
        ipv4 = self._get_ips(self.server_a['server'], network=self.network)
        self.assertEqual(len(ipv4), 1)
        self.server_a['pr_ipv4'] = ipv4[0]
        ipv4 = self._get_ips(self.server_b['server'], network=self.network)
        self.assertEqual(len(ipv4), 1)
        self.server_b['pr_ipv4'] = ipv4

    def test_008_reboot_server_a(self):
        """Rebooting server A"""
        self.clients.cyclades.shutdown_server(self.server_a['server']['id'])
        self._insist_on_server_transition(self.server_a['server'], ["ACTIVE"],
                                          "STOPPED")

        self.clients.cyclades.start_server(self.server_a['server']['id'])
        self._insist_on_server_transition(self.server_a['server'], ["STOPPED"],
                                          "ACTIVE")

    def test_009_ping_server_a(self):
        """Test if server A responds to IPv4 pings"""
        self._insist_on_ping(self._get_ips(self.server_a['server'])[0])

    def test_010_reboot_server_b(self):
        """Rebooting server B"""
        self.clients.cyclades.shutdown_server(self.server_b['server']['id'])
        self._insist_on_server_transition(self.server_b['server'], ["ACTIVE"],
                                          "STOPPED")

        self.clients.cyclades.start_server(self.server_b['server']['id'])
        self._insist_on_server_transition(self.server_b['server'], ["STOPPED"],
                                          "ACTIVE")

    def test_011_ping_server_b(self):
        """Test that server B responds to IPv4 pings"""
        self._insist_on_ping(self._get_ips(self.server_b['server'])[0])

    def test_012_test_connection_exists(self):
        """Ping server B from server A to test if connection exists"""
        self._skip_if(not self._image_is(self.server_a['image'], "linux"),
                      "only valid for Linux servers")
        self._skip_if(not self._image_is(self.server_b['image'], "linux"),
                      "only valid for Linux servers")

        server_a_public_ip = self._get_ips(self.server_a['server'])[0]
        server_b_private_ip = self._get_ips(self.server_b['server'],
                                            network=self.network)[0]
        msg = "Will try to connect to server A (%s) and ping to server B (%s)"
        self.info(msg, server_a_public_ip, server_b_private_ip)

        cmd = "for i in {1..7}; do if ping -c 3 -w 20 %s > /dev/null; " \
            "then echo 'True'; break; fi; done" % server_b_private_ip
        lines, status = self._ssh_execute(server_a_public_ip,
                                          self.server_a['username'],
                                          self.server_a['password'], cmd)

        self.assertEqual(status, 0)
        self.assertEqual(lines, ['True\n'])

    def test_013_disconnect_network(self):
        """Disconnecting servers A and B from network"""
        self._disconnect_from_network(self.server_a['server'], self.network)
        self._disconnect_from_network(self.server_b['server'], self.network)

    def test_014_destroy_network(self):
        """Submit delete network request"""
        self._delete_networks([self.network])

    def test_015_cleanup_servers(self):
        """Cleanup servers created for this test"""
        self._delete_servers(
            [self.server_a['server'], self.server_b['server']])
Example #11
0
class ImagesTestSuite(BurninTests):
    """Test image lists for consistency"""
    simple_images = Proper(value=None)
    detailed_images = Proper(value=None)
    system_images = Proper(value=None)
    temp_dir = Proper(value=None)
    temp_image_name = Proper(value=None)
    temp_image_file = Proper(value=None)

    def test_001_list_images(self):
        """Test simple image list actually returns images"""
        self.simple_images = self._get_list_of_images(detail=False)
        self.assertGreater(len(self.simple_images), 0)

    def test_002_list_images_detailed(self):
        """Test detailed image list is the same length as simple list"""
        self.detailed_images = self._get_list_of_images(detail=True)
        self.assertEqual(len(self.simple_images), len(self.detailed_images))

    def test_003_same_image_names(self):
        """Test detailed and simple image list contain the same names"""
        snames = sorted([i['name'] for i in self.simple_images])
        dnames = sorted([i['name'] for i in self.detailed_images])
        self.assertEqual(snames, dnames)

    def test_004_system_images(self):
        """Test that there are system images registered"""
        images = self._get_list_of_sys_images(images=self.detailed_images)
        self.system_images = images
        self.assertGreater(len(images), 0)

    def test_005_unique_image_names(self):
        """Test system images have unique names"""
        names = sorted([i['name'] for i in self.system_images])
        self.assertEqual(sorted(list(set(names))), names)

    def test_006_image_metadata(self):
        """Test every system image has specific metadata defined"""
        keys = frozenset(["osfamily", "root_partition"])
        for i in self.system_images:
            self.assertTrue(keys.issubset(i['properties'].keys()))

    def test_007_download_image(self):
        """Download image from Pithos"""
        # Find the 'Debian Base' image
        images = self._find_images(["name:^Debian Base$"],
                                   images=self.system_images)
        image = images[0]
        self.info("Will use %s with id %s", image['name'], image['id'])
        image_location = \
            image['location'].replace("://", " ").replace("/", " ").split()
        image_owner = image_location[1]
        self.info("Image's owner is %s", image_owner)
        image_container = image_location[2]
        self.info("Image's container is %s", image_container)
        image_name = image_location[3]
        self.info("Image's name is %s", image_name)
        self.temp_image_name = image_name

        self._set_pithos_account(image_owner)
        self._set_pithos_container(image_container)

        # Create temp directory
        self.temp_dir = self._create_tmp_directory()
        self.temp_image_file = \
            os.path.join(self.temp_dir, self.temp_image_name)

        # Write to file
        self.info("Downloading image to %s", self.temp_image_file)
        with open(self.temp_image_file, "w+b") as fout:
            self.clients.pithos.download_object(image_name, fout)

    def test_008_upload_image(self):
        """Upload the image to Pithos"""
        self._set_pithos_account(self._get_uuid())
        self._create_pithos_container("burnin-images")
        file_size = os.path.getsize(self.temp_image_file)
        with open(self.temp_image_file, "r+b") as fin:
            self.clients.pithos.upload_object(self.temp_image_name, fin)

        # Verify quotas
        self._check_quotas(diskspace=file_size)

    def test_009_register_image(self):
        """Register image to Plankton"""
        location = "pithos://" + self._get_uuid() + \
            "/burnin-images/" + self.temp_image_name
        self.info("Registering image %s", location)

        params = {'is_public': False}
        properties = {'OSFAMILY': "linux", 'ROOT_PARTITION': 1}
        self.clients.image.register(self.temp_image_name, location, params,
                                    properties)

        # Check that image is registered
        self.info("Checking that image has been registered")
        images = self._get_list_of_images(detail=True)
        images = [i for i in images if i['location'] == location]
        self.assertEqual(len(images), 1)
        self.info("Image registered with id %s", images[0]['id'])

    def test_010_cleanup_image(self):
        """Remove uploaded image from Pithos"""
        # Remove uploaded image
        self.info("Deleting uploaded image %s", self.temp_image_name)
        self.clients.pithos.del_object(self.temp_image_name)
        # Verify quotas
        file_size = os.path.getsize(self.temp_image_file)
        self._check_quotas(diskspace=-file_size)
        self.temp_image_name = None
        # Remove temp directory
        self.info("Deleting temp directory %s", self.temp_dir)
        self._remove_tmp_directory(self.temp_dir)
        self.temp_dir = None

    @classmethod
    def tearDownClass(cls):  # noqa
        """Clean up"""
        if cls.temp_image_name is not None:
            try:
                cls.clients.pithos.del_object(cls.temp_image_name)
            except ClientError:
                pass

        if cls.temp_dir is not None:
            try:
                shutil.rmtree(cls.temp_dir)
            except OSError:
                pass
Example #12
0
class GeneratedServerTestSuite(CycladesTests):
    """Test Spawning Serverfunctionality"""
    use_image = Proper(value=None)
    personality = Proper(value=None)
    avail_flavors = Proper(value=None)
    use_flavor = Proper(value=None)
    server = Proper(value=None)
    ipv4 = Proper(value=None)
    ipv6 = Proper(value=None)
    username = Proper(value=None)
    password = Proper(value=None)

    def test_001_submit_create_server(self):
        """Submit a create server request"""
        if self._image_is(self.use_image, "linux"):
            # Enforce personality test
            self.info("Creating personality content to be used")
            self.personality = [{
                'path':
                "/root/test_inj_file",
                'owner':
                "root",
                'group':
                "root",
                'mode':
                stat.S_IRUSR | stat.S_IWUSR,
                'contents':
                base64.b64encode("This is a personality file")
            }]
        self.use_flavor = random.choice(self.avail_flavors)

        self.server = self._create_server(self.use_image,
                                          self.use_flavor,
                                          personality=self.personality,
                                          network=True)
        self.username = self._get_connection_username(self.server)
        self.password = self.server['adminPass']

    def test_002_server_build_list(self):
        """Test server is in BUILD state, in server list"""
        servers = self._get_list_of_servers(detail=True)
        servers = [s for s in servers if s['id'] == self.server['id']]

        self.assertEqual(len(servers), 1)
        server = servers[0]
        self.assertEqual(server['name'], self.server['name'])
        self.assertEqual(server['flavor']['id'], self.use_flavor['id'])
        self.assertEqual(server['image']['id'], self.use_image['id'])
        self.assertEqual(server['status'], "BUILD")

    def test_003_server_build_details(self):
        """Test server is in BUILD state, in details"""
        server = self._get_server_details(self.server)
        self.assertEqual(server['name'], self.server['name'])
        self.assertEqual(server['flavor']['id'], self.use_flavor['id'])
        self.assertEqual(server['image']['id'], self.use_image['id'])
        self.assertEqual(server['status'], "BUILD")

    def test_004_set_server_metadata(self):
        """Test setting some of the server's metadata"""
        image = self.clients.cyclades.get_image_details(self.use_image['id'])
        os_value = image['metadata']['os']
        self.clients.cyclades.update_server_metadata(self.server['id'],
                                                     OS=os_value)

        servermeta = \
            self.clients.cyclades.get_server_metadata(self.server['id'])
        imagemeta = \
            self.clients.cyclades.get_image_metadata(self.use_image['id'])
        self.assertEqual(servermeta['OS'], imagemeta['os'])

    def test_005_server_becomes_active(self):
        """Test server becomes ACTIVE"""
        self._insist_on_server_transition(self.server, ["BUILD"], "ACTIVE")

    def test_006_get_server_oob_console(self):
        """Test getting OOB server console over VNC

        Implementation of RFB protocol follows
        http://www.realvnc.com/docs/rfbproto.pdf.

        """
        console = self.clients.cyclades.get_server_console(self.server['id'])
        self.assertEquals(console['type'], "vnc")
        sock = self._insist_on_tcp_connection(socket.AF_INET, console['host'],
                                              console['port'])

        # Step 1. ProtocolVersion message (par. 6.1.1)
        version = sock.recv(1024)
        self.assertEquals(version, 'RFB 003.008\n')
        sock.send(version)

        # Step 2. Security (par 6.1.2): Only VNC Authentication supported
        sec = sock.recv(1024)
        self.assertEquals(list(sec), ['\x01', '\x02'])

        # Step 3. Request VNC Authentication (par 6.1.2)
        sock.send('\x02')

        # Step 4. Receive Challenge (par 6.2.2)
        challenge = sock.recv(1024)
        self.assertEquals(len(challenge), 16)

        # Step 5. DES-Encrypt challenge, use password as key (par 6.2.2)
        response = d3des_generate_response(
            (console["password"] + '\0' * 8)[:8], challenge)
        sock.send(response)

        # Step 6. SecurityResult (par 6.1.3)
        result = sock.recv(4)
        self.assertEquals(list(result), ['\x00', '\x00', '\x00', '\x00'])
        sock.close()

    def test_007_server_has_ipv4(self):
        """Test active server has a valid IPv4 address"""
        server = self.clients.cyclades.get_server_details(self.server['id'])
        # Update the server attribute
        self.server = server

        self.ipv4 = self._get_ips(server, version=4)

    def test_008_server_has_ipv6(self):
        """Test active server has a valid IPv6 address"""
        self._skip_if(not self.use_ipv6, "--no-ipv6 flag enabled")

        self.ipv6 = self._get_ips(self.server, version=6)

    def test_009_server_ping_ipv4(self):
        """Test server responds to ping on IPv4 address"""
        for ipv4 in self.ipv4:
            self._insist_on_ping(ipv4, version=4)

    def test_010_server_ping_ipv6(self):
        """Test server responds to ping on IPv6 address"""
        self._skip_if(not self.use_ipv6, "--no-ipv6 flag enabled")
        self._insist_on_ping(self.ipv6[0], version=6)

    def test_011a_detach_from_network(self):
        """Detach server from public network"""
        self._disconnect_from_network(self.server)

        try:
            # Test that server is unreachable
            self._insist_on_ping(self.ipv4[0], should_fail=True)
        except AssertionError:
            # If the IP is reachable, test if we can SSH to the server, to
            # make sure that is wasn't attached to another VM.
            self._insist_get_hostname_over_ssh(self.ipv4[0],
                                               self.username,
                                               self.password,
                                               should_fail=True)

    def test_011b_attach_network(self):
        """Re-Attach a public IP to our server"""
        floating_ip = self._create_floating_ip()
        self._create_port(floating_ip['floating_network_id'],
                          device_id=self.server['id'],
                          floating_ip=floating_ip)

        # Update server attributes
        server = self.clients.cyclades.get_server_details(self.server['id'])
        self.server = server
        self.ipv4 = self._get_ips(server, version=4)
        self.assertEqual(len(self.ipv4), 1)

        # Test new IPv4
        self.test_009_server_ping_ipv4()

    def test_012_submit_shutdown(self):
        """Test submit request to shutdown server"""
        self.clients.cyclades.shutdown_server(self.server['id'])

    def test_013_server_becomes_stopped(self):
        """Test server becomes STOPPED"""
        self._insist_on_server_transition(self.server, ["ACTIVE"], "STOPPED")

    def test_014_submit_start(self):
        """Test submit start server request"""
        self.clients.cyclades.start_server(self.server['id'])

    def test_015_server_becomes_active(self):
        """Test server becomes ACTIVE again"""
        self._insist_on_server_transition(self.server, ["STOPPED"], "ACTIVE")

    def test_016_server_ping_ipv4(self):
        """Test server OS is actually up and running again"""
        self.test_009_server_ping_ipv4()

    def test_017_ssh_to_server_ipv4(self):
        """Test SSH to server public IPv4 works, verify hostname"""
        self._skip_if(not self._image_is(self.use_image, "linux"),
                      "only valid for Linux servers")
        hostname = self._insist_get_hostname_over_ssh(self.ipv4[0],
                                                      self.username,
                                                      self.password)

        # The hostname must be of the form 'prefix-id'
        self.assertTrue(hostname.endswith("-%d" % self.server['id']))

    def test_018_ssh_to_server_ipv6(self):
        """Test SSH to server public IPv6 works, verify hostname"""
        self._skip_if(not self._image_is(self.use_image, "linux"),
                      "only valid for Linux servers")
        self._skip_if(not self.use_ipv6, "--no-ipv6 flag enabled")
        hostname = self._insist_get_hostname_over_ssh(self.ipv6[0],
                                                      self.username,
                                                      self.password)
        # The hostname must be of the form 'prefix-id'
        self.assertTrue(hostname.endswith("-%d" % self.server['id']))

    def test_019_rdp_to_server_ipv4(self):
        """Test RDP connection to server public IPv4 works"""
        self._skip_if(not self._image_is(self.use_image, "windows"),
                      "only valid for Windows servers")
        sock = self._insist_on_tcp_connection(socket.AF_INET, self.ipv4[0],
                                              3389)
        # No actual RDP processing done. We assume the RDP server is there
        # if the connection to the RDP port is successful.
        # pylint: disable=fixme
        # FIXME: Use rdesktop, analyze exit code? see manpage
        sock.close()

    def test_020_rdp_to_server_ipv6(self):
        """Test RDP connection to server public IPv6 works"""
        self._skip_if(not self._image_is(self.use_image, "windows"),
                      "only valid for Windows servers")
        self._skip_if(not self.use_ipv6, "--no-ipv6 flag enabled")
        sock = self._insist_on_tcp_connection(socket.AF_INET, self.ipv6[0],
                                              3389)
        # No actual RDP processing done. We assume the RDP server is there
        # if the connection to the RDP port is successful.
        # pylint: disable=fixme
        # FIXME: Use rdesktop, analyze exit code? see manpage
        sock.close()

    def test_021_personality(self):
        """Test file injection for personality enforcement"""
        self._skip_if(not self._image_is(self.use_image, "linux"),
                      "only implemented for linux servers")
        assert self.personality is not None, "No personality used"

        for inj_file in self.personality:
            self._check_file_through_ssh(self.ipv4[0], inj_file['owner'],
                                         self.password, inj_file['path'],
                                         inj_file['contents'])

    def test_022_destroy_floating_ips(self):
        """Destroy the floating IPs"""
        self._disconnect_from_network(self.server)

    def test_023_submit_delete_request(self):
        """Test submit request to delete server"""
        self._delete_servers([self.server])
Example #13
0
class PithosTestSuite(BurninTests):
    """Test Pithos functionality"""
    containers = Proper(value=None)
    created_container = Proper(value=None)

    def test_001_list_containers(self):
        """Test container list actually returns containers"""
        self._set_pithos_account(self._get_uuid())
        self.containers = self._get_list_of_containers()
        self.assertGreater(len(self.containers), 0)

    def test_002_unique_containers(self):
        """Test if containers have unique names"""
        names = [n['name'] for n in self.containers]
        names = sorted(names)
        self.assertEqual(sorted(list(set(names))), names)

    def test_003_create_container(self):
        """Test creating a new container"""
        names = [n['name'] for n in self.containers]
        while True:
            rand_num = random.randint(1000, 9999)
            rand_name = "%s%s" % (self.run_id, rand_num)
            self.info("Trying container name %s", rand_name)
            if rand_name not in names:
                break
            self.info("Container name %s already exists", rand_name)
        # Create container
        self._create_pithos_container(rand_name)
        # Verify that container is created
        containers = self._get_list_of_containers()
        self.info("Verify that container %s is created", rand_name)
        names = [n['name'] for n in containers]
        self.assertIn(rand_name, names)
        # Keep the name of the container so we can remove it
        # at cleanup phase, if something goes wrong.
        self.created_container = rand_name

    def test_004_upload_file(self):
        """Test uploading a txt file to Pithos"""
        # Create a tmp file
        with tempfile.TemporaryFile(dir=self.temp_directory) as fout:
            fout.write("This is a temp file")
            fout.seek(0, 0)
            # Upload the file,
            # The container is the one choosen during the `create_container'
            self.clients.pithos.upload_object("test.txt", fout)
            # Verify quotas
            self._check_quotas(diskspace=+os.fstat(fout.fileno()).st_size)

    def test_005_download_file(self):
        """Test downloading the file from Pithos"""
        # Create a tmp directory to save the file
        with tempfile.TemporaryFile(dir=self.temp_directory) as fout:
            self.clients.pithos.download_object("test.txt", fout)
            # Now read the file
            fout.seek(0, 0)
            contents = fout.read()
            # Compare results
            self.info("Comparing contents with the uploaded file")
            self.assertEqual(contents, "This is a temp file")

    def test_006_remove(self):
        """Test removing files and containers from Pithos"""
        self.info("Removing the file %s from container %s", "test.txt",
                  self.created_container)
        # The container is the one choosen during the `create_container'
        content_length = \
            self.clients.pithos.get_object_info("test.txt")['content-length']
        self.clients.pithos.del_object("test.txt")

        # Verify quotas
        self._check_quotas(diskspace=-int(content_length))

        self.info("Removing the container %s", self.created_container)
        self.clients.pithos.purge_container()

        # List containers
        containers = self._get_list_of_containers()
        self.info("Check that the container %s has been deleted",
                  self.created_container)
        names = [n['name'] for n in containers]
        self.assertNotIn(self.created_container, names)
        # We successfully deleted our container, no need to do it
        # in our clean up phase
        self.created_container = None

    @classmethod
    def tearDownClass(cls):  # noqa
        """Clean up"""
        if cls.created_container is not None:
            cls.clients.pithos.del_container(delimiter='/')
            cls.clients.pithos.purge_container()
Example #14
0
class ImagesTestSuite(BurninTests):
    """Test image lists for consistency"""
    simple_images = Proper(value=None)
    detailed_images = Proper(value=None)
    system_images = Proper(value=None)
    temp_dir = Proper(value=None)
    temp_image_name = Proper(value=None)
    temp_image_file = Proper(value=None)

    def test_001_list_images(self):
        """Test simple image list actually returns images"""
        self.simple_images = self._get_list_of_images(detail=False)
        self.assertGreater(len(self.simple_images), 0)

    def test_002_list_images_detailed(self):
        """Test detailed image list is the same length as simple list"""
        self.detailed_images = self._get_list_of_images(detail=True)
        self.assertEqual(len(self.simple_images), len(self.detailed_images))

    def test_003_same_image_names(self):
        """Test detailed and simple image list contain the same names"""
        snames = sorted([i['name'] for i in self.simple_images])
        dnames = sorted([i['name'] for i in self.detailed_images])
        self.assertEqual(snames, dnames)

    def test_004_system_images(self):
        """Test that there are system images registered"""
        images = self._get_list_of_sys_images(images=self.detailed_images)
        self.system_images = images
        self.assertGreater(len(images), 0)

    def test_005_unique_image_names(self):
        """Test system images have unique names"""
        names = sorted([i['name'] for i in self.system_images])
        self.assertEqual(sorted(list(set(names))), names)

    def test_006_image_metadata(self):
        """Test every system image has specific metadata defined"""
        keys = frozenset(["osfamily", "root_partition"])
        for i in self.system_images:
            self.assertTrue(keys.issubset(i['properties'].keys()),
                            "Failed in image with id '%s'" % i['id'])

    def test_007_download_image(self):
        """Download image from Pithos"""
        # Find the 'Debian Base' image
        images = self._parse_images(possible_images=self.system_images)
        self.assertGreater(len(images),
                           0,
                           msg="Could not detect any suitable "
                           "images to download")
        image = images[0]
        self.info("Will use %s with id %s", image['name'], image['id'])
        image_location = \
            image['location'].replace("://", " ").replace("/", " ").split()
        image_owner = image_location[1]
        self.info("Image's owner is %s", image_owner)
        image_container = image_location[2]
        self.info("Image's container is %s", image_container)
        image_name = image_location[3]
        self.info("Image's name is %s", image_name)
        self.temp_image_name = image_name

        self._set_pithos_account(image_owner)
        self._set_pithos_container(image_container)

        # Create temp directory
        self.temp_dir = self._create_tmp_directory()
        self.temp_image_file = \
            os.path.join(self.temp_dir, self.temp_image_name)

        # Write to file
        self.info("Downloading image to %s", self.temp_image_file)
        with open(self.temp_image_file, "w+b") as fout:
            self.clients.pithos.download_object(image_name, fout)

    def test_008_upload_image(self):
        """Upload the image to Pithos"""
        self._set_pithos_account(self._get_uuid())
        self._create_pithos_container("burnin-images")
        self._set_pithos_container("burnin-images")
        file_size = os.path.getsize(self.temp_image_file)
        with open(self.temp_image_file, "r+b") as fin:
            self.clients.pithos.upload_object(self.temp_image_name, fin)

        # Verify quotas
        changes = \
            {self._get_uuid(): [(QPITHOS, QADD, file_size, None)]}
        self._check_quotas(changes)

    def test_009_register_image(self):
        """Register image to Plankton"""
        location = "pithos://" + self._get_uuid() + \
            "/burnin-images/" + self.temp_image_name
        self.info("Registering image %s", location)

        params = {'is_public': False}
        properties = {'OSFAMILY': "linux", 'ROOT_PARTITION': 1}
        self.clients.image.register(self.temp_image_name, location, params,
                                    properties)

        # Check that image is registered
        self.info("Checking that image has been registered")
        images = self._get_list_of_images(detail=True)
        images = [i for i in images if i['location'] == location]
        self.assertEqual(len(images), 1)
        self.info("Image registered with id %s", images[0]['id'])

        self.info("Registering with unicode name")
        uni_str = u'\u03b5\u03b9\u03ba\u03cc\u03bd\u03b1'
        uni_name = u'%s, or %s in Greek' % (self.temp_image_name, uni_str)
        img = self.clients.image.register(uni_name, location, params,
                                          properties)

        self.info('Checking if image with unicode name exists')
        found_img = self.clients.image.get_meta(img['id'])
        self.assertEqual(found_img['name'], uni_name)
        self.info("Image registered with id %s", found_img['id'])

        self.info("Checking if image is listed "
                  "under the specific container in pithos")
        self._set_pithos_account(self._get_uuid())
        pithos = self.clients.pithos
        pithos.container = 'burnin-images'
        self.assertTrue(
            self.temp_image_name in (o['name'] for o in pithos.list_objects()))

        self.info("Checking copying image to " "another pithos container.")
        pithos.container = other_container = 'burnin-images-backup'
        pithos.create_container()
        pithos.copy_object(src_container='burnin-images',
                           src_object=self.temp_image_name,
                           dst_container=other_container,
                           dst_object='%s_copy' % self.temp_image_name)

        # Verify quotas
        file_size = os.path.getsize(self.temp_image_file)
        changes = \
            {self._get_uuid(): [(QPITHOS, QADD, file_size, None)]}
        self._check_quotas(changes)

        self.info("Checking copied image " "is listed among the images.")
        images = self._get_list_of_images(detail=True)
        locations = [i['location'] for i in images]
        location2 = "pithos://" + self._get_uuid() + \
            "/burnin-images-backup/" + '%s_copy' % self.temp_image_name
        self.assertTrue(location2 in locations)

        self.info("Set image metadata in the pithos domain")
        pithos.set_object_meta('%s_copy' % self.temp_image_name,
                               {'foo': 'bar'})

        self.info("Checking copied image " "is still listed among the images.")
        images = self._get_list_of_images(detail=True)
        locations = [i['location'] for i in images]
        location2 = "pithos://" + self._get_uuid() + \
            "/burnin-images-backup/" + '%s_copy' % self.temp_image_name
        self.assertTrue(location2 in locations)

        # delete copied object
        self.clients.pithos.del_object('%s_copy' % self.temp_image_name)

        # Verify quotas
        file_size = os.path.getsize(self.temp_image_file)
        changes = \
            {self._get_uuid(): [(QPITHOS, QREMOVE, file_size, None)]}
        self._check_quotas(changes)

    def test_010_cleanup_image(self):
        """Remove uploaded image from Pithos"""
        # Remove uploaded image
        self.info("Deleting uploaded image %s", self.temp_image_name)
        self._set_pithos_container("burnin-images")
        self.clients.pithos.del_object(self.temp_image_name)
        # Verify quotas
        file_size = os.path.getsize(self.temp_image_file)
        changes = \
            {self._get_uuid(): [(QPITHOS, QREMOVE, file_size, None)]}
        self._check_quotas(changes)
        self.temp_image_name = None
        # Remove temp directory
        self.info("Deleting temp directory %s", self.temp_dir)
        self._remove_tmp_directory(self.temp_dir)
        self.temp_dir = None

    @classmethod
    def tearDownClass(cls):  # noqa
        """Clean up"""
        for container in ["burnin-images", "burnin-images-backup"]:
            cls.clients.pithos.container = container
            try:
                cls.clients.pithos.del_container(delimiter='/')
                cls.clients.pithos.purge_container(container)
            except ClientError:
                pass

        if cls.temp_dir is not None:
            try:
                shutil.rmtree(cls.temp_dir)
            except OSError:
                pass
Example #15
0
class QuotasTestSuite(CycladesTests):
    """Test Quotas functionality"""
    server = Proper(value=None)

    def test_001_check_skip(self):
        """Check if we are members in more than one projects"""
        self._skip_suite_if(
            len(self.quotas.keys()) < 2,
            "This user is not a member of 2 or more projects")

    def test_002_create(self):
        """Create a machine to a different project than base"""
        image = random.choice(self._parse_images())
        flavors = self._parse_flavors()

        # We want to create our machine in a project other than 'base'
        projects = self.quotas.keys()
        projects.remove(self._get_uuid())
        (flavor, project) = self._find_project(flavors, projects)

        # Create machine
        self.server = self._create_server(image,
                                          flavor,
                                          network=True,
                                          project_id=project)

        # Wait for server to become active
        self._insist_on_server_transition(self.server, ["BUILD"], "ACTIVE")

    def test_003_assign(self):
        """Re-Assign the machine to a different project"""
        # We will use the base project for now
        new_project = self._get_uuid()
        project_name = self._get_project_name(new_project)
        self.info("Assign %s to project %s", self.server['name'], project_name)

        # Reassign server
        old_project = self.server['tenant_id']
        self.clients.cyclades.reassign_server(self.server['id'], new_project)

        # Check tenant_id
        self.server = self._get_server_details(self.server, quiet=True)
        self.assertEqual(self.server['tenant_id'], new_project)

        # Check new quotas
        flavor = self.clients.compute.get_flavor_details(
            self.server['flavor']['id'])
        changes = \
            {old_project:
                [(QDISK, QREMOVE, flavor['disk'], GB),
                 (QVM, QREMOVE, 1, None),
                 (QRAM, QREMOVE, flavor['ram'], MB),
                 (QCPU, QREMOVE, flavor['vcpus'], None)],
             new_project:
                [(QDISK, QADD, flavor['disk'], GB),
                 (QVM, QADD, 1, None),
                 (QRAM, QADD, flavor['ram'], MB),
                 (QCPU, QADD, flavor['vcpus'], None)]}
        self._check_quotas(changes)

    def test_004_cleanup(self):
        """Remove test server"""
        self._delete_servers([self.server])
Example #16
0
class SnapshotsTestSuite(CycladesTests):
    """Test Snapshot functionality"""
    personality = Proper(value=None)
    account = Proper(value=None)
    servers = Proper(value=[])
    snapshot = Proper(value=None)
    tmp_container = Proper(value='burnin-snapshot-temp')
    use_flavor = Proper(value=None)
    personality = Proper(value=None)

    def test_001_submit_create_snapshot(self):
        """Create a server and take a snapshot"""
        self.account = self._get_uuid()
        use_image = random.choice(self._parse_images())
        archipelago_flavors = \
            [f for f in self._parse_flavors() if
             f['SNF:disk_template'].startswith('ext_archipelago')]
        self.assertGreater(len(archipelago_flavors), 0,
                           "No 'archipelago' disk template found")
        self.use_flavor = random.choice(archipelago_flavors)
        if self._image_is(use_image, "linux"):
            # Enforce personality test
            self.info("Creating personality content to be used")
            self.personality = [{
                'path':
                "/root/test_inj_file",
                'owner':
                "root",
                'group':
                "root",
                'mode':
                stat.S_IRUSR | stat.S_IWUSR,
                'contents':
                base64.b64encode("This is a personality file")
            }]

        self.info("Using image %s with id %s", use_image['name'],
                  use_image['id'])
        self.info("Using flavor %s with id %s", self.use_flavor['name'],
                  self.use_flavor['id'])
        self.servers.append(
            self._create_server(use_image,
                                self.use_flavor,
                                personality=self.personality,
                                network=True))
        server = self.servers[0]
        self._insist_on_server_transition(server, ["BUILD"], "ACTIVE")

        volume_id = server['volumes'][0]
        snapshot_name = 'snf-burnin-snapshot_%s' % volume_id
        self.info("Creating snapshot with name '%s', for volume %s",
                  snapshot_name, volume_id)
        self.snapshot = self.clients.block_storage.create_snapshot(
            volume_id, display_name=snapshot_name)
        self.info("Snapshot with id '%s' created", self.snapshot['id'])

        volume_size = self.snapshot['size'] * GB
        self._check_quotas(
            {self.account: [(QPITHOS, QADD, volume_size, None)]})

        self.info('Check that snapshot is listed among snapshots')
        self.assertTrue(
            self.snapshot['id'] in
            [i['id'] for i in self.clients.block_storage.list_snapshots()])

        self.info('Get snapshot details')
        self.clients.block_storage.get_snapshot_details(self.snapshot['id'])

        self.info('Check the snapshot is listed under '
                  'pithos snapshots container')
        pithos = self.clients.pithos
        self._set_pithos_account(self.account)
        self.pithos_account = pithos.account
        pithos.container = 'snapshots'
        self.assertTrue(self.snapshot['display_name'] in
                        [o['name'] for o in pithos.list_objects()])

        self._insist_on_snapshot_transition(self.snapshot,
                                            ["UNAVAILABLE", "CREATING"],
                                            "AVAILABLE")

    def test_002_copy_snapshot(self):
        """Copy snapshot to secondary container"""
        self._create_pithos_container(self.tmp_container)
        pithos = self.clients.pithos

        pithos.copy_object(src_container=pithos.container,
                           src_object=self.snapshot['display_name'],
                           dst_container=self.tmp_container,
                           dst_object='%s_new' % self.snapshot['display_name'])
        pithos.container = 'snapshots'
        resp1 = pithos.get_object_info(self.snapshot['display_name'])

        pithos.container = self.tmp_container
        resp2 = pithos.get_object_info('%s_new' %
                                       self.snapshot['display_name'])

        self.assertEqual(resp1['x-object-hash'], resp2['x-object-hash'])
        self.info('Snapshot has being copied in another container, OK')

        self.info('Check both snapshots are listed among snapshots')
        uploaded_snapshots = [
            i['id'] for i in self.clients.block_storage.list_snapshots()
        ]
        self.assertTrue(resp1['x-object-uuid'] in uploaded_snapshots)
        self.assertTrue(resp2['x-object-uuid'] in uploaded_snapshots)

        volume_size = self.snapshot['size'] * GB
        self._check_quotas(
            {self.account: [(QPITHOS, QADD, volume_size, None)]})

    def test_003_move_snapshot(self):
        """Move snapshot to secondary container"""
        pithos = self.clients.pithos
        pithos.container = self.tmp_container
        resp1 = pithos.get_object_info('%s_new' %
                                       self.snapshot['display_name'])

        pithos.move_object(src_container=self.tmp_container,
                           src_object='%s_new' % self.snapshot['display_name'],
                           dst_container=self.tmp_container,
                           dst_object='%s_renamed' %
                           self.snapshot['display_name'])
        self.assertRaises(ClientError, pithos.get_object_info,
                          '%s_new' % self.snapshot['display_name'])

        resp2 = pithos.get_object_info('%s_renamed' %
                                       self.snapshot['display_name'])
        self.info('Snapshot has being renamed, OK')

        self.info('Check both snapshots are listed among snapshots')
        uploaded_snapshots = [
            i['id'] for i in self.clients.block_storage.list_snapshots()
        ]
        self.assertTrue(self.snapshot['id'] in uploaded_snapshots)
        self.assertEqual(resp1['x-object-uuid'], resp2['x-object-uuid'])
        self.assertTrue(resp2['x-object-uuid'] in uploaded_snapshots)

        # self._check_quotas({self.account: [(QPITHOS, QADD, 0, None)]})
        self._check_quotas({self.account: []})

    def test_004_update_snapshot(self):
        """Update snapshot metadata"""
        pithos = self.clients.pithos
        pithos.container = 'snapshots'
        self.info('Update snapshot \'pithos\' domain metadata')
        pithos.set_object_meta(self.snapshot['display_name'], {'foo': 'bar'})
        resp = pithos.get_object_meta(self.snapshot['display_name'])
        self.assertEqual(resp['x-object-meta-foo'], 'bar')

        self.info('Check snapshot is still listed among snapshots')
        uploaded_snapshots = [
            i['id'] for i in self.clients.block_storage.list_snapshots()
        ]
        self.assertTrue(self.snapshot['id'] in uploaded_snapshots)

    def test_005_spawn_vm_from_snapshot(self):
        """Spawn a VM from the newly created snapshot"""
        self.servers.append(
            self._create_server(self.snapshot, self.use_flavor, network=True))
        server = self.servers[-1]
        self._insist_on_server_transition(server, ["BUILD"], "ACTIVE")

        server = self.clients.cyclades.get_server_details(server['id'])
        ipv4 = self._get_ips(server, version=4)
        self.assertTrue(len(ipv4) >= 1)
        self._insist_on_ping(ipv4[0], version=4)

        # use initial server's password
        for inj_file in (self.personality or ()):
            self._check_file_through_ssh(ipv4[0], inj_file['owner'],
                                         self.servers[0]['adminPass'],
                                         inj_file['path'],
                                         inj_file['contents'])

    def test_006_delete_snapshot(self):
        """Delete snapshot"""
        self.info('Delete snapshot')
        self.clients.block_storage.delete_snapshot(self.snapshot['id'])
        self._insist_on_snapshot_deletion(self.snapshot['id'])

        volume_size = self.snapshot['size'] * GB
        self._check_quotas(
            {self.account: [(QPITHOS, QREMOVE, volume_size, None)]})
        self.snapshot = None

    def test_cleanup(self):
        """Cleanup created servers"""
        for s in self.servers:
            self._disconnect_from_network(s)
        self._delete_servers(self.servers)

    @classmethod
    def tearDownClass(cls):  # noqa
        """Clean up"""
        # Delete snapshot
        snapshots = [
            s for s in cls.clients.block_storage.list_snapshots()
            if s['display_name'].startswith("snf-burnin-")
        ]
        for snapshot in snapshots:
            try:
                cls.clients.block_storage.delete_snapshot(snapshot['id'])
            except ClientError:
                pass

        # Delete temp containers
        cls.clients.pithos.account = cls.account
        cls.clients.pithos.container = cls.tmp_container
        try:
            cls.clients.pithos.del_container(delimiter='/')
            cls.clients.pithos.purge_container(cls.tmp_container)
        except ClientError:
            pass