Justin, how does the below affect plans to modify/fix virsh in libvirt? On Wed, Apr 27, 2011 at 09:47:55AM -0400, Cole Robinson wrote: > Hi all, > > Attached is a patch to virtinst.git that provides a new tool named > virt-xml. virt-xml provides a scriptable command line interface for > editing libvirt guest XML. > > A couple examples: > > Change boot order and boot menu for 'myguest': > $ ./virt-xml --guest myguest --boot network,hd,cdrom,menu=on > Requested changes: > --- Original XML > +++ New XML > @@ -10,6 +10,8 @@ > <os> > <type arch="i686">hvm</type> > <loader>/usr/lib/xen/boot/hvmloader</loader> > + <boot dev="network"/> > + <bootmenu enable="yes"/> > <boot dev="hd"/> > + <boot dev="cdrom"/> > </os> > <features> > <acpi/> > > Change disk #7 to use cache=none for 'myguest': > $ ./virt-xml --guest myguest --device 7 --disk cache=none > Requested changes: > --- Original XML > +++ New XML > @@ -74,6 +74,7 @@ > <disk type="file" device="disk"> > <source file="/tmp/foobar3"/> > <target dev="sdd" bus="usb"/> > + <driver cache="none"/> > </disk> > <disk type="file" device="disk"> > <driver name="tap" type="qcow" cache="writethrough"/> > > > Change watchdog action for 'myguest': > $ ./virt-xml --guest myguest --device 1 --watchdog action=pause > Requested changes: > --- Original XML > +++ New XML > @@ -220,7 +220,7 @@ > <address domain="0x0003" bus="0x00" slot="0x19" function="0x0"/> > </source> > </hostdev> > - <watchdog model="ib700" action="poweroff"/> > + <watchdog model="ib700" action="pause"/> > <memballoon model="xen"/> > </devices> > </domain> > > > --boot, --disk, and --watchdog come straight from virt-install, see man > virt-install for detailed docs of the option format. Those options shown > are the only things wired up right now, but it's a straightforward task > to wire up most of the relevant remaining virt-install opts. Also the > tool doesn't actually apply the changes yet, but that is also a trivial > addition. I think the interesting bit here is nailing down the scope of > the tool and deciding on good CLI syntax. > > Not sure if we should do hotplug/hotunplug as a subcommand or just > another option like: > > virt-xml ... --hotplug --disk /tmp/foo.img > > Also not really sure how to hotunplug using the --device syntax of the above > examples: > > virt-xml ... --hotunplug --device 1 --disk <what goes here?> > > We could make --device just an option to whatever device string the user > gives > > virt-xml ... --hotunplug --disk id=1 > > We can easily allow different XML input methods like: > > virt-xml --guestxml file.xml ... > > or even batch processing > > virt-xml --guest * ... > > Maybe even have allow more intelligence about what guests we edit, say > we want to set cache=none for all disk devices, not CDROM or floppy > (this would take a bit of work to sort out). > > virt-xml --guest * --disk match,device=disk --disk cache=none > > Then there is also the question of extending the tool to also edit other XML > like storage, network, interface, etc. > > Any recommendations appreciated: option syntax, future capabilities, or even a > better name for the tool :) > > A quick word about why I think we should do this with a separate tool rather > than virsh. For starters, I think the need for this functionality on the > command line is clear by now, so it's just a question of where to implement it. > > Why not virsh? Text and command line processing in C is a serious pain > compared to a higher level language like python. I don't think this is a > controversial statement, in fact I think it's partly responsible for why the > virsh XML building commands have typically been in a pretty sorry state. virsh > could conceivably use the internal domain_conf API to make this task much > easier, but it would still require a lot of command line options for every XML > parameter. > > In contrast, virt-install already needs to do most of this command line > processing, and virt-manager needs to do all the XML building, parsing, and > editing. Since this code already lives in one place (virtinst), it's almost > trivial for us to reuse it. Supporting a new XML property on the command line > is a very simple task and will immediately benefit both virt-install and > virt-xml. We also already have over 75% of the domain XML schema available via > existing CLI options that are already documented :) > > Questions or comments appreciated! > > Thanks, > Cole > >From cd821fe259734767619ccb4ca3001df0667c3aed Mon Sep 17 00:00:00 2001 > From: Cole Robinson <crobinso@xxxxxxxxxx> > Date: Thu, 21 Apr 2011 13:13:49 -0400 > Subject: [PATCH] virt-xml initial commit > > --- > tests/pylint-virtinst.sh | 2 +- > todo.txt | 12 +++ > virt-xml | 200 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 213 insertions(+), 1 deletions(-) > create mode 100644 todo.txt > create mode 100755 virt-xml > > diff --git a/tests/pylint-virtinst.sh b/tests/pylint-virtinst.sh > index 7c2a932..98c42fa 100755 > --- a/tests/pylint-virtinst.sh > +++ b/tests/pylint-virtinst.sh > @@ -1,6 +1,6 @@ > #!/bin/sh > > -FILES="setup.py tests/ virt-install virt-image virt-clone virt-convert virtinst/ virtconv virtconv/parsers/*.py" > +FILES="setup.py tests/ virt-install virt-image virt-clone virt-convert virt-xml virtinst/ virtconv virtconv/parsers/*.py" > > # Don't print pylint config warning > NO_PYL_CONFIG=".*No config file found.*" > diff --git a/todo.txt b/todo.txt > new file mode 100644 > index 0000000..9705a43 > --- /dev/null > +++ b/todo.txt > @@ -0,0 +1,12 @@ > + > +virt-xml: > + change commands: > + add device > + remove device > + edit device > + targets: > + --conn URI --guest GUESTNAME > + --conn URI --guestfile file.xml > + other opts: > + --diff (just print diff) > + --print-xml (just print new XML) > diff --git a/virt-xml b/virt-xml > new file mode 100755 > index 0000000..9369991 > --- /dev/null > +++ b/virt-xml > @@ -0,0 +1,200 @@ > +#!/usr/bin/python -tt > +# > +# Copyright 2011 Red Hat, Inc. > +# Cole Robinson <crobinso@xxxxxxxxxx> > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 2 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write to the Free Software > +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, > +# MA 02110-1301 USA. > + > +import sys > +import logging > +import optparse > + > +import libvirt > +import virtinst > +import virtinst.CapabilitiesParser > +import virtinst.cli as cli > +import virtinst.support as support > +from virtinst.VirtualCharDevice import VirtualCharDevice > +from virtinst.VirtualDevice import VirtualDevice > +from virtinst.cli import fail, print_stdout, print_stderr > +import difflib > + > +cli.setupGettext() > + > +def diff(orig, new): > + """ > + Return a unified diff string between the passed strings > + """ > + return "".join(difflib.unified_diff(orig.splitlines(1), > + new.splitlines(1), > + fromfile="Original XML", > + tofile="New XML")) > + > +######################### > +# XML <device> altering # > +######################### > + > +def change_devices(guest, options): > + devmap = { > + VirtualDevice.VIRTUAL_DEV_DISK : options.diskopts, > + VirtualDevice.VIRTUAL_DEV_WATCHDOG : options.watchdog, > + } > + > + if not any(devmap.values()): > + return > + > + if sum(map(int, map(bool, devmap.values()))) > 1: > + fail(_("Only one device can be changed at a time")) > + > + if options.device is None: > + fail(_("A --device must be specified if altering an existing device")) > + if options.device < 1: > + fail(_("--device must be greater than 1")) > + > + dev = None > + try: > + for devtype, devstr in devmap.items(): > + if devstr: > + dev = guest.get_devices(devtype)[options.device - 1] > + break > + except Exception, e: > + cli.log_exception() > + fail(_("Didn't find requested device: %s" % e)) > + > + if options.diskopts: > + cli.parse_disk(guest, options.diskopts, dev) > + elif options.watchdog: > + cli.parse_watchdog(guest, options.watchdog, dev) > + > + > +################## > +# main() helpers # > +################## > + > +def get_xml_flags(vm): > + flags = 0 > + if support.check_domain_support(vm, support.SUPPORT_DOMAIN_XML_INACTIVE): > + flags |= libvirt.VIR_DOMAIN_XML_INACTIVE > + else: > + logging.debug("Domain XML inactive flag not supported.") > + > + if support.check_domain_support(vm, support.SUPPORT_DOMAIN_XML_SECURE): > + flags |= libvirt.VIR_DOMAIN_XML_SECURE > + else: > + logging.debug("Domain XML secure flag not supported.") > + > + return flags > + > +def build_guest(conn, guestname): > + try: > + vm = conn.lookupByName(guestname) > + except Exception, e: > + fail(_("Error fetching domain '%s': %s") % (guestname, e)) > + > + try: > + flags = get_xml_flags(vm) > + except Exception, e: > + cli.log_exception() > + fail(_("Error determining XML flags for '%s': %s") % (guestname, e)) > + > + try: > + xml = vm.XMLDesc(flags) > + except Exception, e: > + fail(_("Error fetching XML for '%s': %s") % (guestname, e)) > + > + logging.debug("Original XML:\n%s" % xml) > + > + try: > + return virtinst.Guest(connection=conn, parsexml=xml) > + except Exception, e: > + cli.log_exception() > + fail(_("Error parsing '%s' XML: %s") % (guestname, e)) > + > +def parse_args(): > + usage = "%prog " > + parser = cli.setupParser(usage) > + cli.add_connect_option(parser) > + > + parser.add_option("-g", "--guest", dest="guest", > + help=_("Name of guest to alter")) > + > + > + gstg = optparse.OptionGroup(parser, _("Guest Configuration")) > + gstg.add_option("", "--boot", dest="bootopts", > + help=_("Configure boot order, menu, permanent kernel " > + "boot, etc.")) > + parser.add_option_group(gstg) > + > + devg = optparse.OptionGroup(parser, _("Device Configuration")) > + devg.add_option("", "--device", type="int", dest="device", > + help=_("Device index")) > + > + devg.add_option("", "--disk", dest="diskopts", > + help=_("Specify disk device with various options. Ex.\n" > + "--disk path=/my/existing/disk\n" > + "--disk path=/my/new/disk,size=5 (in gigabytes)\n" > + "--disk vol=poolname:volname,device=cdrom,bus=scsi,...")) > + > + devg.add_option("", "--watchdog", dest="watchdog", > + help=_("Configure a watchdog device")) > + parser.add_option_group(devg) > + > + misc = optparse.OptionGroup(parser, _("Miscellaneous Options")) > + misc.add_option("-d", "--debug", action="store_true", dest="debug", > + help=_("Print debugging information")) > + parser.add_option_group(misc) > + > + (options, cliargs) = parser.parse_args() > + return options, cliargs > + > +def main(): > + cli.earlyLogging() > + options, cliargs = parse_args() > + cli.setupLogging("virt-xml", options.debug) > + > + if cliargs: > + fail(_("Unknown argument '%s'") % cliargs[0]) > + > + if not options.guest: > + fail(_("--guest must be specified")) > + > + conn = cli.getConnection(options.connect) > + guest = build_guest(conn, options.guest) > + origxml = guest.get_xml_config() > + > + change_devices(guest, options) > + cli.parse_boot(guest, options.bootopts) > + > + newxml = guest.get_xml_config() > + diffstr = diff(origxml, newxml) > + > + if diffstr: > + print_stdout(_("Requested changes:") + "\n" + diffstr) > + else: > + print_stdout(_("No configuration changes were generated")) > + > + return 0 > + > +if __name__ == "__main__": > + try: > + sys.exit(main()) > + except SystemExit, sys_e: > + sys.exit(sys_e.code) > + except KeyboardInterrupt: > + cli.log_exception() > + print_stderr(_("Installation aborted at user request")) > + except Exception, main_e: > + fail(main_e) > -- > 1.7.4 > Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list