diff --git a/doc/source/_static/tobiko.conf.sample b/doc/source/_static/tobiko.conf.sample index f15a3bcdc..b623f8cdc 100644 --- a/doc/source/_static/tobiko.conf.sample +++ b/doc/source/_static/tobiko.conf.sample @@ -38,9 +38,6 @@ # Default cirros password (string value) #password = -# Default cirros interface name (string value) -#interface_name = - # Default cirros SSH connection timeout (seconds) (floating point value) #connection_timeout = @@ -537,9 +534,6 @@ # Default ubuntu password (string value) #password = -# Default ubuntu interface name (string value) -#interface_name = - # Default ubuntu SSH connection timeout (seconds) (floating point value) #connection_timeout = diff --git a/releasenotes/notes/remove-CustomizedGlanceImageFixture-12e9012e57dba25a.yaml b/releasenotes/notes/remove-CustomizedGlanceImageFixture-12e9012e57dba25a.yaml new file mode 100644 index 000000000..d59ba16f1 --- /dev/null +++ b/releasenotes/notes/remove-CustomizedGlanceImageFixture-12e9012e57dba25a.yaml @@ -0,0 +1,15 @@ +--- +deprecations: + - | + CustomizedGlanceImageFixture class is not supported anymore. + This means the Ubuntu image provided via tobiko.conf, which could be customized during test execution in previous tobiko versions, + has to include all the expected customizations. + When using the tobiko ansible roles, the tobiko-download-images roles performes the required customizations by default. + The URL to download an image without any customizations and the command that are executed during the opendev jobs can be found here: + https://opendev.org/x/tobiko/src/commit/eb83ebe860dfb4206b346a822675c01f8ba82ccf/roles/tobiko-common/defaults/main.yaml#L62 + + - | + Due to the deprecation of the CustomizedGlanceImageFixture class, some configuration parameters have been deprecated at image level. + + * `interface_name` is not supported anymore because tobiko does not need to create a VLAN over that interface (the customized image already includes it). + * `customized_image_provided` boolean is not supported anymore because the provided images were previously customized. diff --git a/roles/tobiko-common/defaults/main.yaml b/roles/tobiko-common/defaults/main.yaml index 218fb3946..b7e27a1a5 100644 --- a/roles/tobiko-common/defaults/main.yaml +++ b/roles/tobiko-common/defaults/main.yaml @@ -56,6 +56,7 @@ test_log_file: '{{ test_report_dir | realpath }}/tobiko.log' # Local where test cases results are being collected to test_collect_dir: '{{ test_src_dir | realpath }}/{{ test_report_name }}' + # --- download-images options ------------------------------------------------- download_images_dir: "{{ ansible_user_dir }}/.downloaded-images" download_images: @@ -72,5 +73,10 @@ download_images: --run-command 'systemctl enable iperf3-server@5201' --run-command 'echo "8021q" >> /etc/modules' --run-command - 'echo "network:\n version: 2\n vlans:\n vlan101:\n dhcp4: true\n dhcp4-overrides:\n use-routes: false\n dhcp6: true\n dhcp6-overrides:\n use-routes: false\n id: 101\n link: {{ ubuntu_nic_name | default('ens3') }}\n" + 'echo "network:\n version: 2\n vlans:\n vlan101:\n dhcp4: true\n dhcp4-overrides:\n use-routes: false\n dhcp6: true\n dhcp6-overrides:\n use-routes: false\n id: 101\n link: {{ ubuntu_nic_name }}\n" > /etc/netplan/75-tobiko-vlan.yaml' + +# NIC name expected on Ubuntu VM instances. +# Depending on the openstack version, it has been observed the Ubuntu VM +# instances are created with an interface named 'ens3' or 'enp3s0' +ubuntu_nic_name: 'ens3' diff --git a/roles/tobiko-configure/tasks/main.yaml b/roles/tobiko-configure/tasks/main.yaml index 290d7dc28..fabfac689 100644 --- a/roles/tobiko-configure/tasks/main.yaml +++ b/roles/tobiko-configure/tasks/main.yaml @@ -25,17 +25,7 @@ - section: "{{ dict_value.type }}" option: image_url value: "file://{{ download_images_dir }}/{{ file_name }}" - {% if dict_value.customized | default(False) | bool or dict_value.customize_command_pattern is defined %} - - section: "{{ dict_value.type }}" - option: customized_image_provided - value: True - {% endif %} {% endfor %} - {% if ubuntu_nic_name is defined %} - - section: ubuntu - option: interface_name - value: "{{ ubuntu_nic_name }}" - {% endif %} vars: sections: "{{ test_default_conf | combine(test_conf, recursive=True) }}" diff --git a/tobiko/openstack/glance/__init__.py b/tobiko/openstack/glance/__init__.py index c852c947b..9d21f3fba 100644 --- a/tobiko/openstack/glance/__init__.py +++ b/tobiko/openstack/glance/__init__.py @@ -31,7 +31,6 @@ delete_image = _client.delete_image GlanceImageFixture = _image.GlanceImageFixture HasImageMixin = _image.HasImageMixin UrlGlanceImageFixture = _image.UrlGlanceImageFixture -CustomizedGlanceImageFixture = _image.CustomizedGlanceImageFixture open_image_file = _io.open_image_file diff --git a/tobiko/openstack/glance/_image.py b/tobiko/openstack/glance/_image.py index b7916ceeb..1cf2851ce 100644 --- a/tobiko/openstack/glance/_image.py +++ b/tobiko/openstack/glance/_image.py @@ -18,8 +18,8 @@ import io import os import tempfile import time -import typing # noqa -from abc import ABC, abstractmethod +import typing +from abc import ABC from urllib.parse import urlparse from oslo_log import log @@ -30,7 +30,6 @@ from tobiko.config import get_bool_env from tobiko.openstack.glance import _client from tobiko.openstack.glance import _io from tobiko.openstack import keystone -from tobiko.shell import sh LOG = log.getLogger(__name__) @@ -347,11 +346,7 @@ class UrlGlanceImageFixture(UploadGlanceImageFixture, ABC): # else, download the image return self.get_image_from_url(real_image_file) - def customize_image_file(self, base_file: str) -> str: - return base_file - def get_image_from_file(self, image_file: str): - image_file = self.customize_image_file(base_file=image_file) image_size = os.path.getsize(image_file) LOG.debug('Uploading image %r data from file %r (%d bytes)', self.image_name, image_file, image_size) @@ -418,114 +413,6 @@ class UrlGlanceImageFixture(UploadGlanceImageFixture, ABC): os.rename(temp_file, image_file) -class CustomizedGlanceImageFixture(UrlGlanceImageFixture, ABC): - - @property - def firstboot_commands(self) -> typing.List[str]: - return [] - - @property - def install_packages(self) -> typing.List[str]: - return [] - - @property - def run_commands(self) -> typing.List[str]: - return [] - - @property - def write_files(self) -> typing.Dict[str, str]: - return {} - - @property - @abstractmethod - def customization_required(self) -> bool: - pass - - username: str = '' - password: str = '' - - def _get_customized_suffix(self) -> str: - return 'customized' - - def customize_image_file(self, base_file: str) -> str: - def workaround_passt(full_command, exc): - which_passt = sh.execute( - 'which passt', expect_exit_status=None).stdout.rstrip() - if which_passt == '': - raise exc - - cmd = f'mv {which_passt} {which_passt}.bak' - cmd_cleanup = f'mv {which_passt}.bak {which_passt}' - tobiko.add_cleanup(sh.execute, cmd_cleanup, - expect_exit_status=None, sudo=True) - LOG.exception("Executing virt-customize without passt") - sh.execute(cmd, sudo=True) - sh.execute(full_command) - - # if the image does not have to be customized, then do nothing - if not self.customization_required: - return base_file - - customized_file = f'{base_file}-{self._get_customized_suffix()}' - if os.path.isfile(customized_file): - if (os.stat(base_file).st_mtime_ns < - os.stat(customized_file).st_mtime_ns): - LOG.debug(f"Image file is up to date '{customized_file}'") - return customized_file - else: - LOG.debug(f"Remove obsolete image file '{customized_file}'") - os.remove(customized_file) - work_file = sh.execute('mktemp').stdout.strip() - try: - LOG.debug(f"Copy base image file: '{base_file}' to '{work_file}'") - sh.put_file(base_file, work_file) - - options = self.get_virt_customize_options() - if options: - command = sh.shell_command(['LIBGUESTFS_BACKEND=direct', - 'virt-customize', - '-a', - work_file]) - try: - sh.execute(command + options) - except sh.ShellCommandFailed as exc: - workaround_passt(command + options, exc) - - sh.get_file(work_file, customized_file) - return customized_file - finally: - sh.execute(['rm', '-f', work_file]) - - def get_virt_customize_options(self) -> sh.ShellCommand: - options = sh.ShellCommand() - - firstboot_commands = self.firstboot_commands - if firstboot_commands: - for cmd in firstboot_commands: - options += ['--firstboot-command', cmd] - - install_packages = self.install_packages - if install_packages: - options += ['--install', ','.join(install_packages)] - - username = self.username - password = self.password - if username and password: - options += f'--password "{username}:password:{password}"' - - run_commands = self.run_commands - if run_commands: - for cmd in run_commands: - options += ['--run-command', cmd] - - write_files = self.write_files - if write_files: - for filename, content in write_files.items(): - options += ['--write', f'{filename}:{content}'] - - return options - - class InvalidGlanceImageStatus(tobiko.TobikoException): message = ("Invalid image {image_name!r} (id {image_id!r}) status: " "{actual_status!r} not in {expected_status!r}") diff --git a/tobiko/openstack/glance/config.py b/tobiko/openstack/glance/config.py index e0349049d..9c98b1d01 100644 --- a/tobiko/openstack/glance/config.py +++ b/tobiko/openstack/glance/config.py @@ -58,9 +58,6 @@ def get_images_options(): help="Default " + name + " username"), cfg.StrOpt('password', help="Default " + name + " password"), - cfg.StrOpt('interface_name', - default=None if name != 'ubuntu' else 'ens3', - help="Default " + name + " interface name"), cfg.FloatOpt('connection_timeout', default=None, help=("Default " + name + @@ -70,10 +67,6 @@ def get_images_options(): help=("Allow to disable SSH auth algorithms" "in order to SSH to old servers like" "CirrOS ones")), - cfg.BoolOpt('customized_image_provided', - default=False, - help=("Whether the provided image (URL or file) is" - "already customized or not")) ] )] diff --git a/tobiko/openstack/stacks/_ubuntu.py b/tobiko/openstack/stacks/_ubuntu.py index cff524264..49a3af8e6 100644 --- a/tobiko/openstack/stacks/_ubuntu.py +++ b/tobiko/openstack/stacks/_ubuntu.py @@ -13,8 +13,6 @@ # under the License. from __future__ import absolute_import -import typing - import tobiko from tobiko import config from tobiko.openstack import glance @@ -41,7 +39,7 @@ DefaultInstance=5201 """ -class UbuntuImageFixture(glance.CustomizedGlanceImageFixture): +class UbuntuImageFixture(glance.UrlGlanceImageFixture): """Ubuntu server image running an HTTP server The server has additional installed packages compared to @@ -68,30 +66,6 @@ class UbuntuImageFixture(glance.CustomizedGlanceImageFixture): disabled_algorithms = CONF.tobiko.ubuntu.disabled_algorithms is_reachable_timeout = CONF.tobiko.nova.ubuntu_is_reachable_timeout - def __init__(self, - ethernet_devide: str = None, - **kwargs): - super().__init__(**kwargs) - self._ethernet_device = ethernet_devide - - @property - def customization_required(self) -> bool: - return not CONF.tobiko.ubuntu.customized_image_provided - - @property - def firstboot_commands(self) -> typing.List[str]: - return super().firstboot_commands + [ - 'sh -c "hostname > /var/www/html/id"'] - - @property - def install_packages(self) -> typing.List[str]: - return super().install_packages + ['iperf3', - 'iputils-ping', - 'nano', - 'ncat', - 'nginx', - 'vlan'] - # port of running HTTP server http_port = 80 @@ -102,22 +76,6 @@ class UbuntuImageFixture(glance.CustomizedGlanceImageFixture): def iperf3_service_name(self) -> str: return f"iperf3-server@{self.iperf3_port}.service" - @property - def run_commands(self) -> typing.List[str]: - run_commands = super().run_commands - run_commands.append( - f'echo "{IPERF3_SERVICE_FILE}" ' - '> /etc/systemd/system/iperf3-server@.service') - run_commands.append( - f"systemctl enable iperf3-server@{self.iperf3_port}") - run_commands.append('echo "8021q" >> /etc/modules') - return run_commands - - ethernet_device = CONF.tobiko.ubuntu.interface_name - - def _get_customized_suffix(self) -> str: - return f'{super()._get_customized_suffix()}-{self.ethernet_device}' - @property def vlan_id(self) -> int: return tobiko.tobiko_config().neutron.vlan_id @@ -126,35 +84,6 @@ class UbuntuImageFixture(glance.CustomizedGlanceImageFixture): def vlan_device(self) -> str: return f'vlan{self.vlan_id}' - @property - def vlan_config(self) -> typing.Dict[str, typing.Any]: - return { - 'network': { - 'version': 2, - 'vlans': { - self.vlan_device: { - 'link': self.ethernet_device, - 'dhcp4': True, - 'dhcp4-overrides': { - 'use-routes': False - }, - 'dhcp6': True, - 'dhcp6-overrides': { - 'use-routes': False - }, - 'id': self.vlan_id, - } - } - } - } - - @property - def write_files(self) -> typing.Dict[str, str]: - write_files = super().write_files - write_files['/etc/netplan/75-tobiko-vlan.yaml'] = tobiko.dump_yaml( - self.vlan_config) - return write_files - class UbuntuFlavorStackFixture(_nova.FlavorStackFixture): ram = 256