From ecfc1a527d20f4f8a5257c6c48871da22a7b6983 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Sat, 25 Jan 2014 18:16:16 -0500 Subject: [PATCH] virt-xml: Make --domain positional, allow stdin XML --- .../compare/virtxml-stdin-edit.xml | 20 +++++++ tests/cli-test-xml/virtxml-stdin-edit.xml | 18 ++++++ tests/clitest.py | 33 +++++++---- virt-xml | 56 +++++++++++++------ 4 files changed, 97 insertions(+), 30 deletions(-) create mode 100644 tests/cli-test-xml/compare/virtxml-stdin-edit.xml create mode 100644 tests/cli-test-xml/virtxml-stdin-edit.xml diff --git a/tests/cli-test-xml/compare/virtxml-stdin-edit.xml b/tests/cli-test-xml/compare/virtxml-stdin-edit.xml new file mode 100644 index 00000000..09ae743c --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-stdin-edit.xml @@ -0,0 +1,20 @@ + + test + 6695eb01-f6a4-8304-79aa-97f2502e193f + 8388608 + 2097152 + 2 + + hvm + + + + destroy + restart + destroy + + + + host-passthrough + + diff --git a/tests/cli-test-xml/virtxml-stdin-edit.xml b/tests/cli-test-xml/virtxml-stdin-edit.xml new file mode 100644 index 00000000..4a7b3e32 --- /dev/null +++ b/tests/cli-test-xml/virtxml-stdin-edit.xml @@ -0,0 +1,18 @@ + + test + 6695eb01-f6a4-8304-79aa-97f2502e193f + 8388608 + 2097152 + 2 + + hvm + + + + destroy + restart + destroy + + + + diff --git a/tests/clitest.py b/tests/clitest.py index 6f8969ad..5e72ebda 100644 --- a/tests/clitest.py +++ b/tests/clitest.py @@ -146,6 +146,7 @@ class Command(object): self.check_success = True self.compare_file = None self.support_check = None + self.input_file = None app, opts = self.cmdstr.split(" ", 1) self.app = app @@ -172,12 +173,15 @@ class Command(object): oldstdout = sys.stdout oldstderr = sys.stderr + oldstdin = sys.stdin oldargv = sys.argv try: out = StringIO.StringIO() sys.stdout = out sys.stderr = out sys.argv = self.argv + if self.input_file: + sys.stdin = file(self.input_file) try: if app.count("virt-install"): @@ -202,6 +206,7 @@ class Command(object): finally: sys.stdout = oldstdout sys.stderr = oldstderr + sys.stdin = oldstdin sys.argv = oldargv @@ -402,7 +407,8 @@ class App(object): self.categories[catname] = default_args return _CategoryProxy(self, catname) - def _add(self, catname, testargs, valid, compfile, support_check=None): + def _add(self, catname, testargs, valid, compfile, support_check=None, + input_file=None): args = self.categories[catname] + " " + testargs args = self._default_args(args, bool(compfile)) + " " + args cmdstr = "./%s %s" % (self.appname, args) @@ -412,6 +418,7 @@ class App(object): if compfile: cmd.compare_file = "%s/%s.xml" % (compare_xmldir, compfile) cmd.support_check = support_check + cmd.input_file = input_file self.cmds.append(cmd) def add_valid(self, cat, args, **kwargs): @@ -751,14 +758,16 @@ vixml = App("virt-xml") c = vixml.add_category("misc", "") c.add_valid("--help") # basic --help test c.add_valid("--soundhw=? --tpm=?") # basic introspection test -c.add_invalid("--domain test --edit --hostdev driver_name=vfio") # Guest has no hostdev to edit -c.add_invalid("--domain test --edit --cpu host-passthrough --boot hd,network") # Specified more than 1 option -c.add_invalid("--domain test --edit") # specified no edit option -c.add_invalid("--domain test --edit 2 --cpu host-passthrough") # specifing --edit number where it doesn't make sense -c.add_invalid("--domain test-many-devices --edit 5 --tpm /dev/tpm") # device edit out of range -c.add_compare("--domain test --print-xml --edit --vcpus 7", "virtxml-print-xml") # test --print-xml +c.add_invalid("test --edit --hostdev driver_name=vfio") # Guest has no hostdev to edit +c.add_invalid("test --edit --cpu host-passthrough --boot hd,network") # Specified more than 1 option +c.add_invalid("test --edit") # specified no edit option +c.add_invalid("test --edit 2 --cpu host-passthrough") # specifing --edit number where it doesn't make sense +c.add_invalid("test-many-devices --edit 5 --tpm /dev/tpm") # device edit out of range +c.add_compare("test --print-xml --edit --vcpus 7", "virtxml-print-xml") # test --print-xml +c.add_compare("--edit --cpu host-passthrough", "virtxml-stdin-edit", input_file=(xmldir + "/virtxml-stdin-edit.xml")) # stdin test -c = vixml.add_category("simple edit diff", "--domain test-many-devices --edit --print-diff --define") + +c = vixml.add_category("simple edit diff", "test-many-devices --edit --print-diff --define") c.add_compare("""--metadata name=foo-my-new-name,uuid=12345678-12F4-1234-1234-123456789AFA,description="hey this is my new very,very=new desc\\\'",title="This is my,funky=new title" """, "virtxml-edit-simple-metadata") @@ -789,7 +798,7 @@ c.add_compare("--video cirrus", "virtxml-edit-simple-video") c.add_compare("--soundhw pcspk", "virtxml-edit-simple-soundhw") c.add_compare("--host-device 0x0781:0x5151,driver_name=vfio", "virtxml-edit-simple-host-device") -c = vixml.add_category("edit selection", "--domain test-many-devices --print-diff --define") +c = vixml.add_category("edit selection", "test-many-devices --print-diff --define") c.add_invalid("--edit target=vvv --disk /dev/null") # no match found c.add_compare("--edit 3 --soundhw pcspk", "virtxml-edit-pos-num") c.add_compare("--edit -1 --video qxl", "virtxml-edit-neg-num") @@ -799,13 +808,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 = vixml.add_category("edit clear", "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") -c = vixml.add_category("add/rm devices", "--domain test-many-devices --print-diff --define") +c = vixml.add_category("add/rm devices", "test-many-devices --print-diff --define") c.add_invalid("--add-device --security foo") # --add-device without a device c.add_invalid("--remove-device --clock utc") # --remove-device without a dev c.add_compare("--add-device --host-device net_00_1c_25_10_b1_e4", "virtxml-add-host-device") @@ -979,7 +988,7 @@ p7.add("'/root' must be a file or a device") p7.add("use as the cloned disk", "%(MANAGEDNEW1)s") promptlist.append(p7) -p8 = PromptTest("virt-xml --connect %(TESTURI)s --confirm --domain test " +p8 = PromptTest("virt-xml --connect %(TESTURI)s --confirm test " "--edit --cpu host-passthrough") p8.add("Define 'test' with the changed XML", "yes", num_lines=12) promptlist.append(p8) diff --git a/virt-xml b/virt-xml index 520c552d..6a32b1ab 100755 --- a/virt-xml +++ b/virt-xml @@ -65,10 +65,14 @@ def get_diff(origxml, newxml): return ret -def get_domain_and_guest(conn, domstr): - if not domstr: - fail("--domain must be specified") +def _make_guest(conn, xml): + # We do this to minimize the diff, sanitizing XML quotes to what libxml + # generates + return virtinst.Guest(conn, + parsexml=virtinst.Guest(conn, parsexml=xml).get_xml_config()) + +def get_domain_and_guest(conn, domstr): try: int(domstr) isint = True @@ -91,17 +95,12 @@ def get_domain_and_guest(conn, domstr): except libvirt.libvirtError, e: fail(_("Could not find domain '%s': %s") % (domstr, e)) - def _make_guest(xml): - # We do this to minimize the diff, removing things like ' -> " - return virtinst.Guest(conn, - parsexml=virtinst.Guest(conn, parsexml=xml).get_xml_config()) - state = domain.info()[0] active_xmlobj = None - inactive_xmlobj = _make_guest(domain.XMLDesc(0)) + inactive_xmlobj = _make_guest(conn, domain.XMLDesc(0)) if state != libvirt.VIR_DOMAIN_SHUTOFF: active_xmlobj = inactive_xmlobj - inactive_xmlobj = _make_guest( + inactive_xmlobj = _make_guest(conn, domain.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)) return (domain, inactive_xmlobj, active_xmlobj) @@ -228,7 +227,8 @@ def parse_args(): cli.add_connect_option(parser) actg = parser.add_argument_group(_("Action Options")) - actg.add_argument("--domain", help=_("Domain name, id, or uuid")) + actg.add_argument("domain", nargs='?', + help=_("Domain name, id, or uuid")) actg.add_argument("--edit", nargs='?', default=-1, help=_("Edit VM XML. Examples:\n" "--edit --disk ... (edit first disk device)\n" @@ -281,22 +281,42 @@ def main(conn=None): if options.confirm or options.print_xml or options.print_diff: options.quiet = False - if not options.print_xml and not options.print_diff: - options.define = True - if options.confirm and not options.print_xml: - options.print_diff = True - cli.setupLogging("virt-xml", options.debug, options.quiet) parsermap = cli.build_parser_map(options) if cli.check_option_introspection(options, parsermap): return 0 + options.stdinxml = None + if (not options.domain and + not sys.stdin.closed and + not sys.stdin.isatty()): + if options.confirm: + fail(_("Can't use --confirm is stdin is closed.")) + options.stdinxml = sys.stdin.read() + elif not options.domain: + fail("domain must be specified") + + if not options.print_xml and not options.print_diff: + if options.stdinxml: + if not options.define: + options.print_xml = True + else: + options.define = True + if options.confirm and not options.print_xml: + options.print_diff = True + if conn is None: conn = cli.getConnection(options.connect) - domain, inactive_xmlobj, active_xmlobj = get_domain_and_guest( - conn, options.domain) + if options.domain: + domain, inactive_xmlobj, active_xmlobj = get_domain_and_guest( + conn, options.domain) + else: + domain = None + active_xmlobj = None + inactive_xmlobj = _make_guest(conn, options.stdinxml) + guest = inactive_xmlobj origxml = guest.get_xml_config() # XXX: do we ever need the domain?