How to build opensuse 15.6 via packer utilizing the packer-maas repo

Hello,

I am trying to build an openSUSE 15.6 image using packer-maas from GitHub. An earlier article from July 2023 mentioned that it should be possible to craft an openSUSE image using packer-maas, but it didn’t go into detail on the specific steps involved.

I encountered my first issue about missing python packages like pretty table, jinga2, etc. but managed to resolve it by commenting out certain packages that were not installed on my openSUSE 15.6 server. However, I’ve run into a second problem (attached as OpenSuse2), which suggests that my sles15.xml file might be incorrect. I have checked it against multiple XML validators, and I’m trying to validate it against the AutoYaST schema (profile.rng), but I can’t seem to find where that file has been moved to. I tried using:

wget https://github.com/openSUSE/yast-autoinstallation/blob/master/schema/profile.rng

Any assistance would be greatly appreciated. Thank you in advance!

Opensuse2

Update:
I was able to to download the yast2-schema-default, convert it to .deb, install and find the elusive profile.rng file. I ran the command above and no issues found yet I still get that above error.
Steps taken:

OUTPUT:

server@PkgBldr:~$ sudo find / -name “profile.rng”
/usr/share/YaST2/schema/autoyast/rng/profile.rng
server@PkgBldr:~$ jing /usr/share/YaST2/schema/autoyast/rng/profile.rng /home/server/packer-maas/sles15/http/sles15.xml

server@PkgBldr:~$

server@PkgBldr:~$ xmllint --noout --relaxng /usr/share/YaST2/schema/autoyast/rng/profile.rng /home/server/packer-maas/sles15/http/sles15.xml

/home/server/packer-maas/sles15/http/sles15.xml validates

Hi Magicbuzz,

I don’t have a lot of experience with SUSE, but can you verify whether you executed the jing and yamllint commands in the help dialogue, and what the result of that was?
It looks like you may be using syntax unsupported in 15.6.

Without seeing your XML, it’s a little trickier to diagnose the issue. Could you open a bug report on packer MAAS, and include all the artefacts you’ve created to get an image?

Failing that, you should be able to skip the validation with the following boot parameter:
YAST_SKIP_XML_VALIDATION=1
but obviously it’d be preferable to fix rather than skip.
(https://www.suse.com/support/kb/doc/?id=000020329)

Hi Jack and thank you for responding - regarding the jing and yamllint commands - not sure I understand in the help dialogue? I did run them against my xml with no errors found but can run anything for you once I get clarity. Below are the hcl and xml files for review (sorry for the length) and steps performed.

cat sles.pkr.hcl
packer {
  required_version = ">= 1.7.0"
  required_plugins {
    qemu = {
      version = "~> 1.0"
      source  = "github.com/hashicorp/qemu"
    }
  }
}

variable "filename" {
  type        = string
  default     = "sles15.tar.gz"
  description = "The filename of the tarball to produce"
}

variable "sles15_iso_path" {
  type    = string
  default = "${env("SLES15_ISO_PATH")}"
}

variable "timeout" {
  type        = string
  default     = "1h"
  description = "Timeout for building the image"
}

source "qemu" "sles15" {
  boot_command     = [
    "<esc><enter><wait>",
    "linux netdevice=eth0 ip=10.0.2.15 netmask=255.255.255.0 gateway=10.0.2.2 dns=10.0.2.3 install=cd:/<wait>",
    " lang=en_US autoyast=http://<localhost>/suse_repo/sles15.xml<wait>",
    " textmode=1<wait>",
    "<enter><wait>"
  ]
  boot_wait        = "3s"
  communicator     = "none"
  disk_size        = "4G"
  headless         = true
  http_directory   = "http"
  iso_checksum     = "a74d4072e639c75ca127df3d869c1e57bcc44a093a969550f348a3ead561fe4f"
  iso_url          = var.sles15_iso_path
  memory           = 4096
qemuargs = [
  ["-serial", "stdio"],
  ["-cpu", "host"],
  ["-machine", "type=pc,accel=kvm"],
  ["-netdev", "user,id=usernet,hostfwd=tcp::8080-:80,hostfwd=tcp::2222-:22"],
  ["-device", "virtio-net,netdev=usernet"]
]
  vnc_port_min     = 5900
  vnc_port_max     = 5900
  shutdown_timeout = var.timeout
}

build {
  sources = ["source.qemu.sles15"]

  post-processor "shell-local" {
    inline = [
      "SOURCE=sles15",
      "ROOT_PARTITION=2",
      "OUTPUT=${var.filename}",
      "source ../scripts/fuse-nbd",
      "source ../scripts/fuse-tar-root"
    ]
    inline_shebang = "/bin/bash -e"
  }
}

 cat sles15.xml_BKP3
<?xml version="1.0"?>
<!DOCTYPE profile>
<profile xmlns="http://www.suse.com/1.0/yast2ns" xmlns:config="http://www.suse.com/1.0/configns">
    <!--
    <add-on>
        <add_on_products config:type="list">
            <listentry>
                <media_url>
                    <![CDATA[dvd:///?devices=/dev/sr0]]>
                </media_url>
                <product>sle-module-basesystem-release</product>
                <product_dir>/Module-Basesystem</product_dir>
            </listentry>
            <listentry>
                <media_url>
                    <![CDATA[dvd:///?devices=/dev/sr0]]>
                </media_url>
                <product>sle-module-public-cloud</product>
                <product_dir>/Module-Public-Cloud</product_dir>
            </listentry>
            <listentry>
                <media_url>
                    <![CDATA[dvd:///?devices=/dev/sr0]]>
                </media_url>
                <product>sle-module-server-applications</product>
                <product_dir>/Module-Server-Applications</product_dir>
            </listentry>
            <listentry>
                <media_url>
                    <![CDATA[dvd:///?devices=/dev/sr0]]>
                </media_url>
                <product>sle-module-python3</product>
                <product_dir>/Module-Python3</product_dir>
            </listentry>
        </add_on_products>
    </add-on>
    -->
    <repository>
    <url>http://<localhost IP>/suse_repo/</url>
    <type>rpm-md</type>
</repository>
    <bootloader>
        <global>
            <activate>true</activate>
            <append>splash=silent quiet showopts</append>
            <append_failsafe>showopts apm=off noresume edd=off powersaved=off nohz=off highres=off processor.max_cstate=1 nomodeset x11failsafe</append_failsafe>
            <boot_boot>true</boot_boot>
            <boot_extended>false</boot_extended>
            <boot_mbr>true</boot_mbr>
            <boot_root>true</boot_root>
            <default>0</default>
            <distributor>Leap</distributor>
            <os_prober>false</os_prober>
            <timeout config:type="integer">8</timeout>
        </global>
        <loader_type>grub2</loader_type>
    </bootloader>
    <firewall>
        <enable_firewall config:type="boolean">false</enable_firewall>
        <start_firewall config:type="boolean">false</start_firewall>
    </firewall>
    <general>
        <ask-list config:type="list" />
        <mode>
            <final_halt config:type="boolean">true</final_halt>
            <confirm config:type="boolean">false</confirm>
        </mode>
        <proposals config:type="list" />
        <signature-handling>
            <accept_file_without_checksum config:type="boolean">true</accept_file_without_checksum>
            <accept_non_trusted_gpg_key config:type="boolean">true</accept_non_trusted_gpg_key>
            <accept_unknown_gpg_key config:type="boolean">true</accept_unknown_gpg_key>
            <accept_unsigned_file config:type="boolean">true</accept_unsigned_file>
            <accept_verification_failed config:type="boolean">false</accept_verification_failed>
            <import_gpg_key config:type="boolean">true</import_gpg_key>
        </signature-handling>
        <storage />
    </general>
    <login_settings />
    <networking>
        <dhcp_options>
            <dhclient_client_id />
            <dhclient_hostname_option>AUTO</dhclient_hostname_option>
        </dhcp_options>
        <dns>
            <dhcp_hostname config:type="boolean">false</dhcp_hostname>
            <domain>maas.io</domain>
            <hostname>sles</hostname>
            <resolv_conf_policy>auto</resolv_conf_policy>
            <write_hostname config:type="boolean">true</write_hostname>
        </dns>
        <interfaces config:type="list">
            <interface>
                <bootproto>dhcp</bootproto>
                <device>eth0</device>
                <dhclient_set_default_route>yes</dhclient_set_default_route>
                <startmode>auto</startmode>
                <usercontrol>no</usercontrol>
            </interface>
        </interfaces>
        <keep_install_network config:type="boolean">false</keep_install_network>
    </networking>
    <partitioning config:type="list">
        <drive>
            <enable_snapshots config:type="boolean">false</enable_snapshots>
            <initialize config:type="boolean">true</initialize>
            <partitions config:type="list">
                <partition>
                    <create config:type="boolean">true</create>
                    <filesystem config:type="symbol">ext4</filesystem>
                    <format config:type="boolean">true</format>
                    <mount>/</mount>
                    <mountby config:type="symbol">device</mountby>
                    <partition_id config:type="integer">131</partition_id>
                    <partition_nr config:type="integer">1</partition_nr>
                    <resize config:type="boolean">true</resize>
                    <size>max</size>
                </partition>
            </partitions>
            <use>all</use>
        </drive>
    </partitioning>
    <report>
        <errors>
            <log config:type="boolean">true</log>
            <show config:type="boolean">true</show>
            <timeout config:type="integer">0</timeout>
        </errors>
        <messages>
            <log config:type="boolean">true</log>
            <show config:type="boolean">true</show>
            <timeout config:type="integer">0</timeout>
        </messages>
        <warnings>
            <log config:type="boolean">true</log>
            <show config:type="boolean">true</show>
            <timeout config:type="integer">0</timeout>
        </warnings>
        <yesno_messages>
            <log config:type="boolean">true</log>
            <show config:type="boolean">true</show>
            <timeout config:type="integer">0</timeout>
        </yesno_messages>
    </report>
    <services-manager>
        <default_target>multi-user</default_target>
        <services>
            <disable config:type="list" />
            <enable config:type="list">
                <service>sshd</service>
            </enable>
        </services>
    </services-manager>
    <software>
    <products config:type="list">
        <product>Leap</product>
    </products>
    <packages config:type="list">
        <package>bash-completion</package>
        <!--<package>bcache-tools</package>-->
        <package>btrfsprogs</package>
        <package>bzip2</package>
        <!--<package>cloud-init</package>-->
        <package>cryptsetup</package>
        <!--<package>gcc</package>-->
        <package>glibc</package>
        <package>jfsutils</package>
        <!--<package>kernel-default-devel</package>-->
        <package>kernel-default</package>
        <package>kexec-tools</package>
        <package>lvm2</package>
        <package>make</package>
        <package>mdadm</package>
        <package>openssh</package>
        <package>perl</package>
        <package>python3-configobj</package>
        <!-- <package>python3-dist</package> -->
        <!-- <package>python3-Jinja2</package> -->
        <!-- <package>python3-jsonpatch</package> -->
        <!-- <package>python3-jsonschema</package> -->
        <!-- <package>python3-oauthlib</package> -->
        <!-- <package>python3-PrettyTable</package> -->
        <!-- <package>python3-PyYAML</package> -->
        <package>python3-requests</package>
        <package>sudo</package>
        <package>tar</package>
        <package>wget</package>
        <package>xfsprogs</package>
        <package>grub2-i386-pc</package>
        <package>grub2-x86_64-efi</package>
        <!--<package>grub2-branding-SLE</package>--> <!-- This package might be SLES-specific, consider removing it -->
    </packages>
    <patterns config:type="list">
        <pattern>base</pattern>
    </patterns>
    <remove-packages config:type="list">
        <package>adaptec-firmware</package>
        <package>atmel-firmware</package>
        <package>bash-doc</package>
        <package>cifs-utils</package>
        <package>cups-libs</package>
        <package>ipw-firmware</package>
        <package>mpt-firmware</package>
        <package>postfix</package>
        <package>samba-libs</package>
        <package>ucode-intel</package>
        <package>snapper</package>
        <package>snapper-zypp-plugin</package>
    </remove-packages>
</software>
    <timezone>
        <hwclock>UTC</hwclock>
        <timezone>UTC</timezone>
    </timezone>
    <user_defaults>
        <expire />
        <group>100</group>
        <groups>video,dialout</groups>
        <home>/home</home>
        <inactive>-1</inactive>
        <shell>/bin/bash</shell>
        <skel>/etc/skel</skel>
        <umask>022</umask>
    </user_defaults>
    <users config:type="list">
        <user>
            <encrypted config:type="boolean">false</encrypted>
            <fullname>root</fullname>
            <gid>0</gid>
            <home>/root</home>
            <password_settings>
                <expire />
                <flag />
                <inact />
                <max />
                <min />
                <warn />
            </password_settings>
            <shell>/bin/bash</shell>
            <uid>0</uid>
            <user_password>!</user_password>
            <username>root</username>
        </user>
    </users>
    <scripts>
        <chroot-scripts config:type="list">
            <script>
                    <!--  <filename>cloud-init.sh</filename>
                <interpreter>shell</interpreter>
                <chrooted config:type="boolean">true</chrooted>
                <source><![CDATA[
#!/bin/sh
systemctl enable cloud-init-local.service
systemctl enable cloud-init.service
systemctl enable cloud-config.service
systemctl enable cloud-final.service
                    ]]> -->
                </source>
            </script>
        </chroot-scripts>
        <init-scripts config:type="list">
            <script>
                <filename>clean-persistent-net.sh</filename>
                <source><![CDATA[
#!/bin/sh
cat< /dev/null > /etc/udev/rules.d/70-persistent-net.rules
sed -i s/^root:[^:]*/root:*/ /etc/shadow
rm -rf /root/.ssh
rm -rf /root/.cache
rm -rf /etc/ssh/ssh_host_*
]]>
                </source>
            </script>
        </init-scripts>
    </scripts>
</profile>

STEPS

STEPS PERFORMED FOR INSTALL

1. sudo apt-get install qemu-kvm qemu-system-x86

2. wget https://download.opensuse.org/distribution/leap/15.6/iso/openSUSE-Leap-15.6-DVD-x86_64-Media.iso

3. vi .bashrc
	# Added
	export SLES15_ISO_PATH=/home/username/openSUSE-Leap-15.6-DVD-x86_64-Media.iso

4. git clone https://github.com/canonical/packer-maas.git

5. Made various edits to sles15.hcl among those enabling KVM, added iso cksum.

6. Got an error "Could not access KVM kernel module: Permission denied" fixed it with
	- sudo usermod -aG kvm <username>

7. Made various edits to have the image builder xml file to go online and pull down various python3 images and such, did not work.
   Create local/reachable repo server and posted the images there, confirmed access to those images to no avail. Below are the links 
   to those packages should anyone want to try. 
	- wget https://download.opensuse.org/repositories/devel:/languages:/python/openSUSE_Leap_15.6/x86_64/python3-distro-1.6.0-lp156.1.1.x86_64.rpm
	- wget https://download.opensuse.org/repositories/devel:/languages:/python/openSUSE_Leap_15.6/x86_64/python3-Jinja2-2.11.2-lp156.2.5.noarch.rpm
	- wget https://download.opensuse.org/repositories/devel:/languages:/python/openSUSE_Leap_15.6/x86_64/python3-jsonpatch-1.26-lp156.1.2.noarch.rpm
	- wget https://download.opensuse.org/repositories/devel:/languages:/python/openSUSE_Leap_15.6/x86_64/python3-PrettyTable-0.7.2-lp156.1.2.noarch.rpm
	- wget https://download.opensuse.org/repositories/devel:/languages:/python/openSUSE_Leap_15.6/x86_64/python3-PyYAML-5.3.1-lp156.2.2.x86_64.rpm
	- wget https://download.opensuse.org/repositories/devel:/languages:/python/openSUSE_Leap_15.6/x86_64/python3-distro-1.6.0-lp156.1.1.x86_64.rpm


8. Commented out the following python packages in sles15.xml:
	<!-- <package>python3-dist</package> -->
        <!-- <package>python3-Jinja2</package> -->
        <!-- <package>python3-jsonpatch</package> -->
        <!-- <package>python3-jsonschema</package> -->
        <!-- <package>python3-oauthlib</package> -->
        <!-- <package>python3-PrettyTable</package> -->
        <!-- <package>python3-PyYAML</package> -->
        <!--<package>grub2-branding-SLE</package>--> <-- AI suggested commenting out this line 

9. PACKER_LOG=1 packer build sles.pkr.hcl

10. I am now getting an error related to a misconfiguration in the xml file but have checked several ways.