Beispiel #1
0
 def test_get_images_by_name(self):
     image_mock1 = mock.MagicMock()
     image_mock1.name = 'bob'
     image_mock2 = mock.MagicMock()
     image_mock2.name = 'bill'
     glance_client = mock.MagicMock()
     glance_client.images.list.return_value = [image_mock1, image_mock2]
     self.assertEqual(
         openstack_utils.get_images_by_name(glance_client, 'bob'),
         [image_mock1])
     self.assertEqual(
         openstack_utils.get_images_by_name(glance_client, 'frank'), [])
Beispiel #2
0
def add_image(image_url, glance_client=None, image_name=None, tags=[],
              properties=None):
    """Retrieve image from ``image_url`` and add it to glance.

    :param image_url: Retrievable URL with image data
    :type image_url: str
    :param glance: Authenticated glanceclient
    :type glance: glanceclient.Client
    :param image_name: Label for the image in glance
    :type image_name: str
    :param tags: List of tags to add to image
    :type tags: list of str
    :param properties: Properties to add to image
    :type properties: dict
    """
    if not glance_client:
        keystone_session = openstack_utils.get_overcloud_keystone_session()
        glance_client = openstack_utils.get_glance_session_client(
            keystone_session)
    if image_name:
        image = openstack_utils.get_images_by_name(
            glance_client, image_name)

    if image:
        logging.warning('Using existing glance image "{}" ({})'
                        .format(image_name, image[0].id))
    else:
        logging.info('Downloading image {}'.format(image_name or image_url))
        openstack_utils.create_image(
            glance_client,
            image_url,
            image_name,
            tags=tags,
            properties=properties)
Beispiel #3
0
    def test_100_create_image(self):
        """Create an image and do a simple validation of it.

        The OpenStack Swift API is used to do the validation, since the Ceph
        Rados Gateway serves an API which is compatible with that.
        """
        image_name = 'zaza-ceph-rgw-image'
        openstack_utils.create_image(
            glance=self.glance_client,
            image_url=openstack_utils.find_cirros_image(arch='x86_64'),
            image_name=image_name,
            backend='swift')
        headers, containers = self.swift.get_account()
        self.assertEqual(len(containers), 1)
        container_name = containers[0].get('name')
        headers, objects = self.swift.get_container(container_name)
        images = openstack_utils.get_images_by_name(self.glance_client,
                                                    image_name)
        self.assertEqual(len(images), 1)
        image = images[0]
        total_bytes = 0
        for ob in objects:
            if '{}-'.format(image['id']) in ob['name']:
                total_bytes = total_bytes + int(ob['bytes'])
        logging.info('Checking glance image size {} matches swift '
                     'image size {}'.format(image['size'], total_bytes))
        self.assertEqual(image['size'], total_bytes)
        openstack_utils.delete_image(self.glance_client, image['id'])
Beispiel #4
0
    def test_100_create_delete_image(self):
        """Create an image and do a simple validation of it.

        Validate the size of the image in both Glance API and actual S3 bucket.
        """
        image_name = "zaza-s3-test-image"
        openstack_utils.create_image(
            glance=self.glance_client,
            image_url=openstack_utils.find_cirros_image(arch="x86_64"),
            image_name=image_name,
            backend="s3",
        )
        images = openstack_utils.get_images_by_name(self.glance_client,
                                                    image_name)
        self.assertEqual(len(images), 1)
        image = images[0]

        s3_client = boto3.client(
            "s3",
            endpoint_url=self.s3_store_host,
            aws_access_key_id=self.s3_store_access_key,
            aws_secret_access_key=self.s3_store_secret_key,
        )
        response = s3_client.head_object(Bucket=self.s3_store_bucket,
                                         Key=image["id"])
        logging.info(
            "Checking glance image size {} matches S3 object's ContentLength "
            "{}".format(image["size"], response["ContentLength"]))
        self.assertEqual(image["size"], response["ContentLength"])
        openstack_utils.delete_image(self.glance_client, image["id"])
    def test_100_create_delete_image(self):
        """Create an image and do a simple validation of it.

        Validate the size of the image in both Glance API and Cinder API.
        """
        image_name = "zaza-cinder-test-image"
        openstack_utils.create_image(
            glance=self.glance_client,
            image_url=openstack_utils.find_cirros_image(arch="x86_64"),
            image_name=image_name,
            backend="cinder",
        )
        images = openstack_utils.get_images_by_name(self.glance_client,
                                                    image_name)
        self.assertEqual(len(images), 1)
        image = images[0]

        volume_name = 'image-' + image["id"]
        volumes = openstack_utils.get_volumes_by_name(self.cinder_client,
                                                      volume_name)
        self.assertEqual(len(volumes), 1)
        volume = volumes[0]

        logging.info("Checking glance image size {} matches volume size {} "
                     "GB".format(image["size"], volume.size))
        image_size_in_gb = int(math.ceil(float(image["size"]) / 1024**3))
        self.assertEqual(image_size_in_gb, volume.size)
        openstack_utils.delete_image(self.glance_client, image["id"])
Beispiel #6
0
def get_glance_image(glance):
    """Get the Glance image object to be used by the Ceph tests.

    It looks for the Cirros Glance image, and it's returned if it's found.
    If the Cirros image is not found, it will try and find the Ubuntu
    LTS image.

    :param glance: Authenticated glanceclient
    :type glance: glanceclient.Client
    :returns: Glance image object
    :rtype: glanceclient.image
    """
    images = openstack.get_images_by_name(glance, CIRROS_IMAGE_NAME)
    if images:
        return images[0]
    logging.info("Failed to find {} image, falling back to {}".format(
        CIRROS_IMAGE_NAME, LTS_IMAGE_NAME))
    return openstack.get_images_by_name(glance, LTS_IMAGE_NAME)[0]
Beispiel #7
0
def add_glance_config(ctxt, keystone_session):
    """Add glance config to context.

    :param ctxt: Context dictionary
    :type ctxt: dict
    :param keystone_session: keystoneauth1.session.Session object
    :type: keystoneauth1.session.Session
    :returns: None
    :rtype: None
    """
    glance_client = openstack_utils.get_glance_session_client(keystone_session)
    image = openstack_utils.get_images_by_name(glance_client,
                                               glance_setup.CIRROS_IMAGE_NAME)
    image_alt = openstack_utils.get_images_by_name(
        glance_client, glance_setup.CIRROS_ALT_IMAGE_NAME)
    if image:
        ctxt['image_id'] = image[0].id
    if image_alt:
        ctxt['image_alt_id'] = image_alt[0].id
Beispiel #8
0
def add_image(image_url,
              glance_client=None,
              image_name=None,
              tags=[],
              properties=None,
              backend=None,
              disk_format='qcow2',
              visibility='public',
              container_format='bare'):
    """Retrieve image from ``image_url`` and add it to glance.

    :param image_url: Retrievable URL with image data
    :type image_url: str
    :param glance: Authenticated glanceclient
    :type glance: glanceclient.Client
    :param image_name: Label for the image in glance
    :type image_name: str
    :param tags: List of tags to add to image
    :type tags: list of str
    :param properties: Properties to add to image
    :type properties: dict
    """
    glance_client = glance_client or _get_default_glance_client()
    if backend is not None:
        stores = get_store_ids(glance_client)
        if backend not in stores:
            raise ValueError("Invalid backend: %(backend)s "
                             "(available: %(available)s)" % {
                                 "backend": backend,
                                 "available": ", ".join(stores)
                             })
    if image_name:
        image = openstack_utils.get_images_by_name(glance_client, image_name)

    if image:
        logging.warning('Using existing glance image "{}" ({})'.format(
            image_name, image[0].id))
    else:
        logging.info('Downloading image {}'.format(image_name or image_url))
        openstack_utils.create_image(glance_client,
                                     image_url,
                                     image_name,
                                     tags=tags,
                                     properties=properties,
                                     backend=backend,
                                     disk_format=disk_format,
                                     visibility=visibility,
                                     container_format=container_format)
Beispiel #9
0
 def test_100_create_image(self):
     """Create an image and do simple validation of image in swift."""
     glance_setup.add_lts_image(image_name=self.image_name)
     headers, containers = self.swift.get_account()
     self.assertEqual(len(containers), 1)
     container_name = containers[0].get('name')
     headers, objects = self.swift.get_container(container_name)
     images = openstack_utils.get_images_by_name(self.glance_client,
                                                 self.image_name)
     self.assertEqual(len(images), 1)
     image = images[0]
     total_bytes = 0
     for ob in objects:
         if '{}-'.format(image['id']) in ob['name']:
             total_bytes = total_bytes + int(ob['bytes'])
     logging.info('Checking glance image size {} matches swift '
                  'image size {}'.format(image['size'], total_bytes))
     self.assertEqual(image['size'], total_bytes)
     openstack_utils.delete_image(self.glance_client, image['id'])
Beispiel #10
0
    def test_cinder_volume_mirrored(self):
        """Validate that a volume created through Cinder is mirrored.

        For RBD Mirroring to work clients must enable the correct set of
        features when creating images.

        The RBD image feature settings are announced by the ``ceph-mon`` charm
        over the client relation when it has units related on its
        ``rbd-mirror`` endpoint.

        By creating a volume through cinder on site A, checking for presence on
        site B and subsequently comparing the contents we get a full end to end
        test.
        """
        session = openstack.get_overcloud_keystone_session()
        glance = openstack.get_glance_session_client(session)
        cinder = openstack.get_cinder_session_client(session)

        images = openstack.get_images_by_name(glance, CIRROS_IMAGE_NAME)
        if images:
            image = images[0]
        else:
            logging.info("Failed to find {} image, falling back to {}".format(
                CIRROS_IMAGE_NAME, LTS_IMAGE_NAME))
            image = openstack.get_images_by_name(glance, LTS_IMAGE_NAME)[0]

        # NOTE(fnordahl): for some reason create volume from image often fails
        # when run just after deployment is finished.  We should figure out
        # why, resolve the underlying issue and then remove this.
        #
        # We do not use tenacity here as it will interfere with tenacity used
        # in ``resource_reaches_status``
        def create_volume_from_image(cinder, image, retry=20):
            if retry < 1:
                return
            volume = cinder.volumes.create(8, name='zaza', imageRef=image.id)
            try:
                # Note(coreycb): stop_after_attempt is increased because using
                # juju storage for ceph-osd backed by cinder on undercloud
                # takes longer than the prior method of directory-backed OSD
                # devices.
                openstack.resource_reaches_status(cinder.volumes,
                                                  volume.id,
                                                  msg='volume',
                                                  stop_after_attempt=20)
                return volume
            except AssertionError:
                logging.info('retrying')
                volume.delete()
                return create_volume_from_image(cinder, image, retry=retry - 1)

        volume = create_volume_from_image(cinder, image)

        site_a_hash = zaza.openstack.utilities.ceph.get_rbd_hash(
            zaza.model.get_lead_unit_name('ceph-mon',
                                          model_name=self.site_a_model),
            'cinder-ceph',
            'volume-{}'.format(volume.id),
            model_name=self.site_a_model)
        self.wait_for_mirror_state('up+replaying',
                                   check_entries_behind_master=True,
                                   application_name=self.application_name +
                                   self.site_b_app_suffix,
                                   model_name=self.site_b_model)
        site_b_hash = zaza.openstack.utilities.ceph.get_rbd_hash(
            zaza.model.get_lead_unit_name('ceph-mon' + self.site_b_app_suffix,
                                          model_name=self.site_b_model),
            'cinder-ceph',
            'volume-{}'.format(volume.id),
            model_name=self.site_b_model)
        logging.info(site_a_hash)
        logging.info(site_b_hash)
        self.assertEqual(site_a_hash, site_b_hash)