diff options
author | Cole Robinson <crobinso@redhat.com> | 2014-01-19 10:37:14 -0500 |
---|---|---|
committer | Cole Robinson <crobinso@redhat.com> | 2014-01-25 17:20:29 -0500 |
commit | 748ff1c4cc249be6c3de30429ec0092a7832af33 (patch) | |
tree | e871a045cddb5c14a5b77e1df09a78335a912dab | |
parent | ffa9bb77b3a97bf03586514f6ebc5214401a15cf (diff) | |
download | virt-manager-748ff1c4cc249be6c3de30429ec0092a7832af33.tar.gz |
virt-xml: Initial commit, basic set of tests
41 files changed, 1064 insertions, 48 deletions
@@ -17,6 +17,7 @@ po/virt-manager.pot /man/virt-image.1 /man/virt-convert.1 /man/virt-image.5 +/man/virt-xml.1 /virt-manager.spec /virtcli/cli.cfg diff --git a/man/virt-xml.pod b/man/virt-xml.pod new file mode 100644 index 00000000..720995fd --- /dev/null +++ b/man/virt-xml.pod @@ -0,0 +1,77 @@ +=pod + +=head1 NAME + +virt-xml - XXX + +=head1 SYNOPSIS + +B<virt-xml> XXX + +=head1 DESCRIPTION + +B<virt-xml> XXX + +=head1 OPTIONS + +=over 4 + +=item -h, --help + +Show the help message and exit + +=back + +=head2 BAR SECTION + +=over 2 + +=item FOO + +FOO + +=item BAR + +BAR + +=back + +=head2 Miscellaneous Options + +=over 2 + +=item -q, --quiet + +Avoid verbose output. + +=item -d, --debug + +Print debugging information + +=item --dry-run + +Proceed through the conversion process, but don't convert disks or actually +write any converted files. + +=back + +=head1 EXAMPLES + +XXX + +=head1 BUGS + +Please see http://virt-manager.org/page/BugReporting + +=head1 COPYRIGHT + +Copyright (C) Red Hat, Inc, and various contributors. +This is free software. You may redistribute copies of it under the terms +of the GNU General Public License C<http://www.gnu.org/licenses/gpl.html>. +There is NO WARRANTY, to the extent permitted by law. + +=head1 SEE ALSO + +L<virt-install(1)>, the project website C<http://virt-manager.org> + +=cut @@ -32,7 +32,7 @@ def _generate_potfiles_in(): return ret scripts = ["virt-manager", "virt-install", - "virt-clone", "virt-image", "virt-convert"] + "virt-clone", "virt-image", "virt-convert", "virt-xml"] potfiles = "\n".join(scripts) + "\n\n" potfiles += "\n".join(find("virtManager", "*.py")) + "\n\n" @@ -145,7 +145,7 @@ class my_build(build): def _make_bin_wrappers(self): cmds = ["virt-manager", "virt-install", "virt-clone", - "virt-image", "virt-convert"] + "virt-image", "virt-convert", "virt-xml"] if not os.path.exists("build"): os.mkdir("build") @@ -559,7 +559,7 @@ class CheckPylint(Command): def run(self): files = ["setup.py", "virt-install", "virt-clone", "virt-image", - "virt-convert", "virt-manager", + "virt-convert", "virt-xml", "virt-manager", "virtcli", "virtinst", "virtconv", "virtManager", "tests"] @@ -590,7 +590,8 @@ setup( "build/virt-clone", "build/virt-install", "build/virt-image", - "build/virt-convert"]), + "build/virt-convert", + "build/virt-xml"]), data_files=[ ("share/virt-manager/", [ @@ -599,6 +600,7 @@ setup( "virt-clone", "virt-image", "virt-convert", + "virt-xml", ]), ("share/glib-2.0/schemas", ["data/org.virt-manager.virt-manager.gschema.xml"]), @@ -609,7 +611,8 @@ setup( "man/virt-install.1", "man/virt-clone.1", "man/virt-image.1", - "man/virt-convert.1" + "man/virt-convert.1", + "man/virt-xml.1" ]), ("share/man/man5", ["man/virt-image.5"]), diff --git a/tests/__init__.py b/tests/__init__.py index 4ab1002c..237cbb83 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -70,6 +70,7 @@ virtinstall = _import("virtinstall", "virt-install") virtimage = _import("virtimage", "virt-image") virtclone = _import("virtclone", "virt-clone") virtconvert = _import("virtconvert", "virt-convert") +virtxml = _import("virtxml", "virt-xml") # Variable used to store a local iso or dir path to check for a distro # Specified via 'python setup.py test_urls --path" diff --git a/tests/cli-test-xml/compare/virtxml-edit-all.xml b/tests/cli-test-xml/compare/virtxml-edit-all.xml new file mode 100644 index 00000000..f239b0fd --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-all.xml @@ -0,0 +1,30 @@ +--- Original XML ++++ Altered XML +@@ -265,21 +265,25 @@ + <vendor id="0x04b3"/> + <product id="0x4485"/> + </source> ++ <driver name="vfio"/> + </hostdev> + <hostdev mode="subsystem" type="usb" managed="yes"> + <source> + <address bus="3" device="2"/> + </source> ++ <driver name="vfio"/> + </hostdev> + <hostdev mode="subsystem" type="pci" managed="yes"> + <source> + <address domain="0x0000" bus="0x00" slot="0x19" function="0x0"/> + </source> ++ <driver name="vfio"/> + </hostdev> + <hostdev mode="subsystem" type="pci" managed="yes"> + <source> + <address domain="0x0003" bus="0x00" slot="0x19" function="0x0"/> + </source> ++ <driver name="vfio"/> + </hostdev> + <redirdev bus="usb" type="tcp"> + <source mode="connect" host="localhost" service="4000"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-neg-num.xml b/tests/cli-test-xml/compare/virtxml-edit-neg-num.xml new file mode 100644 index 00000000..aea38550 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-neg-num.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -258,7 +258,7 @@ + <model type="vmvga" vram="9216" heads="1"/> + </video> + <video> +- <model type="cirrus" vram="10240" heads="3"/> ++ <model type="qxl" vram="10240" heads="3"/> + </video> + <hostdev mode="subsystem" type="usb" managed="yes"> + <source> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-pos-num.xml b/tests/cli-test-xml/compare/virtxml-edit-pos-num.xml new file mode 100644 index 00000000..10a64999 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-pos-num.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -253,7 +253,7 @@ + </graphics> + <sound model="sb16"/> + <sound model="es1370"/> +- <sound model="ich6"/> ++ <sound model="pcspk"/> + <video> + <model type="vmvga" vram="9216" heads="1"/> + </video> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-select-disk-target.xml b/tests/cli-test-xml/compare/virtxml-edit-select-disk-target.xml new file mode 100644 index 00000000..27b4b341 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-select-disk-target.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -65,7 +65,7 @@ + <address type="drive" controller="0" bus="0" target="0" unit="1"/> + </disk> + <disk type="file" device="disk"> +- <source file="/tmp/foobar"/> ++ <source file="/dev/null"/> + <target dev="hda" bus="ide"/> + <iotune> + <read_bytes_sec>5242880</read_bytes_sec> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-select-network-mac.xml b/tests/cli-test-xml/compare/virtxml-edit-select-network-mac.xml new file mode 100644 index 00000000..2d1fe324 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-select-network-mac.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -159,7 +159,7 @@ + <interface type="ethernet"> + <mac address="00:11:7f:33:44:55"/> + <script path="/etc/qemu-ifup"/> +- <target dev="nic02"/> ++ <target dev="nic55"/> + </interface> + <interface type="direct"> + <mac address="f0:11:22:33:44:5f"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-select-sound-model.xml b/tests/cli-test-xml/compare/virtxml-edit-select-sound-model.xml new file mode 100644 index 00000000..10a64999 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-select-sound-model.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -253,7 +253,7 @@ + </graphics> + <sound model="sb16"/> + <sound model="es1370"/> +- <sound model="ich6"/> ++ <sound model="pcspk"/> + <video> + <model type="vmvga" vram="9216" heads="1"/> + </video> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-boot.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-boot.xml new file mode 100644 index 00000000..76858bae --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-boot.xml @@ -0,0 +1,17 @@ +--- Original XML ++++ Altered XML +@@ -15,8 +15,10 @@ + </numatune> + <os> + <type arch="i686">hvm</type> +- <loader>/usr/lib/xen/boot/hvmloader</loader> +- <boot dev="hd"/> ++ <loader>foo.bar</loader> ++ <boot dev="network"/> ++ <bios useserial="yes"/> ++ <init>/bin/bash</init> + </os> + <features> + <acpi/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-channel.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-channel.xml new file mode 100644 index 00000000..59738b52 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-channel.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -214,7 +214,7 @@ + <console type="pty"> + <target type="uml" port="1"/> + </console> +- <channel type="pipe"> ++ <channel type="null"> + <source path="/tmp/guestfwd"/> + <target type="guestfwd" address="10.0.2.1" port="4600"/> + </channel> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-clock.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-clock.xml new file mode 100644 index 00000000..21a00dda --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-clock.xml @@ -0,0 +1,19 @@ +--- Original XML ++++ Altered XML +@@ -44,10 +44,11 @@ + <feature policy="require" name="xtpr"/> + <feature policy="require" name="acpi"/> + </cpu> +- <clock offset="utc"> +- <timer name="rtc" tickpolicy="catchup"/> ++ <clock offset="localtime"> ++ <timer name="rtc" tickpolicy="merge"/> + <timer name="pit" tickpolicy="delay"/> +- <timer name="hpet" present="no"/> ++ <timer name="hpet" present="yes"/> ++ <timer name="kvmclock" present="no"/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-console.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-console.xml new file mode 100644 index 00000000..a496d452 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-console.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -209,7 +209,7 @@ + <target port="2"/> + </parallel> + <console type="pty"> +- <target type="virtio" port="0"/> ++ <target type="serial" port="0"/> + </console> + <console type="pty"> + <target type="uml" port="1"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-controller.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-controller.xml new file mode 100644 index 00000000..b59e93da --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-controller.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -98,7 +98,7 @@ + <source file="/tmp/foobar4"/> + <target dev="xvdc" bus="xen"/> + </disk> +- <controller type="scsi" index="0" model="virtio-scsi"/> ++ <controller type="scsi" index="2" model="lsilogic"/> + <controller type="usb" index="0"/> + <controller type="fdc" index="0"/> + <controller type="ide" index="0"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-cpu.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-cpu.xml new file mode 100644 index 00000000..532ce286 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-cpu.xml @@ -0,0 +1,24 @@ +--- Original XML ++++ Altered XML +@@ -28,9 +28,9 @@ + </hyperv> + </features> + <cpu mode="custom" match="exact"> +- <model fallback="allow">core2duo</model> ++ <model fallback="allow">pentium2</model> + <vendor>Intel</vendor> +- <feature policy="require" name="pbe"/> ++ <feature policy="forbid" name="pbe"/> + <feature policy="require" name="tm2"/> + <feature policy="require" name="est"/> + <feature policy="require" name="ss"/> +@@ -43,6 +43,7 @@ + <feature policy="require" name="ds_cpl"/> + <feature policy="require" name="xtpr"/> + <feature policy="require" name="acpi"/> ++ <feature name="x2apic" policy="force"/> + </cpu> + <clock offset="utc"> + <timer name="rtc" tickpolicy="catchup"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-disk.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-disk.xml new file mode 100644 index 00000000..fad2b8b8 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-disk.xml @@ -0,0 +1,16 @@ +--- Original XML ++++ Altered XML +@@ -55,9 +55,10 @@ + <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <disk type="block" device="floppy"> +- <source dev="/dev/null"/> ++ <source dev="/dev/zero" startupPolicy="optional"/> + <target dev="fda" bus="fdc"/> + <address type="drive" controller="0" bus="0" target="0" unit="0"/> ++ <readonly/> + </disk> + <disk type="dir" device="floppy"> + <source dir="/tmp"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-features.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-features.xml new file mode 100644 index 00000000..36fb2e0e --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-features.xml @@ -0,0 +1,17 @@ +--- Original XML ++++ Altered XML +@@ -19,10 +19,9 @@ + <boot dev="hd"/> + </os> + <features> +- <acpi/> +- <apic eoi="off"/> ++ <apic eoi="on"/> + <hyperv> +- <relaxed state="on"/> ++ <relaxed state="off"/> + <vapic state="on"/> + <spinlocks state="on" retries="12287"/> + </hyperv> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-filesystem.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-filesystem.xml new file mode 100644 index 00000000..720cb540 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-filesystem.xml @@ -0,0 +1,18 @@ +--- Original XML ++++ Altered XML +@@ -105,10 +105,10 @@ + <controller type="virtio-serial" index="1"/> + <controller type="virtio-serial" index="0"/> + <controller type="ccid" index="0"/> +- <filesystem type="mount" accessmode="passthrough"> ++ <filesystem type="mount" accessmode="mapped"> + <driver type="handle"/> +- <source dir="/foo/bar"/> +- <target dir="/bar/baz"/> ++ <source dir="/1/2/3"/> ++ <target dir="/4/5/6"/> + </filesystem> + <filesystem type="template" accessmode="passthrough"> + <source name="template_fedora"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-graphics.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-graphics.xml new file mode 100644 index 00000000..139f7c9b --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-graphics.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -238,7 +238,7 @@ + </backend> + </tpm> + <input type="mouse" bus="ps2"/> +- <graphics type="sdl" display=":3.4" xauth="/testdir/.Xauthority" fullscreen="yes"/> ++ <graphics type="sdl" display=":3.4" xauth="/testdir/.Xauthority" fullscreen="yes" tlsPort="5902" keymap="ja"/> + <graphics type="vnc" port="-1" autoport="yes"/> + <graphics type="vnc" port="-1" autoport="yes" listen="1.2.3.4" keymap="fi"> + <listen type="address" address="1.2.3.4"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-host-device.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-host-device.xml new file mode 100644 index 00000000..eef05b17 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-host-device.xml @@ -0,0 +1,17 @@ +--- Original XML ++++ Altered XML +@@ -262,9 +262,10 @@ + </video> + <hostdev mode="subsystem" type="usb" managed="yes"> + <source> +- <vendor id="0x04b3"/> +- <product id="0x4485"/> ++ <vendor id="0x0781"/> ++ <product id="0x5151"/> + </source> ++ <driver name="vfio"/> + </hostdev> + <hostdev mode="subsystem" type="usb" managed="yes"> + <source> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-memballoon.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-memballoon.xml new file mode 100644 index 00000000..e38ec27c --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-memballoon.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -293,7 +293,7 @@ + <usbdev allow="no"/> + </redirfilter> + <watchdog model="ib700" action="poweroff"/> +- <memballoon model="virtio"/> ++ <memballoon model="none"/> + <rng model="virtio"> + <rate bytes="1234" period="2000"/> + <backend model="egd" type="tcp"> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-network.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-network.xml new file mode 100644 index 00000000..288f9061 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-network.xml @@ -0,0 +1,19 @@ +--- Original XML ++++ Altered XML +@@ -124,11 +124,10 @@ + <source dir="/foo/bar"/> + <target dir="/bar/baz"/> + </filesystem> +- <interface type="network"> +- <mac address="22:22:33:54:32:10"/> +- <source network="default"/> ++ <interface type="bridge"> ++ <source bridge="br0"/> + <target dev="testnet0"/> +- <model type="e1000"/> ++ <model type="virtio"/> + </interface> + <interface type="network"> + <mac address="22:11:11:11:11:11"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-numatune.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-numatune.xml new file mode 100644 index 00000000..3ee20e84 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-numatune.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -11,7 +11,7 @@ + </memoryBacking> + <vcpu placement="static" cpuset="1-2,5-9,11,13-14">9</vcpu> + <numatune> +- <memory mode="interleave" placement="auto"/> ++ <memory mode="strict" placement="auto" nodeset="1-5,7"/> + </numatune> + <os> + <type arch="i686">hvm</type> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-parallel.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-parallel.xml new file mode 100644 index 00000000..2cde1c54 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-parallel.xml @@ -0,0 +1,15 @@ +--- Original XML ++++ Altered XML +@@ -195,8 +195,8 @@ + <protocol type="telnet"/> + <target port="1"/> + </serial> +- <parallel type="file"> +- <source path="/tmp/foo.log"/> ++ <parallel type="unix"> ++ <source path="/some/other/log"/> + <target port="0"/> + </parallel> + <parallel type="unix"> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-redirdev.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-redirdev.xml new file mode 100644 index 00000000..855e4c83 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-redirdev.xml @@ -0,0 +1,15 @@ +--- Original XML ++++ Altered XML +@@ -281,8 +281,8 @@ + <address domain="0x0003" bus="0x00" slot="0x19" function="0x0"/> + </source> + </hostdev> +- <redirdev bus="usb" type="tcp"> +- <source mode="connect" host="localhost" service="4000"/> ++ <redirdev bus="usb" type="spicevmc"> ++ <source mode="connect" host="example.com" service="12345"/> + <protocol type="raw"/> + </redirdev> + <redirdev bus="usb" type="spicevmc"> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-rng.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-rng.xml new file mode 100644 index 00000000..396f7699 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-rng.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -295,7 +295,7 @@ + <watchdog model="ib700" action="poweroff"/> + <memballoon model="virtio"/> + <rng model="virtio"> +- <rate bytes="1234" period="2000"/> ++ <rate bytes="3333" period="4444"/> + <backend model="egd" type="tcp"> + <source mode="connect" host="1.2.3.4" service="1234"/> + <protocol type="raw"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-security.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-security.xml new file mode 100644 index 00000000..bfb10aae --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-security.xml @@ -0,0 +1,12 @@ +--- Original XML ++++ Altered XML +@@ -302,4 +302,7 @@ + </backend> + </rng> + </devices> ++ <seclabel relabel="yes"> ++ <label>foo,bar,baz</label> ++ </seclabel> + </domain> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-serial.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-serial.xml new file mode 100644 index 00000000..71884748 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-serial.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -187,7 +187,7 @@ + <protocol type="raw"/> + <address type="ccid" controller="0" slot="3"/> + </smartcard> +- <serial type="null"> ++ <serial type="pty"> + <target port="0"/> + </serial> + <serial type="tcp"> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-smartcard.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-smartcard.xml new file mode 100644 index 00000000..5d1baa4b --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-smartcard.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -170,7 +170,7 @@ + <target dev="testnet6"/> + <address type="pci" domain="0x0000" bus="0x00" slot="0x07" function="0x0"/> + </interface> +- <smartcard mode="host"> ++ <smartcard mode="host" type="spicevmc"> + <address type="ccid" controller="0" slot="0"/> + </smartcard> + <smartcard mode="host-certificates"> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-soundhw.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-soundhw.xml new file mode 100644 index 00000000..3318f8eb --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-soundhw.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -251,7 +251,7 @@ + <channel name="inputs" mode="secure"/> + <channel name="record" mode="insecure"/> + </graphics> +- <sound model="sb16"/> ++ <sound model="pcspk"/> + <sound model="es1370"/> + <sound model="ich6"/> + <video> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-tpm.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-tpm.xml new file mode 100644 index 00000000..b3ba4264 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-tpm.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -234,7 +234,7 @@ + <input type="tablet" bus="usb"/> + <tpm model="tpm-tis"> + <backend type="passthrough"> +- <device path="/dev/tzz"/> ++ <device path="/dev/tpm"/> + </backend> + </tpm> + <input type="mouse" bus="ps2"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-vcpus.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-vcpus.xml new file mode 100644 index 00000000..45bcafea --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-vcpus.xml @@ -0,0 +1,21 @@ +--- Original XML ++++ Altered XML +@@ -9,7 +9,7 @@ + <memoryBacking> + <hugepages/> + </memoryBacking> +- <vcpu placement="static" cpuset="1-2,5-9,11,13-14">9</vcpu> ++ <vcpu placement="static" cpuset="1-2,5-9,11,13-14" current="10">20</vcpu> + <numatune> + <memory mode="interleave" placement="auto"/> + </numatune> +@@ -43,6 +43,7 @@ + <feature policy="require" name="ds_cpl"/> + <feature policy="require" name="xtpr"/> + <feature policy="require" name="acpi"/> ++ <topology sockets="4" cores="5" threads="1"/> + </cpu> + <clock offset="utc"> + <timer name="rtc" tickpolicy="catchup"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-video.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-video.xml new file mode 100644 index 00000000..d73bc719 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-video.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -255,7 +255,7 @@ + <sound model="es1370"/> + <sound model="ich6"/> + <video> +- <model type="vmvga" vram="9216" heads="1"/> ++ <model type="cirrus" vram="9216" heads="1"/> + </video> + <video> + <model type="cirrus" vram="10240" heads="3"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-edit-simple-watchdog.xml b/tests/cli-test-xml/compare/virtxml-edit-simple-watchdog.xml new file mode 100644 index 00000000..736af59a --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-edit-simple-watchdog.xml @@ -0,0 +1,13 @@ +--- Original XML ++++ Altered XML +@@ -292,7 +292,7 @@ + <usbdev class="0x08" vendor="0x15E1" product="0x2007" version="1.10" allow="yes"/> + <usbdev allow="no"/> + </redirfilter> +- <watchdog model="ib700" action="poweroff"/> ++ <watchdog model="ib700" action="reset"/> + <memballoon model="virtio"/> + <rng model="virtio"> + <rate bytes="1234" period="2000"/> + +Domain 'test-many-devices' defined successfully.
\ No newline at end of file diff --git a/tests/cli-test-xml/compare/virtxml-print-xml.xml b/tests/cli-test-xml/compare/virtxml-print-xml.xml new file mode 100644 index 00000000..cd52f8d3 --- /dev/null +++ b/tests/cli-test-xml/compare/virtxml-print-xml.xml @@ -0,0 +1,17 @@ +<domain type="test" id="1"> + <name>test</name> + <uuid>4a64cc71-19c4-2fd0-2323-3050941ea3c3</uuid> + <memory unit="KiB">8388608</memory> + <currentMemory unit="KiB">2097152</currentMemory> + <vcpu placement="static">7</vcpu> + <os> + <type arch="i686">hvm</type> + <boot dev="hd"/> + </os> + <clock offset="utc"/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + </devices> +</domain> diff --git a/tests/clitest.py b/tests/clitest.py index 84712fcb..b78b3aee 100644 --- a/tests/clitest.py +++ b/tests/clitest.py @@ -30,9 +30,12 @@ import StringIO import virtinst.cli from virtinst import support -from tests import virtinstall, virtimage, virtclone, virtconvert +from tests import virtinstall, virtimage, virtclone, virtconvert, virtxml from tests import utils +# Enable this to refresh test output +REGENERATE_OUTPUT = False + os.environ["VIRTCONV_TEST_NO_DISK_CONVERSION"] = "1" os.environ["LANG"] = "en_US.UTF-8" @@ -185,6 +188,8 @@ class Command(object): ret = virtimage.main(conn=conn) elif app.count("virt-convert"): ret = virtconvert.main() + elif app.count("virt-xml"): + ret = virtxml.main() except SystemExit, sys_e: ret = sys_e.code @@ -244,7 +249,7 @@ class Command(object): if filename: # Generate test files that don't exist yet - if not os.path.exists(filename): + if REGENERATE_OUTPUT or not os.path.exists(filename): file(filename, "w").write(output) utils.diff_compare(output, filename) @@ -260,23 +265,40 @@ class PromptCheck(object): """ Individual question/response pair for automated --prompt tests """ - def __init__(self, prompt, response=None): + def __init__(self, prompt, response=None, num_lines=1): self.prompt = prompt self.response = response if self.response: self.response = self.response % test_files + self.num_lines = num_lines - def check(self, proc): - out = proc.stdout.readline() + self._output = None - if not out.count(self.prompt): - out += "\nContent didn't contain prompt '%s'" % (self.prompt) - return False, out + def check(self, proc): + timeout = 3 + def _set_output(): + self._output = "" + for ignore in range(self.num_lines): + self._output += proc.stdout.readline() + + import threading + thread = threading.Thread(target=_set_output) + thread.start() + thread.join(timeout) + + if thread.isAlive(): + proc.terminate() + return False, self._output + "\nProcess hung on readline()" + + if not self._output.count(self.prompt): + self._output += ("\nContent didn't contain prompt '%s'" % + (self.prompt)) + return False, self._output if self.response: proc.stdin.write(self.response + "\n") - return True, out + return True, self._output class PromptTest(Command): @@ -725,6 +747,54 @@ c.add_invalid("--hvm --boot kernel=%(TREEDIR)s/pxeboot/vmlinuz,initrd=%(TREEDIR) +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 = vixml.add_category("simple edit diff", "--domain test-many-devices --edit --print-diff --define") +c.add_compare("--vcpus 10,maxvcpus=20,cores=5,sockets=4,threads=1", "virtxml-edit-simple-vcpus") +c.add_compare("--cpu model=pentium2,+x2apic,forbid=pbe", "virtxml-edit-simple-cpu") +c.add_compare("--numatune 1-5,7,mode=strict", "virtxml-edit-simple-numatune") +c.add_compare("--boot loader=foo.bar,network,useserial=on,init=/bin/bash", "virtxml-edit-simple-boot") +c.add_compare("--security label=foo,bar,baz,relabel=on", "virtxml-edit-simple-security") +c.add_compare("--features eoi=on,hyperv_relaxed=off,acpi=", "virtxml-edit-simple-features") +c.add_compare("--clock offset=localtime,hpet_present=yes,kvmclock_present=no,rtc_tickpolicy=merge", "virtxml-edit-simple-clock") +c.add_compare("--disk /dev/zero,perms=ro,startup_policy=optional", "virtxml-edit-simple-disk") +c.add_compare("--network source=br0,type=bridge,model=virtio,mac=", "virtxml-edit-simple-network") +c.add_compare("--graphics tlsport=5902,keymap=ja", "virtxml-edit-simple-graphics") +c.add_compare("--controller index=2,model=lsilogic", "virtxml-edit-simple-controller") +c.add_compare("--smartcard type=spicevmc", "virtxml-edit-simple-smartcard") +c.add_compare("--redirdev type=spicevmc,server=example.com:12345", "virtxml-edit-simple-redirdev") +c.add_compare("--tpm path=/dev/tpm", "virtxml-edit-simple-tpm") +c.add_compare("--rng rate_bytes=3333,rate_period=4444", "virtxml-edit-simple-rng") +c.add_compare("--watchdog action=reset", "virtxml-edit-simple-watchdog") +c.add_compare("--memballoon model=none", "virtxml-edit-simple-memballoon") +c.add_compare("--serial pty", "virtxml-edit-simple-serial") +c.add_compare("--parallel unix,path=/some/other/log", "virtxml-edit-simple-parallel") +c.add_compare("--channel null", "virtxml-edit-simple-channel") +c.add_compare("--console target_type=serial", "virtxml-edit-simple-console") +c.add_compare("--filesystem /1/2/3,/4/5/6,mode=mapped", "virtxml-edit-simple-filesystem") +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.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") +c.add_compare("--edit all --host-device driver_name=vfio", "virtxml-edit-all") +c.add_compare("--edit ich6 --soundhw pcspk", "virtxml-edit-select-sound-model") +c.add_compare("--edit target=hda --disk /dev/null", "virtxml-edit-select-disk-target") +c.add_compare("--edit mac=00:11:7f:33:44:55 --network target=nic55", "virtxml-edit-select-network-mac") + + vimag = App("virt-image") c = vimag.add_category("graphics", "--name test-image --boot 0 %(IMAGE_XML)s") c.add_valid("--sdl") # SDL @@ -887,6 +957,10 @@ 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 " + "--edit --cpu host-passthrough") +p8.add("Define 'test' with the changed XML", "yes", num_lines=12) +promptlist.append(p8) ######################### @@ -949,6 +1023,7 @@ _cmdlist += vinst.cmds _cmdlist += vclon.cmds _cmdlist += vimag.cmds _cmdlist += vconv.cmds +_cmdlist += vixml.cmds for _cmd in _cmdlist: newidx += 1 diff --git a/tests/testdriver.xml b/tests/testdriver.xml index 218f57e9..1e709ee1 100644 --- a/tests/testdriver.xml +++ b/tests/testdriver.xml @@ -71,13 +71,26 @@ yeah boii < > yeahfoo </description> <features> - <acpi/><apic/> + <acpi/> + <apic eoi='off'/> + <hyperv> + <relaxed state='on'/> + <vapic state='on'/> + <spinlocks state='on' retries='12287'/> + </hyperv> </features> - <clock offset="utc"/> + <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> <vcpu cpuset="1,2,5-9,11,13-14">9</vcpu> + <numatune> + <memory mode='interleave' placement='auto'/> + </numatune> <cpu match="exact"> <model>core2duo</model> <vendor>Intel</vendor> @@ -148,14 +161,13 @@ </interface> <interface type='network'> <source network='idontexistfool'/> + <mac address='22:11:11:11:11:11'/> </interface> <interface type='network'> <source network='dupmac'/> <mac address='22:22:33:54:32:11'/> </interface> - <interface type='user'> - <mac address='22:11:11:11:11:11'/> - </interface> + <interface type='user'/> <interface type='bridge'> <source bridge='brempty'/> <mac address='22:22:33:44:AA:BB'/> @@ -166,9 +178,8 @@ <mac address='22:00:00:44:AA:BF'/> <model type='e1000'/> </interface> - <controller type='usb'/> <interface type='ethernet'> - <mac address='00:11:7F:33:44:55'/> + <mac address='00:11:7f:33:44:55'/> <script path='/etc/qemu-ifup'/> <target dev='nic02'/> </interface> @@ -200,6 +211,9 @@ <channel name="record" mode="insecure"/> </graphics> + <!-- controller devices --> + <controller type='scsi' model='virtio-scsi'/> + <controller type='usb'/> <!-- sound devices --> <sound model='sb16'/> @@ -363,6 +377,9 @@ <panic> <address type='isa' iobase='0x505'/> </panic> + + <!-- memballoon device --> + <memballoon model='virtio'/> </devices> </domain> diff --git a/virt-manager.spec.in b/virt-manager.spec.in index 45a3af81..3c06319e 100644 --- a/virt-manager.spec.in +++ b/virt-manager.spec.in @@ -93,6 +93,7 @@ Provides: virt-install Provides: virt-clone Provides: virt-image Provides: virt-convert +Provides: virt-xml Obsoletes: python-virtinst %description -n virt-install @@ -194,6 +195,7 @@ fi %{_mandir}/man1/virt-install.1* %{_mandir}/man1/virt-clone.1* %{_mandir}/man1/virt-convert.1* +%{_mandir}/man1/virt-xml.1* %{_mandir}/man1/virt-image.1* %{_mandir}/man5/virt-image.5* @@ -201,11 +203,13 @@ fi %{_datadir}/%{name}/virt-clone %{_datadir}/%{name}/virt-image %{_datadir}/%{name}/virt-convert +%{_datadir}/%{name}/virt-xml %{_bindir}/virt-install %{_bindir}/virt-clone %{_bindir}/virt-image %{_bindir}/virt-convert +%{_bindir}/virt-xml %changelog diff --git a/virt-xml b/virt-xml new file mode 100755 index 00000000..182f160e --- /dev/null +++ b/virt-xml @@ -0,0 +1,283 @@ +#!/usr/bin/python -tt +# +# Copyright 2013 Red Hat, Inc. +# Cole Robinson <crobinso@redhat.com> +# +# 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 difflib +import logging +import os +import sys + +import libvirt + +import virtinst +from virtinst import cli +from virtinst.cli import fail, print_stdout, print_stderr + + +################### +# Utility helpers # +################### + +def prompt_yes_or_no(msg): + while 1: + printmsg = msg + " (y/n): " + if "VIRTINST_TEST_SUITE" in os.environ: + printmsg += "\n" + sys.stdout.write(printmsg) + sys.stdout.flush() + + inp = sys.stdin.readline().lower().strip() + if inp in ["y", "yes"]: + return True + elif inp in ["n", "no"]: + return False + else: + print_stdout(_("Please enter 'yes' or 'no'.")) + + +def get_diff(origxml, newxml): + ret = "".join(difflib.unified_diff(origxml.splitlines(1), + newxml.splitlines(1), + fromfile="Original XML", + tofile="Altered XML")) + + if ret: + logging.debug("XML diff:\n%s", ret) + else: + logging.debug("No XML diff, didn't generate any change.") + return ret + + +def get_domain_and_guest(conn, domstr): + if not domstr: + fail("--domain must be specified") + + try: + int(domstr) + isint = True + except ValueError: + isint = False + + try: + virtinst.util.validate_uuid(domstr) + isuuid = True + except ValueError: + isuuid = False + + try: + if isint: + domain = conn.lookupByID(int(domstr)) + elif isuuid: + domain = conn.lookupByUUIDString(domstr) + else: + domain = conn.lookupByName(domstr) + except libvirt.libvirtError, e: + fail(_("Could not find domain '%s': %s") % (domstr, e)) + + # XXX: Require this for first pass, but it sucks for testing + #if domain.info()[0] != libvirt.VIR_DOMAIN_SHUTOFF: + # fail(_("Domain '%s' must be shutoff.") % domain.name()) + + # XXX: any flags to use here? INACTIVE prob, though not secure or cpu + xml = domain.XMLDesc(0) + + # We do this to minimize the diff, removing things like ' -> " + xml = virtinst.Guest(conn, parsexml=xml).get_xml_config() + return (domain, xml, virtinst.Guest(conn, parsexml=xml)) + + +################ +# Change logic # +################ + +def _find_devices_to_edit(guest, options, parserobj): + devlist = guest.get_devices(parserobj.devclass.virtual_device_type) + idx = None + + if options.edit is None: + idx = 1 + elif (options.edit.isdigit() or + options.edit.startswith("-") and options.edit[1:].isdigit()): + idx = int(options.edit) + + if idx is not None: + if idx == 0: + fail(_("Invalid --edit option '%s'") % options.edit) + + if not devlist: + fail(_("No --%s devices found in the XML") % + parserobj.cli_arg_name) + if len(devlist) < abs(idx): + fail(_("--edit %s requested but there's only %s " + "--%s devices in the XML") % + (idx, len(devlist), parserobj.cli_arg_name)) + + if idx > 0: + idx -= 1 + inst = devlist[idx] + elif options.edit == "all": + inst = devlist[:] + else: + inst = parserobj.lookup_device_from_option_string(guest, options.edit) + if not inst: + fail(_("No matching devices found for --edit %s") % options.edit) + + return inst + + +def change_xml(guest, options, parsermap): + # XXX: Make sure actions don't conflict + # XXX: Make sure XML options don't conflict + # XXX: Find a way to factor out whatever defaults there are + if options.edit is -1: + fail("--edit must be specified") + + collisions = [] + for option_variable_name, parserobj in parsermap.items(): + if getattr(options, option_variable_name): + collisions.append(parserobj) + + if len(collisions) == 0: + fail(_("No change specified.")) + if len(collisions) != 1: + fail(_("Only one change operation may be specified " + "(conflicting options %s)") % + ["--" + c.cli_arg_name for c in collisions]) + parserobj = collisions[0] + + if parserobj.devclass: + inst = _find_devices_to_edit(guest, options, parserobj) + else: + inst = guest + if options.edit and options.edit != '1' and options.edit != 'all': + fail(_("'--edit %s' doesn't make sense with --%s, " + "just use empty '--edit'") % + (options.edit, parserobj.cli_arg_name)) + + cli.parse_option_strings(parsermap, options, guest, inst) + + +####################### +# CLI option handling # +####################### + +def parse_args(): + # XXX: man page: mention introspection if it makes sense + # XXX: expand usage + # XXX: notes about the default actions, behavior, etc + parser = cli.setupParser( + "%(prog)s [options]", + _("Edit libvirt XML using command line options."), + introspection_epilog=True) + + 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("--edit", nargs='?', default=-1, + help=_("Edit VM XML")) + + g = parser.add_argument_group(_("XML options")) + cli.add_disk_option(g) + cli.add_net_option(g) + cli.add_gfx_option(g) + cli.vcpu_cli_options(g) + cli.add_guest_xml_options(g) + cli.add_boot_option(g) + cli.add_fs_option(g) + cli.add_device_options(g) + + misc = parser.add_argument_group(_("Miscellaneous Options")) + cli.add_misc_options(misc, prompt=False, printxml=False, dryrun=False) + misc.add_argument("--print-diff", action="store_true", + help=_("Only print the requested change, in diff format")) + misc.add_argument("--print-xml", action="store_true", + help=_("Only print the requested change, in full XML format")) + misc.add_argument("--confirm", action="store_true", + help=_("Require confirmation before saving any results.")) + misc.add_argument("--define", action="store_true", + help=_("Force defining the domain, only required if a --print " + "option was specified.")) + + return parser.parse_args() + + +################### +# main() handling # +################### + +def main(conn=None): + cli.earlyLogging() + options = parse_args() + + 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 + + if conn is None: + conn = cli.getConnection(options.connect) + + domain, origxml, guest = get_domain_and_guest(conn, options.domain) + # XXX: do we ever need the domain? + ignore = domain + + change_xml(guest, options, parsermap) + + newxml = guest.get_xml_config() + diff = get_diff(origxml, newxml) + + if options.print_diff: + if diff: + print_stdout(diff) + elif options.print_xml: + print_stdout(newxml) + + if not options.define: + return 0 + + if options.confirm: + # XXX: Message needs to depend on what action we will take + if not prompt_yes_or_no( + _("Define '%s' with the changed XML?" % guest.name)): + return 0 + + conn.defineXML(guest.get_xml_config()) + print_stdout(_("Domain '%s' defined successfully." % guest.name)) + return 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except SystemExit, sys_e: + sys.exit(sys_e.code) + except KeyboardInterrupt: + logging.debug("", exc_info=True) + print_stderr(_("Aborted at user request")) + except Exception, main_e: + fail(main_e) diff --git a/virtinst/cli.py b/virtinst/cli.py index 6e074487..7c9b10f8 100644 --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -974,39 +974,39 @@ class _VirtCLIArgument(object): self.ignore_default = ignore_default - def parse(self, opts, inst, support_cb=None): + def parse(self, opts, inst, support_cb=None, lookup=False): val = opts.get_opt_param(self.cliname) if val is None: return + if val == "": + val = None if support_cb: support_cb(inst, self.attrname, self.cliname) if self.is_onoff: val = _on_off_convert(self.cliname, val) - if val == "default" and self.ignore_default: + if val == "default" and self.ignore_default and not lookup: return - attr = None + if lookup and not self.attrname: + raise RuntimeError(_("Don't know how to match %s property %s") % + (getattr(inst, "virtual_device_type", ""), self.cliname)) + try: - if self.setter_cb: - attr = None - elif callable(self.attrname): - attr = self.attrname - else: - attr = eval("inst." + self.attrname) + if self.attrname: + eval("inst." + self.attrname) except AttributeError: raise RuntimeError("programming error: obj=%s does not have " "member=%s" % (inst, self.attrname)) - if self.setter_cb: + if lookup: + return eval("inst." + self.attrname) == val + elif self.setter_cb: self.setter_cb(opts, inst, self.cliname, val) - elif callable(attr): - attr(val) else: exec("inst." + self.attrname + " = val") # pylint: disable=W0122 - class VirtOptionString(object): def __init__(self, optstr, virtargs, remove_first=None): """ @@ -1116,7 +1116,11 @@ class VirtCLIParser(object): A command line argument just extends this interface, implements _init_params, and calls set_param in the order it wants the options parsed on the command line. See existing impls examples of how to - do all sorts of crazy stuff + do all sorts of crazy stuff. + + set_param must be set unconditionally (ex from _init_params and not + from overriding _parse), so that we can show all options when the + user requests command line introspection like --disk=? """ devclass = None @@ -1206,6 +1210,28 @@ class VirtCLIParser(object): return ret[0] return ret + def lookup_device_from_option_string(self, guest, optstr): + """ + Given a passed option string, search the guests' device list + for all devices which match the passed options. + """ + devlist = guest.get_devices(self.devclass.virtual_device_type)[:] + ret = [] + + for inst in devlist: + opts = VirtOptionString(optstr, self._params, + remove_first=self.remove_first) + valid = True + for param in self._params: + if param.parse(opts, inst, + support_cb=None, lookup=True) is False: + valid = False + break + if valid: + ret.append(inst) + + return ret + def _parse_single_optstr(self, guest, optstr, inst): if not optstr: return None @@ -1249,9 +1275,9 @@ class ParserNumatune(VirtCLIParser): self.set_param("numatune.memory_mode", "mode") -################## -# --vcpu parsing # -################## +################### +# --vcpus parsing # +################### class ParserVCPU(VirtCLIParser): def _init_params(self): @@ -1317,7 +1343,17 @@ class ParserCPU(VirtCLIParser): ignore = opts policy = cliname for feature_name in util.listify(val): - inst.cpu.add_feature(feature_name, policy) + featureobj = None + + for f in inst.cpu.features: + if f.name == feature_name: + featureobj = f + break + + if featureobj: + featureobj.policy = policy + else: + inst.cpu.add_feature(feature_name, policy) self.set_param(None, "model", setter_cb=set_model_cb) self.set_param("cpu.match", "match") @@ -1627,7 +1663,7 @@ class ParserNetwork(VirtCLIParser): self.set_param("source_mode", "source_mode") self.set_param("target_dev", "target") self.set_param("model", "model") - self.set_param(None, "mac", setter_cb=set_mac_cb) + self.set_param("macaddr", "mac", setter_cb=set_mac_cb) self.set_param("filterref", "filterref") def _parse(self, optsobj, inst): @@ -1701,7 +1737,11 @@ class ParserController(VirtCLIParser): self.set_param("model", "model") self.set_param("index", "index") self.set_param("master_startport", "master") - self.set_param("address.set_addrstr", "address") + + def set_server_cb(opts, inst, cliname, val): + ignore = opts = cliname + inst.address.set_addrstr(val) + self.set_param(None, "address", setter_cb=set_server_cb) def _parse(self, opts, inst): if opts.fullopts == "usb2": @@ -1739,7 +1779,12 @@ class ParserRedir(VirtCLIParser): self.set_param("bus", "bus") self.set_param("type", "type") - self.set_param("parse_friendly_server", "server") + + def set_server_cb(opts, inst, cliname, val): + ignore = opts = cliname + inst.parse_friendly_server(val) + + self.set_param(None, "server", setter_cb=set_server_cb) ################# @@ -1893,15 +1938,28 @@ class _ParserChar(VirtCLIParser): "optname" : cliname}) self.support_cb = support_check + self.set_param("type", "char_type") self.set_param("source_path", "path") self.set_param("source_mode", "mode") self.set_param("protocol", "protocol") self.set_param("target_type", "target_type") self.set_param("target_name", "name") - self.set_param("set_friendly_source", "host") - self.set_param("set_friendly_bind", "bind_host") - self.set_param("set_friendly_target", "target_address") + + def set_host_cb(opts, inst, cliname, val): + ignore = opts = cliname + inst.set_friendly_source(val) + self.set_param(None, "host", setter_cb=set_host_cb) + + def set_bind_cb(opts, inst, cliname, val): + ignore = opts = cliname + inst.set_friendly_bind(val) + self.set_param(None, "bind_host", setter_cb=set_bind_cb) + + def set_target_cb(opts, inst, cliname, val): + ignore = opts = cliname + inst.set_friendly_target(val) + self.set_param(None, "target_address", setter_cb=set_target_cb) def _parse(self, opts, inst): if opts.fullopts == "none" and inst.virtual_device_type == "console": @@ -2042,17 +2100,23 @@ def build_parser_map(options, skip=None, only=None): return parsermap -def parse_option_strings(parsermap, options, guest, inst): +def parse_option_strings(parsermap, options, guest, instlist): """ Iterate over the parsermap, and launch the associated parser function for every value that was filled in on 'options', which came from argparse/the command line. """ + instlist = util.listify(instlist) + if not instlist: + instlist = [None] + for option_variable_name in dir(options): if option_variable_name not in parsermap: continue - parsermap[option_variable_name].parse( - guest, getattr(options, option_variable_name), inst) + + for inst in util.listify(instlist): + parsermap[option_variable_name].parse( + guest, getattr(options, option_variable_name), inst) def check_option_introspection(options, parsermap): |