Skip to content

Commit

Permalink
[antlir2][vm] implement 9p sharing
Browse files Browse the repository at this point in the history
Summary:
Unfortunately we still have lots of RSW on 5.2 kernel that requires
vmtest coverage. Their timeline for migration is end of Q1 2024, but I don't
want to wait that long. So support 9p share so that we can wrap up the last
test for antlir2 vm migration.

Test Plan:
The newly added unit tests and vm test should cover this.
```name=boot default vm and examine shares
$ buck run metalos/vm:kernel-5.2.9-242_fbk16_zion_4245_g53e65cc15fc6-vm
[root@vmtest ~]# uname -r
5.2.9-242_fbk16_zion_4245_g53e65cc15fc6
[root@vmtest ~]# mount | grep ^fs
fs1 on /data/users/junjiew/fbsource type 9p (ro,relatime,dirsync,loose,access=client,msize=512000,trans=virtio)
fs2 on /mnt/gvfs type 9p (ro,relatime,dirsync,loose,access=client,msize=512000,trans=virtio)
fs0 on /usr/local/fbcode type 9p (ro,relatime,dirsync,loose,access=client,msize=512000,trans=virtio)
```

```name=kernel version test
$ buck test metalos/vm/tests:kernel-version-test-5.2.9-229_fbk15_hardened_4185_g357f49b36602
File changed: fbcode//metalos/vm/TARGETS
File changed: fbcode//antlir/antlir2/antlir2_vm/src/share.rs
Buck UI: https://www.internalfb.com/buck2/11750c91-51f0-47cf-bdc0-105d71836a2c
Test UI: https://www.internalfb.com/intern/testinfra/testrun/16607023633164027
Network: Up: 289MiB  Down: 1.5GiB  (reSessionID-0e349c3c-cd19-42e0-be46-f50c8996d70f)
Jobs completed: 341920. Time elapsed: 5:13.8s.
Cache hits: 99%. Commands: 47237 (cached: 46619, remote: 4, local: 614). Fallback: 5/618
Tests finished: Pass 1. Fail 0. Fatal 0. Skip 0. Build failure 0
```

```name=verify VM with newer kernel still use virtiofs
$ buck run antlir/antlir2/antlir2_vm:default-nondisk-boot
[root@vmtest ~]# uname -r
5.12.0-0_fbk16_hardened_7661_geb00762ce6d2
[root@vmtest ~]# mount | grep ^fs
fs2 on /mnt/gvfs type virtiofs (ro,relatime)
fs1 on /usr/local/fbcode type virtiofs (ro,relatime)
fs0 on /data/users/junjiew/fbsource type virtiofs (ro,relatime)

$ buck run metalos/vm:kernel-5.19.0-0_fbk21_rc4_12486_g25ff0d359bcf-vm
[root@vmtest ~]# uname -r
5.19.0-0_fbk21_rc4_12486_g25ff0d359bcf
[root@vmtest ~]# mount | grep ^fs
fs0 on /data/users/junjiew/fbsource type virtiofs (ro,relatime)
fs2 on /mnt/gvfs type virtiofs (ro,relatime)
fs1 on /usr/local/fbcode type virtiofs (ro,relatime)
```

Reviewed By: cooperlees

Differential Revision: D50483032

fbshipit-source-id: f0778899a2477d2471c9c7341d689023af98dfb7
  • Loading branch information
wujj123456 authored and facebook-github-bot committed Oct 23, 2023
1 parent 5208bd8 commit d9b2175
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 4 deletions.
5 changes: 5 additions & 0 deletions antlir/antlir2/antlir2_vm/bzl/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def _machine_json(ctx: AnalysisContext) -> (Artifact, typing.Any):
"num_nics": ctx.attrs.num_nics,
"serial_index": ctx.attrs.serial_index,
"sidecar_services": ctx.attrs.sidecar_services,
"use_legacy_share": ctx.attrs.use_legacy_share,
"use_tpm": ctx.attrs.use_tpm,
},
with_inputs = True,
Expand Down Expand Up @@ -131,6 +132,10 @@ _vm_host = rule(
"mem_mib": attrs.int(default = 4096, doc = "memory size in MiB"),
"num_nics": attrs.int(default = 1),
"serial_index": attrs.int(default = 0, doc = "index of the serial port"),
"use_legacy_share": attrs.bool(
default = False,
doc = "use 9p instead of virtiofs for sharing for older kernels",
),
"use_tpm": attrs.bool(default = False, doc = "enable software TPM"),
} | {
# Non-hardware parameters for the VM
Expand Down
11 changes: 7 additions & 4 deletions antlir/antlir2/antlir2_vm/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use crate::isolation::is_isolated;
use crate::isolation::isolated;
use crate::isolation::Platform;
use crate::runtime::set_runtime;
use crate::share::NinePShare;
use crate::share::VirtiofsShare;
use crate::types::MachineOpts;
use crate::types::RuntimeOpts;
Expand Down Expand Up @@ -106,10 +107,12 @@ fn run(args: &RunCmdArgs) -> Result<()> {

set_runtime(args.runtime_spec.clone().into_inner())
.map_err(|_| anyhow!("Failed to set runtime"))?;
Ok(
VM::<VirtiofsShare>::new(args.machine_spec.clone().into_inner(), args.vm_args.clone())?
.run()?,
)
let machine_opts = args.machine_spec.clone().into_inner();
if machine_opts.use_legacy_share {
Ok(VM::<NinePShare>::new(machine_opts, args.vm_args.clone())?.run()?)
} else {
Ok(VM::<VirtiofsShare>::new(machine_opts, args.vm_args.clone())?.run()?)
}
}

/// Enter isolated container and then respawn itself inside it with `run`
Expand Down
82 changes: 82 additions & 0 deletions antlir/antlir2/antlir2_vm/src/share.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,55 @@ impl VirtiofsShare {
}
}

/// `9pShare` for older kernels
#[derive(Debug, Default)]
pub(crate) struct NinePShare {
/// User specified options for the share
opts: ShareOpts,
/// Index of the share, used to generate unique mount tag, chardev name
/// and socket file.
id: usize,
/// Mount type
mount_type: &'static str,
}

impl Share for NinePShare {
share_getters!();

fn new(opts: ShareOpts, id: usize, _state_dir: PathBuf) -> Self {
Self {
opts,
id,
mount_type: "9p",
}
}

fn setup(&self) -> Result<()> {
Ok(())
}
fn mount_options(&self) -> String {
format!(
"version=9p2000.L,posixacl,cache={cache},{ro_rw},msize=209715200",
cache = if self.opts.read_only { "loose" } else { "none" },
ro_rw = if self.opts.read_only { "ro" } else { "rw" },
)
}

fn qemu_args(&self) -> Vec<OsString> {
let mut args = vec!["-virtfs".into()];
args.push(
format!(
"local,path={path},security_model=none,multidevs=remap,mount_tag={tag},readonly={ro}",
path = self.opts.path.to_str().expect("Path should be valid string"),
tag = self.mount_tag(),
ro = if self.opts.read_only { "on" } else { "off" },

).into()
);
args
}
}

/// In order to mount shares, we have to share something into the VM
/// that contains various mount units for mount generator. This struct
/// represents the initial trojan horse into the VM.
Expand Down Expand Up @@ -332,6 +381,8 @@ mod test {
let share = VirtiofsShare::new(opts, 3, PathBuf::from("/tmp/test"));

assert_eq!(&share.mount_tag(), "fs3");
assert_eq!(share.get_mount_type(), "virtiofs");
assert_eq!(&share.mount_options(), "ro");
assert_eq!(&share.chardev_node(), "fs_chardev3");
assert_eq!(share.socket_path(), PathBuf::from("/tmp/test/fs3"));
assert_eq!(
Expand Down Expand Up @@ -390,6 +441,37 @@ Options=rw"#;
);
}

#[test]
fn test_9p_share() {
let opts = ShareOpts {
path: PathBuf::from("/this/is/a/test"),
read_only: true,
mount_tag: None,
};
let mut share = NinePShare::new(opts, 3, PathBuf::from("/tmp/test"));

assert_eq!(&share.mount_tag(), "fs3");
assert_eq!(share.get_mount_type(), "9p");
assert_eq!(
&share.mount_options(),
"version=9p2000.L,posixacl,cache=loose,ro,msize=209715200",
);
assert_eq!(
&share.qemu_args().join(OsStr::new(" ")),
"-virtfs local,path=/this/is/a/test,security_model=none,multidevs=remap,mount_tag=fs3,readonly=on",
);

share.opts.read_only = false;
assert_eq!(
&share.mount_options(),
"version=9p2000.L,posixacl,cache=none,rw,msize=209715200",
);
assert_eq!(
&share.qemu_args().join(OsStr::new(" ")),
"-virtfs local,path=/this/is/a/test,security_model=none,multidevs=remap,mount_tag=fs3,readonly=off",
);
}

#[test]
fn test_shares() {
let opts = ShareOpts {
Expand Down
2 changes: 2 additions & 0 deletions antlir/antlir2/antlir2_vm/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ pub(crate) struct MachineOpts {
pub(crate) sidecar_services: Vec<Vec<String>>,
/// Enables TPM 2.0 support
pub(crate) use_tpm: bool,
/// Use 9p instead of virtiofs for sharing. This is required for kernel older than 5.4.
pub(crate) use_legacy_share: bool,
}

/// Location of various binary and data we need to operate the VM
Expand Down

0 comments on commit d9b2175

Please sign in to comment.