173 lines
6.7 KiB
Python
Executable File
173 lines
6.7 KiB
Python
Executable File
#!/usr/bin/python3
|
|
# ==============================================================#
|
|
# File : config
|
|
# Desc : generate vagrantfile
|
|
# Ctime : 2024-07-05
|
|
# Mtime : 2025-12-11
|
|
# Path : vagrant/config
|
|
# License : Apache-2.0 @ https://pigsty.io/docs/about/license/
|
|
# Copyright : 2018-2026 Ruohang Feng / Vonng (rh@vonng.com)
|
|
# ==============================================================#
|
|
# this script will generate vagrant/Vagrantfile base on parameters
|
|
|
|
import os
|
|
import sys
|
|
import re
|
|
|
|
IMAGES = {
|
|
"ubuntu2204": "generic/ubuntu2204", "ubuntu22": "generic/ubuntu2204", "u22": "generic/ubuntu2204", "ubuntu": "generic/ubuntu2204", "22": "generic/ubuntu2204",
|
|
"ubuntu2004": "generic/ubuntu2004", "ubuntu20": "generic/ubuntu2004", "u20": "generic/ubuntu2004", "20": "generic/ubuntu2004",
|
|
"ubuntu2404": "bento/ubuntu-24.04", "ubuntu24": "bento/ubuntu-24.04", "u24": "bento/ubuntu-24.04", "24": "bento/ubuntu-24.04",
|
|
"debian13": "cloud-image/debian-13", "deb13": "cloud-image/debian-13", "d13": "cloud-image/debian-13", "13": "bento/debian-13", "b13": "bento/debian-13",
|
|
"debian12": "generic/debian12", "deb12": "generic/debian12", "d12": "generic/debian12", "12": "generic/debian12", "k12": "koalephant/debian12", "b12": "bento/debian-12",
|
|
"debian11": "generic/debian11", "deb11": "generic/debian11", "d11": "generic/debian11", "11": "generic/debian11",
|
|
"el7": "generic/centos7", "rhel7": "generic/rhel7", "centos": "generic/centos7", "7": "generic/centos7", "oracle7": "generic/oracle7",
|
|
"el8": "bento/rockylinux-9", "rocky8": "bento/rockylinux-9", "rhel8": "generic/rhel8", "alma8": "generic/alma8", "oracle8": "generic/oracle8", "el": "bento/rockylinux-9", "8": "bento/rockylinux-9",
|
|
"el9": "bento/rockylinux-9", "rocky9": "bento/rockylinux-9", "rhel9": "generic/rhel9", "alma9": "generic/alma9", "oracle9": "generic/oracle9", "9": "bento/rockylinux-9",
|
|
"el10": "rockylinux/10", "rocky10": "rockylinux/10", "alma10": "almalinux/10", "b10": "bento/rockylinux-10", "10": "rockylinux/10",
|
|
}
|
|
|
|
# do not substitute image in building specs
|
|
BUILD_SPECS = ["build", "all", "rpm", "deb", "old"]
|
|
|
|
ARGS = {
|
|
'spec': 'meta',
|
|
'scale': 1,
|
|
'provider': "virtualbox",
|
|
}
|
|
|
|
def usage():
|
|
print("Usage: %s [spec] [image] [scale] [provider]" % sys.argv[0])
|
|
print(" [VM_SPEC] spec: meta, full, simu, dual, trio, oss, pro, rpm, deb, all...")
|
|
print(" [VM_IMAGE] image: el8, el9, d11, d12, u20, u22")
|
|
print(" [VM_SCALE] scale: 1, 2, 3, ...")
|
|
print(" [VM_PROVIDER] provider: virtualbox, libvirt")
|
|
sys.exit(1)
|
|
|
|
def parse_arg():
|
|
# check environment variables first
|
|
if 'VM_SPEC' in os.environ:
|
|
ARGS['spec'] = os.environ['VM_SPEC']
|
|
if 'VM_IMAGE' in os.environ:
|
|
ARGS['image'] = os.environ['VM_IMAGE']
|
|
if 'VM_SCALE' in os.environ:
|
|
ARGS['scale'] = int(os.environ['VM_SCALE'])
|
|
if 'VM_PROVIDER' in os.environ:
|
|
ARGS['provider'] = os.environ['VM_PROVIDER']
|
|
|
|
if len(sys.argv) > 1:
|
|
ARGS['spec'] = sys.argv[1]
|
|
if len(sys.argv) > 2:
|
|
ARGS['image'] = sys.argv[2]
|
|
if len(sys.argv) > 3:
|
|
ARGS['scale'] = int(sys.argv[3])
|
|
if len(sys.argv) > 4:
|
|
ARGS['provider'] = sys.argv[4]
|
|
|
|
if 'image' in ARGS and ARGS['image'] in IMAGES:
|
|
ARGS['image'] = IMAGES[ARGS['image']]
|
|
|
|
if ARGS['spec'] == 'simu':
|
|
ARGS['scale'] = 1 # do not scale simu template
|
|
|
|
print(
|
|
"[INFO] spec=%s image=%s scale=%d provider=%s" % (ARGS['spec'], ARGS.get('image'), ARGS['scale'], ARGS['provider']))
|
|
|
|
return ARGS
|
|
|
|
|
|
def get_spec(spec_name):
|
|
vagrant_dir = os.path.dirname(os.path.realpath(__file__))
|
|
spec_path = os.path.join(vagrant_dir, 'spec', '%s.rb' % spec_name)
|
|
|
|
# raise error if spec file not found
|
|
if not os.path.exists(spec_path):
|
|
print("[ERRR] spec %s not found" % (spec_name))
|
|
sys.exit(1)
|
|
|
|
modified_specs = []
|
|
with open(spec_path, 'r') as f:
|
|
lines = f.readlines()
|
|
|
|
print("[INFO] get %s spec from %s" % (spec_name, spec_path))
|
|
total_cpu = 0
|
|
total_mem = 0
|
|
scale_factor = int(ARGS['scale'])
|
|
if scale_factor < 0 or scale_factor > 64:
|
|
print("[ERRR] scale factor should be in range [1, 64]")
|
|
sys.exit(1)
|
|
for line in lines:
|
|
line2 = line.lstrip().rstrip()
|
|
if line2.startswith('{'): # this is a node definition line
|
|
try:
|
|
name = re.findall('"name"\\s*=>\\s*"([^"]+)"', line)[0]
|
|
cpu = int(re.findall('"cpu"\\s*=>\\s*"([^"]+)"', line)[0])
|
|
mem = int(re.findall('"mem"\\s*=>\\s*"([^"]+)"', line)[0])
|
|
if 'image' in ARGS:
|
|
image = re.findall('"image"\\s*=>\\s*"([^"]+)"', line)[0]
|
|
|
|
new_cpu = scale_factor * cpu
|
|
new_mem = scale_factor * mem
|
|
total_cpu += new_cpu
|
|
total_mem += new_mem
|
|
except:
|
|
print("[ERRR] failed to parse cpu, mem, image from line: %s" % line)
|
|
sys.exit(1)
|
|
|
|
# if found, replace these fields
|
|
line = re.sub('"cpu"\\s*=>\\s*"([^"]+)"', '"cpu" => "%d"' % new_cpu, line)
|
|
line = re.sub('"mem"\\s*=>\\s*"([^"]+)"', '"mem" => "%d"' % new_mem, line)
|
|
if ARGS['spec'] not in BUILD_SPECS and 'image' in ARGS:
|
|
line = re.sub('"image"\\s*=>\\s*"([^"]+)"', '"image" => "%s"' % ARGS['image'], line)
|
|
modified_specs.append(line)
|
|
|
|
if scale_factor != 1:
|
|
print("[INFO] total_cpu = %d, total_mem = %d GiB [scale factor = %d]" % (
|
|
total_cpu, total_mem / 1024, scale_factor))
|
|
else:
|
|
print("[INFO] total_cpu = %d, total_mem = %d GiB " % (total_cpu, total_mem / 1024))
|
|
return ''.join(modified_specs)
|
|
|
|
|
|
def get_provider(provider):
|
|
vagrant_dir = os.path.dirname(os.path.realpath(__file__))
|
|
provider_path = os.path.join(vagrant_dir, 'Vagrantfile.%s' % provider)
|
|
|
|
# raise error if provider file not found
|
|
if not os.path.exists(provider_path):
|
|
print("[ERRR] provider %s not supported" % (provider))
|
|
sys.exit(2)
|
|
|
|
with open(provider_path, 'r') as f:
|
|
return f.read()
|
|
|
|
|
|
def get_conf():
|
|
spec_conf = get_spec(ARGS['spec'])
|
|
provider_conf = get_provider(ARGS['provider'])
|
|
print('[SPEC]\n')
|
|
print(spec_conf)
|
|
print('\n')
|
|
return "%s\n\n%s" % (spec_conf, provider_conf)
|
|
|
|
|
|
def write_conf(content):
|
|
vagrantfile_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Vagrantfile')
|
|
try:
|
|
with open(vagrantfile_path, 'w') as f:
|
|
f.write(content)
|
|
print("[INFO] write config to %s" % vagrantfile_path)
|
|
except:
|
|
print("[ERRR] write config to %s" % vagrantfile_path)
|
|
|
|
|
|
def main():
|
|
print("[INFO] generate vagrant config")
|
|
parse_arg()
|
|
conf = get_conf()
|
|
write_conf(conf)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|