def build(self, kernel: Artifact, disks: [DiskArtifact], config: Artifact): """Build a fresh microvm.""" vm = init_microvm(self.root_path, self.bin_cloner_path) vm.setup() # Link the microvm to kernel, rootfs, ssh_key artifacts. vm.kernel_file = kernel.local_path() vm.rootfs_file = disks[0].local_path() ssh_key = disks[0].ssh_key() # Download ssh key into microvm root. ssh_key.download(self.root_path) vm.ssh_config['ssh_key_path'] = ssh_key.local_path() os.chmod(vm.ssh_config['ssh_key_path'], 0o400) # Start firecracker. vm.spawn() with open(config.local_path()) as microvm_config_file: microvm_config = json.load(microvm_config_file) # Apply the microvm artifact configuration vm.basic_config(vcpu_count=int(microvm_config['vcpu_count']), mem_size_mib=int(microvm_config['mem_size_mib']), ht_enabled=bool(microvm_config['ht_enabled'])) return vm
def build(self, kernel: Artifact, disks: [DiskArtifact], ssh_key: Artifact, config: Artifact, enable_diff_snapshots=False): """Build a fresh microvm.""" self.init_root_path() vm = init_microvm(self.root_path, self.bin_cloner_path) # Link the microvm to kernel, rootfs, ssh_key artifacts. vm.kernel_file = kernel.local_path() vm.rootfs_file = disks[0].local_path() # Download ssh key into the microvm root. ssh_key.download(self.root_path) vm.ssh_config['ssh_key_path'] = ssh_key.local_path() os.chmod(vm.ssh_config['ssh_key_path'], 0o400) # Start firecracker. vm.spawn() with open(config.local_path()) as microvm_config_file: microvm_config = json.load(microvm_config_file) # Apply the microvm artifact configuration vm.basic_config(vcpu_count=int(microvm_config['vcpu_count']), mem_size_mib=int(microvm_config['mem_size_mib']), ht_enabled=bool(microvm_config['ht_enabled']), track_dirty_pages=enable_diff_snapshots, boot_args='console=ttyS0 reboot=k panic=1') return vm
def _get_snapshot_files_paths(snapshot_dir): mem = vmstate = ssh_key = disk = None for file in os.listdir(snapshot_dir): file_path = os.path.join(Artifact.LOCAL_ARTIFACT_DIR, file) if file.endswith(".mem"): mem = file_path elif file.endswith(".vmstate"): vmstate = file_path elif file.endswith(".id_rsa"): ssh_key = Artifact( None, os.path.basename(file), ArtifactType.SSH_KEY, DEFAULT_TEST_SESSION_ROOT_PATH, ) file_path = ssh_key.local_path() pathlib.Path(os.path.dirname(file_path)).mkdir(parents=True, exist_ok=True) elif file.endswith(".ext4"): disk = file_path # Copy to default root session. shutil.copy(os.path.join(snapshot_dir, file), file_path) assert os.path.isfile(file_path) # Ensure all required snapshot files are present inside the dir. assert mem and vmstate and disk and ssh_key # Change ssh key permissions. os.chmod(ssh_key.local_path(), 0o400) return mem, vmstate, disk, ssh_key
def build(self, kernel: Artifact, disks: [DiskArtifact], ssh_key: Artifact, config: Artifact, enable_diff_snapshots=False, cpu_template=None): """Build a fresh microvm.""" vm = init_microvm(self.root_path, self.bin_cloner_path, self._fc_binary, self._jailer_binary) # Link the microvm to kernel, rootfs, ssh_key artifacts. vm.kernel_file = kernel.local_path() vm.rootfs_file = disks[0].local_path() # Start firecracker. vm.spawn() # Download ssh key into the microvm root. ssh_key.download(self.root_path) vm.ssh_config['ssh_key_path'] = ssh_key.local_path() os.chmod(vm.ssh_config['ssh_key_path'], 0o400) vm.create_tap_and_ssh_config(host_ip=DEFAULT_HOST_IP, guest_ip=DEFAULT_GUEST_IP, netmask_len=DEFAULT_NETMASK, tapname=DEFAULT_TAP_NAME) # TODO: propper network configuraiton with artifacts. guest_mac = net_tools.mac_from_ip(DEFAULT_GUEST_IP) response = vm.network.put( iface_id=DEFAULT_DEV_NAME, host_dev_name=DEFAULT_TAP_NAME, guest_mac=guest_mac, allow_mmds_requests=True, ) assert vm.api_session.is_status_no_content(response.status_code) with open(config.local_path()) as microvm_config_file: microvm_config = json.load(microvm_config_file) response = vm.basic_config(boot_args='console=ttyS0 reboot=k panic=1') # Apply the microvm artifact configuration and template. response = vm.machine_cfg.put( vcpu_count=int(microvm_config['vcpu_count']), mem_size_mib=int(microvm_config['mem_size_mib']), ht_enabled=bool(microvm_config['ht_enabled']), track_dirty_pages=enable_diff_snapshots, cpu_template=cpu_template, ) assert vm.api_session.is_status_no_content(response.status_code) # Reset root path so next microvm is built some place else. self.init_root_path() return vm
def create(self, disks, ssh_key: Artifact, snapshot_type: SnapshotType = SnapshotType.FULL, target_version: str = None, mem_file_name: str = "vm.mem", snapshot_name: str = "vm.vmstate", net_ifaces=None): """Create a Snapshot object from a microvm and artifacts.""" # Disable API timeout as the APIs for snapshot related procedures # take longer. self._microvm.api_session.untime() snapshot_dir = self.create_snapshot_dir() self._microvm.pause_to_snapshot( mem_file_path="/snapshot/" + mem_file_name, snapshot_path="/snapshot/" + snapshot_name, diff=snapshot_type == SnapshotType.DIFF, version=target_version) # Create a copy of the ssh_key artifact. ssh_key_copy = ssh_key.copy() mem_path = os.path.join(snapshot_dir, mem_file_name) vmstate_path = os.path.join(snapshot_dir, snapshot_name) return Snapshot( mem=mem_path, vmstate=vmstate_path, # TODO: To support more disks we need to figure out a # simple and flexible way to store snapshot artifacts # in S3. This should be done in a PR where we add tests # that resume from S3 snapshot artifacts. disks=disks, net_ifaces=net_ifaces or [NetIfaceConfig()], ssh_key=ssh_key_copy.local_path())
def create(self, disks, ssh_key: Artifact, snapshot_type: SnapshotType = SnapshotType.FULL, target_version: str = None): """Create a Snapshot object from a microvm and artifacts.""" # Disable API timeout as the APIs for snapshot related procedures # take longer. self._microvm.api_session.untime() chroot_path = self._microvm.jailer.chroot_path() snapshot_dir = os.path.join(chroot_path, "snapshot") Path(snapshot_dir).mkdir(parents=True, exist_ok=True) cmd = 'chown {}:{} {}'.format(self._microvm.jailer.uid, self._microvm.jailer.gid, snapshot_dir) utils.run_cmd(cmd) self._microvm.pause_to_snapshot( mem_file_path="/snapshot/vm.mem", snapshot_path="/snapshot/vm.vmstate", diff=snapshot_type == SnapshotType.DIFF, version=target_version) # Create a copy of the ssh_key artifact. ssh_key_copy = ssh_key.copy() mem_path = os.path.join(snapshot_dir, "vm.mem") vmstate_path = os.path.join(snapshot_dir, "vm.vmstate") return Snapshot(mem=mem_path, vmstate=vmstate_path, # TODO: To support more disks we need to figure out a # simple and flexible way to store snapshot artifacts # in S3. This should be done in a PR where we add tests # that resume from S3 snapshot artifacts. disks=disks, ssh_key=ssh_key_copy.local_path())
def create(self, disks, ssh_key: Artifact, snapshot_type: SnapshotType = SnapshotType.FULL, target_version: str = None, mem_file_name: str = "vm.mem", snapshot_name: str = "vm.vmstate", net_ifaces=None, use_ramdisk=False): """Create a Snapshot object from a microvm and artifacts.""" if use_ramdisk: snaps_dir = self._microvm.jailer.chroot_ramfs_path() mem_full_path = os.path.join(snaps_dir, mem_file_name) vmstate_full_path = os.path.join(snaps_dir, snapshot_name) memsize = self._microvm.machine_cfg.configuration['mem_size_mib'] # Pre-allocate ram for memfile to eliminate allocation variability. utils.run_cmd('dd if=/dev/zero of={} bs=1M count={}'.format( mem_full_path, memsize )) cmd = 'chown {}:{} {}'.format( self._microvm.jailer.uid, self._microvm.jailer.gid, mem_full_path ) utils.run_cmd(cmd) else: snaps_dir = self.create_snapshot_dir() mem_full_path = os.path.join(snaps_dir, mem_file_name) vmstate_full_path = os.path.join(snaps_dir, snapshot_name) snaps_dir_name = os.path.basename(snaps_dir) self._microvm.pause_to_snapshot( mem_file_path=os.path.join('/', snaps_dir_name, mem_file_name), snapshot_path=os.path.join('/', snaps_dir_name, snapshot_name), diff=snapshot_type == SnapshotType.DIFF, version=target_version) # Create a copy of the ssh_key artifact. ssh_key_copy = ssh_key.copy() return Snapshot(mem=mem_full_path, vmstate=vmstate_full_path, # TODO: To support more disks we need to figure out a # simple and flexible way to store snapshot artifacts # in S3. This should be done in a PR where we add tests # that resume from S3 snapshot artifacts. disks=disks, net_ifaces=net_ifaces or [NetIfaceConfig()], ssh_key=ssh_key_copy.local_path())
def build(self, kernel: Artifact, disks: [DiskArtifact], ssh_key: Artifact, config: Artifact, net_ifaces=None, enable_diff_snapshots=False, cpu_template=None, use_ramdisk=False): """Build a fresh microvm.""" vm = init_microvm(self.root_path, self.bin_cloner_path, self._fc_binary, self._jailer_binary) # Start firecracker. vm.spawn(use_ramdisk=use_ramdisk) # Link the microvm to kernel, rootfs, ssh_key artifacts. vm.kernel_file = kernel.local_path() vm.rootfs_file = disks[0].local_path() # copy rootfs to ramdisk if needed jailed_rootfs_path = vm.copy_to_jail_ramfs(vm.rootfs_file) if \ use_ramdisk else vm.create_jailed_resource(vm.rootfs_file) # Download ssh key into the microvm root. ssh_key.download(self.root_path) vm.ssh_config['ssh_key_path'] = ssh_key.local_path() os.chmod(vm.ssh_config['ssh_key_path'], 0o400) # Provide a default network configuration. if net_ifaces is None or len(net_ifaces) == 0: ifaces = [NetIfaceConfig()] else: ifaces = net_ifaces # Configure network interfaces using artifacts. for iface in ifaces: vm.create_tap_and_ssh_config(host_ip=iface.host_ip, guest_ip=iface.guest_ip, netmask_len=iface.netmask, tapname=iface.tap_name) guest_mac = net_tools.mac_from_ip(iface.guest_ip) response = vm.network.put( iface_id=iface.dev_name, host_dev_name=iface.tap_name, guest_mac=guest_mac, allow_mmds_requests=True, ) assert vm.api_session.is_status_no_content(response.status_code) with open(config.local_path()) as microvm_config_file: microvm_config = json.load(microvm_config_file) response = vm.basic_config( add_root_device=False, boot_args='console=ttyS0 reboot=k panic=1' ) # Add the root file system with rw permissions. response = vm.drive.put( drive_id='rootfs', path_on_host=jailed_rootfs_path, is_root_device=True, is_read_only=False ) assert vm.api_session \ .is_status_no_content(response.status_code), \ response.text # Apply the microvm artifact configuration and template. response = vm.machine_cfg.put( vcpu_count=int(microvm_config['vcpu_count']), mem_size_mib=int(microvm_config['mem_size_mib']), ht_enabled=bool(microvm_config['ht_enabled']), track_dirty_pages=enable_diff_snapshots, cpu_template=cpu_template, ) assert vm.api_session.is_status_no_content(response.status_code) vm.vcpus_count = int(microvm_config['vcpu_count']) # Reset root path so next microvm is built some place else. self.init_root_path() return vm