# PaCkAgE DaTaStReAm SUNWvirtinst 1 2070 # end of header 0707010002b56e000081a40000000000000000000000014b136d15000001d9000000b600010006ffffffffffffffff0000001500000000SUNWvirtinst/pkginfoPKG=SUNWvirtinst NAME=Guest Domain Installer ARCH=i386 VERSION=11.11,REV=2009.11.30.06.58 SUNW_PRODNAME=SunOS SUNW_PRODVERS=5.11/SunOS Development SUNW_PKGTYPE=usr SUNW_PKG_ALLZONES=true SUNW_PKG_HOLLOW=true SUNW_PKG_THISZONE=false MAXINST=1000 CATEGORY=system DESC=Command-line tool for installing virtual guests VENDOR=Sun Microsystems, Inc. HOTLINE=Please contact your local service provider EMAIL= CLASSES=none BASEDIR=/ SUNW_PKGVERS=1.0 PSTAMP=priscilla20091130065829 0707010002b56d000081a40000000000000000000000014b136d150000217f000000b600010006ffffffffffffffff0000001400000000SUNWvirtinst/pkgmap: 1 2070 1 i copyright 18479 5190 1259321509 1 i depend 1955 36654 1259321509 1 i pkginfo 473 38167 1259564309 1 d none usr 0755 root sys 1 d none usr/bin 0755 root bin 1 f none usr/bin/virt-clone 0555 root bin 9922 40439 1259564304 1 f none usr/bin/virt-convert 0555 root bin 10338 27149 1259564304 1 f none usr/bin/virt-install 0555 root bin 35121 32663 1259564304 1 d none usr/lib 0755 root bin 1 d none usr/lib/python2.4 0755 root bin 1 d none usr/lib/python2.4/vendor-packages 0755 root bin 1 d none usr/lib/python2.4/vendor-packages/virtconv 0755 root bin 1 f none usr/lib/python2.4/vendor-packages/virtconv/__init__.py 0644 root bin 1504 63672 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/__init__.pyc 0644 root bin 1044 53585 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/diskcfg.py 0644 root bin 8574 55965 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/diskcfg.pyc 0644 root bin 7347 28689 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/formats.py 0644 root bin 3853 45203 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtconv/formats.pyc 0644 root bin 4251 24953 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/netdevcfg.py 0644 root bin 1403 46239 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtconv/netdevcfg.pyc 0644 root bin 1011 53569 1259564304 1 d none usr/lib/python2.4/vendor-packages/virtconv/parsers 0755 root bin 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/ovf.py 0644 root bin 14867 30836 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/ovf.pyc 0644 root bin 10785 29329 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtimage.py 0644 root bin 8866 16595 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtimage.pyc 0644 root bin 7907 44565 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtinstance.py 0644 root bin 10540 583 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtinstance.pyc 0644 root bin 8936 54423 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/vmx.py 0644 root bin 9579 14873 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/vmx.pyc 0644 root bin 8564 36195 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/vmcfg.py 0644 root bin 3118 48065 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtconv/vmcfg.pyc 0644 root bin 2862 28912 1259564304 1 d none usr/lib/python2.4/vendor-packages/virtinst 0755 root bin 1 f none usr/lib/python2.4/vendor-packages/virtinst/CapabilitiesParser.py 0644 root bin 13601 5687 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/CapabilitiesParser.pyc 0644 root bin 13303 33737 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/CloneManager.py 0644 root bin 21933 40241 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/CloneManager.pyc 0644 root bin 17754 64792 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.py 0644 root bin 10373 40125 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.pyc 0644 root bin 7111 24508 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.py 0644 root bin 5601 24592 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.pyc 0644 root bin 4328 7554 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/Guest.py 0644 root bin 29285 590 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/Guest.pyc 0644 root bin 25329 64767 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.py 0644 root bin 6585 29762 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.pyc 0644 root bin 6671 64747 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageManager.py 0644 root bin 6464 25955 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageManager.pyc 0644 root bin 5423 42657 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageParser.py 0644 root bin 11697 15449 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageParser.pyc 0644 root bin 11498 41608 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.py 0644 root bin 2185 44579 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.pyc 0644 root bin 1794 27248 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/Installer.py 0644 root bin 12506 38179 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/Installer.pyc 0644 root bin 11165 47002 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.py 0644 root bin 2650 8575 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.pyc 0644 root bin 2348 32901 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.py 0644 root bin 14666 29239 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.pyc 0644 root bin 14827 4118 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/OSDistro.py 0644 root bin 43705 22958 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/OSDistro.pyc 0644 root bin 32941 58817 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.py 0644 root bin 1529 55474 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.pyc 0644 root bin 863 38670 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.py 0644 root bin 1883 17790 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.pyc 0644 root bin 1507 5281 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/Storage.py 0644 root bin 36030 49996 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/Storage.pyc 0644 root bin 33353 61957 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/User.py 0644 root bin 2594 2824 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/User.pyc 0644 root bin 2131 34481 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.py 0644 root bin 1608 64007 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.pyc 0644 root bin 1359 58627 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.py 0644 root bin 2489 65039 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.pyc 0644 root bin 2526 55206 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.py 0644 root bin 33483 53124 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.pyc 0644 root bin 28176 51512 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualGraphics.py 0644 root bin 4377 4751 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualGraphics.pyc 0644 root bin 4473 62116 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.py 0644 root bin 6857 64921 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.pyc 0644 root bin 6288 41642 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualNetworkInterface.py 0644 root bin 7848 50307 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualNetworkInterface.pyc 0644 root bin 6809 14244 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/__init__.py 0644 root bin 2157 54434 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/__init__.pyc 0644 root bin 1908 40522 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/_util.py 0644 root bin 6683 3892 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/_util.pyc 0644 root bin 6228 55171 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/cli.py 0644 root bin 14997 40742 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/cli.pyc 0644 root bin 14998 20746 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/keytable.py 0644 root bin 824 52143 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/keytable.pyc 0644 root bin 940 43970 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/osdict.py 0644 root bin 8897 64636 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/osdict.pyc 0644 root bin 4964 1580 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/util.py 0644 root bin 17646 6641 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/util.pyc 0644 root bin 18050 16970 1259564304 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000b00000000TRAILER!!!0707010002b56e000081a40000000000000000000000014b136d15000001d9000000b600010006ffffffffffffffff0000000800000000pkginfoPKG=SUNWvirtinst NAME=Guest Domain Installer ARCH=i386 VERSION=11.11,REV=2009.11.30.06.58 SUNW_PRODNAME=SunOS SUNW_PRODVERS=5.11/SunOS Development SUNW_PKGTYPE=usr SUNW_PKG_ALLZONES=true SUNW_PKG_HOLLOW=true SUNW_PKG_THISZONE=false MAXINST=1000 CATEGORY=system DESC=Command-line tool for installing virtual guests VENDOR=Sun Microsystems, Inc. HOTLINE=Please contact your local service provider EMAIL= CLASSES=none BASEDIR=/ SUNW_PKGVERS=1.0 PSTAMP=priscilla20091130065829 0707010002b56d000081a40000000000000000000000014b136d150000217f000000b600010006ffffffffffffffff0000000700000000pkgmap: 1 2070 1 i copyright 18479 5190 1259321509 1 i depend 1955 36654 1259321509 1 i pkginfo 473 38167 1259564309 1 d none usr 0755 root sys 1 d none usr/bin 0755 root bin 1 f none usr/bin/virt-clone 0555 root bin 9922 40439 1259564304 1 f none usr/bin/virt-convert 0555 root bin 10338 27149 1259564304 1 f none usr/bin/virt-install 0555 root bin 35121 32663 1259564304 1 d none usr/lib 0755 root bin 1 d none usr/lib/python2.4 0755 root bin 1 d none usr/lib/python2.4/vendor-packages 0755 root bin 1 d none usr/lib/python2.4/vendor-packages/virtconv 0755 root bin 1 f none usr/lib/python2.4/vendor-packages/virtconv/__init__.py 0644 root bin 1504 63672 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/__init__.pyc 0644 root bin 1044 53585 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/diskcfg.py 0644 root bin 8574 55965 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/diskcfg.pyc 0644 root bin 7347 28689 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/formats.py 0644 root bin 3853 45203 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtconv/formats.pyc 0644 root bin 4251 24953 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/netdevcfg.py 0644 root bin 1403 46239 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtconv/netdevcfg.pyc 0644 root bin 1011 53569 1259564304 1 d none usr/lib/python2.4/vendor-packages/virtconv/parsers 0755 root bin 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/ovf.py 0644 root bin 14867 30836 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/ovf.pyc 0644 root bin 10785 29329 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtimage.py 0644 root bin 8866 16595 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtimage.pyc 0644 root bin 7907 44565 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtinstance.py 0644 root bin 10540 583 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtinstance.pyc 0644 root bin 8936 54423 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/vmx.py 0644 root bin 9579 14873 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/vmx.pyc 0644 root bin 8564 36195 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtconv/vmcfg.py 0644 root bin 3118 48065 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtconv/vmcfg.pyc 0644 root bin 2862 28912 1259564304 1 d none usr/lib/python2.4/vendor-packages/virtinst 0755 root bin 1 f none usr/lib/python2.4/vendor-packages/virtinst/CapabilitiesParser.py 0644 root bin 13601 5687 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/CapabilitiesParser.pyc 0644 root bin 13303 33737 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/CloneManager.py 0644 root bin 21933 40241 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/CloneManager.pyc 0644 root bin 17754 64792 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.py 0644 root bin 10373 40125 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.pyc 0644 root bin 7111 24508 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.py 0644 root bin 5601 24592 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.pyc 0644 root bin 4328 7554 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/Guest.py 0644 root bin 29285 590 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/Guest.pyc 0644 root bin 25329 64767 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.py 0644 root bin 6585 29762 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.pyc 0644 root bin 6671 64747 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageManager.py 0644 root bin 6464 25955 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageManager.pyc 0644 root bin 5423 42657 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageParser.py 0644 root bin 11697 15449 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageParser.pyc 0644 root bin 11498 41608 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.py 0644 root bin 2185 44579 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.pyc 0644 root bin 1794 27248 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/Installer.py 0644 root bin 12506 38179 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/Installer.pyc 0644 root bin 11165 47002 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.py 0644 root bin 2650 8575 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.pyc 0644 root bin 2348 32901 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.py 0644 root bin 14666 29239 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.pyc 0644 root bin 14827 4118 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/OSDistro.py 0644 root bin 43705 22958 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/OSDistro.pyc 0644 root bin 32941 58817 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.py 0644 root bin 1529 55474 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.pyc 0644 root bin 863 38670 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.py 0644 root bin 1883 17790 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.pyc 0644 root bin 1507 5281 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/Storage.py 0644 root bin 36030 49996 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/Storage.pyc 0644 root bin 33353 61957 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/User.py 0644 root bin 2594 2824 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/User.pyc 0644 root bin 2131 34481 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.py 0644 root bin 1608 64007 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.pyc 0644 root bin 1359 58627 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.py 0644 root bin 2489 65039 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.pyc 0644 root bin 2526 55206 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.py 0644 root bin 33483 53124 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.pyc 0644 root bin 28176 51512 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualGraphics.py 0644 root bin 4377 4751 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualGraphics.pyc 0644 root bin 4473 62116 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.py 0644 root bin 6857 64921 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.pyc 0644 root bin 6288 41642 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualNetworkInterface.py 0644 root bin 7848 50307 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualNetworkInterface.pyc 0644 root bin 6809 14244 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/__init__.py 0644 root bin 2157 54434 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/__init__.pyc 0644 root bin 1908 40522 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/_util.py 0644 root bin 6683 3892 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/_util.pyc 0644 root bin 6228 55171 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/cli.py 0644 root bin 14997 40742 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/cli.pyc 0644 root bin 14998 20746 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/keytable.py 0644 root bin 824 52143 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/keytable.pyc 0644 root bin 940 43970 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/osdict.py 0644 root bin 8897 64636 1259564303 1 f none usr/lib/python2.4/vendor-packages/virtinst/osdict.pyc 0644 root bin 4964 1580 1259564304 1 f none usr/lib/python2.4/vendor-packages/virtinst/util.py 0644 root bin 17646 6641 1259322745 1 f none usr/lib/python2.4/vendor-packages/virtinst/util.pyc 0644 root bin 18050 16970 1259564304 0707010002b56f000041ed0000000000000000000000024b136d1500000000000000b600010006ffffffffffffffff0000000800000000install0707010002b571000081a40000000000000000000000014b0fb8a5000007a3000000b600010006ffffffffffffffff0000000f00000000install/depend# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This package information file defines software dependencies associated # with the pkg. You can define three types of pkg dependencies with this file: # P indicates a prerequisite for installation # I indicates an incompatible package # R indicates a reverse dependency # see pkginfo(4), PKG parameter # see pkginfo(4), NAME parameter # see pkginfo(4), VERSION parameter # see pkginfo(4), ARCH parameter # # () # () # ... # # ... P SUNWcar Core Architecture, (Root) P SUNWcakr Core Solaris Kernel Architecture (Root) P SUNWkvm Core Architecture, (Kvm) P SUNWcsr Core Solaris, (Root) P SUNWckr Core Solaris Kernel (Root) P SUNWcnetr Core Solaris Network Infrastructure (Root) P SUNWcsu Core Solaris, (Usr) P SUNWcsd Core Solaris Devices P SUNWcsl Core Solaris Libraries P SUNWxvmdomr Hypervisor Domain Tools (Root) P SUNWxvmdomu Hypervisor Domain Tools (Usr) P SUNWlibvirt libvirt P SUNWurlgrabber urlgrabber P SUNWvdisk vdisk 0707010002b570000081a40000000000000000000000014b0fb8a50000482f000000b600010006ffffffffffffffff0000001200000000install/copyright For the avoidance of doubt, except that if any license choice other than GPL or LGPL is available it will apply instead, Sun elects to use only the General Public License version 2 (GPLv2) at this time for any software where a choice of GPL license versions is made available with the language indicating that GPLv2 or any later version may be used, or where a choice of which version of the GPL is applied is otherwise unspecified. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. 0707010002b572000041ed0000000000000000000000034b136d1500000000000000b600010006ffffffffffffffff0000000600000000reloc0707010002b573000041ed0000000000000000000000044b136d1500000000000000b600010006ffffffffffffffff0000000a00000000reloc/usr0707010002b574000041ed0000000000000000000000024b136d1500000000000000b600010006ffffffffffffffff0000000e00000000reloc/usr/bin0707010002b577000081ed0000000000000002000000014b136d1000008931000000b600010006ffffffffffffffff0000001b00000000reloc/usr/bin/virt-install#!/usr/bin/python -tt # # Script to set up a Xen guest and kick off an install # # Copyright 2005-2006 Red Hat, Inc. # Jeremy Katz # Option handling added by Andrew Puch # # 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 os, sys import time import errno from optparse import OptionValueError, OptionGroup import logging import urlgrabber.progress as progress import libvirt import virtinst import virtinst.CapabilitiesParser import virtinst.cli as cli from virtinst.cli import fail import gettext import locale locale.setlocale(locale.LC_ALL, '') gettext.bindtextdomain(virtinst.gettext_app, virtinst.gettext_dir) gettext.install(virtinst.gettext_app, virtinst.gettext_dir, unicode=1) DEFAULT_POOL_PATH = "/var/lib/libvirt/images" DEFAULT_POOL_NAME = "default" def build_default_pool(guest): if not virtinst.util.is_storage_capable(guest.conn): # VirtualDisk will raise an error for us return pool = None try: pool = guest.conn.storagePoolLookupByName(DEFAULT_POOL_NAME) except libvirt.libvirtError: pass if pool: return try: logging.debug("Attempting to build default pool with target '%s'" % DEFAULT_POOL_PATH) defpool = virtinst.Storage.DirectoryPool(conn=guest.conn, name=DEFAULT_POOL_NAME, target_path=DEFAULT_POOL_PATH) newpool = defpool.install(build=True, create=True) newpool.setAutostart(True) except Exception, e: raise RuntimeError(_("Couldn't create default storage pool '%s': %s") % (DEFAULT_POOL_PATH, str(e))) def parse_disk_option(guest, path, size): """helper to properly parse --disk options""" abspath = None voltuple = None volinst = None devtype = None ro = False shared = False sparse = True bus = None cache = None driver = None subdriver = None format = None # Strip media type if path.startswith("path="): path_type = "path=" elif path.startswith("vol="): path_type = "vol=" elif path.startswith("pool="): path_type = "pool=" else: fail(_("--disk path must start with path=, pool=, or vol=.")) path = path[len(path_type):] # Parse out comma separated options opts = {} while True: if not path.count(","): break path, tmpopts = path.split(",", 1) for opt in tmpopts.split(","): opt_type = None opt_val = None if opt.count("="): opt_type, opt_val = opt.split("=", 1) opts[opt_type.lower()] = opt_val.lower() for opt in opts.items(): opt_type, opt_val = opt if opt_type == "device": devtype = opt_val elif opt_type == "bus": bus = opt_val elif opt_type == "perms": if opt_val == "ro": ro = True elif opt_val == "sh": shared = True else: fail(_("Unknown '%s' value '%s'" % (opt_type, opt_val))) elif opt_type == "size": try: size = float(opt_val) except Exception, e: fail(_("Improper value for 'size': %s" % str(e))) elif opt_type == "sparse": if opt_val == "true": sparse = True elif opt_val == "false": sparse = False else: fail(_("Unknown '%s' value '%s'") % (opt_type, opt_val)) elif opt_type == "cache": cache = opt_val elif opt_type == "driver": driver = opt_val elif opt_type == "subdriver": subdriver = opt_val elif opt_type == "format": format = opt_val else: fail(_("Unknown --disk option '%s'.") % (opt,)) # We return (path, (poolname, volname), volinst, device, bus, readonly, # shared) if path_type == "path=": abspath = os.path.abspath(path) if os.path.dirname(abspath) == DEFAULT_POOL_PATH: build_default_pool(guest) elif path_type == "pool=": if not size: raise ValueError(_("Size must be specified with all 'pool='")) if path == DEFAULT_POOL_NAME: build_default_pool(guest) vc = virtinst.Storage.StorageVolume.get_volume_for_pool(pool_name=path, conn=guest.conn) vname = virtinst.Storage.StorageVolume.find_free_name(conn=guest.conn, pool_name=path, name=guest.name, suffix=".img") volinst = vc(pool_name=path, name=vname, conn=guest.conn, allocation=0, capacity=(size and size*1024*1024*1024)) elif path_type == "vol=": if not path.count("/"): raise ValueError(_("Storage volume must be specified as " "pool=poolname/volname")) vollist = path.split("/") voltuple = (vollist[0], vollist[1]) logging.debug("Parsed volume: as pool='%s' vol='%s'" % \ (voltuple[0], voltuple[1])) if voltuple[0] == DEFAULT_POOL_NAME: build_default_pool(guest) if not devtype: devtype = virtinst.VirtualDisk.DEVICE_DISK ret = (abspath, voltuple, volinst, devtype, bus, ro, shared, size, sparse, cache, driver, subdriver, format) logging.debug("parse_disk: returning %s" % str(ret)) return ret def get_disk(disk, size, sparse, guest, hvm, conn, is_file_path): try: # Get disk parameters if is_file_path: (path, voltuple, volinst, device, bus, readOnly, shared, size, sparse, cache, driver, subdriver, format) = \ (disk, None, None, virtinst.VirtualDisk.DEVICE_DISK, None, False, False, size, sparse, None, None, None, None) else: (path, voltuple, volinst, device, bus, readOnly, shared, size, sparse, cache, driver, subdriver, format) = \ parse_disk_option(guest, disk, size) if not sparse and volinst: volinst.allocation = volinst.capacity d = virtinst.VirtualDisk(path=path, size=size, sparse=sparse, volInstall=volinst, volName=voltuple, readOnly=readOnly, shareable=shared, device=device, bus=bus, conn=guest.conn, driverCache=cache, driverName=driver, driverType=subdriver, format=format) # Default file backed PV guests to tap driver if d.type == virtinst.VirtualDisk.TYPE_FILE \ and not(hvm) and virtinst.util.is_blktap_capable(): d.driver_name = virtinst.VirtualDisk.DRIVER_TAP except ValueError, e: fail(_("Error with storage parameters: %s" % str(e))) # Check disk conflicts if d.is_conflict_disk(conn) is True: warnmsg = _("Disk %s is already in use by another guest!\n") % d.path if not cli.prompt_for_yes_or_no(warnmsg + _("Do you really want to use the disk (yes or no)? ")): cli.nice_exit() ret = d.is_size_conflict() if ret[0]: fail(ret[1]) elif ret[1]: if not cli.prompt_for_yes_or_no(ret[1] + _(" Do you really want to use the disk (yes or no)?")): cli.nice_exit() guest.disks.append(d) def get_disks(file_paths, disk_paths, size, sparse, nodisks, guest, hvm, conn): if nodisks: if file_paths or disk_paths or size: fail(_("Cannot use --file, --size, or --disk with --nodisks")) return if (file_paths or size or sparse == False) and disk_paths: fail(_("Cannot mix --file, --nonsparse, or --file-size with --disk " "options. Please see the manual for --disk syntax.")) elif not file_paths and not disk_paths: fail(_("A disk must be specified (use --nodisks to override)")) is_file_path = (file_paths or False) disk = (file_paths or disk_paths) # ensure we have equal length lists if (type(disk) == type(size) == list): if len(disk) != len(size): fail(_("Need to pass size for each disk")) elif type(disk) == list: size = [ None ] * len(disk) elif type(size) == list: disk = [ None ] * len(size) if type(disk) == list or type(size) == list: map(lambda d, s: get_disk(d, s, sparse, guest, hvm, conn, is_file_path), disk, size) else: get_disk(disk, size, sparse, guest, hvm, conn, is_file_path) def get_networks(macs, bridges, networks, nonetworks, guest): if nonetworks: if macs: fail(_("Cannot use --mac with --nonetworks")) if bridges: fail(_("Cannot use --bridges with --nonetworks")) if networks: fail(_("Cannot use --network with --nonetworks")) return (macs, networks) = cli.digest_networks(guest.conn, macs, bridges, networks, nics=1) map(lambda m, n: cli.get_network(m, n, guest), macs, networks) ### Paravirt input gathering functions def get_extraargs(extra, guest): guest.extraargs = extra def get_install_media(location, cdpath, pxe, livecd, import_install, guest, ishvm): found = False for m in [pxe, location, cdpath, import_install]: if m: if found: fail(_("Only one install method (%s) can be used") % "--pxe, --location, --cdrom, --import") found = True if not ishvm: if pxe: fail(_("Network PXE boot is not supported for paravirtualized " "guests")) if cdpath or livecd: fail(_("Paravirtualized guests cannot install off cdrom media.")) if location and virtinst.util.is_uri_remote(guest.conn.getURI()): fail(_("--location can not be specified for remote connections.")) cdinstall = (cdpath or False) if not (pxe or cdpath or location or import_install): # Look at Guest disks: if there is a cdrom, use for install for disk in guest.disks: if disk.device == virtinst.VirtualDisk.DEVICE_CDROM: cdinstall = True if not cdinstall: fail(_("One of %s, or cdrom media must be specified.") % "--pxe, --location, --import") if pxe or import_install: return try: if location or cdpath: guest.location = (location or cdpath) if cdpath and os.path.exists(cdpath): # Build a throwaway disk for validation for local CDs only virtinst.VirtualDisk(path=cdpath, conn=guest.conn, transient=True, device=virtinst.VirtualDisk.DEVICE_CDROM, readOnly=True) if cdinstall: guest.installer.cdrom = True except ValueError, e: fail(_("Error creating cdrom disk: %s" % str(e))) ### Option parsing def check_before_store(option, opt_str, value, parser): if len(value) == 0: raise OptionValueError, _("%s option requires an argument") %opt_str setattr(parser.values, option.dest, value) def check_before_append(option, opt_str, value, parser): if len(value) == 0: raise OptionValueError, _("%s option requires an argument") %opt_str parser.values.ensure_value(option.dest, []).append(value) def parse_args(): usage = "%prog --name NAME --ram RAM STORAGE INSTALL [options]" parser = cli.VirtOptionParser(usage=usage) parser.add_option("", "--connect", type="string", dest="connect", action="callback", callback=cli.check_before_store, help=_("Connect to hypervisor with URI"), default=virtinst.util.default_connection()) geng = OptionGroup(parser, _("General Options")) geng.add_option("-n", "--name", type="string", dest="name", action="callback", callback=cli.check_before_store, help=_("Name of the guest instance")) geng.add_option("-r", "--ram", type="int", dest="memory", help=_("Memory to allocate for guest instance in " "megabytes")) geng.add_option("", "--arch", type="string", dest="arch", action="callback", callback=cli.check_before_store, help=_("The CPU architecture to simulate")) geng.add_option("-u", "--uuid", type="string", dest="uuid", action="callback", callback=cli.check_before_store, help=_("UUID for the guest.")) geng.add_option("", "--vcpus", type="int", dest="vcpus", help=_("Number of vcpus to configure for your guest")) geng.add_option("", "--check-cpu", action="store_true", dest="check_cpu", help=_("Check that vcpus do not exceed physical CPUs " "and warn if they do.")) geng.add_option("", "--cpuset", type="string", dest="cpuset", action="callback", callback=cli.check_before_store, help=_("Set which physical CPUs Domain can use.")) geng.add_option("", "--os-type", type="string", dest="distro_type", action="callback", callback=cli.check_before_store, help=_("The OS type for fully virtualized guests, e.g. " "'linux', 'unix', 'windows'")) geng.add_option("", "--os-variant", type="string", dest="distro_variant", action="callback", callback=cli.check_before_store, help=_("The OS variant for fully virtualized guests, " "e.g. 'fedora6', 'rhel5', 'solaris10', 'win2k'")) geng.add_option("", "--host-device", type="string", dest="hostdevs", action="callback", callback=cli.check_before_append, help=_("Physical host device to attach to the domain.")) geng.add_option("", "--no-define", dest="define", action="store_false", default=True, help=_("Don't permanently define the domain.")) parser.add_option_group(geng) fulg = OptionGroup(parser, _("Full Virtualization specific options")) fulg.add_option("", "--sound", action="store_true", dest="sound", default=False, help=_("Use sound device emulation")) fulg.add_option("", "--noapic", action="store_true", dest="noapic", default=False, help=_("Disables APIC for fully virtualized guest " "(overrides value in os-type/os-variant db)")) fulg.add_option("", "--noacpi", action="store_true", dest="noacpi", default=False, help=_("Disables ACPI for fully virtualized guest " "(overrides value in os-type/os-variant db)")) parser.add_option_group(fulg) virg = OptionGroup(parser, _("Virtualization Type Options")) virg.add_option("-v", "--hvm", action="store_true", dest="fullvirt", help=_("This guest should be a fully virtualized guest")) virg.add_option("-p", "--paravirt", action="store_true", dest="paravirt", help=_("This guest should be a paravirtualized guest")) virg.add_option("", "--accelerate", action="store_true", dest="accelerate", default=False, help=_("Use kernel acceleration capabilities " "(kvm, kqemu, ...)")) parser.add_option_group(virg) insg = OptionGroup(parser, _("Installation Method Options")) insg.add_option("-c", "--cdrom", type="string", dest="cdrom", action="callback", callback=cli.check_before_store, help=_("CD-ROM installation media")) insg.add_option("-l", "--location", type="string", dest="location", action="callback", callback=cli.check_before_store, help=_("Installation source (eg, nfs:host:/path, " "http://host/path, ftp://host/path)")) insg.add_option("", "--pxe", action="store_true", dest="pxe", help=_("Boot from the network using the PXE protocol")) insg.add_option("", "--import", action="store_true", dest="import_install", help=_("Build guest around an existing disk image")) insg.add_option("", "--livecd", action="store_true", dest="livecd", help=_("Treat the CD-ROM media as a Live CD")) insg.add_option("-x", "--extra-args", type="string", dest="extra", default="", help=_("Additional arguments to pass to the kernel " "booted from --location")) insg.add_option("", "--autocf", type="string", dest="autocf", default=None, help=_("Guest auto-configuration path. " "A Jumpstart or kickstart path (eg, nfs:host:/path) " "or AI options, comma-separated name=value " "pairs (eg, install_service=x86_install," "install_media=http://host/path)")) parser.add_option_group(insg) stog = OptionGroup(parser, _("Storage Configuration")) stog.add_option("", "--disk", type="string", dest="diskopts", action="callback", callback=cli.check_before_append, help=_("Specify storage to use as a disk with various " "options.")) stog.add_option("-f", "--file", type="string", dest="file_path", action="callback", callback=cli.check_before_append, help=_("File to use as the disk image")) stog.add_option("-s", "--file-size", type="float", action="append", dest="disksize", help=_("Size of the disk image (if it doesn't exist) in " "gigabytes")) stog.add_option("", "--nonsparse", action="store_false", default=True, dest="sparse", help=_("Don't use sparse files for disks. Note that this " "will be significantly slower for guest creation")) stog.add_option("", "--nodisks", action="store_true", help=_("Don't set up any disks for the guest.")) parser.add_option_group(stog) netg = OptionGroup(parser, _("Networking Configuration")) netg.add_option("-b", "--bridge", type="string", dest="bridge", action="callback", callback=cli.check_before_append, help=_("Bridge to connect guest NIC to; if none given, " "will try to determine the default")) netg.add_option("-w", "--network", type="string", dest="network", action="callback", callback=cli.check_before_append, help=_("Specify a network connection for the guest")) netg.add_option("-m", "--mac", type="string", dest="mac", action="callback", callback=cli.check_before_append, help=_("Fixed MAC address for the guest; if none or " "RANDOM is given a random address will be used")) netg.add_option("", "--nonetworks", action="store_true", help=_("Don't create network interfaces for the guest.")) parser.add_option_group(netg) vncg = OptionGroup(parser, _("Graphics Configuration")) vncg.add_option("", "--vnc", action="store_true", dest="vnc", help=_("Use VNC for graphics support")) vncg.add_option("", "--vncport", type="int", dest="vncport", help=_("Port to use for VNC")) vncg.add_option("", "--sdl", action="store_true", dest="sdl", help=_("Use SDL for graphics support")) vncg.add_option("", "--nographics", action="store_true", help=_("Don't set up a graphical console for the guest.")) vncg.add_option("", "--noautoconsole", action="store_false", dest="autoconsole", help=_("Don't automatically try to connect to the guest " "console")) vncg.add_option("-k", "--keymap", type="string", dest="keymap", action="callback", callback=cli.check_before_store, help=_("set up keymap for a graphical console")) parser.add_option_group(vncg) misc = OptionGroup(parser, _("Miscellaneous Options")) misc.add_option("-d", "--debug", action="store_true", dest="debug", help=_("Print debugging information")) misc.add_option("", "--noreboot", action="store_true", dest="noreboot", help=_("Disables the automatic rebooting when the " "installation is complete.")) misc.add_option("", "--wait", type="int", dest="wait", help=_("Time to wait (in minutes)")) misc.add_option("", "--force", action="store_true", dest="force", help=_("Forces 'yes' for any applicable prompts, " "terminates for all others"), default=False) misc.add_option("", "--prompt", action="store_true", dest="prompt", help=_("Request user input for ambiguous situations. " "Default is false, so will terminate if a prompt " "would typically be fired. "), default=False) parser.add_option_group(misc) (options, dummy) = parser.parse_args() return options ### console callback methods def get_xml_string(dom, path): import libxml2 xml = dom.XMLDesc(0) try: doc = libxml2.parseDoc(xml) except: return None ctx = doc.xpathNewContext() try: ret = ctx.xpathEval(path) tty = None if len(ret) == 1: tty = ret[0].content ctx.xpathFreeContext() doc.freeDoc() return tty except Exception, e: ctx.xpathFreeContext() doc.freeDoc() return None def vncviewer_console(dom): num = 0 while num < ( 40 / 0.25 ): # 40 seconds, .25 second sleeps vncport = get_xml_string(dom, "/domain/devices/graphics[@type='vnc']/@port") if vncport == '-1': num += 1 time.sleep(0.25) else: break if vncport == '-1' or vncport is None: print >> sys.stderr, "Unable to connect to graphical console; vnc port number not found." return None vncport = int(vncport) vnchost = "localhost" if not os.environ.has_key("DISPLAY"): print >> sys.stderr, "Unable to connect to graphical console; DISPLAY is not set. Please connect to %s:%d" %(vnchost, vncport) return None if not os.path.exists("/usr/bin/vncviewer"): print >> sys.stderr, "Unable to connect to graphical console; vncviewer not installed. Please connect to %s:%d" %(vnchost, vncport) return None logging.debug("VNC Port: %d; VNC host: %s" % (vncport, vnchost)) child = os.fork() if not child: os.execvp("/usr/bin/vncviewer", ["/usr/bin/vncviewer", "%s:%d" %(vnchost, vncport) ]) os._exit(1) return child def vnc_console(dom, uri): if not os.path.exists("/usr/bin/virt-viewer"): return vncviewer_console(dom) args = ["/usr/bin/virt-viewer"] if uri is not None and uri != "": args = args + [ "--connect", uri] args = args + [ "--wait", "%s" % dom.ID()] child = os.fork() if not child: try: os.execvp(args[0], args) except OSError, (err, msg): if err == errno.ENOENT: print _("Unable to connect to graphical console: virt-viewer not installed. Please install the 'virt-viewer' package.") else: raise OSError, (err, msg) os._exit(1) return child def txt_console(dom, uri): args = ["/usr/bin/virsh"] if uri is not None and uri != "": args = args + [ "--connect", uri] args = args + [ "console", "--verbose", "%s" % dom.ID()] child = os.fork() if not child: os.execvp(args[0], args) os._exit(1) return child ### Let's do it! def main(): options = parse_args() # Default setup options cli.setupLogging("virt-install", options.debug) cli.set_force(options.force) cli.set_prompt(options.prompt) conn = cli.getConnection(options.connect) capabilities = virtinst.CapabilitiesParser.parse(conn.getCapabilities()) # Set up all virt/hypervisor parameters if options.fullvirt and options.paravirt: fail(_("Can't do both --hvm and --paravirt")) if options.fullvirt: req_virt_type = "hvm" elif options.paravirt: req_virt_type = "xen" else: # This should force capabilities to give us the most sensible default req_virt_type = None logging.debug("Requesting virt method '%s'" % (req_virt_type and req_virt_type or _("default"))) try: (capsguest, capsdomain) = virtinst.CapabilitiesParser.guest_lookup(conn=conn, caps=capabilities, os_type=req_virt_type, arch=options.arch, type=None, accelerated=options.accelerate) except Exception, e: fail(e) virt_type = capsguest.os_type hv_name = capsdomain.hypervisor_type logging.debug("Received virt method '%s'" % virt_type) logging.debug("Hypervisor name is '%s'" % hv_name) # Build the Installer instance if options.livecd: instclass = virtinst.LiveCDInstaller elif options.pxe: if options.nonetworks: fail(_("Can't use --pxe with --nonetworks")) instclass = virtinst.PXEInstaller elif options.import_install: instclass = virtinst.ImportInstaller else: instclass = virtinst.DistroInstaller installer = instclass(type=hv_name, os_type=virt_type, conn=conn) installer.arch = capsguest.arch # Get Guest instance from installer parameters. guest = installer.guest_from_installer() # now let's get some of the common questions out of the way if virt_type == "hvm": ishvm = True else: ishvm = False cli.get_name(options.name, guest) cli.get_memory(options.memory, guest) cli.get_uuid(options.uuid, guest) cli.get_vcpus(options.vcpus, options.check_cpu, guest, conn) cli.get_cpuset(options.cpuset, guest.memory, guest, conn) if ishvm: cli.get_sound(options.sound, guest) # set up disks get_disks(options.file_path, options.diskopts, options.disksize, options.sparse, options.nodisks, guest, ishvm, conn) # set up network information get_networks(options.mac, options.bridge, options.network, options.nonetworks, guest) # set up graphics information cli.get_graphics(options.vnc, options.vncport, options.nographics, options.sdl, options.keymap, guest) # Set host device info cli.get_hostdevs(options.hostdevs, guest) get_extraargs(options.extra, guest) if options.distro_type: guest.set_os_type(options.distro_type) if options.distro_variant: guest.set_os_variant(options.distro_variant) # and now for the full-virt vs paravirt specific questions get_install_media(options.location, options.cdrom, options.pxe, options.livecd, options.import_install, guest, ishvm) if not ishvm: # paravirt continue_inst = False else: if options.noacpi: guest.features["acpi"] = False if options.noapic: guest.features["apic"] = False continue_inst = guest.get_continue_inst() if options.autocf is not None: guest.autocf = options.autocf def show_console(dom): if guest.graphics_dev: if guest.graphics_dev.type == virtinst.VirtualGraphics.TYPE_VNC: return vnc_console(dom, options.connect) else: return None # SDL needs no viewer app else: return txt_console(dom, options.connect) # There are two main cases we care about: # # Scripts: these should specify --wait always, maintaining the # semantics of virt-install exit implying the domain has finished # installing. # # Interactive: If this is a continue_inst domain, we default to # waiting. Otherwise, we can exit before the domain has finished # installing. Passing --wait will give the above semantics. # wait = continue_inst wait_time = -1 autoconsole = options.autoconsole if options.wait: wait = True wait_time = options.wait * 60 if wait_time == 0: # --wait 0 implies --noautoconsole autoconsole = False if autoconsole is False: conscb = None else: conscb = show_console progresscb = progress.TextMeter() # we've got everything -- try to start the install print _("\n\nStarting install...") try: start_time = time.time() # Do first install phase dom = do_install(guest, conscb, progresscb, wait, wait_time, start_time, guest.start_install, define=options.define) # This should be valid even before doing continue install if not guest.post_install_check(): print _("Domain installation does not appear to have been\n " "successful. If it was, you can restart your domain\n " "by running 'virsh start %s'; otherwise, please\n " "restart your installation.") % guest.name sys.exit(0) if continue_inst: dom = do_install(guest, conscb, progresscb, wait, wait_time, start_time, guest.continue_install, define=options.define) if options.noreboot: print _("Guest installation complete... you can restart your " "domain\nby running 'virsh start %s'") % guest.name elif options.define: # FIXME: Should we say 'installation' complete for livecd, import? print _("Guest installation complete... restarting guest.") dom.create() guest.connect_console(conscb) except KeyboardInterrupt, e: guest.terminate_console() print _("Guest install interrupted.") except RuntimeError, e: fail(e) except SystemExit, e: sys.exit(e.code) except Exception, e: print str(e) print (_("Domain installation may not have been\n successful. If it " "was, you can restart your domain\n by running 'virsh start " "%s'; otherwise, please\n restart your installation.") % guest.name) raise def domain_is_shutdown(dom): info = dom.info() state = info[0] cpu_time = info[4] if state == libvirt.VIR_DOMAIN_SHUTOFF: return True # If --wait was specified, the dom object we have was looked up # before initially shutting down, which seems to bogus up the # info data (all 0's). So, if it is bogus, assume the domain is # shutdown. We will catch the error later. return state == libvirt.VIR_DOMAIN_NOSTATE and cpu_time == 0 def do_install(guest, conscb, progresscb, wait, wait_time, start_time, install_func, define=True): dom = install_func(conscb, progresscb, wait=(not wait), define=define) if dom is None: if guest.conn.getURI() == "test:///default": print _("test hypervisor supplied. Exiting.") sys.exit(0) else: print _("Guest installation failed.") sys.exit(0) if domain_is_shutdown(dom): return dom # Domain seems to be running if wait: timestr = "" if wait_time > 0: timestr = _("%d minutes ") % (int(wait_time) / 60) print _("Domain installation still in progress. Waiting %s" "for domain to complete installation.") % timestr # Wait loop while True: if domain_is_shutdown(dom): print _("Domain has shutdown. Continuing.") try: # Lookup a new domain object incase current # one returned bogus data (see comment in # domain_is_shutdown if define: dom = guest.conn.lookupByName(guest.name) else: dom = None except Exception, e: raise RuntimeError(_("Could not lookup domain after " "install: %s" % str(e))) break if wait_time < 0 or ((time.time() - start_time) < wait_time): time.sleep(2) else: print _("Installation has exceeded specified time limit. " "Exiting application.") sys.exit(1) else: print _("Domain installation still in progress. You can reconnect" " to \nthe console to complete the installation process.") sys.exit(0) return dom if __name__ == "__main__": try: main() except SystemExit, sys_e: sys.exit(sys_e.code) except KeyboardInterrupt: print >> sys.stderr, _("Installation aborted at user request") except Exception, main_e: logging.exception(main_e) sys.exit(1) 0707010002b576000081ed0000000000000002000000014b136d1000002862000000b600010006ffffffffffffffff0000001b00000000reloc/usr/bin/virt-convert#!/usr/bin/python # # Copyright 2008 Red Hat, Inc. # Joey Boggs # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # 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 os import logging import errno import gettext, locale from optparse import OptionGroup import virtinst.cli as cli from virtinst.cli import fail import virtinst.util as util import virtconv import virtconv.formats as formats import virtconv.vmcfg as vmcfg import virtconv.diskcfg as diskcfg locale.setlocale(locale.LC_ALL, '') gettext.bindtextdomain(virtconv.gettext_app, virtconv.gettext_dir) gettext.install(virtconv.gettext_app, virtconv.gettext_dir, unicode=1) def parse_args(): """Parse and verify command line.""" usage = "%prog [options] inputdir|input.vmx [outputdir|output.xml]" opts = cli.VirtOptionParser(usage=usage) cong = OptionGroup(opts, "Conversion Options") cong.add_option("-i", "--input-format", action="store", dest="input_format", help=_("Input format, e.g. 'vmx'")) cong.add_option("-o", "--output-format", action="store", dest="output_format", default="virt-image", help=_("Output format, e.g. 'virt-image'")) cong.add_option("-D", "--disk-format", action="store", dest="disk_format", help=_("Output disk format")) opts.add_option_group(cong) virg = OptionGroup(opts, "Virtualization Type Options") virg.add_option("-v", "--hvm", action="store_true", dest="fullvirt", help=_("This guest should be a fully virtualized guest")) virg.add_option("-p", "--paravirt", action="store_true", dest="paravirt", help=_("This guest should be a paravirtualized guest")) opts.add_option_group(virg) cfgg = OptionGroup(opts, "Guest Configuration Options") cfgg.add_option("-a", "--arch", type="string", dest="arch", default=util.get_default_arch(), help=_("Machine Architecture Type (i686/x86_64/ppc)")) cfgg.add_option("", "--os-type", type="string", dest="os_type", action="callback", callback=cli.check_before_store, help=_("The OS type for fully virtualized guests, e.g. " "'linux', 'unix', 'windows'")) cfgg.add_option("", "--os-variant", type="string", dest="os_variant", action="callback", callback=cli.check_before_store, help=_("The OS variant for fully virtualized guests, e.g. " "'fedora6', 'rhel5', 'solaris10', 'win2k', 'vista'")) cfgg.add_option("", "--noapic", action="store_true", dest="noapic", help=_("Disables APIC for fully virtualized guest " "(overrides value in os-type/os-variant db)"), default=False) cfgg.add_option("", "--noacpi", action="store_true", dest="noacpi", help=_("Disables ACPI for fully virtualized guest " "(overrides value in os-type/os-variant db)"), default=False) opts.add_option_group(cfgg) misc = OptionGroup(opts, "Miscellaneous Options") misc.add_option("-q", "--quiet", action="store_true", dest="quiet", help=_("Don't be verbose")) misc.add_option("-d", "--debug", action="store_true", dest="debug", help=_("Print debugging information")) opts.add_option_group(misc) (options, args) = opts.parse_args() cli.setupLogging("virt-convert", options.debug) if len(args) < 1: opts.error(_("You need to provide an input VM definition")) if len(args) > 2: opts.error(_("Too many arguments provided")) if (options.disk_format and options.disk_format not in diskcfg.disk_formats()): opts.error(_("Unknown output disk format \"%s\"") % options.disk_format) if len(args) == 1: options.output_file = None options.output_dir = None if os.path.isdir(args[0]): options.output_dir = args[0] elif os.path.isdir(args[1]) or args[1].endswith("/"): options.output_file = None options.output_dir = args[1] else: options.output_file = args[1] options.output_dir = os.path.dirname(os.path.realpath(args[1])) if options.output_format not in formats.formats(): opts.error(_("Unknown output format \"%s\")" % options.output_format)) if options.output_format not in formats.output_formats(): opts.error(_("No output handler for format \"%s\")" % options.output_format)) if not os.access(args[0], os.R_OK): opts.error(_("Couldn't access input argument \"%s\"\n") % args[0]) sys.exit(1) if not options.input_format: try: (args[0], options.input_format) = formats.find_input(args[0]) except StandardError, e: opts.error(_("Couldn't determine input format for \"%s\": %s") % (args[0], e)) sys.exit(1) if options.input_format not in formats.formats(): opts.error(_("Unknown input format \"%s\")" % options.input_format)) if options.input_format not in formats.input_formats(): opts.error(_("No input handler for format \"%s\"") % options.input_format) if os.path.isdir(args[0]): (options.input_file, ignore) = formats.find_input(args[0], options.input_format) options.input_dir = args[0] else: options.input_file = args[0] options.input_dir = os.path.dirname(os.path.realpath(args[0])) return options def verbose(options, msg): """Output a message if --quiet is not set.""" if not options.quiet: print msg def cleanup(msg, options, vmdef, paths): """ After failure, clean up anything we created. """ logging.error(msg) try: for disk in vmdef.disks.values(): disk.cleanup() paths.reverse() for path in paths: if os.path.isdir(path): os.rmdir(path) elif os.path.isfile(path): os.remove(path) except OSError, e: fail(_("Couldn't clean up output directory \"%s\": %s") % (options.output_dir, e.strerror)) sys.exit(1) def main(): options = parse_args() inp = formats.parser_by_name(options.input_format) outp = formats.parser_by_name(options.output_format) vmdef = None try: vmdef = inp.import_file(options.input_file) except IOError, e: fail(_("Couldn't import file \"%s\": %s") % (options.input_file, e.strerror)) except Exception, e: fail(_("Couldn't import file \"%s\": %s") % (options.input_file, e)) if options.paravirt: vmdef.type = vmcfg.VM_TYPE_PV else: vmdef.type = vmcfg.VM_TYPE_HVM vmdef.arch = options.arch vmdef.os_type = options.os_type vmdef.os_variant = options.os_variant vmdef.noapic = options.noapic vmdef.noacpi = options.noacpi clean = [] unixname = vmdef.name.replace(" ", "-") if not options.output_dir: options.output_dir = unixname try: logging.debug("Creating directory %s" % options.output_dir) os.mkdir(options.output_dir) clean += [ options.output_dir ] except OSError, e: if (e.errno != errno.EEXIST): fail("Could not create directory %s: %s" % (options.output_dir, e.strerror)) if not options.output_file: options.output_file = os.path.join(options.output_dir, "%s%s" % (unixname, outp.suffix)) logging.debug("input_file: %s" % options.input_file) logging.debug("input_dir: %s" % options.input_dir) logging.debug("output_file: %s" % options.output_file) logging.debug("output_dir: %s" % options.input_dir) verbose(options, _("Generating output in '%(format)s' format to %(dir)s/") % {"format": options.output_format, "dir": options.output_dir}) try: for d in vmdef.disks.values(): dformat = options.disk_format # VMDK disks on Solaris converted to vdisk by default if (d.format == diskcfg.DISK_FORMAT_VMDK and not dformat and vmcfg.host() == "SunOS"): dformat = "vdisk" elif options.output_format == "vmx": dformat = "vmdk" if not dformat: dformat = "raw" if d.path and dformat != "none": verbose(options, _("Converting disk '%(path)s' to type " "%(format)s...") % {"path": d.path, "format": dformat}) d.convert(options.input_dir, options.output_dir, dformat) except OSError, e: cleanup(_("Couldn't convert disks: %s") % e.strerror, options, vmdef, clean) except RuntimeError, e: cleanup(_("Couldn't convert disks: %s") % e, options, vmdef, clean) try: clean += [ options.output_file ] outp.export_file(vmdef, options.output_file) except ValueError, e: cleanup(_("Couldn't export to file \"%s\": %s") % (options.output_file, e), options, vmdef, clean) verbose(options, "Done.") if __name__ == "__main__": try: main() except SystemExit, sys_e: sys.exit(sys_e.code) except KeyboardInterrupt: print >> sys.stderr, _("Aborted at user request") except Exception, main_e: logging.exception(main_e) sys.exit(1) 0707010002b575000081ed0000000000000002000000014b136d10000026c2000000b600010006ffffffffffffffff0000001900000000reloc/usr/bin/virt-clone#!/usr/bin/python -tt # # Copyright(c) FUJITSU Limited 2007. # # Script to set up an cloning guest configuration and kick off an cloning # # 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 os, sys import logging import virtinst import virtinst.CloneManager as clmgr import urlgrabber.progress as progress from optparse import OptionGroup import gettext import locale import virtinst.cli as cli from virtinst.cli import fail from virtinst.User import User locale.setlocale(locale.LC_ALL, '') gettext.bindtextdomain(virtinst.gettext_app, virtinst.gettext_dir) gettext.install(virtinst.gettext_app, virtinst.gettext_dir, unicode=1) ### General input gathering functions def get_clone_name(new_name, design): while 1: new_name = cli.prompt_for_input(_("What is the name for the cloned virtual machine?"), new_name) try: design.clone_name = new_name break except (ValueError, RuntimeError), e: print _("ERROR: "), e new_name = None def get_original_guest(guest, origfile, design): origxml = None if origfile: f = open(origfile, "r") origxml = f.read() f.close() while 1: if not origxml: guest = cli.prompt_for_input(_("What is the name of the original virtual machine?"), guest) try: if origxml: design.original_xml = origxml else: design.original_guest = guest break except (ValueError, RuntimeError), e: print _("ERROR: "), e guest = None origxml = None def get_clone_macaddr(new_mac, design): if new_mac is None: pass elif new_mac[0] == "RANDOM": new_mac = None else: for i in new_mac: design.set_clone_mac(i) def get_clone_uuid(new_uuid, design): if new_uuid is not None: design.set_clone_uuid(new_uuid) def get_clone_diskfile(new_diskfiles, design, conn, preserve=False): if new_diskfiles is None: new_diskfiles = [None] newidx = 0 for origdev in design.original_devices: failed_loop = False while 1: if not failed_loop: if len(new_diskfiles) <= newidx: new_diskfiles.append(None) disk = new_diskfiles[newidx] else: disk = None failed_loop = True disk = cli.prompt_for_input(_("What would you like to use as the cloned disk (file path) for '%s'?") % origdev, disk) # Build disk object for validation try: d = virtinst.VirtualDisk(path=disk, size=.0001, conn=conn) except ValueError, e: print _("ERROR: "), e continue # Prompt if disk file already exists and preserve mode is not used if not preserve and os.path.exists(d.path): warnmsg = _("This will overwrite the existing path " "'%s'!\n") % d.path if not cli.prompt_for_yes_or_no(warnmsg + _("Do you really want to use this disk (yes or no)?")): continue # Check disk conflicts if d.is_conflict_disk(conn) is True: warnmsg = _("Disk %s is already in use by another guest!\n") % d.path if not cli.prompt_for_yes_or_no(warnmsg + _("Do you really want to use the disk (yes or no)? ")): continue design.clone_devices = d.path newidx += 1 break def get_clone_sparse(sparse, design): design.set_clone_sparse(sparse) def get_preserve(preserve, design): design.set_preserve(preserve) def get_force_target(target, design): if target is None: pass else: for i in target: design.set_force_target(i) def parse_args(): parser = cli.VirtOptionParser() parser.add_option("", "--connect", type="string", dest="connect", action="callback", callback=cli.check_before_store, help=_("Connect to hypervisor with URI"), default=virtinst.util.default_connection()) geng = OptionGroup(parser, _("General Options")) geng.add_option("-o", "--original", type="string", dest="original_guest", action="callback", callback=cli.check_before_store, help=_("Name of the original guest; " "The status must be shut off or paused.")) geng.add_option("", "--original-xml", type="string", dest="original_xml", action="callback", callback=cli.check_before_store, help=_("XML file to use as the original guest.")) geng.add_option("-n", "--name", type="string", dest="new_name", action="callback", callback=cli.check_before_store, help=_("Name for the new guest")) geng.add_option("-u", "--uuid", type="string", dest="new_uuid", action="callback", callback=cli.check_before_store, help=_("New UUID for the clone guest; Default is a " "randomly generated UUID")) parser.add_option_group(geng) stog = OptionGroup(parser, _("Storage Configuration")) stog.add_option("-f", "--file", type="string", dest="new_diskfile", action="callback", callback=cli.check_before_append, help=_("New file to use as the disk image for the " "new guest")) stog.add_option("", "--force-copy", type="string", dest="target", action="callback", callback=cli.check_before_append, help=_("Force to copy devices (eg, if 'hdc' is a " "readonly cdrom device, --force-copy=hdc)")) stog.add_option("", "--nonsparse", action="store_false", default=True, dest="sparse", help=_("Do not use a sparse file for the clone's " "disk image")) stog.add_option("", "--preserve-data", action="store_false", default=True, dest="preserve", help=_("Preserve a new file to use as the disk image " "for the new guest")) parser.add_option_group(stog) netg = OptionGroup(parser, _("Networking Configuration")) netg.add_option("-m", "--mac", type="string", dest="new_mac", action="callback", callback=cli.check_before_append, help=_("New fixed MAC address for the clone guest. " "Default is a randomly generated MAC")) parser.add_option_group(netg) misc = OptionGroup(parser, _("Miscellaneous Options")) misc.add_option("-d", "--debug", action="store_true", dest="debug", help=_("Print debugging information")) misc.add_option("", "--force", action="store_true", dest="force", help=_("Do not prompt for input. Answers yes where " "applicable, terminates for all other prompts"), default=False) parser.add_option_group(misc) (options, dummy) = parser.parse_args() return options ### Let's do it! def main(): options = parse_args() cli.setupLogging("virt-clone", options.debug) cli.set_force(options.force) if not User.current().has_priv(User.PRIV_CLONE, options.connect): fail(_("Must be privileged to clone Xen guests")) conn = cli.getConnection(options.connect) design = clmgr.CloneDesign(connection=conn) try: get_clone_diskfile(options.new_diskfile, design, conn, not options.preserve) get_clone_macaddr(options.new_mac, design) get_original_guest(options.original_guest, options.original_xml, design) get_clone_name(options.new_name, design) get_clone_uuid(options.new_uuid, design) get_clone_sparse(options.sparse, design) get_force_target(options.target, design) get_preserve(options.preserve, design) # This determines the devices that need to be cloned, so that # get_clone_diskfile knows how many new disk paths it needs design.setup_original() get_clone_diskfile(options.new_diskfile, design, conn, not options.preserve) # setup design object design.setup() # start cloning meter = progress.TextMeter() clmgr.start_duplicate(design, meter) print _("\nClone '%s' created successfully.") % design.clone_name logging.debug("end clone") except RuntimeError, e: fail(e) except SystemExit, e: sys.exit(e.code) except Exception, e: fail(e) if __name__ == "__main__": try: main() except SystemExit, sys_e: sys.exit(sys_e.code) except KeyboardInterrupt: print >> sys.stderr, _("Installation aborted at user request") except Exception, main_e: logging.exception(main_e) sys.exit(1) 0707010002b578000041ed0000000000000000000000034b136d1500000000000000b600010006ffffffffffffffff0000000e00000000reloc/usr/lib0707010002b579000041ed0000000000000000000000034b136d1500000000000000b600010006ffffffffffffffff0000001800000000reloc/usr/lib/python2.40707010002b57a000041ed0000000000000000000000044b136d1500000000000000b600010006ffffffffffffffff0000002800000000reloc/usr/lib/python2.4/vendor-packages0707010002b58f000041ed0000000000000000000000024b136d1500000000000000b600010006ffffffffffffffff0000003100000000reloc/usr/lib/python2.4/vendor-packages/virtinst0707010002b597000081a40000000000000002000000014b136d10000010e8000000b600010006ffffffffffffffff0000004300000000reloc/usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.pycm mKc@sFdkZdkZdklZdklZdefdYZdS(N(sGuest(s VirtualDiskt FullVirtGuestcBs_tZdddddddZdZdZdZedZedZ dZ RS(Nc Cs|p"tid|ddd|}nti|||||d|_hdd<dt i |i <dd<|_ ||_|o ||_nd|_|iid|iid |i}|i oQ|oJxG|iD]8}|i|iijo|i|_|i|_qqWn|idjoD|id jo0|iiid jo d |_qqd |_qun|i o|id jo d|_ndS(Nttypetos_typethvmtconnthdtacpitpaetapictarchtxentx86_64s/usr/lib64/xen/bin/qemu-dms/usr/lib/xen/bin/qemu-dms/usr/lib/xen/boot/hvmloader(t installertDistroInstallerRt connectiontGuestt__init__tselft hypervisorURItdisknodetNonet_utiltis_pae_capableRtfeaturestemulatorR tloadert_capstguestForOSTypeRtguesttdomainstdomthypervisor_typethost( RRR RRRR RR((tb/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/FullVirtGuest.pyRs4  0      cCs[|idjodSnt|i}x-ddgD]}|i|}||| s s<%s/>s s (tretRR&Rtsortedtkeystktv(RRR/R,R0((R!t_get_features_xmlUs   cCs?d}|idj od|i}n|dti||S(Nts %s s (temu_xmlRRRRt_get_device_xmltinstall(RR5R3((R!R4ascCsWd}g}x>|iD]3}|ip d|_n|i|i|qW|oT|i oJ|i i do7t |i dt i dt dt }|id}nx|iD]}d }|it ijo9|io/| o'|i}|ip d |_q n|o|d7}n||i|i7}|d jo ||_qqW|S( s-Get the disk config in the libvirt XML formatR2tidet/tdevicet transienttreadOnlytfdas N(R,t used_targetsRt_install_diskstdiskR(tappendtgenerate_targetR5tautocft startswitht VirtualDiskt DEVICE_FLOPPYtTruet autocf_floppytget_xml_configtdRt saved_pathR8t DEVICE_CDROMR9tpathtget_continue_instttarget(RR5R,R<RIRFR>RH((R!t _get_disk_xmljs4   $   %   cCsti||idd}|idd}x0|iD]%}|o|i o ||_q;q;Wx0|i D]%}|o|i o ||_ qnqnWdS(NR>R(tnettmodel( Rt _set_defaultsRR)tdisk_bust net_modelt _install_nicsRORPR=R>R((RRRRSR>RO((R!RQs   ( t__name__t __module__RRR&R+R1RER4RNRQ(((R!Rs$   #(RR RRCR(R RRRRC((R!t?s    0707010002b5b5000081a40000000000000002000000014b136d10000009de000000b600010006ffffffffffffffff0000004300000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.pycm yKc@sBdkZdkZdkZdklZdefdYZdS(N(s _virtinstt VirtualDevicecBs_tZdZedZdZdZeeeZdZ dZ dZ dZ RS(s7 Base class for all domain xml device objects. cCs|o*t|tipttdq1n||_d|_ |iot i |ii |_ nd|_ |ioti|ii|_ ndS(s Initialize device state @param conn: libvirt connection to validate device against @type conn: virConnect s$'conn' must be a virConnect instanceN(tconnt isinstancetlibvirtt virConnectt ValueErrort_tselft_conntNonet_VirtualDevice__remotet_utilt is_uri_remotetgetURIt_capstCapabilitiesParsertparsetgetCapabilities(RR((tb/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/VirtualDevice.pyt__init__!s     cCs|iS(N(RR(R((Rtget_conn6scCs6t|tipttdn||_dS(Ns%'conn' must be a virConnect instance.(RtvalRRRRRR(RR((Rtset_conn8scCs|iS(N(RR (R((Rt _is_remote>scCs.|ttgjottd|ndS(Ns'%s' must be True or False(RtTruetFalseRRtname(RRR((Rt _check_boolAscCs:t|tj o#ttd|t|fndS(Ns '%s' must be a string, not '%s'.(ttypeRtstrRRR(RRR((Rt _check_strEscCs tdS(s} Construct and return device xml @return: device xml representation as a string @rtype: str N(tNotImplementedError(R((Rtget_xml_configJs( t__name__t __module__t__doc__R RRRtpropertyRRRRR (((RRs       (RRR tvirtinstt _virtinstRtobjectR(RRR RR((Rt?s    0707010002b59d000081a40000000000000002000000014b136d100000152f000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImageManager.pycm yKc@sdkZdkZdkZdkZdkZdklZdklZ de fdYZ deifdYZ de fdYZ d ZdS( N(s VirtualDisk(s _virtinsttImageInstallerExceptioncBstZdZRS(NcCsti||dS(N(t Exceptiont__init__tselftmsg(RR((ta/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/ImageManager.pyRs(t__name__t __module__R(((RRstImageInstallercBstZdZeeedZdZdZeeZdZ ee Z edZ dZ dZ dZd ZRS( s Installer for image-based guestscCstii|d|d|_||_|ioti |ii |_ nP|o6t |tipttdn||_ nttd|djoHt|i |iii|_|idjottdqHnT|djp|dt|iijottdn|ii||_|i i|ii|ii|_|idjo,ttd|ii|iifn|ii|_|ii|_ |i i!|_|ii|_dS( Ntconns/'capabilities' must be a Capabilities instance.s+'conn' or 'capabilities' must be specified.s5Could not find suitable boot descriptor for this hostiisboot_index out of range.s&Unsupported virtualization type: %s %s("t InstallerRRR tNonet_archtimaget_imagetCaptparsetgetCapabilitiest _capabilitiest capabilitiest isinstancet Capabilitiest ValueErrort_t boot_indext match_bootstdomaintbootst _boot_capsRtlentguestForOSTypet boot_capsttypetarcht_guesttPlatformMatchExceptiontos_typetbestDomainTypet_domainthypervisor_type(RR RRR ((RR$s4      *,cCs|iidjotSntS(Nthvm(RRR tTruetFalse(R((Rtis_hvmRscCs|iS(N(RR(R((Rt get_imageWscCs|iS(N(RR(R((Rt get_boot_caps[scCs|i||idjopxmdddgD]X}|ii|ti@ot |i|R*t_get_osblob_helperR3R?(RR3R>R;((Rtget_install_xmlms3  cCstS(N(R)(RR3((Rtpost_install_check~scCsCx<|iiD].}|i|ii}d}|ii dj ot |ii d}n|ii t iijo.tii| ottd|nti}|iit iijo ti}nt||d|dti}|iidjotioti |_!n|i"|_"|i$i%|q WdS(NisSystem disk %s does not existtdeviceR R.(&RRtdrivestmt_abspathtdisktfiletpR tstsizetfloattuset ImageParsertDiskt USE_SYSTEMtostpathtexistsRRt VirtualDiskt DEVICE_DISKRDtformatt FORMAT_ISOt DEVICE_CDROMt TYPE_FILEtdR t_utiltis_blktap_capablet DRIVER_TAPt driver_namettargetR3t_install_diskstappend(RR3RFR[RJRKRD((RR2s$ -     cCs|ii|S(N(RR tabspathRJ(RRJ((RRGs(RRt__doc__R RR+R,tpropertyR R-RR:RBRCR2RG(((RR"s .        R#cBstZdZRS(NcCsti||dS(N(RRRR(RR((RRs(RRR(((RR#scCsx|D]}x|iD]}|i|ijoj|i|ijoWt}x;|i i D]*}|i ||i |@p t }PqYqYW|o|SqqqWqWdS(N(RtbRtgueststgR R$R!R)tfoundR5tnamestbfR*R (RRRkRfRhRi((RRs & (RRR ROtCapabilitiesParserRR\RUtvirtinstt _virtinstRRRRR#R( RRRRUR\R#R RRRORR((Rt?s       0707010002b595000081a40000000000000002000000014b136d1000001bc7000000b600010006ffffffffffffffff0000004500000000reloc/usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.pycm mKc@sdkZdkZdkZdkZdklZdklZdkZdklZ dZ dZ deifdYZ dS(N(s VirtualDisk(sUser(s _virtinstcCsA|idp |idp|idotii| S(sK Check if passed string is a (psuedo) valid http, ftp, or nfs url. shttp://sftp://snfs:N(turlt startswithtostpathtexists(R((td/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/DistroInstaller.pyt_is_urlscCs|idovd|d}|idd}|djottdn||dd jo|| d ||}qn|S( sQ Do nothing for http or ftp, but make sure nfs is in the expected format snfs://snfs:it/iis&Invalid NFS format: No path specified.it:N(RRtfindtindext ValueErrort_(RR ((Rt _sanitize_url&s tDistroInstallercBsttZdddddddZdZdZeeeZdZdZ ddZ dZ d Z RS( Ntxenc CsVtii||||||d|hdd<dd<dd<|_ t |_ dS(Ntconntkernelttinitrdt extraargs( t Installert__init__tselfttypetlocationtbootRtos_typeRtinstalltTruet_location_is_path(RRRRRRR((RR:s $cCs|iS(N(Rt _location(R((Rt get_locationLsc Cst}t}t|_t|tj oFt|t j o3t |djo t t dt|nt|t joJt |djo7t id|ipt t dnt}nt|o&t|}t|_t idnrtiitii|oL|i pti|ii o'tii|}t id|nt}|p*|tjo|ioti|io|o|pd}| o|pd}y4td|dtid |id |}|i}Wqetj o8}t it|t t d t|qeXn|pt t d n|i oV|i!d oFt"i#i$t"i%|io |ii ot t dn||_&dS(s^ Valid values for location: 1) it can be a local file (ex. boot.iso), directory (ex. distro tree) or physical device (ex. cdrom media) 2) tuple of the form (poolname, volname) pointing to a file or device which will set location as that path 3) http, ftp, or nfs path for an install tree isInvalid 'location' type %s.s7DistroInstaller location is a (poolname, volname) tuples:'conn' must be specified if 'location' is a storage tuple.s-DistroInstaller location is a network source.s1DistroInstaller location is a local file/path: %sRtdeviceRtvolNames>Checking installer location failed: Could not find media '%s'.seInstall media location must be an NFS, HTTP or FTP network install source, or an existing file/devicesnfs:s+Privilege is required for NFS installationsN('tFalsetis_tupleRt validatedRRRtvaltstrttupletlenR R tloggingtdebugRRR RRRtabspatht_utilt is_uri_remotetgetURItis_storage_capabletNonetstuplet VirtualDiskt DEVICE_CDROMtdt ExceptionteRtUsertcurrentthas_privtPRIV_NFS_MOUNTR(RR&R$R%R2RR5R7((Rt set_locationNsF 9 &      D1 %-c Cs|ip>ti|i||id|id|}|i i |nt d|id|idt idtdt|_dS(Nt scratchdirtdistroRRR!treadOnlyt transient(RRtOSDistrotacquireBootDiskRtmetertguesttarchR=R>tcdromt _tmpfilestappendR3RR4Rt _install_disk(RRDR>RCRF((Rt_prepare_cdroms        c Cs|idj oP|id|id<|id|id<|idj o|i|idsAuto detected OS type as: %ssAuto detected OS variant as: %stpv_cdrom_installRR!RR?R@("RRR1RRRAt acquireKernelRDRRCRER=RR>tkernelfntinitrdfntargst os_variantR*R+RGRHRRRtisdirR3t DEVICE_DISKR!t_lookup_osdict_keyR4RRRI( RRDR>RCRNROR!RRPRM((Rt_prepare_kernel_and_initrds: ' '    1    cCst|ihdd<dd<dd<|_|io%|io|i|||qpn|i |||dS(NRRRR( RtcleanupRRFRRJRDR>RCRT(RRDRCR>((Rtprepares $  c Cs<|o d}nd}|id|d|d|id|S(NRFthdt isinstallRDRtbootdev(RXRYRt_get_osblob_helperRDR(RRDRXRY((Rtget_install_xmls  cCsy"tid|id|i}WntiddSnX|\}}dk }|oT|i i |oA|o|i |di |ptid|d}qntid|d}d}||fS(NRREs"Error attempting to detect distro.tvariantss4Variant returned from detect_distro is not valid: %ss1Type returned from detect_distro is not valid: %s(NN(RAtdetectMediaDistroRRREt dist_infoR*t exceptionR1tdtypetdvarianttosdicttOS_TYPESthas_keyR+(RR`R^RaRb((Rt detect_distros    "( t__name__t __module__R1RR R<tpropertyRRJRTRVR[Re(((RR9s  F  2  ( R*RR-RR3R8RAtvirtinstt _virtinstR RR R( RAR*R R3R-RR8RRRR ((Rt?s          0707010002b59b000081a40000000000000002000000014b136d1000001a0f000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.pycm yKc@sdkZdkZdkZdkZdkiZdkZdkZdkZdk Z dk l Z dfdYZ de fdYZdefdYZdefd YZd e fd YZd efd YZdefdYZdS(N(s _virtinstt ImageFetchercBsGtZdZdZdZdZdZdZdZRS(NcCs||_||_dS(N(tlocationtselft scratchdir(RRR((ta/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/ImageFetcher.pyt__init__%s cCsXt|dot|d}n |i}|idp|d7}n||7}|S(Ntsrcdirt/(thasattrRtgetattrtpathRtendswithtfilename(RR R ((Rt _make_path)s  cCstii|ipti|idntidd|d|i\}}d}z7x0|i |}|pPnti||q^WWdti|X|S(Nitprefixs virtinst-tdiri@i(tosR texistsRRtmakedirsttempfiletmkstempRtfdtfnt block_sizetfileobjtreadtbufftwritetclose(RRRRRRR((RtsaveTemp4scCstS(N(tTrue(R((RtprepareLocationDscCsdS(N((R((RtcleanupLocationGscCsd}z|i|}tii|}t i d|y)t i |d|dtd|}Wn4tj o(}ttd|t|fnX|i|d|d}t i d||SWd|o|inXdS( NsFetching URI: %st progress_objttextsRetrieving file %s...sCouldn't acquire file %s: %sRt.sSaved file to (tNonetfRR R R Rtbasenametbasetloggingtdebugtgrabberturlopent progresscbt_t Exceptiontet ValueErrortstrRttmpnameR(RR R,R%R2R'R R/((Rt acquireFileJs" $cCstddS(NsMust be implemented in subclass(tNotImplementedError(Rtsrc((RthasFilecs( t__name__t __module__RR RRR R3R6(((RR#s     tURIImageFetchercBstZdZdZRS(NcCs tdS(N(R4(RR ((RR6iscCs1|idpttd|indS(NtsOpening URL %s failed.(RR6R0R-R(R((RRls(R7R8R6R(((RR9gs tHTTPImageFetchercBstZdZRS(NcCsjy;|i|}ti|}d|_ti|Wn(t j ot i d|t SnXt S(NcCsdS(NtHEAD((((RtwssHTTP hasFile: didn't find %s(RR R R turllib2tRequesttrequestt get_methodR+R.R(R)tFalseR(RR R@R ((RR6ss  (R7R8R6(((RR;qstFTPImageFetchercBstZdZRS(NcCs|i|}ti|}y`ti|d}|i y|i |dWn'ti j o|i |dnXWn9ti j o*t id|d|dftSnXtS(Niis"FTP hasFile: couldn't access %s/%s(RR R R turlparseturltftplibtFTPtftptlogintsizet all_errorstcwdR(R)RBR(RR RHRER ((RR6s  (R7R8R6(((RRC~stLocalImageFetchercBstZddZdZRS(NcCs ti|||||_dS(N(RRRRRR(RRRR((RRscCsC|i|}tii|otSnti d|t SdS(Nslocal hasFile: Couldn't find %s( RR R R5RR RRR(R)RB(RR R5((RR6s (R7R8R$RR6(((RRMs tMountedImageFetchercBstZdZdZRS(NcCsfd}tiddd|i|_d}ti ddjo d}nt i d|i|i i d o#|d d |i d |ig}ntiti|i tio d }nd }ti ddjo%|ddd ||i |ig}n|d ||i |ig}ti|}|djo'|ittd|i ntS(NRs virtinstmnt.Rs /bin/mountitSunOSs/usr/sbin/mountsPreparing mount at snfs:s-otroisro,loops-FthsfssMounting location '%s' failed(R$tcmdRtmkdtempRRRtmountcmdRtunameR(R)Rt startswithtstattS_ISBLKtST_MODEtmountoptt subprocesstcalltretR R0R-R(RRRR]RTRZ((RRs(  ## %  cCs|tid|itiddjod|ig}nd|ig}ti|yti |iWnnXdS(NsCleaning up mount at iROs/usr/sbin/umounts /bin/umount( R(R)RRRRURRR[R\trmdir(RRR((RR s (R7R8RR (((RRNs tDirectImageFetchercBstZdZRS(NcCs|i|_dS(N(RRR(R((RRs(R7R8R(((RR_s(R(RRWR[turlgrabber.grabberR*R>RDRFRtvirtinstt _virtinstR-RR9R;RCRMRNR_(RFRWR(RR9R>R_R[RDR*RMR;RRNRRCR-((Rt?s          D  *0707010002b5a7000081a40000000000000002000000014b136d10000039eb000000b600010006ffffffffffffffff0000004600000000reloc/usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.pycm yKc@sOdkZdkZdklZdZdZdZdZdZ dZ dZ d Z d e fd YZd efd YZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdZdZdZdZd Zd!ZdS("N(s _virtinsttsystemtnettpcit usb_devicetusbtstoraget scsi_hosttscsit NodeDevicecBsAtZdZddZdZdZdZdZRS(NcCs,d|_d|_d|_|i|dS(N(tNonetselftnametparentt device_typet _parseNodeXMLtnode(R R((te/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/NodeDeviceParser.pyt__init__$s   cCs tdS(s Use device information to attempt to print a human readable device name. @param child_dev: Child node device to display in description @type child_dev: L{NodeDevice} @returns Device description string @rtype C{str} N(tNotImplementedError(R t child_dev((Rt pretty_name+s cCs|i}x{|os|idjo|i|_nG|idjo|i|_n'|idjo|id|_n|i }q WdS(NR R t capabilityttype( RtchildrentchildR tcontentR R tpropR tnext(R RR((RR8s cCs=|i}x-|o%|idjo|Sn|i}q WdS(NR(RRRR RR (R RR((Rt_getCapabilityNodeCs cCs5|i|iot|||i|indS(N(t value_mapthas_keyRR tsetattrR R(R RR((Rt_parseValueHelperKscCs5|i}x%|o|i|||i}q WdS(N(t main_nodeRRR R RR(R R!RR((Rt _parseHelperOs  ( t__name__t __module__RR RRRR R"(((RR#s    t SystemDevicecBs&tZdZdZddZRS(NcCsiti||d|_d|_d|_d|_d|_ d|_ d|_ |i |i |dS(N(RRR RR t hw_vendort hw_versiont hw_serialthw_uuidt fw_vendort fw_versiontfw_datetparseXMLR(R R((RRVs       cCs|i}hdd<dd<dd<dd<}hdd <dd <d d <}x]|oU|id jo|i||n%|idjo|i||n|i}qWWdS(NtvendorR&tversionR'tserialR(tuuidR)R*R+t release_dateR,thardwaretfirmware( RRRt hardware_mapt firmware_mapR R R"R(R RR6R5R((RR-ds *!cCsT|}td}|io4|d|i7}|io|d|i7}qPn|S(NtSystems: %ss %s(Rtignoret_tdescR R&R'(R RR8R:((RRts   (R#R$RR-R R(((RR%Us  t NetDevicecBs&tZdZdZddZRS(NcCsEti||d|_d|_d|_|i|i |dS(N( RRR RR t interfacetaddresstcapability_typeR-R(R R((RRs    cCsshdd<dd<}|i}xK|oC|idjo|id|_n|i|||i }q$WdS(NR<R=RR( RRRRR RR R>R R(R RRR((RR-s cCs4|}|i}|iotd|i}n|S(Ns Interface %s(RR8R R R:R<R9(R RR8R:((RRs   (R#R$RR-R R(((RR;~s t PCIDevicecBs&tZdZdZddZRS(NcCsrti||d|_d|_d|_d|_d|_ d|_ d|_ d|_ |i |i|dS(N(RRR RR tdomaintbustslottfunctiont product_idt product_namet vendor_idt vendor_nameR-R(R R((RRs        cCshdd<dd<dd<dd<}|i}x|o|idjo"|i|_|id|_ nC|idjo"|i|_ |id|_ n|i |||i }q6WdS(NR@RARBRCR.tidtproduct(tval_mapRRRR RR RGRRFRERDR R(R RRJR((RR-s*   cCsxdt|it|it|if}|o&d||it|i f}nd|t|i f}|S(Ns %.2X:%.2X:%Xs %s %s (%s)s%s %s( tintR RARBRCtdevstrRRtstrRER:(R RRLR:((RRs .&(R#R$RR-R R(((RR?s  t USBDevicecBs&tZdZdZddZRS(NcCs`ti||d|_d|_d|_d|_d|_ d|_ |i |i |dS(N( RRR RR RAtdeviceRDRERFRGR-R(R R((RRs      cCshdd<dd<}|i}x|o|idjo"|i|_|id|_ nC|idjo"|i|_ |id|_ n|i |||i }q$WdS(NRAROR.RHRI(RJRRRR RR RGRRFRERDR R(R RRJR((RR-s   cCsQ|}dt|it|if}d|t|it|i f}|S(Ns %.3d:%.3ds%s %s %s( RR8RKR RARORLRMRGRER:(R RRLR8R:((RRs"%(R#R$RR-R R(((RRNs t StorageDevicecBs&tZdZdZddZRS(NcCsti||d|_d|_d|_d|_d|_ d|_ t |_ t |_ d|_t |_|i|i|dS(Ni(RRR RR tblockRAt drive_typetsizetmodelR.tFalset removabletmedia_availablet media_sizet hotpluggableR-R(R R((RRs          cCsXhdd<dd<dd<dd<dd<}|i}x|o |idjot|i|_n|idjo|i d}|d jo t |_ qF|d jot |_ |i}xk|o_|id jott|i|_n'|id jot|i|_n|i}qWqFn|i|||i}q?WdS( NRQRARRRTR.RSRRRYRVRWRX(RJRRRR RKRR RSRtcaptypetTrueRYRVtrmchildtboolRWRXRR (R RR\RRJRZ((RR-s,3      cCs|}d}|io |i}n|iodi||if}n?|iodi||if}ndi||if}|S(Nts: ( RR8R:R RRRQtjoinRTR (R RR8R:((RR"s    (R#R$RR-R R(((RRPs  tUSBBuscBs&tZdZdZddZRS(NcCsNti||d|_d|_d|_d|_|i |i |dS(N( RRR RR tnumbertclassvaltsubclasstprotocolR-R(R R((RR1s     cCs>hdd<dd<dd<dd<}|i||dS(NRatclassRbRcRd(RJR R"R(R RRJ((RR-;s*cCs |}|iS(N(RR8R R (R RR8((RRBs(R#R$RR-R R(((RR`0s t SCSIDevicecBs&tZdZdZddZRS(NcCsWti||d|_d|_d|_d|_d|_ |i |i |dS(N( RRR RR thostRAttargettluntdiskR-R(R R((RRGs     cCsGhdd<dd<dd<dd<dd<}|i||dS(NRgRARhRiR(RJR R"R(R RRJ((RR-Rs3cCs |}|iS(N(RR8R R (R RR8((RRZs(R#R$RR-R R(((RRfFs tSCSIBuscBs&tZdZdZddZRS(NcCs3ti||d|_|i|i|dS(N(RRR RR RgR-R(R R((RR_s cCs#hdd<}|i||dS(NRg(RJR R"R(R RRJ((RR-fscCs |}|iS(N(RR8R R (R RR8((RRjs(R#R$RR-R R(((RRk^s  cCs|ptSnt|tipttdnttiddjotSny|i ddt SWnIt j o=}|itijp|itijotSqnXt S(s Check if the passed libvirt connection supports host device routines @param conn: Connection to check @type conn: libvirt.virConnect @rtype: C{bool} s%'conn' must be a virConnect instance.t virNodeDeviceiN(tconnRUt isinstancetlibvirtt virConnectt ValueErrorR9tdirtcountt listDevicesR R[t Exceptiontetget_error_codet VIR_ERR_RPCtVIR_ERR_NO_SUPPORT(RmRv((Rtis_nodedev_capablens, cCs`|ptSnt|tipttdnttiddjotSnt S(s Check if the passed libvirt connection support pci device Detach/Reset @param conn: Connection to check @type conn: libvirt.virConnect @rtype: C{bool} s%'conn' must be a virConnect instance.tvirNodeDeviceDettachiN( RmRURnRoRpRqR9RrRsR[(Rm((Rtis_pci_detach_capablescCsKt|pttdn|i|}|id}t |S(s Convert the passed libvirt node device name to a NodeDevice instance, with proper error reporting. @param conn: libvirt.virConnect instance to perform the lookup on @param name: libvirt node device name to lookup @rtype: L{NodeDevice} instance s4Connection does not support host device enumeration.iN( RzRmRqR9tnodeDeviceLookupByNameR tnodedevtXMLDesctxmltparse(RmR RR~((RtlookupNodeNames  c CsdfdY}|}ti|idziy(ti|t|ddti }Wn:ti ti fj o"}td||ifnXWdtiddXzT|i}|idjotdnt|}t|}||}Wd|iX|S(s Convert the passed libvirt node device xml into a NodeDevice object @param xml: libvirt node device xml @type xml: C{str} @returns: L{NodeDevice} instance t ErrorHandlercBstZdZdZRS(NcCs d|_dS(NR^(R tmsg(R ((RRscCs|i|7_dS(N(R Rts(R R8R((Rthandlers(R#R$RR(((RRs s%s %sNROsRoot element is not 'device'(Rterrortlibxml2tregisterErrorHandlerRR t readMemoryRtlentXML_PARSE_NOBLANKStdoct parserErrort treeErrorRvRqRtgetRootElementtrootR t _findNodeTypettt_typeToDeviceClasstdevclassROtfreeDoc( RRRvRRRRORR((RRs. "    cCsF|i}x6|o.|idjo|idSn|i}q WdS(NRR(RRRR RRR (RR((RRs cCs|tjotSn|tjotSn|tjotSnj|tjotSnU|t jot Sn@|t jot Sn+|t jotSn|tjotSnttd|dS(Ns$Unknown host device capability '%s'.(RtCAPABILITY_TYPE_SYSTEMR%tCAPABILITY_TYPE_NETR;tCAPABILITY_TYPE_PCIR?tCAPABILITY_TYPE_USBDEVRNtCAPABILITY_TYPE_USBBUSR`tCAPABILITY_TYPE_STORAGERPtCAPABILITY_TYPE_SCSIBUSRktCAPABILITY_TYPE_SCSIDEVRfRqR9(R((RRs"        (RRotvirtinstt _virtinstR9RRRRRRRRtobjectRR%R;R?RNRPR`RfRkRzR|RRRR(R|RRRRzRRRRNRRRR`RfRRoRPR%R9RRkR?RRR;R((Rt?s2   2)/&@    * 0707010002b5bc000081a40000000000000002000000014b136d0f00001ea8000000b600010006ffffffffffffffff0000004c00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualNetworkInterface.py# # Copyright 2006-2009 Red Hat, Inc. # Jeremy Katz # # 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 re import logging import libvirt import __builtin__ import _util import VirtualDevice from virtinst import _virtinst as _ class VirtualNetworkInterface(VirtualDevice.VirtualDevice): TYPE_BRIDGE = "bridge" TYPE_VIRTUAL = "network" TYPE_USER = "user" def __init__(self, macaddr=None, type=TYPE_BRIDGE, bridge=None, network=None, model=None, conn=None, rate=None, vlanid=None): VirtualDevice.VirtualDevice.__init__(self, conn) if (macaddr is not None and __builtin__.type(macaddr) is not str): raise ValueError, _("MAC address must be a string.") if macaddr is not None: form = re.match("^([0-9a-fA-F]{1,2}:){5}[0-9a-fA-F]{1,2}$",macaddr) if form is None: raise ValueError, \ _("MAC address must be of the format AA:BB:CC:DD:EE:FF") if vlanid is not None: if not vlanid.isdigit(): raise ValueError, _("vlanid must be a number") if rate is not None and \ __builtin__.type(rate) is not __builtin__.type("string"): raise ValueError, "bandwidth must be a string." rate_val = None rate_unit = None if rate: bw = re.match("^([0-9]+)([GMK])$", rate) if not bw: raise ValueError, \ _("bandwidth must be of the format '^([0-9]+)([GMK])$'") zerobw = re.match("^(0+)([GMK])$", rate) # '0' rate means no limit if not zerobw: rate_val = bw.group(1) rate_unit = bw.group(2) self._network = None self.macaddr = macaddr self.type = type self.bridge = bridge self.network = network self.model = model self.rate = rate_val self.rate_unit = rate_unit self.vlanid = vlanid if self.type == self.TYPE_VIRTUAL: if network is None: raise ValueError, _("A network name was not provided") elif self.type == self.TYPE_BRIDGE: pass elif self.type == self.TYPE_USER: pass else: raise ValueError, _("Unknown network type %s") % (type,) def get_network(self): return self._network def set_network(self, newnet): def _is_net_active(netobj): """Apparently the 'info' command was never hooked up for libvirt virNetwork python apis.""" if not self.conn: return True return self.conn.listNetworks().count(netobj.name()) if newnet is not None and self.conn: try: net = self.conn.networkLookupByName(newnet) except libvirt.libvirtError, e: raise ValueError(_("Virtual network '%s' does not exist: %s") \ % (newnet, str(e))) if not _is_net_active(net): raise ValueError(_("Virtual network '%s' has not been " "started.") % newnet) self._network = newnet network = property(get_network, set_network) def is_conflict_net(self, conn): """is_conflict_net: determines if mac conflicts with others in system returns a two element tuple: first element is True if fatal collision occured second element is a string description of the collision. Non fatal collisions (mac addr collides with inactive guest) will return (False, "description of collision")""" if self.macaddr is None: return (False, None) vms, inactive_vm = _util.fetch_all_guests(conn) # get the Host's NIC MACaddress hostdevs = _util.get_host_network_devices() if self.countMACaddr(vms) > 0: return (True, _("The MAC address you entered is already in use by another active virtual machine.")) for (dummy, dummy, dummy, dummy, host_macaddr) in hostdevs: if self.macaddr.upper() == host_macaddr.upper(): return (True, _("The MAC address you entered conflicts with a device on the physical host.")) if self.countMACaddr(inactive_vm) > 0: return (False, _("The MAC address you entered is already in use by another inactive virtual machine.")) return (False, None) def setup(self, conn): if self.macaddr is None: while 1: self.macaddr = _util.randomMAC(type=conn.getType().lower()) if self.is_conflict_net(conn)[1] is not None: continue else: break else: ret, msg = self.is_conflict_net(conn) if msg is not None: if ret is False: logging.warning(msg) else: raise RuntimeError(msg) if not self.bridge and self.type == "bridge": self.bridge = _util.default_bridge() def get_xml_config(self): src_xml = "" model_xml = "" if self.type == self.TYPE_BRIDGE: src_xml = " \n" % self.bridge elif self.type == self.TYPE_VIRTUAL: src_xml = " \n" % self.network if self.model: model_xml = " \n" % self.model rate_xml = "" if self.rate: if self.rate_unit == 'G': unit = "gigabit" elif self.rate_unit == 'M': unit = "megabit" elif self.rate_unit == 'K': unit = "kilobit" rate_xml = (" \n" + \ " \n" + \ " \n") % \ { "unit": unit, "value": self.rate } vlan_xml = "" if self.vlanid != None: vlan_xml = (" \n" % { "vlanid": self.vlanid }) return " \n" % self.type + \ src_xml + \ " \n" % self.macaddr + \ model_xml + \ rate_xml + \ vlan_xml + \ " " def countMACaddr(self, vms): if not self.macaddr: return def count_cb(ctx): c = 0 for mac in ctx.xpathEval("/domain/devices/interface/mac"): macaddr = mac.xpathEval("attribute::address")[0].content if macaddr and _util.compareMAC(self.macaddr, macaddr) == 0: c += 1 return c count = 0 for vm in vms: xml = vm.XMLDesc(0) count += _util.get_xml_path(xml, func = count_cb) return count # Back compat class to avoid ABI break class XenNetworkInterface(VirtualNetworkInterface): pass 0707010002b5b3000081a40000000000000002000000014b136d100000054f000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.pycm mKc@s3dkZdklZdeifdYZdS(N(s _virtinstt VirtualAudiocBsGtZdgZddZdZdZeeeZdZ RS(Ntes1370cCs)tii||d|_||_dS(N(t VirtualDevicet__init__tselftconntNonet_modeltmodel(RRR((ta/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/VirtualAudio.pyRs cCs|iS(N(RR(R((R t get_model"scCsgt|tjottdt|n|ii|pttd|n||_dS(Ns$'model' must be a string, was '%s'.sUnsupported sound model '%s'( ttypet new_modeltstrt ValueErrort_RtMODELStcountR(RR ((R t set_model$s cCs d|iS(Ns (RR(R((R tget_xml_config-s( t__name__t __module__RRRR RtpropertyRR(((R Rs     (Rtvirtinstt _virtinstRR(RRR((R t?s  0707010002b5ad000081a40000000000000002000000014b136d10000005e3000000b600010006ffffffffffffffff0000004300000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.pycm yKc@s4dklZdklZdefdYZdS((sGuest(sDistroInstallert ParaVirtGuestcBs2tZdddddZdZedZRS(NcCsL|ptd|ddd|}nti|||||d|_dS(Nttypetos_typetxentconntxvd( t installertDistroInstallerRt connectiontGuestt__init__tselft hypervisorURItdisknode(R RRR R((tb/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/ParaVirtGuest.pyR s cCsdS(NtmouseR(Rsxen((R ((Rt_get_input_device"scCsd}g}x>|iD]3}|ip d|_n|i|i|qWxU|iD]J}|i o| oqWn|o|d7}n||i |i 7}qWW|S(s-Get the disk config in the libvirt XML formattRs N( trett used_targetsR t_install_diskstdisktbustappendtgenerate_targettdt transienttinstalltget_xml_configttarget(R RRRRR((Rt _get_disk_xml%s     (t__name__t __module__tNoneR RtTrueR(((RRs N(R RR(RRR ((Rt?s  0707010002b5a6000081a40000000000000002000000014b0fbd790000394a000000b600010006ffffffffffffffff0000004500000000reloc/usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.py# # Copyright 2009 Red Hat, Inc. # Cole Robinson # # 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 libxml2 import libvirt from virtinst import _virtinst as _ # class USBDevice CAPABILITY_TYPE_SYSTEM = "system" CAPABILITY_TYPE_NET = "net" CAPABILITY_TYPE_PCI = "pci" CAPABILITY_TYPE_USBDEV = "usb_device" CAPABILITY_TYPE_USBBUS = "usb" CAPABILITY_TYPE_STORAGE = "storage" CAPABILITY_TYPE_SCSIBUS = "scsi_host" CAPABILITY_TYPE_SCSIDEV = "scsi" class NodeDevice(object): def __init__(self, node): self.name = None self.parent = None self.device_type = None self._parseNodeXML(node) def pretty_name(self, child_dev=None): """ Use device information to attempt to print a human readable device name. @param child_dev: Child node device to display in description @type child_dev: L{NodeDevice} @returns Device description string @rtype C{str} """ raise NotImplementedError def _parseNodeXML(self, node): child = node.children while child: if child.name == "name": self.name = child.content elif child.name == "parent": self.parent = child.content elif child.name == "capability": self.device_type = child.prop("type") child = child.next def _getCapabilityNode(self, node): child = node.children while child: if child.name == "capability": return child child = child.next return None def _parseValueHelper(self, node, value_map): if value_map.has_key(node.name): setattr(self, value_map[node.name], node.content) def _parseHelper(self, main_node, value_map): node = main_node.children while node: self._parseValueHelper(node, value_map) node = node.next class SystemDevice(NodeDevice): def __init__(self, node): NodeDevice.__init__(self, node) self.hw_vendor = None self.hw_version = None self.hw_serial = None self.hw_uuid = None self.fw_vendor = None self.fw_version = None self.fw_date = None self.parseXML(self._getCapabilityNode(node)) def parseXML(self, node): child = node.children hardware_map = {"vendor": "hw_vendor", "version": "hw_version", "serial": "hw_serial", "uuid": "hw_uuid"} firmware_map = {"vendor": "fw_vendor", "version": "fw_version", "release_date": "fw_date" } while child: if child.name == "hardware": self._parseHelper(child, hardware_map) elif child.name == "firmware": self._parseHelper(child, firmware_map) child = child.next def pretty_name(self, child_dev=None): ignore = child_dev desc = _("System") if self.hw_vendor: desc += ": %s" % self.hw_vendor if self.hw_version: desc += " %s" % self.hw_version return desc class NetDevice(NodeDevice): def __init__(self, node): NodeDevice.__init__(self, node) self.interface = None self.address = None self.capability_type = None self.parseXML(self._getCapabilityNode(node)) def parseXML(self, node): value_map = { "interface" : "interface", "address" : "address", } child = node.children while child: if child.name == "capability": self.capability_type = child.prop("type") else: self._parseValueHelper(child, value_map) child = child.next def pretty_name(self, child_dev=None): ignore = child_dev desc = self.name if self.interface: desc = _("Interface %s") % self.interface return desc class PCIDevice(NodeDevice): def __init__(self, node): NodeDevice.__init__(self, node) self.domain = None self.bus = None self.slot = None self.function = None self.product_id = None self.product_name = None self.vendor_id = None self.vendor_name = None self.parseXML(self._getCapabilityNode(node)) def parseXML(self, node): val_map = { "domain" : "domain", "bus" : "bus", "slot" : "slot", "function" : "function" } child = node.children while child: if child.name == "vendor": self.vendor_name = child.content self.vendor_id = child.prop("id") elif child.name == "product": self.product_name = child.content self.product_id = child.prop("id") else: self._parseValueHelper(child, val_map) child = child.next def pretty_name(self, child_dev=None): devstr = "%.2X:%.2X:%X" % (int(self.bus), int(self.slot), int(self.function)) if child_dev: desc = "%s %s (%s)" % (devstr, child_dev.pretty_name(), str(self.product_name)) else: desc = "%s %s" % (devstr, str(self.product_name)) return desc class USBDevice(NodeDevice): def __init__(self, node): NodeDevice.__init__(self, node) self.bus = None self.device = None self.product_id = None self.product_name = None self.vendor_id = None self.vendor_name = None self.parseXML(self._getCapabilityNode(node)) def parseXML(self, node): val_map = { "bus": "bus", "device": "device"} child = node.children while child: if child.name == "vendor": self.vendor_name = child.content self.vendor_id = child.prop("id") elif child.name == "product": self.product_name = child.content self.product_id = child.prop("id") else: self._parseValueHelper(child, val_map) child = child.next def pretty_name(self, child_dev=None): ignore = child_dev devstr = "%.3d:%.3d" % (int(self.bus), int(self.device)) desc = "%s %s %s" % (devstr, str(self.vendor_name), str(self.product_name)) return desc class StorageDevice(NodeDevice): def __init__(self, node): NodeDevice.__init__(self, node) self.block = None self.bus = None # FIXME: Map this to virtinst.device? self.drive_type = None self.size = 0 self.model = None self.vendor = None self.removable = False self.media_available = False self.media_size = 0 self.hotpluggable = False self.parseXML(self._getCapabilityNode(node)) def parseXML(self, node): val_map = { "block" : "block", "bus" : "bus", "drive_type" : "drive_type", "model" : "model", "vendor" : "vendor"} child = node.children while child: if child.name == "size": self.size = int(child.content) elif child.name == "capability": captype = child.prop("type") if captype == "hotpluggable": self.hotpluggable = True elif captype == "removable": self.removable = True rmchild = child.children while rmchild: if rmchild.name == "media_available": self.media_available = bool(int(rmchild.content)) elif rmchild.name == "media_size": self.media_size = int(rmchild.content) rmchild = rmchild.next else: self._parseValueHelper(child, val_map) child = child.next def pretty_name(self, child_dev=None): ignore = child_dev desc = "" if self.drive_type: desc = self.drive_type if self.block: desc = ": ".join((desc, self.block)) elif self.model: desc = ": ".join((desc, self.model)) else: desc = ": ".join((desc, self.name)) return desc class USBBus(NodeDevice): def __init__(self, node): NodeDevice.__init__(self, node) self.number = None self.classval = None self.subclass = None self.protocol = None self.parseXML(self._getCapabilityNode(node)) def parseXML(self, node): val_map = { "number" : "number", "class" : "classval", "subclass" : "subclass", "protocol" : "protocol" } self._parseHelper(node, val_map) def pretty_name(self, child_dev=None): ignore = child_dev return self.name class SCSIDevice(NodeDevice): def __init__(self, node): NodeDevice.__init__(self, node) self.host = None self.bus = None self.target = None self.lun = None self.disk = None self.parseXML(self._getCapabilityNode(node)) def parseXML(self, node): val_map = { "host" : "host", "bus" : "bus", "target": "target", "lun" : "lun", "type" : "type"} self._parseHelper(node, val_map) def pretty_name(self, child_dev=None): ignore = child_dev return self.name class SCSIBus(NodeDevice): def __init__(self, node): NodeDevice.__init__(self, node) self.host = None self.parseXML(self._getCapabilityNode(node)) def parseXML(self, node): val_map = { "host" : "host" } self._parseHelper(node, val_map) def pretty_name(self, child_dev=None): ignore = child_dev return self.name def is_nodedev_capable(conn): """ Check if the passed libvirt connection supports host device routines @param conn: Connection to check @type conn: libvirt.virConnect @rtype: C{bool} """ if not conn: return False if not isinstance(conn, libvirt.virConnect): raise ValueError(_("'conn' must be a virConnect instance.")) if dir(libvirt).count("virNodeDevice") == 0: # Local libvirt doesn't support it return False try: conn.listDevices(None, 0) return True except Exception, e: if (e.get_error_code() == libvirt.VIR_ERR_RPC or e.get_error_code() == libvirt.VIR_ERR_NO_SUPPORT): return False return True def is_pci_detach_capable(conn): """ Check if the passed libvirt connection support pci device Detach/Reset @param conn: Connection to check @type conn: libvirt.virConnect @rtype: C{bool} """ if not conn: return False if not isinstance(conn, libvirt.virConnect): raise ValueError(_("'conn' must be a virConnect instance.")) if dir(libvirt).count("virNodeDeviceDettach") == 0: return False return True def lookupNodeName(conn, name): """ Convert the passed libvirt node device name to a NodeDevice instance, with proper error reporting. @param conn: libvirt.virConnect instance to perform the lookup on @param name: libvirt node device name to lookup @rtype: L{NodeDevice} instance """ if not is_nodedev_capable(conn): raise ValueError(_("Connection does not support host device " "enumeration.")) nodedev = conn.nodeDeviceLookupByName(name) xml = nodedev.XMLDesc(0) return parse(xml) def parse(xml): """ Convert the passed libvirt node device xml into a NodeDevice object @param xml: libvirt node device xml @type xml: C{str} @returns: L{NodeDevice} instance """ class ErrorHandler: def __init__(self): self.msg = "" def handler(self, ignore, s): self.msg += s error = ErrorHandler() libxml2.registerErrorHandler(error.handler, None) try: # try/except/finally is only available in python-2.5 try: doc = libxml2.readMemory(xml, len(xml), None, None, libxml2.XML_PARSE_NOBLANKS) except (libxml2.parserError, libxml2.treeError), e: raise ValueError("%s\n%s" % (e, error.msg)) finally: libxml2.registerErrorHandler(None, None) try: root = doc.getRootElement() if root.name != "device": raise ValueError("Root element is not 'device'") t = _findNodeType(root) devclass = _typeToDeviceClass(t) device = devclass(root) finally: doc.freeDoc() return device def _findNodeType(node): child = node.children while child: if child.name == "capability": return child.prop("type") child = child.next return None def _typeToDeviceClass(t): if t == CAPABILITY_TYPE_SYSTEM: return SystemDevice elif t == CAPABILITY_TYPE_NET: return NetDevice elif t == CAPABILITY_TYPE_PCI: return PCIDevice elif t == CAPABILITY_TYPE_USBDEV: return USBDevice elif t == CAPABILITY_TYPE_USBBUS: return USBBus elif t == CAPABILITY_TYPE_STORAGE: return StorageDevice elif t == CAPABILITY_TYPE_SCSIBUS: return SCSIBus elif t == CAPABILITY_TYPE_SCSIDEV: return SCSIDevice raise ValueError(_("Unknown host device capability '%s'.") % t) 0707010002b5b7000081a40000000000000002000000014b136d1000006e10000000b600010006ffffffffffffffff0000004100000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.pycm mKc@sdkZdkZdkZdkZdkZdkZdkZdklZdkl Z dZ e dZ defdYZdefdYZdS( N(s VirtualDevice(s _virtinstcCsb|id}y5tiddddt||g}|djSWntj o t SnXdS(Nt/s /usr/sbin/zfstcreates-ps-Vi( tpathtlstriptzvolt subprocesstcalltstrtsizetrctOSErrortFalse(RRR R((t`/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/VirtualDisk.pyt _zvol_create s 'c Csd}tii|}||jp| o|d}n |d}y>tiddddd|d t ||g }|d jSWnt j o t SnXdS( Ntraws:fixeds:sparses/usr/sbin/vdiskadms-utxvmRs-ts-si(t force_fixedtosRt expandusertkindtsparset_typeRRRRR R R (RRRRRRR ((R t _vdisk_create)s 0t VirtualDiskcBs}tZdZdZdZdZeeegZdZdZdZ dZ dZ d Z d Z d Zd Zeee e e e e eeg Zd ZdZdZeeegZdZdZdZeeegZdZdZeegZeeeeeeeeeeeeeeeeedZdZ dZ!edZ"e#e!e"Z$dZ%edZ&e#e%e&Z'dZ(edZ)e#e(e)Z*dZ+edZ,e#e+e,Z-dZ.dZ/e#e.e/Z0d Z1d!Z2e#e1e2Z3d"Z4ed#Z5e#e4e5Z6d$Z7ed%Z8e#e7e8Z9d&Z:ed'Z;e#e:e;Z<d(Z=ed)Z>e#e=e>Z?d*Z@ed+ZAe#e@eAZBd,ZCed-ZDe#eCeDZEd.ZFed/ZGe#eFeGZHed0ZId1ZJd2ZKd3ZLd4ZMd5ZNd6ZOd7ZPed8ZQed9ZRd:ZSed;ZTd<ZUd=ZVRS(>s Builds a libvirt domain disk xml description The VirtualDisk class is used for building libvirt domain xml descriptions for disk devices. If creating a disk object from an existing local block device or file, a path is all that should be required. If you want to create a local file, a size also needs to be specified. The remote case is a bit more complex. The options are: 1. A libvirt virStorageVol instance (passed as 'volObject') for an existing storage volume. 2. A virtinst L{StorageVolume} instance for creating a volume (passed as 'volInstall'). 3. An active connection ('conn') and a path to a storage volume on that connection. 4. An active connection and a tuple of the form ("poolname", "volumename") 5. An active connection and a path. The base of the path must point to the target path for an active pool. For cases 3 and 4, the lookup will be performed, and 'vol_object' will be set to the returned virStorageVol. For the last case, 'volInstall' will be populated for a StorageVolume instance. All the above cases also work on a local connection as well, the only difference being that option 3 won't neccessarily error out if the volume isn't found. __init__ and setting all properties performs lots of validation, and will throw ValueError's if problems are found. tfiletphyttaptaiotqcowtvmdktvdisktiscsiRtzpooltnpivtsantnonet writethrought writebacktdisktcdromtfloppytblockcCsti|d| d|_d|_d|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_||_||_||_d|_||_|i|dt|i| dt|i|dt|i|dt|i |dt|i"|dt|i$| dt|i&| dt|i(|dt|i*|dt|i,|dt| o|i/| n|i0dS(s @param path: filesystem path to the disk image. @type path: C{str} @param size: size of local file to create in gigabytes @type size: C{int} or C{long} or C{float} @param transient: whether to keep disk around after guest install @type transient: C{bool} @param type: disk media type (file, block, ...) @type type: C{str} @param device: Emulated device type (disk, cdrom, floppy, ...) @type device: member of devices @param driverName: name of driver @type driverName: member of driver_names @param driverType: type of driver @type driverType: member of driver_types @param readOnly: Whether emulated disk is read only @type readOnly: C{bool} @param sparse: Create file as a sparse file @type sparse: C{bool} @param conn: Connection disk is being installed on @type conn: libvirt.virConnect @param volObject: libvirt storage volume object to use @type volObject: libvirt.virStorageVol @param volInstall: StorageVolume instance to build for new storage @type volInstall: L{StorageVolume} @param volName: Existing StorageVolume lookup information, (parent pool name, volume name) @type volName: C{tuple} of (C{str}, C{str}) @param bus: Emulated bus type (ide, scsi, virtio, ...) @type bus: C{str} @param shareable: If disk can be shared among VMs @type shareable: C{bool} @param driverCache: Disk cache mode (none, writethrough, writeback) @type driverCache: member of cache_types @param format: driver-specific format to use during create @type format: C{str} tconntvalidateN(1t VirtualDevicet__init__tselfR*tNonet_patht_sizeRt_devicet_sparset _readOnlyt _vol_objectt _vol_installt_bust _shareablet _driver_cachet transientt driverNamet _driverNamet driverTypet _driverTypettargettformatt set_read_onlytreadOnlyR t set_sparseRtset_typettypet set_devicetdevicet _set_pathRt _set_sizeRt_set_vol_objectt volObjectt_set_vol_installt volInstallt_set_bustbust_set_shareablet shareablet_set_driver_cachet driverCachetvolNamet_VirtualDisk__lookup_vol_namet_VirtualDisk__validate_params(R.RRR:RERGR;R=RBRR*RKRMRTRORQRSR@((R R-zs@)                cCsd|i|ifS(sM prints a simple string representation for the disk instance s%s:%sN(R.RER(R.((R t__repr__scCs|iS(N(R.R0(R.((R t _get_pathscCsJ|dj o&|i|dtii|}n|id||dS(NRR0( tvalR/R.t _check_strRRtabspatht_VirtualDisk__validate_wrapperR+(R.RYR+((R RHs cCs|iS(N(R.R1(R.((R t _get_sizescCsd|dj o@t|tttgjp |djottdqMn|i d||dS(Nis''size' must be a number greater than 0.R1( RYR/REtinttfloattlongt ValueErrort_R.R\R+(R.RYR+((R RIs )cCs|iS(N(R.R(R.((R tget_typescCs_|dj o;|i|d||ijottd|qHn|id||dS(NREsUnknown storage type '%s'R( RYR/R.RZttypesRaRbR\R+(R.RYR+((R RDs  cCs|iS(N(R.R2(R.((R t get_devicescCsN|i|d||ijottd|n|id||dS(NRGsUnknown device type '%s'R2(R.RZRYtdevicesRaRbR\R+(R.RYR+((R RFscCs|iS(N(R.R<(R.((R tget_driver_namescCs ||_dS(N(RYR.R<(R.RY((R tset_driver_namescCs|iS(N(R.R>(R.((R tget_driver_typescCs ||_dS(N(RYR.R>(R.RY((R tset_driver_typescCs|iS(N(R.R3(R.((R t get_sparsescCs'|i|d|id||dS(NRR3(R.t _check_boolRYR\R+(R.RYR+((R RCscCs|iS(N(R.R4(R.((R t get_read_only scCs'|i|d|id||dS(Nt read_onlyR4(R.RlRYR\R+(R.RYR+((R RAscCs|iS(N(R.R5(R.((R t_get_vol_objectscCsK|dj o't|ti ottdn|id||dS(Ns+vol_object must be a virStorageVol instanceR5( RYR/t isinstancetlibvirtt virStorageVolRaRbR.R\R+(R.RYR+((R RJs!cCs|iS(N(R.R6(R.((R t_get_vol_installscCsK|dj o't|ti ottdn|id||dS(Ns.vol_install must be a StorageVolume instance.R6( RYR/RptStoraget StorageVolumeRaRbR.R\R+(R.RYR+((R RLs!cCs|iS(N(R.R7(R.((R t_get_bus$scCs8|dj o|i|dn|id||dS(NROR7(RYR/R.RZR\R+(R.RYR+((R RN&s cCs|iS(N(R.R8(R.((R t_get_shareable,scCs'|i|d|id||dS(NRQR8(R.RlRYR\R+(R.RYR+((R RP.scCs|iS(N(R.R9(R.((R t_get_driver_cache3scCs_|dj o;|i|d||ijottd|qHn|id||dS(NtcachesUnknown cache mode '%s'R9( RYR/R.RZt cache_typesRaRbR\R+(R.RYR+((R RR5s  cCsmyt||}Wn |}nXt||||o/y|iWqit|||qiXndS(N(tgetattrR.tvarnametorigtnewvaltsetattrR+RV(R.R|R~R+R}((R t__validate_wrapperAs cCs|odSn|ioX|ioNti|iidd}yt|ddd}Wqd}qXnE|i djo d}n+ti |i \}}|ddd}||i jo(tid||i|dtndS(s@ Fill in 'size' attribute for existing storage. Nis/volume/capacityf1024.0s)Setting size for existing storage to '%s'R+(tcreating_storageR.t_VirtualDisk__storage_specifiedt vol_objectt_utilt get_xml_pathtXMLDesctnewsizeR_RR/t stat_disktignoreRtloggingtdebugRIR (R.RRR((R t __set_sizeNs"  cCsd}|io`|iid}|tijo |i}q:|ti jo |i }q:t t dn|i o0t|i tio |i}q:|i }n|io|i|ijo |i }n.ti|ido |i}n |i }ti|i|io|i|_|i|_q:n|idjotid|n4||ijo#t t d|i|fn|i|dtdS(sF Detect disk 'type' () from passed storage parameters isUnknown storage volume type.sDetected storage as type '%s's:Passed type '%s' does not match detected storage type '%s'R+N(R/tdtypeR.RtinfottRqtVIR_STORAGE_VOL_FILEt TYPE_FILEtVIR_STORAGE_VOL_BLOCKt TYPE_BLOCKRaRbt vol_installRpRtt FileVolumeRR<t DRIVER_PHYRRtis_vdiskt DRIVER_TAPtDRIVER_TAP_VDISKR>RERRRDR (R.RR((R t__set_dev_typehs6           #cCs)t|tj pEt|djp2t|dt|dj o tj nottdn|ipttdnt i |ipttdny:|ii |d}|i |i|ddtWn1tj o%}ttdt|nXd S( sQ lookup volume via tuple passed via __init__'s volName parameter iiis;volName must be a tuple of the form ('poolname', 'volname')s''volName' requires a passed connection.s+Connection does not support storage lookup.R+s!Couldn't lookup volume object: %sN(REt name_tuplettupletlenRRaRbR.R*Rtis_storage_capabletstoragePoolLookupByNametpoolRJtstorageVolLookupByNameR t Exceptionte(R.RRR((R t__lookup_vol_namesX cCs|idjp |idjS(s| Return bool representing if managed storage parameters have been explicitly specified or filled in N(R.RR/R(R.((R t__storage_specifiedsc Csd}d}ti|itii |i}|o|i dt i jo d}ny|ii|i}Wqtj oj}y=y|idWnd}nX|ii|i}Wqtj o}t|}qXqXn|p|o|idjottd|intidtii |i|itii|iftiid|}|iddd}|io d}nd}|dtii|id|d|d |}|i!|d t"q|i#ot|p8td hd |i<d tii |i<}n&tdhd |i<d|<}t|qn|i%|d t"dS(sf Determine if we can use libvirt storage apis to create or lookup 'self.path' is8Size must be specified for non existent volume path '%s's8Path '%s' is target for pool '%s'. Creating volume '%s'.t pool_objectitnametcapacityt allocationRR+sOCannot use storage '%(path)s': '%(rootdir)s' is not managed on the remote host.Rtrootdirs$Cannot use storage %(path)s: %(err)sterrN(&R/tvoltverrRtlookup_pool_by_pathR.R*RRtdirnameRRRqtVIR_STORAGE_POOL_RUNNINGtstorageVolLookupByPathRRtrefreshRRRaRbRRRtbasenameRtRutget_volume_for_pooltvolclasstcapRtallocRLR t _is_remoteRRJ( R.RRRRRRRR((R t__check_if_path_managedsN  >   8%cCs=d }|io|ii}n>|io3ti|iii ddd|ii }n|o4||ijo$t i d|i |dtn|ioP|iiddd}|i|jo$t i d|i|dtqn|io:|io0|iidjot i dd|i_nd S( sg Sync some parameters between storage objects and the older VirtualDisk fields is/pool/target/pathRs8Overwriting 'path' with value from StorageVolume object.R+f1024.0s7Overwriting 'size' with value from StorageVolume objects-Setting vol_install allocation to 0 (sparse).N(R/tnewpathR.RRRRRRRRRRRHR RRRRIRR(R.RR((R t __sync_paramss$     ' cCst}|ioti|i}n| o |iottdn|o,|i d j o|i o|i n|i |i d joH|i|ijo-|i|ijottd|intSn|i p |i d j}|o |ip|i oti i|i  }|i||io| ottdn|pj|pQti i|i o7ti|i |i ottd|i qn|itSn|i|ijp|i|ijottd|in| ou|i oj|i|ijottdn|i|i dt|i!d jottd|i qn |i|i"}|d ot|d n!|d ot$i%|d nd S( so function to validate all the complex interaction between the various disk parameters. s*Connection doesn't support remote storage.s Device type '%s' requires a paths>Must specify libvirt managed storage if on a remote connections9The path '%s' must be a file or a device, not a directorys$Cannot create storage for %s device.s#Local block device path must exist.R+s+size is required for non-existent disk '%s'iiN(&R tstorage_capableR.R*RRRRaRbRR/Rt#_VirtualDisk__check_if_path_managedt_VirtualDisk__sync_paramsRGt DEVICE_FLOPPYt DEVICE_CDROMtTruetmanaged_storageRRtexistst create_mediat_VirtualDisk__set_sizetisdirRR<t_VirtualDisk__set_dev_typeR>RERRDRRtis_size_conflicttretRtwarn(R.RRRR((R t__validate_paramssL % &1 0! &    cCsJ|iodSn5|io*|i|iid|dtdSn|i|ijom|i oc|i |i joLt |i ddd}t|i|pttd|iqqFn|itijom|idj o]tii|i oFt |i ddd}|o/|id|idt |dtd nti|i|io|id |idjo d |_nt|i||i|ipttd |in|i|_|i |_ |i!|i dSnd}zyti#|iti$ti%B}|io/ti&|||o|i|i qnld d d }xZt(dt |i dD]<}ti*|||o|it |ddqqWWn7t+j o+}ttd|it-|fnXWd|dj oti.|n|o|i!|nXndS(s Build storage (if required) If storage doesn't exist (a non-existent file 'path', or 'vol_install' was specified), we create it. @param progresscb: progress meter @type progresscb: instanceof urlgrabber.BaseMeter NtmeterR+lsError creating zvol %stfilenameRttextsCreating storage file...iRsError creating vdisk %stisError creating diskimage %s: %s(/R.RRRJtinstallt progresscbR R<RR>tDRIVER_PHY_ZVOLR`Rt size_bytesR Rt RuntimeErrorRbRERRR/RRtstartRRtupdateR@RRRRtendtfdtopentO_WRONLYtO_CREATt ftruncatetbuftrangetitwriteR RRtclose(R.RRRRRR((R tsetupfsb    ":      '+ c Cs&d}|itijo d}n|io |i}n|pttdnd}|i o|i i }n|i o |i }n|ot i |}nd|i|if}|i}| o|io d|_n|idj old}|idj od|i}nd}|idj od|i}n|d |i||f7}n|dj o|d ||f7}nd} |idj od |i} n|d || f7}|i}|i|ijo t}n|io|d 7}n|o|d7}n|d7}|S(s @param disknode: device name in host (xvda, hdb, etc.). self.target takes precedence. @type disknode: C{str} Rtdevs&'disknode' or self.target must be set!s! tqemuts type='%s's cache='%s's s s bus='%s's s s s N(ttypeattrR.RERRR?tdisknodeRaRbR/RRRt xml_escapeRGRt driver_nametdnamet driver_cachetdtypexmlt driver_typet dcachexmltbus_xmlRORntroRRRQ( R.RRRRRRRRR((R tget_xml_configsT             cCsP|io|iiSn|ipD|idjp4|i p)tii|ip|i |i jot dfSnt }d}titii|i}|ti|ti}t|iddd}||joe|iotd}nt}td}|o.|td|dd|ddf7}qFn||fS(sq reports if disk size conflicts with available space returns a two element tuple: 1. first element is True if fatal conflict occurs 2. second element is a string description of the conflict or None Non fatal conflicts (sparse disk exceeds available space) will return (False, "description of collision") lskThe filesystem will not have enough free space to fully allocate the sparse file when the guest is running.s2There is not enough free space to create the disk.s %d M requested > %d M availableiN(R.RRRRR/RRRRERR RtmsgtstatvfsRtvfstF_FRSIZEtF_BAVAILtavailR`tneedRRbR(R.RRRRR((R Rs$  N   2csti|\} }| |} |io|iin |ipt Snd} d}g}xZ| D]R}|id}ti|d| }|o!||7}|i|iqsqsWt } |djo t} n|o |} n| S(s check if specified storage is in use by any other VMs on passed connection. @param conn: connection to check for collisions on @type conn: libvirt.virConnect @param return_names: Whether or not to return a list of VM names using the same storage (default = False) @type return_names: C{bool} @return: True if a collision, False otherwise (list of names if return_names passed) @rtype: C{bool} cs8d}||id7}||id7}|S(Nis-count(/domain/devices/disk/source[@dev='%s'])s.count(/domain/devices/disk/source[@file='%s'])(tctctxt xpathEvalR(RR(R(R tcount_cb%sitfuncN(Rtfetch_all_guestsR*tactivetinactivetvmsR.RRR RtcounttnamestvmRtxmlRttmpcounttappendRRRt return_names(R.R*RRRRRRRRRRRR((RR tis_conflict_disk s0        cCs|idjodSn|idjp|idjodSn`|idjodSnH|id jodSn0|id jp|i|ijodSndSdS(s Returns the suggested disk target prefix (hd, xvd, sd ...) from the passed parameters. @returns: str prefix, or None if no reasonable guess can be made tvirtiotvditscsitusbtsdtxentxvdtidethdiR(RiN(R i(Ri(Ri(Ri(sfdi(NN(R.RORGRR/(R.((R t_get_target_type=s #cCsWdg}|i\}}|djottdn|i|i joD|djo7d|jod|_ |i Snttdnxct |D]U}d|td|f}||joqn||jo||_ |i SqqWx?|D]7}|i|o!||jo||_ |i SqqWttd|dS( s Generate target device ('hda', 'sdb', etc..) for disk, excluding any targets in list 'skip_targets'. Sets self.target, and returns the generated value @param used_targets: list of targets to exclude @type used_targets: C{list} @raise ValueError: can't determine target type, no targets available @returns generated target @rtype C{str} thdcs!Cannot determine device bus/type.Rs,IDE CDROM must use 'hdc', but target in use.s%s%ctas$No more space for disks of type '%s'N(texcept_targetsR.RtprefixtmaxnodeR/RaRbRGRt skip_targetsR?RRtordtgen_tRt startswith(R.RRRRRRR((R tgenerate_targetPs0            (Wt__name__t __module__t__doc__t DRIVER_FILERRt driver_namestDRIVER_TAP_RAWtDRIVER_TAP_QCOWtDRIVER_TAP_VMDKRtDRIVER_PHY_ISCSIRtDRIVER_PHY_ZPOOLtDRIVER_PHY_NPIVtDRIVER_PHY_SANt driver_typestCACHE_MODE_NONEtCACHE_MODE_WRITETHROUGHtCACHE_MODE_WRITEBACKRzt DEVICE_DISKRRRfRRRdR/R RR-RWRXRHtpropertyRR]RIRRcRDREReRFRGRgRhRRiRjRRkRCRRmRARnRoRJRRsRLRRvRNRORwRPRQRxRRRR\RRRURRRRVRRRR RR(((R R7s ! t j o}tdG|GHq>q>Xq>W|S(s8catches yes_or_no errors and ensures a valid bool returns+Forcing return value of True to prompt '%s'siPrompting disabled, but yes/no was requested. Try --force to force 'yes' for such prompts. Prompt was: %sisERROR: N(R[RRGRnR^RQRRR]RcRtinpRqtresRpR2(R]RsRrR2((R tprompt_for_yes_or_nos    cCsT|djottdny ||_Wntj o}t|nXdS(Ns+A name is required for the virtual machine.(tnameRRQRRtguestRpR2(RuRvR2((R tget_names   cCsy|djottdn|tjottdtny ||_Wntj o}t|nXdS(Ns2Memory amount is required for the virtual machine.s*Installs currently require %d megs of RAM.(tmemoryRRQRRtMIN_RAMRvRpR2(RxRvR2((R t get_memorys   cCs>|o3y ||_Wq:tj o}t|q:XndS(N(tuuidRvRpR2RQ(R{RvR2((R tget_uuids  cCs|ok|i}|d|d|d|d}||joqrttd||fp tqrn|dj o3y ||_Wqt j o}t |qXndS(NiiiisYou have asked for more virtual CPUs (%d) than there are physical CPUs (%d) on the host. This will work, but performance will be poor. Are you sure? (yes or no)(t check_cputconntgetInfothostinfotcpu_numtvcpusRtRRRSRRvRpR2RQ(RR}RvR~R2RR((R t get_vcpuss "   c Cs|o|djo ||_n|djoti|i}|iidjot i ddSn|iii }t |djot i ddSn|idt |}d}|d}xutt |D]a} || |joJt || idjo0|djp|| ||jo | }q>qqW|djot i ddSnd }xC||iD]4} |d jo|d 7}n|t| i7}qxWt i d |||_ndS( Ntautos0No topology section in caps xml. Skipping cpusetis2Capabilities only show <= 1 cell. Not NUMA capableiiisICould not find any usable NUMA cell/cpu combinations. Not setting cpuset.Rt,sAuto cpuset is: %s(tcpusetRvtCapabilitiesParsertparseR~tgetCapabilitiestcapsthostttopologyRRRGtcellstlentgetCellsFreeMemorytcell_memtcell_idtmemtrangetitcpustcpustrtcputstrtid( RRRvR~RRRRRRR((R t get_cpusets>     +"    c CsQd}d}d}d}d}h} x|od}d}d} |i ddjo|i dd\}}n|i ddjo,|i dd\}} | | |i sst:Rs6Need to pass equal numbers of networks & mac addresses(RtmacstbridgestnetworksRQRRRtoldtnewRiRR RERPtmapRRTRURVtPRIV_CREATE_NETWORKR~tgetURIt_utiltdefault_networkRRRRR( R~RRRRRRRiRRR((R tdigest_networksSsR       &"!"! cCs6|o|p|o|p|o|ottdn|p |p|pDdtiijoti dt }qti dt }n|dj od|_ dSn|dj otdti|_ dSn|dj otdti|_ n|o||i _n|o||i _ndS(Ns8Can't specify more than one of VNC, SDL, or --nographicstDISPLAYs+DISPLAY is set: graphics defaulting to VNC.s-DISPLAY is not set: defaulting to nographics.R"(tvnct nographicstsdlRpRRR*tenvirontkeysRRGRnRRvt graphics_devtVirtualGraphicstTYPE_SDLtTYPE_VNCtvncporttporttkeymap(RRRRRRv((R t get_graphicss(*        cCs(|o|iitddndS(Ntmodeltes1370(tsoundRvt sound_devsRt VirtualAudio(RRv((R t get_soundscCsR|pdSnx<|D]4}tiid|id|}|ii|qWdS(NR~Ru( thostdevstdevnametvirtinsttVirtualHostDevicetdevice_from_nodeRvR~tdevR(RRvRR((R t get_hostdevss cCsDt|djottd|nt|i|i |dS(Nis%s option requires an argument( RtvaluetOptionValueErrorRRtopt_strtsetattrtparsertvaluestoptiontdest(RRRR((R tcheck_before_storescCsMt|djottd|n|ii|i gi |dS(Nis%s option requires an argument( RRRRRRRRt ensure_valueRRR(RRRR((R tcheck_before_appends(/R*R Rtlogging.handlersRtoptparseRt OptionParserRRRRRRRRTt _virtinstRRRyRoR[RnR^RRKRQRSRZR\R_RRcRqRtRwRzR|RRRRRRRRRR('RRRZRyRQRRqRzRSRRRRtRRRTRRRRRRRR RRRRR|RRRKRR_RwRRRcR*R\((R t?sF      %  1         $ 7  @   0707010002b5c6000081a40000000000000002000000014b136d0f000022c1000000b600010006ffffffffffffffff0000003b00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/osdict.py# # List of OS Specific data # # Copyright 2006-2008 Red Hat, Inc. # Jeremy Katz # # 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. """ Default values for OS_TYPES keys. Can be overwritten at os_type or variant level """ DEFAULTS = { \ "acpi": True, "apic": True, "clock": "utc", "continue": False, "distro": None, "label": None, "pv_cdrom_install": False, "devices" : { # "devname" : { "attribute" : [( ["applicable", "hv-type", list"], # "recommended value for hv-types" ),]}, "input" : { "type" : [ (["all"], "mouse") ], "bus" : [ (["all"], "ps2") ] }, "disk" : { "bus" : [ (["all"], None) ] }, "net" : { "model": [ (["all"], None) ] }, } } def sort_helper(tosort): """Helps properly sorting os dictionary entires""" key_mappings = {} keys = [] retlist = [] for key in tosort.keys(): if tosort[key].get("skip"): continue sortby = tosort[key].get("sortby") if not sortby: sortby = key key_mappings[sortby] = key keys.append(sortby) keys.sort() for key in keys: retlist.append(key_mappings[key]) return retlist # NOTE: keep variant keys using only lowercase so we can do case # insensitive checks on user passed input OS_TYPES = {\ "linux": { \ "label": "Linux", "variants": { \ "rhel2.1": { "label": "Red Hat Enterprise Linux 2.1", "distro": "rhel" }, "rhel3": { "label": "Red Hat Enterprise Linux 3", "distro": "rhel" }, "rhel4": { "label": "Red Hat Enterprise Linux 4", "distro": "rhel" }, "rhel5": { "label": "Red Hat Enterprise Linux 5", "distro": "rhel" }, "fedora5": { "sortby": "fedora05", "label": "Fedora Core 5", "distro": "fedora" }, "fedora6": { "sortby": "fedora06", "label": "Fedora Core 6", "distro": "fedora" }, "fedora7": { "sortby": "fedora07", "label": "Fedora 7", "distro": "fedora" }, "fedora8": { "sortby": "fedora08", "label": "Fedora 8", "distro": "fedora" }, "fedora9": { "sortby": "fedora09", "label": "Fedora 9", "distro": "fedora", "devices" : { # Apparently F9 has selinux errors when installing # with virtio: # https://bugzilla.redhat.com/show_bug.cgi?id=470386 #"disk" : { "bus" : [ (["kvm"], "virtio") ] }, "net" : { "model" : [ (["kvm"], "virtio") ] } }}, "fedora10": { "label": "Fedora 10", "distro": "fedora", "devices" : { "disk" : { "bus" : [ (["kvm"], "virtio") ] }, "net" : { "model" : [ (["kvm"], "virtio") ] } }}, "fedora11": { "label": "Fedora 11", "distro": "fedora", "devices" : { "disk" : { "bus" : [ (["kvm"], "virtio") ] }, "net" : { "model" : [ (["kvm"], "virtio") ] }, "input" : { "type" : [ (["all"], "tablet") ], "bus" : [ (["all"], "usb"), ] }, }}, "sles10": { "label": "Suse Linux Enterprise Server", "distro": "suse" }, "debianetch": { "label": "Debian Etch", "distro": "debian" }, "debianlenny": { "label": "Debian Lenny", "distro": "debian", "devices" : { "disk" : { "bus" : [ (["kvm"], "virtio") ] }, "net" : { "model" : [ (["kvm"], "virtio") ] } }}, "ubuntuhardy": { "label": "Ubuntu 8.04 LTS (Hardy Heron)", "distro": "ubuntu", "devices" : { "net" : { "model" : [ (["kvm"], "virtio") ] } }}, "ubuntuintrepid": { "label": "Ubuntu 8.10 (Intrepid Ibex)", "distro": "ubuntu", "devices" : { "net" : { "model" : [ (["kvm"], "virtio") ] } }}, "ubuntujaunty": { "label": "Ubuntu 9.04 (Jaunty Jackalope)", "distro": "ubuntu", "devices" : { "net" : { "model" : [ (["kvm"], "virtio") ] }, "disk" : { "bus" : [ (["kvm"], "virtio") ] } }}, "generic24": { "label": "Generic 2.4.x kernel" }, "generic26": { "label": "Generic 2.6.x kernel" }, "virtio26": { "sortby": "genericvirtio26", "label": "Generic 2.6.25 or later kernel with virtio", "devices" : { "disk" : { "bus" : [ (["kvm"], "virtio") ] }, "net" : { "model" : [ (["kvm"], "virtio") ] } }}, }, }, "windows": { \ "label": "Windows", "clock": "localtime", "continue": True, "devices" : { "input" : { "type" : [ (["all"], "tablet") ], "bus" : [ (["all"], "usb"), ] }, }, "variants": { \ "winxp":{ "label": "Microsoft Windows XP (x86)", "acpi": False, "apic": False }, "winxp64":{ "label": "Microsoft Windows XP (x86_64)" }, "win2k": { "label": "Microsoft Windows 2000", "acpi": False, "apic": False }, "win2k3": { "label": "Microsoft Windows 2003" }, "win2k8": { "label": "Microsoft Windows 2008" }, "vista": { "label": "Microsoft Windows Vista" }, }, }, "solaris": { "label": "Solaris", "clock": "localtime", "pv_cdrom_install": True, "variants": { "solaris9": { "label": "Sun Solaris 9", }, "solaris10": { "label": "Sun Solaris 10", "devices" : { "input" : { "type" : [ (["all"], "tablet") ], "bus" : [ (["all"], "usb"), ] } }, }, "opensolaris": { "label": "Sun OpenSolaris", "devices" : { "input" : { "type" : [ (["all"], "tablet") ], "bus" : [ (["all"], "usb"), ] } }, }, }, }, "unix": { "label": "UNIX", "variants": { \ "freebsd6": { "label": "Free BSD 6.x" , # http://www.nabble.com/Re%3A-Qemu%3A-bridging-on-FreeBSD-7.0-STABLE-p15919603.html "devices" : { "net" : { "model" : [ (["all"], "ne2k_pci") ] } }}, "freebsd7": { "label": "Free BSD 7.x" , "devices" : { "net" : { "model" : [ (["all"], "ne2k_pci") ] } }}, "openbsd4": { "label": "Open BSD 4.x" , # http://calamari.reverse-dns.net:980/cgi-bin/moin.cgi/OpenbsdOnQemu # https://www.redhat.com/archives/et-mgmt-tools/2008-June/msg00018.html "devices" : { "net" : { "model" : [ (["all"], "pcnet") ] } }}, }, }, "other": { \ "label": "Other", "variants": { \ "msdos": { "label": "MS-DOS", "acpi": False, "apic": False }, "netware4": { "label": "Novell Netware 4" }, "netware5": { "label": "Novell Netware 5" }, "netware6": { "label": "Novell Netware 6", "pv_cdrom_install": True, }, "generic": { "label": "Generic" }, }, },} # Back compatibility entries solaris_compat = OS_TYPES["unix"]["variants"] solaris_compat["solaris9"] = OS_TYPES["solaris"]["variants"]["solaris9"].copy() solaris_compat["solaris9"]["skip"] = True solaris_compat["solaris10"] = OS_TYPES["solaris"]["variants"]["solaris10"].copy() solaris_compat["solaris10"]["skip"] = True 0707010002b5ba000081a40000000000000002000000014b0fbd7900001ac9000000b600010006ffffffffffffffff0000004600000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.py# # Copyright 2009 Red Hat, Inc. # Cole Robinson # # 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 VirtualDevice import NodeDeviceParser import logging from virtinst import _virtinst as _ class VirtualHostDevice(VirtualDevice.VirtualDevice): def device_from_node(conn, name=None, nodedev=None): """ Convert the passed libvirt node device name to a VirtualHostDevice instance, with proper error reporting. @param conn: libvirt.virConnect instance to perform the lookup on @param name: libvirt node device name to lookup @rtype: L{virtinst.VirtualHostDevice} instance """ if not name and not nodedev: raise ValueError(_("'name' or 'nodedev' required.")) if nodedev: nodeinst = nodedev else: nodeinst = NodeDeviceParser.lookupNodeName(conn, name) if isinstance(nodeinst, NodeDeviceParser.PCIDevice): return VirtualHostDevicePCI(conn, nodedev=nodeinst) elif isinstance(nodeinst, NodeDeviceParser.USBDevice): return VirtualHostDeviceUSB(conn, nodedev=nodeinst) elif isinstance(nodeinst, NodeDeviceParser.NetDevice): parentname = nodeinst.parent try: return VirtualHostDevice.device_from_node(conn, name=parentname) except: logging.exception("Fetching net parent device failed.") raise ValueError(_("Node device type '%s' cannot be attached to " " guest.") % nodeinst.device_type) device_from_node = staticmethod(device_from_node) def __init__(self, conn, nodedev): """ @param conn: Connection the device/guest will be installed on @type conn: libvirt.virConnect @param nodedev: Optional NodeDevice instance for device being attached to the guest @type nodedev: L{virtinst.NodeDeviceParser.NodeDevice} """ VirtualDevice.VirtualDevice.__init__(self, conn) self.mode = None self.type = None self.managed = True self._nodedev = nodedev def _get_source_xml(self): raise NotImplementedError("Must be implemented in subclass") def setup(self, conn = None): """ Perform DeviceDetach and DeviceReset calls if necessary @param conn: libvirt virConnect instance to use (defaults to devices connection) """ raise NotImplementedError def get_xml_config(self): xml = (" \n" % \ (self.mode, self.type, self.managed and "yes" or "no")) xml += " \n" xml += self._get_source_xml() xml += " \n" xml += " \n" return xml class VirtualHostDeviceUSB(VirtualHostDevice): def __init__(self, conn, nodedev=None): VirtualHostDevice.__init__(self, conn, nodedev) self.mode = "subsystem" self.type = "usb" self.vendor = None self.product = None self.bus = None self.device = None self._set_from_nodedev(self._nodedev) def _set_from_nodedev(self, nodedev): if not nodedev: return if not isinstance(nodedev, NodeDeviceParser.USBDevice): raise ValueError(_("'nodedev' must be a USBDevice instance.")) self.vendor = nodedev.vendor_id self.product = nodedev.product_id self.bus = nodedev.bus self.device = nodedev.device def _get_source_xml(self): xml = "" if self.vendor and self.product: xml += " \n" % self.vendor xml += " \n" % self.product elif self.bus and self.device: xml += "
\n" % (self.bus, self.device) else: raise RuntimeError(_("'vendor' and 'product', or 'bus' and " " 'device' are required.")) return xml def setup(self, conn = None): if not conn: conn = self.conn # No libvirt api support for USB Detach/Reset yet return class VirtualHostDevicePCI(VirtualHostDevice): def __init__(self, conn, nodedev=None): VirtualHostDevice.__init__(self, conn, nodedev) self.mode = "subsystem" self.type = "pci" self.domain = "0x0" self.bus = None self.slot = None self.function = None self._set_from_nodedev(self._nodedev) def _set_from_nodedev(self, nodedev): if not nodedev: return if not isinstance(nodedev, NodeDeviceParser.PCIDevice): raise ValueError(_("'nodedev' must be a PCIDevice instance.")) self.domain = nodedev.domain self.bus = nodedev.bus self.slot = nodedev.slot self.function = nodedev.function def _get_source_xml(self): if not (self.domain and self.bus and self.slot and self.function): raise RuntimeError(_("'domain', 'bus', 'slot', and 'function' " "must be specified.")) xml = "
\n" return xml % (self.domain, self.bus, self.slot, self.function) def setup(self, conn = None): """ Perform DeviceDetach and DeviceReset calls if necessary @param conn: libvirt virConnect instance to use (defaults to devices connection) """ if not conn: conn = self.conn if not NodeDeviceParser.is_pci_detach_capable(conn): return try: # Do this as a sanity check, so that we don't fail at domain # start time self._nodedev.deviceDetach() self._nodedev.deviceReset() except Exception, e: raise RuntimeError(_("Could not detach PCI device: %s" % str(e))) 0707010002b5c5000081a40000000000000002000000014b136d10000003ac000000b600010006ffffffffffffffff0000003e00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/keytable.pycm yKc@shdd<dd<dd<dd<dd<dd<dd<dd<dd<d d<d d <d d <d d <d d <dd<dd<dd<dd<dd<dd<dd<dd<dd<dd<dd<dd<dd<dd<dd<dd<dd<dd<d d <d!d!<d"d"<d#d#<d$d$<d%d$<d&d$<d'd'<d(d(<d)d)<d*d*<d+d+d&Z?d'Z@ee?e@ZAd(ZBeeBZCd)ZDd*ZEeeDeEZFd+ZGd,ZHeeGeHZId-ZJd.ZKeeJeKZLeMd/ZNd0ZOd1ZPd2ZQd3ZRd4ZSd5ZTd6ZUeMd7ZVd8ZWd9ZXeMeYd:ZZddeYeMeMd;Z[d<Z\eMeMd=Z]d>Z^d?Z_eYeMeMd@Z`dAZaeMdBZbdCZcdDZddEZedFZfdGZgRS(HNcCstitiS(N(tosdictt sort_helperRt _OS_TYPES(((tZ/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/Guest.pyt list_os_types+scCstiti|dS(Ntvariants(RRRRttype(R((Rtlist_os_variants/scCsti|dS(Ntlabel(RRR(R((Rtget_os_type_label3scCsti|d|dS(NRR (RRRtvariant(RR ((Rtget_os_variant_label7scCs?||_d|_d|_d|_d|_d|_d|_ d|_ d|_ d|_ t |_d|_d|_g|_g|_g|_g|_g|_g|_d|_d|_||_|idjo'tid|ti||_n|idjot t!dnt"i#|ii$|_%dS(Nis)No conn passed to Guest, opening URI '%s's7Unable to connect to hypervisor, aborting installation!(&t installertselft _installertNonet_namet_uuidt_memoryt _maxmemoryt_vcpust_cpusett _graphics_devt _consolechildt_autocftFalset _has_autocft_os_typet _os_varianttdiskstnicst sound_devsthostdevst_install_diskst _install_nicstdomaintdisknodet connectiontconntloggingtdebugt hypervisorURItlibvirttopent RuntimeErrort_tCapabilitiesParsertparsetgetCapabilitiest_caps(RRR&R*R ((Rt__init__<s8                      cCs|iS(N(RR(R((Rt get_autocflscCs|iS(N(RR(R((Rt has_autocfnscCst|tdj ottdn|ido'tii| ottdn|dj o ||_ nt |_ dS(Ntstrings3You must specify a value for autoconfiguration datat/s$autocf floppy image. "%s" not found.t( Rtvalt ValueErrorR.t startswithtostpathtexistsRRtTrueR(RR9((Rt set_autocfps$  cCs|iS(N(RR(R((Rt get_installerzscCs ||_dS(N(R9RR(RR9((Rt set_installer|scCs|iS(N(RR(R((Rtget_namescCs[titd|y|ii|Wn||_dSnXttd|dS(NRs"Guest name '%s' is already in use.( t_utilt validate_nameR.R9RR't lookupByNameRR:(RR9((Rtset_names cCs|iS(N(RR(R((Rt get_memoryscCsst|tdj p |djottdn||_|idjp|i|jo ||_ndS(Niis.Memory value must be an integer greater than 0(RR9R:R.RRRR(RR9((Rt set_memorys &  cCs|iS(N(RR(R((Rt get_maxmemoryscCsFt|tdj p |djottdn||_dS(Niis2Max Memory value must be an integer greater than 0(RR9R:R.RR(RR9((Rt set_maxmemorys&cCs|iS(N(RR(R((Rtget_uuidscCsti|}||_dS(N(RDt validate_uuidR9RR(RR9((Rtset_uuidscCs|iS(N(RR(R((Rt get_vcpusscCs|ti|i|i}t|tj p |djott dn||jott d|n||_ dS(Nis*Number of vcpus must be a postive integer.s<Number of vcpus must be no greater than %d for this vm type.( RDt get_max_vcpusRR'RtmaxvcpusR9tintR:R.R(RR9RQ((Rt set_vcpuss   cCs|iS(N(RR(R((Rt get_cpusetscCs^t|tdj pt|djottdntid|djottdnti |i }x|i dD]}|iddjo~|i d\}}t|t|jottd nt||jpt||jottd qMqt||jottd qqW||_dS( NR6iscpuset must be strings ^[0-9,-]*$s7cpuset can only contain numeric, ',', or '-' characterst,t-iscpuset contains invalid format.s.cpuset's pCPU numbers must be less than pCPUs.(RR9tlenR:R.tretmatchRRDt get_phy_cpusRR'tpcpustsplittctfindtxtyRRR(RR9R[R]R`R_((Rt set_cpusets ,&cCs|iS(N(RR(R((Rtget_graphics_devscCs ||_dS(N(R9RR(RR9((Rtset_graphics_devscCs|iS(N(RR(R((Rt get_os_typescCst|tj ottdn|i}|ii|o.|i |jodSn||_ d|_ nttd|dS(NsOS type must be a string.s-OS type '%s' does not exist in our dictionary( RR9tstrR:R.tlowerRRthas_keyRRR(RR9((Rt set_os_types   cCs|iS(N(RR(R((Rtget_os_variantscCs0t|tj ottdn|i}|ioW|i|idi |o ||_ q,ttdhd|<d|i <nx|i D]r}|i|di |oQ|i|d|id o1tid||f||_||_ dSqqWttd|dS( NsOS variant must be a string.RsJOS variant '%(var)s; does not exist in our dictionary for OS type '%(ty)s'tvarttytskips(Setting os type to '%s' for variant '%s'sUnknown OS variant '%s'(RR9ReR:R.RfRtos_typeRRgRRRtostypetgetR(R)(RR9Rn((Rtset_os_variants   , ;   cCs |idS(Ntdistro(Rt_lookup_osdict_key(R((Rt get_os_distroscCs"|idjodSn|iiS(N(RRRtkeymap(R((Rt get_keymapscCs$|idj o||i_ndS(N(RRRR9Rt(RR9((Rt set_keymapscCsI|idjohdttid|}|o ||_n|o ||_qn||_dS(NRws)Must specify whether graphics are enabledRtoptsiiiiitvnctsdls&Graphics enabled must be True or False(RzR{(RtporttgtypeRRwRttgdevRR9tdictRgR:R.ttupleRWR?tVirtualGraphicsRR(RR9RwR~RtR}R|((Rt set_graphics%sF     cCs |iiS(N(RRR(R((Rtget_typeZscCs||i_dS(N(R9RRR(RR9((Rtset_type\scCs |iiS(N(RR tarch(R((Rtget_arch`scCs||i_dS(N(R9RR R(RR9((Rtset_archbscCs |iiS(N(RRtlocation(R((Rt get_locationgscCs||i_dS(N(R9RRR(RR9((Rt set_locationiscCs |iiS(N(RRt scratchdir(R((Rtget_scratchdirnscCs |iiS(N(RRtboot(R((Rtget_bootsscCs||i_dS(N(R9RRR(RR9((Rtset_bootuscCs |iiS(N(RRt extraargs(R((Rt get_extraargszscCs||i_dS(N(R9RRR(RR9((Rt set_extraargs|scCs |iiS(N(RRR(R((Rt get_cdromscCs|djp,t|tdj pt|djottdn|idoBtii |pttdntii ||i _ n ||i _ t|i _dS(NR6isDYou must specify a valid ISO or CD-ROM location for the installationR7s(The specified media path does not exist.(R9RRRWR:R.R;R<R=R>tabspathRRRR?tcdrom(RR9((Rt set_cdroms9 cCs tdS(s=Return xml for disk devices (Must be implemented in subclass)N(tNotImplementedError(Rtinstall((Rt _get_disk_xmlscCs|id}d|S(Ntclocks(RRrR9(RR9((Rt_get_clock_xmlscCs6d}x)|iD]}ti||i}qW|S(s0Get the network config in the libvirt XML formatR8N(txmlRR#tnRDt xml_appendtget_xml_config(RRR((Rt_get_network_xmls  cCs%|idjodSn|iiS(s2Get the graphics config in the libvirt XML format.R8N(RRRR(R((Rt_get_graphics_xmlscCs tdS(sw Return a tuple of the form (devtype, bus) for the desired input device. (Must be implemented in subclass) N(R(R((Rt_get_input_devicescCs |i\}}d||fS(s2Get the input device config in libvirt XML format.s N(RRtdevtypetbus(RRR((Rt_get_input_xmlscCs6d}x)|iD]}ti||i}qW|S(s9Get the sound device configuration in libvirt XML format.R8N(RRR t sound_devRDRR(RRR((Rt_get_sound_xmls  cCs6d}x)|iD]}ti||i}qW|S(NR8(RRR!thostdevRDRR(RRR((Rt_get_hostdev_xmls  cCsd}ti||i|}ti||i}ti||i}ti||i}ti||i }ti||i }|S(NR8( RRDRRRRRRRRR(RRR((Rt_get_device_xmlscCsdS(sX Return features (pae, acpi, apic) xml (currently only releavnt for FV) R8N((R((Rt_get_features_xmlscCsd}|ii||}|pdSnti||ii||}ti||i }ti||i }|S(s<Return os, features, and clock xml (Implemented in subclass)R8N( RRR tget_install_xmlRtosxmlRRDRRR(RRRR((Rt _get_osblobs c CsB|o d}nd}|}|o t}n|i|}|pdSn|i dj od|i d}nd}|i }|p d}n|i }|p d}ndhd|i <d |i <d |<d |<d |i<d |<d|i<d|id<d|id<d|i|<d|<d|<S(s Return the full Guest xml configuration. @param install: Whether we want the 'OS install' configuration or the 'post-install' configuration. (Some Installers, like the LiveCDInstaller may not have an 'install' config.) @type install: C{bool} @param disk_boot: Whether we should boot off the harddisk, regardless of our position in the install process (this is used for 2 stage installs, where the second stage boots off the disk. You probably don't need to touch this.) @type disk_boot: C{bool} tdestroytrestarts cpuset='t'R8tunknowns %(name)s %(ramkb)s %(maxramkb)s %(uuid)s %(osblob)s destroy %(action)s %(action)s %(os_type)s %(os_variant)s %(vcpus)d %(devices)s RtnameRmt os_varianttvcpustcpusettuuidtramkbitmaxramkbtdevicestosblobtactionN(RRtosblob_installt disk_bootRRRRRRRmRRRRRtmemoryt maxmemoryR( RRRRRRRRmR((Rtget_config_xmls(      cCso|id|_|djoti}n|i|z|i|||||SWd|i iXdS(s)Do the startup of the guest installation.N(Rtvalidate_parmsRRtmetertprogresst BaseMetert_prepare_installt _do_installt consolecbt removeOldtwaittdefineRtcleanup(RRRRRR((Rt start_install,s    cCsR|id}|p t}n|tjo!|idtp t}qNn|S(NtcontinueR(RRrR9RR?R(RR9((Rtget_continue_inst<s  cCs |idt}tid||idddd|oH|i i d}|i i||_ |i i|i i|n|i i|d|_ |i djottdn|id|i|||otidn|i i|iS( NRsContinuing guest with: %stsizettextsStarting domain...is8Unable to start domain for guest, aborting installation!i(RRR?tcont_xmlR(R)RtstartRRR$tXMLDesctfinalxmlR't defineXMLtcreatet createXMLR-R.tendtconnect_consoleRRttimetsleepRFR(RRRRRRR((Rtcontinue_installHs   cCsn|i|_|i|_|i|iid|d||ii dj o|ii |ii ndS(NtguestR( RRR"RR#t _set_defaultsRtprepareRt install_diskRtappend(RR((RRis    cCsgx|iD]}|i|q Wx!|iD]}|i|iq+Wx|iD]}|iqOWdS(sEnsure that devices are setupN( RR"tdisktsetupt progresscbR#tnicR'R!R(RRRRR((Rt_create_devicesss   cCsd}y|ii|i}Wntij onX|dj o|oyW|i djo"t i d|i|i nt i d|i|i Wqtij o+} ttd|it| fqXqttd|ifnd} |i||i}|ot id||idddtd |ii|d |_|idjottd n|id t id t|i|i} | djottd n|o@|iidj o)t id||i} | |_ q)n|idt!} |iidjot id| GHdSn|o%t id| |ii$| n| o]|oVyt&i'| d Wn.t(j o"\}} t+Gd|| fGHnXt,i-dn|ii|iS(NisDestroying image %ss$Removing old definition for image %ss Could not remove old vm '%s': %ssDomain named %s already exists!sCreating guest from: %sRRsCreating domain...is=Unable to create domain for the guest, aborting installation!s.Created guest, looking to see if it is runningsgIt appears that your installation has crashed. You should be able to find more information in the logsstest:///defaultsLaunching console callbackRstest hypervisor selectedsSaving XML boot config: %sswaitpid: %s: %si(.RtvmRR'RFRR+t libvirtErrorRtIDR(tinfoRtundefineteR-R.RetchildRRRt install_xmlR)RRR$Rt_wait_for_domaintdRtgetURIRRtboot_xmlRRRR<twaitpidtOSErrorterr_notmsgt__name__RR(RRRRRRRRRRRRRR((RR|sb +       cCs|ii|S(N(RR tpost_install_check(R((RRscCstidt|i|i|_|idjott dn*|ii djott dnd}|o)tid||i}||_ n|oP|oIyti|dWqtj o"\}}td||fqXndS(Ns0Restarted guest, looking to see if it is runningsPDomain has not existed. You should be able to find more information in the logsisPDomain has not run yet. You should be able to find more information in the logssLaunching console callbackis!waiting console pid error: %s: %s(R(R)RRR'RR$RR-R.RRRRRR<RRRR(RRRRRR((RRs    cCs'|idj ottdndS(Ns Domain has already been started!(RR$RR-R.(R((RRscCs|idjoExntiti|_ti|i|ioqnPqWn-ti|i|iott dn|i djp|i djott dndS(Nis8The UUID you entered is already in use by another guest!s1Name and memory must be specified for all guests!( RRRRDt uuidToStringt randomUUIDtvm_uuid_collisionR'R-R.RR(R((RRs  cCs|i}|i}|oo|o:|i|d|i|o|i|d||Sq|i|i|o|i||Sqn|i|S(s Using self.os_type and self.os_variant to find key in OSTYPES @returns: dict value, or None if os_type/variant wasn't set RN( RRmttypRRjRRgtkeyt _DEFAULTS(RRRjR((RRrs  &c Cs|id}|id}x||gD]w}|i|pq)nxW|||D]G}|d}|d}|i |jo|SqUd|jo|SqUqUWq)Wt td||fdS(s Check the OS dictionary for the prefered device setting for passed device type and param (bus, model, etc.) Riitalls+Invalid dictionary entry for device '%s %s'N(RRrtos_devsRt default_devstdevsRgt device_keytparamtentthv_typest param_valueRR-R.( RRRRRRRRR((Rt_lookup_device_params      cCs6|io(yti|itiWq2q2XndS(N(RRR<tkilltsignaltSIGKILL(R((Rtterminate_consoles  (hRt __module__RtDEFAULTSRtOS_TYPESRRt staticmethodRR R RR3R4R5R@tpropertytautocfRARBR RCRGRRHRIRRJRKRRLRNRRORSRRTRaRRbRct graphics_devRdRhRmRiRpRRst os_distroRuRvRtRxRtgraphicsRRRRRRRRRRRRRRRRRRRRR?RRRRRRRRRRRRRRRRRRRRRRRRrR R (((RR%s          0                             /                        K ! D      cCsd}xtdtddD]}}y2|i|}|o|idjoPnWn5t i j o&}t i dt|d}nXtidq W|S(Niif0.25isNo guest running yet: (RtdomtrangeRRtignoreR'RFRRR+RRR(R)ReRR(R'RRRR((RRs  (R<tos.pathRRXturlgrabber.progressRRDR+R/RRtvirtinstt _virtinstR.R(R tobjectRRtXenGuest(RR(RR/R RRDR+RXRRRR<R.R((Rt?s             0707010002b592000081a40000000000000002000000014b136d0f000055ad000000b600010006ffffffffffffffff0000004100000000reloc/usr/lib/python2.4/vendor-packages/virtinst/CloneManager.py# # Copyright(c) FUJITSU Limited 2007. # # Cloning a virtual machine module. # # 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. """ Module for cloning an existing virtual machine General workflow for cloning: - Instantiate CloneDesign. Requires at least a libvirt connection and either the name of an existing domain to clone (original_guest), or a string of libvirt xml representing the guest to clone (original_guest_xml) - Run 'setup' from the CloneDesign instance to prep for cloning - Run 'CloneManager.start_duplicate', passing the CloneDesign instance """ import os import libxml2 import logging import subprocess import _util import libvirt import Guest from VirtualNetworkInterface import VirtualNetworkInterface from VirtualDisk import VirtualDisk from virtinst import _virtinst as _ # # This class is the design paper for a clone virtual machine. # class CloneDesign(object): def __init__(self, connection): # hypervisor connection if not isinstance(connection, libvirt.virConnect): raise ValueError(_("Connection must be a 'virConnect' instance.")) self._hyper_conn = connection # original guest name or uuid self._original_guest = None self._original_dom = None self._original_virtual_disks = [] self._original_xml = None # Deliberately private: user doesn't need to know this self._original_devices_idx = [] # clone guest self._clone_name = None self._clone_devices = [] self._clone_virtual_disks = [] self._clone_bs = 1024*1024*10 self._clone_mac = [] self._clone_uuid = None self._clone_sparse = True self._clone_xml = None self._force_target = [] self._preserve = True # Throwaway guest to use for easy validation self._valid_guest = Guest.Guest(connection=connection) # Generate a random UUID at the start while 1: uuid = _util.uuidToString(_util.randomUUID()) if _util.vm_uuid_collision(self._hyper_conn, uuid): continue self.clone_uuid = uuid break # Getter/Setter methods def get_original_guest(self): return self._original_guest def set_original_guest(self, original_guest): if self._lookup_vm(original_guest): self._original_guest = original_guest original_guest = property(get_original_guest, set_original_guest) def set_original_xml(self, val): if type(val) is not str: raise ValueError(_("Original xml must be a string.")) self._original_xml = val def get_original_xml(self): return self._original_xml original_xml = property(get_original_xml, set_original_xml) def get_clone_name(self): return self._clone_name def set_clone_name(self, name): try: self._valid_guest.set_name(name) except ValueError, e: raise ValueError, _("Invalid name for new guest: %s") % (str(e),) # Make sure new VM name isn't taken. try: if self._hyper_conn.lookupByName(name) is not None: raise ValueError(_("Domain name '%s' already in use.") % name) except libvirt.libvirtError: pass self._clone_name = name clone_name = property(get_clone_name, set_clone_name) def set_clone_uuid(self, uuid): try: self._valid_guest.set_uuid(uuid) except ValueError, e: raise ValueError, _("Invalid uuid for new guest: %s") % (str(e),) if _util.vm_uuid_collision(self._hyper_conn, uuid): raise ValueError(_("UUID '%s' is in use by another guest.") % uuid) self._clone_uuid = uuid def get_clone_uuid(self): return self._clone_uuid clone_uuid = property(get_clone_uuid, set_clone_uuid) def set_clone_devices(self, devpath): # Devices here is a string path. Every call to set_clone_devices # Adds the path (if valid) to the internal _clone_devices list # Check path is valid try: disk = VirtualDisk(devpath, size=.0000001, conn=self._hyper_conn) except Exception, e: raise ValueError(_("Could not use path '%s' for cloning: %s") % (devpath, str(e))) self._clone_virtual_disks.append(disk) self._clone_devices.append(devpath) def get_clone_devices(self): return self._clone_devices clone_devices = property(get_clone_devices, set_clone_devices) def get_clone_virtual_disks(self): return self._clone_virtual_disks clone_virtual_disks = property(get_clone_virtual_disks) def set_clone_mac(self, mac): VirtualNetworkInterface(mac, conn=self.original_conn) self._clone_mac.append(mac) def get_clone_mac(self): return self._clone_mac clone_mac = property(get_clone_mac, set_clone_mac) def get_clone_bs(self): return self._clone_bs def set_clone_bs(self, rate): self._clone_bs = rate clone_bs = property(get_clone_bs, set_clone_bs) def get_original_devices_size(self): ret = [] for disk in self.original_virtual_disks: ret.append(disk.size) return ret original_devices_size = property(get_original_devices_size) def get_original_devices(self): ret = [] for disk in self.original_virtual_disks: ret.append(disk.path) return ret original_devices = property(get_original_devices) def get_original_virtual_disks(self): return self._original_virtual_disks original_virtual_disks = property(get_original_virtual_disks) def get_hyper_conn(self): return self._hyper_conn original_conn = property(get_hyper_conn) def get_original_dom(self): return self._original_dom original_dom = property(get_original_dom) def get_clone_xml(self): return self._clone_xml def set_clone_xml(self, clone_xml): self._clone_xml = clone_xml clone_xml = property(get_clone_xml, set_clone_xml) def get_clone_sparse(self): return self._clone_sparse def set_clone_sparse(self, flg): self._clone_sparse = flg clone_sparse = property(get_clone_sparse, set_clone_sparse) def get_preserve(self): return self._preserve def set_preserve(self, flg): self._preserve = flg preserve = property(get_preserve, set_preserve) def set_force_target(self, dev): self._force_target.append(dev) def get_force_target(self): return self._force_target force_target = property(set_force_target) # Functional methods def setup_original(self): """ Validate and setup all parameters needed for the original (cloned) VM """ logging.debug("Validating original guest parameters") if self.original_guest == None and self.original_xml == None: raise RuntimeError(_("Original guest name or xml is required.")) if self.original_guest != None: self._original_dom = self._lookup_vm(self.original_guest) self.original_xml = self._original_dom.XMLDesc(0) # Pull clonable storage info from the original xml self._original_virtual_disks, \ self._original_devices_idx = self._get_original_devices_info(self._original_xml) logging.debug("Original paths: %s" % (self.original_devices)) logging.debug("Original sizes: %s" % (self.original_devices_size)) logging.debug("Original idxs: %s" % (self._original_devices_idx)) # If there are any devices that need to be cloned and we are on # a remote connection, fail if (self.original_devices and _util.is_uri_remote(self.original_conn.getURI())): raise RuntimeError(_("Cannot clone remote VM storage.")) # If domain has devices to clone, it must be 'off' or 'paused' if self._original_dom and len(self.original_devices) != 0: status = self._original_dom.info()[0] if status not in [libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_PAUSED]: raise RuntimeError, _("Domain with devices to clone must be " "paused or shutoff.") # Check mac address is not in use # XXX: Check this at set time? for i in self._clone_mac: ret, msg = self._check_mac(i) if msg is not None: if ret: raise RuntimeError, msg else: logging.warning(msg) def setup_clone(self): """ Validate and set up all parameters needed for the new (clone) VM """ logging.debug("Validating clone parameters.") self._clone_xml = self.original_xml # XXX: Make sure a clone name has been specified? or generate one? logging.debug("Clone paths: %s" % (self._clone_devices)) # We simply edit the original VM xml in place doc = libxml2.parseDoc(self._clone_xml) ctx = doc.xpathNewContext() typ = ctx.xpathEval("/domain")[0].prop("type") # changing name node = ctx.xpathEval("/domain/name") node[0].setContent(self._clone_name) # Changing storage paths clone_devices = iter(self._clone_devices) for i in self._original_devices_idx: node = ctx.xpathEval("/domain/devices/disk[%d]/source" % i) node = node[0].get_properties() try: node.setContent(clone_devices.next()) except Exception: raise ValueError, _("Missing path to use as disk clone " "destination for '%s'") % node.getContent() # We always have a UUID since one is generated at init time node = ctx.xpathEval("/domain/uuid") node[0].setContent(self._clone_uuid) # changing mac count = ctx.xpathEval("count(/domain/devices/interface/mac)") for i in range(1, int(count+1)): node = ctx.xpathEval("/domain/devices/interface[%d]/mac/@address" % i) try: node[0].setContent(self._clone_mac[i-1]) except Exception: while 1: mac = _util.randomMAC(typ) dummy, msg = self._check_mac(mac) if msg is not None: continue else: break node[0].setContent(mac) # Change xml disk type values if original and clone disk types # (block/file) don't match for i in range(0, len(self._original_devices_idx)): orig_type = (self._original_virtual_disks[i].type == VirtualDisk.TYPE_FILE) clone_type = (self._clone_virtual_disks[i].type == VirtualDisk.TYPE_FILE) self._change_disk_type(orig_type, clone_type, self._original_devices_idx[i], ctx) # Save altered clone xml self._clone_xml = str(doc) ctx.xpathFreeContext() doc.freeDoc() def setup(self): """ Helper function that wraps setup_original and setup_clone, with additional debug logging. """ self.setup_original() logging.debug("Original guest xml is\n%s" % (self._original_xml)) self.setup_clone() logging.debug("Clone guest xml is\n%s" % (self._clone_xml)) # Private helper functions # Check if new mac address is valid def _check_mac(self, mac): nic = VirtualNetworkInterface(macaddr=mac, conn=self.original_conn) return nic.is_conflict_net(self._hyper_conn) # Parse disk paths that need to be cloned from the original guest's xml # Return a tuple of lists: # ([list of paths to clone], [size of those paths], # [file/block type of those paths], [indices of disks to be cloned]) def _get_original_devices_info(self, xml): disks = [] lst = [] idx_lst = [] doc = libxml2.parseDoc(xml) ctx = doc.xpathNewContext() try: count = ctx.xpathEval("count(/domain/devices/disk)") for i in range(1, int(count+1)): # Check if the disk needs cloning node = self._get_available_cloning_device(ctx, i, self._force_target) if node == None: continue idx_lst.append(i) lst.append(node[0].get_properties().getContent()) finally: if ctx is not None: ctx.xpathFreeContext() if doc is not None: doc.freeDoc() # Set up virtual disk to encapsulate all relevant path info for path in lst: d = None try: try: d = VirtualDisk(path, conn=self._hyper_conn) except: # Let's specify a size, and see if the error goes away. # If so, we know the media doesn't exist d = VirtualDisk(path, conn=self._hyper_conn, size=.0001) raise ValueError(_("Disk '%s' does not exist.") % d.path) except Exception, e: raise ValueError(_("Could not determine original disk " "information: %s" % str(e))) disks.append(d) return (disks, idx_lst) # Pull disk #i from the original guest xml, return it's xml # if it should be cloned (skips readonly, empty, or sharable disks # unless its target is in the 'force' list) def _get_available_cloning_device(self, ctx, i, force): node = None force_flg = False node = ctx.xpathEval("/domain/devices/disk[%d]/source" % i) # If there is no media path, ignore if len(node) == 0: return None target = ctx.xpathEval("/domain/devices/disk[%d]/target/@dev" % i) target = target[0].getContent() for f_target in force: if target == f_target: force_flg = True # Skip readonly disks unless forced ro = ctx.xpathEval("/domain/devices/disk[%d]/readonly" % i) if len(ro) != 0 and force_flg == False: return None # Skip sharable disks unless forced share = ctx.xpathEval("/domain/devices/disk[%d]/shareable" % i) if len(share) != 0 and force_flg == False: return None return node # Check if original disk type (file/block) is different from # requested clones disk type, and alter xml if needed def _change_disk_type(self, org_type, cln_type, dev_idx, ctx): disk_type = ctx.xpathEval("/domain/devices/disk[%d]/@type" % dev_idx) driv_name = ctx.xpathEval("/domain/devices/disk[%d]/driver/@name" % dev_idx) src = ctx.xpathEval("/domain/devices/disk[%d]/source" % dev_idx) src_chid_txt = src[0].get_properties().getContent() # different type if org_type != cln_type: if org_type == True: # changing from file to disk typ, driv, newprop = ("block", "phy", "dev") else: # changing from disk to file typ, driv, newprop = ("file", "file", "file") disk_type[0].setContent(typ) if driv_name: driv_name[0].setContent(driv) src[0].get_properties().unlinkNode() src[0].newProp(newprop, src_chid_txt) # Simple wrapper for checking a vm exists and returning the domain def _lookup_vm(self, name): try: return self._hyper_conn.lookupByName(name) except libvirt.libvirtError: raise ValueError(_("Domain '%s' was not found.") % str(name)) def start_duplicate(design, meter=None): """ Actually perform the duplication: cloning disks if needed and defining the new clone xml. """ logging.debug("Starting duplicate.") dom = None try: # Define domain first so we can catch any xml errors before duplicating # storage dom = design.original_conn.defineXML(design.clone_xml) if design.preserve == True: _do_duplicate(design, meter) except Exception, e: logging.debug("Duplicate failed: %s" % str(e)) if dom: dom.undefine() raise logging.debug("Duplicating finished.") def _vdisk_clone(path, clone): logging.debug("Using vdisk clone.") path = os.path.expanduser(path) clone = os.path.expanduser(clone) try: rc = subprocess.call([ '/usr/sbin/vdiskadm', '-u', 'xvm', 'clone', path, clone ]) return rc == 0 except OSError: return False # Iterate over the list of disks, and clone them using the appropriate # clone method def _do_duplicate(design, meter): IS_UNKNOWN = 0 IS_LOCAL = 1 IS_VDISK = 2 dst_dev_iter = iter(design.clone_virtual_disks) clone_type_dict = {} # First loop over the devices, validate we can clone them, and # determine what clone operation to use for src_dev in design.original_virtual_disks: dst_dev = dst_dev_iter.next() src_path = src_dev.path dst_path = dst_dev.path clone_type = IS_UNKNOWN if (_util.is_vdisk(src_path, None) or (os.path.exists(dst_path) and _util.is_vdisk(dst_path, None))): if (not _util.is_vdisk(src_path, None) or os.path.exists(dst_path)): raise RuntimeError, _("copying to an existing vdisk is not" " supported") clone_type = IS_VDISK else: clone_type = IS_LOCAL if clone_type == IS_UNKNOWN: raise RuntimeError(_("Could not determine storage type for '%s'") % src_path) clone_type_dict[src_path] = clone_type dst_dev_iter = iter(design.clone_virtual_disks) dst_siz_iter = iter(design.original_devices_size) # Now actually do the cloning for src_dev in design.original_virtual_disks: src_path = src_dev.path dst_dev = dst_dev_iter.next() dst_path = dst_dev.path dst_siz = int(dst_siz_iter.next() * 1024 * 1024 * 1024) clone_type = clone_type_dict[src_path] if src_path == "/dev/null": # Not really sure why this check was here, but keeping for compat logging.debug("Source dev was /dev/null. Skipping") continue elif src_path == dst_path: logging.debug("Source and destination are the same. Skipping.") continue if meter: meter.start(size=dst_siz, text=_("Cloning %(srcfile)s") % {'srcfile' : src_path}) if clone_type == IS_LOCAL: _local_clone(src_path, dst_path, dst_siz, design, meter) elif clone_type == IS_VDISK: if not _vdisk_clone(src_path, dst_path): raise RuntimeError, _("failed to clone disk") if meter: meter.end(dst_siz) def _local_clone(src_dev, dst_dev, dst_siz, design, meter=None): # if a destination file exists and sparse flg is True, # this priority takes a existing file. if (os.path.exists(dst_dev) == False and design.clone_sparse == True): clone_block_size = 4096 sparse = True try: fd = os.open(dst_dev, os.O_WRONLY | os.O_CREAT) os.ftruncate(fd, dst_siz) finally: os.close(fd) else: clone_block_size = 1024*1024*10 sparse = False logging.debug("Local Cloning %s to %s, sparse=%s, block_size=%s" % (src_dev, dst_dev, sparse, clone_block_size)) zeros = '\0' * 4096 try: src_fd = os.open(src_dev, os.O_RDONLY) dst_fd = os.open(dst_dev, os.O_WRONLY | os.O_CREAT) i=0 while 1: l = os.read(src_fd, clone_block_size) s = len(l) if s == 0: if meter: meter.end(dst_siz) break # check sequence of zeros if sparse and zeros == l: os.lseek(dst_fd, s, 1) else: b = os.write(dst_fd, l) if s != b: if meter: meter.end(i) break i += s if i < dst_siz: if meter: meter.update(i) finally: if src_fd is not None: os.close(src_fd) if dst_fd is not None: os.close(dst_fd) 0707010002b5c7000081a40000000000000002000000014b136d1000001364000000b600010006ffffffffffffffff0000003c00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/osdict.pycm mKc@sdZhde<de<dd<de<de<de<de<d hd hd d gd fg<dd gdfg<<dhdd gefg<<dhdd gefg<<<<d?hdd@<dd><d hdhdd1gd2fg<<dhdd1gd2fg<<<<dAhddB<ddC<d hdhdd1gd2fg<<<<dDhddE<ddC<d hdhdd1gd2fg<<<<dFhddG<ddC<d hdhdd1gd2fg<<dhdd1gd2fg<<<<dHhddI<<dJhddK<<dLhd!dM<ddN<d hdhdd1gd2fg<<dhdd1gd2fg<<<<<<dOhddP<ddQ<de<d hd hd d gd7fg<dd gd8fg<<<dhdRhddS<de<de<<dThddU<<dVhddW<de<de<<dXhddY<<dZhdd[<<d\hdd]<<<<d^hdd_<ddQ<de<dhd`hdda<<dbhddc<d hd hd d gd7fg<dd gd8fg<<<<ddhdde<d hd hd d gd7fg<dd gd8fg<<<<<<dfhddg<dhdhhddi<d hdhdd gdjfg<<<<dkhddl<d hdhdd gdjfg<<<<dmhddn<d hdhdd gdofg<<<<<<dphddq<dhdrhdds<de<de<<dthddu<<dvhddw<<dxhddy<de<<dzhdd{<<< # # 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 os, statvfs import subprocess import logging import libvirt import _util import Storage from VirtualDevice import VirtualDevice from virtinst import _virtinst as _ def _zvol_create(path, size): zvol = path.lstrip("/") try: rc = subprocess.call(['/usr/sbin/zfs', 'create', '-p', '-V', str(size), zvol]) return rc == 0 except OSError: return False def _vdisk_create(path, size, kind, sparse = True): force_fixed = "raw" path = os.path.expanduser(path) if kind in force_fixed or not sparse: _type = kind + ":fixed" else: _type = kind + ":sparse" try: rc = subprocess.call([ '/usr/sbin/vdiskadm', '-u', 'xvm', 'create', '-t', _type, '-s', str(size), path ]) return rc == 0 except OSError: return False class VirtualDisk(VirtualDevice): """ Builds a libvirt domain disk xml description The VirtualDisk class is used for building libvirt domain xml descriptions for disk devices. If creating a disk object from an existing local block device or file, a path is all that should be required. If you want to create a local file, a size also needs to be specified. The remote case is a bit more complex. The options are: 1. A libvirt virStorageVol instance (passed as 'volObject') for an existing storage volume. 2. A virtinst L{StorageVolume} instance for creating a volume (passed as 'volInstall'). 3. An active connection ('conn') and a path to a storage volume on that connection. 4. An active connection and a tuple of the form ("poolname", "volumename") 5. An active connection and a path. The base of the path must point to the target path for an active pool. For cases 3 and 4, the lookup will be performed, and 'vol_object' will be set to the returned virStorageVol. For the last case, 'volInstall' will be populated for a StorageVolume instance. All the above cases also work on a local connection as well, the only difference being that option 3 won't neccessarily error out if the volume isn't found. __init__ and setting all properties performs lots of validation, and will throw ValueError's if problems are found. """ DRIVER_FILE = "file" DRIVER_PHY = "phy" DRIVER_TAP = "tap" driver_names = [DRIVER_FILE, DRIVER_PHY, DRIVER_TAP] DRIVER_TAP_RAW = "aio" DRIVER_TAP_QCOW = "qcow" DRIVER_TAP_VMDK = "vmdk" DRIVER_TAP_VDISK = "vdisk" DRIVER_PHY_ISCSI = "iscsi" DRIVER_PHY_ZVOL = "zvol" DRIVER_PHY_ZPOOL = "zpool" DRIVER_PHY_NPIV = "npiv" DRIVER_PHY_SAN = "san" driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, DRIVER_TAP_VMDK, DRIVER_TAP_VDISK, DRIVER_PHY_ISCSI, DRIVER_PHY_ZVOL, DRIVER_PHY_ZPOOL, DRIVER_PHY_NPIV, DRIVER_PHY_SAN] CACHE_MODE_NONE = "none" CACHE_MODE_WRITETHROUGH = "writethrough" CACHE_MODE_WRITEBACK = "writeback" cache_types = [CACHE_MODE_NONE, CACHE_MODE_WRITETHROUGH, CACHE_MODE_WRITEBACK] DEVICE_DISK = "disk" DEVICE_CDROM = "cdrom" DEVICE_FLOPPY = "floppy" devices = [DEVICE_DISK, DEVICE_CDROM, DEVICE_FLOPPY] TYPE_FILE = "file" TYPE_BLOCK = "block" types = [TYPE_FILE, TYPE_BLOCK] def __init__(self, path=None, size=None, transient=False, type=None, device=DEVICE_DISK, driverName=None, driverType=None, readOnly=False, sparse=True, conn=None, volObject=None, volInstall=None, volName=None, bus=None, shareable=False, driverCache=None, format=None): """ @param path: filesystem path to the disk image. @type path: C{str} @param size: size of local file to create in gigabytes @type size: C{int} or C{long} or C{float} @param transient: whether to keep disk around after guest install @type transient: C{bool} @param type: disk media type (file, block, ...) @type type: C{str} @param device: Emulated device type (disk, cdrom, floppy, ...) @type device: member of devices @param driverName: name of driver @type driverName: member of driver_names @param driverType: type of driver @type driverType: member of driver_types @param readOnly: Whether emulated disk is read only @type readOnly: C{bool} @param sparse: Create file as a sparse file @type sparse: C{bool} @param conn: Connection disk is being installed on @type conn: libvirt.virConnect @param volObject: libvirt storage volume object to use @type volObject: libvirt.virStorageVol @param volInstall: StorageVolume instance to build for new storage @type volInstall: L{StorageVolume} @param volName: Existing StorageVolume lookup information, (parent pool name, volume name) @type volName: C{tuple} of (C{str}, C{str}) @param bus: Emulated bus type (ide, scsi, virtio, ...) @type bus: C{str} @param shareable: If disk can be shared among VMs @type shareable: C{bool} @param driverCache: Disk cache mode (none, writethrough, writeback) @type driverCache: member of cache_types @param format: driver-specific format to use during create @type format: C{str} """ VirtualDevice.__init__(self, conn=conn) self._path = None self._size = None self._type = None self._device = None self._sparse = None self._readOnly = None self._vol_object = None self._vol_install = None self._bus = None self._shareable = None self._driver_cache = None # XXX: No property methods for these self.transient = transient self._driverName = driverName self._driverType = driverType self.target = None self.format = format self.set_read_only(readOnly, validate=False) self.set_sparse(sparse, validate=False) self.set_type(type, validate=False) self.set_device(device, validate=False) self._set_path(path, validate=False) self._set_size(size, validate=False) self._set_vol_object(volObject, validate=False) self._set_vol_install(volInstall, validate=False) self._set_bus(bus, validate=False) self._set_shareable(shareable, validate=False) self._set_driver_cache(driverCache, validate=False) if volName: self.__lookup_vol_name(volName) self.__validate_params() def __repr__(self): """ prints a simple string representation for the disk instance """ return "%s:%s" %(self.type, self.path) def _get_path(self): return self._path def _set_path(self, val, validate=True): if val is not None: self._check_str(val, "path") val = os.path.abspath(val) self.__validate_wrapper("_path", val, validate) path = property(_get_path, _set_path) def _get_size(self): return self._size def _set_size(self, val, validate=True): if val is not None: if type(val) not in [int, float, long] or val < 0: raise ValueError, _("'size' must be a number greater than 0.") self.__validate_wrapper("_size", val, validate) size = property(_get_size, _set_size) def get_type(self): return self._type def set_type(self, val, validate=True): if val is not None: self._check_str(val, "type") if val not in self.types: raise ValueError, _("Unknown storage type '%s'" % val) self.__validate_wrapper("_type", val, validate) type = property(get_type, set_type) def get_device(self): return self._device def set_device(self, val, validate=True): self._check_str(val, "device") if val not in self.devices: raise ValueError, _("Unknown device type '%s'" % val) self.__validate_wrapper("_device", val, validate) device = property(get_device, set_device) def get_driver_name(self): return self._driverName def set_driver_name(self, val): self._driverName = val driver_name = property(get_driver_name, set_driver_name) def get_driver_type(self): return self._driverType def set_driver_type(self, val): self._driverType = val driver_type = property(get_driver_type, set_driver_type) def get_sparse(self): return self._sparse def set_sparse(self, val, validate=True): self._check_bool(val, "sparse") self.__validate_wrapper("_sparse", val, validate) sparse = property(get_sparse, set_sparse) def get_read_only(self): return self._readOnly def set_read_only(self, val, validate=True): self._check_bool(val, "read_only") self.__validate_wrapper("_readOnly", val, validate) read_only = property(get_read_only, set_read_only) def _get_vol_object(self): return self._vol_object def _set_vol_object(self, val, validate=True): if val is not None and not isinstance(val, libvirt.virStorageVol): raise ValueError, _("vol_object must be a virStorageVol instance") self.__validate_wrapper("_vol_object", val, validate) vol_object = property(_get_vol_object, _set_vol_object) def _get_vol_install(self): return self._vol_install def _set_vol_install(self, val, validate=True): if val is not None and not isinstance(val, Storage.StorageVolume): raise ValueError, _("vol_install must be a StorageVolume " " instance.") self.__validate_wrapper("_vol_install", val, validate) vol_install = property(_get_vol_install, _set_vol_install) def _get_bus(self): return self._bus def _set_bus(self, val, validate=True): if val is not None: self._check_str(val, "bus") self.__validate_wrapper("_bus", val, validate) bus = property(_get_bus, _set_bus) def _get_shareable(self): return self._shareable def _set_shareable(self, val, validate=True): self._check_bool(val, "shareable") self.__validate_wrapper("_shareable", val, validate) shareable = property(_get_shareable, _set_shareable) def _get_driver_cache(self): return self._driver_cache def _set_driver_cache(self, val, validate=True): if val is not None: self._check_str(val, "cache") if val not in self.cache_types: raise ValueError, _("Unknown cache mode '%s'" % val) self.__validate_wrapper("_driver_cache", val, validate) driver_cache = property(_get_driver_cache, _set_driver_cache) # Validation assistance methods # Initializes attribute if it hasn't been done, then validates args. # If validation fails, reset attribute to original value and raise error def __validate_wrapper(self, varname, newval, validate=True): try: orig = getattr(self, varname) except: orig = newval setattr(self, varname, newval) if validate: try: self.__validate_params() except: setattr(self, varname, orig) raise def __set_size(self, creating_storage): """ Fill in 'size' attribute for existing storage. """ if creating_storage: return if self.__storage_specified() and self.vol_object: newsize = _util.get_xml_path(self.vol_object.XMLDesc(0), "/volume/capacity") try: newsize = float(newsize) / 1024.0 / 1024.0 / 1024.0 except: newsize = 0 elif self.path is None: newsize = 0 else: ignore, newsize = _util.stat_disk(self.path) newsize = newsize / 1024.0 / 1024.0 / 1024.0 if newsize != self.size: logging.debug("Setting size for existing storage to '%s'" % newsize) self._set_size(newsize, validate=False) def __set_dev_type(self): """ Detect disk 'type' () from passed storage parameters """ dtype = None if self.vol_object: # vol info is [ vol type (file or block), capacity, allocation ] t = self.vol_object.info()[0] if t == libvirt.VIR_STORAGE_VOL_FILE: dtype = self.TYPE_FILE elif t == libvirt.VIR_STORAGE_VOL_BLOCK: dtype = self.TYPE_BLOCK else: raise ValueError, _("Unknown storage volume type.") elif self.vol_install: if isinstance(self.vol_install, Storage.FileVolume): dtype = self.TYPE_FILE else: # All others should be using TYPE_BLOCK (hopefully) dtype = self.TYPE_BLOCK elif self.path: if self._driverName == self.DRIVER_PHY: dtype = self.TYPE_BLOCK elif _util.stat_disk(self.path)[0]: dtype = self.TYPE_FILE else: dtype = self.TYPE_BLOCK if _util.is_vdisk(self.path, self._driverName): self._driverName = self.DRIVER_TAP self._driverType = self.DRIVER_TAP_VDISK if self.type is None: logging.debug("Detected storage as type '%s'" % dtype) elif dtype != self.type: raise ValueError(_("Passed type '%s' does not match detected " "storage type '%s'" % (self.type, dtype))) self.set_type(dtype, validate=False) def __lookup_vol_name(self, name_tuple): """ lookup volume via tuple passed via __init__'s volName parameter """ if type(name_tuple) is not tuple or len(name_tuple) != 2 \ or (type(name_tuple[0]) is not type(name_tuple[1]) is not str): raise ValueError(_("volName must be a tuple of the form " "('poolname', 'volname')")) if not self.conn: raise ValueError(_("'volName' requires a passed connection.")) if not _util.is_storage_capable(self.conn): raise ValueError(_("Connection does not support storage lookup.")) try: pool = self.conn.storagePoolLookupByName(name_tuple[0]) self._set_vol_object(pool.storageVolLookupByName(name_tuple[1]), validate=False) except Exception, e: raise ValueError(_("Couldn't lookup volume object: %s" % str(e))) def __storage_specified(self): """ Return bool representing if managed storage parameters have been explicitly specified or filled in """ return (self.vol_object != None or self.vol_install != None) def __check_if_path_managed(self): """ Determine if we can use libvirt storage apis to create or lookup 'self.path' """ vol = None verr = None pool = _util.lookup_pool_by_path(self.conn, os.path.dirname(self.path)) if pool: # Is pool running? if pool.info()[0] != libvirt.VIR_STORAGE_POOL_RUNNING: pool = None try: vol = self.conn.storageVolLookupByPath(self.path) except Exception, e: try: try: # Pool may need to be refreshed, but if it errors, # invalidate it pool.refresh(0) except: pool = None raise vol = self.conn.storageVolLookupByPath(self.path) except Exception, e: verr = str(e) if not vol: # Path wasn't a volume. See if base of path is a managed # pool, and if so, setup a StorageVolume object if pool: if self.size == None: raise ValueError(_("Size must be specified for non " "existent volume path '%s'" % \ self.path)) logging.debug("Path '%s' is target for pool '%s'. " "Creating volume '%s'." % \ (os.path.dirname(self.path), pool.name(), os.path.basename(self.path))) volclass = Storage.StorageVolume.get_volume_for_pool(pool_object=pool) cap = (self.size * 1024 * 1024 * 1024) if self.sparse: alloc = 0 else: #alloc = cap # XXX: disable setting managed storage as nonsparse # XXX: since it hoses libvirtd (for now) alloc = 0 vol = volclass(name=os.path.basename(self.path), capacity=cap, allocation=alloc, pool=pool) self._set_vol_install(vol, validate=False) elif self._is_remote(): if not verr: # Since there is no error, no pool was ever found err = (_("Cannot use storage '%(path)s': '%(rootdir)s' is " "not managed on the remote host.") % { 'path' : self.path, 'rootdir' : os.path.dirname(self.path)}) else: err = (_("Cannot use storage %(path)s: %(err)s") % { 'path' : self.path, 'err' : verr }) raise ValueError(err) else: self._set_vol_object(vol, validate=False) def __sync_params(self): """ Sync some parameters between storage objects and the older VirtualDisk fields """ newpath = None if self.vol_object: newpath = self.vol_object.path() elif self.vol_install: newpath = (_util.get_xml_path(self.vol_install.pool.XMLDesc(0), "/pool/target/path") + "/" + self.vol_install.name) if newpath and newpath != self.path: logging.debug("Overwriting 'path' with value from StorageVolume" " object.") self._set_path(newpath, validate=False) if self.vol_install: newsize = self.vol_install.capacity/1024.0/1024.0/1024.0 if self.size != newsize: logging.debug("Overwriting 'size' with value from " "StorageVolume object") self._set_size(newsize, validate=False) # Remove this piece when storage volume creation is async if self.sparse and self.vol_install and \ self.vol_install.allocation != 0: logging.debug("Setting vol_install allocation to 0 (sparse).") self.vol_install.allocation = 0 def __validate_params(self): """ function to validate all the complex interaction between the various disk parameters. """ # if storage capable, try to lookup path # if no obj: if remote, error storage_capable = False if self.conn: storage_capable = _util.is_storage_capable(self.conn) if not storage_capable and self._is_remote(): raise ValueError, _("Connection doesn't support remote storage.") # If the user didn't pass storage parameters, try to determine them # from the passed path if storage_capable and self.path is not None \ and not self.__storage_specified(): self.__check_if_path_managed() # Sync parameters between VirtualDisk and potentially passed # storage objects. self.__sync_params() # One small caveat: if self.path isn't set at this point, we are # basically done. if self.path is None: if self.device != self.DEVICE_FLOPPY and \ self.device != self.DEVICE_CDROM: raise ValueError, _("Device type '%s' requires a path") % \ self.device return True # The main distinctions from this point forward: # Are we doing storage API operations or local media checks? managed_storage = self.__storage_specified() or self.path is None # Do we need to create the storage? create_media = not ((managed_storage and self.vol_object) or \ (self.path and os.path.exists(self.path))) self.__set_size(create_media) if self._is_remote() and not managed_storage: raise ValueError, _("Must specify libvirt managed storage if on " "a remote connection") # If not creating the storage, our job is easy if not create_media: # Make sure we have access to the local path if not managed_storage: if os.path.isdir(self.path) and not _util.is_vdisk(self.path, self._driverName): # vdisk _is_ a directory. raise ValueError(_("The path '%s' must be a file or a " "device, not a directory") % self.path) # XXX: Any selinux validation checks should go here self.__set_dev_type() return True if self.device == self.DEVICE_FLOPPY or \ self.device == self.DEVICE_CDROM: raise ValueError, _("Cannot create storage for %s device.") % \ self.device if not managed_storage and not self._driverType: if self.type is self.TYPE_BLOCK: raise ValueError, _("Local block device path must exist.") self.set_type(self.TYPE_FILE, validate=False) if self.size is None: raise ValueError, _("size is required for non-existent disk " "'%s'" % self.path) else: self.__set_dev_type() # Applicable for managed or local storage ret = self.is_size_conflict() if ret[0]: raise ValueError, ret[1] elif ret[1]: logging.warn(ret[1]) def setup(self, progresscb=None): """ Build storage (if required) If storage doesn't exist (a non-existent file 'path', or 'vol_install' was specified), we create it. @param progresscb: progress meter @type progresscb: instanceof urlgrabber.BaseMeter """ if self.vol_object: return elif self.vol_install: self._set_vol_object(self.vol_install.install(meter=progresscb), validate=False) return elif self._driverName == self.DRIVER_PHY and self._driverType: if self._driverType == self.DRIVER_PHY_ZVOL: size_bytes = long(self.size * 1024L * 1024L * 1024L) if (not _zvol_create(self.path, size_bytes)): raise RuntimeError, _("Error creating zvol %s" % self.path) elif (self.type == VirtualDisk.TYPE_FILE and self.path is not None and not os.path.exists(self.path)): size_bytes = long(self.size * 1024L * 1024L * 1024L) if progresscb: progresscb.start(filename=self.path,size=long(size_bytes), \ text=_("Creating storage file...")) if _util.is_vdisk(self.path, self._driverName): progresscb.update(1024) if self.format is None: self.format = "vmdk" if (not _vdisk_create(self.path, size_bytes, self.format, self.sparse)): raise RuntimeError, _("Error creating vdisk %s" % self.path) self._driverName = self.DRIVER_TAP self._driverType = self.DRIVER_TAP_VDISK progresscb.end(self.size) return fd = None try: try: fd = os.open(self.path, os.O_WRONLY | os.O_CREAT) if self.sparse: os.ftruncate(fd, size_bytes) if progresscb: progresscb.update(self.size) else: buf = '\x00' * 1024 * 1024 # 1 meg of nulls for i in range(0, long(self.size * 1024L)): os.write(fd, buf) if progresscb: progresscb.update(long(i * 1024L * 1024L)) except OSError, e: raise RuntimeError, _("Error creating diskimage %s: %s" % \ (self.path, str(e))) finally: if fd is not None: os.close(fd) if progresscb: progresscb.end(size_bytes) # FIXME: set selinux context? def get_xml_config(self, disknode=None): """ @param disknode: device name in host (xvda, hdb, etc.). self.target takes precedence. @type disknode: C{str} """ typeattr = 'file' if self.type == VirtualDisk.TYPE_BLOCK: typeattr = 'dev' if self.target: disknode = self.target if not disknode: raise ValueError(_("'disknode' or self.target must be set!")) path = None if self.vol_object: path = self.vol_object.path() elif self.path: path = self.path if path: path = _util.xml_escape(path) ret = " \n" % (self.type, self.device) dname = self.driver_name if not dname and self.driver_cache: self.driver_name = "qemu" if not self.driver_name is None: dtypexml = "" if not self.driver_type is None: dtypexml = " type='%s'" % self.driver_type dcachexml = "" if not self.driver_cache is None: dcachexml = " cache='%s'" % self.driver_cache ret += " \n" % (self.driver_name, dtypexml, dcachexml) if path is not None: ret += " \n" % (typeattr, path) bus_xml = "" if self.bus is not None: bus_xml = " bus='%s'" % self.bus ret += " \n" % (disknode, bus_xml) ro = self.read_only if self.device == self.DEVICE_CDROM: ro = True if self.shareable: ret += " \n" if ro: ret += " \n" ret += " " return ret def is_size_conflict(self): """ reports if disk size conflicts with available space returns a two element tuple: 1. first element is True if fatal conflict occurs 2. second element is a string description of the conflict or None Non fatal conflicts (sparse disk exceeds available space) will return (False, "description of collision") """ if self.vol_install: return self.vol_install.is_size_conflict() if self.vol_object or self.size is None or not self.path \ or os.path.exists(self.path) or self.type != self.TYPE_FILE: return (False, None) ret = False msg = None vfs = os.statvfs(os.path.dirname(self.path)) avail = vfs[statvfs.F_FRSIZE] * vfs[statvfs.F_BAVAIL] need = long(self.size * 1024L * 1024L * 1024L) if need > avail: if self.sparse: msg = _("The filesystem will not have enough free space" " to fully allocate the sparse file when the guest" " is running.") else: ret = True msg = _("There is not enough free space to create the disk.") if msg: msg += _(" %d M requested > %d M available") % \ ((need / (1024*1024)), (avail / (1024*1024))) return (ret, msg) def is_conflict_disk(self, conn, return_names=False): """ check if specified storage is in use by any other VMs on passed connection. @param conn: connection to check for collisions on @type conn: libvirt.virConnect @param return_names: Whether or not to return a list of VM names using the same storage (default = False) @type return_names: C{bool} @return: True if a collision, False otherwise (list of names if return_names passed) @rtype: C{bool} """ active, inactive = _util.fetch_all_guests(conn) vms = active + inactive if self.vol_object: path = self.vol_object.path() else: path = self.path if not path: return False def count_cb(ctx): c = 0 c += ctx.xpathEval("count(/domain/devices/disk/source[@dev='%s'])" % path) c += ctx.xpathEval("count(/domain/devices/disk/source[@file='%s'])" % path) return c count = 0 names = [] for vm in vms: xml = vm.XMLDesc(0) tmpcount = _util.get_xml_path(xml, func = count_cb) if tmpcount: count += tmpcount names.append(vm.name()) ret = False if count > 0: ret = True if return_names: ret = names return ret def _get_target_type(self): """ Returns the suggested disk target prefix (hd, xvd, sd ...) from the passed parameters. @returns: str prefix, or None if no reasonable guess can be made """ if self.bus == "virtio": return ("vd", 16) elif self.bus == "scsi" or self.bus == "usb": return ("sd", 16) elif self.bus == "xen": return ("xvd", 16) elif self.bus == "ide": return ("hd", 4) elif self.bus == "floppy" or self.device == self.DEVICE_FLOPPY: return ("fd", 2) else: return (None, None) def generate_target(self, skip_targets): """ Generate target device ('hda', 'sdb', etc..) for disk, excluding any targets in list 'skip_targets'. Sets self.target, and returns the generated value @param used_targets: list of targets to exclude @type used_targets: C{list} @raise ValueError: can't determine target type, no targets available @returns generated target @rtype C{str} """ # Only use these targets if there are no other options except_targets = ["hdc"] prefix, maxnode = self._get_target_type() if prefix is None: raise ValueError(_("Cannot determine device bus/type.")) # Special case: IDE cdrom must be hdc if self.device == self.DEVICE_CDROM and prefix == "hd": if "hdc" not in skip_targets: self.target = "hdc" return self.target raise ValueError(_("IDE CDROM must use 'hdc', but target in use.")) # Regular scanning for i in range(maxnode): gen_t = "%s%c" % (prefix, ord('a') + i) if gen_t in except_targets: continue if gen_t not in skip_targets: self.target = gen_t return self.target # Check except_targets for any options for t in except_targets: if t.startswith(prefix) and t not in skip_targets: self.target = t return self.target raise ValueError(_("No more space for disks of type '%s'" % prefix)) class XenDisk(VirtualDisk): """ Back compat class to avoid ABI break. """ pass 0707010002b593000081a40000000000000002000000014b136d100000455a000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/CloneManager.pycm mKc@sdZdkZdkZdkZdkZdkZdkZdkZdklZdk l Z dk l Z de fdYZedZdZd Zed ZdS( s Module for cloning an existing virtual machine General workflow for cloning: - Instantiate CloneDesign. Requires at least a libvirt connection and either the name of an existing domain to clone (original_guest), or a string of libvirt xml representing the guest to clone (original_guest_xml) - Run 'setup' from the CloneDesign instance to prep for cloning - Run 'CloneManager.start_duplicate', passing the CloneDesign instance N(sVirtualNetworkInterface(s VirtualDisk(s _virtinstt CloneDesigncBs?tZdZdZdZeeeZdZdZeeeZ dZ dZ ee e Z dZ d Zeee Zd Zd ZeeeZd ZeeZd ZdZeeeZdZdZeeeZdZeeZdZeeZdZeeZ dZ!ee!Z"dZ#ee#Z$dZ%dZ&ee%e&Z'dZ(dZ)ee(e)Z*dZ+dZ,ee+e,Z-dZ.dZ/ee.Z0dZ1dZ2d Z3d!Z4d"Z5d#Z6d$Z7d%Z8RS(&NcCst|tipttdn||_d|_ d|_ g|_ d|_ g|_ d|_g|_g|_ddd|_g|_d|_t|_d|_g|_t|_tid||_xAtiti}ti|i|oqn||_ PqWdS(Ns+Connection must be a 'virConnect' instance.ii t connectioni(!t isinstanceRtlibvirtt virConnectt ValueErrort_tselft _hyper_conntNonet_original_guestt _original_domt_original_virtual_diskst _original_xmlt_original_devices_idxt _clone_namet_clone_devicest_clone_virtual_diskst _clone_bst _clone_mact _clone_uuidtTruet _clone_sparset _clone_xmlt _force_targett _preservetGuestt _valid_guestt_utilt uuidToStringt randomUUIDtuuidtvm_uuid_collisiont clone_uuid(RRR((ta/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/CloneManager.pyt__init__3s4                cCs|iS(N(RR (R((R"tget_original_guest]scCs!|i|o ||_ndS(N(Rt _lookup_vmtoriginal_guestR (RR&((R"tset_original_guest_scCs6t|tj ottdn||_dS(NsOriginal xml must be a string.(ttypetvaltstrRRRR (RR)((R"tset_original_xmldscCs|iS(N(RR (R((R"tget_original_xmlhscCs|iS(N(RR(R((R"tget_clone_namelscCsy|ii|Wn1tj o%}ttdt|fnXy7|ii |dj ottd|nWnt i j onX||_ dS(NsInvalid name for new guest: %ss Domain name '%s' already in use.(RRtset_nametnameRteRR*Rt lookupByNameR Rt libvirtErrorR(RR/R0((R"tset_clone_namens!cCsy|ii|Wn1tj o%}ttdt|fnXti |i |ottd|n||_ dS(NsInvalid uuid for new guest: %ss%UUID '%s' is in use by another guest.( RRtset_uuidRRR0RR*RR RR(RRR0((R"tset_clone_uuids!cCs|iS(N(RR(R((R"tget_clone_uuidscCs}yt|ddd|i}Wn7tj o+}ttd|t |fnX|i i ||i i |dS(Ntsizef9.9999999999999995e-08tconns'Could not use path '%s' for cloning: %s( t VirtualDisktdevpathRRtdiskt ExceptionR0RRR*RtappendR(RR:R0R;((R"tset_clone_devicess 'cCs|iS(N(RR(R((R"tget_clone_devicesscCs|iS(N(RR(R((R"tget_clone_virtual_disksscCs't|d|i|ii|dS(NR8(tVirtualNetworkInterfacetmacRt original_connRR=(RRB((R"t set_clone_macscCs|iS(N(RR(R((R"t get_clone_macscCs|iS(N(RR(R((R"t get_clone_bsscCs ||_dS(N(trateRR(RRG((R"t set_clone_bsscCs.g}x!|iD]}|i|iqW|S(N(tretRtoriginal_virtual_disksR;R=R7(RR;RI((R"tget_original_devices_sizes  cCs.g}x!|iD]}|i|iqW|S(N(RIRRJR;R=tpath(RR;RI((R"tget_original_devicess  cCs|iS(N(RR (R((R"tget_original_virtual_disksscCs|iS(N(RR(R((R"tget_hyper_connscCs|iS(N(RR (R((R"tget_original_domscCs|iS(N(RR(R((R"t get_clone_xmlscCs ||_dS(N(t clone_xmlRR(RRR((R"t set_clone_xmlscCs|iS(N(RR(R((R"tget_clone_sparsescCs ||_dS(N(tflgRR(RRU((R"tset_clone_sparsescCs|iS(N(RR(R((R"t get_preservescCs ||_dS(N(RURR(RRU((R"t set_preservescCs|ii|dS(N(RRR=tdev(RRY((R"tset_force_targetscCs|iS(N(RR(R((R"tget_force_targetscCstid|id jo&|id jottdn|id jo.|i|i|_ |i i d|_n|i |i \|_ |_tid|itid|itid|i|io/ti|iiottdn|i oYt|idjoC|i id}|titigjottdqwnxX|iD]M}|i|\}}|d j o%|o t|qti |qqWd S( sW Validate and setup all parameters needed for the original (cloned) VM s$Validating original guest parameterss'Original guest name or xml is required.isOriginal paths: %ssOriginal sizes: %ssOriginal idxs: %ssCannot clone remote VM storage.s7Domain with devices to clone must be paused or shutoff.N(!tloggingtdebugRR&R t original_xmlt RuntimeErrorRR%R tXMLDesct_get_original_devices_infoR R Rtoriginal_devicestoriginal_devices_sizeRt is_uri_remoteRCtgetURItlentinfotstatusRtVIR_DOMAIN_SHUTOFFtVIR_DOMAIN_PAUSEDRtit _check_macRItmsgtwarning(RRhRkRmRI((R"tsetup_originals0  #    c Cstid|i|_tid|iti|i} | i } | i ddi d}| i d}|di|it|i}xz|iD]o} | i d| }|di}y|i|iWqtj o ttd|iqXqW| i d }|di|i| i d }xtd t|d D]} | i d | }y |di|i| d Wqbtj oYx>t i!|}|i#|\}}|d j oqqPqW|di|qbXqbWxotdt'|iD]U} |i(| i)t*i+j}|i-| i)t*i+j} |i/|| |i| | q Wt0| |_| i1| i2d S(sR Validate and set up all parameters needed for the new (clone) VM sValidating clone parameters.sClone paths: %ss/domainiR(s /domain/names/domain/devices/disk[%d]/sources6Missing path to use as disk clone destination for '%s's /domain/uuids$count(/domain/devices/interface/mac)is*/domain/devices/interface[%d]/mac/@addressN(3R\R]RR^RRtlibxml2tparseDoctdoctxpathNewContexttctxt xpathEvaltpropttyptnodet setContentRtitert clone_devicesRRktget_propertiestnextR<RRt getContentRtcounttrangetintRRt randomMACRBRltdummyRmR RfR R(R9t TYPE_FILEt orig_typeRt clone_typet_change_disk_typeR*txpathFreeContexttfreeDoc( RR{RRmRxRBRwRRRkRrRtR((R"t setup_clonesZ    "      cCs@|itid|i|itid|idS(ss Helper function that wraps setup_original and setup_clone, with additional debug logging. sOriginal guest xml is %ssClone guest xml is %sN(RRoR\R]R RR(R((R"tsetupZs   cCs(td|d|i}|i|iS(NtmacaddrR8(RARBRRCtnictis_conflict_netR(RRBR((R"Rlisc Csg} g}g}ti|} | i} z| i d}xwt dt |dD]\} |i| | |i}|djoqYn|i| |i|diiqYWWd| dj o| in| dj o| inXx|D]}d}y[yt|d|i}Wn;t|d|idd}ttd|inXWn1tj o%}ttdt |nX| i|qW| |fS( Nscount(/domain/devices/disk)iiR8R7f0.0001sDisk '%s' does not exist.s1Could not determine original disk information: %s(!tdiskstlsttidx_lstRpRqtxmlRrRsRtRuRRRRkRt_get_available_cloning_deviceRRxR R=R|R~RRRLtdR9RRRR<R0R*( RRRRRxRLRR0RRkRrRRt((R"RaqsB     %  !!c Csd}t}|id|}t|djodSn|id|}|di }x%|D]}||jo t }qdqdW|id|} t| djo|tjodSn|id|}t|djo|tjodSn|S(Ns/domain/devices/disk[%d]/sourceis$/domain/devices/disk[%d]/target/@devs!/domain/devices/disk[%d]/readonlys"/domain/devices/disk[%d]/shareable(R RxtFalset force_flgRtRuRkRfttargetR~tforcetf_targetRtrotshare( RRtRkRRxRRRRR((R"Rs$   c Cs|id|} |id|} |id|}|dii}||jo|t jod \}}} nd \}}} | di|| o| di|n|dii|di| |ndS( Ns/domain/devices/disk[%d]/@types%/domain/devices/disk[%d]/driver/@names/domain/devices/disk[%d]/sourceitblocktphyRYtfile(sblockRsdev(sfilesfilesfile(RtRutdev_idxt disk_typet driv_nametsrcR|R~t src_chid_txttorg_typetcln_typeRRwtdrivtnewpropRyt unlinkNodetnewProp( RRRRRtRRRRwRRR((R"Rs  cCsMy|ii|SWn2tij o#ttdt|nXdS(NsDomain '%s' was not found.( RRR1R/RR2RRR*(RR/((R"R%s(9t__name__t __module__R#R$R'tpropertyR&R+R,R^R-R3t clone_nameR5R6R!R>R?R{R@tclone_virtual_disksRDREt clone_macRFRHtclone_bsRKRcRMRbRNRJRORCRPt original_domRQRSRRRTRVt clone_sparseRWRXtpreserveRZR[t force_targetRoRRRlRaRRR%(((R"R1sl *                                  / G   .  cCstidd}y:|ii|i}|it jot ||nWnDt j o8}tidt||o|innXtiddS(sg Actually perform the duplication: cloning disks if needed and defining the new clone xml. sStarting duplicate.sDuplicate failed: %ssDuplicating finished.N(R\R]R tdomtdesignRCt defineXMLRRRRt _do_duplicatetmeterR<R0R*tundefine(RRRR0((R"tstart_duplicates cCs~tidtii|}tii|}y/tidddd||g}|djSWnt j o t SnXdS(NsUsing vdisk clone.s/usr/sbin/vdiskadms-utxvmtclonei( R\R]tosRLt expanduserRt subprocesstcalltrctOSErrorR(RLRR((R"t _vdisk_clones !c Csxd}d}d}t|i} h}x|iD]} | i }| i } |i } |} ti| dp&ti i| oWti| doDti| d pti i| ottdn|} n|} | |jottd| n| || # # 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 re import os import _util import VirtualDevice from virtinst import _virtinst as _ class VirtualGraphics(VirtualDevice.VirtualDevice): TYPE_SDL = "sdl" TYPE_VNC = "vnc" def __init__(self, type=TYPE_VNC, port=-1, listen=None, passwd=None, keymap=None, conn=None): VirtualDevice.VirtualDevice.__init__(self, conn=conn) if type != self.TYPE_VNC and type != self.TYPE_SDL: raise ValueError(_("Unknown graphics type")) self._type = type self._port = None self._listen = None self._passwd = None self._keymap = None self.set_port(port) self.set_keymap(keymap) self.set_listen(listen) self.set_passwd(passwd) def get_type(self): return self._type type = property(get_type) def get_keymap(self): return self._keymap def set_keymap(self, val): if not val: val = _util.default_keymap() if not val or type(val) != type("string"): raise ValueError, _("Keymap must be a string") if len(val) > 16: raise ValueError, _("Keymap must be less than 16 characters") if re.match("^[a-zA-Z0-9_-]*$", val) == None: raise ValueError, _("Keymap can only contain alphanumeric, '_', or '-' characters") self._keymap = val keymap = property(get_keymap, set_keymap) def get_port(self): return self._port def set_port(self, val): if val is None: val = -1 elif type(val) is not int \ or (val != -1 and (val < 5900 or val > 65535)): raise ValueError, _("VNC port must be a number between 5900 and 65535, or -1 for auto allocation") self._port = val port = property(get_port, set_port) def get_listen(self): return self._listen def set_listen(self, val): self._listen = val listen = property(get_listen, set_listen) def get_passwd(self): return self._passwd def set_passwd(self, val): self._passwd = val passwd = property(get_passwd, set_passwd) def valid_keymaps(self): """ Return a list of valid keymap values. """ import keytable orig_list = keytable.keytable.values() sort_list = [] orig_list.sort() for k in orig_list: if k not in sort_list: sort_list.append(k) return sort_list def _sdl_config(self): if not os.environ.has_key("DISPLAY"): raise RuntimeError("No DISPLAY environment variable set.") disp = os.environ["DISPLAY"] xauth = os.path.expanduser("~/.Xauthority") return """ """ % \ (disp, xauth) def get_xml_config(self): if self._type == self.TYPE_SDL: return self._sdl_config() keymapxml = "" listenxml = "" passwdxml = "" if self.keymap: keymapxml = " keymap='%s'" % self._keymap if self.listen: listenxml = " listen='%s'" % self._listen if self.passwd: passwdxml = " passwd='%s'" % self._passwd xml = " " return xml 0707010002b5a9000081a40000000000000002000000014b136d10000080ad000000b600010006ffffffffffffffff0000003e00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/OSDistro.pycm mKc@s`dkZdkZdkZdkZdkZdkZdkZdkZdklZdkl Z dk l Z dk l Z dk lZdk lZedZeedZd eed Zd eed Zd eed Zd ZeedZdfdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefd YZ d!e fd"YZ!d#efd$YZ"d%efd&YZ#d'e#fd(YZ$d)e#fd*YZ%d+efd,YZ&d-e'fd.YZ(dS(/N(s_util(s _virtinst(sMountedImageFetcher(sFTPImageFetcher(sHTTPImageFetcher(sDirectImageFetchercCs~|ido t}nX|ido t}n>|ido t}n$tii|o t }nt}|||S(Nshttp://sftp://snfs://( turit startswithtHTTPImageFetchertfclasstFTPImageFetchertMountedImageFetchertostpathtisdirtDirectImageFetchert scratchdir(RR R((t]/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/OSDistro.pyt_fetcherForURI's    c Csg}t}tidtii||||||} | o| Snt}|djp |djo|itn|djp |djo|itn|djp |djo|itn|djp |djo|itn|djp |djo|itn|djp |djo|itn|djp |djo|itn|d jp |djo|itn|d jp |djo|itn|d jp |djo|itn|d jp |djo|itn|itxR|D]J} | ||||} |o t| _!n| i"||o| Sq<q<Wt#t$d |dS( NsAttempting to detect distro:tfedoratrheltcentostsltsusetdebiantubuntutmandrivatsolaristnetwares2Could not find an installable distribution at '%s'(%tstorestFalset skip_treeinfotloggingtdebugtvirtinsttOSDistrotdistroFromTreeinfotfetchert progresscbtbaseuritarchttypR tdisttTruetdistrotNonetappendt FedoraDistrot RHELDistrot CentOSDistrotSLDistrot SuseDistrot DebianDistrot UbuntuDistrotMandrivaDistrot SolarisDistrotOpenSolarisDistrot NetWareDistrot GenericDistrotsclasststoret uses_treeinfot isValidStoret ValueErrort_( RR!R#R R"R&R RRR$R6R5((R t_storeForDistro5sN    s/var/tmpc Cst||} y| iWn.tj o"}ttdt|nXzt d| d|d|d|d|d|d|} |tjo&| i|| || i| ifSn&|tjo| i| |Sn| SWd| iXdS( NsInvalid install location: RR!R#R R&R R"(R R!R RtprepareLocationR9teR:tstrR;t_typeR R&R"R6tiskernelR%t acquireKerneltguesttos_typet os_variantRtacquireBootDisktcleanupLocation( R@RBR!R R"R R?R&R=RR6((R t _acquireMediahs   & c Cstt|||||||S(N( RGR%RBR!R R"R ttypeR&(RBR!R R"R RHR&((R RAsc Csttd||||||S(N( RGRR'R!R R"R RHR&(R!R R"R RHR&((R REscCsCdk}|ii}tdd|||d}|i|i fS(Ns/var/tmp( t urlgrabbertprogresst BaseMeterRGR'tlocationR"R6RCRD(RLR"RIRJR6((R tdetectMediaDistros c Cs|idpdSn|id|}zti} | i |Wdt i |X| i dd} tid| o t}n^tid| o t}nAtid| o t}n$tid| o t}nt}|||||}| |_|i|||S(Ns .treeinfotgeneraltfamilys .*Fedora.*s .*CentOS.*s.*Red Hat Enterprise Linux.*s.*Scientific Linux.*(RthasFileR't acquireFileR t tmptreeinfot ConfigParsertSafeConfigParserttreeinfotreadRtunlinktgettfamtretmatchR)tdclassR+R*R,R4RR"tvmtypeR tobR8( RR RR"R]R RRR\R^RURY((R Rs,      tDistrocBstZdZdZdZgZgZgZe Z dddZ dZ dZ dZdZdZdZd ZRS( NtcCs1||_||_||_||_d|_dS(N(RtselfR]RHR R"R'RU(RaRR"R]R ((R t__init__s     cCs tdS(s7Determine if uri points to a tree of the store's distroN(tNotImplementedError(RaRR ((R R8sc Csd}d}|i||o"|id}|id}n~|idjp|idjo |i }n |i }xD|D]<\}}|i|o |i|o|}|}q~q~W| p| o2ttdhd|i<d|i<n|i|||||S(Ntkerneltinitrdthvms2Couldn't find %(type)s kernel for %(distro)s tree.R&RH(R't kernelpatht initrdpathRat _hasTreeinfoRR t_getTreeinfoMediaRHt_hvm_kernel_pathstpathst_xen_kernel_pathstkpathtipathRPt RuntimeErrorR:tnamet_kernelFetchHelperRB( RaRBRR RlRoRnRgRh((R RAs"     2cCs|i||o|i|idSnRx5|iD]*}|i|o|i||Sq7q7Wt t d|i dS(Nsboot.isos#Could not find boot.iso in %s tree.( RaRiRR RQRjt_boot_iso_pathsRRPRpR:Rq(RaRR R((R REs cCs|idj otSn|i p|id otSnti d|i d|}z#t i|_|ii|Wdti|XtS(Ns .treeinfosDetected .treeinfo file(RaRUR'R%R7RRPRRRRQR RRRSRTRVRRW(RaRR RR((R Ris cCsF|idjo d}n|iidd}|iid||S(NtxenRNR"s images-%s(RaRHttRURXt mediaName(RaRvRu((R Rj s cCsd}zy|i||}Wn tSnXt|d}z?x8|i }|pPnt i ||otSqBqBWWd|iXWd|dj oti|nXtS(Ntri(R't local_fileRRQtfilenameR RtopentftreadlinetbufRZR[tregexR%tcloseRRW(RaRR RyR~RxR{R}((R t_fetchAndMatchRegexs*  c Cs|i||}d}|iidp|d|i7}n|i o|d|i 7}ny#|i||}|||fSWnt i |nXdS(NR`t/smethod=t (RRQRgR RdtargsRLRRBt extraargsRhReRRW( RaRRBR RgRhRdRRe((R Rr-s (t__name__t __module__RqR'RCRDRsRkRmRR7RbR8RARERiRjRRr(((R R_s     R4cBsktZdZdZdZeZdgZdgZddd d gZ e Z e Z d Z d Zd ZRS(sGeneric distro store. Check well known paths for kernel locations as a last resort if we can't recognize any actual distrotGenerictlinuxsimages/xen/vmlinuzsimages/xen/initrd.imgsimages/pxeboot/vmlinuzsimages/pxeboot/initrd.imgsimages/boot.isos boot/boot.isoscurrent/images/netboot/mini.isosinstall/images/boot.isoc Cs|i||o|idjo d}n|iidd}d|}d|iidd}|ii |o%|i d|i df|_ n|ii |o|ii|d|_ qn|idjo |i} n |i} xX| D]P\}}|i djo4|i|o$|i|o||f|_ PqqWx?|iD]4}|i djo|i|o||_ Pq[q[W|i p |i otSntS(NRtRNR"s images-%sRdResboot.iso(RaRiRR RHR#RURXt kernelSectiont isoSectiont has_sectionRjt_valid_kernel_patht_valid_iso_patht _xen_pathst kern_listt _hvm_pathstkerntinitR'RPt _iso_pathstisoR%R( RaRR RRRRRR#R((R R8Ys4  %    0     cCsT|idjottd|in|i||||id|idS(Ns/Could not find a kernel path for virt type '%s'ii( RaRR'R9R:RHRrRRBR (RaRBRR ((R RAs  cCs9|idjottdn|i|i|S(Ns-Could not find a boot iso path for this tree.(RaRR'R9R:RRQR (RaRR ((R REs(simages/xen/vmlinuzsimages/xen/initrd.img(simages/pxeboot/vmlinuzsimages/pxeboot/initrd.img(RRt__doc__RqRCR%R7RRRR'RRR8RARE(((R R4As    & t RedHatDistrocBs>tZdZdZeZdgZd gZd gZdZ RS( NsRed HatRsimages/boot.isosimages/pxeboot/vmlinuzsimages/pxeboot/initrd.imgsimages/xen/vmlinuzsimages/xen/initrd.imgcCs tdS(N(Rc(RaRR ((R R8s(simages/pxeboot/vmlinuzsimages/pxeboot/initrd.img(simages/xen/vmlinuzsimages/xen/initrd.img( RRRqRCR%R7RsRkRmR8(((R Rs   R)cBs tZdZdZdZRS(NtFedoracCs|i||otid|iidd}|dj}|oW|iidd}|djo|i |_ q|odt||_ qn|Sn*|idotidtSntSdS( Ns .*Fedora.*RNROtversiont developmentR RsDetected a Fedora distro(RaRiRR RZR[RURXtmR'trettvert_latestFedoraVariantRDR>RPRRR%R(RaRR RRR((R R8s!   cCsRdk}d}x<|i|iddD] }|ido |}q*q*W|S(NRtvariantsR (tosdictR'Rt sort_helpertOS_TYPEStvarR(RaRRR((R Rs (RRRqR8R(((R R)s R*cBs tZdZdZdZRS(NsRed Hat Enterprise LinuxcCs|i||oJtid|iidd}|dj}|o|i n|Sn|i dot idd|_tSn|i dot idd|_tSn|i d ot id d |_tSntSdS( Ns.*Red Hat Enterprise Linux.*RNROtServersDetected a RHEL 5 Server distrotrhel5tClientsDetected a RHEL 5 Client distrotRedHatsDetected a RHEL 4 distrotrhel4(RaRiRR RZR[RURXRR'Rt_variantFromVersionRPRRRDR%R(RaRR RR((R R8s(        cCs9|iidd}|pdSnd|d|_dS(NRNRRi(RaRURXRRD(RaR((R Rs(RRRqR8R(((R R*s R+cBstZdZdZRS(NtCentOScCs|i||oJtid|iidd}|dj}|o|i n|Sn*|i dot idtSntSdS(Ns .*CentOS.*RNRORsDetected a CentOS distro(RaRiRR RZR[RURXRR'RRRPRRR%R(RaRR RR((R R8s!  (RRRqR8(((R R+sR,cBs7tZdZeidgZeidgZdZRS(NsScientific Linuxsimages/SL/boot.isosimages/SL/pxeboot/vmlinuzsimages/SL/pxeboot/initrd.imgcCs|i||oJtid|iidd}|dj}|o|i n|Sn*|i dot idtSntSdS(Ns.*Scientific Linux.*RNROtSLs"Detected a Scientific Linux distro(RaRiRR RZR[RURXRR'RRRPRRR%R(RaRR RR((R R8 s   (simages/SL/pxeboot/vmlinuzsimages/SL/pxeboot/initrd.img(RRRqR*RsRkR8(((R R,sR-cBsntZdZdZdgZgZgZdddZdZ dZ dZ dZ d Z d ZRS( NtSUSERs boot/boot.isocCsxti|||||tid|o d|_n|i d|id|ifg7_ |i d d g7_ dS( Nsi[4-9]86ti386sboot/%s/loader/linuxsboot/%s/loader/initrdsboot/x86_64/vmlinuz-xensboot/x86_64/initrd-xensboot/i386/vmlinuz-xensboot/i386/initrd-xen(sboot/x86_64/vmlinuz-xensboot/x86_64/initrd-xen(sboot/i386/vmlinuz-xensboot/i386/initrd-xen( R_RbRaRR"R]R RZR[RkRm(RaRR"R]R ((R Rb$s  &cCs)|idotidtSntS(Nsdirectory.yastsDetected a Suse distro.(RRPRRR%R(RaRR ((R R82s cCs|idjpF|idjp6|i|iddp|i|iddoti||||Snt i d|i ||S(NRfiis!Trying Opensuse 10 PV rpm hacking( RaRHR'RRPRmR_RARBR RRt _findXenRPMS(RaRBRR ((R RA:sV c Cs|i||}d}|iidpA|i} | idp| idd} n|d| 7}n|i o|d|i 7}n|i dp|d7}ny#|i||}|||fSWnti|nXdS( NR`Rsnfs://snfs:sinstall=Rtenableds textmode=1 xencons=tty(RRQRgR RdRRLRtreplaceRBRtgraphicsRhReRRW( RaRRBR RgRhRdRReRL((R RrEs   cCsd}d}d}ze|id|}|i|\}}|i||}|i||}|i ||||SWd|dj ot i |n|dj ot i |n|dj ot i |nXdS(Nsls-lR.gz(R't kernelrpmtinstallinitrdrpmtfilelistRRQR Rat_extractRPMNamest kernelrpmnamet initrdrpmnamet_buildKernelInitrdRRW(RaRR RRRRR((R R^s    c Csti|dd} z|ig}|idjo$|id|idd}nd}d}d}d} x| i } | pPn| djo?x|D]0}d |}| d |d jo |} PqqWqs| d jo d} qs| d djoftid| d}|d djo| d|}qe|t| |jo| d|}qeqsqsW|djottdn|djottdn||fSWd| iXdS(NtmodeRwRti586ti686s kernel-xenpaes kernel-xenis/suse/t.s: s ittotals\s+iisinstall-initrdRs#Unable to determine kernel RPM paths+Unable to determine install-initrd RPM path(tgziptGzipFileRt filelistDataRaR"tarchesR(t kernelnameR'RRtdirnameR|tdatatwantdirRZtsplitRytlent ExceptionR:R( RaRRR"RRRyRRRRR((R RysL            cCsZ|idtddd|idtiddd|i}zt i |d d |d |d }t id |t i||idd}xAt i|dD],}|idotid|}qqW|dd|d}|dd|dd|d}t idt|h} xht i|ddtD]M\}}} x;| D]3}|i!dot i"i#||| || i(}|pPn|t*|d }|i+|q-WWd| i,X|idd|d |d!}t id |t i||id"|d#|d$}|d#|}t i/|t i/|t i0d%||d&t i0d'|d(|d)d*|d|dd+d,|}t id |t i||id-xS|D]K}| i2|o5| |} |d.|}t id*| d,|qqW|id/d0|d1|d2|d,|}t id |t i||id3d |d4|d5}t id |t i||id6d7|d!}t id |t i||i5d|i7t&|d8dd9}t id:|yL|i7t&|d;|dd<} t id:| | |d=|i:fSWnt i;|nXWdt id>|XdS(?NttextsBuilding initrdtsizei itprefixs virtinstcpio.tdirs/kernelscd s/kernel && (rpm2cpio s | cpio --quiet -idm)sRunning is /kernel/boots System.map-t-s -override-isGot kernel version s/kernel/lib/modulesttopdowns.kos/installinitrds/installinitrd && (rpm2cpio is&/installinitrd/usr/lib/install-initrd/s /module.listRwis gunzip -c s7/installinitrd/usr/lib/install-initrd/initrd-base.gz > s /initrd.imgis/initrd/lib/modules/s/initrd/s../s/updatess lib/modules/s/initrds/initrd/modulesscp s/module.configRiRis depmod -a -b s /initrd -F s/kernel/boot/System.map-i s4/initrd && ( find . | cpio --quiet -o -H newc -A -F s /initrd.img)i s gzip -f9N s/initrd.img.gzs initrd.imgsSaved s/kernel/boot/vmlinuz-tvmlinuzsinstall=srm -rf (<R tstartR:tupdatettempfiletmkdtempRaR tcpiodirRtmkdirRtcmdRRtsystemR't kernelinfotlistdirR{RRZRtkernel_overridetkernel_versionR>tmodpathstwalkRtroottdummytfilesRqtendswithRtjoinRtmodnamesRztfnR|tlineRR(Rtmoddirt moddepdirtmakedirstsymlinktmodnamethas_keytsrctdsttendRtsaveTempt initrdnameRRLRW(RaRRRR RRRRRRRRRRRRRqRRRR{RRRR((R Rs   "%          "   ! "      #(RRRqRCRsRkRmR'RbR8RARrRRR(((R R-s     6R.cBs5tZdZdZdddZdZdZRS(NtDebianRcCsti||||||ido d|_n'|ido d|_n d|_t i d|o d|_nd|_ |i dS(Nsinstaller-i386Rsinstaller-amd64tamd64si[4-9]86scurrent/images( R_RbRaRR"R]R tcountt _treeArchRZR[t_prefixt_set_media_paths(RaRR"R]R ((R Rb"s     cCsnd|ig|_d|i|if}d|i}|d|dfg|_|d|dfg|_dS(Ns%s/netboot/mini.isos%s/netboot/debian-installer/%s/s%s/netboot/xen/Rs initrd.gzR(RaRRsRthvmroottxenrootRkRm(RaRR((R R1s  cCs|id|ion9|idod|_|intidtSd|i}|i |||dotidt SntS(Ns %s/MANIFESTsimages/daily/MANIFESTs images/dailys"Doesn't look like a Debian distro.s.*debian-installer.*sDetected a Debian distro( RRPRaRRRRRRyRR R%(RaRR Ry((R R8;s     (RRRqRCR'RbRR8(((R R.s  R/cBs tZdZdZdZRS(NtUbuntucCsJti|d|i|if}|d|dfg|_g|_dS(Ns%s/netboot/ubuntu-installer/%s/Rs initrd.gz(R.RRaRRRRkRm(RaR((R RVs cCs|idj o|idjotSn|id|iptSn|i||d|idot i dt SntS(NRfs %s/MANIFESTs.*ubuntu-installer.*sDetected an Ubuntu distro( RaRHR'RRRPRRR RRR%(RaRR ((R R8]s     (RRRqRR8(((R R/Rs R0cBs5tZdZdZdgZdgZgZdZRS(NtMandrivaRsinstall/images/boot.isosisolinux/alt0/vmlinuzsisolinux/alt0/all.rdzcCsr|idj o|idjotSn|idptSn|i||ddoti dt SntS(NRftVERSIONs .*Mandriva.*sDetected a Mandriva distro( RaRHR'RRRPRR RRR%(RaRR ((R R8ys   (sisolinux/alt0/vmlinuzsisolinux/alt0/all.rdz(RRRqRCRsRkRmR8(((R R0os   t SunDistrocBs/tZdZdZdZdZdZRS(NtSolarisRcCs tdS(s7Determine if uri points to a tree of the store's distroN(Rc(RaRR ((R R8scCs|id|S(Nsimages/solarisdvd.iso(RRQR (RaRR ((R REsc Cs||pd Snd}d}d}d}|i}d}x0|t |jo||}|djoV|d7}|t |joq<n|p||}q]di |||g}n|djo2|d7}|t |joq<n||}nc|i do-|d jo|d}q]||d}n&|d jo |}n|d|}|d7}q<W||||fS( sCollect additional arguments.R`is-Bit,s-mRRN(NNNN( targstrR'tkoptstkargstsmfargstBargsRRtiRtexargRR( RaRRRRRRRR((R tprocess_extra_argssB         (RRRqRCR8RER(((R Rs   R1cBs/tZdZdZdZdZdZRS(Ns boot/platform/i86xpv/kernel/unixsboot/x86.minirootcCs?|i|io(|i|iotidtSntS(NsDetected Solaris( RRPRaRgRhRRR%R(RaRR ((R R8s& cCs[|i|i\}}}} dg}|o|d|g7}n| o|d| g7}nd}|oOxL|i D]:}|i do|i dd}qx||g7}qxWnd}|idp|d7}n|io|d 7}n|ii d o-yti|id d }Wn|d 7}q>X|ii dd}|ii dd } ti|d d }|d|d| 7}|d|7}|o|d|7}nti|id i} | o|d| 7}n|id io|id ii d}x\tt |D]H}t ||djo+||d djo||d||n |d7}|d|g7}di"|S(sConstruct kernel cmdline args for the installer, consisting of: the pathname of the kernel (32/64) to load, kernel options and args, and '-B' boot properties.R`s-%ss-Bs subnet-maskt=iRsnowin s install snfs:iis dhcpt:s -B install_media=s ,host-ip=s,subnet-mask=%ss ,router-ip=t0s ,boot-mac=s,sysid_config=s,install_config=sfailed to lookup host %ss-B install_media=cdromRRN((RaRRBRRRtignore_smfargstkbargsRtnetmaskRtkargRtiargsRtautocfRLtsockett gethostbyaddrRqtguestIPtiserverRot iserverIPt_utilt default_routetnicstbridgetdroutetmacaddrtentrangeRRRtboot_mactacf_hosttacf_patht acf_hostipRp(RaRBRRRR RRRRoRR RRRR R R RRR((R t install_argssl   ,  cCstio&|idjod|_d|_ny|i|i|}Wnt d|inX|ii dd}ddi||i|}y&|i|i|}|||fSWn-ti|t td|inXdS(Nis&boot/platform/i86xpv/kernel/amd64/unixsboot/amd64/x86.miniroots!Solaris PV kernel not found at %sRis Solaris miniroot not found at %s(Rtis_64bit_capableRBtmemoryRaRgRhRRQR RdRpRRnRR RReRRWR:(RaRBRR RdRRnRe((R RAs    (RRRgRhR8R RA(((R R1s   HR2cBsDtZdZdZddgZdZdZdZdZRS( Nt opensolarissplatform/i86xpv/kernel/unixsplatform/i86pc/boot_archivesboot/x86.microrootcCs,|i|iotidtSntS(NsDetected OpenSolaris(RRPRaRgRRR%R(RaRR ((R R84s c Cs5|i|i\}} }}d}|o|d|7}n|o|d|7}n|i oy|i |i }Wn4t j o(}td|i t|fnX|d7}|iido|d|i7}nx&|D]}|d|||f7}qW|id p d GHq1n|S( sConstruct kernel cmdline args for the installer, consisting of: the pathname of the kernel (32/64) to load, kernel options and args, and '-B' boot properties.R`s -s -B s2Unable to parse OpenSolaris AI options from %s: %ss5 -B network-interface=xnf0,xpv-hcp=dhcp,livemode=textthttps,install_media=%ss,%s=%stinstall_servicesjWARNING: No install_service set via --autocf arguments, using default installation service, if configured.N(RaRRBRRt ignore_kargsR R Rt has_autocftparse_ai_bootargst get_autocftai_optstOSDistroExceptiont osd_exceptionRR>t get_locationRtkeyR( RaRBR,R.RR*R RR R&((R R :s* $  cCsitio/|idjod|_dddg|_ny|i|i|}Wn t t d|inXd|i|i |}y*|i|id|}|||fSWntj oy*|i|id |}|||fSWqetj oZ}y*|i|id |}|||fSWq`ti|td |q`XqeXnXdS( Nis!platform/i86xpv/kernel/amd64/unixs!platform/i86pc/amd64/boot_archivesboot/amd64/x86.microrootsboot/x86.microroots%OpenSolaris PV kernel not found at %sRiiis&No OpenSolaris boot archive found: %s (RR!RBR"RaRgt initrdpathsRRQR RdRpR:R RReRR=RRW(RaRBRR RdR=RRe((R RAds,  cCsh}|dj ojxg|idD]R}|id}t|djotd|n|\}}|||tZdZedZdZdZdZdZRS(sRepresent a set of features. For each feature, store a bit mask of FEATURE_ON and FEATURE_OFF to indicate whether the feature can be turned on or off. For features for which toggling doesn't make sense (e.g., 'vmx') store FEATURE_ON when the feature is present.cCs+h|_|dj o|i|ndS(N(RtfeaturestnodetNonetparseXML(RR ((RR's  cCs&|ii|o|i|SndS(Ni(RR thas_keytfeature(RR((Rt __getitem__,scCs |iiS(N(RR tkeys(R((Rtnames1scCsa|i}xQ|idD]@}|i}|i|pd||(RR R7R*((RR s (RRR RR (((RR9s R+cBstZddZdZRS(NcCs+g|_|dj o|i|ndS(N(RtcellsR R R (RR ((RRs  cCs_|i}|idjoBx?|iD]0}|idjo|iit|q#q#WndS(NRFtcell( R R)R*RRGRRFR8t TopologyCell(RR RGR*((RR s   (RRR RR (((RR+s RHcBstZddZdZRS(NcCs4d|_g|_|dj o|i|ndS(N(R RtidtcpusR R (RR ((RRs   cCswt|id|_|i}|idjoBx?|iD]0}|idjo|i i t |q;q;WndS(NRIRJR(( tintR R6RRIR)R*RR(RJR8t TopologyCPU(RR R*R(((RR s  (RRR RR (((RRHs RLcBstZddZdZRS(NcCs+d|_|dj o|i|ndS(N(R RRIR R (RR ((RRs  cCst|id|_dS(NRI(RKR R6RRI(RR ((RR s(RRR RR (((RRLs t CapabilitiescBs5tZddZdddZdZdZRS(NcCsGd|_g|_d|_|dj o|i|n|idS(N(R Rthosttguestst _topologyR R t_fixBrokenEmulator(RR ((RRs     cCs|idjodSn|djo|iidg}n |g}xd|D]\}xS|iD]H}|djp|i |jo%|djp|i|jo|Sq[q[WqKWdS(N( RRNR R&tarchstaROtgR5R/(RR5R&RSRTRR((RtguestForOSType s   :cCs|iidjodSnd}xr|iD]g}|idjp|idjoq+nx7|iD],}|i i ddjo |i }qbqbWq+W|pdSnxr|iD]g}|idjp|idjoqnx7|iD],}|i i ddjo ||_ qqWqWdS(Ntx86_64thvmtlib64iti686( RRNR&R t fixEmulatorRORTR/R0RR2tfind(RRZRTR((RRQs*      cCs|i}x|o}|idjot||_n+|idjo|iit |n|idjot ||_ n|i }q W|ii djo|i |i_ ndS(NRNtguestR'(R R)R*RR%RRNROR8R.R+RPR,R'R (RR R*((RR 2s (RRR RRURQR (((RRMs  cCsdfdY}|}ti|idziy(ti|t|ddti }Wn:ti ti fj o"}td||ifnXWdtiddXz<|i}|idjotdnt|}Wd|iX|S(Nt ErrorHandlercBstZdZdZRS(NcCs d|_dS(Nt(RR(R((RRDscCs|i|7_dS(N(RRts(RtignoreR_((RthandlerFs(RRRRa(((RR]Cs s%s %st capabilitiess"Root element is not 'capabilities'(R]terrortlibxml2tregisterErrorHandlerRaR t readMemorytxmlR>tXML_PARSE_NOBLANKStdoct parserErrort treeErrorteRRtgetRootElementtrootRRMRbtfreeDoc(RgRlRcR]RiRbRn((RtparseBs( "  c CsZ|pt|i}n|id|d|}|pttd|} |p d} ntd|}|ptd}nt tdhd|<d| <nd }|o9xH|iD]'} | i|ijo | }PqqWn|id |}|d jo;t td hd |<d|i<d|i<n||fS( s Simple virtualization availability lookup Convenience function for looking up 'Guest' and 'Domain' capabilities objects for the desired virt type. If type, arch, or os_type are none, we return the default virt type associated with those values. These are typically: - os_type : hvm, then xen - type : kvm over plain qemu - arch : host arch over all others Otherwise the default will be the first listed in the capabilities xml. This function throws C{ValueError}s if any of the requested values are not found. @param conn: virConnect instance @type conn: libvirt.virConnect @param caps: Optional L{Capabilities} instance (saves a lookup) @type conn: L{Capabilities} @param type: Virtualization type ('hvm', 'xen', ...) @type type: C{str} @param arch: Guest architecture ('x86_64', 'i686' ...) @type arch: C{str} @param os_type: Hypervisor name ('qemu', 'kvm', 'xen', ...) @type os_type: C{str} @param accelerated: Whether to look for accelerated domain if none is specifically requested @type accelerated: C{bool} @returns: A (Capabilities Guest, Capabilities Domain) tuple R5R&s for arch '%s'R^svirtualization type '%s'sany virtualization optionss+Host does not support %(virttype)s %(arch)stvirttypeR@seHost does not support domain type '%(domain)s' for virtualization type '%(virttype)s' arch '%(arch)s'R4N(tcapsRptconntgetCapabilitiesRUR/R&R\R?tarchstrtosstrt ValueErrorR R4R5R0RRDtlowerRER@( RsRrR/R&R5R@R4RvR\RuR((Rt guest_lookupas.! ,   ;cCs4|id|}t|djo |}n|S(Ns string(%s)i(R RtpathtresultR>R!(R RzR!R{((RR s (Rdtvirtinstt _virtinstR?RRR#R$tobjectRRR%R.R9R+RHRLRMRpR tFalseRyR (R#RRRdR$RHRRMRyRpR%R RLR9R+R?R.((Rt?s  ! E C F0707010002b5a5000081a40000000000000002000000014b136d100000092c000000b600010006ffffffffffffffff0000004500000000reloc/usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.pycm yKc@sVdkZdklZdklZdefdYZdeifdYZdS(N(s VirtualDisk(s _virtinsttLiveCDInstallerExceptioncBstZdZRS(NcCsti||dS(N(t Exceptiont__init__tselftmsg(RR((td/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/LiveCDInstaller.pyRs(t__name__t __module__R(((RRstLiveCDInstallercBs\tZdddddZdZdZeeeZddZdZ dZ RS(Ntxenc Cs,tii|d|d|d|d|dS(Nttypetlocationtos_typetconn(t InstallerRRR R R R (RR R R R ((RRscCs|iS(N(Rt _location(R((Rt _get_location'sc Csd}d}t|tjo |}n|}|p|o4td|d|id|dti dt |_ n||_ t |_ dS(NtpathR tvolNametdevicetreadOnly(tNoneRt vol_tupleR tvalttuplet VirtualDiskRR t DEVICE_CDROMtTruet _install_diskRtcdrom(RRRR((Rt _set_location)s   cCs.|i|ipttdndS(Ns8CDROM media must be specified for the live CD installer.(RtcleanupRt ValueErrort_(Rtguesttmetertdistro((Rtprepare>s  c Cs1|odSn|id|d|ddddS(Nt isinstallR"tkerneltbootdevR(R&RRt_get_osblob_helperR"(RR"R&((Rtget_install_xmlEscCstS(N(R(RR"((Rtpost_install_checkMs( RRRRRRtpropertyR R%R*R+(((RRs    (RRtvirtinstt _virtinstR!RRR(RRRRR!((Rt?s   0707010002b59e000081a40000000000000002000000014b0fbd7900002db1000000b600010006ffffffffffffffff0000004000000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImageParser.py# Sample code to parse an image XML description and # spit out libvirt XML; will be hooked into virt-install # # Copyright 2007 Red Hat, Inc. # David Lutterkort # # 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 os.path import libxml2 import CapabilitiesParser from virtinst import _virtinst as _ import _util import logging class ParserException(Exception): def __init__(self, msg): Exception.__init__(self, msg) class Image: """The toplevel object representing a VM image""" def __init__(self, node = None, base = None, filename = None): self.storage = {} self.domain = None if filename == None: self.filename = None else: self.filename = os.path.abspath(filename) if base is None: if filename is not None: self.base = os.path.dirname(filename) if self.base == '' : self.base ="." else: self.base ="." else: self.base = base self.name = None self.label = None self.descr = None self.version = None self.release = None if not node is None: self.parseXML(node) def abspath(self, p): """Turn P into an absolute path. Relative paths are taken relative to self.BASE""" return os.path.abspath(os.path.join(self.base, p)) def parseXML(self, node): self.name = xpathString(node, "name") self.label = xpathString(node, "label") self.descr = xpathString(node, "description") self.version = xpathString(node, "name/@version") self.release = xpathString(node, "name/@release") for d in node.xpathEval("storage/disk"): disk = Disk(d) if disk.file is None: disk.id = "disk%d.img" % len(self.storage) disk.file = "disk%d.img" % (len(self.storage) + 1) if self.storage.has_key(disk.id): raise ParserException("Disk file '%s' defined twice" % disk.file) self.storage[disk.id] = disk lm = node.xpathEval("domain") if len(lm) == 1: self.domain = Domain(lm[0]) else: raise ParserException(_("Expected exactly one 'domain' element")) # Connect the disk maps to the disk definitions for boot in self.domain.boots: for d in boot.drives: if not self.storage.has_key(d.disk_id): raise ParserException(_("Disk entry for '%s' not found") % d.disk_id) d.disk = self.storage[d.disk_id] class Domain: """The description of a virtual domain as part of an image""" def __init__(self, node = None): self.boots = [] self.vcpu = None self.memory = None self.interface = 0 self.graphics = None if not node is None: self.parseXML(node) def parseXML(self, node): self.boots = [ Boot(b) for b in node.xpathEval("boot") ] self.vcpu = xpathString(node, "devices/vcpu", 1) tmpmem = xpathString(node, "devices/memory") self.interface = int(node.xpathEval("count(devices/interface)")) self.graphics = node.xpathEval("count(devices/graphics)") > 0 # FIXME: There must be a better way to check this if tmpmem is not None: try: self.memory = int(tmpmem) except ValueError: raise ParserException(_("Memory must be an integer, " "but is '%s'") % self.memory) else: tmpmem = 0 class ImageFeatures(CapabilitiesParser.Features): def __init__(self, node = None): CapabilitiesParser.Features.__init__(self, node) def _extractFeature(self, feature, d, n): state = xpathString(n, "@state", "on") if state == "on": d[feature] = CapabilitiesParser.FEATURE_ON elif state == "off": d[feature] = CapabilitiesParser.FEATURE_OFF else: raise ParserException("The state for feature %s must be either 'on' or 'off', but is '%s'" % (feature, state)) class Boot: """The overall description of how the image can be booted, including required capabilities of the host and mapping of disks into the VM""" def __init__(self, node = None): # 'xen' or 'hvm' self.type = None # Either 'pygrub' or nothing; might have others in the future # For HVM, figure outhte right loader based on the guest self.loader = None # Only used for hvm self.bootdev = None self.kernel = None self.initrd = None self.cmdline = None self.drives = [] self.arch = None self.features = ImageFeatures() if not node is None: self.parseXML(node) def parseXML(self, node): self.type = xpathString(node, "@type") self.loader = xpathString(node, "os/loader") self.bootdev = xpathString(node, "os/loader/@dev") self.kernel = xpathString(node, "os/kernel") self.initrd = xpathString(node, "os/initrd") self.cmdline = xpathString(node, "os/cmdline") self.arch = _util.sanitize_arch(xpathString(node, "guest/arch")) fl = node.xpathEval("guest/features") if len(fl) > 1: raise ParserException("Expected at most one element in %s boot descriptor for %s" % (self.type, self.arch)) elif len(fl) == 1: self.features = ImageFeatures(fl[0]) for d in node.xpathEval("drive"): self.drives.append(Drive(d)) validate(self.type is not None, "The boot type must be provided") validate(self.type == "hvm" or self.type == "xen", "Boot type must be 'xen' or 'hvm', but is %s" % self.type) validate(self.arch is not None, "Missing guest arch") validate(self.loader is None or self.loader == "pygrub", "Invalid loader %s" % self.loader) validate([None, "hd", "cdrom"].count(self.bootdev) > 0, "Invalid bootdev %s" % self.bootdev) # We should make sure that kernel/initrd/cmdline are only used for pv # and without a loader class Drive: """The mapping of a disk from the storage section to a virtual drive in a guest""" def __init__(self, node = None): self.disk_id = None self.target = None self.disk = None # Will point to the underlying Disk object if node: self.parseXML(node) def parseXML(self, node): self.disk_id = xpathString(node, "@disk") self.target = xpathString(node, "@target") class Disk: FORMAT_RAW = "raw" FORMAT_ISO = "iso" FORMAT_QCOW = "qcow" FORMAT_QCOW2 = "qcow2" FORMAT_VMDK = "vmdk" USE_SYSTEM = "system" USE_USER = "user" USE_SCRATCH = "scratch" def __init__(self, node = None): self.id = None self.file = None self.format = None self.size = None self.use = None self.csum = {} if not node is None: self.parseXML(node) def parseXML(self, node): self.file = xpathString(node, "@file") self.id = xpathString(node, "@id", self.file) self.format = xpathString(node, "@format", Disk.FORMAT_RAW) self.size = xpathString(node, "@size") self.use = xpathString(node, "@use", Disk.USE_SYSTEM) for d in node.xpathEval("checksum"): csumtype = xpathString(d, "@type") csumvalue = xpathString(d, "") self.csum[csumtype] = csumvalue formats = [Disk.FORMAT_RAW, Disk.FORMAT_QCOW, Disk.FORMAT_QCOW2, Disk.FORMAT_VMDK, Disk.FORMAT_ISO] validate (formats.count(self.format) > 0, _("The format for disk %s must be one of %s") % (self.file, ",".join(formats))) def check_disk_signature(self, meter=None): try: import hashlib has_hashlib = True except: import sha has_hashlib = False meter_ct = 0 m = None disk_size = os.path.getsize(self.file) if meter: meter.start(size=disk_size, text=_("Checking disk signature for %s" % self.file)) if has_hashlib is True: if self.csum.has_key("sha256"): csumvalue = self.csum["sha256"] m = hashlib.sha256() elif self.csum.has_key("sha1"): csumvalue = self.csum["sha1"] m = hashlib.sha1() else: if self.csum.has_key("sha1"): csumvalue = self.csum["sha1"] m = sha.new() if not m: return f = open(self.file,"r") while 1: chunk = f.read(65536) if not chunk: break if meter: meter.update(meter_ct) meter_ct = meter_ct + 65536 m.update(chunk) checksum = m.hexdigest() if checksum != csumvalue: logging.debug(_("Disk signature for %s does not match " "Expected: %s Received: %s" % (self.file, csumvalue,checksum))) raise ValueError (_("Disk signature for %s does not " "match" % self.file)) def validate(cond, msg): if not cond: raise ParserException(msg) def xpathString(node, path, default = None): result = node.xpathEval("string(%s)" % path) if len(result) == 0: result = default return result def parse(xml, filename): """Parse the XML description of a VM image into a data structure. Returns an object of class Image. BASE should be the directory where the disk image files for this image can be found""" class ErrorHandler: def __init__(self): self.msg = "" def handler(self, ignore, s): self.msg += s error = ErrorHandler() libxml2.registerErrorHandler(error.handler, None) try: try: doc = libxml2.readMemory(xml, len(xml), None, None, libxml2.XML_PARSE_NOBLANKS) except (libxml2.parserError, libxml2.treeError), e: raise ParserException("%s\n%s" % (e, error.msg)) finally: libxml2.registerErrorHandler(None, None) try: root = doc.getRootElement() if root.name != "image": raise ParserException(_("Root element is not 'image'")) image = Image(root, filename = filename) finally: doc.freeDoc() return image def parse_file(filename): f = open(filename, "r") xml = f.read() f.close() return parse(xml, filename = filename) 0707010002b5aa000081a40000000000000002000000014b0fbd79000005f9000000b600010006ffffffffffffffff0000004100000000reloc/usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.py# # Copyright 2006-2009 Red Hat, Inc. # Daniel P. Berrange # # 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 Installer class PXEInstaller(Installer.Installer): # General Installer methods def prepare(self, guest, meter, distro = None): pass def get_install_xml(self, guest, isinstall): if isinstall: bootdev = "network" else: # TODO: This can be smarter, take into account different # disk types, media availability, etc. Probably relevant # for other installers as well. if len(guest.disks) == 0: bootdev = "network" else: bootdev = "hd" return self._get_osblob_helper(isinstall=isinstall, guest=guest, kernel=None, bootdev=bootdev) 0707010002b5ab000081a40000000000000002000000014b136d100000035f000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.pycm yKc@s&dkZdeifdYZdS(Nt PXEInstallercBstZddZdZRS(NcCsdS(N((tselftguesttmetertdistro((ta/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/PXEInstaller.pytpreparesc CsY|o d}n't|idjo d}nd}|id|d|ddd|S(Ntnetworkithdt isinstallRtkerneltbootdev(R R tlenRtdisksRt_get_osblob_helpertNone(RRR R ((Rtget_install_xmls  (t__name__t __module__RRR(((RRs (t InstallerR(RR((Rt?s 0707010002b5ae000081a40000000000000002000000014b0fbd7900008cbe000000b600010006ffffffffffffffff0000003c00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/Storage.py# # Copyright 2008 Red Hat, Inc. # Cole Robinson # # 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. """ Classes for building and installing libvirt storage xml General workflow for the different storage objects: 1. Storage Pool: Pool type options can be exposed to a user via the static function L{StoragePool.get_pool_types}. Any selection can be fed back into L{StoragePool.get_pool_class} to get the particular volume class to instantiate. From here, values can be set at init time or via properties post init. Different pool types have different options and requirements, so using getattr() is probably the best way to check for parameter availability. 2) Storage Volume: There are a few options for determining what pool volume class to use: - Pass the pools type for L{StoragePool.get_volume_for_pool} - Pass the pool object or name to L{StorageVolume.get_volume_for_pool} These will give back the appropriate class to instantiate. For most cases, all that's needed is a name and capacity, the rest will be filled in. @see: U{http://libvirt.org/storage.html} """ import libvirt import logging from xml.sax.saxutils import escape import _util from virtinst import _virtinst as _ DEFAULT_DEV_TARGET = "/dev" DEFAULT_LVM_TARGET_BASE = "/dev/" DEFAULT_DIR_TARGET_BASE = "/var/lib/libvirt/images/" DEFAULT_ISCSI_TARGET = "/dev/disk/by-path" # Pools: # DirectoryPool : A flat filesystem directory # FilesystemPool : A formatted partition # NetworkFilesystemPool : NFS # LogicalPool : LVM Volume Group # DiskPool : Raw disk # iSCSIPool : iSCSI class StorageObject(object): """ Base class for building any libvirt storage object. Mostly meaningless to directly instantiate. """ TYPE_POOL = "pool" TYPE_VOLUME = "volume" def __init__(self, object_type, name, conn=None): """ Initialize storage object parameters """ if object_type not in [self.TYPE_POOL, self.TYPE_VOLUME]: raise ValueError, _("Unknown storage object type: %s") % type self._object_type = object_type self._conn = None self._name = None if conn is not None: self.conn = conn self.name = name # Initialize all optional properties self._perms = None ## Properties def get_object_type(self): # 'pool' or 'volume' return self._object_type object_type = property(get_object_type) def get_conn(self): return self._conn def set_conn(self, val): if not isinstance(val, libvirt.virConnect): raise ValueError(_("'conn' must be a libvirt connection object.")) if not _util.is_storage_capable(val): raise ValueError(_("Passed connection is not libvirt storage " "capable")) self._conn = val conn = property(get_conn, set_conn, doc=""" Libvirt connection to check object against/install on """) def get_name(self): return self._name def set_name(self, val): _util.validate_name(_("Storage object"), val) # Check that name doesn't collide with other storage objects self._check_name_collision(val) self._name = val name = property(get_name, set_name, doc=_("Name for the storage object.")) # Get/Set methods for use by some objects. Will register where applicable def get_perms(self): return self._perms def set_perms(self, val): if type(val) is not dict: raise ValueError(_("Permissions must be passed as a dict object")) for key in ["mode", "owner", "group", "label"]: if not key in val: raise ValueError(_("Permissions must contain 'mode', 'owner', 'group' and 'label' keys.")) self._perms = val # Validation helper functions def _validate_path(self, path): if type(path) is not type("str") or not path.startswith("/"): raise ValueError(_("'%s' is not an absolute path." % path)) def _check_name_collision(self, name): raise RuntimeError, "Must be implemented in subclass" # XML Building def _get_storage_xml(self): """ Returns the pool/volume specific xml blob """ raise RuntimeError, "Must be implemented in subclass" def _get_perms_xml(self): perms = self.get_perms() if not perms: return "" return " \n" + \ " %o\n" % perms["mode"] + \ " %d\n" % perms["owner"] + \ " %d\n" % perms["group"] + \ " \n" % perms["label"] + \ " \n" def get_xml_config(self): """ Construct the xml description of the storage object @returns: xml description @rtype: C{str} """ if not hasattr(self, "type"): root_xml = "<%s>\n" % self.object_type else: _type = getattr(self, "type") root_xml = "<%s type='%s'>\n" % (self.object_type, _type) xml = "%s" % (root_xml) + \ """ %s\n""" % (self.name) + \ """%(stor_xml)s""" % { "stor_xml" : self._get_storage_xml() } + \ """""" % (self.object_type) return xml class StoragePool(StorageObject): """ Base class for building and installing libvirt storage pool xml """ TYPE_DIR = "dir" TYPE_FS = "fs" TYPE_NETFS = "netfs" TYPE_LOGICAL = "logical" TYPE_DISK = "disk" TYPE_ISCSI = "iscsi" """@group Types: TYPE_*""" # Pool type descriptions for use in higher level programs _types = {} _types[TYPE_DIR] = _("Filesystem Directory") _types[TYPE_FS] = _("Pre-Formatted Block Device") _types[TYPE_NETFS] = _("Network Exported Directory") _types[TYPE_LOGICAL] = _("LVM Volume Group") _types[TYPE_DISK] = _("Physical Disk Device") _types[TYPE_ISCSI] = _("iSCSI Target") def get_pool_class(ptype): """ Return class associated with passed pool type. @param ptype: Pool type @type ptype: C{str} member of L{Types} """ if ptype not in StoragePool._types: raise ValueError, _("Unknown storage pool type: %s" % ptype) if ptype == StoragePool.TYPE_DIR: return DirectoryPool if ptype == StoragePool.TYPE_FS: return FilesystemPool if ptype == StoragePool.TYPE_NETFS: return NetworkFilesystemPool if ptype == StoragePool.TYPE_LOGICAL: return LogicalPool if ptype == StoragePool.TYPE_DISK: return DiskPool if ptype == StoragePool.TYPE_ISCSI: return iSCSIPool get_pool_class = staticmethod(get_pool_class) def get_volume_for_pool(pool_type): """Convenience method, returns volume class associated with pool_type""" pool_class = StoragePool.get_pool_class(pool_type) return pool_class.get_volume_class() get_volume_for_pool = staticmethod(get_volume_for_pool) def get_pool_types(): """Return list of appropriate pool types""" return StoragePool._types.keys() get_pool_types = staticmethod(get_pool_types) def get_pool_type_desc(pool_type): """Return human readable description for passed pool type""" return StoragePool._types[pool_type] get_pool_type_desc = staticmethod(get_pool_type_desc) def __init__(self, conn, name, type, target_path=None, uuid=None): StorageObject.__init__(self, object_type=StorageObject.TYPE_POOL, \ name=name, conn=conn) if type not in self.get_pool_types(): raise ValueError, _("Unknown storage pool type: %s" % type) self._type = type self._target_path = None self._host = None self._format = None self._source_path = None if target_path is None: target_path = self._get_default_target_path() self.target_path = target_path # Initialize all optional properties self._host = None self._source_path = None if not uuid: self._uuid = None self._random_uuid = _util.uuidToString(_util.randomUUID()) # Properties used by all pools def get_type(self): return self._type type = property(get_type, doc=_("Storage device type the pool will represent.")) def get_target_path(self): return self._target_path def set_target_path(self, val): self._validate_path(val) self._target_path = val # Get/Set methods for use by some pools. Will be registered when applicable def get_source_path(self): return self._source_path def set_source_path(self, val): self._validate_path(val) self._source_path = val def get_host(self): return self._host def set_host(self, val): if type(val) is not type("str"): raise ValueError(_("Host name must be a string")) self._host = val """uuid: uuid of the storage object. optional: generated if not set""" def get_uuid(self): return self._uuid def set_uuid(self, val): val = _util.validate_uuid(val) self._uuid = val uuid = property(get_uuid, set_uuid) # Validation functions def _check_name_collision(self, name): pool = None try: pool = self.conn.storagePoolLookupByName(name) except libvirt.libvirtError: pass if pool: raise ValueError(_("Name '%s' already in use by another pool." % name)) def _get_default_target_path(self): raise RuntimeError, "Must be implemented in subclass" # XML Building def _get_target_xml(self): raise RuntimeError, "Must be implemented in subclass" def _get_source_xml(self): raise RuntimeError, "Must be implemented in subclass" def _get_storage_xml(self): src_xml = "" if self._get_source_xml() != "": src_xml = " \n" + \ "%s" % (self._get_source_xml()) + \ " \n" tar_xml = " \n" + \ "%s" % (self._get_target_xml()) + \ " \n" return " %s\n" % (self.uuid or self._random_uuid) + \ "%s" % src_xml + \ "%s" % tar_xml def install(self, meter=None, create=False, build=False): """ Install storage pool xml. """ xml = self.get_xml_config() logging.debug("Creating storage pool '%s' with xml:\n%s" % \ (self.name, xml)) try: pool = self.conn.storagePoolDefineXML(xml, 0) except Exception, e: raise RuntimeError(_("Could not define storage pool: %s" % str(e))) errmsg = None if build: if meter: #meter.start(size=None, text=_("Creating storage pool...")) pass try: pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW) except Exception, e: errmsg = _("Could not build storage pool: %s" % str(e)) if meter: #meter.end(0) pass if create and not errmsg: try: pool.create(0) except Exception, e: errmsg = _("Could not start storage pool: %s" % str(e)) if errmsg: # Try and clean up the leftover pool try: pool.undefine() except Exception, e: logging.debug("Error cleaning up pool after failure: " + "%s" % str(e)) raise RuntimeError(errmsg) return pool class DirectoryPool(StoragePool): """ Create a directory based storage pool """ def get_volume_class(): return FileVolume get_volume_class = staticmethod(get_volume_class) # Register applicable property methods from parent class perms = property(StorageObject.get_perms, StorageObject.set_perms) target_path = property(StoragePool.get_target_path, StoragePool.set_target_path, doc=_("Directory to use for the storage pool.")) def __init__(self, conn, name, target_path=None, uuid=None, perms=None): StoragePool.__init__(self, name=name, type=StoragePool.TYPE_DIR, target_path=target_path, uuid=uuid, conn=conn) if perms: self.perms = perms def _get_default_target_path(self): path = (DEFAULT_DIR_TARGET_BASE + self.name) return path def _get_target_xml(self): xml = " %s\n" % escape(self.target_path) + \ "%s" % self._get_perms_xml() return xml def _get_source_xml(self): return "" class FilesystemPool(StoragePool): """ Create a formatted partition based storage pool """ def get_volume_class(): return FileVolume get_volume_class = staticmethod(get_volume_class) formats = [ "auto", "ext2", "ext3", "ext4", "ufs", "iso9660", "udf", "gfs", "gfs2", "vfat", "hfs+", "xfs" ] # Register applicable property methods from parent class perms = property(StorageObject.get_perms, StorageObject.set_perms) source_path = property(StoragePool.get_source_path, StoragePool.set_source_path, doc=_("The existing device to mount for the pool.")) target_path = property(StoragePool.get_target_path, StoragePool.set_target_path, doc=_("Location to mount the source device.")) def __init__(self, conn, name, source_path=None, target_path=None, format="auto", uuid=None, perms=None): StoragePool.__init__(self, name=name, type=StoragePool.TYPE_FS, target_path=target_path, uuid=uuid, conn=conn) self.format = format if source_path: self.source_path = source_path if perms: self.perms = perms def get_format(self): return self._format def set_format(self, val): if not val in self.formats: raise ValueError(_("Unknown Filesystem format: %s" % val)) self._format = val format = property(get_format, set_format, doc=_("Filesystem type of the source device.")) def _get_default_target_path(self): path = (DEFAULT_DIR_TARGET_BASE + self.name) return path def _get_target_xml(self): xml = " %s\n" % escape(self.target_path) + \ "%s" % self._get_perms_xml() return xml def _get_source_xml(self): if not self.source_path: raise RuntimeError(_("Device path is required")) xml = " \n" % self.format + \ " \n" % escape(self.source_path) return xml class NetworkFilesystemPool(StoragePool): """ Create a network mounted filesystem storage pool """ def get_volume_class(): return FileVolume get_volume_class = staticmethod(get_volume_class) formats = [ "auto", "nfs" ] # Register applicable property methods from parent class source_path = property(StoragePool.get_source_path, StoragePool.set_source_path, doc=_("Path on the host that is being shared.")) host = property(StoragePool.get_host, StoragePool.set_host, doc=_("Name of the host sharing the storage.")) target_path = property(StoragePool.get_target_path, StoragePool.set_target_path, doc=_("Location to mount the source device.")) def __init__(self, conn, name, source_path=None, host=None, target_path=None, format="auto", uuid=None): StoragePool.__init__(self, name=name, type=StoragePool.TYPE_NETFS, uuid=uuid, target_path=target_path, conn=conn) self.format = format if source_path: self.source_path = source_path if host: self.host = host def get_format(self): return self._format def set_format(self, val): if not val in self.formats: raise ValueError(_("Unknown Network Filesystem format: %s" % val)) self._format = val format = property(get_format, set_format, doc=_("Type of network filesystem.")) def _get_default_target_path(self): path = (DEFAULT_DIR_TARGET_BASE + self.name) return path def _get_target_xml(self): xml = " %s\n" % escape(self.target_path) return xml def _get_source_xml(self): if not self.host: raise RuntimeError(_("Hostname is required")) if not self.source_path: raise RuntimeError(_("Host path is required")) xml = """ \n""" % self.format + \ """ \n""" % self.host + \ """ \n""" % escape(self.source_path) return xml class LogicalPool(StoragePool): """ Create a logical (lvm volume group) storage pool """ def get_volume_class(): return LogicalVolume get_volume_class = staticmethod(get_volume_class) # Register applicable property methods from parent class perms = property(StorageObject.get_perms, StorageObject.set_perms) target_path = property(StoragePool.get_target_path, StoragePool.set_target_path, doc=_("Location of the existing LVM volume group.")) def __init__(self, conn, name, target_path=None, uuid=None, perms=None): StoragePool.__init__(self, name=name, type=StoragePool.TYPE_LOGICAL, target_path=target_path, uuid=uuid, conn=conn) if perms: self.perms = perms def _get_default_target_path(self): return DEFAULT_LVM_TARGET_BASE + self.name def _get_target_xml(self): xml = " %s\n" % escape(self.target_path) + \ "%s" % self._get_perms_xml() return xml def _get_source_xml(self): return "" class DiskPool(StoragePool): """ Create a storage pool from a physical disk """ # Register applicable property methods from parent class source_path = property(StoragePool.get_source_path, StoragePool.set_source_path, doc=_("Path to the existing disk device.")) target_path = property(StoragePool.get_target_path, StoragePool.set_target_path, doc=_("Root location for identifying new storage" " volumes.")) formats = [ "auto", "bsd", "dos", "dvh", "gpt", "mac", "pc98", "sun" ] def get_volume_class(): raise NotImplementedError(_("Disk volume creation is not implemented.")) get_volume_class = staticmethod(get_volume_class) def __init__(self, conn, name, source_path=None, target_path=None, format="auto", uuid=None): StoragePool.__init__(self, name=name, type=StoragePool.TYPE_DISK, uuid=uuid, target_path=target_path, conn=conn) self.format = format if source_path: self.source_path = source_path def get_format(self): return self._format def set_format(self, val): if not val in self.formats: raise ValueError(_("Unknown Disk format: %s" % val)) self._format = val format = property(get_format, set_format, doc=_("Format of the source device's partition table.")) def _get_default_target_path(self): return DEFAULT_DEV_TARGET def _get_target_xml(self): xml = " %s\n" % escape(self.target_path) return xml def _get_source_xml(self): if not self.source_path: raise RuntimeError(_("Host path is required")) xml = "" # There is no explicit "auto" type for disk pools, but leaving out # the format type seems to do the job for existing formatted disks if self.format != "auto": xml = """ \n""" % self.format xml += """ \n""" % escape(self.source_path) return xml def install(self, meter=None, create=False, build=False): if self.format == "auto" and build: raise ValueError(_("Must explicitly specify disk format if " "formatting disk device.")) return StoragePool.install(self, meter=meter, create=create, build=build) class iSCSIPool(StoragePool): """ Create an iSCSI based storage pool """ host = property(StoragePool.get_host, StoragePool.set_host, doc=_("Name of the host sharing the storage.")) target_path = property(StoragePool.get_target_path, StoragePool.set_target_path, doc=_("Root location for identifying new storage" " volumes.")) def get_volume_class(): raise NotImplementedError(_("iSCSI volume creation is not " "implemented.")) get_volume_class = staticmethod(get_volume_class) def __init__(self, conn, name, source_path=None, host=None, target_path=None, uuid=None): StoragePool.__init__(self, name=name, type=StoragePool.TYPE_ISCSI, uuid=uuid, target_path=target_path, conn=conn) if source_path: self.source_path = source_path if host: self.host = host # Need to overwrite pool *_source_path since iscsi device isn't # a fully qualified path def get_source_path(self): return self._source_path def set_source_path(self, val): self._source_path = val source_path = property(get_source_path, set_source_path, doc=_("Path on the host that is being shared.")) def _get_default_target_path(self): return DEFAULT_ISCSI_TARGET def _get_target_xml(self): xml = " %s\n" % escape(self.target_path) return xml def _get_source_xml(self): if not self.host: raise RuntimeError(_("Hostname is required")) if not self.source_path: raise RuntimeError(_("Host path is required")) xml = """ \n""" % self.host + \ """ \n""" % escape(self.source_path) return xml class StorageVolume(StorageObject): """ Base class for building and installing libvirt storage volume xml """ formats = [] def __init__(self, name, capacity, conn=None, pool_name=None, pool=None, allocation=0): if pool is None: if pool_name is None: raise ValueError(_("One of pool or pool_name must be " "specified.")) if conn is None: raise ValueError(_("'conn' must be specified with 'pool_name'")) pool = StorageVolume.lookup_pool_by_name(pool_name=pool_name, conn=conn) self._pool = None self.pool = pool StorageObject.__init__(self, object_type=StorageObject.TYPE_VOLUME, name=name, conn=self.pool._conn) self._allocation = None self._capacity = None self._format = None self.allocation = allocation self.capacity = capacity def get_volume_for_pool(pool_object=None, pool_name=None, conn=None): """ Returns volume class associated with passed pool_object/name """ pool_object = StorageVolume.lookup_pool_by_name(pool_object=pool_object, pool_name=pool_name, conn=conn) return StoragePool.get_volume_for_pool(_util.get_xml_path(pool_object.XMLDesc(0), "/pool/@type")) get_volume_for_pool = staticmethod(get_volume_for_pool) def find_free_name(name, pool_object=None, pool_name=None, conn=None, suffix=""): """ Finds a name similar (or equal) to passed 'name' that is not in use by another pool This function scans the list of existing Volumes on the passed or looked up pool object for a collision with the passed name. If the name is in use, it append "-1" to the name and tries again, then "-2", continuing to 100000 (which will hopefully never be reached.") If suffix is specified, attach it to the (potentially incremented) name before checking for collision. Ex name="test", suffix=".img" -> name-3.img @returns: A free name @rtype: C{str} """ pool_object = StorageVolume.lookup_pool_by_name(pool_object=pool_object, pool_name=pool_name, conn=conn) pool_object.refresh(0) for i in range(0, 100000): tryname = name if i != 0: tryname += ("-%d" % i) tryname += suffix try: pool_object.storageVolLookupByName(tryname) except libvirt.libvirtError: return tryname raise ValueError(_("Default volume target path range exceeded.")) find_free_name = staticmethod(find_free_name) def lookup_pool_by_name(pool_object=None, pool_name=None, conn=None): """ Returns pool object determined from passed parameters. Largely a convenience function for the other static functions. """ if pool_object is None and pool_name is None: raise ValueError(_("Must specify pool_object or pool_name")) if pool_name is not None and pool_object is None: if conn is None: raise ValueError(_("'conn' must be specified with 'pool_name'")) if not _util.is_storage_capable(conn): raise ValueError(_("Connection does not support storage " "management.")) try: pool_object = conn.storagePoolLookupByName(pool_name) except Exception, e: raise ValueError(_("Couldn't find storage pool '%s': %s" % \ (pool_name, str(e)))) if not isinstance(pool_object, libvirt.virStoragePool): raise ValueError(_("pool_object must be a virStoragePool")) return pool_object lookup_pool_by_name = staticmethod(lookup_pool_by_name) # Properties used by all volumes def get_capacity(self): return self._capacity def set_capacity(self, val): if type(val) not in (int, float, long) or val <= 0: raise ValueError(_("Capacity must be a positive number")) newcap = int(val) origcap = self.capacity origall = self.allocation self._capacity = newcap if self.allocation != None and (newcap < self.allocation): self._allocation = newcap ret = self.is_size_conflict() if ret[0]: self._capacity = origcap self._allocation = origall raise ValueError(ret[1]) elif ret[1]: logging.warn(ret[1]) capacity = property(get_capacity, set_capacity) def get_allocation(self): return self._allocation def set_allocation(self, val): if type(val) not in (int, float, long) or val < 0: raise ValueError(_("Allocation must be a non-negative number")) newall = int(val) if self.capacity != None and newall > self.capacity: logging.debug("Capping allocation at capacity.") newall = self.capacity origall = self._allocation self._allocation = newall ret = self.is_size_conflict() if ret[0]: self._allocation = origall raise ValueError(ret[1]) elif ret[1]: logging.warn(ret[1]) allocation = property(get_allocation, set_allocation) def get_pool(self): return self._pool def set_pool(self, newpool): if not isinstance(newpool, libvirt.virStoragePool): raise ValueError, _("'pool' must be a virStoragePool instance.") if newpool.info()[0] != libvirt.VIR_STORAGE_POOL_RUNNING: raise ValueError, _("pool '%s' must be active." % newpool.name()) self._pool = newpool pool = property(get_pool, set_pool) # Property functions used by more than one child class def get_format(self): return self._format def set_format(self, val): if val not in self.formats: raise ValueError(_("'%s' is not a valid format.") % val) self._format = val def _check_name_collision(self, name): vol = None try: vol = self.pool.storageVolLookupByName(name) except libvirt.libvirtError: pass if vol: raise ValueError(_("Name '%s' already in use by another volume." % name)) def _check_target_collision(self, path): col = None try: col = self.conn.storageVolLookupByPath(path) except libvirt.libvirtError: pass if col: return True return False # xml building functions def _get_target_xml(self): raise RuntimeError, "Must be implemented in subclass" def _get_source_xml(self): raise RuntimeError, "Must be implemented in subclass" def _get_storage_xml(self): src_xml = "" if self._get_source_xml() != "": src_xml = " \n" + \ "%s" % (self._get_source_xml()) + \ " \n" tar_xml = " \n" + \ "%s" % (self._get_target_xml()) + \ " \n" return " %d\n" % self.capacity + \ " %d\n" % self.allocation + \ "%s" % src_xml + \ "%s" % tar_xml def install(self, meter=None): """ Build and install storage volume from xml """ xml = self.get_xml_config() logging.debug("Creating storage volume '%s' with xml:\n%s" % \ (self.name, xml)) if meter: #meter.start(size=self.capacity, # text=_("Creating storage volume...")) # XXX: We don't have any meaningful way to update the meter # XXX: throughout the operation, so just skip it pass try: vol = self.pool.createXML(xml, 0) except Exception, e: raise RuntimeError("Couldn't create storage volume '%s': '%s'" % (self.name, str(e))) if meter: #meter.end(0) pass logging.debug("Storage volume '%s' install complete." % self.name) return vol def is_size_conflict(self): """ Report if requested size exceeds its pool's available amount @returns: 2 element tuple: 1. True if collision is fatal, false otherwise 2. String message if some collision was encountered. @rtype: 2 element C{tuple}: (C{bool}, C{str}) """ # pool info is [ pool state, capacity, allocation, available ] avail = self.pool.info()[3] if self.allocation > avail: return (True, _("There is not enough free space on the storage " "pool to create the volume. " "(%d M requested allocation > %d M available)" % \ ((self.allocation/(1024*1024)), (avail/(1024*1024))))) elif self.capacity > avail: return (False, _("The requested volume capacity will exceed the " "available pool space when the volume is fully " "allocated. " "(%d M requested capacity > %d M available)" % \ ((self.capacity/(1024*1024)), (avail/(1024*1024))))) return (False, "") class FileVolume(StorageVolume): """ Build and install xml for use on pools which use file based storage """ formats = ["raw", "bochs", "cloop", "cow", "dmg", "iso", "qcow",\ "qcow2", "vmdk", "vpc"] # Register applicable property methods from parent class perms = property(StorageObject.get_perms, StorageObject.set_perms) format = property(StorageVolume.get_format, StorageVolume.set_format) def __init__(self, name, capacity, pool=None, pool_name=None, conn=None, format="raw", allocation=None, perms=None): StorageVolume.__init__(self, name=name, pool=pool, pool_name=pool_name, allocation=allocation, capacity=capacity, conn=conn) self.format = format if perms: self.perms = perms def _get_target_xml(self): return " \n" % self.format + \ "%s" % self._get_perms_xml() def _get_source_xml(self): return "" #class DiskVolume(StorageVolume): # """ # Build and install xml for use on disk device pools # """ # def __init__(self, *args, **kwargs): # raise NotImplementedError #class iSCSIVolume(StorageVolume): # """ # Build and install xml for use on iSCSI device pools # """ # def __init__(self, *args, **kwargs): # raise NotImplementedError class LogicalVolume(StorageVolume): """ Build and install logical volumes for lvm pools """ # Register applicable property methods from parent class perms = property(StorageObject.get_perms, StorageObject.set_perms) def __init__(self, name, capacity, pool=None, pool_name=None, conn=None, allocation=None, perms=None): StorageVolume.__init__(self, name=name, pool=pool, pool_name=pool_name, allocation=allocation, capacity=capacity, conn=conn) if perms: self.perms = perms def _get_target_xml(self): return "%s" % self._get_perms_xml() def _get_source_xml(self): return "" 0707010002b5a3000081a40000000000000002000000014b136d1000002b9d000000b600010006ffffffffffffffff0000003f00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/Installer.pycm mKc@sdkZdkZdkZdkZdkZdkZdkZdklZdklZ dk l Z dZ dZ de fdYZdS(N(sCapabilitiesParser(s _virtinst(s VirtualDisks /var/lib/xens/var/lib/libvirt/boott InstallercBstZdZdeeeeedZdZeeZdZeeZ dZ dZ ee e Z dZ dZee eZd Zd ZeeeZd ZeeZd Zd ZeeeZdZdZeeeZdZdZeeeZdZdZeeeZ eedZ!dZ"dZ#edZ$dZ%dZ&dZ'RS(s Installer classes attempt to encapsulate all the parameters needed to 'install' a guest: essentially, booting the guest with the correct media for the OS install phase (if there is one), and setting up the guest to boot to the correct media for all subsequent runs. Some of the actual functionality: - Determining what type of install media has been requested, and representing it correctly to the Guest - Fetching install kernel/initrd or boot.iso from a URL - Setting the boot device as appropriate depending on whether we are booting into an OS install, or booting post-install Some of the information that the Installer needs to know to accomplish this: - Install media location (could be a URL, local path, ...) - Virtualization type (parameter 'os_type') ('xen', 'hvm', etc.) - Hypervisor name (parameter 'type') ('qemu', 'kvm', 'xen', etc.) - Guest architecture ('i686', 'x86_64') txencCs*d|_d|_d|_d|_t|_d|_||_ d|_ |i o1t i |i i|_|iii|_nd|_d|_|djo d}n||_|dj o ||_n|dj o ||_n|dj o ||_n|dj o ||_ng|_dS(NR(tNonetselft_typet _locationt _extraargst_boottFalset_cdromt_os_typetconnt_connt _install_disktCapabilitiesParsertparsetgetCapabilitiest_capsthosttarcht_archttypetos_typetlocationtboott extraargst _tmpfiles(RRRRRRR ((t^/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/Installer.pyt__init__=s2                      cCs|iS(N(RR (R((Rtget_install_diskdscCs|iS(N(RR (R((Rtget_connhscCs|iS(N(RR(R((Rtget_typemscCs ||_dS(N(tvalRR(RR ((Rtset_typeoscCs|iS(N(RR (R((Rt get_os_typetscCs$|djo d}n||_dS(NtlinuxR(R RR (RR ((Rt set_os_typevs  cCs|iS(N(RR(R((Rtget_archscCs ||_dS(N(R RR(RR ((Rtset_archscCstidjodSn|idjotiitotSntidjotiit ot Sntii dSdS(NtSunOSs/var/tmpRis~/.virtinst/boot( tplatformtsystemRRtostpathtexistst XEN_SCRATCHtgeteuidtLIBVIRT_SCRATCHt expanduser(R((Rtget_scratchdirs#&cCs|iS(N(RR (R((Rt get_cdromscCs3|ttgjottdn||_dS(Ns"Guest.cdrom must be a boolean type(tenabletTrueRt ValueErrort_RR (RR3((Rt set_cdromscCs|iS(N(RR(R((Rt get_locationscCs ||_dS(N(R RR(RR ((Rt set_locationscCs|iS(N(RR(R((Rtget_bootscCs5t|_t|tjoQt|djottdn|\}}hd|<d|<|_ nt|t joB|i d p|i d ottdn||_ npt|tjoMt|djottdnhd|d<d|d<|_ nttddS(Nis"Must pass both a kernel and initrdtkerneltinitrdiis>Kernel and initrd must be specified by a list, dict, or tuple.(RRtcdromRR ttupletlenR5R6tktiRtdictthas_keytlist(RR RAR@((Rtset_boots  " 'cCs|iS(N(RR(R((Rtget_extra_argsscCs ||_dS(N(R RR(RR ((Rtset_extra_argssc Csd} t}t|tio t}n|i} |i }| |d}d}| o| odti| Snd}|i} | djo|idjo d} n|o|d|| f7}n|d | 7}|o|d |7}n|og|o`|d oU|d ti|d 7}|d ti|d7}|dti|d7}n |dj o|d|7}n|d7}|S(NcCs%t||ot||SndS(N(thasattrtobjt paramnametgetattrR(RIRJ((Rt get_paramstloaderts%ss RR#s %s s %s s %s R;s %s s %s R<s %s Rs s (RLRtishvmt isinstancetguesttvirtinstt FullVirtGuestR4R RRRMtosblobt isinstallt_utilt pygrub_pathRRR;t xml_escapetbootdevR( RRQRUR;RYRRTRMRORLRR ((Rt_get_osblob_helpers6        cCs tdS(s Generate the portion of the guest xml that determines boot devices and parameters. (typically the block) @param guest: Guest instance we are installing @type guest: L{Guest} @param isinstall: Whether we want xml for the 'install' phase or the 'post-install' phase. @type isinstall: C{bool} N(tNotImplementedError(RRQRU((Rtget_install_xmls cCs?x/|iD]$}tid|ti|q Wg|_dS(sJ Remove any temporary files retrieved during installation s Removing N(RRtftloggingtdebugR*tunlink(RR]((Rtcleanups  cCstddS(s; Fetch any files needed for installation. @param guest: guest instance being installed @type L{Guest} @param meter: progress meter @type Urlgrabber ProgressMeter @param distro: Name of distro being installed @type C{str} name from Guest os dictionary sMust be implemented in subclassN(R[(RRQtmetertdistro((Rtprepare s cCsMti|iiotSnt|idjp|idit i jotSnti |idi dotSny#ti|idi ti}WnZtj oN\}}tid||tijotidjotSqnXti|d}ti|t|djotid|dd!djS( s Attempt to verify that installing to disk was successful. @param guest: guest instance that was installed @type L{Guest} isFailed to open guest disk: %sitHiiUN(iU(RVt is_uri_remoteRQR tgetURIR4R?tdiskstdevicet VirtualDiskt DEVICE_DISKtis_vdiskR+RR*topentO_RDONLYtfdtOSErrorterrtmsgR^R_terrnotEACCESR.treadtbuftclosetstructtunpack(RRQRqRvRoRr((Rtpost_install_checks"0## cCsdS(s Attempt to detect the distro for the Installer's 'location'. If an error is encountered in the detection process (or if detection is not relevant for the Installer type), (None, None) is returned @returns: (distro type, distro variant) tuple N(NN(R(R((Rt detect_distro9sc Cs|ipttdntid|id|id|id|id|i \}}|idjo+t i d|d |i}|i |_ ng|id jo=t id|d |id |id|i }|i|_nttd |i|S(s Return a L{Guest} instance wrapping the current installer. If all the appropriate values are present in the installer (conn, type, os_type, arch), we have everything we need to determine what L{Guest} class is expected and what default values to pass it. This is a convenience method to save the API user from having to enter all these known details twice. sA connection must be specified.R tcapsRRRRt installert connectionthvmtemulators-No 'Guest' class for virtualization type '%s'N(RR R5R6Rt guest_lookupRRRRRQtdomainRRt ParaVirtGuesttgobjRSRRM(RRRQR((Rtguest_from_installerCs&        ((t__name__t __module__t__doc__RRRtpropertyt install_diskRR RR!RR"R$RR%R&RR1t scratchdirR2R7R=R8R9RR:RERRFRGRRZR\RaRdRzR{R(((RR$sH '                   5  (R*RsRxR(R^RVRRRt _virtinstR6RjR-R/tobjectR( RRR^RxRsRRjRVR(RR/R-R*R6((Rt?s        0707010002b598000081a40000000000000002000000014b136d0f00007265000000b600010006ffffffffffffffff0000003a00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/Guest.py# # Common code for all guests # # Copyright 2006-2009 Red Hat, Inc. # Jeremy Katz # # 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 os, os.path import time import re import urlgrabber.progress as progress import _util import libvirt import CapabilitiesParser import VirtualGraphics import osdict from virtinst import _virtinst as _ import logging import signal class Guest(object): # OS Dictionary static variables and methods _DEFAULTS = osdict.DEFAULTS _OS_TYPES = osdict.OS_TYPES def list_os_types(): return osdict.sort_helper(Guest._OS_TYPES) list_os_types = staticmethod(list_os_types) def list_os_variants(type): return osdict.sort_helper(Guest._OS_TYPES[type]["variants"]) list_os_variants = staticmethod(list_os_variants) def get_os_type_label(type): return Guest._OS_TYPES[type]["label"] get_os_type_label = staticmethod(get_os_type_label) def get_os_variant_label(type, variant): return Guest._OS_TYPES[type]["variants"][variant]["label"] get_os_variant_label = staticmethod(get_os_variant_label) def __init__(self, type=None, connection=None, hypervisorURI=None, installer=None): # We specifically ignore the 'type' parameter here, since # it has been replaced by installer.type, and child classes can # use it when creating a default installer. self._installer = installer self._name = None self._uuid = None self._memory = None self._maxmemory = None self._vcpus = 1 self._cpuset = None self._graphics_dev = None self._consolechild = None self._autocf = None self._has_autocf = False self._os_type = None self._os_variant = None # Public device lists unaltered by install process self.disks = [] self.nics = [] self.sound_devs = [] self.hostdevs = [] # Device lists to use/alter during install process self._install_disks = [] self._install_nics = [] # The libvirt virDomain object we 'Create' self.domain = None # Default disk target prefix ('hd' or 'xvd'). Set in subclass self.disknode = None self.conn = connection if self.conn == None: logging.debug("No conn passed to Guest, opening URI '%s'" % \ hypervisorURI) self.conn = libvirt.open(hypervisorURI) if self.conn == None: raise RuntimeError, _("Unable to connect to hypervisor, aborting " "installation!") self._caps = CapabilitiesParser.parse(self.conn.getCapabilities()) # location of auto-install config data (Solaris jumpstart, kickstart or OpenSolaris AI) def get_autocf(self): return self._autocf def has_autocf(self): return self._has_autocf def set_autocf(self, val): if type(val) is not type("string"): raise ValueError, _("You must specify a value for autoconfiguration data") if val.startswith('/') and not os.path.exists(val): raise ValueError, _("autocf floppy image. \"%s\" not found.") elif val is not "": self._autocf = val self._has_autocf = True autocf = property(get_autocf, set_autocf) def get_installer(self): return self._installer def set_installer(self, val): # FIXME: Make sure this is valid: it's pretty fundamental to # working operation. Should we even allow it to be changed? self._installer = val installer = property(get_installer, set_installer) # Domain name of the guest def get_name(self): return self._name def set_name(self, val): _util.validate_name(_("Guest"), val) try: self.conn.lookupByName(val) except: # Name not found self._name = val return raise ValueError(_("Guest name '%s' is already in use.") % val) name = property(get_name, set_name) # Memory allocated to the guest. Should be given in MB def get_memory(self): return self._memory def set_memory(self, val): if (type(val) is not type(1) or val <= 0): raise ValueError, _("Memory value must be an integer greater " "than 0") self._memory = val if self._maxmemory is None or self._maxmemory < val: self._maxmemory = val memory = property(get_memory, set_memory) # Memory allocated to the guest. Should be given in MB def get_maxmemory(self): return self._maxmemory def set_maxmemory(self, val): if (type(val) is not type(1) or val <= 0): raise ValueError, _("Max Memory value must be an integer greater " "than 0") self._maxmemory = val maxmemory = property(get_maxmemory, set_maxmemory) # UUID for the guest def get_uuid(self): return self._uuid def set_uuid(self, val): val = _util.validate_uuid(val) self._uuid = val uuid = property(get_uuid, set_uuid) # number of vcpus for the guest def get_vcpus(self): return self._vcpus def set_vcpus(self, val): maxvcpus = _util.get_max_vcpus(self.conn, self.type) if type(val) is not int or val < 1: raise ValueError, _("Number of vcpus must be a postive integer.") if val > maxvcpus: raise ValueError, _("Number of vcpus must be no greater than %d " "for this vm type.") % maxvcpus self._vcpus = val vcpus = property(get_vcpus, set_vcpus) # set phy-cpus for the guest def get_cpuset(self): return self._cpuset def set_cpuset(self, val): if type(val) is not type("string") or len(val) == 0: raise ValueError, _("cpuset must be string") if re.match("^[0-9,-]*$", val) is None: raise ValueError, _("cpuset can only contain numeric, ',', or " "'-' characters") pcpus = _util.get_phy_cpus(self.conn) for c in val.split(','): if c.find('-') != -1: (x, y) = c.split('-') if int(x) > int(y): raise ValueError, _("cpuset contains invalid format.") if int(x) >= pcpus or int(y) >= pcpus: raise ValueError, _("cpuset's pCPU numbers must be less " "than pCPUs.") else: if int(c) >= pcpus: raise ValueError, _("cpuset's pCPU numbers must be less " "than pCPUs.") self._cpuset = val cpuset = property(get_cpuset, set_cpuset) def get_graphics_dev(self): return self._graphics_dev def set_graphics_dev(self, val): self._graphics_dev = val graphics_dev = property(get_graphics_dev, set_graphics_dev) # GAH! - installer.os_type = "hvm" or "xen" (aka xen paravirt) # guest.os_type = "Solaris", "Windows", "Linux" # FIXME: We should really rename this property to something else, # change it throughout the codebase for readability sake, but # maintain back compat. def get_os_type(self): return self._os_type def set_os_type(self, val): if type(val) is not str: raise ValueError(_("OS type must be a string.")) val = val.lower() if self._OS_TYPES.has_key(val): if self._os_type == val: # No change, don't invalidate variant return # Invalidate variant, since it may not apply to the new os type self._os_type = val self._os_variant = None else: raise ValueError, _("OS type '%s' does not exist in our " "dictionary") % val os_type = property(get_os_type, set_os_type) def get_os_variant(self): return self._os_variant def set_os_variant(self, val): if type(val) is not str: raise ValueError(_("OS variant must be a string.")) val = val.lower() if self.os_type: if self._OS_TYPES[self.os_type]["variants"].has_key(val): self._os_variant = val else: raise ValueError, _("OS variant '%(var)s; does not exist in " "our dictionary for OS type '%(ty)s'" ) % \ {'var' : val, 'ty' : self._os_type} else: for ostype in self.list_os_types(): if self._OS_TYPES[ostype]["variants"].has_key(val) and \ not self._OS_TYPES[ostype]["variants"][val].get("skip"): logging.debug("Setting os type to '%s' for variant '%s'" %\ (ostype, val)) self.os_type = ostype self._os_variant = val return raise ValueError, _("Unknown OS variant '%s'" % val) os_variant = property(get_os_variant, set_os_variant) # Get the current variants 'distro' tag: 'rhel', 'fedora', etc. def get_os_distro(self): return self._lookup_osdict_key("distro") os_distro = property(get_os_distro) # DEPRECATED PROPERTIES # Deprecated: Should set graphics_dev.keymap directly def get_keymap(self): if self._graphics_dev is None: return None return self._graphics_dev.keymap def set_keymap(self, val): if self._graphics_dev is not None: self._graphics_dev.keymap = val keymap = property(get_keymap, set_keymap) # Deprecated: Should set guest.graphics_dev = VirtualGraphics(...) def get_graphics(self): if self._graphics_dev is None: return { "enabled" : False } return { "enabled" : True, "type" : self._graphics_dev, \ "keymap" : self._graphics_dev.keymap} def set_graphics(self, val): # val can be: # a dictionary with keys: enabled, type, port, keymap # a tuple of the form : (enabled, type, port, keymap) # last 2 optional # : "vnc", "sdl", or false port = None gtype = None enabled = False keymap = None gdev = None if type(val) == dict: if not val.has_key("enabled"): raise ValueError, _("Must specify whether graphics are enabled") enabled = val["enabled"] if val.has_key("type"): gtype = val["type"] if val.has_key("opts"): port = val["opts"] elif type(val) == tuple: if len(val) >= 1: enabled = val[0] if len(val) >= 2: gtype = val[1] if len(val) >= 3: port = val[2] if len(val) >= 4: keymap = val[3] else: if val in ("vnc", "sdl"): gtype = val enabled = True else: enabled = val if enabled not in (True, False): raise ValueError, _("Graphics enabled must be True or False") if enabled: gdev = VirtualGraphics.VirtualGraphics(type=gtype) if port: gdev.port = port if keymap: gdev.keymap = keymap self._graphics_dev = gdev graphics = property(get_graphics, set_graphics) # Properties that are mapped through to the Installer # Hypervisor name (qemu, xen, kvm, etc.) def get_type(self): return self._installer.type def set_type(self, val): self._installer.type = val type = property(get_type, set_type) def get_arch(self): return self.installer.arch def set_arch(self, val): self.installer.arch = val arch = property(get_arch, set_arch) # Deprecated: Should be called from the installer directly def get_location(self): return self._installer.location def set_location(self, val): self._installer.location = val location = property(get_location, set_location) # Deprecated: Should be called from the installer directly def get_scratchdir(self): return self._installer.scratchdir scratchdir = property(get_scratchdir) # Deprecated: Should be called from the installer directly def get_boot(self): return self._installer.boot def set_boot(self, val): self._installer.boot = val boot = property(get_boot, set_boot) # Deprecated: Should be called from the installer directly def get_extraargs(self): return self._installer.extraargs def set_extraargs(self, val): self._installer.extraargs = val extraargs = property(get_extraargs, set_extraargs) # Deprecated: Should set the installer values directly def get_cdrom(self): return self._installer.location def set_cdrom(self, val): if val is None or type(val) is not type("string") or len(val) == 0: raise ValueError, _("You must specify a valid ISO or CD-ROM location for the installation") if val.startswith("/"): if not os.path.exists(val): raise ValueError, _("The specified media path does not exist.") self._installer.location = os.path.abspath(val) else: # Assume its a http/nfs/ftp style path self._installer.location = val self._installer.cdrom = True cdrom = property(get_cdrom, set_cdrom) # END DEPRECATED PROPERTIES # Private xml building methods def _get_disk_xml(self, install=True): """Return xml for disk devices (Must be implemented in subclass)""" raise NotImplementedError def _get_clock_xml(self): val = self._lookup_osdict_key("clock") return """""" % val def _get_network_xml(self): """Get the network config in the libvirt XML format""" xml = "" for n in self._install_nics: xml = _util.xml_append(xml, n.get_xml_config()) return xml def _get_graphics_xml(self): """Get the graphics config in the libvirt XML format.""" if self._graphics_dev is None: return "" return self._graphics_dev.get_xml_config() def _get_input_device(self): """ Return a tuple of the form (devtype, bus) for the desired input device. (Must be implemented in subclass) """ raise NotImplementedError def _get_input_xml(self): """Get the input device config in libvirt XML format.""" (devtype, bus) = self._get_input_device() return " " % (devtype, bus) def _get_sound_xml(self): """Get the sound device configuration in libvirt XML format.""" xml = "" for sound_dev in self.sound_devs: xml = _util.xml_append(xml, sound_dev.get_xml_config()) return xml def _get_hostdev_xml(self): xml = "" for hostdev in self.hostdevs: xml = _util.xml_append(xml, hostdev.get_xml_config()) return xml def _get_device_xml(self, install=True): xml = "" xml = _util.xml_append(xml, self._get_disk_xml(install)) xml = _util.xml_append(xml, self._get_network_xml()) xml = _util.xml_append(xml, self._get_input_xml()) xml = _util.xml_append(xml, self._get_graphics_xml()) xml = _util.xml_append(xml, self._get_sound_xml()) xml = _util.xml_append(xml, self._get_hostdev_xml()) return xml def _get_features_xml(self): """ Return features (pae, acpi, apic) xml (currently only releavnt for FV) """ return "" def _get_osblob(self, install): """Return os, features, and clock xml (Implemented in subclass)""" xml = "" osxml = self.installer.get_install_xml(self, install) if not osxml: return None xml = _util.xml_append(xml, self.installer.get_install_xml(self, install)) xml = _util.xml_append(xml, self._get_features_xml()) xml = _util.xml_append(xml, self._get_clock_xml()) return xml def get_config_xml(self, install = True, disk_boot = False): """ Return the full Guest xml configuration. @param install: Whether we want the 'OS install' configuration or the 'post-install' configuration. (Some Installers, like the LiveCDInstaller may not have an 'install' config.) @type install: C{bool} @param disk_boot: Whether we should boot off the harddisk, regardless of our position in the install process (this is used for 2 stage installs, where the second stage boots off the disk. You probably don't need to touch this.) @type disk_boot: C{bool} """ if install: action = "destroy" else: action = "restart" osblob_install = install if disk_boot: osblob_install = False osblob = self._get_osblob(osblob_install) if not osblob: # This means there is no 'install' phase, so just return return None if self.cpuset is not None: cpuset = " cpuset='" + self.cpuset + "'" else: cpuset = "" os_type = self.os_type if not os_type: os_type = "unknown" os_variant = self.os_variant if not os_variant: os_variant = "unknown" return """ %(name)s %(ramkb)s %(maxramkb)s %(uuid)s %(osblob)s destroy %(action)s %(action)s %(os_type)s %(os_variant)s %(vcpus)d %(devices)s """ % { "type": self.type, "name": self.name, \ "os_type": os_type, \ "os_variant": os_variant, \ "vcpus": self.vcpus, \ "cpuset": cpuset, \ "uuid": self.uuid, \ "ramkb": self.memory * 1024, \ "maxramkb": self.maxmemory * 1024, \ "devices": self._get_device_xml(install), \ "osblob": osblob, \ "action": action } def start_install(self, consolecb=None, meter=None, removeOld=False, wait=True, define=True): """Do the startup of the guest installation.""" self.validate_parms() self._consolechild = None if meter is None: # BaseMeter does nothing, but saves a lot of null checking meter = progress.BaseMeter() self._prepare_install(meter) try: return self._do_install(consolecb, meter, removeOld, wait, define) finally: self._installer.cleanup() def get_continue_inst(self): val = self._lookup_osdict_key("continue") if not val: val = False if val == True: # If we are doing an 'import' or 'liveCD' install, there is # no true install process, so continue install has no meaning if not self.get_config_xml(install=True): val = False return val def continue_install(self, consolecb, meter, wait=True, define=True): cont_xml = self.get_config_xml(disk_boot = True) logging.debug("Continuing guest with:\n%s" % cont_xml) meter.start(size=None, text="Starting domain...") if define: # As of libvirt 0.5.1 we can't 'create' over an defined VM. # So, redefine the existing domain (which should be shutoff at # this point), and start it. finalxml = self.domain.XMLDesc(0) self.domain = self.conn.defineXML(cont_xml) self.domain.create() self.conn.defineXML(finalxml) else: self.domain = self.conn.createXML(cont_xml, 0) if self.domain is None: raise RuntimeError, _("Unable to start domain for guest, aborting installation!") meter.end(0) self.connect_console(consolecb, wait) # ensure there's time for the domain to finish destroying if the # install has finished or the guest crashed if consolecb: time.sleep(1) # This should always work, because it'll lookup a config file # for inactive guest, or get the still running install.. return self.conn.lookupByName(self.name) def _prepare_install(self, meter): self._install_disks = self.disks[:] self._install_nics = self.nics[:] self._set_defaults() self._installer.prepare(guest = self, meter = meter) if self._installer.install_disk is not None: self._install_disks.append(self._installer.install_disk) def _create_devices(self, progresscb): """Ensure that devices are setup""" for disk in self._install_disks: disk.setup(progresscb) for nic in self._install_nics: nic.setup(self.conn) for hostdev in self.hostdevs: hostdev.setup() def _do_install(self, consolecb, meter, removeOld=False, wait=True, define=True): vm = None try: vm = self.conn.lookupByName(self.name) except libvirt.libvirtError: pass if vm is not None: if removeOld : try: if vm.ID() != -1: logging.info("Destroying image %s" %(self.name)) vm.destroy() logging.info("Removing old definition for image %s" %(self.name)) vm.undefine() except libvirt.libvirtError, e: raise RuntimeError, _("Could not remove old vm '%s': %s") %(self.name, str(e)) else: raise RuntimeError, _("Domain named %s already exists!") %(self.name,) child = None self._create_devices(meter) install_xml = self.get_config_xml() if install_xml: logging.debug("Creating guest from:\n%s" % install_xml) meter.start(size=None, text=_("Creating domain...")) self.domain = self.conn.createXML(install_xml, 0) if self.domain is None: raise RuntimeError, _("Unable to create domain for the guest, aborting installation!") meter.end(0) logging.debug("Created guest, looking to see if it is running") d = _wait_for_domain(self.conn, self.name) if d is None: raise RuntimeError, _("It appears that your installation has crashed. You should be able to find more information in the logs") if consolecb and not self.conn.getURI() == "test:///default": logging.debug("Launching console callback") child = consolecb(self.domain) self._consolechild = child boot_xml = self.get_config_xml(install = False) if self.conn.getURI() == "test:///default": logging.debug("test hypervisor selected") print boot_xml return None if define: logging.debug("Saving XML boot config:\n%s" % boot_xml) self.conn.defineXML(boot_xml) if child and wait: # if we connected the console, wait for it to finish try: os.waitpid(child, 0) except OSError, (err_no, msg): print __name__, "waitpid: %s: %s" % (err_no, msg) # ensure there's time for the domain to finish destroying if the # install has finished or the guest crashed time.sleep(1) # This should always work, because it'll lookup a config file # for inactive guest, or get the still running install.. return self.conn.lookupByName(self.name) def post_install_check(self): return self.installer.post_install_check(self) def connect_console(self, consolecb, wait=True): logging.debug("Restarted guest, looking to see if it is running") self.domain = _wait_for_domain(self.conn, self.name) if self.domain is None: raise RuntimeError, _("Domain has not existed. You should be able to find more information in the logs") elif self.domain.ID() == -1: raise RuntimeError, _("Domain has not run yet. You should be able to find more information in the logs") child = None if consolecb: logging.debug("Launching console callback") child = consolecb(self.domain) self._consolechild = child if child and wait: # if we connected the console, wait for it to finish try: os.waitpid(child, 0) except OSError, (err_no, msg): raise RuntimeError, \ "waiting console pid error: %s: %s" % (err_no, msg) def validate_parms(self): if self.domain is not None: raise RuntimeError, _("Domain has already been started!") def _set_defaults(self): if self.uuid is None: while 1: self.uuid = _util.uuidToString(_util.randomUUID()) if _util.vm_uuid_collision(self.conn, self.uuid): continue break else: if _util.vm_uuid_collision(self.conn, self.uuid): raise RuntimeError, _("The UUID you entered is already in " "use by another guest!") if self.name is None or self.memory is None: raise RuntimeError, _("Name and memory must be specified for all guests!") # Guest Dictionary Helper methods def _lookup_osdict_key(self, key): """ Using self.os_type and self.os_variant to find key in OSTYPES @returns: dict value, or None if os_type/variant wasn't set """ typ = self.os_type var = self.os_variant if typ: if var and self._OS_TYPES[typ]["variants"][var].has_key(key): return self._OS_TYPES[typ]["variants"][var][key] elif self._OS_TYPES[typ].has_key(key): return self._OS_TYPES[typ][key] return self._DEFAULTS[key] def _lookup_device_param(self, device_key, param): """ Check the OS dictionary for the prefered device setting for passed device type and param (bus, model, etc.) """ os_devs = self._lookup_osdict_key("devices") default_devs = self._DEFAULTS["devices"] for devs in [os_devs, default_devs]: if not devs.has_key(device_key): continue for ent in devs[device_key][param]: hv_types = ent[0] param_value = ent[1] if self.type in hv_types: return param_value elif "all" in hv_types: return param_value raise RuntimeError(_("Invalid dictionary entry for device '%s %s'" % \ (device_key, param))) def terminate_console(self): if self._consolechild: try: os.kill(self._consolechild, signal.SIGKILL) except: pass def _wait_for_domain(conn, name): # sleep in .25 second increments until either a) we get running # domain ID or b) it's been 5 seconds. this is so that # we can try to gracefully handle domain restarting failures dom = None for ignore in range(1, int(5 / .25)): # 5 seconds, .25 second sleeps try: dom = conn.lookupByName(name) if dom and dom.ID() != -1: break except libvirt.libvirtError, e: logging.debug("No guest running yet: " + str(e)) dom = None time.sleep(0.25) return dom # Back compat class to avoid ABI break XenGuest = Guest 0707010002b5ac000081a40000000000000002000000014b0fbd790000075b000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.py# # Paravirtualized guest support # # Copyright 2006-2007 Red Hat, Inc. # Jeremy Katz # # 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. from Guest import Guest from DistroInstaller import DistroInstaller class ParaVirtGuest(Guest): def __init__(self, type=None, connection=None, hypervisorURI=None, installer=None): if not installer: installer = DistroInstaller(type = type, os_type = "xen", conn=connection) Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "xvd" def _get_input_device(self): return ("mouse", "xen") def _get_disk_xml(self, install = True): """Get the disk config in the libvirt XML format""" ret = "" used_targets = [] for disk in self._install_disks: if not disk.bus: disk.bus = "xen" used_targets.append(disk.generate_target(used_targets)) for d in self._install_disks: if d.transient and not install: continue if ret: ret += "\n" ret += d.get_xml_config(d.target) return ret 0707010002b590000081a40000000000000002000000014b0fbd7900003521000000b600010006ffffffffffffffff0000004700000000reloc/usr/lib/python2.4/vendor-packages/virtinst/CapabilitiesParser.py# # Some code for parsing libvirt's capabilities XML # # Copyright 2007 Red Hat, Inc. # Mark McLoughlin # # 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 libxml2 from virtinst import _virtinst as _ class CapabilitiesParserException(Exception): def __init__(self, msg): Exception.__init__(self, msg) # Whether a guest can be created with a certain feature on resp. off FEATURE_ON = 0x01 FEATURE_OFF = 0x02 class Features(object): """Represent a set of features. For each feature, store a bit mask of FEATURE_ON and FEATURE_OFF to indicate whether the feature can be turned on or off. For features for which toggling doesn't make sense (e.g., 'vmx') store FEATURE_ON when the feature is present.""" def __init__(self, node = None): self.features = {} if node is not None: self.parseXML(node) def __getitem__(self, feature): if self.features.has_key(feature): return self.features[feature] return 0 def names(self): return self.features.keys() def parseXML(self, node): d = self.features for n in node.xpathEval("*"): feature = n.name if not d.has_key(feature): d[feature] = 0 self._extractFeature(feature, d, n) def _extractFeature(self, feature, d, node): """Extract the value of FEATURE from NODE and set DICT[FEATURE] to its value. Abstract method, must be overridden""" raise NotImplementedError("Abstract base class") class CapabilityFeatures(Features): def __init__(self, node = None): Features.__init__(self, node) def _extractFeature(self, feature, d, n): default = xpathString(n, "@default") toggle = xpathString(n, "@toggle") if default is not None: if default == "on": d[feature] = FEATURE_ON elif default == "off": d[feature] = FEATURE_OFF else: raise CapabilitiesParserException("Feature %s: value of default must be 'on' or 'off', but is '%s'" % (feature, default)) if toggle == "yes": d[feature] |= d[feature] ^ (FEATURE_ON|FEATURE_OFF) else: if feature == "nonpae": d["pae"] |= FEATURE_OFF else: d[feature] |= FEATURE_ON class Host(object): def __init__(self, node = None): # e.g. "i686" or "x86_64" self.arch = None self.features = CapabilityFeatures() self.topology = None if not node is None: self.parseXML(node) def parseXML(self, node): child = node.children while child: if child.name == "topology": self.topology = Topology(child) if child.name != "cpu": child = child.next continue n = child.children while n: if n.name == "arch": self.arch = n.content elif n.name == "features": self.features = CapabilityFeatures(n) n = n.next child = child.next class Guest(object): def __init__(self, node = None): # e.g. "xen" or "hvm" self.os_type = None # e.g. "i686" or "x86_64" self.arch = None self.domains = [] self.features = CapabilityFeatures() if not node is None: self.parseXML(node) def parseXML(self, node): child = node.children while child: if child.name == "os_type": self.os_type = child.content elif child.name == "features": self.features = CapabilityFeatures(child) elif child.name == "arch": self.arch = child.prop("name") machines = [] emulator = None loader = None n = child.children while n: if n.name == "machine": machines.append(n.content) elif n.name == "emulator": emulator = n.content elif n.name == "loader": loader = n.content n = n.next n = child.children while n: if n.name == "domain": self.domains.append(Domain(n.prop("type"), emulator, loader, machines, n)) n = n.next child = child.next def bestDomainType(self, accelerated=None): if len(self.domains) == 0: raise CapabilitiesParserException(_("No domains available for " "virt type '%(type)s', arch " "%(arch)s.") % \ {'type': self.os_type, 'arch': self.arch}) if accelerated is None: # Picking last in list so we favour KVM/KQEMU over QEMU return self.domains[-1] else: priority = ["kvm", "xen", "kqemu", "qemu"] if not accelerated: priority.reverse() for t in priority: for d in self.domains: if d.hypervisor_type == t: return d # Fallback, just return last item in list return self.domains[-1] class Domain(object): def __init__(self, hypervisor_type, emulator = None, loader = None, machines = None, node = None): self.hypervisor_type = hypervisor_type self.emulator = emulator self.loader = loader self.machines = machines if node is not None: self.parseXML(node) def parseXML(self, node): child = node.children machines = [] while child: if child.name == "emulator": self.emulator = child.content elif child.name == "machine": machines.append(child.content) child = child.next if len(machines) > 0: self.machines = machines class Topology(object): def __init__(self, node = None): self.cells = [] if not node is None: self.parseXML(node) def parseXML(self, node): child = node.children if child.name == "cells": for cell in child.children: if cell.name == "cell": self.cells.append(TopologyCell(cell)) class TopologyCell(object): def __init__(self, node = None): self.id = None self.cpus = [] if not node is None: self.parseXML(node) def parseXML(self, node): self.id = int(node.prop("id")) child = node.children if child.name == "cpus": for cpu in child.children: if cpu.name == "cpu": self.cpus.append(TopologyCPU(cpu)) class TopologyCPU(object): def __init__(self, node = None): self.id = None if not node is None: self.parseXML(node) def parseXML(self, node): self.id = int(node.prop("id")) class Capabilities(object): def __init__(self, node = None): self.host = None self.guests = [] self._topology = None if not node is None: self.parseXML(node) self._fixBrokenEmulator() def guestForOSType(self, type = None, arch = None): if self.host is None: return None if arch is None: archs = [self.host.arch, None] else: archs = [arch] for a in archs: for g in self.guests: if (type is None or g.os_type == type) and \ (a is None or g.arch == a): return g # 32-bit HVM emulator path, on a 64-bit host is wrong due # to bug in libvirt capabilities. We fix by copying the # 64-bit emualtor path def _fixBrokenEmulator(self): if self.host.arch != "x86_64": return fixEmulator = None for g in self.guests: if g.os_type != "hvm" or g.arch != "x86_64": continue for d in g.domains: if d.emulator.find("lib64") != -1: fixEmulator = d.emulator if not fixEmulator: return for g in self.guests: if g.os_type != "hvm" or g.arch != "i686": continue for d in g.domains: if d.emulator.find("lib64") == -1: d.emulator = fixEmulator def parseXML(self, node): child = node.children while child: if child.name == "host": self.host = Host(child) elif child.name == "guest": self.guests.append(Guest(child)) if child.name == "topology": self._topology = Topology(child) child = child.next # Libvirt < 0.4.1 placed topology info at the capabilities level # rather than the host level. This is just for back compat if self.host.topology is None: self.host.topology = self._topology def parse(xml): class ErrorHandler: def __init__(self): self.msg = "" def handler(self, ignore, s): self.msg += s error = ErrorHandler() libxml2.registerErrorHandler(error.handler, None) try: # try/except/finally is only available in python-2.5 try: doc = libxml2.readMemory(xml, len(xml), None, None, libxml2.XML_PARSE_NOBLANKS) except (libxml2.parserError, libxml2.treeError), e: raise CapabilitiesParserException("%s\n%s" % (e, error.msg)) finally: libxml2.registerErrorHandler(None, None) try: root = doc.getRootElement() if root.name != "capabilities": raise CapabilitiesParserException("Root element is not 'capabilities'") capabilities = Capabilities(root) finally: doc.freeDoc() return capabilities def guest_lookup(conn, caps=None, os_type=None, arch=None, type=None, accelerated=False): """ Simple virtualization availability lookup Convenience function for looking up 'Guest' and 'Domain' capabilities objects for the desired virt type. If type, arch, or os_type are none, we return the default virt type associated with those values. These are typically: - os_type : hvm, then xen - type : kvm over plain qemu - arch : host arch over all others Otherwise the default will be the first listed in the capabilities xml. This function throws C{ValueError}s if any of the requested values are not found. @param conn: virConnect instance @type conn: libvirt.virConnect @param caps: Optional L{Capabilities} instance (saves a lookup) @type conn: L{Capabilities} @param type: Virtualization type ('hvm', 'xen', ...) @type type: C{str} @param arch: Guest architecture ('x86_64', 'i686' ...) @type arch: C{str} @param os_type: Hypervisor name ('qemu', 'kvm', 'xen', ...) @type os_type: C{str} @param accelerated: Whether to look for accelerated domain if none is specifically requested @type accelerated: C{bool} @returns: A (Capabilities Guest, Capabilities Domain) tuple """ if not caps: caps = parse(conn.getCapabilities()) guest = caps.guestForOSType(type=os_type, arch=arch) if not guest: archstr = _("for arch '%s'") % arch if not arch: archstr = "" osstr = _("virtualization type '%s'") % os_type if not os_type: osstr = _("any virtualization options") raise ValueError(_("Host does not support %(virttype)s %(arch)s") % {'virttype' : osstr, 'arch' : archstr}) domain = None if type: for d in guest.domains: if d.hypervisor_type == type.lower(): domain = d break else: domain = guest.bestDomainType(accelerated=accelerated) if domain == None: raise ValueError(_("Host does not support domain type " "'%(domain)s' for virtualization type " "'%(virttype)s' arch '%(arch)s'") % {'domain': type, 'virttype': guest.os_type, 'arch': guest.arch}) return (guest, domain) def xpathString(node, path, default = None): result = node.xpathEval("string(%s)" % path) if len(result) == 0: result = default return result 0707010002b5c9000081a40000000000000002000000014b136d1000004682000000b600010006ffffffffffffffff0000003a00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/util.pycm yKc@sdkZdkZdkZdkZdkZdkZdkZdkl Z dk Z dk l Z dkZdklZdZdZddZdZdZd Zd Zd Zdd Zd ZdZdZdZdZddZdZ dZ!dZ"dZ#ddZ$dZ%dZ&dZ'dZ(dZ)dZ*ddZ+d Z,d!Z-d"Z.d#Z/d$Z0d%Z1ddd&Z2d'Z3d(Z4e5d)jo e4ndS(*N(sstderr(s _virtinst(sUsers/etc/sysconfig/keyboards/etc/X11/xorg.confc Cstidjoddg}|o|d|g7}nti|dtidti}xS|ii D]B}|i }t |djo|dd jo |dSqkqkWdSnd } t| }d}x|iD]}|i }t |d jo-ttd | IJttd |IJPny0t|dd}|djo |dSnWqtj o qqXqWdS(NtSunOSs/usr/bin/netstats-rns-Itstdouttstderriitdefaults/proc/net/routei s%Invalid line length while parsing %s.sDefaulting bridge to xenbr%di(tplatformtsystemtcmdtnict subprocesstPopentPIPEtprocRt readlinestlinetsplittvalstlentNonet route_filetfiletdtdefnt xreadlinestinfoRt_tinttroutet ValueError( RRRRRRRR R R((tY/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/util.pyt default_route/s:  $     cCsd}tidjo|Sntiddgdtidti}|ii}t |djo|di }n|S( snReturn the default NIC to use, if one is specified. This is NOT part of the API and may change at will.tRs/usr/lib/xen/bin/xenstore-readsdevice-misc/vif/default-nicRRiN( tdevRRRR R R RR toutRtrstrip(RR R ((Rt _default_nicNs cCsotidjo tSnt}|djo d}nt|d}|djodSn d|SdS(NRitxenbr0sxenbr%d(RRR"RtrtRRR(R$R((Rtdefault_bridgeas     cCstidjodtgSnt}|dj ot|i oyt i i d|od|gSnt |d}t i i d|o)t i i d|odd|gSqndd gS( NRtbridges/sys/class/net/%s/bridgeis/sys/class/net/peth%d/brports/sys/class/net/xenbr%d/bridgesxenbr%dtnetworkR(RRR"RRRt is_uri_remotetconntgetURItostpathtexistsRR(R)RR((Rtdefault_networkps !.cCstiido:tiidodSntiidodSqMntiidp9tiidp&tiidptiido)tiitiod Sqd SndS( Ns /var/lib/xends/dev/xen/evtchntxens /proc/xens /usr/bin/qemus/usr/bin/qemu-kvms /usr/bin/kvms/usr/bin/xennersqemu:///systemsqemu:///session(R+R,R-tUsertcurrentthas_privtPRIV_QEMU_SYSTEMR(((Rtdefault_connections LcCstidjotdntd}|i}|ixR|D]J}|i dpqLn|d i ddd}|i d}|SqLWgS( NRsCPU flags not availables /proc/cpuinfotflagsit:it ( RRtOSErrortopentfR tlinestcloseR t startswithRR5tflst(R:R>R;R5R ((Rt get_cpu_flagss   cCs*|ptid}nd|ijS(s-Determine if a machine is PAE capable or not.RtpaeN(R)tlibvirtR9tgetCapabilities(R)((Rtis_pae_capablescCsttidjotdnd}tiidotdi}n|i ddjot Snt S(s-Determine if a machine is HVM capable or not.RsHVM capability not determinibleRs'/sys/hypervisor/properties/capabilitiesthvmiN( RRR8tcapsR+R,R-R9treadtfindtTruetFalse(RE((Rtis_hvm_capablescCstiidS(Ns /dev/kqemu(R+R,R-(((Rtis_kqemu_capablescCstiidS(Ns/dev/kvm(R+R,R-(((Rtis_kvm_capablescCsztidjotSntd}|i}|ix6|D].}|i dp|i dot SqDqDWtS(NRs /proc/modulessblktap s xenblktap ( RRRIR9R:R R;R<R R=RH(R:R;R ((Rtis_blktap_capables     cCs)tid}|djodSndS(Nitx86_64ti686(R+tunametarch(RQ((Rtget_default_archs R/cCshddddg<ddddg<}y||}Wntj o|d}nX|tiddtidd tidd g}d itd |S( sGenerate a random MAC address. 00-16-3E allocated to xensource 54-52-00 used by qemu/kvm The OUI list is available at http://standards.ieee.org/regauth/oui/oui.txt. The remaining 3 fields are random, with the first bit of the first random field set 0. >>> randomMAC().startswith("00:16:36") True >>> randomMAC("foobar").startswith("00:16:36") True >>> randomMAC("xen").startswith("00:16:36") True >>> randomMAC("qemu").startswith("54:52:00") True @return: MAC address string R/iii6tqemuiTiRiiR6cCsd|S(Ns%02x(tx(RT((RtsN( touisttypetouitKeyErrortrandomtrandinttmactjointmap(RWRXR\RV((Rt randomMACs*7cCs4g}tddD]}|tiddq~S(sGenerate a random UUID.iiiN(t_[1]trangetdummyRZR[(R`Rb((Rt randomUUIDscCs:diddddddddddgt|S(Nt-s%02xiii(R]ttupletu(Rf((Rt uuidToStringscCsQ|idd}g}tdddD]!}|t|||d!dq)~S(NRdRii ii(tstreplaceR`RatiR(RhR`Rj((RtuuidFromStringscCsg}xdddgD]}tii|d}tii|pqnyd|}ti|}Wnt j o qnXxy|D]q}|i ddjoU|i i}x@tt|D](}||djo|i|qqWqqWqW|S( NRs/sbin/s /usr/sbintifconfigsLC_ALL=C %s -a 2>/dev/nullsencap:Ethernetithwaddr(tdevicetdirnameR+R,R]t executableR-RtpopentpipetIOErrorR RGtlowerRtwordsRaRRjtappend(RpRjRRrRuRnR Ro((Rtget_host_network_devices s( !cCsY|djo|i}ny|i|i}Wntij o d}nX|S(sd@conn libvirt connection to poll for max possible vcpus @type optional guest type (kvm, etc.)i N( RWRR)tgetTypet getMaxVcpusRttmRAt libvirtError(R)RWRz((Rt get_max_vcpuss  cCs2|i}|d|d|d|d}|S(sGet number of physical CPUs.iiiiN(R)tgetInfothostinfotpcpus(R)RR~((Rt get_phy_cpus(s "cCs\ti|}ti|o9ti|djo#td|ti|fndS(Nis Failed to run %s, exited with %d(R+RRtstt WIFEXITEDt WEXITSTATUSR8(RR((RR.s&cCs^|idd}|idd}|idd}|idd}|id d }|S( s3Replaces chars ' " < > & with xml safe counterpartst&s&t's's"s"ts>N(tstrRi(R((Rt xml_escape4scCs|id}|id}t|t|jo||jodSqTdSnxhtt|D]T}t||dt||d}|djodSqg|djodSqgqgWdS(sCompare two MAC addressesR6iiiiN( tpRtpatqtqaRtxrangeRjRtn(RRRRjRR((Rt compareMAC=s $   cCsd}yttd}Wn2tj o&}tidtt |fngXt i d}xI|D]0}|i|}|o|id}PqdqdWtidt|i|S(stLook in /etc/X11/xorg.conf for the host machine's keymap, and attempt to map it to a keymap supported by qemutrsCould not open "%s": %s s+\s*Option\s+"XkbLayout"\s+"(?P[a-z-]+)"tktsDidn't find keymap in '%s'!N(RRR9t XORG_CONFR:RstetloggingtdebugRtretcompilet keymap_reR tmatchRztgroupR<(RR:RzRRR ((Rt _xorg_keymapPs "  c CsGdk} d} d} d}yttd}Wn5tj o)}t i dt |t }nXx|i} | djoPntid| djp2tid| djomtid | djoT| id o d }n| id o d }nqi| i|di}qiqiW|i|djot i d | Sn|i}| ii|io| i|} nd }|iddidd}t| ii|}xT|D]L}|}|iddidd}|i!|o| i|} PqqW| pt i d|| Sn| S(spLook in /etc/sysconfig for the host machine's keymap, and attempt to map it to a keymap supported by qemuNsen-usRs)Could not open "/etc/sysconfig/keyboard" iRtKEYTABLEtKEYBOARDt KEYBOARDTYPEt"t=s$Did not parse any usable keymapping.cCst|t|S(N(Rtbta(RR((Rtlen_cmpsRdRs%Didn't match keymap '%s' in keytable!("tkeytableRRtkeymapRR9t KEYBOARD_DIRR:RsRRRRRtreadlineRhRtsearchtcounttdelimRtstripR<Rtthas_keyRRitclean_kttsortedtkeyst sorted_keystkeytorigkeyR=( RRRRRRRRR:RRhRR((Rtdefault_keymapesV   K  "       cCs^|o8ti|i}|iidjodSq?dSntidjodSndS(sV Return the pygrub path for the current host, or connection if available. ti86pcs/usr/lib/xen/bin/pygrubs/usr/bin/pygrubRN( R)tCapabilitiesParsertparseRBtcapthostRQRR(R)R((Rt pygrub_pathsc Cs6dd}d}}}}|id}|djo|| i||d}}|d djoT||d\}}|id}|djo|d|!}||d}qnd |jo|i d d\}}nd |jo|i d d\}}q n |i}||||||fS( s Parse a libvirt hypervisor uri into it's individual parts @returns: tuple of the form (scheme (ex. 'qemu', 'xen+ssh'), username, hostname, path (ex. '/system'), query, fragment) icCsVx>dD]*}|i||}|djoPqqWt|}|||!||fS(Ns/?#i(tcturlRGtstartRR(RRRR((Rt splitnetlocs   RR6iis//t@t#t?N( RtusernametnetloctquerytfragmentturiRGRjRttschemetoffsetR( RRRRRjRRRR((Rt uri_splits$        cCsdy3t|}|d}|djotSntSWn*tj o}ti d|tSnXdS(NiRs"Error parsing URI in is_remote: %s( RRt split_uriRRIRHt ExceptionRRt exception(RRRR((RR(s   cCshy/t|}|d}|djo|SnWn2tj o&}tid|t|fnXdS(NiRsCannot parse URI %s: %st localhost( RRRRRRRtwarningR(RRRR((Rtget_uri_hostnames    "cCsuyat|}|d}|d}|o6|id}|djo||d|gSq`nWnnXddgS(Niit+(RRRRRtindexRR(RRRRR((Rtget_uri_transports    cCskyQt|}|d}|o0|id}|djo || Sn|SnWntj onXdS(NiRR/(RRRRRGRR(RRRR((Rtget_uri_drivers     cCs|ptSnt|tipttdny,t|idptSn|i WnLti j o=}|i ti jp|i tijotSqnXtS(s5check if virConnectPtr passed has storage API supports%'conn' must be a virConnect instance.tlistStoragePoolsN(R)RIt isinstanceRAt virConnectRRtdirRRR{Rtget_error_codet VIR_ERR_RPCtVIR_ERR_NO_SUPPORTRH(R)R((Rtis_storage_capables, cCsd}d}d}zti|}|i}|oe|i |}|djoEt |t jo(t |djo|di}qq|}qn*|o||}nttdWd|o|in|o|inX|S(s Return the content from the passed xml xpath, or return the result of a passed function (receives xpathContext as its only arg) iis'path' or 'func' is required.N(Rtdoctctxtresulttlibxml2tparseDoctxmltxpathNewContextR,t xpathEvaltretRWtlistRtcontenttfuncRRtfreeDoctxpathFreeContext(RR,RRRRR((Rt get_xml_paths.  cstpdSnd}i}i}xC||gD]5}x,|D]$}|||}|o|SqSqSWqFWdS(s' Return the first pool with matching matching target path. return the first we find, active or inactive. This iterates over all pools and dumps their xml, so it is NOT quick. Favor running pools over inactive pools. @return virStoragePool object if found, None otherwise csLi|}t|idd}tii ||jo|SndS(Nis/pool/target/path( R)tstoragePoolLookupByNametpoolnametpoolRtXMLDesctxml_pathR+R,tabspath(RR,RR(R)(Rt check_poolKsN( RR)RRRt running_listtlistDefinedStoragePoolst inactive_listtplisttnameR,R(R)R,RRRRRR((R)Rtlookup_pool_by_path@s     cCsdk}|idS(N(tdoctestttestmod(R((Rt_testZs t__main__(6RRZtos.pathR+RRRRtsysRRAtvirtinstt _virtinstRRR0RRRRR"R%R.R4R?RCRJRKRLRMRRR_RcRgRkRwR|RRRRRRRRR(RRRRRRRt__name__(0R4RRRR%R"RcRRLRRR(RRRRkRR.R0R?RKRRgRRZR|RR_RRARRRMRRRRRRRwRRJRRRRRCR+R((RRsb                      '         A  #   "   0707010002b594000081a40000000000000002000000014b136d0f00002885000000b600010006ffffffffffffffff0000004400000000reloc/usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.py# # Copyright 2006-2009 Red Hat, Inc. # Daniel P. Berrange # # 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 logging import os import _util import Installer from VirtualDisk import VirtualDisk from User import User import OSDistro from virtinst import _virtinst as _ def _is_url(url): """ Check if passed string is a (psuedo) valid http, ftp, or nfs url. """ return (url.startswith("http://") or url.startswith("ftp://") or \ url.startswith("nfs:")) and not os.path.exists(url) def _sanitize_url(url): """ Do nothing for http or ftp, but make sure nfs is in the expected format """ if url.startswith("nfs://"): # Convert RFC compliant NFS nfs://server/path/to/distro # to what mount/anaconda expect nfs:server:/path/to/distro # and carry the latter form around internally url = "nfs:" + url[6:] # If we need to add the : after the server index = url.find("/", 4) if index == -1: raise ValueError(_("Invalid NFS format: No path specified.")) if url[index - 1] != ":": url = url[:index] + ":" + url[index:] return url class DistroInstaller(Installer.Installer): def __init__(self, type = "xen", location = None, boot = None, extraargs = None, os_type = None, conn = None): Installer.Installer.__init__(self, type, location, boot, extraargs, os_type, conn=conn) self.install = { "kernel" : "", "initrd" : "", "extraargs" : "", } # True == location is a filesystem path # False == location is a url self._location_is_path = True # DistroInstaller specific methods/overwrites def get_location(self): return self._location def set_location(self, val): """ Valid values for location: 1) it can be a local file (ex. boot.iso), directory (ex. distro tree) or physical device (ex. cdrom media) 2) tuple of the form (poolname, volname) pointing to a file or device which will set location as that path 3) http, ftp, or nfs path for an install tree """ is_tuple = False validated = True self._location_is_path = True # Basic validation if type(val) is not str and (type(val) is not tuple and len(val) != 2): raise ValueError(_("Invalid 'location' type %s." % type(val))) if type(val) is tuple and len(val) == 2: logging.debug("DistroInstaller location is a (poolname, volname)" " tuple") if not self.conn: raise ValueError(_("'conn' must be specified if 'location' is" " a storage tuple.")) is_tuple = True elif _is_url(val): val = _sanitize_url(val) self._location_is_path = False logging.debug("DistroInstaller location is a network source.") elif os.path.exists(os.path.abspath(val)) \ and (not self.conn or not _util.is_uri_remote(self.conn.getURI())): val = os.path.abspath(val) logging.debug("DistroInstaller location is a local " "file/path: %s" % val) else: # Didn't determine anything about the location validated = False if is_tuple or (validated == False and self.conn and _util.is_storage_capable(self.conn)): # If user passed a storage tuple, OR # We couldn't determine the location type and a storage capable # connection was passed: # Pass the parameters off to VirtualDisk to validate, and pull # out the path stuple = (is_tuple and val) or None path = (not validated and val) or None try: d = VirtualDisk(path=path, device=VirtualDisk.DEVICE_CDROM, conn=self.conn, volName=stuple) val = d.path except Exception, e: logging.debug(str(e)) raise ValueError(_("Checking installer location failed: " "Could not find media '%s'." % str(val))) elif not validated: raise ValueError(_("Install media location must be an NFS, HTTP " "or FTP network install source, or an existing " "file/device")) if (not self._location_is_path and val.startswith("nfs:") and not User.current().has_priv(User.PRIV_NFS_MOUNT, (self.conn and self.conn.getURI()))): raise ValueError(_('Privilege is required for NFS installations')) self._location = val location = property(get_location, set_location) # Private helper methods def _prepare_cdrom(self, guest, distro, meter): if not self._location_is_path: # Xen needs a boot.iso if its a http://, ftp://, or nfs: url cdrom = OSDistro.acquireBootDisk(self.location, meter, guest.arch, scratchdir = self.scratchdir, distro = distro) self._tmpfiles.append(cdrom) self._install_disk = VirtualDisk(path=self.location, conn=guest.conn, device=VirtualDisk.DEVICE_CDROM, readOnly=True, transient=True) def _prepare_kernel_and_initrd(self, guest, distro, meter): if self.boot is not None: # Got a local kernel/initrd already self.install["kernel"] = self.boot["kernel"] self.install["initrd"] = self.boot["initrd"] if not self.extraargs is None: self.install["extraargs"] = self.extraargs else: # Need to fetch the kernel & initrd from a remote site, or # out of a loopback mounted disk image/device ((kernelfn, initrdfn, args), os_type, os_variant) = OSDistro.acquireKernel(guest, self.location, meter, guest.arch, scratchdir=self.scratchdir, type=self.os_type, distro=distro) # Only set OS type if the user didn't explictly pass one # XXX: Should this be opt in? if guest.os_type == None and os_type: logging.debug("Auto detected OS type as: %s" % os_type) guest.os_type = os_type if (guest.os_variant == None and os_variant and guest.os_type == os_type): logging.debug("Auto detected OS variant as: %s" % os_variant) guest.os_variant = os_variant self.install["kernel"] = kernelfn self.install["initrd"] = initrdfn self.install["extraargs"] = args self._tmpfiles.append(kernelfn) if initrdfn: self._tmpfiles.append(initrdfn) # If they're installing off a local file/device, we map it # through to a virtual CD or disk if (self.location is not None and self._location_is_path and not os.path.isdir(self.location)): device = VirtualDisk.DEVICE_DISK if guest._lookup_osdict_key('pv_cdrom_install'): device = VirtualDisk.DEVICE_CDROM self._install_disk = VirtualDisk(conn=guest.conn, device=device, path=self.location, readOnly=True, transient=True) # General Installer methods def prepare(self, guest, meter, distro = None): self.cleanup() self.install = { "kernel" : "", "initrd" : "", "extraargs" : "", } if self.cdrom: if self.location: self._prepare_cdrom(guest, distro, meter) else: # Booting from a cdrom directly allocated to the guest pass else: self._prepare_kernel_and_initrd(guest, distro, meter) def get_install_xml(self, guest, isinstall): if isinstall: bootdev = "cdrom" else: bootdev = "hd" return self._get_osblob_helper(isinstall=isinstall, guest=guest, kernel=self.install, bootdev=bootdev) def detect_distro(self): try: dist_info = OSDistro.detectMediaDistro(location=self.location, arch=self.arch) except: logging.exception("Error attempting to detect distro.") return (None, None) # Verify these are valid values dtype, dvariant = dist_info import osdict if dtype and osdict.OS_TYPES.has_key(dtype): if not (dvariant and osdict.OS_TYPES[dtype]["variants"].has_key(dvariant)): logging.debug("Variant returned from detect_distro is not " "valid: %s" % dvariant) dvariant = None else: logging.debug("Type returned from detect_distro is not valid: %s" % dtype) dtype = None dvariant = None return (dtype, dvariant) 0707010002b5c0000081a40000000000000002000000014b136d0f00001a1b000000b600010006ffffffffffffffff0000003a00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/_util.py# # Copyright 2006 Red Hat, Inc. # Jeremy Katz # # 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 th