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:
parent
737491a816
commit
a5c6dc0977
@ -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")
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
@ -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
|
||||||
|
@ -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 }}
|
||||||
|
@ -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'
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user