# PaCkAgE DaTaStReAm SUNWvirtinst 1 1998 # end of header 0707010002bb93000081a40000000000000000000000014ae194b3000001d9000000b600010006ffffffffffffffff0000001500000000SUNWvirtinst/pkginfoPKG=SUNWvirtinst NAME=Guest Domain Installer ARCH=i386 VERSION=11.11,REV=2009.10.23.10.12 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=priscilla20091023113411 0707010002bb92000081a40000000000000000000000014ae194b3000020b0000000b600010006ffffffffffffffff0000001400000000SUNWvirtinst/pkgmap: 1 1998 1 i copyright 18479 5190 1256282684 1 i depend 1955 36654 1256282684 1 i pkginfo 473 38135 1256297651 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 1256297646 1 f none usr/bin/virt-convert 0555 root bin 10327 26229 1256297646 1 f none usr/bin/virt-install 0555 root bin 34704 5187 1256297646 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 1497 63197 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtconv/__init__.pyc 0644 root bin 1033 53323 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/diskcfg.py 0644 root bin 8101 23144 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtconv/diskcfg.pyc 0644 root bin 7102 15777 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/formats.py 0644 root bin 3853 45203 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/formats.pyc 0644 root bin 4251 25113 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/netdevcfg.py 0644 root bin 1403 46239 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/netdevcfg.pyc 0644 root bin 1011 53729 1256297646 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/virtimage.py 0644 root bin 8876 17732 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtimage.pyc 0644 root bin 7896 44251 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtinstance.py 0644 root bin 10540 583 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtinstance.pyc 0644 root bin 8936 54747 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/vmx.py 0644 root bin 9599 16737 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/vmx.pyc 0644 root bin 8584 38421 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/vmcfg.py 0644 root bin 3118 48065 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/vmcfg.pyc 0644 root bin 2862 29072 1256297646 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 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/CapabilitiesParser.pyc 0644 root bin 13303 33897 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/CloneManager.py 0644 root bin 21907 39030 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/CloneManager.pyc 0644 root bin 17733 64089 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.py 0644 root bin 10373 40125 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.pyc 0644 root bin 7111 24832 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.py 0644 root bin 5601 24592 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.pyc 0644 root bin 4328 7878 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/Guest.py 0644 root bin 29134 57835 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/Guest.pyc 0644 root bin 25226 60348 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.py 0644 root bin 6585 29762 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.pyc 0644 root bin 6671 64907 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageManager.py 0644 root bin 6464 25955 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageManager.pyc 0644 root bin 5423 42817 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageParser.py 0644 root bin 11697 15449 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageParser.pyc 0644 root bin 11498 41768 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.py 0644 root bin 2185 44579 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.pyc 0644 root bin 1794 27408 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/Installer.py 0644 root bin 12506 38179 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/Installer.pyc 0644 root bin 11165 47326 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.py 0644 root bin 2650 8575 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.pyc 0644 root bin 2348 33061 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.py 0644 root bin 14666 29239 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.pyc 0644 root bin 14827 4278 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/OSDistro.py 0644 root bin 43068 40572 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/OSDistro.pyc 0644 root bin 32480 31821 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.py 0644 root bin 1529 55474 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.pyc 0644 root bin 863 38830 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.py 0644 root bin 1883 17790 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.pyc 0644 root bin 1507 5441 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/Storage.py 0644 root bin 36030 49996 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/Storage.pyc 0644 root bin 33353 62117 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/User.py 0644 root bin 2594 2824 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/User.pyc 0644 root bin 2131 34641 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.py 0644 root bin 1608 64007 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.pyc 0644 root bin 1359 58951 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.py 0644 root bin 2489 65039 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.pyc 0644 root bin 2526 55366 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.py 0644 root bin 33947 20772 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.pyc 0644 root bin 28419 64417 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualGraphics.py 0644 root bin 4377 4751 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualGraphics.pyc 0644 root bin 4473 62276 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.py 0644 root bin 6857 64921 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.pyc 0644 root bin 6288 41802 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualNetworkInterface.py 0644 root bin 7848 50307 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualNetworkInterface.pyc 0644 root bin 6809 14568 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/__init__.py 0644 root bin 2157 54434 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/__init__.pyc 0644 root bin 1908 40682 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/_util.py 0644 root bin 6447 52167 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/_util.pyc 0644 root bin 5887 40341 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/cli.py 0644 root bin 14997 40742 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/cli.pyc 0644 root bin 14998 21070 1256297647 1 f none usr/lib/python2.4/vendor-packages/virtinst/keytable.py 0644 root bin 824 52143 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/keytable.pyc 0644 root bin 940 44130 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/osdict.py 0644 root bin 8897 64636 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/osdict.pyc 0644 root bin 4964 1904 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/util.py 0644 root bin 17646 6641 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/util.pyc 0644 root bin 18050 17130 1256297646 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000b00000000TRAILER!!!0707010002bb93000081a40000000000000000000000014ae194b3000001d9000000b600010006ffffffffffffffff0000000800000000pkginfoPKG=SUNWvirtinst NAME=Guest Domain Installer ARCH=i386 VERSION=11.11,REV=2009.10.23.10.12 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=priscilla20091023113411 0707010002bb92000081a40000000000000000000000014ae194b3000020b0000000b600010006ffffffffffffffff0000000700000000pkgmap: 1 1998 1 i copyright 18479 5190 1256282684 1 i depend 1955 36654 1256282684 1 i pkginfo 473 38135 1256297651 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 1256297646 1 f none usr/bin/virt-convert 0555 root bin 10327 26229 1256297646 1 f none usr/bin/virt-install 0555 root bin 34704 5187 1256297646 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 1497 63197 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtconv/__init__.pyc 0644 root bin 1033 53323 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/diskcfg.py 0644 root bin 8101 23144 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtconv/diskcfg.pyc 0644 root bin 7102 15777 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/formats.py 0644 root bin 3853 45203 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/formats.pyc 0644 root bin 4251 25113 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/netdevcfg.py 0644 root bin 1403 46239 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/netdevcfg.pyc 0644 root bin 1011 53729 1256297646 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/virtimage.py 0644 root bin 8876 17732 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtimage.pyc 0644 root bin 7896 44251 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtinstance.py 0644 root bin 10540 583 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/virtinstance.pyc 0644 root bin 8936 54747 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/vmx.py 0644 root bin 9599 16737 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/parsers/vmx.pyc 0644 root bin 8584 38421 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtconv/vmcfg.py 0644 root bin 3118 48065 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtconv/vmcfg.pyc 0644 root bin 2862 29072 1256297646 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 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/CapabilitiesParser.pyc 0644 root bin 13303 33897 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/CloneManager.py 0644 root bin 21907 39030 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/CloneManager.pyc 0644 root bin 17733 64089 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.py 0644 root bin 10373 40125 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/DistroInstaller.pyc 0644 root bin 7111 24832 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.py 0644 root bin 5601 24592 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.pyc 0644 root bin 4328 7878 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/Guest.py 0644 root bin 29134 57835 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/Guest.pyc 0644 root bin 25226 60348 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.py 0644 root bin 6585 29762 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.pyc 0644 root bin 6671 64907 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageManager.py 0644 root bin 6464 25955 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageManager.pyc 0644 root bin 5423 42817 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageParser.py 0644 root bin 11697 15449 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImageParser.pyc 0644 root bin 11498 41768 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.py 0644 root bin 2185 44579 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.pyc 0644 root bin 1794 27408 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/Installer.py 0644 root bin 12506 38179 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/Installer.pyc 0644 root bin 11165 47326 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.py 0644 root bin 2650 8575 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.pyc 0644 root bin 2348 33061 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.py 0644 root bin 14666 29239 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.pyc 0644 root bin 14827 4278 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/OSDistro.py 0644 root bin 43068 40572 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/OSDistro.pyc 0644 root bin 32480 31821 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.py 0644 root bin 1529 55474 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/PXEInstaller.pyc 0644 root bin 863 38830 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.py 0644 root bin 1883 17790 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.pyc 0644 root bin 1507 5441 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/Storage.py 0644 root bin 36030 49996 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/Storage.pyc 0644 root bin 33353 62117 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/User.py 0644 root bin 2594 2824 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/User.pyc 0644 root bin 2131 34641 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.py 0644 root bin 1608 64007 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.pyc 0644 root bin 1359 58951 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.py 0644 root bin 2489 65039 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.pyc 0644 root bin 2526 55366 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.py 0644 root bin 33947 20772 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.pyc 0644 root bin 28419 64417 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualGraphics.py 0644 root bin 4377 4751 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualGraphics.pyc 0644 root bin 4473 62276 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.py 0644 root bin 6857 64921 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.pyc 0644 root bin 6288 41802 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualNetworkInterface.py 0644 root bin 7848 50307 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/VirtualNetworkInterface.pyc 0644 root bin 6809 14568 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/__init__.py 0644 root bin 2157 54434 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/__init__.pyc 0644 root bin 1908 40682 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/_util.py 0644 root bin 6447 52167 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/_util.pyc 0644 root bin 5887 40341 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/cli.py 0644 root bin 14997 40742 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/cli.pyc 0644 root bin 14998 21070 1256297647 1 f none usr/lib/python2.4/vendor-packages/virtinst/keytable.py 0644 root bin 824 52143 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/keytable.pyc 0644 root bin 940 44130 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/osdict.py 0644 root bin 8897 64636 1256292722 1 f none usr/lib/python2.4/vendor-packages/virtinst/osdict.pyc 0644 root bin 4964 1904 1256297646 1 f none usr/lib/python2.4/vendor-packages/virtinst/util.py 0644 root bin 17646 6641 1256283815 1 f none usr/lib/python2.4/vendor-packages/virtinst/util.pyc 0644 root bin 18050 17130 1256297646 0707010002bb94000041ed0000000000000000000000024ae194b300000000000000b600010006ffffffffffffffff0000000800000000install0707010002bb96000081a40000000000000000000000014ae15a3c000007a3000000b600010006ffffffffffffffff0000000f00000000install/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 0707010002bb95000081a40000000000000000000000014ae15a3c0000482f000000b600010006ffffffffffffffff0000001200000000install/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. 0707010002bb97000041ed0000000000000000000000034ae194b300000000000000b600010006ffffffffffffffff0000000600000000reloc0707010002bb98000041ed0000000000000000000000044ae194b300000000000000b600010006ffffffffffffffff0000000a00000000reloc/usr0707010002bb9d000041ed0000000000000000000000034ae194b300000000000000b600010006ffffffffffffffff0000000e00000000reloc/usr/lib0707010002bb9e000041ed0000000000000000000000034ae194b300000000000000b600010006ffffffffffffffff0000001800000000reloc/usr/lib/python2.40707010002bb9f000041ed0000000000000000000000044ae194b300000000000000b600010006ffffffffffffffff0000002800000000reloc/usr/lib/python2.4/vendor-packages0707010002bbb2000041ed0000000000000000000000024ae194b300000000000000b600010006ffffffffffffffff0000003100000000reloc/usr/lib/python2.4/vendor-packages/virtinst0707010002bbc6000081a40000000000000002000000014ae194ae00002b9d000000b600010006ffffffffffffffff0000003f00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/Installer.pycm rJc@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        0707010002bbbb000081a40000000000000002000000014ae18172000071ce000000b600010006ffffffffffffffff0000003a00000000reloc/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): """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) 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): 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...") # 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) #self.domain = self.conn.createLinux(install_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): 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.createLinux(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 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 0707010002bbb9000081a40000000000000002000000014ae18172000015e1000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.py# # Fullly virtualized 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. import _util import DistroInstaller from Guest import Guest from VirtualDisk import VirtualDisk class FullVirtGuest(Guest): def __init__(self, type=None, arch=None, connection=None, hypervisorURI=None, emulator=None, installer=None): if not installer: installer = DistroInstaller.DistroInstaller(type = type, os_type = "hvm", conn=connection) Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "hd" self.features = { "acpi": None, "pae": _util.is_pae_capable(self.conn), "apic": None } self.emulator = emulator if arch: self.arch = arch self.loader = None guest = self._caps.guestForOSType(type=self.installer.os_type, arch=self.arch) if (not self.emulator) and guest: for dom in guest.domains: if dom.hypervisor_type == self.installer.type: self.emulator = dom.emulator self.loader = dom.loader # Fall back to default hardcoding if self.emulator is None: if self.type == "xen": if self._caps.host.arch in ("x86_64"): self.emulator = "/usr/lib64/xen/bin/qemu-dm" else: self.emulator = "/usr/lib/xen/bin/qemu-dm" if (not self.loader) and self.type == "xen": self.loader = "/usr/lib/xen/boot/hvmloader" def os_features(self): """Determine the guest features, based on explicit settings in FEATURES and the OS_TYPE and OS_VARIANT. FEATURES takes precedence over the OS preferences""" if self.features is None: return None # explicitly disabling apic and acpi will override OS_TYPES values features = dict(self.features) for f in ["acpi", "apic"]: val = self._lookup_osdict_key(f) features[f] = val return features def _get_input_device(self): typ = self._lookup_device_param("input", "type") bus = self._lookup_device_param("input", "bus") return (typ, bus) def _get_features_xml(self): ret = " \n" features = self.os_features() if features: ret += " " for k in sorted(features.keys()): v = features[k] if v: ret += "<%s/>" %(k,) ret += "\n" return ret + " " def _get_device_xml(self, install=True): emu_xml = "" if self.emulator is not None: emu_xml = " %s\n" % self.emulator return (emu_xml + """ \n""" + Guest._get_device_xml(self, install)) 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 = "ide" used_targets.append(disk.generate_target(used_targets)) # attach a floppy device if provided '--autocf=/pathname' if install and self.autocf and self.autocf.startswith('/'): autocf_floppy = VirtualDisk(self.autocf, \ device=VirtualDisk.DEVICE_FLOPPY, transient=True, \ readOnly=True) ret = autocf_floppy.get_xml_config('fda') for d in self._install_disks: saved_path = None if d.device == VirtualDisk.DEVICE_CDROM \ and d.transient and not install: # Keep cdrom around, but with no media attached # But only if we are a distro that doesn't have a multi # stage install (aka not Windows) saved_path = d.path if not self.get_continue_inst(): d.path = None if ret: ret += "\n" ret += d.get_xml_config(d.target) if saved_path != None: d.path = saved_path return ret def _set_defaults(self): Guest._set_defaults(self) disk_bus = self._lookup_device_param("disk", "bus") net_model = self._lookup_device_param("net", "model") # Only overwrite params if they weren't already specified for net in self._install_nics: if net_model and not net.model: net.model = net_model for disk in self._install_disks: if disk_bus and not disk.bus: disk.bus = disk_bus 0707010002bbc4000081a40000000000000002000000014ae194ae00000702000000b600010006ffffffffffffffff0000004500000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.pycm ^Jc@s3dkZdklZdeifdYZdS(N(s VirtualDisktImportInstallercBs5tZdZedZdZdZdZRS(s? Create a Guest around an existing disk device, and perform no 'install' stage. ImportInstaller sets the Guest's boot device to that of the first disk attached to the Guest (so, one of 'hd', 'cdrom', or 'floppy'). All the user has to do is fill in the Guest object with the desired parameters. cCs0t|idjottdndS(Nis A disk device must be specified.(tlentguesttdiskst ValueErrort_(tselfRtmetertdistro((td/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/ImportInstaller.pytprepare#sc CsG|odSn|i|id}|id|d|ddd|S(Nit isinstallRtkerneltbootdev(R tNoneRt_disk_to_bootdevRRR t_get_osblob_helper(RRR R ((R tget_install_xml's cCstS(N(tTrue(RR((R tpost_install_check1scCsY|itijodSn;|itijodSn |itijodSndSdS(Nthdtcdromtfloppy(tdisktdevicet VirtualDiskt DEVICE_DISKt DEVICE_CDROMt DEVICE_FLOPPY(RR((R R7s(t__name__t __module__t__doc__RR RRR(((R Rs   (t InstallerRR(R RR((R t?s  0707010002bbe5000081a40000000000000002000000014ae1817200003a95000000b600010006ffffffffffffffff0000003800000000reloc/usr/lib/python2.4/vendor-packages/virtinst/cli.py# # Utility functions for the command line drivers # # 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. import os, sys import logging import logging.handlers import locale from optparse import OptionValueError, OptionParser import libvirt import _util import virtinst from virtinst import CapabilitiesParser, VirtualNetworkInterface, \ VirtualGraphics, VirtualAudio, User from virtinst import _virtinst as _ MIN_RAM = 64 force = False doprompt = True class VirtOptionParser(OptionParser): '''Subclass to get print_help to work properly with non-ascii text''' def _get_encoding(self, f): encoding = getattr(f, "encoding", None) if not encoding: (dummy, encoding) = locale.getlocale() return encoding def print_help(self, file=None): if file is None: file = sys.stdout encoding = self._get_encoding(file) file.write(self.format_help().encode(encoding, "replace")) # # Setup helpers # def setupLogging(appname, debug=False): # set up logging vi_dir = os.path.expanduser("~/.virtinst") if not os.access(vi_dir,os.W_OK): try: os.mkdir(vi_dir) except IOError, e: raise RuntimeError, "Could not create %d directory: " % vi_dir, e dateFormat = "%a, %d %b %Y %H:%M:%S" fileFormat = "[%(asctime)s " + appname + " %(process)d] %(levelname)s (%(module)s:%(lineno)d) %(message)s" streamDebugFormat = "%(asctime)s %(levelname)-8s %(message)s" streamErrorFormat = "%(levelname)-8s %(message)s" filename = os.path.join(vi_dir, appname + ".log") rootLogger = logging.getLogger() rootLogger.setLevel(logging.DEBUG) fileHandler = logging.handlers.RotatingFileHandler(filename, "a", 1024*1024, 5) fileHandler.setFormatter(logging.Formatter(fileFormat, dateFormat)) rootLogger.addHandler(fileHandler) streamHandler = logging.StreamHandler(sys.stderr) if debug: streamHandler.setLevel(logging.DEBUG) streamHandler.setFormatter(logging.Formatter(streamDebugFormat, dateFormat)) else: streamHandler.setLevel(logging.ERROR) streamHandler.setFormatter(logging.Formatter(streamErrorFormat)) rootLogger.addHandler(streamHandler) # Register libvirt handler def libvirt_callback(ignore, err): if err[3] != libvirt.VIR_ERR_ERROR: # Don't log libvirt errors: global error handler will do that logging.warn("Non-error from libvirt: '%s'" % err[2]) libvirt.registerErrorHandler(f=libvirt_callback, ctx=None) # Register python error handler to log exceptions def exception_log(type, val, tb): import traceback s = traceback.format_exception(type, val, tb) logging.exception("".join(s)) sys.__excepthook__(type, val, tb) sys.excepthook = exception_log def fail(msg): """Convenience function when failing in cli app""" logging.error(msg) import traceback tb = "".join(traceback.format_exc()).strip() if tb != "None": logging.debug(tb) sys.exit(1) def nice_exit(): print _("Exiting at user request.") sys.exit(0) def getConnection(connect): if not User.current().has_priv(User.PRIV_CREATE_DOMAIN, connect): fail(_("Must be root to create Xen guests")) if connect is None: fail(_("Could not find usable default libvirt connection.")) logging.debug("Using libvirt URI '%s'" % connect) return libvirt.open(connect) # # Prompting # def set_force(val=True): global force force = val def set_prompt(prompt=True): # Set whether we allow prompts, or fail if a prompt pops up global doprompt doprompt = prompt def prompt_for_input(prompt = "", val = None): if val is not None: return val if force: fail(_("Force flag is set but input was required. " "Prompt was: %s" % prompt)) if not doprompt: fail(_("Prompting disabled, but input was requested. " "Prompt was: %s" % prompt)) print prompt + " ", return sys.stdin.readline().strip() def yes_or_no(s): s = s.lower() if s in ("y", "yes", "1", "true", "t"): return True elif s in ("n", "no", "0", "false", "f"): return False raise ValueError, "A yes or no response is required" def prompt_for_yes_or_no(prompt): """catches yes_or_no errors and ensures a valid bool return""" if force: logging.debug("Forcing return value of True to prompt '%s'") return True if not doprompt: fail(_("Prompting disabled, but yes/no was requested. " "Try --force to force 'yes' for such prompts. " "Prompt was: %s" % prompt)) while 1: inp = prompt_for_input(prompt, None) try: res = yes_or_no(inp) break except ValueError, e: print _("ERROR: "), e continue return res # # Ask for attributes # def get_name(name, guest): if name is None: fail(_("A name is required for the virtual machine.")) try: guest.name = name except ValueError, e: fail(e) def get_memory(memory, guest): if memory is None: fail(_("Memory amount is required for the virtual machine.")) if memory < MIN_RAM: fail(_("Installs currently require %d megs of RAM.") % MIN_RAM) try: guest.memory = memory except ValueError, e: fail(e) def get_uuid(uuid, guest): if uuid: try: guest.uuid = uuid except ValueError, e: fail(e) def get_vcpus(vcpus, check_cpu, guest, conn): if check_cpu: hostinfo = conn.getInfo() cpu_num = hostinfo[4] * hostinfo[5] * hostinfo[6] * hostinfo[7] if vcpus <= cpu_num: pass elif not prompt_for_yes_or_no(_("You 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)") % (vcpus, cpu_num)): nice_exit() if vcpus is not None: try: guest.vcpus = vcpus except ValueError, e: fail(e) def get_cpuset(cpuset, mem, guest, conn): if cpuset and cpuset != "auto": guest.cpuset = cpuset elif cpuset == "auto": caps = CapabilitiesParser.parse(conn.getCapabilities()) if caps.host.topology is None: logging.debug("No topology section in caps xml. Skipping cpuset") return cells = caps.host.topology.cells if len(cells) <= 1: logging.debug("Capabilities only show <= 1 cell. Not NUMA capable") return cell_mem = conn.getCellsFreeMemory(0, len(cells)) cell_id = -1 mem = mem * 1024 for i in range(len(cells)): if cell_mem[i] > mem and len(cells[i].cpus) != 0: # Find smallest cell that fits if cell_id < 0 or cell_mem[i] < cell_mem[cell_id]: cell_id = i if cell_id < 0: logging.debug("Could not find any usable NUMA cell/cpu combinations. Not setting cpuset.") return # Build cpuset cpustr = "" for cpu in cells[cell_id].cpus: if cpustr != "": cpustr += "," cpustr += str(cpu.id) logging.debug("Auto cpuset is: %s" % cpustr) guest.cpuset = cpustr return def parse_network_option(network): """helper to properly parse --network options in new syntax net=host:bridge,bridge=linkname,mac=mac_addr,capped-bandwidth=rate,vlanid=vid return value: (network, mac, rate, vlanid)""" net = None bridge = None mac = None rate = None vlanid = None # Parse out comma separated options opts = {} while network: tmpopts = None opt_type = None opt_val = None if network.count(",") != 0: network, tmpopts = network.split(",", 1) if network.count("=") != 0: opt_type, opt_val = network.split("=", 1) opts[opt_type.lower()] = opt_val network = tmpopts for opt in opts.items(): opt_type, opt_val = opt if opt_type == "net": net = opt_val elif opt_type == "bridge": bridge = opt_val elif opt_type == "mac": mac = opt_val elif opt_type == "capped-bandwidth": rate = opt_val elif opt_type == "vlanid": vlanid = opt_val else: print >> sys.stderr, _("Unknown --network option ") + opt_type sys.exit(1) if bridge and net: print >> sys.stderr, _("Cannot mix both 'net' and 'bridge' options of --network") sys.exit(1) if rate is not None and net: print >> sys.stderr, _("Cannot specify 'capped-bandwidth' for non-bridge network") sys.exit(1) if vlanid is not None and net: print >> sys.stderr, _("Cannot specify 'vlanid' for non-bridge network") sys.exit(1) if bridge: net = "bridge:" + bridge elif not net: net = "bridge:" # default type is 'bridge', if not specified return (net, mac, rate, vlanid) def get_network(mac, network, guest): rate = None vlanid = None if network.count("=") != 0: (network, mac, rate, vlanid) = parse_network_option(network) if mac == "RANDOM": mac = None if network == "user": n = VirtualNetworkInterface(mac, type="user", conn=guest.conn) elif network[0:6] == "bridge": n = VirtualNetworkInterface(mac, type="bridge", bridge=network[7:], conn=guest.conn, rate=rate, vlanid=vlanid) elif network[0:7] == "network": n = VirtualNetworkInterface(mac, type="network", network=network[8:], conn=guest.conn) else: fail(_("Unknown network type ") + network) guest.nics.append(n) def digest_networks(conn, macs, bridges, networks, nics = 0): def listify(l): if l is None: return [] elif type(l) != list: return [ l ] else: return l macs = listify(macs) bridges = listify(bridges) networks = listify(networks) if bridges and networks: fail(_("Cannot mix both --bridge and --network arguments")) if networks != None: old = 0 new = 0 for n in networks: if n.count("=") != 0: new = 1 # using new syntax else: old = 1 # using old syntax if old and new: print >> sys.stderr, _("Cannot mix old syntax and new syntax of --network arguments") sys.exit(1) if new and macs: print >> sys.stderr, _("Cannot mix both --macs and new syntax of --network arguments") sys.exit(1) if bridges: networks = map(lambda b: "bridge:" + b, bridges) # With just one mac, create a default network if one is not # specified. if len(macs) == 1 and len(networks) == 0: if User.current().has_priv(User.PRIV_CREATE_NETWORK, conn.getURI()): net = _util.default_network(conn) networks.append(net[0] + ":" + net[1]) else: networks.append("user") # ensure we have less macs then networks. Auto fill in the remaining # macs if len(macs) > len(networks): fail(_("Need to pass equal numbers of networks & mac addresses")) else: for dummy in range (len(macs),len(networks)): macs.append(None) # Create extra networks up to the number of nics requested if len(macs) < nics: for dummy in range(len(macs),nics): if User.current().has_priv(User.PRIV_CREATE_NETWORK, conn.getURI()): net = _util.default_network(conn) networks.append(net[0] + ":" + net[1]) else: networks.append("user") macs.append(None) return (macs, networks) def get_graphics(vnc, vncport, nographics, sdl, keymap, guest): if (vnc and nographics) or \ (vnc and sdl) or \ (sdl and nographics): raise ValueError, _("Can't specify more than one of VNC, SDL, " "or --nographics") if not (vnc or nographics or sdl): if "DISPLAY" in os.environ.keys(): logging.debug("DISPLAY is set: graphics defaulting to VNC.") vnc = True else: logging.debug("DISPLAY is not set: defaulting to nographics.") nographics = True if nographics is not None: guest.graphics_dev = None return if sdl is not None: guest.graphics_dev = VirtualGraphics(type=VirtualGraphics.TYPE_SDL) return if vnc is not None: guest.graphics_dev = VirtualGraphics(type=VirtualGraphics.TYPE_VNC) if vncport: guest.graphics_dev.port = vncport if keymap: guest.graphics_dev.keymap = keymap def get_sound(sound, guest): # Sound is just a boolean value, so just specify a default of 'es1370' # model since this should provide audio out of the box for most modern # distros if sound: guest.sound_devs.append(VirtualAudio(model="es1370")) def get_hostdevs(hostdevs, guest): if not hostdevs: return for devname in hostdevs: dev = virtinst.VirtualHostDevice.device_from_node(conn=guest.conn, name=devname) guest.hostdevs.append(dev) ### 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) 0707010002bbd5000081a40000000000000002000000014ae1817200000648000000b600010006ffffffffffffffff0000004100000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.py# # Copyright 2008-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 from virtinst import _virtinst as _ class VirtualAudio(VirtualDevice.VirtualDevice): MODELS = [ "es1370" ] def __init__(self, model, conn=None): VirtualDevice.VirtualDevice.__init__(self, conn) self._model = None self.model = model def get_model(self): return self._model def set_model(self, new_model): if type(new_model) != str: raise ValueError, _("'model' must be a string, " " was '%s'." % type(new_model)) if not self.MODELS.count(new_model): raise ValueError, _("Unsupported sound model '%s'" % new_model) self._model = new_model model = property(get_model, set_model) def get_xml_config(self): return " " % self.model 0707010002bbc3000081a40000000000000002000000014ae15ea700000889000000b600010006ffffffffffffffff0000004400000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImportInstaller.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 Installer from VirtualDisk import VirtualDisk class ImportInstaller(Installer.Installer): """ Create a Guest around an existing disk device, and perform no 'install' stage. ImportInstaller sets the Guest's boot device to that of the first disk attached to the Guest (so, one of 'hd', 'cdrom', or 'floppy'). All the user has to do is fill in the Guest object with the desired parameters. """ # General Installer methods def prepare(self, guest, meter, distro = None): if len(guest.disks) == 0: raise ValueError(_("A disk device must be specified.")) def get_install_xml(self, guest, isinstall): if isinstall: # Signifies to the 'Guest' that there is no 'install' phase return None else: bootdev = self._disk_to_bootdev(guest.disks[0]) return self._get_osblob_helper(isinstall=isinstall, guest=guest, kernel=None, bootdev=bootdev) def post_install_check(self, guest): return True # Private methods def _disk_to_bootdev(self, disk): if disk.device == VirtualDisk.DEVICE_DISK: return "hd" elif disk.device == VirtualDisk.DEVICE_CDROM: return "cdrom" elif disk.device == VirtualDisk.DEVICE_FLOPPY: return "floppy" else: return "hd" 0707010002bbcc000081a40000000000000002000000014ae194ae00007ee0000000b600010006ffffffffffffffff0000003e00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/OSDistro.pycm rJc@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   ,  cCsy|i|i|}Wntd|inX|iidd}ddi ||i |}y&|i|i |}|||fSWn-ti|ttd|i nXdS(Ns!Solaris PV kernel not found at %sRis Solaris miniroot not found at %s(RRQRaRgR RdRpRRnRR RBRRhReRRWR:(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 R80s 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 6s* $  cCsy|i|i|}Wn ttd|inXd|i|i|}y*|i|i d|}|||fSWnft j oZ}y*|i|i d|}|||fSWqti|t d|qXnXdS(Ns%OpenSolaris PV kernel not found at %sRiis&No OpenSolaris boot archive found: %s (RRQRaRgR RdRpR:R RBRt initrdpathsReRR=RRW(RaRBRR RdR=RRe((R RA`s cCsh}|dj ojxg|idD]R}|id}t|djotd|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 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) 0707010002bbb4000081a40000000000000002000000014ae194ae000033f7000000b600010006ffffffffffffffff0000004800000000reloc/usr/lib/python2.4/vendor-packages/virtinst/CapabilitiesParser.pycm ^Jc@s/dkZdklZdefdYZdZdZdefdYZ de fd YZ d efd YZ d efd YZ defdYZ defdYZdefdYZdefdYZdefdYZdZddddedZddZdS(N(s _virtinsttCapabilitiesParserExceptioncBstZdZRS(NcCsti||dS(N(t Exceptiont__init__tselftmsg(RR((tg/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/CapabilitiesParser.pyRs(t__name__t __module__R(((RRsiitFeaturescBs>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 F0707010002bbd2000081a40000000000000002000000014ae194ae00008249000000b600010006ffffffffffffffff0000003d00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/Storage.pycm ^Jc@sIdZdkZdkZdklZdkZdklZdZ dZ dZ dZ de fd YZd efd YZd efd YZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdS(s 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} N(sescape(s _virtinsts/devs/dev/s/var/lib/libvirt/images/s/dev/disk/by-patht StorageObjectcBstZdZdZdZedZdZeeZ dZ dZ ee e ddZ d Z d Zee eded Zd Zd ZdZdZdZdZdZRS(sn Base class for building any libvirt storage object. Mostly meaningless to directly instantiate. tpooltvolumecCs{||i|igjottdtn||_d|_ d|_ |dj o ||_ n||_ d|_ dS(s6 Initialize storage object parameters sUnknown storage object type: %sN(t object_typetselft TYPE_POOLt TYPE_VOLUMEt ValueErrort_ttypet _object_typetNonet_connt_nametconntnamet_perms(RRRR((t\/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/Storage.pyt__init__Ps      cCs|iS(N(RR (R((Rtget_object_typecscCs|iS(N(RR (R((Rtget_connhscCs\t|tipttdnti|pttdn||_ dS(Ns+'conn' must be a libvirt connection object.s0Passed connection is not libvirt storage capable( t isinstancetvaltlibvirtt virConnectRRt_utiltis_storage_capableRR (RR((Rtset_connjs tdocs? Libvirt connection to check object against/install on cCs|iS(N(RR (R((Rtget_nameuscCs0titd||i|||_dS(NsStorage object(Rt validate_nameRRRt_check_name_collisionR (RR((Rtset_namews sName for the storage object.cCs|iS(N(RR(R((Rt get_permsscCsvt|tj ottdnx=ddddgD])}||jottdq<q<W||_dS(Ns+Permissions must be passed as a dict objecttmodetownertgrouptlabelsCPermissions must contain 'mode', 'owner', 'group' and 'label' keys.(R RtdictRRtkeyRR(RRR'((Rt set_permss cCsHt|tdj p|id ottd|ndS(Ntstrt/s'%s' is not an absolute path.(R tpatht startswithRR(RR+((Rt_validate_paths*cCs tddS(NsMust be implemented in subclass(t RuntimeError(RR((RRscCs tddS(s; Returns the pool/volume specific xml blob sMust be implemented in subclassN(R.(R((Rt_get_storage_xmlscCsS|i}|pdSndd|dd|dd|dd |d d S( Nts s %o R"s %d R#s %d R$s R%s (RR!tperms(RR1((Rt_get_perms_xmls cCs~t|dpd|i}n#t|d}d|i|f}d|d|idhd|i<d|i}|S( s Construct the xml description of the storage object @returns: xml description @rtype: C{str} R s<%s> s<%s type='%s'> s%ss %s s %(stor_xml)ststor_xmlsN( thasattrRRtroot_xmltgetattrt_typeRR/txml(RR8R7R5((Rtget_xml_configs7(t__name__t __module__t__doc__RRR RRtpropertyRRRRRR RRR!R(R-RR/R2R9(((RRFs&             t StoragePoolcBstZdZdZdZdZdZdZdZhZ e de et_typesRRtTYPE_DIRt DirectoryPooltTYPE_FStFilesystemPoolt TYPE_NETFStNetworkFilesystemPoolt TYPE_LOGICALt LogicalPoolt TYPE_DISKtDiskPoolt TYPE_ISCSIt iSCSIPool(RE((Rtget_pool_classscCsti|}|iS(sBConvenience method, returns volume class associated with pool_typeN(R>RSt pool_typet pool_classtget_volume_class(RTRU((Rtget_volume_for_poolscCs tiiS(s%Return list of appropriate pool typesN(R>RFtkeys(((Rtget_pool_typesscCs ti|S(s6Return human readable description for passed pool typeN(R>RFRT(RT((Rtget_pool_type_descscCsti|dtid|d|||ijott d|n||_ d|_ d|_ d|_d|_|djo|i}n||_d|_ d|_|p d|_ntiti|_dS(NRRRsUnknown storage pool type: %s(RRRRRRR RYRRR7R t _target_patht_hostt_formatt _source_patht target_patht_get_default_target_pathtuuidt_uuidRt uuidToStringt randomUUIDt _random_uuid(RRRR R_Ra((RRs"          cCs|iS(N(RR7(R((Rtget_typesRs,Storage device type the pool will represent.cCs|iS(N(RR[(R((Rtget_target_pathscCs|i|||_dS(N(RR-RR[(RR((Rtset_target_paths cCs|iS(N(RR^(R((Rtget_source_pathscCs|i|||_dS(N(RR-RR^(RR((Rtset_source_path s cCs|iS(N(RR\(R((Rtget_host$scCs<t|tdj ottdn||_dS(NR)sHost name must be a string(R RRRRR\(RR((Rtset_host&scCs|iS(N(RRb(R((Rtget_uuid,scCsti|}||_dS(N(Rt validate_uuidRRRb(RR((Rtset_uuid.scCsZd}y|ii|}Wntij onX|ott d|ndS(Ns)Name '%s' already in use by another pool.( R RRRtstoragePoolLookupByNameRRt libvirtErrorRR(RRR((RR4scCs tddS(NsMust be implemented in subclass(R.(R((RR`>scCs tddS(NsMust be implemented in subclass(R.(R((Rt_get_target_xmlBscCs tddS(NsMust be implemented in subclass(R.(R((Rt_get_source_xmlEscCsrd}|idjodd|id}ndd|id}d|ip|id|d|S(NR0s s%ss s s s %s (tsrc_xmlRRsRrttar_xmlRaRe(RRuRt((RR/Hs cCs|i}tid|i|fy|ii|d}Wn1t j o%}t t dt |nXd}|o\|ony|itiWn+t j o}t dt |}nX|oqn|oK| oCy|idWq.t j o}t dt |}q.Xn|oQy|iWn0t j o$}tiddt |nXt |n|S( s+ Install storage pool xml. s'Creating storage pool '%s' with xml: %sis!Could not define storage pool: %ss Could not build storage pool: %ss Could not start storage pool: %ss&Error cleaning up pool after failure: s%sN(RR9R8tloggingtdebugRRtstoragePoolDefineXMLRt ExceptionteR.RR)R terrmsgtbuildtmeterRtVIR_STORAGE_POOL_BUILD_NEWtcreatetundefine(RR}RR|R8R{RzR((RtinstallVs: ! (%R:R;R<RGRIRKRMRORQRFRRSt staticmethodRWRYRZR RRfR=R RgRhRiRjRkRlRmRoRaRR`RrRsR/tFalseR(((RR>sV                      RHcBstZdZdZeeZeeieiZ ee i e i de dZeeedZdZdZdZRS(s/ Create a directory based storage pool cCstS(N(t FileVolume(((RRVsRs&Directory to use for the storage pool.c CsFti|d|dtid|d|d||o ||_ndS(NRR R_RaR( R>RRRRGR_RaRR1(RRRR_RaR1((RRscCst|i}|S(N(tDEFAULT_DIR_TARGET_BASERRR+(RR+((RR`s cCs%dt|id|i}|S(Ns %s s%s(tescapeRR_R2R8(RR8((RRrs!cCsdS(NR0((R((RRss(R:R;R<RVRR=RR!R(R1R>RgRhRR_R RR`RrRs(((RRHs      RJc BstZdZdZeeZdddddddd d d d d g Zeeiei Z ee i e i dedZee ie idedZeedeedZdZdZeeededZdZdZdZRS(s9 Create a formatted partition based storage pool cCstS(N(R(((RRVstautotext2text3text4tufstiso9660tudftgfstgfs2tvfatshfs+txfsRs*The existing device to mount for the pool.s$Location to mount the source device.c Cscti|d|dtid|d|d|||_|o ||_ n|o ||_ ndS(NRR R_RaR( R>RRRRIR_RaRtformatt source_pathR1(RRRRR_RRaR1((RRs  cCs|iS(N(RR](R((Rt get_formatscCs7||ijottd|n||_dS(NsUnknown Filesystem format: %s(RRtformatsRRR](RR((Rt set_formatss%Filesystem type of the source device.cCst|i}|S(N(RRRR+(RR+((RR`s cCs%dt|id|i}|S(Ns %s s%s(RRR_R2R8(RR8((RRrs!cCsB|ipttdnd|idt|i}|S(NsDevice path is requireds s (RRR.RRRR8(RR8((RRss (R:R;R<RVRRR=RR!R(R1R>RiRjRRRgRhR_R RRRRR`RrRs(((RRJs&   *       RLcBstZdZdZeeZddgZeeiei de dZ eei ei de dZeeieide dZeeededZd Zd Zeeede d Zd Zd ZdZRS(s: Create a network mounted filesystem storage pool cCstS(N(R(((RRVsRtnfsRs&Path on the host that is being shared.s%Name of the host sharing the storage.s$Location to mount the source device.c Cscti|d|dtid|d|d|||_|o ||_ n|o ||_ ndS(NRR RaR_R( R>RRRRKRaR_RRRthost(RRRRRR_RRa((RRs  cCs|iS(N(RR](R((RRscCs7||ijottd|n||_dS(Ns%Unknown Network Filesystem format: %s(RRRRRR](RR((RRssType of network filesystem.cCst|i}|S(N(RRRR+(RR+((RR`s cCsdt|i}|S(Ns %s (RRR_R8(RR8((RRr scCsm|ipttdn|ipttdnd|id|idt|i}|S(NsHostname is requiredsHost path is requireds s s (RRR.RRRRR8(RR8((RRss   )(R:R;R<RVRRR=R>RiRjRRRkRlRRgRhR_R RRRRR`RrRs(((RRLs(           RNcBstZdZdZeeZeeieiZ ee i e i de dZeeedZdZdZdZRS(s: Create a logical (lvm volume group) storage pool cCstS(N(t LogicalVolume(((RRVsRs*Location of the existing LVM volume group.c CsFti|d|dtid|d|d||o ||_ndS(NRR R_RaR( R>RRRRMR_RaRR1(RRRR_RaR1((RR'scCs t|iS(N(tDEFAULT_LVM_TARGET_BASERR(R((RR`-scCs%dt|id|i}|S(Ns %s s%s(RRR_R2R8(RR8((RRr0s!cCsdS(NR0((R((RRs5s(R:R;R<RVRR=RR!R(R1R>RgRhRR_R RR`RrRs(((RRNs      RPcBstZdZeeieidedZeei ei dedZ dddddd d d gZ d Z ee Z eeded ZdZdZeeededZdZdZdZeeedZRS(s4 Create a storage pool from a physical disk Rs!Path to the existing disk device.s2Root location for identifying new storage volumes.Rtbsdtdostdvhtgpttmactpc98tsuncCsttddS(Ns(Disk volume creation is not implemented.(tNotImplementedErrorR(((RRVHsc CsOti|d|dtid|d|d|||_|o ||_ ndS(NRR RaR_R( R>RRRRORaR_RRR(RRRRR_RRa((RRLs  cCs|iS(N(RR](R((RRTscCs7||ijottd|n||_dS(NsUnknown Disk format: %s(RRRRRR](RR((RRVss.Format of the source device's partition table.cCstS(N(tDEFAULT_DEV_TARGET(R((RR`]scCsdt|i}|S(Ns %s (RRR_R8(RR8((RRr`scCsb|ipttdnd}|idjod|i}n|dt|i7}|S(NsHost path is requiredR0Rs s (RRR.RR8RR(RR8((RRsds cCsL|idjo|ottdnti|d|d|d|S(NRs>Must explicitly specify disk format if formatting disk device.R}RR|( RRR|RRR>RR}R(RR}RR|((RRps(R:R;R<R=R>RiRjRRRgRhR_RRVRR RRRRR`RrRsRR(((RRP8s&           RRcBstZdZeeieidedZeei ei dedZ dZ e e Z eeeedZdZdZeeededZd Zd Zd ZRS( s, Create an iSCSI based storage pool Rs%Name of the host sharing the storage.s2Root location for identifying new storage volumes.cCsttddS(Ns)iSCSI volume creation is not implemented.(RR(((RRVsc CsZti|d|dtid|d|d||o ||_n|o ||_ ndS(NRR RaR_R( R>RRRRQRaR_RRR(RRRRRR_Ra((RRs  cCs|iS(N(RR^(R((RRiscCs ||_dS(N(RRR^(RR((RRjss&Path on the host that is being shared.cCstS(N(tDEFAULT_ISCSI_TARGET(R((RR`scCsdt|i}|S(Ns %s (RRR_R8(RR8((RRrscCsb|ipttdn|ipttdnd|idt|i}|S(NsHostname is requiredsHost path is requireds s (RRR.RRRR8(RR8((RRss   (R:R;R<R=R>RkRlRRRgRhR_RVRR RRiRjRR`RrRs(((RRRws         t StorageVolumecBs=tZdZgZeeeddZeeedZeeZeeeddZeeZeeedZ ee Z dZ dZ e e e Z d Zd Ze eeZd Zd Ze eeZd ZdZdZdZdZdZdZedZdZRS(sK Base class for building and installing libvirt storage volume xml icCs|djob|djottdn|djottdntid|d|}nd|_ ||_t i |dt i d|d|iid|_d|_d|_||_||_dS(Ns+One of pool or pool_name must be specified.s)'conn' must be specified with 'pool_name't pool_nameRRR(RR RRRRRtlookup_pool_by_nameRt_poolRRRRR t _allocationt _capacityR]t allocationtcapacity(RRRRRRR((RRs           cCs@tid|d|d|}titi|i ddS(sN Returns volume class associated with passed pool_object/name t pool_objectRRis /pool/@typeN( RRRRRR>RWRt get_xml_pathtXMLDesc(RRR((RRWs   R0cCstid|d|d|}|idxttddD]c}|}|djo|d|7}n||7}y|i |Wq;t i j o |Sq;Xq;WttddS( s{ 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} RRRiis-%ds*Default volume target path range exceeded.N(RRRRRtrefreshtrangetiRttrynametsuffixtstorageVolLookupByNameRRqRR(RRRRRRR((Rtfind_free_names       cCs|djo#|djottdn|dj o|djo|djottdnti|pttdny|i|}Wqt j o+}ttd|t |fqXnt |t ipttdn|S(s Returns pool object determined from passed parameters. Largely a convenience function for the other static functions. s%Must specify pool_object or pool_names)'conn' must be specified with 'pool_name's/Connection does not support storage management.s#Couldn't find storage pool '%s': %ss$pool_object must be a virStoragePoolN(RR RRRRRRRpRyRzR)RRtvirStoragePool(RRRRz((RRs +cCs|iS(N(RR(R((Rt get_capacityscCst|tttfjp |djottdnt|}|i }|i }||_ |i djo||i jo ||_n|i}|do&||_ ||_t|dn!|doti|dndS(Nis"Capacity must be a positive numberi(R RtinttfloattlongRRtnewcapRRtorigcapRtorigallRR Rtis_size_conflicttretRvtwarn(RRRRRR((Rt set_capacitys)           cCs|iS(N(RR(R((Rtget_allocation)scCst|tttfjp |djottdnt|}|i djo*||i jot i d|i }n|i }||_ |i}|do||_ t|dn!|dot i|dndS(Nis(Allocation must be a non-negative numbersCapping allocation at capacity.i(R RRRRRRtnewallRRR RvRwRRRRR(RRRRR((Rtset_allocation+s)          cCs|iS(N(RR(R((Rtget_pool=scCsjt|tipttdn|idtijottd|in||_ dS(Ns)'pool' must be a virStoragePool instance.ispool '%s' must be active.( RtnewpoolRRRRtinfotVIR_STORAGE_POOL_RUNNINGRRR(RR((Rtset_pool?s cCs|iS(N(RR](R((RRHscCs7||ijottd|n||_dS(Ns'%s' is not a valid format.(RRRRRR](RR((RRJscCsZd}y|ii|}Wntij onX|ott d|ndS(Ns+Name '%s' already in use by another volume.( R tvolRRRRRRqRR(RRR((RROscCsHd}y|ii|}Wntij onX|otSnt S(N( R tcolRRtstorageVolLookupByPathR+RRqtTrueR(RR+R((Rt_check_target_collisionYscCs tddS(NsMust be implemented in subclass(R.(R((RRrdscCs tddS(NsMust be implemented in subclass(R.(R((RRsgscCssd}|idjodd|id}ndd|id}d|id|id|d|S( NR0s s%ss s s s %d s %d (RtRRsRrRuRR(RRuRt((RR/js cCs|i}tid|i|f|ony|ii|d}Wn4t j o(}t d|it |fnX|ontid|i|S(s; Build and install storage volume from xml s)Creating storage volume '%s' with xml: %sis)Couldn't create storage volume '%s': '%s's%Storage volume '%s' install complete.N(RR9R8RvRwRR}Rt createXMLRRyRzR.R)(RR}R8RRz((RRxs $cCs|iid}|i|jo1ttd|idd|ddffSnB|i|jo1ttd|idd|ddffSntdfS(s$ 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}) isuThere is not enough free space on the storage pool to create the volume. (%d M requested allocation > %d M available)isThe requested volume capacity will exceed the available pool space when the volume is fully allocated. (%d M requested capacity > %d M available)R0N( RRRtavailRRRRR(RR((RRs11(R:R;R<RR RRWRRRRRR=RRRRRRRRRRRRrRsR/RR(((RRs6  "              Rc BstZdZddddddddd d g ZeeieiZee i e i Z e e e de e d Zd Zd ZRS(sM Build and install xml for use on pools which use file based storage trawtbochstclooptcowtdmgtisotqcowtqcow2tvmdktvpcc CsRti|d|d|d|d|d|d|||_ |o ||_ ndS(NRRRRRR( RRRRRRRRRRR1( RRRRRRRRR1((RRs    cCsd|id|iS(Ns s%s(RRR2(R((RRrscCsdS(NR0((R((RRss(R:R;R<RR=RR!R(R1RRRRR RRrRs(((RRs $ RcBsMtZdZeeieiZeeeeedZ dZ dZ RS(s9 Build and install logical volumes for lvm pools cCsIti|d|d|d|d|d|d||o ||_ ndS(NRRRRRR( RRRRRRRRRR1(RRRRRRRR1((RRs   cCsd|iS(Ns%s(RR2(R((RRrscCsdS(NR0((R((RRss( R:R;R<R=RR!R(R1R RRrRs(((RRs  (R<RRvtxml.sax.saxutilsRRtvirtinstt _virtinstRRRRRtobjectRR>RHRJRLRNRPRRRRR(RJRRvRHRPRLRRRRRRRNRR>RRRRRR((Rt?.s(      v!:<?4*0707010002bbd7000081a40000000000000002000000014ae15ea7000009b9000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.py# # Base class for all VM devices # # 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. import libvirt import CapabilitiesParser import _util from virtinst import _virtinst as _ class VirtualDevice(object): """ Base class for all domain xml device objects. """ def __init__(self, conn=None): """ Initialize device state @param conn: libvirt connection to validate device against @type conn: virConnect """ if conn: if not isinstance(conn, libvirt.virConnect): raise ValueError, _("'conn' must be a virConnect instance") self._conn = conn self.__remote = None if self.conn: self.__remote = _util.is_uri_remote(self.conn.getURI()) self._caps = None if self.conn: self._caps = CapabilitiesParser.parse(self.conn.getCapabilities()) def get_conn(self): return self._conn def set_conn(self, val): if not isinstance(val, libvirt.virConnect): raise ValueError(_("'conn' must be a virConnect instance.")) self._conn = val conn = property(get_conn, set_conn) def _is_remote(self): return self.__remote def _check_bool(self, val, name): if val not in [True, False]: raise ValueError, _("'%s' must be True or False" % name) def _check_str(self, val, name): if type(val) is not str: raise ValueError, _("'%s' must be a string, not '%s'." % (name, type(val))) def get_xml_config(self): """ Construct and return device xml @return: device xml representation as a string @rtype: str """ raise NotImplementedError() 0707010002bbdc000081a40000000000000002000000014ae194ae00001179000000b600010006ffffffffffffffff0000004500000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualGraphics.pycm ^Jc@sNdkZdkZdkZdkZdklZdeifdYZdS(N(s _virtinsttVirtualGraphicscBstZdZdZeddddddZdZeeZdZ dZ ee e Z dZ d Z ee e Zd Zd ZeeeZd Zd ZeeeZdZdZdZRS(NtsdltvncicCstii|d|||ijo&||ijottdn||_ d|_ d|_ d|_ d|_|i||i||i||i|dS(NtconnsUnknown graphics type(t VirtualDevicet__init__tselfRttypetTYPE_VNCtTYPE_SDLt ValueErrort_t_typetNonet_portt_listent_passwdt_keymaptset_porttportt set_keymaptkeymapt set_listentlistent set_passwdtpasswd(RRRRRRR((td/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/VirtualGraphics.pyR s         cCs|iS(N(RR (R((Rtget_type3scCs|iS(N(RR(R((Rt get_keymap7scCs|pti}n| pt|tdjottdnt|djottdntid|djottdn||_ dS(NtstringsKeymap must be a stringis&Keymap must be less than 16 characterss^[a-zA-Z0-9_-]*$s<Keymap can only contain alphanumeric, '_', or '-' characters( tvalt_utiltdefault_keymapRR R tlentretmatchR RR(RR((RR9s!cCs|iS(N(RR(R((Rtget_portEscCsq|djo d}nNt|tj p'|djo-|djp |djottdn||_dS(Nii isKVNC port must be a number between 5900 and 65535, or -1 for auto allocation(RR RtintR R RR(RR((RRGs   :cCs|iS(N(RR(R((Rt get_listenPscCs ||_dS(N(RRR(RR((RRRscCs|iS(N(RR(R((Rt get_passwdVscCs ||_dS(N(RRR(RR((RRXscCs[dk}|ii}g}|ix,|D]$}||jo|i|q/q/W|S(s7 Return a list of valid keymap values. N(tkeytabletvaluest orig_listt sort_listtsorttktappend(RR-R(R*R+((Rt valid_keymaps\s   cCsPtiidptdntid}tiid}d||fS(NtDISPLAYs$No DISPLAY environment variable set.s ~/.Xauthoritys2 (tostenvironthas_keyt RuntimeErrortdisptpatht expandusertxauth(RR5R8((Rt _sdl_configls  cCs|i|ijo|iSnd}d}d}|iod|i}n|i od|i }n|i od|i }nddhd|i <dhd |<d hd |<d hd |<d}|S(Nts keymap='%s's listen='%s's passwd='%s's (RR R R9R;R<R=RRRRRRRtxml(RR>R<R=R;((Rtget_xml_configvs   Q(t__name__t __module__R RR RRtpropertyRRRRR$RRR&RRR'RRR/R9R?(((RRs(            (R"R1RRtvirtinstt _virtinstR R(RRRR"R1R ((Rt?s     0707010002bbd3000081a40000000000000002000000014ae15ea700000a22000000b600010006ffffffffffffffff0000003900000000reloc/usr/lib/python2.4/vendor-packages/virtinst/User.py# # 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 platform import os class User(object): """Defines a particular user account.""" PRIV_CLONE = 1 PRIV_NFS_MOUNT = 2 PRIV_QEMU_SYSTEM = 3 PRIV_CREATE_DOMAIN = 4 PRIV_CREATE_NETWORK = 5 _privs = [ PRIV_CLONE, PRIV_NFS_MOUNT, PRIV_QEMU_SYSTEM, PRIV_CREATE_DOMAIN, PRIV_CREATE_NETWORK ] def __init__(self, euid): self._euid = euid def get_euid(self): return self._euid euid = property(get_euid) def has_priv(self, priv, conn=None): """Return if the given user is privileged enough to perform the given operation. This isn't entirely accurate currently, especially on Solaris.""" if priv not in self._privs: raise ValueError('unknown privilege %s' % priv) if priv == self.PRIV_QEMU_SYSTEM: return self._euid == 0 if platform.system() != 'SunOS': is_xen = not conn or conn.lower()[0:3] == 'xen' if priv in [ self.PRIV_CLONE, self.PRIV_CREATE_DOMAIN ]: if is_xen: return self._euid == 0 return True return self._euid == 0 # Not easy to work out! if self._euid != User.current().euid: return self._euid == 0 import ucred cred = ucred.get(os.getpid()) if priv in [ self.PRIV_CLONE, self.PRIV_CREATE_DOMAIN, self.PRIV_CREATE_NETWORK ]: return cred.has_priv('Effective', 'virt_manage') if priv == self.PRIV_NFS_MOUNT: return (cred.has_priv('Effective', 'sys_mount') and cred.has_priv('Effective', 'net_privaddr')) def current(): """Return the current user.""" return User(os.geteuid()) current = staticmethod(current) 0707010002bbc7000081a40000000000000002000000014ae15ea700000a5a000000b600010006ffffffffffffffff0000004400000000reloc/usr/lib/python2.4/vendor-packages/virtinst/LiveCDInstaller.py# # An installer class for LiveCD images # # 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 Installer from VirtualDisk import VirtualDisk from virtinst import _virtinst as _ class LiveCDInstallerException(Exception): def __init__(self, msg): Exception.__init__(self, msg) class LiveCDInstaller(Installer.Installer): def __init__(self, type = "xen", location = None, os_type = None, conn = None): Installer.Installer.__init__(self, type=type, location=location, os_type=os_type, conn=conn) # LiveCD specific methods/overwrites def _get_location(self): return self._location def _set_location(self, val): path = None vol_tuple = None if type(val) is tuple: vol_tuple = val else: path = val if path or vol_tuple: self._install_disk = VirtualDisk(path=path, conn=self.conn, volName=vol_tuple, device = VirtualDisk.DEVICE_CDROM, readOnly = True) self._location = val self.cdrom = True location = property(_get_location, _set_location) # General Installer methods def prepare(self, guest, meter, distro = None): self.cleanup() if not self._install_disk: raise ValueError(_("CDROM media must be specified for the live " "CD installer.")) def get_install_xml(self, guest, isinstall): if isinstall: # Signifies to the 'Guest' that there is no 'install' phase return None return self._get_osblob_helper(isinstall=isinstall, guest=guest, kernel=None, bootdev="cdrom") def post_install_check(self, guest): return True 0707010002bbcf000081a40000000000000002000000014ae15ea70000075b000000b600010006ffffffffffffffff0000004200000000reloc/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 0707010002bbd1000081a40000000000000002000000014ae15ea700008cbe000000b600010006ffffffffffffffff0000003c00000000reloc/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 "" 0707010002bbbf000081a40000000000000002000000014ae15ea700001940000000b600010006ffffffffffffffff0000004100000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImageManager.py# Installer for images # # 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 import Installer import ImageParser import CapabilitiesParser as Cap import _util from VirtualDisk import VirtualDisk from virtinst import _virtinst as _ class ImageInstallerException(Exception): def __init__(self, msg): Exception.__init__(self, msg) class ImageInstaller(Installer.Installer): """Installer for image-based guests""" def __init__(self, image, capabilities=None, boot_index=None, conn=None): Installer.Installer.__init__(self, conn=conn) self._arch = None self._image = image # Set capabilities if self.conn: self._capabilities = Cap.parse(self.conn.getCapabilities()) elif capabilities: if not isinstance(capabilities, Cap.Capabilities): raise ValueError(_("'capabilities' must be a " "Capabilities instance.")) self._capabilities = capabilities else: raise ValueError(_("'conn' or 'capabilities' must be specified.")) # Set boot _boot_caps/_boot_parameters if boot_index is None: self._boot_caps = match_boots(self._capabilities, self.image.domain.boots) if self._boot_caps is None: raise ImageInstallerException(_("Could not find suitable boot " "descriptor for this host")) else: if (boot_index < 0 or (boot_index + 1) > len(image.domain.boots)): raise ValueError(_("boot_index out of range.")) self._boot_caps = image.domain.boots[boot_index] # Set up internal caps.guest object self._guest = self._capabilities.guestForOSType(self.boot_caps.type, self.boot_caps.arch) if self._guest is None: raise PlatformMatchException(_("Unsupported virtualization type: " "%s %s" % (self.boot_caps.type, self.boot_caps.arch))) self.os_type = self.boot_caps.type self._domain = self._guest.bestDomainType() self.type = self._domain.hypervisor_type self.arch = self._guest.arch # Custom ImageInstaller methods def is_hvm(self): if self._boot_caps.type == "hvm": return True return False def get_image(self): return self._image image = property(get_image) def get_boot_caps(self): return self._boot_caps boot_caps = property(get_boot_caps) # General Installer methods def prepare(self, guest, meter, distro = None): self._make_disks(guest) # Ugly: for PV xen, there's no guest.features, and nothing to toggle if self.os_type != "xen": for f in ['pae', 'acpi', 'apic']: if self.boot_caps.features[f] & Cap.FEATURE_ON: guest.features[f] = True elif self.boot_caps.features[f] & Cap.FEATURE_OFF: guest.features[f] = False def get_install_xml(self, guest, isinstall): kernel = { "kernel" : self.boot_caps.kernel, "initrd" : self.boot_caps.initrd, "extrargs" : self.boot_caps.cmdline } if self.boot_caps.kernel: isinstall = True else: isinstall = False # FYI: self.boot_caps.loader is _not_ analagous to guest loader tag return self._get_osblob_helper(guest, isinstall=isinstall, kernel=kernel, bootdev=self.boot_caps.bootdev) def post_install_check(self, guest): return True # Private methods def _make_disks(self, guest): for m in self.boot_caps.drives: p = self._abspath(m.disk.file) s = None if m.disk.size is not None: s = float(m.disk.size)/1024 # FIXME: This is awkward; the image should be able to express # whether the disk is expected to be there or not independently # of its classification, especially for user disks # FIXME: We ignore the target for the mapping in m.target if (m.disk.use == ImageParser.Disk.USE_SYSTEM and not os.path.exists(p)): raise ImageInstallerException(_("System disk %s does not exist") % p) device = VirtualDisk.DEVICE_DISK if m.disk.format == ImageParser.Disk.FORMAT_ISO: device = VirtualDisk.DEVICE_CDROM d = VirtualDisk(p, s, device = device, type = VirtualDisk.TYPE_FILE) if self.boot_caps.type == "xen" and _util.is_blktap_capable(): d.driver_name = VirtualDisk.DRIVER_TAP d.target = m.target guest._install_disks.append(d) def _abspath(self, p): return self.image.abspath(p) class PlatformMatchException(Exception): def __init__(self, msg): Exception.__init__(self, msg) def match_boots(capabilities, boots): for b in boots: for g in capabilities.guests: if b.type == g.os_type and b.arch == g.arch: found = True for bf in b.features.names(): if not b.features[bf] & g.features[bf]: found = False break if found: return b return None 0707010002bbca000081a40000000000000002000000014ae194ae000039eb000000b600010006ffffffffffffffff0000004600000000reloc/usr/lib/python2.4/vendor-packages/virtinst/NodeDeviceParser.pycm ^Jc@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)/&@    * 0707010002bbd9000081a40000000000000002000000014ae181720000849b000000b600010006ffffffffffffffff0000004000000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.py# # Classes for building disk device xml # # 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. 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', '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) # Path doesn't exist: make sure we have write access to dir if not os.access(os.path.dirname(self.path), os.R_OK): raise ValueError("No read access to directory '%s'" % os.path.dirname(self.path)) if self.size is None: raise ValueError, _("size is required for non-existent disk " "'%s'" % self.path) if not os.access(os.path.dirname(self.path), os.W_OK): raise ValueError, _("No write access to directory '%s'") % \ os.path.dirname(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 0707010002bbbd000081a40000000000000002000000014ae15ea7000019b9000000b600010006ffffffffffffffff0000004100000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.py# # Convenience module for fetching files from a network source # # Copyright 2006-2007 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 stat import subprocess import urlgrabber.grabber as grabber import urllib2 import urlparse import ftplib import tempfile from virtinst import _virtinst as _ # This is a generic base class for fetching/extracting files from # a media source, such as CD ISO, NFS server, or HTTP/FTP server class ImageFetcher: def __init__(self, location, scratchdir): self.location = location self.scratchdir = scratchdir def _make_path(self, filename): if hasattr(self, "srcdir"): path = getattr(self, "srcdir") else: path = self.location if not path.endswith("/"): path += "/" path += filename return path def saveTemp(self, fileobj, prefix): if not os.path.exists(self.scratchdir): os.makedirs(self.scratchdir, 0750) (fd, fn) = tempfile.mkstemp(prefix="virtinst-" + prefix, dir=self.scratchdir) block_size = 16384 try: while 1: buff = fileobj.read(block_size) if not buff: break os.write(fd, buff) finally: os.close(fd) return fn def prepareLocation(self): return True def cleanupLocation(self): pass def acquireFile(self, filename, progresscb): # URLGrabber works for all network and local cases f = None try: path = self._make_path(filename) base = os.path.basename(filename) logging.debug("Fetching URI: %s" % path) try: f = grabber.urlopen(path, progress_obj = progresscb, text = _("Retrieving file %s...") % base) except Exception, e: raise ValueError, _("Couldn't acquire file %s: %s") % \ (path, str(e)) tmpname = self.saveTemp(f, prefix=base + ".") logging.debug("Saved file to " + tmpname) return tmpname finally: if f: f.close() def hasFile(self, src): raise NotImplementedError("Must be implemented in subclass") # Base class for downloading from FTP / HTTP class URIImageFetcher(ImageFetcher): def hasFile(self, filename): raise NotImplementedError def prepareLocation(self): if not self.hasFile(""): raise ValueError(_("Opening URL %s failed.") % \ (self.location)) class HTTPImageFetcher(URIImageFetcher): def hasFile(self, filename): try: path = self._make_path(filename) request = urllib2.Request(path) request.get_method = lambda: "HEAD" urllib2.urlopen(request) except Exception: logging.debug("HTTP hasFile: didn't find %s" % path) return False return True class FTPImageFetcher(URIImageFetcher): def hasFile(self, filename): path = self._make_path(filename) url = urlparse.urlparse(path) try: ftp = ftplib.FTP(url[1]) ftp.login() try: ftp.size(url[2]) # If a file except ftplib.all_errors: ftp.cwd(url[2]) # If a dir except ftplib.all_errors: logging.debug("FTP hasFile: couldn't access %s/%s" % \ (url[1], url[2])) return False return True class LocalImageFetcher(ImageFetcher): def __init__(self, location, scratchdir, srcdir=None): ImageFetcher.__init__(self, location, scratchdir) self.srcdir = srcdir def hasFile(self, filename): src = self._make_path(filename) if os.path.exists(src): return True else: logging.debug("local hasFile: Couldn't find %s" % src) return False # This is a fetcher capable of extracting files from a NFS server # or loopback mounted file, or local CDROM device class MountedImageFetcher(LocalImageFetcher): def prepareLocation(self): cmd = None self.srcdir = tempfile.mkdtemp(prefix="virtinstmnt.", dir=self.scratchdir) mountcmd = "/bin/mount" if os.uname()[0] == "SunOS": mountcmd = "/usr/sbin/mount" logging.debug("Preparing mount at " + self.srcdir) if self.location.startswith("nfs:"): cmd = [mountcmd, "-o", "ro", self.location[4:], self.srcdir] else: if stat.S_ISBLK(os.stat(self.location)[stat.ST_MODE]): mountopt = "ro" else: mountopt = "ro,loop" if os.uname()[0] == 'SunOS': cmd = [mountcmd, "-F", "hsfs", "-o", mountopt, self.location, self.srcdir] else: cmd = [mountcmd, "-o", mountopt, self.location, self.srcdir] ret = subprocess.call(cmd) if ret != 0: self.cleanupLocation() raise ValueError(_("Mounting location '%s' failed") % (self.location)) return True def cleanupLocation(self): logging.debug("Cleaning up mount at " + self.srcdir) if os.uname()[0] == "SunOS": cmd = ["/usr/sbin/umount", self.srcdir] else: cmd = ["/bin/umount", self.srcdir] subprocess.call(cmd) try: os.rmdir(self.srcdir) except: pass class DirectImageFetcher(LocalImageFetcher): def prepareLocation(self): self.srcdir = self.location 0707010002bbd0000081a40000000000000002000000014ae194ae000005e3000000b600010006ffffffffffffffff0000004300000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ParaVirtGuest.pycm ^Jc@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  0707010002bbd4000081a40000000000000002000000014ae194ae00000853000000b600010006ffffffffffffffff0000003a00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/User.pycm ^Jc@s,dkZdkZdefdYZdS(NtUsercBstZdZdZdZdZdZdZeeeeegZdZ dZ e e Z e dZd ZeeZRS( s"Defines a particular user account.iiiiicCs ||_dS(N(teuidtselft_euid(RR((tY/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/User.pyt__init__#scCs|iS(N(RR(R((Rtget_euid&scCsy||ijotd|n||ijo|idjSntidjok| p|i dd!dj}||i |i gjo |o|idjSnt Sn|idjSn|itiijo|idjSndk}|iti}||i |i |igjo|iddSn||ijo'|idd o|idd SndS( sReturn if the given user is privileged enough to perform the given operation. This isn't entirely accurate currently, especially on Solaris.sunknown privilege %sitSunOSitxenNt Effectivet virt_managet sys_mountt net_privaddr(tprivRt_privst ValueErrortPRIV_QEMU_SYSTEMRtplatformtsystemtconntlowertis_xent PRIV_CLONEtPRIV_CREATE_DOMAINtTrueRtcurrentRtucredtgettostgetpidtcredtPRIV_CREATE_NETWORKthas_privtPRIV_NFS_MOUNT(RR RRRR((RR *s(! cCsttiS(sReturn the current user.N(RRtgeteuid(((RRJs(t__name__t __module__t__doc__RR!RRRRRRtpropertyRtNoneR Rt staticmethod(((RRs     (RRtobjectR(RRR((Rt?s  0707010002bbe4000081a40000000000000002000000014ae194ae000016ff000000b600010006ffffffffffffffff0000003b00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/_util.pycm rJc@sdkZdkZdkZdkZdkZdkZdklZdklZ dZ dZ dZ dZ dZdZd Zd Zd ZeiZeiZeiZeiZeiZeiZeiZeiZeiZeiZeiZeiZeiZei Z ei!Z!ei"Z"ei#Z#ei$Z$ei%Z%ei&Z&ei'Z'ei(Z(ei)Z)ei*Z*ei+Z+ei,Z,ei-Z-dS( N(sutil(s _virtinstcCstiidptSn|djotSn|djotii| otSntii|otii|dotSntS(Ns/usr/sbin/vdiskadmttaps /vdisk.xml(tostpathtexiststFalsetdrivertTruetNonetisdir(RR((tZ/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/_util.pytis_vdisk%s !*cCs tii|ptdfSnt|do'ttid|}t|fSnti |t i }t i |oYy;ti|ti}ti|dd}ti|Wn d}nXt|fSn+t i|ottii|fSntdfS(s Returns the tuple (isreg, size).isvdiskadm prop-get -p max-size iN(RRRRR Rtinttcommandst getoutputtsizetstattST_MODEtmodetS_ISBLKtopentO_RDONLYtfdtlseektcloseRtS_ISREGtgetsize(RRRR((R t stat_disk1s$ cCs;ti|ti}ti|dd}ti||S(shReturn the size of the block device. We can't use os.stat() as that returns zero on many platforms.iiN(RRRRRRRR(RRR((R t blkdev_sizeLs  cCsU|p|Sn|ii}tid|odSn|djodSn|S(saEnsure passed architecture string is the format we expect it. Returns the sanitized resultsi[3-9]86ti686tamd64tx86_64N(tarchtlowertstripttmparchtretmatch(RR"((R t sanitize_archUs cCsXt}|dj oAy$|i|dj o t}nWqTtij oqTXn|S(si Check if passed UUID string is in use by another guest of the connection Returns true/false N( RtchecktuuidRtconntlookupByUUIDStringRtlibvirtt libvirtError(R(R'R&((R tvm_uuid_collisionas  cCst|tj ottdntid|}|djotid|}|djottdq|dd!d|dd!d|dd !d|d d !d|d d !}n|S( NsUUID must be a string.s7[a-fA-F0-9]{8}[-]([a-fA-F0-9]{4}[-]){3}[a-fA-F0-9]{12}$s[a-fA-F0-9]{32}$sUUID must be a 32-digit hexadecimal number. It may take the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX or may omit hyphens altogether.iit-i iii ( ttypetvaltstrt ValueErrort_R#R$tformR(R/R3((R t validate_uuidos    McCst|tdj p&t|djpt|djottd|ntid|ottd|ntid|djottd|ndS( Ntstringi2is4%s name must be a string between 0 and 50 characterss^[0-9]+$s*%s name can not be only numeric characterss^[a-zA-Z0-9._-]+$sB%s name can only contain alphanumeric, '_', '.', or '-' characters( R.R/tlenR1R2t name_typeR#R$R(R7R/((R t validate_names ?cCs,|p|Sn|o|d7}n||S(s< Little function that helps generate consistent xml s N(tnewtorig(R:R9((R t xml_appends cCsg}g}|i}xX|D]P}y |i|}|i|Wqt i j ot i d|qXqW|i }xI|D]A}y |i|}|i|Wqt i d|qXqW||fS(sC Return 2 lists: ([all_running_vms], [all_nonrunning_vms]) s$Failed to lookup active domain id %ds#Failed to lookup inactive domain %dN(tactivetinactiveR(t listDomainsIDtidstit lookupByIDtvmtappendR*R+tloggingtwarntlistDefinedDomainstnamestnamet lookupByName(R(RHR@R?RBR=RGR<((R tfetch_all_guestss(  (.RRR#R RDR*tvirtinsttutilt _virtinstR2R RRR%R,R4R8R;RJt default_routetdefault_bridgetdefault_networktdefault_connectiont get_cpu_flagstis_pae_capabletis_blktap_capabletget_default_archt randomMACt randomUUIDt uuidToStringtuuidFromStringtget_host_network_devicest get_max_vcpust get_phy_cpust xml_escapet compareMACtdefault_keymapt pygrub_patht uri_splitt is_uri_remotetget_uri_hostnametget_uri_transporttget_uri_drivertis_storage_capablet get_xml_pathtlookup_pool_by_path(,ReRQRNRXRhRORWRfRR\RbR R`RYR#R4RRRVR%RdRR[RaRgR8R*RLRSRcRJRTR^RR2R RDRURZR]RPR_R,R;R((R t?sV            !                          0707010002bbe1000081a40000000000000002000000014ae15ea70000086d000000b600010006ffffffffffffffff0000003d00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/__init__.py# # 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 gettext gettext_dir = "::LOCALEDIR::" gettext_app = "virtinst" gettext.bindtextdomain(gettext_app, gettext_dir) def _virtinst(msg): return gettext.dgettext(gettext_app, msg) import util import Storage from Guest import Guest, XenGuest from VirtualNetworkInterface import VirtualNetworkInterface, \ XenNetworkInterface from VirtualGraphics import VirtualGraphics from VirtualAudio import VirtualAudio from VirtualDisk import VirtualDisk, XenDisk from VirtualHostDevice import (VirtualHostDevice, VirtualHostDeviceUSB, VirtualHostDevicePCI) from FullVirtGuest import FullVirtGuest from ParaVirtGuest import ParaVirtGuest from DistroInstaller import DistroInstaller from PXEInstaller import PXEInstaller from LiveCDInstaller import LiveCDInstaller from ImportInstaller import ImportInstaller from ImageManager import ImageInstaller from CloneManager import CloneDesign from User import User # This represents the PUBLIC API. Any changes to these classes (or 'util.py') # must be mindful of this fact. __all__ = ["Guest", "XenGuest", "VirtualNetworkInterface", "XenNetworkInterface", "VirtualGraphics", "VirtualAudio", "VirtualDisk", "XenDisk", "FullVirtGuest", "ParaVirtGuest", "DistroInstaller", "PXEInstaller", "LiveCDInstaller", "ImportInstaller", "ImageInstaller", "CloneDesign", "Storage", "User", "util"] 0707010002bbea000081a40000000000000002000000014ae194ae00001364000000b600010006ffffffffffffffff0000003c00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/osdict.pycm rJc@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 logging import os import gzip import re import tempfile import socket import ConfigParser import virtinst from virtinst import _util from virtinst import _virtinst as _ from ImageFetcher import MountedImageFetcher from ImageFetcher import FTPImageFetcher from ImageFetcher import HTTPImageFetcher from ImageFetcher import DirectImageFetcher def _fetcherForURI(uri, scratchdir=None): if uri.startswith("http://"): fclass = HTTPImageFetcher elif uri.startswith("ftp://"): fclass = FTPImageFetcher elif uri.startswith("nfs://"): fclass = MountedImageFetcher else: if os.path.isdir(uri): fclass = DirectImageFetcher else: fclass = MountedImageFetcher return fclass(uri, scratchdir) def _storeForDistro(fetcher, baseuri, typ, progresscb, arch, distro=None, scratchdir=None): stores = [] skip_treeinfo = False logging.debug("Attempting to detect distro:") dist = virtinst.OSDistro.distroFromTreeinfo(fetcher, progresscb, baseuri, arch, typ, scratchdir) if dist: return dist skip_treeinfo = True # FIXME: This 'distro ==' doesn't cut it. 'distro' is from our os # dictionary, so would look like 'fedora9' or 'rhel5', so this needs # to be a bit more intelligent if distro == "fedora" or distro is None: stores.append(FedoraDistro) if distro == "rhel" or distro is None: stores.append(RHELDistro) if distro == "centos" or distro is None: stores.append(CentOSDistro) if distro == "sl" or distro is None: stores.append(SLDistro) if distro == "suse" or distro is None: stores.append(SuseDistro) if distro == "debian" or distro is None: stores.append(DebianDistro) if distro == "ubuntu" or distro is None: stores.append(UbuntuDistro) if distro == "mandriva" or distro is None: stores.append(MandrivaDistro) # XXX: this is really "nevada" if distro == "solaris" or distro is None: stores.append(SolarisDistro) if distro == "solaris" or distro is None: stores.append(OpenSolarisDistro) if distro == "netware" or distro is None: stores.append(NetWareDistro) stores.append(GenericDistro) for sclass in stores: store = sclass(baseuri, arch, typ, scratchdir) if skip_treeinfo: store.uses_treeinfo = False if store.isValidStore(fetcher, progresscb): return store raise ValueError, _("Could not find an installable distribution at '%s'" % baseuri) def _acquireMedia(iskernel, guest, baseuri, progresscb, arch, scratchdir="/var/tmp", _type=None, distro=None): fetcher = _fetcherForURI(baseuri, scratchdir) try: fetcher.prepareLocation() except ValueError, e: raise ValueError, _("Invalid install location: ") + str(e) try: store = _storeForDistro(fetcher=fetcher, baseuri=baseuri, typ=_type, progresscb=progresscb, distro=distro, scratchdir=scratchdir, arch=arch) if iskernel is True: # FIXME: We should probably do this for both kernel and boot # disk? return (store.acquireKernel(guest, fetcher, progresscb), store.os_type, store.os_variant) elif iskernel is False: return store.acquireBootDisk(fetcher, progresscb) else: # Kind of a hack. Just return the store for detectDistro return store finally: fetcher.cleanupLocation() # Helper method to lookup install media distro and fetch an install kernel def acquireKernel(guest, baseuri, progresscb, arch, scratchdir="/var/tmp", type=None, distro=None): return _acquireMedia(True, guest, baseuri, progresscb, arch, scratchdir, type, distro) # Helper method to lookup install media distro and fetch a boot iso def acquireBootDisk(baseuri, progresscb, arch, scratchdir="/var/tmp", type=None, distro=None): return _acquireMedia(False, None, baseuri, progresscb, arch, scratchdir, type, distro) # Attempt to detect the os type + variant for the passed location def detectMediaDistro(location, arch): import urlgrabber progress = urlgrabber.progress.BaseMeter() store = _acquireMedia(None, None, location, progress, arch, "/var/tmp") return (store.os_type, store.os_variant) def distroFromTreeinfo(fetcher, progresscb, uri, arch, vmtype=None, scratchdir=None): # Parse treeinfo 'family' field, and return the associated Distro class # None if no treeinfo, GenericDistro if unknown family type. if not fetcher.hasFile(".treeinfo"): return None tmptreeinfo = fetcher.acquireFile(".treeinfo", progresscb) try: treeinfo = ConfigParser.SafeConfigParser() treeinfo.read(tmptreeinfo) finally: os.unlink(tmptreeinfo) fam = treeinfo.get("general", "family") if re.match(".*Fedora.*", fam): dclass = FedoraDistro elif re.match(".*CentOS.*", fam): dclass = CentOSDistro elif re.match(".*Red Hat Enterprise Linux.*", fam): dclass = RHELDistro elif re.match(".*Scientific Linux.*", fam): dclass = SLDistro else: dclass = GenericDistro ob = dclass(uri, arch, vmtype, scratchdir) ob.treeinfo = treeinfo # Explictly call this, so we populate os_type/variant info ob.isValidStore(fetcher, progresscb) return ob # An image store is a base class for retrieving either a bootable # ISO image, or a kernel+initrd pair for a particular OS distribution class Distro: name = "" # osdict type and variant values os_type = None os_variant = None _boot_iso_paths = [] _hvm_kernel_paths = [] _xen_kernel_paths = [] uses_treeinfo = False def __init__(self, uri, arch, vmtype=None, scratchdir=None): self.uri = uri self.type = vmtype self.scratchdir = scratchdir self.arch = arch self.treeinfo = None def isValidStore(self, fetcher, progresscb): """Determine if uri points to a tree of the store's distro""" raise NotImplementedError def acquireKernel(self, guest, fetcher, progresscb): kernelpath = None initrdpath = None if self._hasTreeinfo(fetcher, progresscb): kernelpath = self._getTreeinfoMedia("kernel") initrdpath = self._getTreeinfoMedia("initrd") else: # fall back to old code if self.type is None or self.type == "hvm": paths = self._hvm_kernel_paths else: paths = self._xen_kernel_paths for kpath, ipath in paths: if fetcher.hasFile(kpath) and fetcher.hasFile(ipath): kernelpath = kpath initrdpath = ipath if not kernelpath or not initrdpath: raise RuntimeError(_("Couldn't find %(type)s kernel for " "%(distro)s tree.") % \ { "distro": self.name, "type" : self.type }) return self._kernelFetchHelper(fetcher, guest, progresscb, kernelpath, initrdpath) def acquireBootDisk(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): return fetcher.acquireFile(self._getTreeinfoMedia("boot.iso")) else: for path in self._boot_iso_paths: if fetcher.hasFile(path): return fetcher.acquireFile(path, progresscb) raise RuntimeError(_("Could not find boot.iso in %s tree." % \ self.name)) def _hasTreeinfo(self, fetcher, progresscb): # all Red Hat based distros should have .treeinfo, perhaps others # will in time if not (self.treeinfo is None): return True if not self.uses_treeinfo or not fetcher.hasFile(".treeinfo"): return False logging.debug("Detected .treeinfo file") tmptreeinfo = fetcher.acquireFile(".treeinfo", progresscb) try: self.treeinfo = ConfigParser.SafeConfigParser() self.treeinfo.read(tmptreeinfo) finally: os.unlink(tmptreeinfo) return True def _getTreeinfoMedia(self, mediaName): if self.type == "xen": t = "xen" else: t = self.treeinfo.get("general", "arch") return self.treeinfo.get("images-%s" % t, mediaName) def _fetchAndMatchRegex(self, fetcher, progresscb, filename, regex): # Fetch 'filename' and return True/False if it matches the regex local_file = None try: try: local_file = fetcher.acquireFile(filename, progresscb) except: return False f = open(local_file, "r") try: while 1: buf = f.readline() if not buf: break if re.match(regex, buf): return True finally: f.close() finally: if local_file is not None: os.unlink(local_file) return False def _kernelFetchHelper(self, fetcher, guest, progresscb, kernelpath, initrdpath): # Simple helper for fetching kernel + initrd and performing # cleanup if neccessary kernel = fetcher.acquireFile(kernelpath, progresscb) args = '' if not fetcher.location.startswith("/"): args += "method=" + fetcher.location if guest.extraargs: args += " " + guest.extraargs try: initrd = fetcher.acquireFile(initrdpath, progresscb) return kernel, initrd, args except: os.unlink(kernel) class GenericDistro(Distro): """Generic distro store. Check well known paths for kernel locations as a last resort if we can't recognize any actual distro""" name = "Generic" os_type = "linux" uses_treeinfo = True _xen_paths = [ ("images/xen/vmlinuz", "images/xen/initrd.img"), # Fedora ] _hvm_paths = [ ("images/pxeboot/vmlinuz", "images/pxeboot/initrd.img"), # Fedora ] _iso_paths = [ "images/boot.iso", # RH/Fedora "boot/boot.iso", # Suse "current/images/netboot/mini.iso", # Debian "install/images/boot.iso", # Mandriva ] # Holds values to use when actually pulling down media _valid_kernel_path = None _valid_iso_path = None def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): # Use treeinfo to pull down media paths if self.type == "xen": typ = "xen" else: typ = self.treeinfo.get("general", "arch") kernelSection = "images-%s" % typ isoSection = "images-%s" % self.treeinfo.get("general", "arch") if self.treeinfo.has_section(kernelSection): self._valid_kernel_path = (self._getTreeinfoMedia("kernel"), self._getTreeinfoMedia("initrd")) if self.treeinfo.has_section(isoSection): self._valid_iso_path = self.treeinfo.get(isoSection, "boot.iso") if self.type == "xen": kern_list = self._xen_paths else: kern_list = self._hvm_paths # If validated media paths weren't found (no treeinfo), check against # list of media location paths. for kern, init in kern_list: if self._valid_kernel_path == None \ and fetcher.hasFile(kern) and fetcher.hasFile(init): self._valid_kernel_path = (kern, init) break for iso in self._iso_paths: if self._valid_iso_path == None \ and fetcher.hasFile(iso): self._valid_iso_path = iso break if self._valid_kernel_path or self._valid_iso_path: return True return False def acquireKernel(self, guest, fetcher, progresscb): if self._valid_kernel_path == None: raise ValueError(_("Could not find a kernel path for virt type " "'%s'" % self.type)) return self._kernelFetchHelper(fetcher, guest, progresscb, self._valid_kernel_path[0], self._valid_kernel_path[1]) def acquireBootDisk(self, fetcher, progresscb): if self._valid_iso_path == None: raise ValueError(_("Could not find a boot iso path for this tree.")) return fetcher.acquireFile(self._valid_iso_path, progresscb) # Base image store for any Red Hat related distros which have # a common layout class RedHatDistro(Distro): name = "Red Hat" os_type = "linux" uses_treeinfo = True _boot_iso_paths = [ "images/boot.iso" ] _hvm_kernel_paths = [ ("images/pxeboot/vmlinuz", "images/pxeboot/initrd.img") ] _xen_kernel_paths = [ ("images/xen/vmlinuz", "images/xen/initrd.img") ] def isValidStore(self, fetcher, progresscb): raise NotImplementedError # Fedora distro check class FedoraDistro(RedHatDistro): name = "Fedora" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): m = re.match(".*Fedora.*", self.treeinfo.get("general", "family")) ret = (m != None) if ret: ver = self.treeinfo.get("general", "version") if ver == "development": self.os_variant = self._latestFedoraVariant() elif ver: self.os_variant = "fedora" + str(ver) return ret else: if fetcher.hasFile("Fedora"): logging.debug("Detected a Fedora distro") return True return False def _latestFedoraVariant(self): import osdict ret = None for var in osdict.sort_helper(osdict.OS_TYPES["linux"]["variants"]): if var.startswith("fedora"): # Last fedora* occurence should be the newest ret = var return ret # Red Hat Enterprise Linux distro check class RHELDistro(RedHatDistro): name = "Red Hat Enterprise Linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): m = re.match(".*Red Hat Enterprise Linux.*", self.treeinfo.get("general", "family")) ret = (m != None) if ret: self._variantFromVersion() return ret else: # fall back to old code if fetcher.hasFile("Server"): logging.debug("Detected a RHEL 5 Server distro") self.os_variant = "rhel5" return True if fetcher.hasFile("Client"): logging.debug("Detected a RHEL 5 Client distro") self.os_variant = "rhel5" return True if fetcher.hasFile("RedHat"): logging.debug("Detected a RHEL 4 distro") self.os_variant = "rhel4" return True return False def _variantFromVersion(self): # XXX: Version will look like '5.2', rather than just '5'. We # need to support this in the os dictionary at some point, but for # now, just use the '5' part ver = self.treeinfo.get("general", "version") if not ver: return self.os_variant = "rhel" + ver[0] # CentOS distro check class CentOSDistro(RHELDistro): name = "CentOS" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): m = re.match(".*CentOS.*", self.treeinfo.get("general", "family")) ret = (m != None) if ret: self._variantFromVersion() return ret else: # fall back to old code if fetcher.hasFile("CentOS"): logging.debug("Detected a CentOS distro") return True return False # Scientific Linux distro check class SLDistro(RHELDistro): name = "Scientific Linux" _boot_iso_paths = RHELDistro._boot_iso_paths + [ "images/SL/boot.iso" ] _hvm_kernel_paths = RHELDistro._hvm_kernel_paths + \ [ ("images/SL/pxeboot/vmlinuz", "images/SL/pxeboot/initrd.img") ] def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): m = re.match(".*Scientific Linux.*", self.treeinfo.get("general", "family")) ret = (m != None) if ret: self._variantFromVersion() return ret else: if fetcher.hasFile("SL"): logging.debug("Detected a Scientific Linux distro") return True return False # Suse image store is harder - we fetch the kernel RPM and a helper # RPM and then munge bits together to generate a initrd class SuseDistro(Distro): name = "SUSE" os_type = "linux" _boot_iso_paths = [ "boot/boot.iso" ] _hvm_kernel_paths = [] _xen_kernel_paths = [] def __init__(self, uri, arch, vmtype=None, scratchdir=None): Distro.__init__(self, uri, arch, vmtype, scratchdir) if re.match(r'i[4-9]86', arch): self.arch = 'i386' # Tested with Opensuse 10, 11, and sles 10 self._hvm_kernel_paths += [ ("boot/%s/loader/linux" % self.arch, "boot/%s/loader/initrd" % self.arch) ] # Matches Opensuse > 10.2 and sles 10 self._xen_kernel_paths += [ ("boot/x86_64/vmlinuz-xen", "boot/x86_64/initrd-xen"), ("boot/i386/vmlinuz-xen", "boot/i386/initrd-xen") ] def isValidStore(self, fetcher, progresscb): # Suse distros always have a 'directory.yast' file in the top # level of install tree, which we use as the magic check if fetcher.hasFile("directory.yast"): logging.debug("Detected a Suse distro.") return True return False def acquireKernel(self, guest, fetcher, progresscb): # If installing a fullvirt guest, or PV kernel is found if (self.type is None or self.type == "hvm" or fetcher.hasFile(self._xen_kernel_paths[0][0]) or fetcher.hasFile(self._xen_kernel_paths[1][0])): return Distro.acquireKernel(self, guest, fetcher, progresscb) # For Opensuse <= 10.2, we need to perform some heinous stuff logging.debug("Trying Opensuse 10 PV rpm hacking") return self._findXenRPMS(fetcher, progresscb) def _kernelFetchHelper(self, fetcher, guest, progresscb, kernelpath, initrdpath): # Simple helper for fetching kernel + initrd and performing # cleanup if neccessary kernel = fetcher.acquireFile(kernelpath, progresscb) args = '' if not fetcher.location.startswith("/"): location = fetcher.location if not location.startswith("nfs://"): location = location.replace("nfs:", "nfs://") args += "install=" + location if guest.extraargs: args += " " + guest.extraargs if not guest.graphics['enabled']: args += " textmode=1 xencons=tty" try: initrd = fetcher.acquireFile(initrdpath, progresscb) return kernel, initrd, args except: os.unlink(kernel) def _findXenRPMS(self, fetcher, progresscb): kernelrpm = None installinitrdrpm = None filelist = None try: # There is no predictable filename for kernel/install-initrd RPMs # so we have to grok the filelist and find them filelist = fetcher.acquireFile("ls-lR.gz", progresscb) (kernelrpmname, initrdrpmname) = self._extractRPMNames(filelist) # Now fetch the two RPMs we want kernelrpm = fetcher.acquireFile(kernelrpmname, progresscb) installinitrdrpm = fetcher.acquireFile(initrdrpmname, progresscb) # Process the RPMs to extract the kernel & generate an initrd return self._buildKernelInitrd(fetcher, kernelrpm, installinitrdrpm, progresscb) finally: if filelist is not None: os.unlink(filelist) if kernelrpm is not None: os.unlink(kernelrpm) if installinitrdrpm is not None: os.unlink(installinitrdrpm) # We need to parse the ls-lR.gz file, looking for the kernel & # install-initrd RPM entries - capturing the directory they are # in and the version'd filename. def _extractRPMNames(self, filelist): filelistData = gzip.GzipFile(filelist, mode = "r") try: arches = [self.arch] # On i686 arch, we also look under i585 and i386 dirs # in case the RPM is built for a lesser arch. We also # need the PAE variant (for Fedora dom0 at least) # # XXX shouldn't hard code that dom0 is PAE if self.arch == "i386": arches.append("i586") arches.append("i686") kernelname = "kernel-xenpae" else: kernelname = "kernel-xen" installinitrdrpm = None kernelrpm = None dirname = None while 1: data = filelistData.readline() if not data: break if dirname is None: for arch in arches: wantdir = "/suse/" + arch if data == "." + wantdir + ":\n": dirname = wantdir break else: if data == "\n": dirname = None else: if data[:5] != "total": filename = re.split("\s+", data)[8] if filename[:14] == "install-initrd": installinitrdrpm = dirname + "/" + filename elif filename[:len(kernelname)] == kernelname: kernelrpm = dirname + "/" + filename if kernelrpm is None: raise Exception(_("Unable to determine kernel RPM path")) if installinitrdrpm is None: raise Exception(_("Unable to determine install-initrd RPM path")) return (kernelrpm, installinitrdrpm) finally: filelistData.close() # We have a kernel RPM and a install-initrd RPM with a generic initrd in it # Now we have to merge the two together to build an initrd capable of # booting the installer. # # Yes, this is crazy ass stuff :-) def _buildKernelInitrd(self, fetcher, kernelrpm, installinitrdrpm, progresscb): progresscb.start(text=_("Building initrd"), size=11) progresscb.update(1) cpiodir = tempfile.mkdtemp(prefix="virtinstcpio.", dir=self.scratchdir) try: # Extract the kernel RPM contents os.mkdir(cpiodir + "/kernel") cmd = "cd " + cpiodir + "/kernel && (rpm2cpio " + kernelrpm + " | cpio --quiet -idm)" logging.debug("Running " + cmd) os.system(cmd) progresscb.update(2) # Determine the raw kernel version kernelinfo = None for f in os.listdir(cpiodir + "/kernel/boot"): if f.startswith("System.map-"): kernelinfo = re.split("-", f) kernel_override = kernelinfo[1] + "-override-" + kernelinfo[3] kernel_version = kernelinfo[1] + "-" + kernelinfo[2] + "-" + kernelinfo[3] logging.debug("Got kernel version " + str(kernelinfo)) # Build a list of all .ko files modpaths = {} for root, dummy, files in os.walk(cpiodir + "/kernel/lib/modules", topdown=False): for name in files: if name.endswith(".ko"): modpaths[name] = os.path.join(root, name) progresscb.update(3) # Extract the install-initrd RPM contents os.mkdir(cpiodir + "/installinitrd") cmd = "cd " + cpiodir + "/installinitrd && (rpm2cpio " + installinitrdrpm + " | cpio --quiet -idm)" logging.debug("Running " + cmd) os.system(cmd) progresscb.update(4) # Read in list of mods required for initrd modnames = [] fn = open(cpiodir + "/installinitrd/usr/lib/install-initrd/" + kernelinfo[3] + "/module.list", "r") try: while 1: line = fn.readline() if not line: break line = line[:len(line)-1] modnames.append(line) finally: fn.close() progresscb.update(5) # Uncompress the basic initrd cmd = "gunzip -c " + cpiodir + "/installinitrd/usr/lib/install-initrd/initrd-base.gz > " + cpiodir + "/initrd.img" logging.debug("Running " + cmd) os.system(cmd) progresscb.update(6) # Create temp tree to hold stuff we're adding to initrd moddir = cpiodir + "/initrd/lib/modules/" + kernel_override + "/initrd/" moddepdir = cpiodir + "/initrd/lib/modules/" + kernel_version os.makedirs(moddir) os.makedirs(moddepdir) os.symlink("../" + kernel_override, moddepdir + "/updates") os.symlink("lib/modules/" + kernel_override + "/initrd", cpiodir + "/initrd/modules") cmd = "cp " + cpiodir + "/installinitrd/usr/lib/install-initrd/" + kernelinfo[3] + "/module.config" + " " + moddir logging.debug("Running " + cmd) os.system(cmd) progresscb.update(7) # Copy modules we need into initrd staging dir for modname in modnames: if modpaths.has_key(modname): src = modpaths[modname] dst = moddir + "/" + modname os.system("cp " + src + " " + dst) progresscb.update(8) # Run depmod across the staging area cmd = "depmod -a -b " + cpiodir + "/initrd -F " + cpiodir + "/kernel/boot/System.map-" + kernel_version + " " + kernel_version logging.debug("Running " + cmd) os.system(cmd) progresscb.update(9) # Add the extra modules to the basic initrd cmd = "cd " + cpiodir + "/initrd && ( find . | cpio --quiet -o -H newc -A -F " + cpiodir + "/initrd.img)" logging.debug("Running " + cmd) os.system(cmd) progresscb.update(10) # Compress the final initrd cmd = "gzip -f9N " + cpiodir + "/initrd.img" logging.debug("Running " + cmd) os.system(cmd) progresscb.end(11) # Save initrd & kernel to temp files for booting... initrdname = fetcher.saveTemp(open(cpiodir + "/initrd.img.gz", "r"), "initrd.img") logging.debug("Saved " + initrdname) try: kernelname = fetcher.saveTemp(open(cpiodir + "/kernel/boot/vmlinuz-" + kernel_version, "r"), "vmlinuz") logging.debug("Saved " + kernelname) return (kernelname, initrdname, "install=" + fetcher.location) except: os.unlink(initrdname) finally: #pass os.system("rm -rf " + cpiodir) class DebianDistro(Distro): # ex. http://ftp.egr.msu.edu/debian/dists/sarge/main/installer-i386/ # daily builds: http://people.debian.org/~joeyh/d-i/ name = "Debian" os_type = "linux" def __init__(self, uri, arch, vmtype=None, scratchdir=None): Distro.__init__(self, uri, arch, vmtype, scratchdir) if uri.count("installer-i386"): self._treeArch = "i386" elif uri.count("installer-amd64"): self._treeArch = "amd64" else: self._treeArch = "i386" if re.match(r'i[4-9]86', arch): self.arch = 'i386' self._prefix = 'current/images' self._set_media_paths() def _set_media_paths(self): # Use self._prefix to set media paths self._boot_iso_paths = [ "%s/netboot/mini.iso" % self._prefix ] hvmroot = "%s/netboot/debian-installer/%s/" % (self._prefix, self._treeArch) xenroot = "%s/netboot/xen/" % self._prefix self._hvm_kernel_paths = [ (hvmroot + "linux", hvmroot + "initrd.gz") ] self._xen_kernel_paths = [ (xenroot + "vmlinuz", xenroot + "initrd.gz") ] def isValidStore(self, fetcher, progresscb): # For regular trees if fetcher.hasFile("%s/MANIFEST" % self._prefix): pass # For daily trees elif fetcher.hasFile("images/daily/MANIFEST"): self._prefix = "images/daily" self._set_media_paths() else: logging.debug("Doesn't look like a Debian distro.") return False filename = "%s/MANIFEST" % self._prefix if self._fetchAndMatchRegex(fetcher, progresscb, filename, ".*debian-installer.*"): logging.debug("Detected a Debian distro") return True return False class UbuntuDistro(DebianDistro): name = "Ubuntu" def _set_media_paths(self): DebianDistro._set_media_paths(self) root = "%s/netboot/ubuntu-installer/%s/" % (self._prefix, self._treeArch) self._hvm_kernel_paths = [ (root + "linux", root + "initrd.gz") ] self._xen_kernel_paths = [] def isValidStore(self, fetcher, progresscb): # Don't support any paravirt installs if self.type is not None and self.type != "hvm": return False # For regular trees if not fetcher.hasFile("%s/MANIFEST" % self._prefix): return False if self._fetchAndMatchRegex(fetcher, progresscb, "%s/MANIFEST" % self._prefix, ".*ubuntu-installer.*"): logging.debug("Detected an Ubuntu distro") return True return False class MandrivaDistro(Distro): # Ex. ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2007.1/x86_64/ name = "Mandriva" os_type = "linux" _boot_iso_paths = [ "install/images/boot.iso" ] # Kernels for HVM: valid for releases 2007.1, 2008.*, 2009.0 _hvm_kernel_paths = [ ("isolinux/alt0/vmlinuz", "isolinux/alt0/all.rdz")] _xen_kernel_paths = [] def isValidStore(self, fetcher, progresscb): # Don't support any paravirt installs if self.type is not None and self.type != "hvm": return False # Mandriva websites / media appear to have a VERSION # file in top level which we can use as our 'magic' # check for validity if not fetcher.hasFile("VERSION"): return False if self._fetchAndMatchRegex(fetcher, progresscb, "VERSION", ".*Mandriva.*"): logging.debug("Detected a Mandriva distro") return True return False # Solaris and OpenSolaris distros class SunDistro(Distro): name = "Solaris" os_type = "solaris" def isValidStore(self, fetcher, progresscb): """Determine if uri points to a tree of the store's distro""" raise NotImplementedError def acquireBootDisk(self, fetcher, progresscb): return fetcher.acquireFile("images/solarisdvd.iso", progresscb) def process_extra_args(self, argstr): """Collect additional arguments.""" if not argstr: return (None, None, None, None) kopts = '' kargs = '' smfargs = '' Bargs = '' args = argstr.split() i = 0 while i < len(args): exarg = args[i] if exarg == '-B': i += 1 if i == len(args): continue if not Bargs: Bargs = args[i] else: Bargs = ','.join([Bargs, args[i]]) elif exarg == '-m': i += 1 if i == len(args): continue smfargs = args[i] elif exarg.startswith('-'): if kopts is None: kopts = exarg[1:] else: kopts = kopts + exarg[1:] else: if kargs is None: kargs = exarg else: kargs = kargs + ' ' + exarg i += 1 return kopts, kargs, smfargs, Bargs class SolarisDistro(SunDistro): kernelpath = 'boot/platform/i86xpv/kernel/unix' initrdpath = 'boot/x86.miniroot' def isValidStore(self, fetcher, progresscb): if fetcher.hasFile(self.kernelpath) and fetcher.hasFile(self.initrdpath): logging.debug('Detected Solaris') return True return False def install_args(self, guest): """Construct 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.""" # XXX: ignoring smfargs for the time being (kopts, kargs, ignore_smfargs, kbargs) = \ self.process_extra_args(guest.extraargs) args = [ '' ] if kopts: args += [ '-%s' % kopts ] if kbargs: args += [ '-B', kbargs ] netmask = '' # Yuck. Non-default netmasks require this option to be passed. # It's distinctly not-trivial to work out the netmask to be used # automatically. if kargs: for karg in kargs.split(): if karg.startswith('subnet-mask'): netmask = karg.split('=')[1] else: args += [ kargs ] iargs = '' if not guest.graphics['enabled']: iargs += 'nowin ' if guest.autocf: iargs += ' install ' if guest.location.startswith('nfs:'): try: guestIP = socket.gethostbyaddr(guest.name)[2][0] except: iargs += ' dhcp' else: iserver = guest.location.split(':')[1] ipath = guest.location.split(':')[2] iserverIP = socket.gethostbyaddr(iserver)[2][0] iargs += ' -B install_media=' + iserverIP + ':' + ipath iargs += ',host-ip=' + guestIP if netmask: iargs += ',subnet-mask=%s' % netmask droute = _util.default_route(guest.nics[0].bridge) if droute: iargs += ',router-ip=' + droute if guest.nics[0].macaddr: en = guest.nics[0].macaddr.split(':') for i in range(len(en)): # remove leading '0' from mac address element if len(en[i]) > 1 and en[i][0] == '0': en[i] = en[i][1] boot_mac = ':'.join(en) iargs += ',boot-mac=' + boot_mac if guest.autocf: acf_host = guest.autocf.split(':')[1] acf_path = guest.autocf.split(':')[2] try: acf_hostip = socket.gethostbyaddr(acf_host)[2][0] iargs += ',sysid_config=' + acf_hostip + ':' + acf_path iargs += ',install_config=' + acf_hostip + ':' + acf_path except: raise RuntimeError('failed to lookup host %s' % acf_host) else: iargs += '-B install_media=cdrom' args += [ '-', iargs ] return ' '.join(args) def acquireKernel(self, guest, fetcher, progresscb): try: kernel = fetcher.acquireFile(self.kernelpath, progresscb) except: raise RuntimeError("Solaris PV kernel not found at %s" % self.kernelpath) # strip boot from the kernel path kpath = self.kernelpath.split('/')[1:] args = "/" + "/".join(kpath) + self.install_args(guest) try: initrd = fetcher.acquireFile(self.initrdpath, progresscb) return (kernel, initrd, args) except: os.unlink(kernel) raise RuntimeError(_("Solaris miniroot not found at %s") % self.initrdpath) class OpenSolarisDistro(SunDistro): os_variant = "opensolaris" kernelpath = "platform/i86xpv/kernel/unix" initrdpaths = [ "platform/i86pc/boot_archive", "boot/x86.microroot" ] def isValidStore(self, fetcher, progresscb): if fetcher.hasFile(self.kernelpath): logging.debug("Detected OpenSolaris") return True return False def install_args(self, guest): """Construct 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.""" # XXX: ignoring smfargs and kargs for the time being (kopts, ignore_kargs, ignore_smfargs, kbargs) = \ self.process_extra_args(guest.extraargs) args = '' if kopts: args += ' -' + kopts if kbargs: args += ' -B ' + kbargs # For OpenSolaris AI install, pull install server # and other options from the autocf entry if guest.has_autocf(): try: ai_opts = self.parse_ai_bootargs(guest.get_autocf()) except OSDistroException, osd_exception: raise Exception, "Unable to parse OpenSolaris AI options from %s: %s" \ % (guest.get_autocf(), str(osd_exception)) args += " -B network-interface=xnf0,xpv-hcp=dhcp,livemode=text" # If we're installing from a non http location # (like an AI-capable CD) we likely have the .zlib files locally # available and won't need to download from the install_media server. # Of course, the user can always set it in --autocf if they prefer if guest.get_location().startswith('http'): args += ",install_media=%s" % guest.get_location() for key in ai_opts: args += ",%s=%s" % (key, ai_opts[key]) # The user really should specify an install_service option unless # the installation server has a default set if not ai_opts.has_key('install_service'): print "WARNING: No install_service set via --autocf arguments,\ using default installation service, if configured." return args def acquireKernel(self, guest, fetcher, progresscb): try: kernel = fetcher.acquireFile(self.kernelpath, progresscb) except: raise RuntimeError(_("OpenSolaris PV kernel not found at %s") % self.kernelpath) args = "/" + self.kernelpath + self.install_args(guest) try: initrd = fetcher.acquireFile(self.initrdpaths[0], progresscb) return (kernel, initrd, args) except Exception, e: try: initrd = fetcher.acquireFile(self.initrdpaths[1], progresscb) return (kernel, initrd, args) except: os.unlink(kernel) raise Exception("No OpenSolaris boot archive found: %s\n" % e) def parse_ai_bootargs(self, autocf): """For OpenSolaris AI installs, autocf boot arguments are comma-separated name-value pairs, eg. --autocf=install_service=foobar,install_media=http://foo/bar """ ai_opts = {} if autocf is not None: for nvpair in autocf.split(','): items = nvpair.split('=') if len(items) != 2: raise OSDistroException("Missing key value pair from autocf arg %s" % items) name, value = items ai_opts[name] = value return ai_opts # NetWare 6 PV class NetWareDistro(Distro): name = "NetWare" os_type = "other" os_variant = "netware6" loaderpath = "STARTUP/XNLOADER.SYS" def isValidStore(self, fetcher, progresscb): if fetcher.hasFile(self.loaderpath): logging.debug("Detected NetWare") return True return False def acquireKernel(self, guest, fetcher, progresscb): loader = fetcher.acquireFile(self.loaderpath, progresscb) return (loader, "", "") class OSDistroException(Exception): pass 0707010002bbba000081a40000000000000002000000014ae194ae000010e8000000b600010006ffffffffffffffff0000004300000000reloc/usr/lib/python2.4/vendor-packages/virtinst/FullVirtGuest.pycm rJc@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    0707010002bbd8000081a40000000000000002000000014ae194ae000009de000000b600010006ffffffffffffffff0000004300000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualDevice.pycm ^Jc@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    0707010002bbc2000081a40000000000000002000000014ae194ae00002cea000000b600010006ffffffffffffffff0000004100000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImageParser.pycm ^Jc@sdkZdkZdkZdklZdkZdkZde fdYZ dfdYZ dfdYZ dei fd YZd fd YZd fd YZdfdYZdZddZdZdZdS(N(s _virtinsttParserExceptioncBstZdZRS(NcCsti||dS(N(t Exceptiont__init__tselftmsg(RR((t`/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/ImageParser.pyRs(t__name__t __module__R(((RRstImagecBs2tZdZeeedZdZdZRS(s+The toplevel object representing a VM imagecCsh|_d|_|djo d|_ntii||_|djoP|dj o6tii ||_|idjo d|_qqd|_n ||_d|_ d|_ d|_ d|_ d|_|dj o|i|ndS(Ntt.(RtstoragetNonetdomaintfilenametostpathtabspathtbasetdirnametnametlabeltdescrtversiontreleasetnodetparseXML(RRRR((RR#s&              cCs"tiitii|i|S(sWTurn P into an absolute path. Relative paths are taken relative to self.BASEN(RRRtjoinRRtp(RR((RR;scCst|d|_t|d|_t|d|_t|d|_t|d|_x|idD]}t |}|i djo4dt|i|_dt|id|_ n|ii|iotd |i n||i|iR?((Rt_extractFeature|s   (RRR RRC(((RR9xs R5cBs#tZdZedZdZRS(sThe overall description of how the image can be booted, including required capabilities of the host and mapping of disks into the VMcCsvd|_d|_d|_d|_d|_d|_g|_d|_ t |_ |dj o|i |ndS(N(R RttypetloadertbootdevtkerneltinitrdtcmdlineR,tarchR9tfeaturesRR(RR((RRs          cCst|d|_t|d|_t|d|_t|d|_t|d|_t|d|_t i t|d|_ |i d}t|d jo td |i|i fn+t|d jot|d |_nx-|i d D]}|iit|qWt|idj d t|idjp |idjd|it|i dj dt|idjp |idjd|itdddgi|id jd|idS(Ns@types os/loadersos/loader/@devs os/kernels os/initrds os/cmdlines guest/archsguest/featuresisDExpected at most one element in %s boot descriptor for %sitdrivesThe boot type must be providedthvmtxens+Boot type must be 'xen' or 'hvm', but is %ssMissing guest archtpygrubsInvalid loader %sthdtcdromsInvalid bootdev %s(RRRRDRERFRGRHRIt_utilt sanitize_archRJRtflR$RR9RKR R,tappendtDrivetvalidateR tcount(RRR RT((RRs0 !(RRR.R RR(((RR5s  RVcBs#tZdZedZdZRS(sPThe mapping of a disk from the storage section to a virtual drive in a guestcCs7d|_d|_d|_|o|i|ndS(N(R RR-ttargetR"RR(RR((RRs    cCs(t|d|_t|d|_dS(Ns@disks@target(RRRR-RY(RR((RRs(RRR.R RR(((RRVs  R!cBsYtZdZdZdZdZdZdZdZdZ dd Z d Z dd Z RS( Ntrawtisotqcowtqcow2tvmdktsystemtusertscratchcCsXd|_d|_d|_d|_d|_h|_|dj o|i |ndS(N( R RR%R#tformattsizetusetcsumRR(RR((RRs       cCst|d|_t|d|i|_t|dti|_t|d|_t|dti |_ xB|i dD]1}t|d}t|d}||i| # # 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))) 0707010002bbeb000081a40000000000000002000000014ae15ea7000044ee000000b600010006ffffffffffffffff0000003900000000reloc/usr/lib/python2.4/vendor-packages/virtinst/util.py# # Utility functions used for guest installation # # 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 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. # # WARNING: the contents of this file, somewhat unfortunately, are legacy # API. No incompatible changes are allowed to this file, and no new # code should be added here (utility functions live in _util.py). # Clients of virtinst shouldn't use these functions: if you think you # need to, tell us why. # import platform import random import os.path import re import libxml2 import logging import subprocess from sys import stderr import libvirt from virtinst import _virtinst as _ import CapabilitiesParser from User import User KEYBOARD_DIR = "/etc/sysconfig/keyboard" XORG_CONF = "/etc/X11/xorg.conf" def default_route(nic = None): if platform.system() == 'SunOS': cmd = [ '/usr/bin/netstat', '-rn' ] if nic: cmd += [ '-I', nic ] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in proc.stdout.readlines(): vals = line.split() if len(vals) > 1 and vals[0] == 'default': return vals[1] return None route_file = "/proc/net/route" d = file(route_file) defn = 0 for line in d.xreadlines(): info = line.split() if (len(info) != 11): # 11 = typical num of fields in the file print >> stderr, _("Invalid line length while parsing %s.") %(route_file) print >> stderr, _("Defaulting bridge to xenbr%d") % (defn) break try: route = int(info[1],16) if route == 0: return info[0] except ValueError: continue return None def _default_nic(): """Return the default NIC to use, if one is specified. This is NOT part of the API and may change at will.""" dev = '' if platform.system() != 'SunOS': return dev # XXX: fails without PRIV_XVM_CONTROL proc = subprocess.Popen(['/usr/lib/xen/bin/xenstore-read', 'device-misc/vif/default-nic'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out = proc.stdout.readlines() if len(out) > 0: dev = out[0].rstrip() return dev def default_bridge(): if platform.system() == 'SunOS': return _default_nic() rt = default_route() if rt is None: defn = None else: defn = int(rt[-1]) if defn is None: return "xenbr0" else: return "xenbr%d"%(defn) def default_network(conn): if platform.system() == 'SunOS': return ["bridge", _default_nic()] dev = default_route() if dev is not None and not is_uri_remote(conn.getURI()): # New style peth0 == phys dev, eth0 == bridge, eth0 == default route if os.path.exists("/sys/class/net/%s/bridge" % dev): return ["bridge", dev] # Old style, peth0 == phys dev, eth0 == netloop, xenbr0 == bridge, # vif0.0 == netloop enslaved, eth0 == default route defn = int(dev[-1]) if os.path.exists("/sys/class/net/peth%d/brport" % defn) and \ os.path.exists("/sys/class/net/xenbr%d/bridge" % defn): return ["bridge", "xenbr%d" % defn] return ["network", "default"] def default_connection(): if os.path.exists('/var/lib/xend'): if os.path.exists('/dev/xen/evtchn'): return 'xen' if os.path.exists("/proc/xen"): return 'xen' if os.path.exists("/usr/bin/qemu") or \ os.path.exists("/usr/bin/qemu-kvm") or \ os.path.exists("/usr/bin/kvm") or \ os.path.exists("/usr/bin/xenner"): if User.current().has_priv(User.PRIV_QEMU_SYSTEM): return "qemu:///system" else: return "qemu:///session" return None def get_cpu_flags(): if platform.system() == 'SunOS': raise OSError('CPU flags not available') f = open("/proc/cpuinfo") lines = f.readlines() f.close() for line in lines: if not line.startswith("flags"): continue # get the actual flags flags = line[:-1].split(":", 1)[1] # and split them flst = flags.split(" ") return flst return [] def is_pae_capable(conn = None): """Determine if a machine is PAE capable or not.""" if not conn: conn = libvirt.open('') return "pae" in conn.getCapabilities() def is_hvm_capable(): """Determine if a machine is HVM capable or not.""" if platform.system() == 'SunOS': raise OSError('HVM capability not determinible') caps = "" if os.path.exists("/sys/hypervisor/properties/capabilities"): caps = open("/sys/hypervisor/properties/capabilities").read() if caps.find("hvm") != -1: return True return False def is_kqemu_capable(): return os.path.exists("/dev/kqemu") def is_kvm_capable(): return os.path.exists("/dev/kvm") def is_blktap_capable(): if platform.system() == 'SunOS': return False #return os.path.exists("/dev/xen/blktapctrl") f = open("/proc/modules") lines = f.readlines() f.close() for line in lines: if line.startswith("blktap ") or line.startswith("xenblktap "): return True return False def get_default_arch(): arch = os.uname()[4] if arch == "x86_64": return "x86_64" return "i686" # this function is directly from xend/server/netif.py and is thus # available under the LGPL, # Copyright 2004, 2005 Mike Wray # Copyright 2005 XenSource Ltd def randomMAC(type = "xen"): """Generate 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 """ ouis = { 'xen': [ 0x00, 0x16, 0x36 ], 'qemu': [ 0x54, 0x52, 0x00 ] } try: oui = ouis[type] except KeyError: oui = ouis['xen'] mac = oui + [ random.randint(0x00, 0x7f), random.randint(0x00, 0xff), random.randint(0x00, 0xff) ] return ':'.join(map(lambda x: "%02x" % x, mac)) # the following three functions are from xend/uuid.py and are thus # available under the LGPL, # Copyright 2005 Mike Wray # Copyright 2005 XenSource Ltd def randomUUID(): """Generate a random UUID.""" return [ random.randint(0, 255) for dummy in range(0, 16) ] def uuidToString(u): return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2, "%02x" * 6]) % tuple(u) def uuidFromString(s): s = s.replace('-', '') return [ int(s[i : i + 2], 16) for i in range(0, 32, 2) ] # the following function quotes from python2.5/uuid.py def get_host_network_devices(): device = [] for dirname in ['', '/sbin/', '/usr/sbin']: executable = os.path.join(dirname, "ifconfig") if not os.path.exists(executable): continue try: cmd = 'LC_ALL=C %s -a 2>/dev/null' % (executable) pipe = os.popen(cmd) except IOError: continue for line in pipe: if line.find("encap:Ethernet") > 0: words = line.lower().split() for i in range(len(words)): if words[i] == "hwaddr": device.append(words) return device def get_max_vcpus(conn, type=None): """@conn libvirt connection to poll for max possible vcpus @type optional guest type (kvm, etc.)""" if type is None: type = conn.getType() try: m = conn.getMaxVcpus(type.lower()) except libvirt.libvirtError: m = 32 return m def get_phy_cpus(conn): """Get number of physical CPUs.""" hostinfo = conn.getInfo() pcpus = hostinfo[4] * hostinfo[5] * hostinfo[6] * hostinfo[7] return pcpus def system(cmd): st = os.system(cmd) if os.WIFEXITED(st) and os.WEXITSTATUS(st) != 0: raise OSError("Failed to run %s, exited with %d" % (cmd, os.WEXITSTATUS(st))) def xml_escape(str): """Replaces chars ' " < > & with xml safe counterparts""" str = str.replace("&", "&") str = str.replace("'", "'") str = str.replace("\"", """) str = str.replace("<", "<") str = str.replace(">", ">") return str def compareMAC(p, q): """Compare two MAC addresses""" pa = p.split(":") qa = q.split(":") if len(pa) != len(qa): if p > q: return 1 else: return -1 for i in xrange(len(pa)): n = int(pa[i], 0x10) - int(qa[i], 0x10) if n > 0: return 1 elif n < 0: return -1 return 0 def _xorg_keymap(): """Look in /etc/X11/xorg.conf for the host machine's keymap, and attempt to map it to a keymap supported by qemu""" kt = None try: f = open(XORG_CONF, "r") except IOError, e: logging.debug('Could not open "%s": %s ' % (XORG_CONF, str(e))) else: keymap_re = re.compile(r'\s*Option\s+"XkbLayout"\s+"(?P[a-z-]+)"') for line in f: m = keymap_re.match(line) if m: kt = m.group('kt') break else: logging.debug("Didn't find keymap in '%s'!" % XORG_CONF) f.close() return kt def default_keymap(): """Look in /etc/sysconfig for the host machine's keymap, and attempt to map it to a keymap supported by qemu""" # Set keymap to same as hosts import keytable default = "en-us" keymap = None kt = None try: f = open(KEYBOARD_DIR, "r") except IOError, e: logging.debug('Could not open "/etc/sysconfig/keyboard" ' + str(e)) kt = _xorg_keymap() else: while 1: s = f.readline() if s == "": break if re.search("KEYTABLE", s) != None or \ (re.search("KEYBOARD", s) != None and re.search("KEYBOARDTYPE", s) == None): if s.count('"'): delim = '"' elif s.count('='): delim = '=' else: continue kt = s.split(delim)[1].strip() f.close() if kt == None: logging.debug("Did not parse any usable keymapping.") return default kt = kt.lower() # Try a simple lookup in the keytable if keytable.keytable.has_key(kt.lower()): keymap = keytable.keytable[kt] else: # Try a more intelligent lookup: strip out all '-' and '_', sort # the keytable keys putting the longest first, then compare # by string prefix def len_cmp(a, b): return len(b) - len(a) clean_kt = kt.replace("-", "").replace("_", "") sorted_keys = sorted(keytable.keytable.keys(), len_cmp) for key in sorted_keys: origkey = key key = key.replace("-", "").replace("_","") if clean_kt.startswith(key): keymap = keytable.keytable[origkey] break if not keymap: logging.debug("Didn't match keymap '%s' in keytable!" % kt) return default return keymap def pygrub_path(conn=None): """ Return the pygrub path for the current host, or connection if available. """ # FIXME: This should be removed/deprecated when capabilities are # fixed to provide bootloader info if conn: cap = CapabilitiesParser.parse(conn.getCapabilities()) if (cap.host.arch == "i86pc"): return "/usr/lib/xen/bin/pygrub" else: return "/usr/bin/pygrub" if platform.system() == "SunOS": return "/usr/lib/xen/bin/pygrub" return "/usr/bin/pygrub" def uri_split(uri): """ 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) """ def splitnetloc(url, start=0): for c in '/?#': # the order is important! delim = url.find(c, start) if delim >= 0: break else: delim = len(url) return url[start:delim], url[delim:] username = netloc = query = fragment = '' i = uri.find(":") if i > 0: scheme, uri = uri[:i].lower(), uri[i+1:] if uri[:2] == '//': netloc, uri = splitnetloc(uri, 2) offset = netloc.find("@") if offset > 0: username = netloc[0:offset] netloc = netloc[offset+1:] if '#' in uri: uri, fragment = uri.split('#', 1) if '?' in uri: uri, query = uri.split('?', 1) else: scheme = uri.lower() return scheme, username, netloc, uri, query, fragment def is_uri_remote(uri): try: split_uri = uri_split(uri) netloc = split_uri[2] if netloc == "": return False return True except Exception, e: logging.exception("Error parsing URI in is_remote: %s" % e) return True def get_uri_hostname(uri): try: split_uri = uri_split(uri) netloc = split_uri[2] if netloc != "": return netloc except Exception, e: logging.warning("Cannot parse URI %s: %s" % (uri, str(e))) return "localhost" def get_uri_transport(uri): try: split_uri = uri_split(uri) scheme = split_uri[0] username = split_uri[1] if scheme: offset = scheme.index("+") if offset > 0: return [scheme[offset+1:], username] except: pass return [None, None] def get_uri_driver(uri): try: split_uri = uri_split(uri) scheme = split_uri[0] if scheme: offset = scheme.find("+") if offset > 0: return scheme[:offset] return scheme except Exception: pass return "xen" def is_storage_capable(conn): """check if virConnectPtr passed has storage API support""" if not conn: return False if not isinstance(conn, libvirt.virConnect): raise ValueError(_("'conn' must be a virConnect instance.")) try: if not dir(conn).count("listStoragePools"): return False conn.listStoragePools() except libvirt.libvirtError, 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 get_xml_path(xml, path=None, func=None): """ Return the content from the passed xml xpath, or return the result of a passed function (receives xpathContext as its only arg) """ doc = None ctx = None result = None try: doc = libxml2.parseDoc(xml) ctx = doc.xpathNewContext() if path: ret = ctx.xpathEval(path) if ret != None: if type(ret) == list: if len(ret) == 1: result = ret[0].content else: result = ret elif func: result = func(ctx) else: raise ValueError(_("'path' or 'func' is required.")) finally: if doc: doc.freeDoc() if ctx: ctx.xpathFreeContext() return result def lookup_pool_by_path(conn, path): """ 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 """ if not is_storage_capable(conn): return None def check_pool(poolname, path): pool = conn.storagePoolLookupByName(poolname) xml_path = get_xml_path(pool.XMLDesc(0), "/pool/target/path") if os.path.abspath(xml_path) == path: return pool running_list = conn.listStoragePools() inactive_list = conn.listDefinedStoragePools() for plist in [running_list, inactive_list]: for name in plist: p = check_pool(name, path) if p: return p return None def _test(): import doctest doctest.testmod() if __name__ == "__main__": _test() 0707010002bbc1000081a40000000000000002000000014ae15ea700002db1000000b600010006ffffffffffffffff0000004000000000reloc/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) 0707010002bbda000081a40000000000000002000000014ae194ae00006f03000000b600010006ffffffffffffffff0000004100000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualDisk.pycm rJc@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 'cCsd}tii|}||jp| o|d}n |d}y8tiddd|dt ||g}|djSWnt j o t SnXdS( Ntraws:fixeds:sparses/usr/sbin/vdiskadmRs-ts-si(t force_fixedtosRt expandusertkindtsparset_typeRRRRR R R (RRRRRRR ((R t _vdisk_create)s *t 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-RRR9RDRFR:R<RARR)RJRLRSRNRPRRR?((R R,zs@)                cCsd|i|ifS(sM prints a simple string representation for the disk instance s%s:%sN(R-RDR(R-((R t__repr__scCs|iS(N(R-R/(R-((R t _get_pathscCsJ|dj o&|i|dtii|}n|id||dS(NRR/( tvalR.R-t _check_strRRtabspatht_VirtualDisk__validate_wrapperR*(R-RXR*((R RGs cCs|iS(N(R-R0(R-((R t _get_sizescCsd|dj o@t|tttgjp |djottdqMn|i d||dS(Nis''size' must be a number greater than 0.R0( RXR.RDtinttfloattlongt ValueErrort_R-R[R*(R-RXR*((R RHs )cCs|iS(N(R-R(R-((R tget_typescCs_|dj o;|i|d||ijottd|qHn|id||dS(NRDsUnknown storage type '%s'R( RXR.R-RYttypesR`RaR[R*(R-RXR*((R RCs  cCs|iS(N(R-R1(R-((R t get_devicescCsN|i|d||ijottd|n|id||dS(NRFsUnknown device type '%s'R1(R-RYRXtdevicesR`RaR[R*(R-RXR*((R REscCs|iS(N(R-R;(R-((R tget_driver_namescCs ||_dS(N(RXR-R;(R-RX((R tset_driver_namescCs|iS(N(R-R=(R-((R tget_driver_typescCs ||_dS(N(RXR-R=(R-RX((R tset_driver_typescCs|iS(N(R-R2(R-((R t get_sparsescCs'|i|d|id||dS(NRR2(R-t _check_boolRXR[R*(R-RXR*((R RBscCs|iS(N(R-R3(R-((R t get_read_only scCs'|i|d|id||dS(Nt read_onlyR3(R-RkRXR[R*(R-RXR*((R R@scCs|iS(N(R-R4(R-((R t_get_vol_objectscCsK|dj o't|ti ottdn|id||dS(Ns+vol_object must be a virStorageVol instanceR4( RXR.t isinstancetlibvirtt virStorageVolR`RaR-R[R*(R-RXR*((R RIs!cCs|iS(N(R-R5(R-((R t_get_vol_installscCsK|dj o't|ti ottdn|id||dS(Ns.vol_install must be a StorageVolume instance.R5( RXR.RotStoraget StorageVolumeR`RaR-R[R*(R-RXR*((R RKs!cCs|iS(N(R-R6(R-((R t_get_bus$scCs8|dj o|i|dn|id||dS(NRNR6(RXR.R-RYR[R*(R-RXR*((R RM&s cCs|iS(N(R-R7(R-((R t_get_shareable,scCs'|i|d|id||dS(NRPR7(R-RkRXR[R*(R-RXR*((R RO.scCs|iS(N(R-R8(R-((R t_get_driver_cache3scCs_|dj o;|i|d||ijottd|qHn|id||dS(NtcachesUnknown cache mode '%s'R8( RXR.R-RYt cache_typesR`RaR[R*(R-RXR*((R RQ5s  cCsmyt||}Wn |}nXt||||o/y|iWqit|||qiXndS(N(tgetattrR-tvarnametorigtnewvaltsetattrR*RU(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_disktignoreRtloggingtdebugRHR (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-RtinfottRptVIR_STORAGE_VOL_FILEt TYPE_FILEtVIR_STORAGE_VOL_BLOCKt TYPE_BLOCKR`Rat vol_installRoRst FileVolumeRR;t DRIVER_PHYRRtis_vdiskt DRIVER_TAPtDRIVER_TAP_VDISKR=RDRRRCR (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(RDt name_tuplettupletlenRR`RaR-R)Rtis_storage_capabletstoragePoolLookupByNametpoolRItstorageVolLookupByNameR 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)RRtdirnameRRRptVIR_STORAGE_POOL_RUNNINGtstorageVolLookupByPathRRtrefreshRRR`RaRRRtbasenameRsRttget_volume_for_pooltvolclasstcapRtallocRKR t _is_remoteRRI( 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-RRRRRRRRRRRGR RRRRHRR(R-RR((R t __sync_paramss$     ' cCs|t}|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| o|i o|i|ijottdn|i|i dtti!ti i"|i ti#p#tdti i"|i n|i$d jottd |i nti!ti i"|i ti%p&ttd ti i"|i q0n |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 No read access to directory '%s's+size is required for non-existent disk '%s's!No write access to directory '%s'iiN(*R tstorage_capableR-R)RRRR`RaRR.Rt#_VirtualDisk__check_if_path_managedt_VirtualDisk__sync_paramsRFt DEVICE_FLOPPYt DEVICE_CDROMtTruetmanaged_storageRRtexistst create_mediat_VirtualDisk__set_sizetisdirRR;t_VirtualDisk__set_dev_typeR=RDRRCRtaccessRtR_OKRtW_OKtis_size_conflicttretRtwarn(R-RRRR((R t__validate_paramssT % &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-RRRItinstallt progresscbR R;RR=tDRIVER_PHY_ZVOLR_Rt size_bytesR Rt RuntimeErrorRaRDRRR.RRtstartRRtupdateR?RRRRtendtfdtopentO_WRONLYtO_CREATt ftruncatetbuftrangetitwriteR RRtclose(R-RRRRRR((R tsetupmsb    ":      '+ 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-RDRRR>tdisknodeR`RaR.RRRt xml_escapeRFRt driver_nametdnamet driver_cachetdtypexmlt driver_typet dcachexmltbus_xmlRNRmtroRRRP( 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.RRRRDRR RtmsgtstatvfsRtvfstF_FRSIZEtF_BAVAILtavailR_tneedRRaR(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)R RRRRRRRRRRR((RR tis_conflict_disks0        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-RNRFRR.(R-((R t_get_target_typeDs #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.R`RaRFRt skip_targetsR>RRtordtgen_tRt startswith(R-RRRRRRR((R tgenerate_targetWs0            (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_WRITEBACKRyt DEVICE_DISKRRReRRRcR.R RR,RVRWRGtpropertyRR\RHRRbRCRDRdRERFRfRgRRhRiRRjRBRRlR@RmRnRIRRrRKRRuRMRNRvRORPRwRQRR[RRRTRRRRURRRR RR(((R R7s ! 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   0707010002bbdf000081a40000000000000002000000014ae1817200001ea8000000b600010006ffffffffffffffff0000004c00000000reloc/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 0707010002bbde000081a40000000000000002000000014ae194ae00001890000000b600010006ffffffffffffffff0000004700000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualHostDevice.pycm ^Jc@sqdkZdkZdkZdklZdeifdYZdefdYZdefdYZdS(N(s _virtinsttVirtualHostDevicecBsJtZdddZeeZdZdZddZdZRS(NcCs| o| ottdn|o |}nti||}t|ti ot |d|Snvt|ti ot |d|SnOt|ti o;|i}yti|d|SWqtidqXnttd|idS(s> 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 s'name' or 'nodedev' required.tnodedevtnames"Fetching net parent device failed.s3Node device type '%s' cannot be attached to guest.N(RRt ValueErrort_tnodeinsttNodeDeviceParsertlookupNodeNametconnt isinstancet PCIDevicetVirtualHostDevicePCIt USBDevicetVirtualHostDeviceUSBt NetDevicetparentt parentnameRtdevice_from_nodetloggingt exceptiont device_type(RRRRR((tf/export/xvm-gate/xvm-3.4///proto/install/usr/lib/python2.4/site-packages/virtinst/VirtualHostDevice.pyRs$    cCs;tii||d|_d|_t|_||_ dS(s* @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} N( t VirtualDevicet__init__tselfRtNonetmodettypetTruetmanagedRt_nodedev(RRR((RR?s    cCstddS(NsMust be implemented in subclass(tNotImplementedError(R((Rt_get_source_xmlPscCs tdS(s Perform DeviceDetach and DeviceReset calls if necessary @param conn: libvirt virConnect instance to use (defaults to devices connection) N(R(RR((RtsetupSscCs\d|i|i|iodpdf}|d7}||i7}|d7}|d7}|S(Ns/ tyestnos s s (RRRRtxmlR (RR$((Rtget_xml_config\s *   ( t__name__t __module__RRt staticmethodRR R!R%(((RRs "    R cBs2tZddZdZdZddZRS(NcCs]ti|||d|_d|_d|_d|_ d|_ d|_ |i |i dS(Nt subsystemtusb(RRRRRRRRtvendortproducttbustdevicet_set_from_nodedevR(RRR((RRhs      cCsl|pdSnt|tipttdn|i|_|i |_ |i |_ |i |_ dS(Ns''nodedev' must be a USBDevice instance.( RR RR RRt vendor_idRR+t product_idR,R-R.(RR((RR/ws   cCsd}|io0|io&|d|i7}|d|i7}nE|io(|io|d|i|if7}nttd|S(Nts s s(
s<'vendor' and 'product', or 'bus' and 'device' are required.(R$RR+R,R-R.t RuntimeErrorR(RR$((RR scCs|p |i}ndS(N(RR(RR((RR!s (R&R'RRR/R R!(((RR fs  R cBs2tZddZdZdZddZRS(NcCs]ti|||d|_d|_d|_d|_ d|_ d|_ |i |i dS(NR)tpcit0x0(RRRRRRRtdomainRR-tslottfunctionR/R(RRR((RRs      cCsl|pdSnt|tipttdn|i|_|i|_|i |_ |i |_ dS(Ns''nodedev' must be a PCIDevice instance.( RR RR RRR6RR-R7R8(RR((RR/s   cCsd|io|io|io|ipttdnd}||i|i|i|ifS(Ns:'domain', 'bus', 'slot', and 'function' must be specified.s@
(RR6R-R7R8R3RR$(RR$((RR s(cCs|p |i}nti|pdSny|ii|iiWn1tj o%}t t dt |nXdS(s Perform DeviceDetach and DeviceReset calls if necessary @param conn: libvirt virConnect instance to use (defaults to devices connection) NsCould not detach PCI device: %s( RRRtis_pci_detach_capableRt deviceDetacht deviceResett ExceptionteR3Rtstr(RRR=((RR!s  (R&R'RRR/R R!(((RR s  ( RRRtvirtinstt _virtinstRRR R (RR RRR RR((Rt?s    M20707010002bbe7000081a40000000000000002000000014ae15ea700000338000000b600010006ffffffffffffffff0000003d00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/keytable.py# Host keytable entry : keymap name in qemu/xen # Only use lower case entries: all lookups are .lower()'d keytable = { "ar":"ar", "da":"da", "dk":"da", "de":"de", "de-ch":"de-ch", "en-gb":"en-gb", "gb":"en-gb", "uk":"en-gb", "en-us":"en-us", "us":"en-us", "es":"es", "et":"et", "fi":"fi", "se_fi":"fi", "fo":"fo", "fr":"fr", "fr-be":"fr-be", "be":"fr-be", "fr-ca":"fr-ca", "fr-ch":"fr-ch", "fr_ch":"fr-ch", "hr":"hr", "hu":"hu", "is":"is", "it":"it", "ja":"ja", "jp106":"ja", "jp": "ja", "lt":"lt", "lv":"lv", "mk":"mk", "nl": "nl", "nl-be":"nl-be", "no":"no", "pl":"pl", "pt":"pt", "pt-br":"pt-br", "br":"pt-br", "br-abnt2":"pt-br", "ru":"ru", "sl":"sl", "sv":"sv", "th":"th", "tr":"tr", } 0707010002bbd6000081a40000000000000002000000014ae194ae0000054f000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/VirtualAudio.pycm rJc@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  0707010002bbe9000081a40000000000000002000000014ae18172000022c1000000b600010006ffffffffffffffff0000003b00000000reloc/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 0707010002bbbc000081a40000000000000002000000014ae194ae0000628a000000b600010006ffffffffffffffff0000003b00000000reloc/usr/lib/python2.4/vendor-packages/virtinst/Guest.pycm rJc@sdkZdkZdkZdkZdkiZdkZdkZdkZdk Z dk Z dk l Z dkZdkZdefdYZdZeZdS(N(s _virtinsttGuestcBs.tZeiZeiZdZeeZdZ ee Z dZ ee Z dZ ee Z dddddZ dZdZdZeeeZd Zd ZeeeZd Zd ZeeeZd ZdZeeeZdZdZeeeZdZdZ eee Z!dZ"dZ#ee"e#Z$dZ%dZ&ee%e&Z'dZ(dZ)ee(e)Z*dZ+dZ,ee+e,Z-dZ.dZ/ee.e/Z0dZ1ee1Z2dZ3dZ4ee3e4Z5d Z6d!Z7ee6e7Z8d"Z9d#Z:ee9e:Z;d$Z<d%Z=ee<e=Z>d&Z?d'Z@ee?e@ZAd(ZBeeBZCd)ZDd*ZEeeDeEZFd+ZGd,ZHeeGeHZId-ZJd.ZKeeJeKZLeMd/ZNd0ZOd1ZPd2ZQd3ZRd4ZSd5ZTd6ZUeMd7ZVd8ZWd9ZXeMeYd:ZZddeYeMd;Z[d<Z\eMd=Z]d>Z^d?Z_eYeMd@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(      cCsl|id|_|djoti}n|i|z|i||||SWd|i i XdS(s)Do the startup of the guest installation.N(Rtvalidate_parmsRRtmetertprogresst BaseMetert_prepare_installt _do_installt consolecbt removeOldtwaitRtcleanup(RRRRR((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|i i d}|i i ||_ |i i|i i ||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)RtstartRR$tXMLDesctfinalxmlR't defineXMLtcreateR-R.tendtconnect_consoleRRttimetsleepRFR(RRRRRR((Rtcontinue_installHs  cCsn|i|_|i|_|i|iid|d||ii dj o|ii |ii ndS(NtguestR( RRR"RR#t _set_defaultsRtprepareRt install_diskRtappend(RR((RRgs    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_devicesqs   c Csd}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| GHdSnt id| |ii#| | 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)Rt createLinuxR$Rt_wait_for_domaintdRtgetURIRRtboot_xmlRRR<twaitpidtOSErrorterr_notmsgt__name__RR( RRRRRRRRRRRRR((RRzs` +       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_console s  (hRt __module__RtDEFAULTSRtOS_TYPESRRt staticmethodRR R RR3R4R5R@tpropertytautocfRARBR RCRGRRHRIRRJRKRRLRNRRORSRRTRaRRbRct graphics_devRdRhRmRiRpRRst os_distroRuRvRtRxRtgraphicsRRRRRRRRRRRRRRRRRRRRR?RRRRRRRRRRRRRRRRRRRRRRRRrRR (((RR%s          0                             /                        K  B      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             0707010002bbbe000081a40000000000000002000000014ae194ae00001a0f000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImageFetcher.pycm ^Jc@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  *0707010002bbc0000081a40000000000000002000000014ae194ae0000152f000000b600010006ffffffffffffffff0000004200000000reloc/usr/lib/python2.4/vendor-packages/virtinst/ImageManager.pycm ^Jc@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((