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 build_from_snapshot(self, snapshot: Snapshot, resume=False, # Enable incremental snapshot capability. diff_snapshots=False, use_ramdisk=False, fc_binary=None, jailer_binary=None, daemonize=True): """Build a microvm from a snapshot artifact.""" vm = init_microvm(self.root_path, self.bin_cloner_path, fc_binary, jailer_binary,) vm.jailer.daemonize = daemonize vm.spawn(log_level='Error', use_ramdisk=use_ramdisk) vm.api_session.untime() metrics_file_path = os.path.join(vm.path, 'metrics.log') metrics_fifo = log_tools.Fifo(metrics_file_path) response = vm.metrics.put( metrics_path=vm.create_jailed_resource(metrics_fifo.path) ) assert vm.api_session.is_status_no_content(response.status_code) # Hardlink all the snapshot files into the microvm jail. jailed_mem = vm.copy_to_jail_ramfs(snapshot.mem) if use_ramdisk else \ vm.create_jailed_resource(snapshot.mem) jailed_vmstate = vm.copy_to_jail_ramfs(snapshot.vmstate) \ if use_ramdisk else vm.create_jailed_resource(snapshot.vmstate) assert len(snapshot.disks) > 0, "Snapshot requires at least one disk." _jailed_disks = [] for disk in snapshot.disks: _jailed_disks.append(vm.copy_to_jail_ramfs(disk) if use_ramdisk else vm.create_jailed_resource(disk)) vm.ssh_config['ssh_key_path'] = snapshot.ssh_key.local_path() # Create network interfaces. for iface in snapshot.net_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) response = vm.snapshot.load(mem_file_path=jailed_mem, snapshot_path=jailed_vmstate, diff=diff_snapshots, resume=resume) status_ok = vm.api_session.is_status_no_content(response.status_code) # Verify response status and cleanup if needed before assert. if not status_ok: # Destroy VM here before we assert. vm.kill() del vm assert status_ok, response.text # Return a resumed microvm. return vm, metrics_fifo
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 build_from_snapshot( self, snapshot: Snapshot, host_ip=None, guest_ip=None, netmask_len=None, resume=False, # Enable incremental snapshot capability. enable_diff_snapshots=False): """Build a microvm from a snapshot artifact.""" self.init_root_path() vm = init_microvm(self.root_path, self.bin_cloner_path) vm.spawn(log_level='Info') metrics_file_path = os.path.join(vm.path, 'metrics.log') metrics_fifo = log_tools.Fifo(metrics_file_path) response = vm.metrics.put( metrics_path=vm.create_jailed_resource(metrics_fifo.path)) assert vm.api_session.is_status_no_content(response.status_code) # Hardlink all the snapshot files into the microvm jail. jailed_mem = vm.create_jailed_resource(snapshot.mem) jailed_vmstate = vm.create_jailed_resource(snapshot.vmstate) assert len(snapshot.disks) > 0, "Snapshot requiures at least one disk." _jailed_disks = [] for disk in snapshot.disks: _jailed_disks.append(vm.create_jailed_resource(disk)) vm.ssh_config['ssh_key_path'] = snapshot.ssh_key if host_ip is not None: vm.create_tap_and_ssh_config(host_ip=host_ip, guest_ip=guest_ip, netmask_len=netmask_len, tapname="tap0") response = vm.snapshot_load.put(mem_file_path=jailed_mem, snapshot_path=jailed_vmstate, diff=enable_diff_snapshots) assert vm.api_session.is_status_no_content(response.status_code) if resume: # Resume microvm response = vm.vm.patch(state='Resumed') assert vm.api_session.is_status_no_content(response.status_code) # Return a resumed microvm. return vm, metrics_fifo
def build_from_snapshot( self, snapshot: Snapshot, resume=False, # Enable incremental snapshot capability. enable_diff_snapshots=False): """Build a microvm from a snapshot artifact.""" vm = init_microvm(self.root_path, self.bin_cloner_path, self._fc_binary, self._jailer_binary) vm.spawn(log_level='Info') metrics_file_path = os.path.join(vm.path, 'metrics.log') metrics_fifo = log_tools.Fifo(metrics_file_path) response = vm.metrics.put( metrics_path=vm.create_jailed_resource(metrics_fifo.path)) assert vm.api_session.is_status_no_content(response.status_code) # Hardlink all the snapshot files into the microvm jail. jailed_mem = vm.create_jailed_resource(snapshot.mem) jailed_vmstate = vm.create_jailed_resource(snapshot.vmstate) assert len(snapshot.disks) > 0, "Snapshot requires at least one disk." _jailed_disks = [] for disk in snapshot.disks: _jailed_disks.append(vm.create_jailed_resource(disk)) vm.ssh_config['ssh_key_path'] = snapshot.ssh_key vm.create_tap_and_ssh_config(host_ip=DEFAULT_HOST_IP, guest_ip=DEFAULT_GUEST_IP, netmask_len=DEFAULT_NETMASK, tapname=DEFAULT_TAP_NAME) response = vm.snapshot_load.put(mem_file_path=jailed_mem, snapshot_path=jailed_vmstate, diff=enable_diff_snapshots) assert vm.api_session.is_status_no_content(response.status_code) if resume: # Resume microvm response = vm.vm.patch(state='Resumed') 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 a resumed microvm. return vm, metrics_fifo
def setup_vm(context): """Init microVM using context provided.""" root_path = context.custom['session_root_path'] bin_cloner_path = context.custom['bin_cloner_path'] print(f"Creating snapshot of microVM with kernel {context.kernel.name()}" f" and disk {context.disk.name()}.") vm = init_microvm(root_path, bin_cloner_path) # Change kernel name to match the one in the config file. kernel_full_path = os.path.join(vm.path, DEST_KERNEL_NAME) shutil.copyfile(context.kernel.local_path(), kernel_full_path) vm.kernel_file = kernel_full_path rootfs_full_path = os.path.join(vm.path, context.disk.name()) shutil.copyfile(context.disk.local_path(), rootfs_full_path) vm.rootfs_file = rootfs_full_path return vm
def build_from_snapshot( self, snapshot: Snapshot, host_ip, guest_ip, netmask_len, resume=False, # Enable incremental snapshot capability. enable_diff_snapshots=False): """Build a microvm from a snapshot artifact.""" self.init_root_path() vm = init_microvm(self.root_path, self.bin_cloner_path) vm.spawn(log_level='Debug') # Hardlink all the snapshot files into the microvm jail. jailed_mem = vm.create_jailed_resource(snapshot.mem) jailed_vmstate = vm.create_jailed_resource(snapshot.vmstate) assert len(snapshot.disks) > 0, "Snapshot requiures at least one disk." _jailed_disk = vm.create_jailed_resource(snapshot.disks[0]) vm.ssh_config['ssh_key_path'] = snapshot.ssh_key vm.create_tap_and_ssh_config(host_ip=host_ip, guest_ip=guest_ip, netmask_len=netmask_len, tapname="tap0") response = vm.snapshot_load.put(mem_file_path=jailed_mem, snapshot_path=jailed_vmstate, diff=enable_diff_snapshots) assert vm.api_session.is_status_no_content(response.status_code) if resume: # Resume microvm response = vm.vm.patch(state='Resumed') assert vm.api_session.is_status_no_content(response.status_code) # Return a resumed microvm. return vm
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
def create_basevm(self): """Create a clean VM in an initial state.""" return init_microvm(self.root_path, self.bin_cloner_path, self._fc_binary, self._jailer_binary)