Skip to content

Commit

Permalink
Provide custom base OS image in config
Browse files Browse the repository at this point in the history
  • Loading branch information
vedp committed Sep 20, 2024
1 parent 1f66db1 commit af52412
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 4 deletions.
4 changes: 2 additions & 2 deletions deployer/deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ def _parse_networks(self):
return False

for nw_conf in nw_configs:
name = nw_conf["name"]
nw = Network(nw_conf)
if nw is None:
return False
name = nw.name_
self.Topology().AddNetwork(name, nw)

return True
Expand All @@ -74,10 +74,10 @@ def _parse_vms(self):
return False

for vm_conf in vm_configs:
name = vm_conf["name"]
vm = VirtualMachine(vm_conf)
if vm is None:
return False
name = vm.name_
self.Topology().AddVm(name, vm)

return True
Expand Down
3 changes: 3 additions & 0 deletions deployer/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ def _has_valid_network_fields(nw):

@staticmethod
def _validate_network_conf(nw):
if G.NO_NETWORK:
return True

if not Network._has_valid_network_fields(nw):
return False

Expand Down
57 changes: 57 additions & 0 deletions deployer/tests/test_virtual_machines.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

import deployer
import deployer.topology
import deployer.globals as G
from deployer.deployer import Deployer
from deployer.network import Network
from deployer.virtual_machine import VirtualMachine


class TestVirtualMachine(unittest.TestCase):
def setUp(self):
self.deployer_ = Deployer({})
self.vm_ = None
self.iso_nw_ = Network({
"name": "iso1",
Expand Down Expand Up @@ -278,3 +281,57 @@ def test_add_ce_virtual_machine(self):
"/var/lib/libvirt/images/vm1/cloud-init.iso")
self.assertEqual(str(self.vm_.libvirt_vm_base),
"/var/lib/libvirt/images/vm1")

def test_add_custom_virtual_machine(self):
del self.vm_conf_["flavor"]
self.vm_conf_["disk"] = "300G"
self.vm_conf_["ram"] = 24576
self.vm_conf_["vcpus"] = 12
self.vm_ = VirtualMachine(self.vm_conf_)
self.mock_mkdir.assert_called_once_with(parents=True, exist_ok=True)
self.assertEqual(self.vm_.name_, "vm1")
self.assertEqual(self.vm_.vnc_port_, 5900)
self.assertEqual(self.vm_.flavor_, "")
self.assertEqual(self.vm_.vcpus_, 12)
self.assertEqual(self.vm_.ram_, 24576)
self.assertEqual(self.vm_.root_disk_sz_, "300G")
self.assertEqual(self.vm_.networks_, {
"mgmt1": self.mgmt_conf_,
"nat1": self.nat_conf_,
"iso1": self.iso_conf_
})
self.assertEqual(str(self.vm_.user_data_cfg_),
"/var/lib/libvirt/images/vm1/user-data.cfg")
self.assertEqual(str(self.vm_.network_data_cfg_),
"/var/lib/libvirt/images/vm1/nw-data.cfg")
self.assertEqual(str(self.vm_.root_disk_),
"/var/lib/libvirt/images/vm1/root_disk.qcow2")
self.assertEqual(str(self.vm_.cloud_init_iso_),
"/var/lib/libvirt/images/vm1/cloud-init.iso")
self.assertEqual(str(self.vm_.libvirt_vm_base),
"/var/lib/libvirt/images/vm1")

@mock.patch('pathlib.Path.is_file', return_value=True)
def test_add_virtual_machine_valid_base_image(self, mock_is_file):
self.vm_conf_["base_image"] = "/path/to/base_image"
self.deployer_.config_['vms'] = [self.vm_conf_]
ok = self.deployer_._parse_vms()
self.vm_ = self.deployer_.topology_.vms_[self.vm_conf_["name"]]
self.assertEqual(self.vm_.base_image_, "/path/to/base_image")
self.assertTrue(ok)

@mock.patch('pathlib.Path.is_file', return_value=False)
def test_add_virtual_machine_invalid_base_image(self, mock_is_file):
self.vm_conf_["base_image"] = "/path/to/base_image"
self.deployer_.config_['vms'] = [self.vm_conf_]
ok = self.deployer_._parse_vms()
self.vm_ = self.deployer_.topology_.vms_[self.vm_conf_["name"]]
self.assertFalse(ok)
del self.deployer_.topology_.vms_[self.vm_conf_["name"]]

def test_add_virtual_machine_default_base_image(self):
self.deployer_.config_['vms'] = [self.vm_conf_]
ok = self.deployer_._parse_vms()
self.vm_ = self.deployer_.topology_.vms_[self.vm_conf_["name"]]
self.assertEqual(self.vm_.base_image_, G.UBUNTU_TEMPLATE)
self.assertTrue(ok)
19 changes: 17 additions & 2 deletions deployer/virtual_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import yaml
import ipaddress
from pathlib import Path

import deployer.globals as G
from deployer.globals import LIBVIRT_IMAGES, VM_FLAVORS
Expand All @@ -21,6 +22,7 @@ class VirtualMachine:
vcpus_ = 8
ram_ = 16384
root_disk_sz_ = "80G"
base_image_ = ""
topology_ = Topology()

def __new__(cls, conf):
Expand All @@ -31,7 +33,8 @@ def __new__(cls, conf):

def __init__(self, conf):
self.name_ = conf["name"]
self.flavor_ = conf["flavor"]
self.base_image_ = conf.get("base_image", G.OS_IMAGE_TEMPLATE)
self.flavor_ = conf.get("flavor", "")
self.vnc_port_ = int(conf["vnc_port"])
self.libvirt_vm_base = LIBVIRT_IMAGES.joinpath(self.name_)
self.user_data_cfg_ = self.libvirt_vm_base.joinpath("user-data.cfg")
Expand Down Expand Up @@ -72,6 +75,15 @@ def _has_valid_vm_fields(vm):
logging.critical("'name' is required key in vm config")
return False

base_image = vm.get("base_image", None)
if base_image:
if not isinstance(base_image, str):
logging.critical("'base_image' must be a string")
return False
if not Path(base_image).is_file():
logging.critical(f"'base_image' file does not exist: {base_image}")
return False

networks = vm.get("networks", None)
if not networks or not isinstance(networks, dict):
logging.critical("'networks' is required key in vm config")
Expand Down Expand Up @@ -155,6 +167,9 @@ def _validate_vm_network_config(nws):

@staticmethod
def _validate_vm_config(vm):
if G.NO_VM:
return True

if not VirtualMachine._has_valid_vm_fields(vm):
return False

Expand Down Expand Up @@ -324,7 +339,7 @@ def __generate_iso_config(self, ip4, ip6):
# end __generate_iso_config

def __create_root_disk(self):
cmd = f"sudo qemu-img convert -f qcow2 -O qcow2 {G.OS_IMAGE_TEMPLATE} {self.root_disk_}"
cmd = f"sudo qemu-img convert -f qcow2 -O qcow2 {self.base_image_} {self.root_disk_}"
ExecuteCommand(cmd)

cmd = f"sudo qemu-img resize {self.root_disk_} {self.root_disk_sz_}"
Expand Down
1 change: 1 addition & 0 deletions topologies/evpn-2pe.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
],
"vms" : [{
"name": "evpn-pe1",
"base_image": "~/github/topology-deployer/README.md",
"flavor": "pe",
"vnc_port": 5950,
"networks": {
Expand Down

0 comments on commit af52412

Please sign in to comment.