diff --git a/example/ubuntu.json b/example/ubuntu.json index 6affcec..840ed5c 100644 --- a/example/ubuntu.json +++ b/example/ubuntu.json @@ -1,5 +1,5 @@ { - "machine_id": "banutoo", + "machine_id": "ubuntu", "machine_type": "q", "spec": { "options": { @@ -12,9 +12,15 @@ "drives": [ { "file": "ubuntu-root.bin", - "datastore": "realm", + "datastore": "default", "index": 0, "if": "virtio" + }, + { + "file": "ubuntu-14.04.iso", + "datastore": "default", + "index": 1, + "media": "cdrom" } ], "netifaces": [ @@ -22,13 +28,13 @@ "type": "nic", "vlan": 0, "model": "e1000", - "macaddr": "82:25:60:41:D5:97" + "macaddr": "82:25:60:41:07:98" }, { "type": "tap" } ], - "vnc": 5 + "vnc": 10 } } } diff --git a/zhypervisor/api/api.py b/zhypervisor/api/api.py index 3d6b8e3..c29444f 100644 --- a/zhypervisor/api/api.py +++ b/zhypervisor/api/api.py @@ -95,11 +95,8 @@ class ZApiV1(Mountable): """ assert fmt in ["qcow2", "raw"], "Disk format is invalid" assert name.endswith(".bin"), "Disk must be named .bin" + self.root.master.create_disk(datastore, name, fmt, size) - disk_path = self.root.master.datastores[datastore].get_filepath(name) - img_args = ["qemu-img", "create", "-f", fmt, disk_path, "{}M".format(int(size))] - logging.info("Creating disk with: %s", str(img_args)) - subprocess.check_call(img_args) return name diff --git a/zhypervisor/daemon.py b/zhypervisor/daemon.py index a0879f8..ca90ed4 100644 --- a/zhypervisor/daemon.py +++ b/zhypervisor/daemon.py @@ -4,6 +4,7 @@ import json import signal import logging import argparse +import subprocess from time import sleep from concurrent.futures import ThreadPoolExecutor from threading import Thread @@ -55,31 +56,6 @@ class ZHypervisorDaemon(object): machine_id = machine_info["machine_id"] self.add_machine(machine_id, machine_info["machine_type"], machine_info["spec"]) - def add_machine(self, machine_id, machine_type, machine_spec, write=False): - """ - Create or update a machine. - :param machine_id: alphanumeric id of machine to modify/create - :param machine_type: runnable type e.g. "q" - :param machine_spec: dictionary of machine options - see example/ubuntu.json - :param write: commit machinge changes to on-disk state - """ - # Find / create the machine - if machine_id in self.machines: - machine = self.machines[machine_id] - machine.options = machine_spec["options"] - machine.properties = machine_spec["properties"] - else: - machine = MachineSpec(self, machine_id, machine_type, machine_spec) - self.machines[machine_id] = machine - - # Update if necessary - if write: - self.state.write_machine(machine_id, machine_type, machine_spec) - - # Launch if machine is an autostarted machine - if machine.options.get("autostart", False) and machine.machine.get_status() == "stopped": - machine.start() - def signal_handler(self, signum, frame): """ Handle signals sent to the daemon. On any, exit. @@ -107,6 +83,50 @@ class ZHypervisorDaemon(object): # for machine_id in self.machines.keys(): # self.forceful_stop(machine_id) + # Below here are methods external forces may use to manipulate disks + + def create_disk(self, datastore, name, fmt, size=None): + """ + Create a disk. Disks represent arbitrary storage + @TODO support formats passed by runnable modules + :param datastore: datastore to store the disk in + :param name: name for the disk + :param size: size of the disk, in mb, if applicable + :param format: format of the disk + """ + disk_path = self.datastores[datastore].get_filepath(name) + assert not os.path.exists(disk_path), "Disk already exists!" + img_args = ["qemu-img", "create", "-f", fmt, disk_path, "{}M".format(int(size))] + logging.info("Creating disk with: %s", str(img_args)) + subprocess.check_call(img_args) + + # Below here are methods external forces may use to manipulate machines + + def add_machine(self, machine_id, machine_type, machine_spec, write=False): + """ + Create or update a machine. + :param machine_id: alphanumeric id of machine to modify/create + :param machine_type: runnable type e.g. "q" + :param machine_spec: dictionary of machine options - see example/ubuntu.json + :param write: commit machinge changes to on-disk state + """ + # Find / create the machine + if machine_id in self.machines: + machine = self.machines[machine_id] + machine.options = machine_spec["options"] + machine.properties = machine_spec["properties"] + else: + machine = MachineSpec(self, machine_id, machine_type, machine_spec) + self.machines[machine_id] = machine + + # Update if necessary + if write: + self.state.write_machine(machine_id, machine_type, machine_spec) + + # Launch if machine is an autostarted machine + if machine.options.get("autostart", False) and machine.machine.get_status() == "stopped": + machine.start() + def forceful_stop(self, machine_id, timeout=10): # make this timeout longer? """ Gracefully stop a machine by asking it nicely, waiting some time, then forcefully killing it. @@ -122,7 +142,7 @@ class ZHypervisorDaemon(object): def remove_machine(self, machine_id): """ - Remove a stopped machine from the system + Remove a stopped machine from the system. The machine should already be stopped. """ assert self.machines[machine_id].machine.get_status() == "stopped" self.state.remove_machine(machine_id) diff --git a/zhypervisor/machine.py b/zhypervisor/machine.py index 9851310..e1d9a24 100644 --- a/zhypervisor/machine.py +++ b/zhypervisor/machine.py @@ -30,6 +30,7 @@ class MachineSpec(object): """ Start this machine (pass-through) """ + self.machine.block_respawns = False self.machine.start_machine() def stop(self):