Skip to content

Commit 249b3ca

Browse files
helltjmussmann
andauthored
Introducing Ubuntu support and qemu args (cpu/mem/smp/args) (#198)
* add ubuntu support * add ubuntu to global Makefile * using env variables for cpu, number of cpus and memory * use the cpu, smp and memory options of vrnetlab.VM * add: allow additional disk using ADD_DISK ENV * preprend qemu cpu/mem/smp args with qemu prefix * set bash shell for the user do not upgrade the base vm add support for qemu additional args --------- Co-authored-by: jmussmann <[email protected]>
1 parent 1e1ec73 commit 249b3ca

File tree

24 files changed

+486
-116
lines changed

24 files changed

+486
-116
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
IMAGES_DIR=
2-
VRS = vr-xcon vr-bgp csr nxos routeros sros veos vjunosswitch vjunosevolved vmx vsr1000 vqfx vrp xrv xrv9k vsrx openbsd ftdv freebsd
2+
VRS = vr-xcon vr-bgp csr nxos routeros sros veos vjunosswitch vjunosevolved vmx vsr1000 vqfx vrp xrv xrv9k vsrx openbsd ftdv freebsd ubuntu
33
VRS_PUSH = $(VRS:=-push)
44

55
.PHONY: all $(VRS) $(VRS_PUSH)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Since the changes we made in this fork are VM specific, we added a few popular r
5454
* Nokia SR OS
5555
* OpenBSD
5656
* FreeBSD
57+
* Ubuntu
5758

5859
The rest are left untouched and can be contributed back by the community.
5960

aoscx/docker/launch.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,12 @@ def __init__(self, hostname, username, password, conn_mode):
4747
logging.getLogger().info("Disk image was not found")
4848
exit(1)
4949
super(AOSCX_vm, self).__init__(
50-
username, password, disk_image=disk_image, ram=4096
50+
username, password, disk_image=disk_image, ram=4096, cpu="host,level=9", smp="2"
5151
)
5252
self.hostname = hostname
5353
self.conn_mode = conn_mode
5454
self.num_nics = 20
5555
self.nic_type = "virtio-net-pci"
56-
self.qemu_args.extend(["-cpu", "host,level=9"])
57-
self.qemu_args.extend(["-smp", "2"])
5856

5957
def bootstrap_spin(self):
6058
"""This function should be called periodically to do work."""

common/vrnetlab.py

Lines changed: 85 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ def __init__(
7676
ram=4096,
7777
driveif="ide",
7878
provision_pci_bus=True,
79+
cpu="host",
80+
smp=1,
7981
):
8082
self.logger = logging.getLogger()
8183

@@ -91,6 +93,10 @@ def __init__(
9193
self.p = None
9294
self.tn = None
9395

96+
self._ram = ram
97+
self._cpu = cpu
98+
self._smp = smp
99+
94100
# various settings
95101
self.uuid = None
96102
self.fake_start_date = None
@@ -135,20 +141,30 @@ def __init__(
135141
]
136142
)
137143

138-
self.qemu_args = ["qemu-system-x86_64", "-display", "none", "-machine", "pc"]
139-
self.qemu_args.extend(
140-
["-monitor", "tcp:0.0.0.0:40%02d,server,nowait" % self.num]
141-
)
142-
self.qemu_args.extend(
143-
[
144-
"-m",
145-
str(ram),
146-
"-serial",
147-
"telnet:0.0.0.0:50%02d,server,nowait" % self.num,
148-
"-drive",
149-
f"if={driveif},file={overlay_disk_image}",
150-
]
151-
)
144+
self.qemu_args = [
145+
"qemu-system-x86_64",
146+
"-display",
147+
"none",
148+
"-machine",
149+
"pc",
150+
"-monitor",
151+
f"tcp:0.0.0.0:40{self.num:02d},server,nowait",
152+
"-serial",
153+
f"telnet:0.0.0.0:50{self.num:02d},server,nowait",
154+
"-m", # memory
155+
str(self.ram),
156+
"-cpu", # cpu type
157+
self.cpu,
158+
"-smp",
159+
self.smp, # cpu core configuration
160+
"-drive",
161+
f"if={driveif},file={overlay_disk_image}",
162+
]
163+
164+
# add additional qemu args if they were provided
165+
if self.qemu_additional_args:
166+
self.qemu_args.extend(self.qemu_additional_args)
167+
152168
# enable hardware assist if KVM is available
153169
if os.path.exists("/dev/kvm"):
154170
self.qemu_args.insert(1, "-enable-kvm")
@@ -706,7 +722,6 @@ def check_qemu(self):
706722
self.stop()
707723
self.start()
708724

709-
710725
@property
711726
def version(self):
712727
"""Read version number from VERSION environment variable
@@ -719,6 +734,57 @@ def version(self):
719734
return version
720735
raise ValueError("The VERSION environment variable is not set")
721736

737+
@property
738+
def ram(self):
739+
"""
740+
Read memory size from the QEMU_MEMORY environment variable and use it in the qemu parameters for the VM.
741+
If the QEMU_MEMORY environment variable is not set, use the default value.
742+
Should be provided as a number of MB. e.g. 4096.
743+
"""
744+
745+
if "QEMU_MEMORY" in os.environ:
746+
return get_digits(str(os.getenv("QEMU_MEMORY")))
747+
748+
return self._ram
749+
750+
@property
751+
def cpu(self):
752+
"""
753+
Read the CPU type the QEMU_CPU environment variable and use it in the qemu parameters for the VM.
754+
If the QEMU_CPU environment variable is not set, use the default value.
755+
"""
756+
757+
if "QEMU_CPU" in os.environ:
758+
return str(os.getenv("QEMU_CPU"))
759+
760+
return str(self._cpu)
761+
762+
@property
763+
def smp(self):
764+
"""
765+
Read SMP parameter (e.g. number of CPU cores) from the QEMU_SMP environment variable.
766+
If the QEMU_SMP parameter is not set, the default value is used.
767+
Should be provided as a number, e.g. 2
768+
"""
769+
770+
if "QEMU_SMP" in os.environ:
771+
return str(os.getenv("QEMU_SMP"))
772+
773+
return str(self._smp)
774+
775+
@property
776+
def qemu_additional_args(self):
777+
"""
778+
Read additional qemu arguments (e.g. number of CPU cores) from the QEMU_ADDITIONAL_ARGS environment variable.
779+
If the QEMU_ADDITIONAL_ARGS parameter is not set, nothing is added to the default args set.
780+
Should be provided as a space separated list of arguments, e.g. "-machine pc -display none"
781+
"""
782+
783+
if "QEMU_ADDITIONAL_ARGS" in os.environ:
784+
s = str(os.getenv("QEMU_ADDITIONAL_ARGS"))
785+
if s:
786+
return s.split()
787+
722788

723789
class VR:
724790
def __init__(self, username, password):
@@ -777,49 +843,10 @@ class QemuBroken(Exception):
777843
"""Our Qemu instance is somehow broken"""
778844

779845

780-
# getMem returns the RAM size (in Mb) for a given VM mode.
781-
# RAM can be specified in the variant dict, provided by a user via the custom type definition,
782-
# or set via env vars.
783-
# If set via env vars, the getMem will return this value as the most specific one.
784-
# Otherwise, the ram provided to this function will be converted to Mb and returned.
785-
def getMem(vmMode: str, ram: int) -> int:
786-
if vmMode == "integrated":
787-
# Integrated VM can use both MEMORY and CP_MEMORY env vars
788-
if "MEMORY" in os.environ:
789-
return 1024 * get_digits(os.getenv("MEMORY"))
790-
if "CP_MEMORY" in os.environ:
791-
return 1024 * get_digits(os.getenv("CP_MEMORY"))
792-
if vmMode == "cp":
793-
if "CP_MEMORY" in os.environ:
794-
return 1024 * get_digits(os.getenv("CP_MEMORY"))
795-
if vmMode == "lc":
796-
if "LC_MEMORY" in os.environ:
797-
return 1024 * get_digits(os.getenv("LC_MEMORY"))
798-
return 1024 * int(ram)
799-
800-
801-
# getCpu returns the number of cpu cores for a given VM mode.
802-
# Cpu can be specified in the variant dict, provided by a user via the custom type definition,
803-
# or set via env vars.
804-
# If set via env vars, the function will return this value as the most specific one.
805-
# Otherwise, the number provided to this function via cpu param returned.
806-
def getCpu(vsimMode: str, cpu: int) -> int:
807-
if vsimMode == "integrated":
808-
# Integrated VM can use both MEMORY and CP_MEMORY env vars
809-
if "CPU" in os.environ:
810-
return int(os.getenv("CPU"))
811-
if "CP_CPU" in os.environ:
812-
return int(os.getenv("CP_CPU"))
813-
if vsimMode == "cp":
814-
if "CP_CPU" in os.environ:
815-
return int(os.getenv("CP_CPU"))
816-
if vsimMode == "lc":
817-
if "LC_CPU" in os.environ:
818-
return int(os.getenv("LC_CPU"))
819-
return cpu
820-
821-
822-
# strip all non-numeric characters from a string
823846
def get_digits(input_str: str) -> int:
847+
"""
848+
Strip all non-numeric characters from a string
849+
"""
850+
824851
non_string_chars = re.findall(r"\d", input_str)
825852
return int("".join(non_string_chars))

fortigate/docker/launch.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ def __init__(self, hostname, username, password, conn_mode):
5656
self.nic_type = "virtio-net-pci"
5757
self.highest_port = 0
5858
self.qemu_args.extend(["-uuid", str(uuid.uuid4())])
59-
self.qemu_args.extend(["-smp", "1", "-cpu", "host"])
6059
self.spins = 0
6160
self.running = None
6261

ftdv/docker/launch.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ def trace(self, message, *args, **kws):
3838

3939

4040
class FTDV_vm(vrnetlab.VM):
41+
42+
# FIPS check fails without exposing cpu (ERROR: FIPS Self-Test failure, fipsPostGFSboxKat)
4143
def __init__(
42-
self, hostname, username, password, nics, conn_mode, install_mode=False
44+
self, hostname, username, password, nics, conn_mode, install_mode=False, smp="4,sockets=1,cores=4,threads=1"
4345
):
4446
for e in os.listdir("/"):
4547
if re.search(".qcow2$", e):
@@ -56,8 +58,6 @@ def __init__(
5658
self.hostname = hostname
5759
self.conn_mode = conn_mode
5860
self.nic_type = "virtio-net-pci"
59-
# FIPS check fails without exposing cpu (ERROR: FIPS Self-Test failure, fipsPostGFSboxKat)
60-
self.qemu_args.extend(["-cpu", "host", "-smp", "4,sockets=1,cores=4,threads=1"])
6161
overlay_disk_image = re.sub(r"(\.[^.]+$)", r"-overlay\1", disk_image)
6262
# boot harddrive first
6363
self.qemu_args.extend(["-boot", "order=c"])

ftosv/docker/launch.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def __init__(self, hostname, username, password, conn_mode):
4747
logging.getLogger().info("Disk image was not found")
4848
exit(1)
4949
super(FTOS_vm, self).__init__(
50-
username, password, disk_image=disk_image, ram=4096
50+
username, password, disk_image=disk_image, ram=4096, smp="4"
5151
)
5252
self.credentials = [["admin", "admin"]]
5353
self.hostname = hostname
@@ -57,7 +57,6 @@ def __init__(self, hostname, username, password, conn_mode):
5757
# available OS10 virtualization platform options: S4000,S4128,S5212,S5224,S5248,S6000,S6010
5858
self.num_nics = 56
5959
self.nic_type = "e1000"
60-
self.qemu_args.extend(["-cpu", "host", "-smp", "4"])
6160

6261
overlay_disk_image = re.sub(r"(\.[^.]+$)", r"-overlay\1", disk_image)
6362
# boot harddrive first

n9kv/docker/launch.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,13 @@ def __init__(self, hostname, username, password, conn_mode):
4848
logging.getLogger().info("Disk image was not found")
4949
exit(1)
5050
super(N9KV_vm, self).__init__(
51-
username, password, disk_image=disk_image, ram=8192
51+
username, password, disk_image=disk_image, ram=8192, cpu="host,level=9"
5252
)
5353
self.hostname = hostname
5454
self.conn_mode = conn_mode
5555
# mgmt + 128 that show up in the vm, may as well populate them all in vrnetlab right away
5656
self.num_nics = 129
5757
self.nic_type = "e1000"
58-
self.qemu_args.extend(["-cpu", "host,level=9"])
5958

6059
# bios for n9kv
6160
self.qemu_args.extend(["-bios", "/OVMF.fd"])

nxos/docker/launch.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,11 @@ def __init__(self, hostname, username, password, conn_mode):
4444
if re.search(".qcow2$", e):
4545
disk_image = "/" + e
4646
super(NXOS_vm, self).__init__(
47-
username, password, disk_image=disk_image, ram=4096
47+
username, password, disk_image=disk_image, ram=4096, smp="2"
4848
)
4949
self.credentials = [["admin", "admin"]]
5050
self.hostname = hostname
5151
self.conn_mode = conn_mode
52-
self.qemu_args.extend(["-cpu", "host", "-smp", "2"])
5352

5453
def bootstrap_spin(self):
5554
"""This function should be called periodically to do work."""

ocnos/docker/launch.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,13 @@ def __init__(self, hostname, username, password, conn_mode):
4747
logging.getLogger().info("Disk image was not found")
4848
exit(1)
4949
super(OCNOS_vm, self).__init__(
50-
username, password, disk_image=disk_image, ram=4096
50+
username, password, disk_image=disk_image, ram=4096, cpu="host,level=9", smp="2,sockets=1,cores=1"
5151
)
5252
self.hostname = hostname
5353
self.conn_mode = conn_mode
5454
self.num_nics = 8
5555
self.nic_type = "virtio-net-pci"
5656

57-
self.qemu_args.extend(["-cpu", "host,level=9"])
58-
self.qemu_args.extend(["-smp", "2,sockets=1,cores=1"])
5957

6058
def bootstrap_spin(self):
6159
"""This function should be called periodically to do work."""

pan/docker/launch.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,13 @@ def __init__(self, hostname, username, password, conn_mode):
4949
logging.getLogger().info("Disk image was not found")
5050
exit(1)
5151
super(PAN_vm, self).__init__(
52-
username, password, disk_image=disk_image, ram=6144
52+
username, password, disk_image=disk_image, ram=6144, cpu="host,level=9", smp="2,sockets=1,cores=1"
5353
)
5454
self.hostname = hostname
5555
self.conn_mode = conn_mode
5656
# mgmt + 24 that show up in the vm, may as well populate them all in vrnetlab right away
5757
self.num_nics = 25
5858
self.nic_type = "virtio-net-pci"
59-
self.qemu_args.extend(["-cpu", "host,level=9"])
60-
self.qemu_args.extend(["-smp", "2,sockets=1,cores=1"])
6159
# pan wants a uuid it seems (for licensing reasons?!)
6260
self.uuid = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
6361

0 commit comments

Comments
 (0)