virt-xml: Allow --option clearxml to clear all XML first

Needed for things like --cpu host-model,clearxml to easily clear all
the previous state.
This commit is contained in:
Cole Robinson 2014-01-25 15:44:14 -05:00
parent 9f5a842a3a
commit 26737eb7d5
6 changed files with 135 additions and 14 deletions

View File

@ -0,0 +1,22 @@
--- Original XML
+++ Altered XML
@@ -44,11 +44,6 @@
<feature policy="require" name="xtpr"/>
<feature policy="require" name="acpi"/>
</cpu>
- <clock offset="utc">
- <timer name="rtc" tickpolicy="catchup"/>
- <timer name="pit" tickpolicy="delay"/>
- <timer name="hpet" present="no"/>
- </clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
@@ -303,4 +298,5 @@
</backend>
</rng>
</devices>
+ <clock offset="utc"/>
</domain>
Domain 'test-many-devices' defined successfully.

View File

@ -0,0 +1,36 @@
--- Original XML
+++ Altered XML
@@ -27,23 +27,6 @@
<spinlocks state="on" retries="12287"/>
</hyperv>
</features>
- <cpu mode="custom" match="exact">
- <model fallback="allow">core2duo</model>
- <vendor>Intel</vendor>
- <feature policy="require" name="pbe"/>
- <feature policy="require" name="tm2"/>
- <feature policy="require" name="est"/>
- <feature policy="require" name="ss"/>
- <feature policy="require" name="ht"/>
- <feature policy="require" name="ds"/>
- <feature policy="require" name="lahf_lm"/>
- <feature policy="require" name="tm"/>
- <feature policy="require" name="cx16"/>
- <feature policy="require" name="vmx"/>
- <feature policy="require" name="ds_cpl"/>
- <feature policy="require" name="xtpr"/>
- <feature policy="require" name="acpi"/>
- </cpu>
<clock offset="utc">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" tickpolicy="delay"/>
@@ -303,4 +286,7 @@
</backend>
</rng>
</devices>
+ <cpu mode="custom" match="exact">
+ <model>host-passthrough</model>
+ </cpu>
</domain>
Domain 'test-many-devices' defined successfully.

View File

@ -0,0 +1,17 @@
--- Original XML
+++ Altered XML
@@ -54,10 +54,9 @@
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
- <disk type="block" device="floppy">
- <source dev="/dev/null"/>
+ <disk device="floppy">
+ <source file="/foo/bar"/>
<target dev="fda" bus="fdc"/>
- <address type="drive" controller="0" bus="0" target="0" unit="0"/>
</disk>
<disk type="dir" device="floppy">
<source dir="/tmp"/>
Domain 'test-many-devices' defined successfully.

View File

@ -799,6 +799,13 @@ c.add_compare("--edit target=hda --disk /dev/null", "virtxml-edit-select-disk-ta
c.add_compare("--edit /tmp/foobar2 --disk shareable=off,readonly=on", "virtxml-edit-select-disk-path")
c.add_compare("--edit mac=00:11:7f:33:44:55 --network target=nic55", "virtxml-edit-select-network-mac")
c = vixml.add_category("edit clear", "--domain test-many-devices --print-diff --define")
c.add_invalid("--edit --memory 200,clearxml") # clear isn't wired up for memory
c.add_compare("--edit --cpu host-passthrough,clearxml", "virtxml-edit-clear-cpu")
c.add_compare("--edit --clock offset=utc,clearxml", "virtxml-edit-clear-clock")
c.add_compare("--edit --disk /foo/bar,target=fda,bus=fdc,device=floppy,clearxml", "virtxml-edit-clear-disk")
vimag = App("virt-image")
c = vimag.add_category("graphics", "--name test-image --boot 0 %(IMAGE_XML)s")

View File

@ -967,8 +967,8 @@ def add_disk_option(stog):
class _VirtCLIArgument(object):
def __init__(self, attrname, cliname,
setter_cb=None, ignore_default=False,
can_comma=False, is_list=False, is_onoff=False,
aliases=None):
can_comma=False, aliases=None,
is_list=False, is_onoff=False, is_bool=False):
"""
A single subargument passed to compound command lines like --disk,
--network, etc.
@ -986,22 +986,25 @@ class _VirtCLIArgument(object):
option string until it finds another known argument name:
everything prior to that argument name is considered part of
the value of this option, '=' included. Should be used sparingly.
@aliases: List of cli aliases. Useful if we want to change a property
name on the cli but maintain back compat.
@is_list: This value should be stored as a list, so multiple instances
are appended.
@is_onoff: The value expected on the cli is on/off or yes/no, convert
it to true/false.
@aliases: List of cli aliases. Useful if we want to change a property
name on the cli but maintain back compat.
@is_bool: This value shouldn't have an = component, so if it's present
on the command line, assume value is True
"""
self.attrname = attrname
self.cliname = cliname
self.setter_cb = setter_cb
self.can_comma = can_comma
self.is_list = is_list
self.is_onoff = is_onoff
self.ignore_default = ignore_default
self.aliases = util.listify(aliases)
self.is_list = is_list
self.is_onoff = is_onoff
self.is_bool = is_bool
def parse(self, opts, inst, support_cb=None, lookup=False):
@ -1009,7 +1012,7 @@ class _VirtCLIArgument(object):
for cliname in self.aliases + [self.cliname]:
# We iterate over all values unconditionally, so they are
# removed from opts
foundval = opts.get_opt_param(cliname)
foundval = opts.get_opt_param(cliname, is_bool=self.is_bool)
if foundval is not None:
val = foundval
if val is None:
@ -1044,7 +1047,7 @@ class _VirtCLIArgument(object):
class VirtOptionString(object):
def __init__(self, optstr, virtargs, remove_first=None):
def __init__(self, optstr, virtargs, remove_first):
"""
Helper class for parsing opt strings of the form
opt1=val1,opt2=val2,...
@ -1066,7 +1069,9 @@ class VirtOptionString(object):
self.opts, self.orderedopts = self._parse_optstr(
virtargmap, remove_first)
def get_opt_param(self, key):
def get_opt_param(self, key, is_bool=False):
if is_bool and key in self.opts and self.opts[key] is None:
self.opts[key] = True
return self.opts.pop(key, None)
def check_leftover_opts(self):
@ -1103,6 +1108,8 @@ class VirtOptionString(object):
if opt.count("="):
cliname, val = opt.split("=", 1)
remove_first = []
elif cliname in virtargmap and virtargmap[cliname].is_bool:
remove_first = []
elif remove_first:
val = cliname
cliname = remove_first.pop(0)
@ -1174,6 +1181,10 @@ class VirtCLIParser(object):
@support_cb: An extra support check function for further validation.
Called before the virtinst object is altered. Take arguments
(inst, attrname, cliname)
@clear_attr: If the user requests to clear the XML (--disk clearxml),
this is the property name we grab from inst to actually clear
(so 'security' to get guest.security). If it's True, then
clear inst (in the case of devices)
"""
self.cli_arg_name = cli_arg_name
# This is the name of the variable that argparse will set in
@ -1184,12 +1195,32 @@ class VirtCLIParser(object):
self.remove_first = None
self.check_none = False
self.support_cb = None
self.clear_attr = None
self._params = []
self._inparse = False
self.__init_global_params()
self._init_params()
def __init_global_params(self):
def set_clearxml_cb(opts, inst, cliname, val):
ignore = opts = cliname
if not self.clear_attr and not self.devclass:
raise RuntimeError("Don't know how to clearxml --%s" %
self.cli_arg_name)
clearobj = inst
if self.clear_attr:
clearobj = getattr(inst, self.clear_attr)
if val is not True:
return
clearobj.clear()
self.set_param(None, "clearxml",
setter_cb=set_clearxml_cb, is_bool=True)
def check_introspection(self, option):
for optstr in util.listify(option):
if optstr == "?":
@ -1257,8 +1288,7 @@ class VirtCLIParser(object):
ret = []
for inst in devlist:
opts = VirtOptionString(optstr, self._params,
remove_first=self.remove_first)
opts = VirtOptionString(optstr, self._params, self.remove_first)
valid = True
for param in self._params:
if param.parse(opts, inst,
@ -1282,8 +1312,7 @@ class VirtCLIParser(object):
try:
self.guest = guest
self._inparse = True
opts = VirtOptionString(optstr, self._params,
remove_first=self.remove_first)
opts = VirtOptionString(optstr, self._params, self.remove_first)
return self._parse(opts, inst)
finally:
self.guest = None
@ -1317,6 +1346,7 @@ class ParserMetadata(VirtCLIParser):
class ParserNumatune(VirtCLIParser):
def _init_params(self):
self.clear_attr = "numatune"
self.remove_first = "nodeset"
self.set_param("numatune.memory_nodeset", "nodeset", can_comma=True)
@ -1393,6 +1423,7 @@ class ParserVCPU(VirtCLIParser):
class ParserCPU(VirtCLIParser):
def _init_params(self):
self.clear_attr = "cpu"
self.remove_first = "model"
def set_model_cb(opts, inst, cliname, val):
@ -1458,6 +1489,8 @@ class ParserCPU(VirtCLIParser):
class ParserBoot(VirtCLIParser):
def _init_params(self):
self.clear_attr = "os"
self.set_param("os.useserial", "useserial", is_onoff=True)
self.set_param("os.enable_bootmenu", "menu", is_onoff=True)
self.set_param("os.kernel", "kernel")
@ -1501,6 +1534,8 @@ class ParserBoot(VirtCLIParser):
class ParserSecurity(VirtCLIParser):
def _init_params(self):
self.clear_attr = "seclabel"
self.set_param("seclabel.type", "type")
self.set_param("seclabel.label", "label", can_comma=True)
self.set_param("seclabel.relabel", "relabel",
@ -1513,6 +1548,8 @@ class ParserSecurity(VirtCLIParser):
class ParserFeatures(VirtCLIParser):
def _init_params(self):
self.clear_attr = "features"
self.set_param("features.acpi", "acpi", is_onoff=True)
self.set_param("features.apic", "apic", is_onoff=True)
self.set_param("features.pae", "pae", is_onoff=True)
@ -1540,6 +1577,8 @@ class ParserFeatures(VirtCLIParser):
class ParserClock(VirtCLIParser):
def _init_params(self):
self.clear_attr = "clock"
self.set_param("clock.offset", "offset")
def set_timer(opts, inst, cliname, val):

View File

@ -80,7 +80,7 @@ class VirtualConnection(object):
ret = uri.split(",", 1)
self._open_uri = ret[0]
self._test_opts = VirtOptionString(
len(ret) > 1 and ret[1] or "", []).opts
len(ret) > 1 and ret[1] or "", [], None).opts
self._early_virtinst_test_uri()
self._uri = self._virtinst_uri_make_fake()
else: