Working virt-install
This commit is contained in:
parent
494c8b5653
commit
eb1fbf7eb4
5 changed files with 145 additions and 17 deletions
24
README.md
24
README.md
|
|
@ -1,5 +1,27 @@
|
||||||
A quick and dirty script to help set up a RHOSP AIO
|
A quick and dirty script to help set up a RHOSP AIO
|
||||||
|
|
||||||
|
This has grown a bit. At some point I will make this a proper readme, but for now a few notes:
|
||||||
|
|
||||||
|
The goal is to build a VM (although you could use baremetal) and deploy a RHOSP AIO to it. Then to add a project, flavors, images, networks to support testing os-migrate.
|
||||||
|
|
||||||
|
After that create a VM to migrate, a conversion host to do the migration.
|
||||||
|
|
||||||
|
This may well be useful for other things, but this is the current aim.
|
||||||
|
|
||||||
|
I am primarily targetting RHEL8.4 and RHOSP16.2. As a result I'm tied to virt-install v3.2.0 which makes using cloud-init for configuring network on the AIO VM a little annoying. Later versions allow you to pass in a network config, but 3.2.0 means I have to use nmcli and bootcmd to get the network configure.
|
||||||
|
|
||||||
|
There is a vestigial network-config.tpl in the virt-install directory but it is not actually used yet.
|
||||||
|
|
||||||
|
EVerything is a bit of a mess but here's a brief overview:
|
||||||
|
|
||||||
|
main.py - original script. Generates the yaml files and a dploy script to deploy a RHOSP AIO. Assumes a VM to run on. Don't run this on your laptop. You'll be sorry if you do.
|
||||||
|
|
||||||
|
os_migrate_setup.py - build the OSP infrastructure to allow testing os-migrate.
|
||||||
|
|
||||||
|
os_migrate_teardown.py - remove that infrastructure (to allow for refinement/iteration)
|
||||||
|
|
||||||
|
virt-install/create_aio_vm.py - use virt-install to create and configure a VM to run the other scripts on.
|
||||||
|
|
||||||
```
|
```
|
||||||
usage: main.py [-h] -u USERNAME -p PASSWORD -a ADDRESS [-i INTERFACE]
|
usage: main.py [-h] -u USERNAME -p PASSWORD -a ADDRESS [-i INTERFACE]
|
||||||
[-m NETMASK] -d DNS [DNS ...] [-D DOMAIN]
|
[-m NETMASK] -d DNS [DNS ...] [-D DOMAIN]
|
||||||
|
|
@ -25,7 +47,7 @@ optional arguments:
|
||||||
--standalone-yaml-out STANDALONE_YAML_OUT
|
--standalone-yaml-out STANDALONE_YAML_OUT
|
||||||
```
|
```
|
||||||
|
|
||||||
Use this script to generate the yaml and a deploy script to buyild an AIO
|
Use this script to generate the yaml and a deploy script to build an AIO
|
||||||
|
|
||||||
By default the files will be placed in the home directory of the user running the script (should probable be the stack user)
|
By default the files will be placed in the home directory of the user running the script (should probable be the stack user)
|
||||||
|
|
||||||
|
|
|
||||||
6
dev_requirements.txt
Normal file
6
dev_requirements.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
black==22.8.0
|
||||||
|
bpython==0.22.1
|
||||||
|
flake8==5.0.4
|
||||||
|
pyflakes==2.5.0
|
||||||
|
pylint==2.13.9
|
||||||
|
PyYAML==6.0.1
|
||||||
|
|
@ -4,6 +4,7 @@ import subprocess
|
||||||
|
|
||||||
MD_PATH = "./meta-data"
|
MD_PATH = "./meta-data"
|
||||||
UD_PATH = "./user-data"
|
UD_PATH = "./user-data"
|
||||||
|
ND_PATH = "./network-config"
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
@ -12,7 +13,20 @@ def parse_args():
|
||||||
parser.add_argument("--local-hostname", default="aio3.gpslab.cbr.redhat.com")
|
parser.add_argument("--local-hostname", default="aio3.gpslab.cbr.redhat.com")
|
||||||
parser.add_argument("--user-data", default="./user-data.tpl", type=open)
|
parser.add_argument("--user-data", default="./user-data.tpl", type=open)
|
||||||
parser.add_argument("--meta-data", default="./meta-data.tpl", type=open)
|
parser.add_argument("--meta-data", default="./meta-data.tpl", type=open)
|
||||||
|
parser.add_argument("--network-data", default="./network-config.tpl", type=open)
|
||||||
parser.add_argument("--instance-id", default="aio3")
|
parser.add_argument("--instance-id", default="aio3")
|
||||||
|
parser.add_argument("--output-image", required=True)
|
||||||
|
parser.add_argument("--image-size", default="100G")
|
||||||
|
parser.add_argument("--input-image", required=True)
|
||||||
|
parser.add_argument("--os-variant", required=True)
|
||||||
|
parser.add_argument("--name", required=True)
|
||||||
|
parser.add_argument("--memory", default=2048) #, type="int")
|
||||||
|
parser.add_argument("--gateway", required=True)
|
||||||
|
parser.add_argument("--cidr-1", required=True)
|
||||||
|
parser.add_argument("--cidr-2", required=True)
|
||||||
|
parser.add_argument("--dns", required=True)
|
||||||
|
parser.add_argument("--search-domain", required=True)
|
||||||
|
parser.add_argument("-v", "--verbose", action="store_true")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
@ -23,6 +37,19 @@ def parse_args():
|
||||||
|
|
||||||
args.meta_data = args.meta_data.read()
|
args.meta_data = args.meta_data.read()
|
||||||
args.meta_data = args.meta_data.format(data=args)
|
args.meta_data = args.meta_data.format(data=args)
|
||||||
|
|
||||||
|
args.network_data = args.network_data.read()
|
||||||
|
args.network_data = args.network_data.format(data=args)
|
||||||
|
|
||||||
|
output_image = pathlib.Path(args.output_image)
|
||||||
|
if output_image.exists():
|
||||||
|
raise ValueError(f"{args.output_image} already exists")
|
||||||
|
args.output_image = output_image
|
||||||
|
|
||||||
|
input_image = pathlib.Path(args.input_image)
|
||||||
|
if not input_image.exists():
|
||||||
|
raise ValueError(f"{args.input_image} not found")
|
||||||
|
args.input_image = input_image
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
@ -34,35 +61,79 @@ def write_meta_data(meta_data):
|
||||||
with open(MD_PATH, "w", encoding="utf-8") as meta_data_file:
|
with open(MD_PATH, "w", encoding="utf-8") as meta_data_file:
|
||||||
meta_data_file.write(meta_data)
|
meta_data_file.write(meta_data)
|
||||||
|
|
||||||
|
def write_network_data(network_data):
|
||||||
|
with open(ND_PATH, "w", encoding="utf-8") as network_data_file:
|
||||||
|
network_data_file.write(network_data)
|
||||||
|
|
||||||
|
def create_image(args):
|
||||||
|
print("creating image")
|
||||||
|
cmd = f"qemu-img create -f qcow2 -o preallocation=metadata {args.output_image} {args.image_size}"
|
||||||
|
|
||||||
|
result = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||||
|
if args.verbose:
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
print("Resizing image")
|
||||||
|
cmd = f"virt-resize --expand /dev/sda3 {args.input_image} {args.output_image}"
|
||||||
|
|
||||||
|
result= subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||||
|
|
||||||
|
if args.verbose:
|
||||||
|
print(result)
|
||||||
|
|
||||||
def virt_install_cmd(args):
|
def virt_install_cmd(args):
|
||||||
tpl = f"""
|
cmd = f"""
|
||||||
sudo virt-install
|
sudo virt-install \\
|
||||||
--os-variant {args.os_variant}
|
--os-variant {args.os_variant} \\
|
||||||
--name {args.name}
|
--name {args.name} \\
|
||||||
--memory {args.ram}
|
--memory {args.memory} \\
|
||||||
--disk ./test.qcow2
|
--disk {args.output_image} \\
|
||||||
--import
|
--import \\
|
||||||
--graphics spice,listen=0.0.0.0
|
--graphics spice,listen=127.0.0.1 \\
|
||||||
--video virtio
|
--video virtio \\
|
||||||
--channel spicevmc
|
--channel spicevmc \\
|
||||||
--wait 0
|
--wait 0 \\
|
||||||
--cloud-init meta-data=./meta-data,user-data=./user-data
|
--cloud-init meta-data=./meta-data,user-data=./user-data \\
|
||||||
|
--network bridge=bridge0 \\
|
||||||
|
--network bridge=bridge0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
print("running virt-install")
|
||||||
|
|
||||||
|
if args.verbose:
|
||||||
|
print(cmd)
|
||||||
|
|
||||||
|
result =subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||||
|
if args.verbose:
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
|
||||||
def delete_meta_data():
|
def delete_meta_data():
|
||||||
pathlib.Path.unlink(MD_PATH)
|
pathlib.Path.unlink(pathlib.Path(MD_PATH))
|
||||||
|
|
||||||
def delete_user_data():
|
def delete_user_data():
|
||||||
pathlib.Path.unlink(UD_PATH)
|
pathlib.Path.unlink(pathlib.Path(UD_PATH))
|
||||||
|
|
||||||
|
def install_packages(args):
|
||||||
|
cmd = "sudo dnf install -y virt-install virt-viewer qemu-img libguestfs.x86_64"
|
||||||
|
|
||||||
|
print("installing needed packages...")
|
||||||
|
|
||||||
|
if args.verbose:
|
||||||
|
print(subprocess.check_output(cmd, shell=True, universal_newlines=True))
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
|
|
||||||
print(args)
|
if args.verbose:
|
||||||
|
print(args)
|
||||||
|
|
||||||
|
install_packages(args)
|
||||||
|
create_image(args)
|
||||||
write_meta_data(args.meta_data)
|
write_meta_data(args.meta_data)
|
||||||
write_user_data(args.user_data)
|
write_user_data(args.user_data)
|
||||||
|
|
||||||
|
virt_install_cmd(args)
|
||||||
|
|
||||||
delete_meta_data()
|
delete_meta_data()
|
||||||
delete_user_data()
|
delete_user_data()
|
||||||
|
|
|
||||||
20
virt-install/network-config.tpl
Normal file
20
virt-install/network-config.tpl
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
network:
|
||||||
|
version: 1
|
||||||
|
config:
|
||||||
|
- type: physical
|
||||||
|
name: en0
|
||||||
|
subnets:
|
||||||
|
- type: static
|
||||||
|
address: {data.cidr_1}
|
||||||
|
gateway: {data.gateway}
|
||||||
|
- type: physical
|
||||||
|
name: en1
|
||||||
|
subnets:
|
||||||
|
- type: static
|
||||||
|
address: {data.cidr_2}
|
||||||
|
gateway: {data.gateway}
|
||||||
|
- type: nameserver
|
||||||
|
address:
|
||||||
|
- {data.dns}
|
||||||
|
search:
|
||||||
|
- {data.search_domain}
|
||||||
|
|
@ -1,6 +1,15 @@
|
||||||
#cloud-config
|
#cloud-config
|
||||||
|
system_info:
|
||||||
|
default_user:
|
||||||
|
name: stack
|
||||||
password: {data.password}
|
password: {data.password}
|
||||||
chpasswd: {{expire: False}}
|
chpasswd: {{expire: False}}
|
||||||
ssh_pwauth: True
|
ssh_pwauth: True
|
||||||
ssh_authorized_keys:
|
ssh_authorized_keys:
|
||||||
- {data.public_key}
|
- {data.public_key}
|
||||||
|
|
||||||
|
bootcmd:
|
||||||
|
- "nmcli conn delete 'System eth0'"
|
||||||
|
- "nmcli conn delete 'Wired connection 1'"
|
||||||
|
- "nmcli con add con-name eth0 ifname eth0 type ethernet ip4 {data.cidr_1} gw4 {data.gateway} ipv4.dns {data.dns}"
|
||||||
|
- "nmcli con add con-name eth1 ifname eth1 type ethernet ip4 {data.cidr_2} gw4 {data.gateway} ipv4.dns {data.dns}"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue