mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 17:28:08 +00:00
Qemu integration stage 2, support for ASA and IDS.
This commit is contained in:
parent
d1715baae1
commit
aca9e0de56
@ -67,26 +67,6 @@ class Qemu(IModule):
|
|||||||
|
|
||||||
def __init__(self, name, *args, **kwargs):
|
def __init__(self, name, *args, **kwargs):
|
||||||
|
|
||||||
# get the qemu-img location
|
|
||||||
config = Config.instance()
|
|
||||||
qemu_config = config.get_section_config(name.upper())
|
|
||||||
self._qemu_img_path = qemu_config.get("qemu_img_path")
|
|
||||||
if not self._qemu_img_path or not os.path.isfile(self._qemu_img_path):
|
|
||||||
paths = [os.getcwd()] + os.environ["PATH"].split(":")
|
|
||||||
# look for qemu-img in the current working directory and $PATH
|
|
||||||
for path in paths:
|
|
||||||
try:
|
|
||||||
if "qemu-img" in os.listdir(path) and os.access(os.path.join(path, "qemu-img"), os.X_OK):
|
|
||||||
self._qemu_img_path = os.path.join(path, "qemu-img")
|
|
||||||
break
|
|
||||||
except OSError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not self._qemu_img_path:
|
|
||||||
log.warning("qemu-img couldn't be found!")
|
|
||||||
elif not os.access(self._qemu_img_path, os.X_OK):
|
|
||||||
log.warning("qemu-img is not executable")
|
|
||||||
|
|
||||||
# a new process start when calling IModule
|
# a new process start when calling IModule
|
||||||
IModule.__init__(self, name, *args, **kwargs)
|
IModule.__init__(self, name, *args, **kwargs)
|
||||||
self._qemu_instances = {}
|
self._qemu_instances = {}
|
||||||
@ -173,13 +153,6 @@ class Qemu(IModule):
|
|||||||
self.send_param_error()
|
self.send_param_error()
|
||||||
return
|
return
|
||||||
|
|
||||||
if "qemu_img_path" in request and request["qemu_img_path"]:
|
|
||||||
self._qemu_img_path = request["qemu_img_path"]
|
|
||||||
log.info("QEMU image utility path set to {}".format(self._qemu_img_path))
|
|
||||||
for qemu_id in self._qemu_instances:
|
|
||||||
qemu_instance = self._qemu_instances[qemu_id]
|
|
||||||
qemu_instance.qemu_img_path = self._qemu_img_path
|
|
||||||
|
|
||||||
if "working_dir" in request:
|
if "working_dir" in request:
|
||||||
new_working_dir = request["working_dir"]
|
new_working_dir = request["working_dir"]
|
||||||
log.info("this server is local with working directory path to {}".format(new_working_dir))
|
log.info("this server is local with working directory path to {}".format(new_working_dir))
|
||||||
@ -245,7 +218,6 @@ class Qemu(IModule):
|
|||||||
try:
|
try:
|
||||||
qemu_instance = QemuVM(name,
|
qemu_instance = QemuVM(name,
|
||||||
qemu_path,
|
qemu_path,
|
||||||
self._qemu_img_path,
|
|
||||||
self._working_dir,
|
self._working_dir,
|
||||||
self._host,
|
self._host,
|
||||||
qemu_id,
|
qemu_id,
|
||||||
|
@ -23,6 +23,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import shlex
|
||||||
|
|
||||||
from .qemu_error import QemuError
|
from .qemu_error import QemuError
|
||||||
from .adapters.ethernet_adapter import EthernetAdapter
|
from .adapters.ethernet_adapter import EthernetAdapter
|
||||||
@ -39,7 +40,6 @@ class QemuVM(object):
|
|||||||
|
|
||||||
:param name: name of this QEMU VM
|
:param name: name of this QEMU VM
|
||||||
:param qemu_path: path to the QEMU binary
|
:param qemu_path: path to the QEMU binary
|
||||||
:param qemu_img_path: path to the QEMU IMG binary
|
|
||||||
:param working_dir: path to a working directory
|
:param working_dir: path to a working directory
|
||||||
:param host: host/address to bind for console and UDP connections
|
:param host: host/address to bind for console and UDP connections
|
||||||
:param qemu_id: QEMU VM instance ID
|
:param qemu_id: QEMU VM instance ID
|
||||||
@ -54,7 +54,6 @@ class QemuVM(object):
|
|||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
name,
|
||||||
qemu_path,
|
qemu_path,
|
||||||
qemu_img_path,
|
|
||||||
working_dir,
|
working_dir,
|
||||||
host="127.0.0.1",
|
host="127.0.0.1",
|
||||||
qemu_id=None,
|
qemu_id=None,
|
||||||
@ -85,18 +84,21 @@ class QemuVM(object):
|
|||||||
self._started = False
|
self._started = False
|
||||||
self._process = None
|
self._process = None
|
||||||
self._stdout_file = ""
|
self._stdout_file = ""
|
||||||
self._qemu_img_path = qemu_img_path
|
|
||||||
self._console_start_port_range = console_start_port_range
|
self._console_start_port_range = console_start_port_range
|
||||||
self._console_end_port_range = console_end_port_range
|
self._console_end_port_range = console_end_port_range
|
||||||
|
|
||||||
# QEMU settings
|
# QEMU settings
|
||||||
self._qemu_path = qemu_path
|
self._qemu_path = qemu_path
|
||||||
self._disk_image = ""
|
self._hda_disk_image = ""
|
||||||
|
self._hdb_disk_image = ""
|
||||||
self._options = ""
|
self._options = ""
|
||||||
self._ram = 256
|
self._ram = 256
|
||||||
self._console = console
|
self._console = console
|
||||||
self._ethernet_adapters = []
|
self._ethernet_adapters = []
|
||||||
self._adapter_type = "e1000"
|
self._adapter_type = "e1000"
|
||||||
|
self._initrd = ""
|
||||||
|
self._kernel_image = ""
|
||||||
|
self._kernel_command_line = ""
|
||||||
|
|
||||||
working_dir_path = os.path.join(working_dir, "qemu", "vm-{}".format(self._id))
|
working_dir_path = os.path.join(working_dir, "qemu", "vm-{}".format(self._id))
|
||||||
|
|
||||||
@ -134,11 +136,15 @@ class QemuVM(object):
|
|||||||
qemu_defaults = {"name": self._name,
|
qemu_defaults = {"name": self._name,
|
||||||
"qemu_path": self._qemu_path,
|
"qemu_path": self._qemu_path,
|
||||||
"ram": self._ram,
|
"ram": self._ram,
|
||||||
"disk_image": self._disk_image,
|
"hda_disk_image": self._hda_disk_image,
|
||||||
|
"hdb_disk_image": self._hdb_disk_image,
|
||||||
"options": self._options,
|
"options": self._options,
|
||||||
"adapters": self.adapters,
|
"adapters": self.adapters,
|
||||||
"adapter_type": self._adapter_type,
|
"adapter_type": self._adapter_type,
|
||||||
"console": self._console}
|
"console": self._console,
|
||||||
|
"initrd": self._initrd,
|
||||||
|
"kernel_image": self._kernel_image,
|
||||||
|
"kernel_command_line": self._kernel_command_line}
|
||||||
|
|
||||||
return qemu_defaults
|
return qemu_defaults
|
||||||
|
|
||||||
@ -306,50 +312,51 @@ class QemuVM(object):
|
|||||||
self._qemu_path = qemu_path
|
self._qemu_path = qemu_path
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def qemu_img_path(self):
|
def hda_disk_image(self):
|
||||||
"""
|
"""
|
||||||
Returns the QEMU IMG binary path for this QEMU VM.
|
Returns the hda disk image path for this QEMU VM.
|
||||||
|
|
||||||
:returns: QEMU IMG path
|
:returns: QEMU hda disk image path
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._qemu_img_path
|
return self._hda_disk_image
|
||||||
|
|
||||||
@qemu_img_path.setter
|
@hda_disk_image.setter
|
||||||
def qemu_img_path(self, qemu_img_path):
|
def hda_disk_image(self, hda_disk_image):
|
||||||
"""
|
"""
|
||||||
Sets the QEMU IMG binary path this QEMU VM.
|
Sets the hda disk image for this QEMU VM.
|
||||||
|
|
||||||
:param qemu_img_path: QEMU IMG path
|
:param hda_disk_image: QEMU hda disk image path
|
||||||
"""
|
"""
|
||||||
|
|
||||||
log.info("QEMU VM {name} [id={id}] has set the QEMU IMG path to {qemu_img_path}".format(name=self._name,
|
log.info("QEMU VM {name} [id={id}] has set the QEMU hda disk image path to {disk_image}".format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
qemu_img_path=qemu_img_path))
|
disk_image=hda_disk_image))
|
||||||
self._qemu_img_path = qemu_img_path
|
self._hda_disk_image = hda_disk_image
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def disk_image(self):
|
def hdb_disk_image(self):
|
||||||
"""
|
"""
|
||||||
Returns the disk image path for this QEMU VM.
|
Returns the hdb disk image path for this QEMU VM.
|
||||||
|
|
||||||
:returns: QEMU disk image path
|
:returns: QEMU hdb disk image path
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._disk_image
|
return self._hdb_disk_image
|
||||||
|
|
||||||
@disk_image.setter
|
@hdb_disk_image.setter
|
||||||
def disk_image(self, disk_image):
|
def hdb_disk_image(self, hdb_disk_image):
|
||||||
"""
|
"""
|
||||||
Sets the disk image for this QEMU VM.
|
Sets the hdb disk image for this QEMU VM.
|
||||||
|
|
||||||
:param disk_image: QEMU disk image path
|
:param hdb_disk_image: QEMU hdb disk image path
|
||||||
"""
|
"""
|
||||||
|
|
||||||
log.info("QEMU VM {name} [id={id}] has set the QEMU disk image path to {disk_image}".format(name=self._name,
|
log.info("QEMU VM {name} [id={id}] has set the QEMU hdb disk image path to {disk_image}".format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
disk_image=disk_image))
|
disk_image=hdb_disk_image))
|
||||||
self._disk_image = disk_image
|
self._hdb_disk_image = hdb_disk_image
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def adapters(self):
|
def adapters(self):
|
||||||
@ -401,6 +408,121 @@ class QemuVM(object):
|
|||||||
id=self._id,
|
id=self._id,
|
||||||
adapter_type=adapter_type))
|
adapter_type=adapter_type))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ram(self):
|
||||||
|
"""
|
||||||
|
Returns the RAM amount for this QEMU VM.
|
||||||
|
|
||||||
|
:returns: RAM amount in MB
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._ram
|
||||||
|
|
||||||
|
@ram.setter
|
||||||
|
def ram(self, ram):
|
||||||
|
"""
|
||||||
|
Sets the amount of RAM for this QEMU VM.
|
||||||
|
|
||||||
|
:param ram: RAM amount in MB
|
||||||
|
"""
|
||||||
|
|
||||||
|
log.info("QEMU VM {name} [id={id}] has set the RAM to {ram}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
ram=ram))
|
||||||
|
self._ram = ram
|
||||||
|
|
||||||
|
@property
|
||||||
|
def options(self):
|
||||||
|
"""
|
||||||
|
Returns the options for this QEMU VM.
|
||||||
|
|
||||||
|
:returns: QEMU options
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._options
|
||||||
|
|
||||||
|
@options.setter
|
||||||
|
def options(self, options):
|
||||||
|
"""
|
||||||
|
Sets the options for this QEMU VM.
|
||||||
|
|
||||||
|
:param options: QEMU options
|
||||||
|
"""
|
||||||
|
|
||||||
|
log.info("QEMU VM {name} [id={id}] has set the QEMU options to {options}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
options=options))
|
||||||
|
self._options = options
|
||||||
|
|
||||||
|
@property
|
||||||
|
def initrd(self):
|
||||||
|
"""
|
||||||
|
Returns the initrd path for this QEMU VM.
|
||||||
|
|
||||||
|
:returns: QEMU initrd path
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._initrd
|
||||||
|
|
||||||
|
@initrd.setter
|
||||||
|
def initrd(self, initrd):
|
||||||
|
"""
|
||||||
|
Sets the initrd path for this QEMU VM.
|
||||||
|
|
||||||
|
:param initrd: QEMU initrd path
|
||||||
|
"""
|
||||||
|
|
||||||
|
log.info("QEMU VM {name} [id={id}] has set the QEMU initrd path to {initrd}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
initrd=initrd))
|
||||||
|
self._initrd = initrd
|
||||||
|
|
||||||
|
@property
|
||||||
|
def kernel_image(self):
|
||||||
|
"""
|
||||||
|
Returns the kernel image path for this QEMU VM.
|
||||||
|
|
||||||
|
:returns: QEMU kernel image path
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._kernel_image
|
||||||
|
|
||||||
|
@kernel_image.setter
|
||||||
|
def kernel_image(self, kernel_image):
|
||||||
|
"""
|
||||||
|
Sets the kernel image path for this QEMU VM.
|
||||||
|
|
||||||
|
:param kernel_image: QEMU kernel image path
|
||||||
|
"""
|
||||||
|
|
||||||
|
log.info("QEMU VM {name} [id={id}] has set the QEMU kernel image path to {kernel_image}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
kernel_image=kernel_image))
|
||||||
|
self._kernel_image = kernel_image
|
||||||
|
|
||||||
|
@property
|
||||||
|
def kernel_command_line(self):
|
||||||
|
"""
|
||||||
|
Returns the kernel command line for this QEMU VM.
|
||||||
|
|
||||||
|
:returns: QEMU kernel command line
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._kernel_command_line
|
||||||
|
|
||||||
|
@kernel_command_line.setter
|
||||||
|
def kernel_command_line(self, kernel_command_line):
|
||||||
|
"""
|
||||||
|
Sets the kernel command line for this QEMU VM.
|
||||||
|
|
||||||
|
:param kernel_command_line: QEMU kernel command line
|
||||||
|
"""
|
||||||
|
|
||||||
|
log.info("QEMU VM {name} [id={id}] has set the QEMU kernel command line to {kernel_command_line}".format(name=self._name,
|
||||||
|
id=self._id,
|
||||||
|
kernel_command_line=kernel_command_line))
|
||||||
|
self._kernel_command_line = kernel_command_line
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""
|
"""
|
||||||
Starts this QEMU VM.
|
Starts this QEMU VM.
|
||||||
@ -411,9 +533,7 @@ class QemuVM(object):
|
|||||||
if not os.path.isfile(self._qemu_path) or not os.path.exists(self._qemu_path):
|
if not os.path.isfile(self._qemu_path) or not os.path.exists(self._qemu_path):
|
||||||
raise QemuError("QEMU binary '{}' is not accessible".format(self._qemu_path))
|
raise QemuError("QEMU binary '{}' is not accessible".format(self._qemu_path))
|
||||||
|
|
||||||
#TODO: check binary image is valid?
|
|
||||||
self._command = self._build_command()
|
self._command = self._build_command()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
log.info("starting QEMU: {}".format(self._command))
|
log.info("starting QEMU: {}".format(self._command))
|
||||||
self._stdout_file = os.path.join(self._working_dir, "qemu.log")
|
self._stdout_file = os.path.join(self._working_dir, "qemu.log")
|
||||||
@ -567,36 +687,81 @@ class QemuVM(object):
|
|||||||
|
|
||||||
def _disk_options(self):
|
def _disk_options(self):
|
||||||
|
|
||||||
hda_disk = os.path.join(self._working_dir, "hda.disk")
|
options = []
|
||||||
if not os.path.exists(hda_disk):
|
qemu_img_path = ""
|
||||||
try:
|
qemu_path_dir = os.path.dirname(self._qemu_path)
|
||||||
retcode = subprocess.call([self._qemu_img_path, "create", "-o",
|
try:
|
||||||
"backing_file={}".format(self._disk_image),
|
for f in os.listdir(qemu_path_dir):
|
||||||
"-f", "qcow2", hda_disk])
|
if f.startswith("qemu-img"):
|
||||||
log.info("{} returned with {}".format(self._qemu_img_path, retcode))
|
qemu_img_path = os.path.join(qemu_path_dir, f)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise QemuError("Could not create disk image {}".format(e))
|
raise QemuError("Error while looking for qemu-img in {}: {}".format(qemu_path_dir, e))
|
||||||
|
|
||||||
return ["-hda", hda_disk]
|
if not qemu_img_path:
|
||||||
|
raise QemuError("Could not find qemu-img in {}".format(qemu_path_dir))
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._hda_disk_image:
|
||||||
|
hda_disk = os.path.join(self._working_dir, "hda_disk.qcow2")
|
||||||
|
if not os.path.exists(hda_disk):
|
||||||
|
retcode = subprocess.call([qemu_img_path, "create", "-o",
|
||||||
|
"backing_file={}".format(self._hda_disk_image),
|
||||||
|
"-f", "qcow2", hda_disk])
|
||||||
|
log.info("{} returned with {}".format(qemu_img_path, retcode))
|
||||||
|
else:
|
||||||
|
# create a "FLASH" with 256MB if no disk image has been specified
|
||||||
|
hda_disk = os.path.join(self._working_dir, "flash.qcow2")
|
||||||
|
if not os.path.exists(hda_disk):
|
||||||
|
retcode = subprocess.call([qemu_img_path, "create", "-f", "qcow2", hda_disk, "256M"])
|
||||||
|
log.info("{} returned with {}".format(qemu_img_path, retcode))
|
||||||
|
|
||||||
|
except OSError as e:
|
||||||
|
raise QemuError("Could not create disk image {}".format(e))
|
||||||
|
|
||||||
|
options.extend(["-hda", hda_disk])
|
||||||
|
if self._hdb_disk_image:
|
||||||
|
hdb_disk = os.path.join(self._working_dir, "hdb_disk.qcow2")
|
||||||
|
if not os.path.exists(hdb_disk):
|
||||||
|
try:
|
||||||
|
retcode = subprocess.call([qemu_img_path, "create", "-o",
|
||||||
|
"backing_file={}".format(self._hdb_disk_image),
|
||||||
|
"-f", "qcow2", hdb_disk])
|
||||||
|
log.info("{} returned with {}".format(qemu_img_path, retcode))
|
||||||
|
except OSError as e:
|
||||||
|
raise QemuError("Could not create disk image {}".format(e))
|
||||||
|
options.extend(["-hdb", hdb_disk])
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
|
def _linux_boot_options(self):
|
||||||
|
|
||||||
|
options = []
|
||||||
|
if self._initrd:
|
||||||
|
options.extend(["-initrd", self._initrd])
|
||||||
|
if self._kernel_image:
|
||||||
|
options.extend(["-kernel", self._kernel_image])
|
||||||
|
if self._kernel_command_line:
|
||||||
|
options.extend(["-append", self._kernel_command_line])
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
def _network_options(self):
|
def _network_options(self):
|
||||||
|
|
||||||
network_options = []
|
network_options = []
|
||||||
adapter_id = 0
|
adapter_id = 0
|
||||||
for adapter in self._ethernet_adapters:
|
for adapter in self._ethernet_adapters:
|
||||||
|
#TODO: let users specify a base mac address
|
||||||
|
mac = "00:00:ab:%02x:%02x:%02d" % (random.randint(0x00, 0xff), random.randint(0x00, 0xff), adapter_id)
|
||||||
|
network_options.extend(["-device", "{},mac={},netdev=gns3-{}".format(self._adapter_type, mac, adapter_id)])
|
||||||
nio = adapter.get_nio(0)
|
nio = adapter.get_nio(0)
|
||||||
if nio:
|
if nio and isinstance(nio, NIO_UDP):
|
||||||
#TODO: let users specific the base mac address
|
network_options.extend(["-netdev", "socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_id,
|
||||||
mac = "00:00:ab:%02x:%02x:%02d" % (random.randint(0x00, 0xff), random.randint(0x00, 0xff), adapter_id)
|
nio.rhost,
|
||||||
network_options.extend(["-device", "{},mac={},netdev=gns3-{}".format(self._adapter_type, mac, adapter_id)])
|
nio.rport,
|
||||||
if isinstance(nio, NIO_UDP):
|
self._host,
|
||||||
network_options.extend(["-netdev", "socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_id,
|
nio.lport)])
|
||||||
nio.rhost,
|
|
||||||
nio.rport,
|
|
||||||
self._host,
|
|
||||||
nio.lport)])
|
|
||||||
else:
|
else:
|
||||||
network_options.extend(["-device", "{}".format(self._adapter_type)])
|
network_options.extend(["-netdev", "user,id=gns3-{}".format(adapter_id)])
|
||||||
adapter_id += 1
|
adapter_id += 1
|
||||||
|
|
||||||
return network_options
|
return network_options
|
||||||
@ -611,6 +776,10 @@ class QemuVM(object):
|
|||||||
command.extend(["-name", self._name])
|
command.extend(["-name", self._name])
|
||||||
command.extend(["-m", str(self._ram)])
|
command.extend(["-m", str(self._ram)])
|
||||||
command.extend(self._disk_options())
|
command.extend(self._disk_options())
|
||||||
|
command.extend(self._linux_boot_options())
|
||||||
command.extend(self._serial_options())
|
command.extend(self._serial_options())
|
||||||
|
additional_options = self._options.strip()
|
||||||
|
if additional_options:
|
||||||
|
command.extend(shlex.split(additional_options))
|
||||||
command.extend(self._network_options())
|
command.extend(self._network_options())
|
||||||
return command
|
return command
|
||||||
|
@ -79,8 +79,13 @@ QEMU_UPDATE_SCHEMA = {
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
},
|
},
|
||||||
"disk_image": {
|
"hda_disk_image": {
|
||||||
"description": "QEMU disk image path",
|
"description": "QEMU hda disk image path",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
"hdb_disk_image": {
|
||||||
|
"description": "QEMU hdb disk image path",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
},
|
},
|
||||||
@ -105,6 +110,21 @@ QEMU_UPDATE_SCHEMA = {
|
|||||||
"maximum": 65535,
|
"maximum": 65535,
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"initrd": {
|
||||||
|
"description": "QEMU initrd path",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
"kernel_image": {
|
||||||
|
"description": "QEMU kernel image path",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
|
"kernel_command_line": {
|
||||||
|
"description": "QEMU kernel command line",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"description": "additional QEMU options",
|
"description": "additional QEMU options",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -23,5 +23,5 @@
|
|||||||
# or negative for a release candidate or beta (after the base version
|
# or negative for a release candidate or beta (after the base version
|
||||||
# number has been incremented)
|
# number has been incremented)
|
||||||
|
|
||||||
__version__ = "1.0beta3.dev1"
|
__version__ = "1.0beta3.dev2"
|
||||||
__version_info__ = (1, 0, 0, -99)
|
__version_info__ = (1, 0, 0, -99)
|
||||||
|
Loading…
Reference in New Issue
Block a user