begin work on composing vagrant boxes

This commit is contained in:
Neil Hanlon 2022-11-19 16:27:03 -05:00
parent c244f298eb
commit 4777fc3db0
Signed by: neil
GPG Key ID: 705BC21EC3C70F34
9 changed files with 181 additions and 24 deletions

View File

@ -93,6 +93,9 @@
format: raw.xz
OCP:
format: qcow2
Vagrant:
format: box
variants: [Libvirt, Vbox, VMware]
livemap:
git_repo: 'https://git.resf.org/sig_core/kickstarts.git'
branch: 'r8'

View File

@ -97,6 +97,9 @@
format: raw.xz
OCP:
format: qcow2
Vagrant:
format: box
variants: [Libvirt, Vbox, VMware]
livemap:
git_repo: 'https://git.resf.org/sig_core/kickstarts.git'
branch: 'r9'

View File

@ -101,6 +101,25 @@ class ImageBuild:
self.checkout_kickstarts()
self.kickstart_arg = self.kickstart_imagefactory_args()
try:
os.mkdir(self.outdir)
except FileExistsError as e:
log.info("Directory already exists for this release. If possible, previously executed steps may be skipped")
except Exception as e:
log.exception("Some other exception occured while creating the output directory", e)
return 0
if os.path.exists(self.metadata):
with open(self.metadata, "r") as f:
try:
o = json.load(f)
self.base_uuid = o['base_uuid']
self.target_uuid = o['target_uuid']
except json.decoder.JSONDecodeError as e:
log.exception("Couldn't decode metadata file", e)
finally:
f.flush()
# Yes, this is gross. I'll fix it later.
if self.image_type in ["Container"]:
self.stage_commands = [
@ -127,37 +146,44 @@ class ImageBuild:
]
if self.image_type in ["Vagrant"]:
_map = {
"Vbox": "vmdk",
"Libvirt": "qcow2",
"VMware": "vmdk"
"Vbox": {"format": "vmdk", "provider": "virtualbox"},
"Libvirt": {"format": "qcow2", "provider": "libvirt"},
"VMware": {"format": "vmdk", "convertOptions": ["-o", "subformat=streamOptimized"], "provider": "vmware_desktop"}
}
output = f"{_map[self.variant]}" #type: ignore
self.stage_commands = [
["qemu-img", "convert", "-c", "-f", "raw", "-O", output, lambda: f"{STORAGE_DIR}/{self.target_uuid}.body", f"{self.outdir}/{self.outname}.{output}"]
]
output = f"{_map[self.variant]['format']}" #type: ignore
options = f"{_map[self.variant]['convertOptions']}" if 'convertOptions' in _map[self.variant].keys() else '' #type: ignore
provider = f"{_map[self.variant]['provider']}" # type: ignore
self.prepare_vagrant(provider)
self.stage_commands = [
["qemu-img", "convert", "-c", "-f", "raw", "-O", output, *options, lambda: f"{STORAGE_DIR}/{self.target_uuid}.body", f"{self.outdir}/{self.outname}.{output}"],
["tar", "--strip-components=2", "-czf", f"{self.outdir}/{self.outname}.box", f"{self.outdir}"]
]
if self.stage_commands:
self.stage_commands.append(["cp", "-v", lambda: f"{STORAGE_DIR}/{self.target_uuid}.meta", f"{self.outdir}/build.meta"])
try:
os.mkdir(self.outdir)
except FileExistsError as e:
log.info("Directory already exists for this release. If possible, previously executed steps may be skipped")
except Exception as e:
log.exception("Some other exception occured while creating the output directory", e)
return 0
if os.path.exists(self.metadata):
with open(self.metadata, "r") as f:
try:
o = json.load(f)
self.base_uuid = o['base_uuid']
self.target_uuid = o['target_uuid']
except json.decoder.JSONDecodeError as e:
log.exception("Couldn't decode metadata file", e)
finally:
f.flush()
def prepare_vagrant(self, provider):
"""Setup the output directory for the Vagrant type variant, dropping templates as required"""
file_loader = FileSystemLoader(f"{_rootdir}/templates")
tmplenv = Environment(loader=file_loader)
templates = {}
templates['Vagrantfile'] = tmplenv.get_template(f"vagrant/Vagrantfile.{self.variant}")
templates['metadata.json'] = tmplenv.get_template('vagrant/metadata.tmpl.json')
templates['info.json'] = tmplenv.get_template('vagrant/info.tmpl.json')
if self.variant == "VMware":
provider = "vmware_desktop"
templates[f"{self.outname}.vmx"] = tmplenv.get_template('vagrant/vmx.tmpl')
for name, template in templates.items():
print(name, template)
self.render_template(f"{self.outdir}/{name}", template,
name=self.outname,
provider=provider
)
def checkout_kickstarts(self) -> int:
cmd = ["git", "clone", "--branch", f"r{self.architecture.major}", rlvars['livemap']['git_repo'], f"{KICKSTART_PATH}"]
@ -225,6 +251,17 @@ class ImageBuild:
return ["--file-parameter", "install_script", str(self.kickstart_path)]
def render_template(self, path, template, **kwargs) -> pathlib.Path:
with open(path, "wb") as f:
_template = template.render(**kwargs)
f.write(_template.encode())
f.flush()
output = pathlib.Path(path)
if not output.exists():
log.error("Failed to write template")
raise Exception("Failed to template")
return output
def render_icicle_template(self) -> pathlib.Path:
handle, output = tempfile.mkstemp()
if not handle:

View File

@ -0,0 +1,45 @@
# frozen_string_literal: true
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
# Example configuration of new VM..
#
#config.vm.define :test_vm do |test_vm|
# Box name
#
#test_vm.vm.box = "rockylinux"
# Domain Specific Options
#
# See README for more info.
# Interfaces for VM
#
# Networking features in the form of `config.vm.network`
#
#test_vm.vm.network :private_network, :ip => '10.20.30.40'
#test_vm.vm.network :public_network, :ip => '10.20.30.41'
#end
# Options for VMware Vagrant provider.
["vmware_fusion", "vmware_workstation", "vmware_desktop"].each do |provider|
config.vm.provider provider do |vmware, override|
vmware.whitelist_verified = true
vmware.gui = false
# The machine is configured with 2 cores and 1GB of RAM by default
vmware.vmx["memsize"] = "1024"
vmware.vmx["numvcpus"] = "2"
vmware.vmx["cpuid.coresPerSocket"] = "2"
# For compatility reasons version 10 (VMware Workstation 10.x and later)
# is used, this can be changed to every later version without any
# other changes if features are needed
# https://kb.vmware.com/s/article/1003746
vmware.vmx["virtualHW.version"] = "10"
end
end
end

View File

@ -0,0 +1,7 @@
{
"Author": "Rocky Linux Team",
"Website": "https://rockylinux.org/",
"Artifacts": "https://vagrantcloud.com/rockylinux/",
"Repository": "https://git.resf.org/sig_core/toolkit",
"Description": "1st party distributed Vagrant images."
}

View File

@ -0,0 +1,3 @@
{
"provider": "{{ provider }}"
}

View File

@ -0,0 +1,59 @@
.encoding = "UTF-8"
bios.bootorder = "hdd,cdrom"
cleanShutdown = "TRUE"
config.version = "8"
cpuid.coresPerSocket = "2"
ehci.present = "FALSE"
firmware = "efi"
floppy0.present = "FALSE"
guestOS = "rhel7_64Guest"
hpet0.present = "TRUE"
mem.hotadd = "TRUE"
memsize = "1024"
numvcpus = "2"
pciBridge0.pciSlotNumber = "17"
pciBridge0.present = "TRUE"
pciBridge4.functions = "8"
pciBridge4.pciSlotNumber = "21"
pciBridge4.present = "TRUE"
pciBridge4.virtualDev = "pcieRootPort"
pciBridge5.functions = "8"
pciBridge5.pciSlotNumber = "22"
pciBridge5.present = "TRUE"
pciBridge5.virtualDev = "pcieRootPort"
pciBridge6.functions = "8"
pciBridge6.pciSlotNumber = "23"
pciBridge6.present = "TRUE"
pciBridge6.virtualDev = "pcieRootPort"
pciBridge7.functions = "8"
pciBridge7.pciSlotNumber = "24"
pciBridge7.present = "TRUE"
pciBridge7.virtualDev = "pcieRootPort"
powerType.powerOff = "soft"
powerType.powerOn = "soft"
powerType.reset = "soft"
powerType.suspend = "soft"
sata0.present = "FALSE"
scsi0:0.present = "TRUE"
scsi0:0.redo = ""
scsi0.pciSlotNumber = "160"
scsi0.present = "TRUE"
scsi0.virtualDev = "pvscsi"
serial0.present = "FALSE"
softPowerOff = "TRUE"
sound.present = "FALSE"
svga.vramSize = "134217728"
tools.syncTime = "TRUE"
usb.present = "FALSE"
uuid.action = "create"
vcpu.hotadd = "TRUE"
virtualHW.productCompatibility = "hosted"
virtualHW.version = "10"
vmci0.id = "-1024033366"
vmci0.present = "TRUE"
vmotion.checkpointFBSize = "134217728"
displayName = "{{ outname }}"
nvram = "{{ outname }}.nvram"
scsi0:0.fileName = "{{ outname }}.vmdk"
extendedConfigFile = "{{ outname }}.vmxf"