diff --git a/installvm.py b/installvm.py index 26abd07..1173d58 100644 --- a/installvm.py +++ b/installvm.py @@ -20,6 +20,8 @@ import re import netaddr import time +import json +import posixpath import logging import logging.config from datetime import datetime @@ -152,6 +154,8 @@ def configDHCP(self): cmd = 'rm -rf /tmp/dhcpd.conf' self.runCommand(self.dhcpSrvCon, cmd) cmd = 'setenforce Permissive' + if 'restart dhcpd' in cmd: + self.runCommand(self.dhcpSrvCon, 'dhcpd -t -cf /etc/dhcp/dhcpd.conf') self.runCommand(self.dhcpSrvCon, cmd) cmd = 'systemctl restart dhcpd' self.runCommand(self.dhcpSrvCon, cmd) @@ -315,7 +319,7 @@ def copyNetbootImage(self): + self.repoDir + '/boot/grub/powerpc-ieee1275/core.elf -P ' + \ self.destDir+"/boot/grub/powerpc-ieee1275/" self.runCommand(self.nxtSrvCon, cmd) - self.filename = vmParser.netDir + '/boot/grub/powerpc-ieee1275/core.elf' + self.filename = vmParser.netDir + '/boot/grub/powerpc-ieee1275/core.elf' def createKickstart(self): logging.info("Prepareing kick start file") @@ -334,9 +338,16 @@ def createKickstart(self): else: host_disk = '' disks = vmParser.args.host_disk.split(',') - for disk in disks: - host_disk += '/dev/disk/by-id/' + disk+',' - vmParser.args.host_disk = host_disk.rstrip(',') + #for disk in disks: + # host_disk += '/dev/disk/by-id/' + disk+',' + #vmParser.args.host_disk = host_disk.rstrip(',') + full_disks = ["/dev/disk/by-id/" + disk.strip() for disk in disks] + boot_disk = full_disks[0] # /boot only on first disk + root_disks = full_disks # / can be on all disks (RAID or not) + vmParser.args.host_disk = ",".join(full_disks) + print(f"{boot_disk}") + print(f"{root_disks}") + if vmParser.args.install_protocol == 'http': if version.startswith('8') or version.startswith('9') or version.startswith('10'): @@ -347,9 +358,7 @@ def createKickstart(self): lstr = "telnet\njava\n%end" urlstring = "--url=http://"+vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ self.repoDir - - if vmParser.args.install_protocol == 'ftp': - # username:password@server/ + elif vmParser.args.install_protocol == 'ftp': if version.startswith('8') or version.startswith('9') or version.startswith('10'): lstr = "%end" urlstring = "--url=ftp://" + \ @@ -359,8 +368,7 @@ def createKickstart(self): lstr = "telnet\njava\n%end" urlstring = "--url=ftp://" + \ vmParser.confparser('repo', 'RepoIP') + ':' + self.repoDir - - if vmParser.args.install_protocol == 'nfs': + elif vmParser.args.install_protocol == 'nfs': if version.startswith('8') or version.startswith('9') or version.startswith('10'): lstr = "%end" urlstring = "--url=nfs://" + \ @@ -371,42 +379,47 @@ def createKickstart(self): urlstring = "--url=nfs://" + \ vmParser.confparser('repo', 'RepoIP') + \ ':/var/www/html' + self.repoDir - - if vmParser.args.fs_type == 'btrfs': - if vmParser.args.partition_type == 'plain': - addksstring = "autopart --fstype=btrfs" - else: - addksstring = "autopart --type=lvm --fstype=btrfs" - elif vmParser.args.fs_type == 'ext4': - if vmParser.args.partition_type == 'plain': - addksstring = "autopart --fstype=ext4" - else: - addksstring = "autopart --type=lvm --fstype=ext4" else: - if vmParser.args.partition_type == 'plain': - addksstring = "autopart --fstype=xfs" - else: - addksstring = "autopart --type=lvm --fstype=xfs" + logging.error(f"Unsupported install protocol: {vmParser.args.install_protocol}") + exit(1) - exit_nosupport = 0 - if vmParser.args.partition_type not in ['lvm', 'plain']: - logging.info("Aborting Installation : as partition type %s is not supported or not valid" % - vmParser.args.partition_type) - exit_nosupport = 1 + fs_type = vmParser.args.fs_type.lower() + part_type = vmParser.args.partition_type.lower() + if fs_type not in ['xfs', 'ext4', 'btrfs']: + logging.error(f"Unsupported filesystem type: {fs_type}") + exit(1) + if part_type not in ['lvm', 'plain', 'raid']: + logging.error(f"Unsupported partition type: {part_type}") + exit(1) - if vmParser.args.fs_type not in ['xfs', 'ext4', 'btrfs']: - logging.info( - "Aborting Installation : as filesystem type %s is not supported or not valid" % vmParser.args.fs_type) - exit_nosupport = 1 + # Kernel params string + kernel_params = '' + if vmParser.args.kernel_params: + kernel_params = f' --append="{vmParser.args.kernel_params}"' - if vmParser.args.install_protocol not in ['http', 'nfs', 'ftp']: - logging.info("Aborting Installation : as install protocol type %s is not supported or not valid" % - vmParser.args.install_protocol) - exit_nosupport = 1 + if part_type == 'plain': + partitioning = f"autopart --fstype={fs_type}" + elif part_type == 'lvm': + partitioning = f"autopart --type=lvm --fstype={fs_type}" + elif part_type == 'raid': + if len(root_disks) < 2: + logging.error("RAID requires at least two disks") + exit(1) - if exit_nosupport: - exit(1) + raid_parts = [] + for i, disk in enumerate(root_disks, 1): + raid_parts.append(f"part raid.{i:02d} --fstype=mdmember --size=1 --grow --ondisk={disk}") + raid_part_lines = "\n".join(raid_parts) + prep_part = f"part prepboot --fstype=prepboot --size=8 --ondisk={boot_disk}" + boot_part = f"part /boot --fstype={fs_type} --size=2048 --ondisk={boot_disk}" + raid_root = f"raid / --fstype={fs_type} --level=1 --device=md1 " + \ + " ".join([f"raid.{i:02d}" for i in range(1, len(root_disks)+1)]) + + partitioning = f"{prep_part}\n{boot_part}\n{raid_part_lines}\n{raid_root}" + else: + logging.error(f"Unknown partition_type: {part_type}") + exit(1) ksparm = sftp.open('/var/www/html'+self.ksinst, 'w') sshd_file = '' kernel_params = '' @@ -414,26 +427,84 @@ def createKickstart(self): kernel_params = " --append="+'\"'+vmParser.args.kernel_params+'\"' mpath_file = ";multipath -t >/etc/multipath.conf;service multipathd start" if vmParser.args.multipathsetup != '': - sshd_file = "\n%post \n"+mpath_file+"\n%end" + sshd_file = "\n%post \n"+mpath_file+"\n" if version.startswith('9') or version.startswith('10'): - sshd_file = "\n%post \nsed -i 's/#\?PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config;service sshd restart"+mpath_file+"\n%end" + sshd_file = "\n%post \nsed -i 's/#\?PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config;service sshd restart"+mpath_file+"\n" if version.startswith('10'): timezone = "" else: timezone = "--isUtc" - inst_param = "%pre\n%end\nurl "+urlstring, "\ntext\nkeyboard"\ - " --vckeymap=us --xlayouts='us'\nlang en_US.UTF-8\n"\ - "rootpw --plaintext " + vmParser.args.host_password, \ - "\nskipx\ntimezone Asia/Kolkata " + timezone, \ - "\nzerombr" \ - "\nclearpart --all --initlabel "\ - "--drives=" + vmParser.args.host_disk, \ - "\nbootloader --location=mbr --boot-drive=" + vmParser.args.host_disk+kernel_params, \ - "\nignoredisk --only-use=" + vmParser.args.host_disk, \ - "\n" + addksstring, \ - "\nservices --enabled=NetworkManager,sshd" \ - "\nreboot\n%packages\n@core\nkexec-tools\ndevice-mapper-multipath\n"+lstr+sshd_file + inst_param = ( + "%pre --interpreter /bin/bash\n" + " DISK_LIST=\"{{ vmParser.args.host_disk }}\"\n" + " for dev in $DISK_LIST; do\n" + " echo \"Wiping $dev ...\"\n" + " dd if=/dev/zero of=$dev bs=512 count=2048 status=none\n" + " done\n" + "%end\n" + "url " + urlstring + "\n" + "text\n" + "keyboard --vckeymap=us --xlayouts='us'\n" + "lang en_US.UTF-8\n" + "rootpw --plaintext " + vmParser.args.host_password + "\n" + "skipx\n" + "timezone Asia/Kolkata " + timezone + "\n" + "zerombr\n" + "clearpart --all --initlabel --drives=" + vmParser.args.host_disk + "\n" + "bootloader --location=mbr --boot-drive=" + boot_disk + kernel_params + "\n" + "ignoredisk --only-use=" + vmParser.args.host_disk + "\n" + + partitioning + "\n" + "services --enabled=NetworkManager,sshd\n" + "reboot\n" + "%packages\n" + "@core\n" + "kexec-tools\n" + "device-mapper-multipath\n" + + lstr + sshd_file + + "\n" + "--interpreter /bin/bash\n" + " exec > /root/post-install.log 2>&1\n" + " set -x\n" + "\n" + " echo \">> Determining boot disk from /boot mount\"\n" + " BOOTDISK=$(lsblk -P -o NAME,TYPE,MOUNTPOINT | awk '\n" + " {\n" + " name=\"\"; mount=\"\";\n" + " for (i = 1; i <= NF; i++) {\n" + " if ($i ~ /^NAME=/) {\n" + " gsub(/NAME=|\"/, \"\", $i);\n" + " name = $i;\n" + " }\n" + " if ($i ~ /^MOUNTPOINT=\"\\/boot\"/) {\n" + " gsub(/MOUNTPOINT=|\"/, \"\", $i);\n" + " mount = $i;\n" + " }\n" + " }\n" + " if (mount == \"/boot\") {\n" + " cmd = \"lsblk -ndo PKNAME /dev/\" name;\n" + " cmd | getline parent;\n" + " close(cmd);\n" + " print \"/dev/\" parent;\n" + " exit;\n" + " }\n" + " }')\n" + "\n" + " echo \">> Setting bootlist to $BOOTDISK\"\n" + " bootlist -m normal $BOOTDISK -o\n" + "\n" + " echo \">> Configuring SSH to skip StrictHostKeyChecking\"\n" + " mkdir -p /root/.ssh\n" + " cat < /root/.ssh/config\n" + "Host *\n" + " StrictHostKeyChecking no\n" + " UserKnownHostsFile /dev/null\n" + "EOF\n" + " chmod 600 /root/.ssh/config\n" + "\n" + " # Optional: Uncomment to install your SSH key\n" + " %end\n" + ) ksparm.writelines(inst_param) ksparm.sftp.close() @@ -452,20 +523,23 @@ def configGrub(self): vmParser.confparser(vmParser.domain, 'NextServer') + '\n') gfd.write(' echo \'Loading OS Install kernel ...\'\n') installer_string = '' + httppath="(http,"+vmParser.confparser('repo', 'RepoIP')+":"+ vmParser.confparser('repo', 'RepoPort')+")" + httplinux="/"+self.repoDir+'/ppc/ppc64/vmlinuz ' + httpintrd="/"+self.repoDir+'/ppc/ppc64/initrd.img' if version.startswith('10'): installer_string = ' inst.text inst.xtimeout=300' cli_nw = 'ifname=net0:' + vmParser.args.host_mac + ' ip=' + vmParser.args.host_ip + '::' + \ vmParser.args.host_gw + ':' + vmParser.args.host_netmask + ':' + \ vmParser.args.host_name + ':' + 'net0:none' + ' nameserver=' + \ vmParser.confparser(vmParser.domain, 'DNS') - strLnx = ' linux ' + vmParser.netDir + '/ppc/ppc64/vmlinuz ' + cli_nw + \ + strLnx = ' linux ' + httppath + httplinux + cli_nw + \ ' inst.repo=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ self.repoDir + \ ' inst.ks=http://' + \ vmParser.confparser('kshost', 'Host') + \ self.ksinst + installer_string+'\n' gfd.write(strLnx) - strInit = ' initrd ' + vmParser.netDir + '/ppc/ppc64/initrd.img\n' + strInit = ' initrd ' + httppath + httpintrd+'\n' gfd.write(strInit) gfd.write('}\n') gfd.sftp.close() @@ -478,58 +552,254 @@ def configGrub(self): class Sles(Distro): def copyNetbootImage(self): - logging.info("Copyt netboot image to tftp server") + logging.info("Copying netboot image to TFTP server") cutdir = len(list(filter(None, self.repoDir.split('/')))) cmd = 'rm -rf ' + self.destDir self.runCommand(self.nxtSrvCon, cmd) - cmd = 'mkdir ' + self.destDir + cmd = 'mkdir -p ' + self.destDir self.runCommand(self.nxtSrvCon, cmd) - if '16SP' in version.upper(): - cmd = 'wget -r --reject="index.html*" --no-parent -nH --cut-dir=' + str(cutdir) + ' http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + self.repoDir + '/LiveOS/squashfs.img -P ' + self.destDir + '/LiveOS/' - self.runCommand(self.nxtSrvCon, cmd) + + if '11SP' in version.upper(): cmd = 'wget -r --reject="index.html*" --no-parent -nH --cut-dir=' + str(cutdir) \ + ' http://' + vmParser.confparser('repo', 'RepoIP') + ':' \ + vmParser.confparser('repo', 'RepoPort') \ - + self.repoDir + '/boot/' + ' -P ' + self.destDir + + self.repoDir + '/suseboot/' + ' -P ' + self.destDir self.runCommand(self.nxtSrvCon, cmd) - print("second cmd: {cmd}") - cmd = 'grub2-mknetdir --net-directory=' + self.baseURL + ' --subdir=' + vmParser.netDir + '/boot/ppc64le/grub2-ieee1275/' - print(cmd) - self.runCommand(self.nxtSrvCon, cmd) - src_cfg = self.destDir + '/boot/grub2/grub.cfg' - dest_cfg = self.destDir + '/boot/ppc64le/grub2-ieee1275/grub.cfg' - cmd = f'cp {src_cfg} {dest_cfg}' + cmd = 'mv ' + self.destDir + '/suseboot/yaboot.ibm ' + self.destDir + '/suseboot/yaboot.suse' + self.runCommand(self.nxtSrvCon, cmd) + self.filename = vmParser.netDir + '/suseboot/yaboot.suse' + else: + cmd = 'wget -r --reject="index.html*" --no-parent -nH --cut-dir=' + str(cutdir) + ' http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + self.repoDir + '/LiveOS/squashfs.img -P ' + self.destDir + '/LiveOS/' + self.runCommand(self.nxtSrvCon, cmd) + # cmd = 'wget -r --reject="index.html*" --no-parent -nH --cut-dir=' + str(cutdir) + \ + # ' http://' + vmParser.confparser('repo', 'RepoIP') + ':' + \ + # vmParser.confparser('repo', 'RepoPort') + self.repoDir + '/install/' + \ + # ' -P ' + self.destDir self.runCommand(self.nxtSrvCon, cmd) - self.runCommand(self.nxtSrvCon, 'chmod 777 -R ' + self.destDir) - self.filename = vmParser.netDir + '/boot/ppc64le/grub2-ieee1275/powerpc-ieee1275/core.elf' - elif '15SP' in version.upper(): cmd = 'wget -r --reject="index.html*" --no-parent -nH --cut-dir=' + str(cutdir) \ + ' http://' + vmParser.confparser('repo', 'RepoIP') + ':' \ + vmParser.confparser('repo', 'RepoPort') \ + self.repoDir + '/boot/' + ' -P ' + self.destDir self.runCommand(self.nxtSrvCon, cmd) - cmd = 'grub2-mknetdir --net-directory=' + self.baseURL + \ - ' --subdir=' + vmParser.netDir + '/boot/ppc64le/grub2-ieee1275/' + cmd = 'grub2-mknetdir --net-directory=' + self.baseURL + ' --subdir=' + vmParser.netDir + '/boot/ppc64le/grub2-ieee1275/' self.runCommand(self.nxtSrvCon, cmd) - cmd = 'wget -r --reject="index.html*" --no-parent -nH --cut-dir=' + str(cutdir) \ - + ' http://' + vmParser.confparser('repo', 'RepoIP') + ':' \ - + vmParser.confparser('repo', 'RepoPort') \ - + self.repoDir + '/boot/ppc64le/grub2-ieee1275/core.elf -P ' + \ - self.destDir+"/boot/ppc64le/grub2-ieee1275/powerpc-ieee1275/" + # Step 3: Copy or symlink the correct grub.cfg to the expected location + src_cfg = self.destDir + '/boot/grub2/grub.cfg' + dest_cfg = self.destDir + '/boot/ppc64le/grub2-ieee1275/grub.cfg' + cmd = f'cp {src_cfg} {dest_cfg}' self.runCommand(self.nxtSrvCon, cmd) + if '16' not in version: + cmd = 'wget -r --reject="index.html*" --no-parent -nH --cut-dir=' + str(cutdir) \ + + ' http://' + vmParser.confparser('repo', 'RepoIP') + ':' \ + + vmParser.confparser('repo', 'RepoPort') \ + + self.repoDir + '/boot/ppc64le/grub2-ieee1275/core.elf -P ' + self.destDir + '/boot/ppc64le/grub2-ieee1275/powerpc-ieee1275/' + self.runCommand(self.nxtSrvCon, cmd) self.runCommand(self.nxtSrvCon, 'chmod 777 -R ' + self.destDir) - self.filename = vmParser.netDir + \ - '/boot/ppc64le/grub2-ieee1275/powerpc-ieee1275/core.elf' - else: - cmd = 'wget -r --reject="index.html*" --no-parent -nH --cut-dir=' + str(cutdir) \ - + ' http://' + vmParser.confparser('repo', 'RepoIP') + ':' \ - + vmParser.confparser('repo', 'RepoPort') \ - + self.repoDir + '/suseboot/' + ' -P ' + self.destDir - self.runCommand(self.nxtSrvCon, cmd) - cmd = 'mv ' + self.destDir + '/suseboot/yaboot.ibm ' + \ - self.destDir + '/suseboot/yaboot.suse' - self.runCommand(self.nxtSrvCon, cmd) - self.filename = vmParser.netDir + '/suseboot/yaboot.suse' + self.filename = vmParser.netDir + '/boot/ppc64le/grub2-ieee1275/powerpc-ieee1275/core.elf' + + def createKickstart(self): + logging.info("Preparing kickstart file for SLES15") + self.KsHost = paramiko.SSHClient() + self.KsHost.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + self.KsHost.connect(vmParser.confparser('kshost', 'Host'), + username=vmParser.confparser('kshost', 'User'), + password=vmParser.confparser('kshost', 'Password')) + + sftp = self.KsHost.open_sftp() + self.ksinst = vmParser.confparser('kshost', 'KsDir') + '/' + distro + '/' + distro + '-' + vmParser.args.host_mac + '.ks' + + partition_string = '' + multipath_string = '' + kernel_params = 'mitigations=auto quiet crashkernel=1024M ' + if vmParser.args.kernel_params: + kernel_params = f"{kernel_params} {vmParser.args.kernel_params}" + + if vmParser.args.multipathsetup: + multipath_string = '\n true\n' + + if vmParser.args.host_disk: + vmParser.args.host_disk = '/dev/disk/by-id/' + vmParser.args.host_disk + partition_string = f"{vmParser.args.host_disk} all" + else: + partition_string = """all + + + / + max + + + +sle-module-python2 +/Module-Python2 + +""" + + value = ["SP4", "SP3", "SP1", "SP5"] + if any(x in subversion for x in value): + python_str = '' + + sles15_url = f""" + + + +sle-module-server-applications +/{subversion}Module-Server-Applications + +""" \ + f""" + +sle-module-legacy +/{subversion}Module-Legacy + +""" \ + f""" + +sle-module-development-tools +/{subversion}Module-Development-Tools + +""" \ + f""" + +sle-module-desktop-applications +/{subversion}Module-Desktop-Applications + +""" \ + f""" + +sle-module-basesystem +/{subversion}Module-Basesystem + +""" + python_str + """ + +""" + + sles_package = "sles-releasesle-module-server-applications-release" \ + "sle-module-legacy-release" \ + "sle-module-development-tools-releasesle-module-desktop-applications-release" \ + "sle-module-basesystem-releasejava-11-openjdkapparmor" \ + "base" \ + "basesystemenhanced_basefontsgnome_basic" \ + "gnome_basisminimal_basesw_managementx11" \ + "x11_enhancedx11_yastyast2_basis" + else: + sles15_url = f""" + + + +sle-module-server-applications +/ + + + +""" + sles_package = "java-1_8_0-openjdk" + + print(self.ksinst) + ksparm = sftp.open('/var/www/html' + self.ksinst, 'w') + inst_param = f""" + + +""" + \ + sles15_url + \ + f""" + +{kernel_params} +crashkernel=1024M\<4G + + +""" + \ + f""" +true +1024M +1024M\<4G + +""" + \ + f""" + +false +{vmParser.args.host_password} +root + + +""" + \ + f""" + +false + +{multipath_string} +""" + \ + f""" + +{partition_string} + +""" + \ + f""" +multi-user + + +sshd + + + +""" + \ + f""" +false +false + +""" + \ + f""" + +{host_name} + +false + +false + +true + +""" + \ + f""" + +gcc +multipath-tools +kdump +gcc-c++ +""" + \ + sles_package + \ + f""" + + + + + +""" + ksparm.writelines(inst_param) + ksparm.sftp.close() + + + def createAutoyastJsonnet(self): logging.info("Generating dynamic autoyast.jsonnet for SLES16") @@ -538,202 +808,70 @@ def createAutoyastJsonnet(self): self.KsHost.connect(vmParser.confparser('kshost', 'Host'), username=vmParser.confparser('kshost', 'User'), password=vmParser.confparser('kshost', 'Password')) + print ("in json net") sftp = self.KsHost.open_sftp() - self.ksinst = vmParser.confparser('kshost', 'KsDir') + '/sles/' + vmParser.args.host_mac + '.jsonnet' + self.ksinst = vmParser.confparser('kshost', 'KsDir') + '/sles16/' + vmParser.args.host_mac + '.jsonnet' remote_path = '/var/www/html' + self.ksinst ip_cidr = f"{vmParser.args.host_ip}/{netaddr.IPNetwork(vmParser.args.host_ip + '/' + vmParser.args.host_netmask).prefixlen}" - if vmParser.args.host_disk: - if "-" not in vmParser.args.host_disk: - print(f"ERROR: '{vmParser.args.host_disk}' looks like a device name. Provide a valid disk ID from /dev/disk/by-id/", file=sys.stderr) - sys.exit(1) - disk_id = f"/dev/disk/by-id/{vmParser.args.host_disk}" + disk_id = f"/dev/disk/by-id/{vmParser.args.host_disk}" nameserver = vmParser.confparser(vmParser.domain, 'DNS') - pre_script_block = '' - post_script_block = '' - scripts_block = '' - pre_script_block = """{ - name: "activate-multipath", - content: ||| - #!/usr/bin/bash - systemctl start multipathd.socket multipathd.service - ||| - }""" - post_script_block = """{ - name: "permit-root-login", - content: ||| - #!/bin/bash - ssh_file="/usr/etc/ssh/sshd_config" - backup_file="/usr/etc/ssh/sshd_config.bak.$(date +%F_%T)" - cp "$ssh_file" "$backup_file" - if grep -q "^PermitRootLogin" "$ssh_file"; then - sed -i "s/^PermitRootLogin.*/PermitRootLogin yes/" "$ssh_file" - else - echo "PermitRootLogin yes" >> "$ssh_file" - fi - systemctl enable sshd.service - ||| - }""" + pre_script = '' + print("++++++++++") + #if vmParser.args.multipathsetup: if "mpath" in vmParser.args.host_disk: - scripts_block = f""" scripts: {{ - pre: [ - {pre_script_block} - ], - post: [ - {post_script_block} - ] - }}""" - else: - scripts_block = f""" scripts: {{ - post: [ - {post_script_block} - ] - }}""" - + pre_script = ''' "scripts": { + "pre": [ + { + "name": "activate-multipath", + "content": "|||\n#!/usr/bin/bash\nsystemctl start multipathd.socket multipathd.service\n|||" + } + ] + },''' jsonnet_content = f'''{{ "bootloader": {{ "stopOnBootMenu": false }}, "user": {{ "fullName": "abc", "userName": "abc", "password": "abc123", "hashedPassword": false, "autologin": false }}, - "root": {{ "hashedPassword": false, "password": "{vmParser.args.host_password}" }}, + "root": {{ "sshPublicKey": "ssh-ed25519 AAAAC3...", "hashedPassword": false, "password": "{vmParser.args.host_password}" }}, "software": {{ "patterns": [] }}, "product": {{ "id": "SLES" }}, "storage": {{ "drives": [{{ "search": "{disk_id}", "partitions": [{{ "search": "*", "delete": true }}, {{ "filesystem": {{ "path": "/" }}, "size": {{ "min": "10 GiB" }} }}, {{ "filesystem": {{ "path": "swap" }}, "size": {{ "min": "1 GiB", "max": "4 GiB" }} }}] }}] }}, "network": {{ - "connections": [{{ "id": "Wired Connection", "method4": "manual", "gateway4": "{vmParser.args.host_gw}", "method6": "disabled", "addresses": ["{ip_cidr}"], "nameservers": ["{nameserver}"], "ignoreAutoDns": false, "status": "up", "autoconnect": true }}] + "connections": [{{ "id": "eth0", "method4": "manual", "gateway4": "{vmParser.args.host_gw}", "method6": "disabled", "addresses": ["{ip_cidr}"], "nameservers": ["{nameserver}"], "ignoreAutoDns": false, "status": "up", "autoconnect": true }}] }}, "localization": {{ "language": "en_US.UTF-8", "keyboard": "us", "timezone": "Europe/Berlin" }}, -{scripts_block} +{pre_script} }}''' + ''' + audit_log = f"/LOGS/jsonnet-{vmParser.args.host_mac}.log" + print ("0000000000000000") + with open(audit_log, 'w') as audit_fd: + audit_fd.write(jsonnet_content) + ''' + #logging.info(f"Saved autoyast.jsonnet for audit: {audit_log}") + + #remote_dir = posixpath.dirname(remote_path) + '''' + try: + sftp.stat(remote_dir) + except FileNotFoundError: + sftp.mkdir(remote_dir) + ''' + print ("4444444444444") with sftp.open(remote_path, 'w') as jfd: jfd.write(jsonnet_content) sftp.close() - - def createKickstart(self): - logging.info("Prepareing kick start file") - self.KsHost = paramiko.SSHClient() - self.KsHost.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - self.KsHost.connect(vmParser.confparser('kshost', 'Host'), - username=vmParser.confparser( - 'kshost', 'User'), - password=vmParser.confparser('kshost', 'Password')) - - sftp = self.KsHost.open_sftp() - self.ksinst = vmParser.confparser( - 'kshost', 'KsDir') + '/' + distro+'/'+distro+'-' + vmParser.args.host_mac + '.ks' - - partition_string = '' - multipath_string = '' - kernel_params = 'mitigations=auto quiet crashkernel=1024M ' - if not vmParser.args.kernel_params: - kernel_params = "%s %s" % ( - kernel_params, vmParser.args.kernel_params) - - if vmParser.args.multipathsetup != '': - multipath_string = "\ntrue\n" - if vmParser.args.host_disk != '': - vmParser.args.host_disk = '/dev/disk/by-id/' + vmParser.args.host_disk - partition_string = ""+vmParser.args.host_disk+"\nall" - else: - partition_string = "all\n\n\n/\nmax\n\n\n" - - host_name = '' - if vmParser.args.host_name: - host_name = vmParser.args.host_name - else: - host_name = "localhost" - urlstring = '' - sles15_url = '' - sles_package = '' - urlstring = "http://"+vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ - self.repoDir + "/sdk" - if '15' in version: - subversion = '' - python_str = '' - if version[2:5]: - subversion = version[2:5].upper()+"-" - if 'SP' in subversion: - urlstring = "http://"+vmParser.confparser( - 'repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort')+self.repoDir - if 'SP1' in subversion: - urlstring = "http://"+vmParser.confparser( - 'repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort')+self.repoDir+'/sdk' - python_str = "\n" \ - "\n" \ - "sle-module-python2\n/Module-Python2\n" \ - "\n" - value = ["SP4", "SP3", "SP1", "SP5"] - if any(x in subversion for x in value): - python_str = '' - subversion = '' - - sles15_url = "\n\n\n" \ - "\n" \ - "sle-module-server-applications\n/"+subversion+"Module-Server-Applications\n" \ - "\n\n" \ - "\n" \ - "sle-module-legacy\n/"+subversion+"Module-Legacy\n" \ - "\n\n" \ - "\n" \ - "sle-module-development-tools\n/"+subversion+"Module-Development-Tools\n" \ - "\n\n" \ - "\n" \ - "sle-module-desktop-applications\n/"+subversion+"Module-Desktop-Applications\n" \ - "\n\n" \ - "\n" \ - "sle-module-basesystem\n/"+subversion+"Module-Basesystem\n" \ - "\n"+python_str + \ - "\n\n" - - sles_package = "sles-releasesle-module-server-applications-release\n" \ - "sle-module-legacy-release\n" \ - "sle-module-development-tools-releasesle-module-desktop-applications-release\n" \ - "sle-module-basesystem-releasejava-11-openjdkapparmor\n" \ - "base\n" \ - "basesystemenhanced_basefontsgnome_basic\n" \ - "gnome_basisminimal_basesw_managementx11\n" \ - "x11_enhancedx11_yastyast2_basis\n" - else: - sles15_url = "\n\n\n" \ - "\n" \ - "sle-module-server-applications\n/\n" \ - "\n\n\n" - sles_package = "java-1_8_0-openjdk\n" - print(self.ksinst) - ksparm = sftp.open('/var/www/html'+self.ksinst, 'w') - inst_param = "\n\n" \ - "\n"+sles15_url+""\ - "\n\n"+kernel_params+"\n" \ - "crashkernel=1024M\<4G\n\n\n" \ - "\ntrue\n1024M\n" \ - "1024M\<4G\n \n" \ - "\n\nfalse\n" \ - ""+vmParser.args.host_password+"\nroot\n\n\n" \ - "\n\nfalse\n\n"+multipath_string+"\n" \ - "\n\n"+partition_string+"\n\n" \ - "\nmulti-user\n\n\n" \ - "sshd\n\n\n\n\n" \ - "false\nfalse\n" \ - "\n\n\n"+host_name+"\n\nfalse\n\n" \ - "false\n\n" \ - "true\n\n\n" \ - "\ngcc\nmultipath-tools\nkdump\n" \ - "gcc-c++\n"+sles_package+"\n\n\n\n\n\n\n" - ksparm.writelines(inst_param) - ksparm.sftp.close() - def configGrub(self): if '16' in version: self.createAutoyastJsonnet() logging.info("Preparing GRUB for SLES16") sftp = self.nxtSrvCon.open_sftp() gfd = sftp.open(self.destDir + '/boot/ppc64le/grub2-ieee1275/grub.cfg','w') + #gfd = sftp.open(self.destDir + '/boot/grub2/grub.cfg', 'w') gfd.write('set timeout=1 ') gfd.write('\n') gfd.write('menuentry \'Install SLES16\' {') @@ -747,75 +885,82 @@ def configGrub(self): gfd.write(' echo \'Loading SLES16 kernel ...\'') httppath="(http,"+vmParser.confparser('repo', 'RepoIP')+":"+ vmParser.confparser('repo', 'RepoPort')+")" httplinux="/"+self.repoDir+'/boot/ppc64le/linux ' - httpintrd="/"+self.repoDir+'/boot/ppc64le/initrd' + httpintrd="/"+self.repoDir+'/boot/ppc64le/linuxinitrd' + ''' + cli_nw = ' Display_IP=' + vmParser.args.host_ip + ' Netmask=' + vmParser.args.host_netmask + \ + ' HostIP=' + vmParser.args.host_ip + ' Gateway=' + vmParser.args.host_gw + \ + ' nameserver=' + vmParser.confparser(vmParser.domain, 'DNS') + + #strLnx = ' linux linux.sles16' + vmParser.netDir + '/boot/ppc64le/linux ' + cli_nw + \ + #' autoyast=http://' + vmParser.confparser('kshost', 'Host') + self.ksinst + '' + #strLnx = ' linux linux.sles16 agama.install_url='+vmParser.netDir+'/install' + cli_nw + \ + # 'root=live:http://'+vmParser.netDir+'/LiveOS/squashfs.img live.password=abc123 inst.copy_network inst.auto=http://'+vmParser.confparser('kshost', 'Host') + self.ksinst +'' + strLnx = ' linux agama.install_url=http://10.40.71.11:81/crtl/repo/sles/16sp0/beta4/install/ root=live:http://10.40.71.11:81/ctrl/repo/sles/16sp0/beta4/LiveOS/squashfs.img live.password=abc123 inst.copy_network inst.auto=http://' + \ + vmParser.confparser('kshost', 'Host') + self.ksinst + ''' gfd.write('\n') cli_nw = 'rd.neednet=1 ' + 'ip=' + vmParser.args.host_ip + '::' + vmParser.args.host_gw + ':' + vmParser.args.host_netmask + \ - ':' + vmParser.args.host_name + '::none' + ' nameserver=' + vmParser.confparser(vmParser.domain, 'DNS') - strLnx = ' linux ' + vmParser.netDir + '/boot/ppc64le/linux '+ cli_nw + \ + ':' + vmParser.args.host_name + '::none' + ' nameserver=' + vmParser.confparser(vmParser.domain, 'DNS') + strLnx = ' linux ' + httppath + httplinux + cli_nw + \ ' agama.install_url=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ - self.repoDir +'/install root=live:http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ - self.repoDir + '/LiveOS/squashfs.img live.password=abc123' + \ - ' inst.auto=http://' +vmParser.confparser('kshost', 'Host') + self.ksinst + '\n' + self.repoDir + ' root=live:http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ + self.repoDir + '/LiveOS/squashfs.img' + ' agama.install_url=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + \ + vmParser.confparser('repo', 'RepoPort') + self.repoDir + ' inst.auto=http://' +vmParser.confparser('kshost', 'Host') + self.ksinst + '\n' gfd.write(strLnx) - strInit = ' initrd ' + vmParser.netDir + '/boot/ppc64le/initrd\n' + strInit = ' initrd ' + httppath + httpintrd+'\n' gfd.write(strInit) + #strInit = ' initrd http://10.40.71.11:81/crtl/repo/sles/16sp0/beta4/boot/ppc64le/initrd' + #gfd.write(strInit) gfd.write('}') gfd.close() sftp.close() - elif '11SP' not in version.upper(): - self.createKickstart() - sftp = self.nxtSrvCon.open_sftp() - logging.info("Prepareing GRUB for sles15") - gfd = sftp.open( - self.destDir + '/boot/ppc64le/grub2-ieee1275/grub.cfg', 'w') - gfd.write('set timeout=1\n') - gfd.write('menuentry \'Install OS\' {\n') - gfd.write(' insmod http\n') - gfd.write(' insmod tftp\n') - gfd.write(' set root=tftp,' + - vmParser.confparser(vmParser.domain, 'NextServer') + '\n') - gfd.write(' echo \'Loading OS Install kernel ...\'\n') - cli_nw = ' Display_IP=' + vmParser.args.host_ip + ' Netmask=' + vmParser.args.host_netmask + \ - ' HostIP=' + vmParser.args.host_ip + ' Gateway=' + vmParser.args.host_gw + \ - ' nameserver=' + vmParser.confparser(vmParser.domain, 'DNS') - strLnx = ' linux ' + vmParser.netDir + '/boot/ppc64le/linux ' + cli_nw + \ - ' install=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ - self.repoDir - # if '15' in version: - # strLnx = strLnx+ ' autoyast=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ - # '/powervmks/sles%s.ks\n' % "15" - # else: - strLnx = strLnx + ' autoyast=http://' + \ - vmParser.confparser('kshost', 'Host') + self.ksinst + '\n' - gfd.write(strLnx) - strInit = ' initrd ' + vmParser.netDir + '/boot/ppc64le/initrd\n' - gfd.write(strInit) - gfd.write('}\n') - gfd.sftp.close() else: - gfd = sftp.open(self.baseURL + '/yaboot.conf', 'w') - gfd.write('message=suseboot/yaboot.txt\n\n') - gfd.write('default=install\n') - gfd.write('timeout=10\n') - gfd.write('image[64bit]=' + vmParser.netDir + + if '11SP' not in version.upper(): + gfd = sftp.open( + self.destDir + '/boot/ppc64le/grub2-ieee1275/grub.cfg', 'w') + gfd.write('set timeout=1\n') + gfd.write('menuentry \'Install OS\' {\n') + gfd.write(' insmod http\n') + gfd.write(' insmod tftp\n') + gfd.write(' set root=tftp,' + + vmParser.confparser(vmParser.domain, 'NextServer') + '\n') + gfd.write(' echo \'Loading OS Install kernel ...\'\n') + cli_nw = ' Display_IP=' + vmParser.args.host_ip + ' Netmask=' + vmParser.args.host_netmask + \ + ' HostIP=' + vmParser.args.host_ip + ' Gateway=' + vmParser.args.host_gw + \ + ' nameserver=' + vmParser.confparser(vmParser.domain, 'DNS') + strLnx = ' linux ' + vmParser.netDir + '/boot/ppc64le/linux ' + cli_nw + \ + ' install=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ + self.repoDir + strLnx = strLnx + ' autoyast=http://' + \ + vmParser.confparser('kshost', 'Host') + self.ksinst + '\n' + gfd.write(strLnx) + strInit = ' initrd ' + vmParser.netDir + '/boot/ppc64le/initrd\n' + gfd.write(strInit) + gfd.write('}\n') + gfd.sftp.close() + else: + gfd = sftp.open(self.baseURL + '/yaboot.conf', 'w') + gfd.write('message=suseboot/yaboot.txt\n\n') + gfd.write('default=install\n') + gfd.write('timeout=10\n') + gfd.write('image[64bit]=' + vmParser.netDir + '/suseboot/linux64\n') - gfd.write(' label=install\n') - gfd.write(' initrd=' + vmParser.netDir + '/suseboot/initrd64\n') - cli_nw = ' gateway=' + vmParser.args.host_gw + ' hostip=' + vmParser.args.host_ip + \ - ' netmask=' + vmParser.args.host_netmask + ' dns=' + \ - vmParser.confparser(vmParser.domain, 'DNS') - cli_mod = 'sysrq=1 install=slp insmod=sym53c8xx insmod=ipr insmod=tftp insmod=http slp=1 splash=0 TERM=linux textmode=1' - cli_repo = ' install=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ - self.repoDir - cli_yast = ' autoyast=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ - '/powervmks/sles99.ks' - gfd.write(' append="' + cli_mod + cli_repo + + gfd.write(' label=install\n') + gfd.write(' initrd=' + vmParser.netDir + '/suseboot/initrd64\n') + cli_nw = ' gateway=' + vmParser.args.host_gw + ' hostip=' + vmParser.args.host_ip + \ + ' netmask=' + vmParser.args.host_netmask + ' dns=' + \ + vmParser.confparser(vmParser.domain, 'DNS') + cli_mod = 'sysrq=1 install=slp insmod=sym53c8xx insmod=ipr insmod=tftp insmod=http slp=1 splash=0 TERM=linux textmode=1' + cli_repo = ' install=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ + self.repoDir + cli_yast = ' autoyast=http://' + vmParser.confparser('repo', 'RepoIP') + ':' + vmParser.confparser('repo', 'RepoPort') + \ + '/powervmks/sles99.ks' + gfd.write(' append="' + cli_mod + cli_repo + cli_nw + cli_yast + '"\n') - gfd.sftp.close() - gfm = '/yaboot.conf-' + (vmParser.args.host_mac).replace(':', '-') - cmd = 'mv ' + self.baseURL + '/yaboot.conf ' + self.baseURL + gfm - self.runCommand(self.nxtSrvCon, cmd) - + gfd.sftp.close() + gfm = '/yaboot.conf-' + (vmParser.args.host_mac).replace(':', '-') + cmd = 'mv ' + self.baseURL + '/yaboot.conf ' + self.baseURL + gfm + self.runCommand(self.nxtSrvCon, cmd) def logger(): if not os.path.isdir("./log"):