Allow non admin users to upload image to glance

* Currently only users having admin related permission, has the
  ability to upload image to glance which later used to set Image/
  image_alt ref in tempest.conf. In order to make easier for non-admin
  user, this changes allow the same and if the user does not have
  permission to do the same, it will log an exception with the
  proper message as non-admin user can upload the image from CLI.

* Fixed set_default_tempest_options method for image as it is giving
  AttributeError: 'ImageService' object has no attribute 'image_path
  because image_path is set in set_image_preferences which is called
  after service_class in main.py which leads to the above error.

* Removed additional overrides image.http_image from roles

Change-Id: I3ab32b6c5628281f55193291cd367dcdb76a5571
This commit is contained in:
Chandan Kumar 2018-05-16 09:08:30 +00:00
parent 737491a816
commit a5c6dc0977
7 changed files with 34 additions and 49 deletions

View File

@ -387,10 +387,10 @@ def config_tempest(**kwargs):
flavors.create_tempest_flavors() flavors.create_tempest_flavors()
image = services.get_service('image') image = services.get_service('image')
image.set_image_preferences(kwargs.get('create', False), conf.set('image', 'http_image', kwargs.get('image_path', C.DEFAULT_IMAGE))
kwargs.get('image_path', C.DEFAULT_IMAGE), image.set_image_preferences(kwargs.get('image_disk_format',
kwargs.get('image_disk_format', C.DEFAULT_IMAGE_FORMAT),
C.DEFAULT_IMAGE_FORMAT)) kwargs.get('non_admin', False))
image.create_tempest_images(conf) image.create_tempest_images(conf)
has_neutron = services.is_service("network") has_neutron = services.is_service("network")

View File

@ -29,26 +29,22 @@ class ImageService(VersionedService):
super(ImageService, self).__init__(name, service_url, token, super(ImageService, self).__init__(name, service_url, token,
disable_ssl_validation, disable_ssl_validation,
client) client)
self.allow_creation = False
self.image_path = ""
self.disk_format = ""
def set_image_preferences(self, allow_creation, image_path, disk_format): def set_image_preferences(self, disk_format, non_admin):
"""Sets image prefferences. """Sets image prefferences.
:type allow_creation: boolean
:type image_path: string
:type disk_format: string :type disk_format: string
:type non_admin: bool
""" """
self.allow_creation = allow_creation
self.image_path = image_path
self.disk_format = disk_format self.disk_format = disk_format
self.non_admin = non_admin
def set_default_tempest_options(self, conf): def set_default_tempest_options(self, conf):
# When cirros is the image, set validation.image_ssh_user to cirros. # When cirros is the image, set validation.image_ssh_user to cirros.
# The option is heavily used in CI and it's also usefull for refstack, # The option is heavily used in CI and it's also usefull for refstack,
# because we don't have to specify overrides. # because we don't have to specify overrides.
if 'cirros' in self.image_path.rsplit('/')[-1]: if 'cirros' in conf.get_defaulted('image',
'http_image').rsplit('/')[-1]:
conf.set('validation', 'image_ssh_user', 'cirros') conf.set('validation', 'image_ssh_user', 'cirros')
def set_versions(self): def set_versions(self):
@ -63,9 +59,10 @@ class ImageService(VersionedService):
:type conf: TempestConf object :type conf: TempestConf object
""" """
img_dir = os.path.join(conf.get("scenario", "img_dir")) img_dir = os.path.join(conf.get("scenario", "img_dir"))
image_path = conf.get_defaulted('image', 'http_image')
img_path = os.path.join(img_dir, img_path = os.path.join(img_dir,
os.path.basename(self.image_path)) os.path.basename(image_path))
name = self.image_path[self.image_path.rfind('/') + 1:] name = image_path[image_path.rfind('/') + 1:]
if not os.path.exists(img_dir): if not os.path.exists(img_dir):
try: try:
os.makedirs(img_dir) os.makedirs(img_dir)
@ -77,13 +74,13 @@ class ImageService(VersionedService):
if conf.has_option('compute', 'image_ref'): if conf.has_option('compute', 'image_ref'):
image_id = conf.get('compute', 'image_ref') image_id = conf.get('compute', 'image_ref')
image_id = self.find_or_upload_image(image_id, name, image_id = self.find_or_upload_image(image_id, name,
image_source=self.image_path, image_source=image_path,
image_dest=img_path) image_dest=img_path)
alt_image_id = None alt_image_id = None
if conf.has_option('compute', 'image_ref_alt'): if conf.has_option('compute', 'image_ref_alt'):
alt_image_id = conf.get('compute', 'image_ref_alt') alt_image_id = conf.get('compute', 'image_ref_alt')
alt_image_id = self.find_or_upload_image(alt_image_id, alt_name, alt_image_id = self.find_or_upload_image(alt_image_id, alt_name,
image_source=self.image_path, image_source=image_path,
image_dest=img_path) image_dest=img_path)
conf.set('compute', 'image_ref', image_id) conf.set('compute', 'image_ref', image_id)
@ -99,10 +96,6 @@ class ImageService(VersionedService):
:type image_dest: string :type image_dest: string
""" """
image = self._find_image(image_id, image_name) image = self._find_image(image_id, image_name)
if not image and not self.allow_creation:
raise Exception("Image '%s' not found, but resource creation"
" isn't allowed. Either use '--create' or provide"
" an existing image_ref" % image_name)
if image: if image:
LOG.info("(no change) Found image '%s'", image['name']) LOG.info("(no change) Found image '%s'", image['name'])
@ -143,13 +136,18 @@ class ImageService(VersionedService):
:type name: string :type name: string
:type path: string :type path: string
""" """
LOG.info("Uploading image '%s' from '%s'", name, os.path.abspath(path)) LOG.info("Uploading image '%s' from '%s'",
name, os.path.abspath(path))
if self.non_admin:
visibility = 'community'
else:
visibility = 'public'
with open(path) as data: with open(path) as data:
image = self.client.create_image(name=name, image = self.client.create_image(name=name,
disk_format=self.disk_format, disk_format=self.disk_format,
container_format='bare', container_format='bare',
visibility="public") visibility=visibility)
self.client.store_image_file(image['id'], data) self.client.store_image_file(image['id'], data)
return image return image

View File

@ -36,14 +36,14 @@ class TestImageService(BaseServiceTest):
self.FAKE_URL, self.FAKE_URL,
self.FAKE_TOKEN, self.FAKE_TOKEN,
disable_ssl_validation=False) disable_ssl_validation=False)
self.Service.allow_creation = False
self.Service.image_path = "my_path/my_image.qcow2"
self.Service.disk_format = ".format" self.Service.disk_format = ".format"
self.Service.non_admin = False
self.Service.client = self.FakeServiceClient() self.Service.client = self.FakeServiceClient()
self.dir = "/img/" self.dir = "/img/"
self.conf = TempestConf() self.conf = TempestConf()
self.conf.set("scenario", "img_dir", self.dir) self.conf.set("scenario", "img_dir", self.dir)
self.conf.set("image", "http_image", "my_image.qcow2")
@mock.patch('config_tempest.services.image.ImageService' @mock.patch('config_tempest.services.image.ImageService'
'.find_or_upload_image') '.find_or_upload_image')
@ -68,7 +68,6 @@ class TestImageService(BaseServiceTest):
image_source = format + "://any_random_url" image_source = format + "://any_random_url"
image_dest = "my_dest" image_dest = "my_dest"
image_name = "my_image" image_name = "my_image"
self.Service.allow_creation = True
image_id = self.Service.find_or_upload_image( image_id = self.Service.find_or_upload_image(
image_id=None, image_dest=image_dest, image_id=None, image_dest=image_dest,
image_name=image_name, image_source=image_source) image_name=image_name, image_source=image_source)
@ -143,7 +142,6 @@ class TestImageService(BaseServiceTest):
image_source = "ftp://any_random_url" image_source = "ftp://any_random_url"
image_dest = "place_on_disk" image_dest = "place_on_disk"
image_name = "my_image" image_name = "my_image"
self.Service.allow_creation = True
image_id = self.Service.find_or_upload_image( image_id = self.Service.find_or_upload_image(
image_id=None, image_name=image_name, image_id=None, image_name=image_name,
image_source=image_source, image_dest=image_dest) image_source=image_source, image_dest=image_dest)

View File

@ -0,0 +1,8 @@
---
features:
- |
Allow all users irrespective of Admin and non-admin to upload images to
glance and generate image_ref and image_ref_alt for compute.
- |
image.http_image name is set based on the image name passed or if not
passed is taken from the default one.

View File

@ -36,7 +36,7 @@
--create \ --create \
--os-cloud {{ cloud_user }} \ --os-cloud {{ cloud_user }} \
auth.tempest_roles Member \ auth.tempest_roles Member \
service_available.swift False \ service_available.swift False
args: args:
chdir: "{{ tempestconf_src_relative_path }}" chdir: "{{ tempestconf_src_relative_path }}"
executable: /bin/bash executable: /bin/bash

View File

@ -18,4 +18,4 @@ discover-tempest-config \
identity.uri $OS_AUTH_URL \ identity.uri $OS_AUTH_URL \
identity.admin_password $OS_PASSWORD \ identity.admin_password $OS_PASSWORD \
service_available.swift False \ service_available.swift False \
{{ aditional_tempestconf_params }} \ {{ aditional_tempestconf_params }}

View File

@ -19,22 +19,3 @@
with_items: with_items:
- { name: "m1.nano", ram: 64 } - { name: "m1.nano", ram: 64 }
- { name: "m1.micro", ram: 128 } - { name: "m1.micro", ram: 128 }
- name: Download cirros image
get_url:
url: "{{ url_cirros_image }}"
dest: "{{ tempestconf_src_relative_path }}/etc/"
mode: 0660
- name: Create image and image alt for demo user
shell: |
set -x
openstack image create --os-cloud {{ cloud_admin }} \
--disk-format qcow2 \
--public \
--file {{ tempestconf_src_relative_path }}/etc/{{ url_cirros_image | basename }} \
{{ item }}
with_items:
- "{{ url_cirros_image | basename }}"
- '{{ url_cirros_image | basename }}_alt'