Skip to content

Commit

Permalink
virtme-ng: introduce NUMA support
Browse files Browse the repository at this point in the history
Add the --numa option to create custom NUMA nodes inside the guest and
assign virtual CPUs to them.

Syntax:

  --numa MEM[,cpus=FIRST_CPU1[-LAST_CPU1]][,cpus=FIRST_CPU2[-LAST_CPU2]]...

Example:

 $ vng -r -m 4G --numa 2G,cpus=0-1,cpus=3 --numa 2G,cpus=2,cpus=4-7 -- numactl -H
 available: 2 nodes (0-1)
 node 0 cpus: 0 1 3
 node 0 size: 2013 MB
 node 0 free: 1939 MB
 node 1 cpus: 2 4 5 6 7
 node 1 size: 1908 MB
 node 1 free: 1782 MB
 node distances:
 node   0   1
   0:  10  20
   1:  20  10

Keep in mind that using --numa automatically disables the microvm
architecture (that doesn't expose NUMA information).

Also note that virtiofsd requires a memory backed NUMA node, so if some
custom NUMA nodes are created virtiofs will use the first one of them,
otherwise it will create a single NUMA node that maps all the memory
(that was the previous behavior).

But this allows to use --numa and enable virtiofsd at the same time.

This implements the request from issue #56.

Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
  • Loading branch information
Andrea Righi committed Jan 27, 2024
1 parent 19d5f89 commit 82d19fd
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 4 deletions.
30 changes: 26 additions & 4 deletions virtme/commands/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ def make_parser() -> argparse.ArgumentParser:
default=None,
help="Set guest memory and qemu -m flag.",
)
g.add_argument(
"--numa",
action="append",
default=None,
help="Create NUMA nodes in the guest.",
)
g.add_argument(
"--cpus", action="store", default=None, help="Set guest cpu and qemu -smp flag."
)
Expand Down Expand Up @@ -643,11 +649,14 @@ def export_virtiofs(

# Adjust qemu options to use virtiofsd
fsid = "virtfs%d" % len(qemuargs)
if memory is None:
memory = "128M"

vhost_dev_type = arch.vhost_dev_type()
qemuargs.extend(["-chardev", f"socket,id=char{fsid},path={virtio_fs.sock}"])
qemuargs.extend(["-device", f"{vhost_dev_type},chardev=char{fsid},tag={mount_tag}"])
if memory is None:
memory = "128M"
elif memory == 0:
return True
qemuargs.extend(["-object", f"memory-backend-memfd,id=mem,size={memory},share=on"])
qemuargs.extend(["-numa", "node,memdev=mem"])

Expand Down Expand Up @@ -724,7 +733,7 @@ def can_use_kvm():


def can_use_microvm(args):
return not args.disable_microvm and args.arch == "x86_64" and can_use_kvm()
return not args.disable_microvm and not args.numa and args.arch == "x86_64" and can_use_kvm()


def has_read_acl(username, file_path):
Expand Down Expand Up @@ -799,6 +808,16 @@ def do_it() -> int:
args.memory += "M"
qemuargs.extend(["-m", args.memory])

# Parse NUMA settings.
if args.numa:
for i, numa in enumerate(args.numa, start=1):
size, cpus = numa.split(",", 1) if "," in numa else (numa, None)
cpus = f",{cpus}" if cpus else ""
qemuargs.extend([
"-object", f"memory-backend-memfd,id=mem{i},size={size},share=on",
"-numa", f"node,memdev=mem{i}{cpus}"
])

if args.snaps:
if args.root == "/":
snapd_state = "/var/lib/snapd/state.json"
Expand Down Expand Up @@ -853,7 +872,10 @@ def do_it() -> int:
args.root,
"ROOTFS",
guest_tools_path=guest_tools_path,
memory=args.memory,
# virtiofsd requires a NUMA not, if --numa is specified simply use
# the user-defined NUMA node, otherwise create a NUMA node with all
# the memory.
memory=0 if args.numa else args.memory,
verbose=args.verbose,
)
if can_use_microvm(args) and use_virtiofs:
Expand Down
16 changes: 16 additions & 0 deletions virtme_ng/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,13 @@ def make_parser():
"--memory", "-m", action="store", help="Set guest memory size (qemu -m flag)"
)

parser.add_argument(
"--numa",
metavar="MEM[,cpus=FIRST_CPU1[-LAST_CPU1]][,cpus=FIRST_CPU2[-LAST_CPU2]]...",
action="append",
help="Create NUMA nodes in the guest (this implicitly disables the microvm architecture)"
)

parser.add_argument(
"--balloon",
action="store_true",
Expand Down Expand Up @@ -879,6 +886,13 @@ def _get_virtme_memory(self, args):
else:
self.virtme_param["memory"] = "--memory " + args.memory

def _get_virtme_numa(self, args):
if args.numa is not None:
numa_str = " ".join([f"--numa {numa}" for numa in args.numa])
self.virtme_param["numa"] = numa_str
else:
self.virtme_param["numa"] = ""

def _get_virtme_balloon(self, args):
if args.balloon:
self.virtme_param["balloon"] = "--balloon"
Expand Down Expand Up @@ -948,6 +962,7 @@ def run(self, args):
self._get_virtme_append(args)
self._get_virtme_cpus(args)
self._get_virtme_memory(args)
self._get_virtme_numa(args)
self._get_virtme_balloon(args)
self._get_virtme_snaps(args)
self._get_virtme_busybox(args)
Expand Down Expand Up @@ -982,6 +997,7 @@ def run(self, args):
+ f'{self.virtme_param["append"]} '
+ f'{self.virtme_param["cpus"]} '
+ f'{self.virtme_param["memory"]} '
+ f'{self.virtme_param["numa"]} '
+ f'{self.virtme_param["balloon"]} '
+ f'{self.virtme_param["snaps"]} '
+ f'{self.virtme_param["busybox"]} '
Expand Down

0 comments on commit 82d19fd

Please sign in to comment.