From bkearney at redhat.com Mon Dec 1 13:32:41 2008 From: bkearney at redhat.com (Bryan Kearney) Date: Mon, 01 Dec 2008 08:32:41 -0500 Subject: [et-mgmt-tools] Making a disk image created with virt-install qcow2 format from the start In-Reply-To: <4efe67b6c9226f5529d58556b41ebf60@localhost> References: <4efe67b6c9226f5529d58556b41ebf60@localhost> Message-ID: <4933E779.1080202@redhat.com> Stephan wrote: > Hi, > > I've been creating images with virt-install (thanks by the way!) > > I was just wondering, is there a way to specify the disk image file type > when you create the machine? I can convert it using tools from qemu, but > it's an extra step and I'd prefer to have the images as qcow2 from the > start if possible. > > I'm doing this: > > sudo mkdir /vservers/edi1-whatever1/ && sudo virt-install --hvm > --accelerate --os-type=linux --os-variant=debianEtch --arch=x86_64 > --bridge=br0 --ram=256 --vcpus=4 --check-cpu --vnc --name=edi1-whatever1 > --file=/vservers/edi1-whatever1/disk0.qcow2 --file-size=8 > --cdrom=/dev/cdrom --debug > > but the file isn't the right format: > > file disk0.qcow2 > disk0.qcow2: x86 boot sector; partition 1: ID=0x83, active, starthead 1, > startsector 63, 15952482 sectors; partition 2: ID=0x5, starthead 0, > startsector 15952545, 819315 sectors > > instead of something like this: > > file disk0.qcow2 > disk0.qcow2: Qemu Image, Format: Qcow , Version: 2 > > Is there a way to specify the image type using virt-install? I've read the > man file and looked on the Internet, but can't find the answer. Sorry if > this is an easy question. Do you have a kickstart file to describe the system? if so, you can build it with the appliance-tools package and then install is using virt-image. You can control the file type with that chain. appliance-creator --config FOO.ks -f qcow2 --vcpu 4 --vmem 256 -- bk From crobinso at redhat.com Mon Dec 1 14:40:34 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 09:40:34 -0500 Subject: =?ISO-8859-1?Q?R=E9f=2E_=3A_Re=3A_=5Bet-mgmt-tools=5D_?= =?ISO-8859-1?Q?virt-manager_on_windows_workstation_=3F?= In-Reply-To: References: , <492D76D2.4000609@redhat.com> Message-ID: <4933F762.4050203@redhat.com> FCOMBERNOUS at ares.fr wrote: > -----Cole Robinson a ?crit : ----- >> FCOMBERNOUS at ares.fr wrote: >>> Lo, >>> >>> Is it possible to run virt-manager on windows workstation ? >>> >>> I hope my google search is wrong. In a short way, it says "No". >>> >>> In this case, virt-manager would be a "simple" acces point to the >>> demon libvirt running on a linux host. >> No one has done it yet, but it should be possible. virt-manager would >> need patches though. > > So, python and something like cygwin, installed on the workstation is not > enough ? > That could be sufficient, but I'm really not sure what would be required. If you give it a shot, I'd be interested in what steps it takes or bugs you hit. Thanks, Cole From crobinso at redhat.com Mon Dec 1 14:43:17 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 09:43:17 -0500 Subject: [et-mgmt-tools] Connecting to a remote libvirtd host using virt-manger In-Reply-To: <41c0f86d0811301002p7d561f6er9bf365a07c89e718@mail.gmail.com> References: <41c0f86d0811301002p7d561f6er9bf365a07c89e718@mail.gmail.com> Message-ID: <4933F805.1070508@redhat.com> Jon Smith wrote: > virt-manager and libvirtd both functioning locally. I tried to use > virt-manager to access the same libvirtd host remotely but I'm having > some trouble. > > I'm using qemu+ssh to connect to the remote host, but when I do, > virt-manager turns gray and becomes unresponsive, eventually the part > of the window showing the hosts goes blank. If I stop libvirtd on the > remote host, virt-manager refreshes itself and shows the libvirtd host > as connected, and even lists all the domains available. I'm also able > to connect using virsh and that works fine. > > I can repeat this process over and over again, even after rebooting > the hosts involved. I've also run libvirtd with the --verbose flag > and can send the output (~80K) if that would help. > What distro are you using? What virt-manager version? Distro package or compiled from source? How are you invoking virt-manager? Can you try running 'virt-manager --no-fork' from the command line, trying to connect to the remote host, and seeing if a password prompt pops up in the terminal? Thanks, Cole From crobinso at redhat.com Mon Dec 1 15:07:45 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 10:07:45 -0500 Subject: [et-mgmt-tools] [PATCH] Fix lookup pool by path In-Reply-To: <200811281447.06174.anschneider@suse.de> References: <200811251608.25707.anschneider@suse.de> <200811281447.06174.anschneider@suse.de> Message-ID: <4933FDC1.4030909@redhat.com> Andreas Schneider wrote: > On Tuesday 25 November 2008 16:08:25 Andreas Schneider wrote: >> Hi, >> >> attached is a patch for virtinst to fix the lookup_pool_by_path() function. >> It removes the trailing slash to have a normalized path. >> > > I've updated the patch. It works now :) > > Hmm, so your pool xml lists the target directory with a trailing slash? I'm not seeing that. What version of libvirt are you using, and can you provide the pools xml? Thanks, Cole From crobinso at redhat.com Mon Dec 1 15:12:52 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 10:12:52 -0500 Subject: [et-mgmt-tools] [PATCH] Use netcat if found In-Reply-To: <200811251611.49998.anschneider@suse.de> References: <200811251611.49998.anschneider@suse.de> Message-ID: <4933FEF4.9000501@redhat.com> Andreas Schneider wrote: > Hi, > > attached is a patch for virt-manager to use the netcat binary instead of nc if > it is found. > > > Cheers, > > > -- andreas > I'd rather keep things operating the same if 'nc' is present, which would mean using 'netcat' only if 'nc' isn't available. Is there a reason we should prefer netcat over nc, or is it just that your distro provides one and not the other? Thanks, Cole From berrange at redhat.com Mon Dec 1 15:26:48 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 1 Dec 2008 15:26:48 +0000 Subject: [et-mgmt-tools] [PATCH] Use netcat if found In-Reply-To: <4933FEF4.9000501@redhat.com> References: <200811251611.49998.anschneider@suse.de> <4933FEF4.9000501@redhat.com> Message-ID: <20081201152628.GG24079@redhat.com> On Mon, Dec 01, 2008 at 10:12:52AM -0500, Cole Robinson wrote: > Andreas Schneider wrote: > > Hi, > > > > attached is a patch for virt-manager to use the netcat binary instead of nc if > > it is found. > > > > > > Cheers, > > > > > > -- andreas > > > > I'd rather keep things operating the same if 'nc' is present, which > would mean using 'netcat' only if 'nc' isn't available. Is there a > reason we should prefer netcat over nc, or is it just that your distro > provides one and not the other? This used to be the case with Debian/Ubuntu, but they now provide the 'nc' binary too. In addition the 'netcat' binary they also ship does not work with libvirt since it doesn't support UNIX sockets. Finally the patch is wrong because its doing + if os.path.exists('/usr/bin/netcat'): + netcat = "netcat" which is in the context of the machine virt-manager is running on, which is totally bogus when connecting to a remote machine. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From crobinso at redhat.com Mon Dec 1 15:28:15 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 10:28:15 -0500 Subject: [et-mgmt-tools] [PATCH] virtinst: also look at xorg.conf for keymap In-Reply-To: <20081129174346.GA24473@bogon.ms20.nix> References: <20081129174346.GA24473@bogon.ms20.nix> Message-ID: <4934028F.8030703@redhat.com> Guido G?nther wrote: > Hi, > attached patch looks at xorg.conf if no /etc/sysconfig/keyboard for the > default keyboard. This helps with distros that don't have > /etc/sysconfig/ like Debian. > Cheers, > -- Guido > Couple small nits: > HG changeset patch > # User Guido G?nther > # Date 1227979760 -3600 > # Node ID a292eb8430cd2d9544e89dba127323704f3963ce > # Parent 16e923676e84d81cf9bf6dc2cdd30d95bf65bbe1 > parse xorg.conf for keymap > > diff -r 16e923676e84 -r a292eb8430cd virtinst/util.py > --- a/virtinst/util.py Tue Nov 25 10:25:08 2008 -0500 > +++ b/virtinst/util.py Sat Nov 29 18:29:20 2008 +0100 > @@ -33,6 +33,7 @@ > > > KEYBOARD_DIR = "/etc/sysconfig/keyboard" > +XORG_CONF = "/etc/X11/xorg.conf" > > def default_route(): > route_file = "/proc/net/route" > @@ -276,6 +277,28 @@ > 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""" > + > + import keytable This is unused ('python setup.py check' will warn about this :) > + 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 '%s' in keytable!" % kt) This logging isn't really accurate here. Maybe 'Didn't find keymap in xorg.conf' The rest looks fine. Thanks, Cole From crobinso at redhat.com Mon Dec 1 15:33:44 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 10:33:44 -0500 Subject: [et-mgmt-tools] [PATCH] virtinst: pool separator is '/' not ':' In-Reply-To: <20081129174216.GA24390@bogon.ms20.nix> References: <20081129174216.GA24390@bogon.ms20.nix> Message-ID: <493403D8.6070104@redhat.com> Guido G?nther wrote: > Hi, > Doc typo. Possible patch attached. > Cheers, > -- Guido > > Applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=0a953a339693 Thanks, Cole From crobinso at redhat.com Mon Dec 1 15:44:43 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 10:44:43 -0500 Subject: [et-mgmt-tools] [PATCH] virtinst: also look at xorg.conf for keymap In-Reply-To: <4934028F.8030703@redhat.com> References: <20081129174346.GA24473@bogon.ms20.nix> <4934028F.8030703@redhat.com> Message-ID: <4934066B.4030705@redhat.com> Cole Robinson wrote: > Guido G?nther wrote: >> Hi, >> attached patch looks at xorg.conf if no /etc/sysconfig/keyboard for the >> default keyboard. This helps with distros that don't have >> /etc/sysconfig/ like Debian. >> Cheers, >> -- Guido >> > > Couple small nits: > >> HG changeset patch >> # User Guido G?nther >> # Date 1227979760 -3600 >> # Node ID a292eb8430cd2d9544e89dba127323704f3963ce >> # Parent 16e923676e84d81cf9bf6dc2cdd30d95bf65bbe1 >> parse xorg.conf for keymap >> >> diff -r 16e923676e84 -r a292eb8430cd virtinst/util.py >> --- a/virtinst/util.py Tue Nov 25 10:25:08 2008 -0500 >> +++ b/virtinst/util.py Sat Nov 29 18:29:20 2008 +0100 >> @@ -33,6 +33,7 @@ >> >> >> KEYBOARD_DIR = "/etc/sysconfig/keyboard" >> +XORG_CONF = "/etc/X11/xorg.conf" >> >> def default_route(): >> route_file = "/proc/net/route" >> @@ -276,6 +277,28 @@ >> return -1 >> return 0 >> >> +def xorg_keymap(): One other thing: could you rename this to _xorg_keymap so it isn't confused for a public function? Thanks, Cole From crobinso at redhat.com Mon Dec 1 15:53:05 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 10:53:05 -0500 Subject: [et-mgmt-tools] FYI: Changes to virtinst test suite In-Reply-To: <20081127143031.GA12890@bogon.ms20.nix> References: <492B29AD.1030101@redhat.com> <20081127143031.GA12890@bogon.ms20.nix> Message-ID: <49340861.6090709@redhat.com> Guido G?nther wrote: > HI Cole, > On Mon, Nov 24, 2008 at 05:24:45PM -0500, Cole Robinson wrote: >> Hi all, >> >> I've added some changes to the virtinst test suite that will affect >> anyone writing patches. Two commands have been added to the setup.py script: >> >> python setup.py check : runs a pylint wrapper against the >> >> codebase >> python setup.py test_urls: runs a url fetching test suite > Cool thing! Would it make sense to release a new version? Hg acquired > quiet some new features and bugfixes, so I'd probably make sense. Having > virtinst release more often would help distros to get the new stuff out > quicker. > -- Guido > Completely agreed on releasing more often: the huge lapse between the previous two releases was no good. I think pushing new virtinst + virt-manager in a couple weeks would be fine, there are still a couple other things I'd like to pick off until then. Going forward, my goal is to have an actual schedule, and transparency wrt planned features, timelines, etc. Thanks, Cole From bkearney at redhat.com Mon Dec 1 16:27:41 2008 From: bkearney at redhat.com (Bryan Kearney) Date: Mon, 01 Dec 2008 11:27:41 -0500 Subject: [et-mgmt-tools] virt-image on F-10 Message-ID: <4934107D.2050902@redhat.com> Have you seen this on F-10? I get the following traceback: Traceback (most recent call last): File "/home/bkearney/src/adk2/deps/virtinst--devel/virt-image", line 240, in main() File "/home/bkearney/src/adk2/deps/virtinst--devel/virt-image", line 224, in main dom = guest.start_install(None, progresscb, options.replace) File "/home/bkearney/src/adk2/deps/virtinst--devel/virtinst/Guest.py", line 932, in start_install return self._do_install(consolecb, meter, removeOld, wait) File "/home/bkearney/src/adk2/deps/virtinst--devel/virtinst/Guest.py", line 972, in _do_install self.domain = self.conn.createLinux(install_xml, 0) File "/usr/lib/python2.5/site-packages/libvirt.py", line 892, in createLinux if ret is None:raise libvirtError('virDomainCreateLinux() failed', conn=self) libvirtError: internal error QEMU quit during console startup qemu: could not open disk image /home/bkearney/appliances/sugarxo/sugarxo-sda.raw And if I run the raw cmd, I get the following: [root at localhost sugarxo]# /usr/bin/qemu-kvm -S -M pc -m 512 -smp 1 -name sugarxo -monitor pty -no-reboot -boot c -drive file=/home/bkearney/appliances/sugarxo/sugarxo-sda.raw,if=ide,index=0,boot=on -net nic,macaddr=54:52:00:4b:ac:20,vlan=0 -net tap,fd=12,script=,vlan=0,ifname=vnet0 -serial pty -parallel none -usb -vnc 127.0.0.1:0 -k en-us TUNGETIFF ioctl() failed: Bad file descriptor char device redirected to /dev/pts/3 char device redirected to /dev/pts/4 I am trying to dig into the exact issue.. i am guessing it is network. But I was curious if folks had seen this? -- bk From pradhanparas at gmail.com Mon Dec 1 18:43:29 2008 From: pradhanparas at gmail.com (Paras pradhan) Date: Mon, 1 Dec 2008 12:43:29 -0600 Subject: [et-mgmt-tools] running virt-manager Message-ID: <8b711df40812011043q33fce52dkb20bca5462e8b963@mail.gmail.com> Hi all, I have compiled libvirt using: ./configure make make install And after that I have complied virt-manager using: ./configuire make make install The I added /usr/local/lib to ld.so.conf.d , ran ldconfig. Now when i run virt-manager I get the followiing error: --- [root at ha1 ~]# virt-manager Traceback (most recent call last): File "/usr/local/share/virt-manager/virt-manager.py", line 26, in ? import libvirt ImportError: No module named libvirt [root at ha1 ~]# -- What went wrong in here? Thanks Paras. -------------- next part -------------- An HTML attachment was scrubbed... URL: From agx at sigxcpu.org Mon Dec 1 18:53:28 2008 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Mon, 1 Dec 2008 19:53:28 +0100 Subject: [et-mgmt-tools] [PATCH] virtinst: also look at xorg.conf for keymap In-Reply-To: <4934028F.8030703@redhat.com> References: <20081129174346.GA24473@bogon.ms20.nix> <4934028F.8030703@redhat.com> Message-ID: <20081201185328.GA17071@bogon.ms20.nix> On Mon, Dec 01, 2008 at 10:28:15AM -0500, Cole Robinson wrote: > > + import keytable > > This is unused ('python setup.py check' will warn about this :) Fixed. > > > + 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 '%s' in keytable!" % kt) > > This logging isn't really accurate here. Maybe 'Didn't find keymap in > xorg.conf' Yes, that's bogus. Fixed version attached. -- Guido -------------- next part -------------- A non-text attachment was scrubbed... Name: xorg-keymap.diff Type: text/x-diff Size: 2339 bytes Desc: not available URL: From agx at sigxcpu.org Mon Dec 1 18:54:42 2008 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Mon, 1 Dec 2008 19:54:42 +0100 Subject: [et-mgmt-tools] [PATCH] virtinst: remove bashisms from tests/pylint-virtinst.sh Message-ID: <20081201185442.GB17071@bogon.ms20.nix> Hi, the script uses /bin/sh so "function" mustn't be used. Patch attached. Cheers, -- Guido -------------- next part -------------- A non-text attachment was scrubbed... Name: bashisms.diff Type: text/x-diff Size: 875 bytes Desc: not available URL: From crobinso at redhat.com Mon Dec 1 19:01:00 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 14:01:00 -0500 Subject: [et-mgmt-tools] running virt-manager In-Reply-To: <8b711df40812011043q33fce52dkb20bca5462e8b963@mail.gmail.com> References: <8b711df40812011043q33fce52dkb20bca5462e8b963@mail.gmail.com> Message-ID: <4934346C.2090603@redhat.com> Paras pradhan wrote: > Hi all, > > I have compiled libvirt using: > ./configure > make > make install > > > And after that I have complied virt-manager using: > > ./configuire > make > make install > > > The I added /usr/local/lib to ld.so.conf.d , ran ldconfig. > > Now when i run virt-manager > > I get the followiing error: > > --- > [root at ha1 ~]# virt-manager > Traceback (most recent call last): > File "/usr/local/share/virt-manager/virt-manager.py", line 26, in ? > import libvirt > ImportError: No module named libvirt > [root at ha1 ~]# > > -- > > > What went wrong in here? > > Thanks > Paras. > You'll need to find out where libvirt 'make install' placed the python bindings (look for file 'libvirt.py'), and set the environment variable PYTHONPATH to that directory. - Cole From crobinso at redhat.com Mon Dec 1 19:07:03 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 14:07:03 -0500 Subject: [et-mgmt-tools] [PATCH] virtinst: remove bashisms from tests/pylint-virtinst.sh In-Reply-To: <20081201185442.GB17071@bogon.ms20.nix> References: <20081201185442.GB17071@bogon.ms20.nix> Message-ID: <493435D7.4080502@redhat.com> Guido G?nther wrote: > Hi, > the script uses /bin/sh so "function" mustn't be used. Patch attached. > Cheers, > -- Guido > Thanks, I'm not too shell savvy. Applied now: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=318a441c1bed - Cole From bkearney at redhat.com Mon Dec 1 19:03:18 2008 From: bkearney at redhat.com (Bryan Kearney) Date: Mon, 01 Dec 2008 14:03:18 -0500 Subject: [et-mgmt-tools] virt-image on F-10 In-Reply-To: <4934107D.2050902@redhat.com> References: <4934107D.2050902@redhat.com> Message-ID: <493434F6.4030209@redhat.com> Bryan Kearney wrote: > Have you seen this on F-10? I get the following traceback: > > Traceback (most recent call last): > File "/home/bkearney/src/adk2/deps/virtinst--devel/virt-image", line > 240, in > main() > File "/home/bkearney/src/adk2/deps/virtinst--devel/virt-image", line > 224, in main > dom = guest.start_install(None, progresscb, options.replace) > File "/home/bkearney/src/adk2/deps/virtinst--devel/virtinst/Guest.py", > line 932, in start_install > return self._do_install(consolecb, meter, removeOld, wait) > File "/home/bkearney/src/adk2/deps/virtinst--devel/virtinst/Guest.py", > line 972, in _do_install > self.domain = self.conn.createLinux(install_xml, 0) > File "/usr/lib/python2.5/site-packages/libvirt.py", line 892, in > createLinux > if ret is None:raise libvirtError('virDomainCreateLinux() failed', > conn=self) > libvirtError: internal error QEMU quit during console startup > qemu: could not open disk image > /home/bkearney/appliances/sugarxo/sugarxo-sda.raw > > > > And if I run the raw cmd, I get the following: > > [root at localhost sugarxo]# /usr/bin/qemu-kvm -S -M pc -m 512 -smp 1 -name > sugarxo -monitor pty -no-reboot -boot c -drive > file=/home/bkearney/appliances/sugarxo/sugarxo-sda.raw,if=ide,index=0,boot=on > -net nic,macaddr=54:52:00:4b:ac:20,vlan=0 -net > tap,fd=12,script=,vlan=0,ifname=vnet0 -serial pty -parallel none -usb > -vnc 127.0.0.1:0 -k en-us > TUNGETIFF ioctl() failed: Bad file descriptor > char device redirected to /dev/pts/3 > char device redirected to /dev/pts/4 Sorry.. this is an selinux error. Should I submit a "make it error nicely" feature request? -- bk From crobinso at redhat.com Mon Dec 1 19:07:54 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 14:07:54 -0500 Subject: [et-mgmt-tools] [PATCH] virtinst: also look at xorg.conf for keymap In-Reply-To: <20081201185328.GA17071@bogon.ms20.nix> References: <20081129174346.GA24473@bogon.ms20.nix> <4934028F.8030703@redhat.com> <20081201185328.GA17071@bogon.ms20.nix> Message-ID: <4934360A.6000306@redhat.com> Guido G?nther wrote: > On Mon, Dec 01, 2008 at 10:28:15AM -0500, Cole Robinson wrote: >>> + import keytable >> This is unused ('python setup.py check' will warn about this :) > Fixed. >>> + 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 '%s' in keytable!" % kt) >> This logging isn't really accurate here. Maybe 'Didn't find keymap in >> xorg.conf' > Yes, that's bogus. Fixed version attached. > -- Guido > Applied now: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=bcd052e6ef9d Thanks, Cole From crobinso at redhat.com Mon Dec 1 19:10:38 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 14:10:38 -0500 Subject: [et-mgmt-tools] virt-image on F-10 In-Reply-To: <493434F6.4030209@redhat.com> References: <4934107D.2050902@redhat.com> <493434F6.4030209@redhat.com> Message-ID: <493436AE.7090409@redhat.com> Bryan Kearney wrote: >> And if I run the raw cmd, I get the following: >> >> [root at localhost sugarxo]# /usr/bin/qemu-kvm -S -M pc -m 512 -smp 1 -name >> sugarxo -monitor pty -no-reboot -boot c -drive >> file=/home/bkearney/appliances/sugarxo/sugarxo-sda.raw,if=ide,index=0,boot=on >> -net nic,macaddr=54:52:00:4b:ac:20,vlan=0 -net >> tap,fd=12,script=,vlan=0,ifname=vnet0 -serial pty -parallel none -usb >> -vnc 127.0.0.1:0 -k en-us >> TUNGETIFF ioctl() failed: Bad file descriptor >> char device redirected to /dev/pts/3 >> char device redirected to /dev/pts/4 > > Sorry.. this is an selinux error. Should I submit a "make it error > nicely" feature request? > > -- bk > There's already a bug tracking a similar request for virt-manager: https://bugzilla.redhat.com/show_bug.cgi?id=452671 Though any complete solution will need work at the virtinst level too, so in my mind it covers both. Thanks, Cole From pradhanparas at gmail.com Mon Dec 1 20:29:55 2008 From: pradhanparas at gmail.com (Paras pradhan) Date: Mon, 1 Dec 2008 14:29:55 -0600 Subject: [et-mgmt-tools] running virt-manager In-Reply-To: <4934346C.2090603@redhat.com> References: <8b711df40812011043q33fce52dkb20bca5462e8b963@mail.gmail.com> <4934346C.2090603@redhat.com> Message-ID: <8b711df40812011229ga92ae10sd91d72b2f82fe02e@mail.gmail.com> On Mon, Dec 1, 2008 at 1:01 PM, Cole Robinson wrote: > Paras pradhan wrote: > > Hi all, > > > > I have compiled libvirt using: > > ./configure > > make > > make install > > > > > > And after that I have complied virt-manager using: > > > > ./configuire > > make > > make install > > > > > > The I added /usr/local/lib to ld.so.conf.d , ran ldconfig. > > > > Now when i run virt-manager > > > > I get the followiing error: > > > > --- > > [root at ha1 ~]# virt-manager > > Traceback (most recent call last): > > File "/usr/local/share/virt-manager/virt-manager.py", line 26, in ? > > import libvirt > > ImportError: No module named libvirt > > [root at ha1 ~]# > > > > -- > > > > > > What went wrong in here? > > > > Thanks > > Paras. > > > > You'll need to find out where libvirt 'make install' placed the python > bindings (look for file 'libvirt.py'), and set the environment variable > PYTHONPATH to that directory. > > - Cole Thanks for the reply. Now it has stopped complaining about import libvirt.I had to set the PYTHONPATH to /usr/local/lib/python2.4/site-packages But here comes the new error after i run 'virt-manager' ----------- traceback (most recent call last): File "/usr/local/share/virt-manager/virt-manager.py", line 346, in ? main() File "/usr/local/share/virt-manager/virt-manager.py", line 287, in main from virtManager.engine import vmmEngine File "/usr/local/share/virt-manager/virtManager/engine.py", line 31, in ? from virtManager.connection import vmmConnection File "/usr/local/share/virt-manager/virtManager/connection.py", line 36, in ? from virtManager.domain import vmmDomain File "/usr/local/share/virt-manager/virtManager/domain.py", line 669 finally: ^ SyntaxError: invalid syntax -------- Thanks Paras. -------------- next part -------------- An HTML attachment was scrubbed... URL: From crobinso at redhat.com Mon Dec 1 21:17:56 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 16:17:56 -0500 Subject: [et-mgmt-tools] running virt-manager In-Reply-To: <8b711df40812011229ga92ae10sd91d72b2f82fe02e@mail.gmail.com> References: <8b711df40812011043q33fce52dkb20bca5462e8b963@mail.gmail.com> <4934346C.2090603@redhat.com> <8b711df40812011229ga92ae10sd91d72b2f82fe02e@mail.gmail.com> Message-ID: <49345484.50807@redhat.com> Paras pradhan wrote: > > Thanks for the reply. > > Now it has stopped complaining about import libvirt.I had to set the > PYTHONPATH to /usr/local/lib/python2.4/site-packages > But here comes the new error after i run 'virt-manager' > ----------- > traceback (most recent call last): > File "/usr/local/share/virt-manager/virt-manager.py", line 346, in ? > main() > File "/usr/local/share/virt-manager/virt-manager.py", line 287, in main > from virtManager.engine import vmmEngine > File "/usr/local/share/virt-manager/virtManager/engine.py", line 31, in ? > from virtManager.connection import vmmConnection > File "/usr/local/share/virt-manager/virtManager/connection.py", line 36, > in ? > from virtManager.domain import vmmDomain > File "/usr/local/share/virt-manager/virtManager/domain.py", line 669 > finally: > ^ > SyntaxError: invalid syntax > -------- > > Thanks > Paras. > Ah, I take it you are using the virt-manager 0.6.0 release. There were some python2.5 specific pieces that crept into the release, so you will need to apply this patch: http://hg.et.redhat.com/virt/applications/virt-manager--devel?cs=a8cafeaa92a6 Or you can try building from an upstream checkout. - Cole From pradhanparas at gmail.com Mon Dec 1 22:41:53 2008 From: pradhanparas at gmail.com (Paras pradhan) Date: Mon, 1 Dec 2008 16:41:53 -0600 Subject: [et-mgmt-tools] running virt-manager In-Reply-To: <49345484.50807@redhat.com> References: <8b711df40812011043q33fce52dkb20bca5462e8b963@mail.gmail.com> <4934346C.2090603@redhat.com> <8b711df40812011229ga92ae10sd91d72b2f82fe02e@mail.gmail.com> <49345484.50807@redhat.com> Message-ID: <8b711df40812011441j28251c8m8e9508f5ac43cd74@mail.gmail.com> On Mon, Dec 1, 2008 at 3:17 PM, Cole Robinson wrote: > Paras pradhan wrote: > > > > Thanks for the reply. > > > > Now it has stopped complaining about import libvirt.I had to set the > > PYTHONPATH to /usr/local/lib/python2.4/site-packages > > But here comes the new error after i run 'virt-manager' > > ----------- > > traceback (most recent call last): > > File "/usr/local/share/virt-manager/virt-manager.py", line 346, in ? > > main() > > File "/usr/local/share/virt-manager/virt-manager.py", line 287, in main > > from virtManager.engine import vmmEngine > > File "/usr/local/share/virt-manager/virtManager/engine.py", line 31, in > ? > > from virtManager.connection import vmmConnection > > File "/usr/local/share/virt-manager/virtManager/connection.py", line > 36, > > in ? > > from virtManager.domain import vmmDomain > > File "/usr/local/share/virt-manager/virtManager/domain.py", line 669 > > finally: > > ^ > > SyntaxError: invalid syntax > > -------- > > > > Thanks > > Paras. > > > > Ah, I take it you are using the virt-manager 0.6.0 release. There were > some python2.5 specific pieces that crept into the release, so you will > need to apply this patch: > > > http://hg.et.redhat.com/virt/applications/virt-manager--devel?cs=a8cafeaa92a6 > > Or you can try building from an upstream checkout. > > - Cole Cole. thanks.. the patch worked and I can now see the GUI of virt-manager. Now when I click the Domain-0 in virt-manager. I am having an err msg. -- Traceback (most recent call last): File "/usr/share/virt-manager/virtManager/engine.py", line 304, in show_details details = vmmDetails(self.get_config(), con.get_vm(uuid), self) File "/usr/share/virt-manager/virtManager/details.py", line 188, in __init__ self.vncViewer.set_scaling(True) AttributeError: 'gtkvnc.Display' object has no attribute 'set_scaling' --- I have gtk-vnc-pythond installed. NO idea what is going on. Thanks Paras. -------------- next part -------------- An HTML attachment was scrubbed... URL: From cmdrlinux at gmail.com Tue Dec 2 02:41:40 2008 From: cmdrlinux at gmail.com (Jon Smith) Date: Mon, 1 Dec 2008 20:41:40 -0600 Subject: [et-mgmt-tools] Connecting to a remote libvirtd host using virt-manger In-Reply-To: <4933F805.1070508@redhat.com> References: <41c0f86d0811301002p7d561f6er9bf365a07c89e718@mail.gmail.com> <4933F805.1070508@redhat.com> Message-ID: <41c0f86d0812011841w7936f8a8n640203bb810398c2@mail.gmail.com> On Mon, Dec 1, 2008 at 8:43 AM, Cole Robinson wrote: > Jon Smith wrote: >> virt-manager and libvirtd both functioning locally. I tried to use >> virt-manager to access the same libvirtd host remotely but I'm having >> some trouble. >> >> I'm using qemu+ssh to connect to the remote host, but when I do, >> virt-manager turns gray and becomes unresponsive, eventually the part >> of the window showing the hosts goes blank. If I stop libvirtd on the >> remote host, virt-manager refreshes itself and shows the libvirtd host >> as connected, and even lists all the domains available. I'm also able >> to connect using virsh and that works fine. >> >> I can repeat this process over and over again, even after rebooting >> the hosts involved. I've also run libvirtd with the --verbose flag >> and can send the output (~80K) if that would help. >> > > What distro are you using? What virt-manager version? Distro package or > compiled from source? > > How are you invoking virt-manager? Can you try running 'virt-manager > --no-fork' from the command line, trying to connect to the remote host, > and seeing if a password prompt pops up in the terminal? > > Thanks, > Cole Server is CentOS 5.2, client is fedora 9. Virt-manager version is 0.5.4 binary RPM from the Fedora repo. The server was Fedora 9 but I installed CentOS 5.2 on it today and it's using the Xen kernel now and having the same trouble. Again, locally, virt-manager works fantastically, but when I try to connect remotely it gives me trouble. I don't know how it could possibly matter, but I'm connecting back to another location using vpnc and then opening virt-manager, so I've got maybe 150ms latency to the libvirtd host. I've been launching virt-manager from Applications -> System Tools -> Virtual Machine Manager. Also I've launched it a few times with something similar to: $virt-manager -c xen+ssh://10.2.30.12/system. Now I've also tried: $virt-manager --no-fork -c xen+ssh://10.2.30.12/system (no password prompt by the way). It seems to be logging in because, like I said, if I stop libvirtd, I get a list of the available guests on the libvirtd server. And actually once I connect if I wait 15 or 20 minutes it will return a list. It will just freeze up intermittently and it's never responsive to input. If I try to click on a guest to select it, it will take 2 or 3 minutes before the selection takes effect and the item is highlighted. From crobinso at redhat.com Tue Dec 2 03:54:41 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 01 Dec 2008 22:54:41 -0500 Subject: [et-mgmt-tools] running virt-manager In-Reply-To: <8b711df40812011441j28251c8m8e9508f5ac43cd74@mail.gmail.com> References: <8b711df40812011043q33fce52dkb20bca5462e8b963@mail.gmail.com> <4934346C.2090603@redhat.com> <8b711df40812011229ga92ae10sd91d72b2f82fe02e@mail.gmail.com> <49345484.50807@redhat.com> <8b711df40812011441j28251c8m8e9508f5ac43cd74@mail.gmail.com> Message-ID: <4934B181.3080609@redhat.com> Paras pradhan wrote: > > Cole. thanks.. the patch worked and I can now see the GUI of virt-manager. > > Now when I click the Domain-0 in virt-manager. I am having an err msg. > > -- > Traceback (most recent call last): > File "/usr/share/virt-manager/virtManager/engine.py", line 304, in > show_details > details = vmmDetails(self.get_config(), con.get_vm(uuid), self) > File "/usr/share/virt-manager/virtManager/details.py", line 188, in > __init__ > self.vncViewer.set_scaling(True) > AttributeError: 'gtkvnc.Display' object has no attribute 'set_scaling' > --- > > > I have gtk-vnc-pythond installed. > > > NO idea what is going on. > > > Thanks > Paras. > You'll need the latest version of gtk-vnc, or at least the minimum that is specified in the packaged virt-manager spec file. Make sure all other dependencies in the spec file are met on your machine as well. - Cole From anschneider at suse.de Tue Dec 2 10:48:00 2008 From: anschneider at suse.de (Andreas Schneider) Date: Tue, 2 Dec 2008 11:48:00 +0100 Subject: [et-mgmt-tools] [PATCH] Fix lookup pool by path In-Reply-To: <4933FDC1.4030909@redhat.com> References: <200811251608.25707.anschneider@suse.de> <200811281447.06174.anschneider@suse.de> <4933FDC1.4030909@redhat.com> Message-ID: <200812021148.00833.anschneider@suse.de> On Monday 01 December 2008 16:07:45 Cole Robinson wrote: > Hmm, so your pool xml lists the target directory with a trailing slash? > I'm not seeing that. What version of libvirt are you using, and can you > provide the pools xml? Hi, I'm using virt-manager to connect to a remote host, so if I create a pool I have to specify the path to the pool manually. This means you can enter as many trailing slashes as you want. So the questions is, should the slashes be stripped during the creation of the pool too? tmp 17e0c17a-3cd3-bc20-f1bc-7c9ffaceb255 0 0 0 /var/lib/libvirt/images/tmp///// 0700 0 0 > > Thanks, > Cole Best regards, -- andreas -- Andreas Schneider, SUSE Labs, http://www.suse.de/ SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nuernberg) -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 197 bytes Desc: This is a digitally signed message part. URL: From john.levon at sun.com Tue Dec 2 18:13:12 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 02 Dec 2008 10:13:12 -0800 Subject: [et-mgmt-tools] [PATCH] Fix pylint on Solaris Message-ID: <583d6aff027f0c0348f6.1228241592@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228241583 28800 # Node ID 583d6aff027f0c0348f6c15919b3a2d36a40164c # Parent bcd052e6ef9dd3a56f2cadee8198a622e3f2068d Fix pylint on Solaris Use a good enough awk. Signed-off-by: John Levon diff --git a/tests/pylint-virtinst.sh b/tests/pylint-virtinst.sh --- a/tests/pylint-virtinst.sh +++ b/tests/pylint-virtinst.sh @@ -82,6 +82,9 @@ addchecker "Design" # Things lik # "Too man public methods" addchecker "Similarities" # Finds duplicate code (enable this later?) +AWK=awk +[ `uname -s` = 'SunOS' ] && AWK=nawk + pylint --ignore=coverage.py, $FILES \ --reports=n \ --output-format=colorized \ @@ -99,7 +102,7 @@ pylint --ignore=coverage.py, $FILES \ -ve "$URLTEST_ACCESS" \ -ve "$UNUSED_ARGS" \ -ve "$PROT_MEM_BUGS" | \ - awk '\ + $AWK '\ # Strip out any "*** Module name" lines if we dont list any errors for them BEGIN { found=0; cur_line="" } { From pradhanparas at gmail.com Tue Dec 2 16:11:44 2008 From: pradhanparas at gmail.com (Paras pradhan) Date: Tue, 2 Dec 2008 10:11:44 -0600 Subject: [et-mgmt-tools] running virt-manager In-Reply-To: <4934B181.3080609@redhat.com> References: <8b711df40812011043q33fce52dkb20bca5462e8b963@mail.gmail.com> <4934346C.2090603@redhat.com> <8b711df40812011229ga92ae10sd91d72b2f82fe02e@mail.gmail.com> <49345484.50807@redhat.com> <8b711df40812011441j28251c8m8e9508f5ac43cd74@mail.gmail.com> <4934B181.3080609@redhat.com> Message-ID: <8b711df40812020811q119350f7kdfbf5f0b2034a3ce@mail.gmail.com> On Mon, Dec 1, 2008 at 9:54 PM, Cole Robinson wrote: > Paras pradhan wrote: > > > > Cole. thanks.. the patch worked and I can now see the GUI of > virt-manager. > > > > Now when I click the Domain-0 in virt-manager. I am having an err msg. > > > > -- > > Traceback (most recent call last): > > File "/usr/share/virt-manager/virtManager/engine.py", line 304, in > > show_details > > details = vmmDetails(self.get_config(), con.get_vm(uuid), self) > > File "/usr/share/virt-manager/virtManager/details.py", line 188, in > > __init__ > > self.vncViewer.set_scaling(True) > > AttributeError: 'gtkvnc.Display' object has no attribute 'set_scaling' > > --- > > > > > > I have gtk-vnc-pythond installed. > > > > > > NO idea what is going on. > > > > > > Thanks > > Paras. > > > > You'll need the latest version of gtk-vnc, or at least the minimum that is > specified in the packaged virt-manager spec file. Make sure all other > dependencies in the spec file are met on your machine as well. > > - Cole The README file that comes with the tar ball of virt-manager mentions the required version of to be gtk-vnc >= 0.0.1. I have 0.3.2 [root at ha1 virt-manager-0.6.0]# rpm -qa |grep gtk-vnc gtk-vnc-python-0.3.2-3.el5 gtk-vnc-0.3.2-3.el5 gtk-vnc-devel-0.3.2-3.el5 Thanks Paras. -------------- next part -------------- An HTML attachment was scrubbed... URL: From pradhanparas at gmail.com Tue Dec 2 17:27:00 2008 From: pradhanparas at gmail.com (Paras pradhan) Date: Tue, 2 Dec 2008 11:27:00 -0600 Subject: [et-mgmt-tools] running virt-manager In-Reply-To: <8b711df40812020811q119350f7kdfbf5f0b2034a3ce@mail.gmail.com> References: <8b711df40812011043q33fce52dkb20bca5462e8b963@mail.gmail.com> <4934346C.2090603@redhat.com> <8b711df40812011229ga92ae10sd91d72b2f82fe02e@mail.gmail.com> <49345484.50807@redhat.com> <8b711df40812011441j28251c8m8e9508f5ac43cd74@mail.gmail.com> <4934B181.3080609@redhat.com> <8b711df40812020811q119350f7kdfbf5f0b2034a3ce@mail.gmail.com> Message-ID: <8b711df40812020927t6dd67d26w2eeaf5390e07d68@mail.gmail.com> On Tue, Dec 2, 2008 at 10:11 AM, Paras pradhan wrote: > > > On Mon, Dec 1, 2008 at 9:54 PM, Cole Robinson wrote: > >> Paras pradhan wrote: >> > >> > Cole. thanks.. the patch worked and I can now see the GUI of >> virt-manager. >> > >> > Now when I click the Domain-0 in virt-manager. I am having an err msg. >> > >> > -- >> > Traceback (most recent call last): >> > File "/usr/share/virt-manager/virtManager/engine.py", line 304, in >> > show_details >> > details = vmmDetails(self.get_config(), con.get_vm(uuid), self) >> > File "/usr/share/virt-manager/virtManager/details.py", line 188, in >> > __init__ >> > self.vncViewer.set_scaling(True) >> > AttributeError: 'gtkvnc.Display' object has no attribute 'set_scaling' >> > --- >> > >> > >> > I have gtk-vnc-pythond installed. >> > >> > >> > NO idea what is going on. >> > >> > >> > Thanks >> > Paras. >> > >> >> You'll need the latest version of gtk-vnc, or at least the minimum that is >> specified in the packaged virt-manager spec file. Make sure all other >> dependencies in the spec file are met on your machine as well. >> >> - Cole > > > > The README file that comes with the tar ball of virt-manager mentions the > required version of to be gtk-vnc >= 0.0.1. I have 0.3.2 > > [root at ha1 virt-manager-0.6.0]# rpm -qa |grep gtk-vnc > gtk-vnc-python-0.3.2-3.el5 > gtk-vnc-0.3.2-3.el5 > gtk-vnc-devel-0.3.2-3.el5 > > > Thanks > Paras. > > > I removed the gtk-vnc rpms and compiled from source... Now I don't have that error now. Thanks paras. -------------- next part -------------- An HTML attachment was scrubbed... URL: From pradhanparas at gmail.com Tue Dec 2 18:45:27 2008 From: pradhanparas at gmail.com (Paras pradhan) Date: Tue, 2 Dec 2008 12:45:27 -0600 Subject: [et-mgmt-tools] virt-install Message-ID: <8b711df40812021045h612bad82taa3aaafbab99d5ae@mail.gmail.com> Hi all, What is causing this? --- [root at ha1 init.d]# virt-install ERROR A name is required for the virtual machine. --- It should be run interactively. Correct? Version is the 0.400.0 and compiled from source tar ball under CentOS 52 Thanks Paras. -------------- next part -------------- An HTML attachment was scrubbed... URL: From crobinso at redhat.com Tue Dec 2 21:17:44 2008 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 02 Dec 2008 16:17:44 -0500 Subject: [et-mgmt-tools] virt-install In-Reply-To: <8b711df40812021045h612bad82taa3aaafbab99d5ae@mail.gmail.com> References: <8b711df40812021045h612bad82taa3aaafbab99d5ae@mail.gmail.com> Message-ID: <4935A5F8.9000409@redhat.com> Paras pradhan wrote: > Hi all, > > What is causing this? > > --- > [root at ha1 init.d]# virt-install > ERROR A name is required for the virtual machine. > --- > > It should be run interactively. Correct? > > > Version is the 0.400.0 and compiled from source tar ball under CentOS 52 > Most prompting was removed from virt-install in the 0.400.0 release. It was a maintenance burden and and largely unnecessary. The minimum required options should be --name, --ram, and an install method (either --location, --pxe, or --cdrom). - Cole From crobinso at redhat.com Tue Dec 2 21:26:12 2008 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 02 Dec 2008 16:26:12 -0500 Subject: [et-mgmt-tools] Connecting to a remote libvirtd host using virt-manger In-Reply-To: <41c0f86d0812011841w7936f8a8n640203bb810398c2@mail.gmail.com> References: <41c0f86d0811301002p7d561f6er9bf365a07c89e718@mail.gmail.com> <4933F805.1070508@redhat.com> <41c0f86d0812011841w7936f8a8n640203bb810398c2@mail.gmail.com> Message-ID: <4935A7F4.20405@redhat.com> Jon Smith wrote: > On Mon, Dec 1, 2008 at 8:43 AM, Cole Robinson wrote: >> Jon Smith wrote: >>> virt-manager and libvirtd both functioning locally. I tried to use >>> virt-manager to access the same libvirtd host remotely but I'm having >>> some trouble. >>> >>> I'm using qemu+ssh to connect to the remote host, but when I do, >>> virt-manager turns gray and becomes unresponsive, eventually the part >>> of the window showing the hosts goes blank. If I stop libvirtd on the >>> remote host, virt-manager refreshes itself and shows the libvirtd host >>> as connected, and even lists all the domains available. I'm also able >>> to connect using virsh and that works fine. >>> >>> I can repeat this process over and over again, even after rebooting >>> the hosts involved. I've also run libvirtd with the --verbose flag >>> and can send the output (~80K) if that would help. >>> >> What distro are you using? What virt-manager version? Distro package or >> compiled from source? >> >> How are you invoking virt-manager? Can you try running 'virt-manager >> --no-fork' from the command line, trying to connect to the remote host, >> and seeing if a password prompt pops up in the terminal? >> >> Thanks, >> Cole > > Server is CentOS 5.2, client is fedora 9. Virt-manager version is > 0.5.4 binary RPM from the Fedora repo. The server was Fedora 9 but I > installed CentOS 5.2 on it today and it's using the Xen kernel now and > having the same trouble. Again, locally, virt-manager works > fantastically, but when I try to connect remotely it gives me trouble. > I don't know how it could possibly matter, but I'm connecting back to > another location using vpnc and then opening virt-manager, so I've got > maybe 150ms latency to the libvirtd host. > > I've been launching virt-manager from Applications -> System Tools -> > Virtual Machine Manager. Also I've launched it a few times with > something similar to: $virt-manager -c xen+ssh://10.2.30.12/system. > Now I've also tried: $virt-manager --no-fork -c > xen+ssh://10.2.30.12/system (no password prompt by the way). It seems > to be logging in because, like I said, if I stop libvirtd, I get a > list of the available guests on the libvirtd server. And actually > once I connect if I wait 15 or 20 minutes it will return a list. It > will just freeze up intermittently and it's never responsive to input. > If I try to click on a guest to select it, it will take 2 or 3 > minutes before the selection takes effect and the item is highlighted. Sounds like virt-manager is connecting fine, but the communication with the remote libvirtd is so slow virt-manager is frozen solid waiting for all the polling calls to return. Can you try 'virsh --connect your_remote_uri' from the host you are running virt-manager, and see if there is a large delay when connection, listing domains, etc. If there is though, I'm not sure what could be causing the delays. - Cole From pradhanparas at gmail.com Tue Dec 2 21:35:50 2008 From: pradhanparas at gmail.com (Paras pradhan) Date: Tue, 2 Dec 2008 15:35:50 -0600 Subject: [et-mgmt-tools] virt-install In-Reply-To: <4935A5F8.9000409@redhat.com> References: <8b711df40812021045h612bad82taa3aaafbab99d5ae@mail.gmail.com> <4935A5F8.9000409@redhat.com> Message-ID: <8b711df40812021335u6a5b11a1pbcdab94f97da1f20@mail.gmail.com> On Tue, Dec 2, 2008 at 3:17 PM, Cole Robinson wrote: > Paras pradhan wrote: > > Hi all, > > > > What is causing this? > > > > --- > > [root at ha1 init.d]# virt-install > > ERROR A name is required for the virtual machine. > > --- > > > > It should be run interactively. Correct? > > > > > > Version is the 0.400.0 and compiled from source tar ball under CentOS 52 > > > > Most prompting was removed from virt-install in the 0.400.0 release. It > was a maintenance burden and and largely unnecessary. > > The minimum required options should be --name, --ram, and an install > method (either --location, --pxe, or --cdrom). > > - Cole > > ok.. no problem with that when I can run virt-install with options. I get stuck in the middle.. this might not be the issue with virt-install or virt-manager. I am trying to install centos para virt guest. When I choose to install from nfs. it then tries to determine IP address automatically. I don't know if gets the ip or not. But the installer stops here in this screen. I am not being able to figure out this. Paras. -------------- next part -------------- An HTML attachment was scrubbed... URL: From levon at movementarian.org Wed Dec 3 01:49:55 2008 From: levon at movementarian.org (John Levon) Date: Wed, 3 Dec 2008 01:49:55 +0000 Subject: [et-mgmt-tools] prompt bug Message-ID: <20081203014955.GA16793@totally.trollied.org.uk> RuntimeError: Prompting disabled, but yes/no was requested. Try --force to force 'yes' for such prompts. Prompt was: Disk /export/guests/2008.11/root.img is already in use by another guest! What's the intended behaviour? regards john From levon at movementarian.org Wed Dec 3 02:23:45 2008 From: levon at movementarian.org (John Levon) Date: Wed, 3 Dec 2008 02:23:45 +0000 Subject: [et-mgmt-tools] HVM installs are broken? Message-ID: <20081203022345.GA17700@totally.trollied.org.uk> Current tip, Fedora 8: virt-install -d -n domu-225 -r 1024 --hvm --vnc -f /export/guests/2008.11/root.img --os-type=windows -l /net/heaped/export/netimage/windows/xp.iso Tue, 02 Dec 2008 18:36:58 DEBUG Using libvirt URI connect 'xen' Tue, 02 Dec 2008 18:36:58 DEBUG Requesting virt method 'hvm' Tue, 02 Dec 2008 18:36:58 DEBUG Received virt method 'hvm' ... Tue, 02 Dec 2008 18:36:58 DEBUG Attempting to detect distro: ... Tue, 02 Dec 2008 18:36:58 DEBUG Cleaning up mount at /var/lib/xen/virtinstmnt.REF5Hf Could not find an installable distribution at '/net/heaped/export/netimage/windows/xp.iso' Looks like it's no longer skipping the PV install detection for HVM guests. Am I missing something? regards john From john.levon at sun.com Wed Dec 3 02:24:50 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 02 Dec 2008 18:24:50 -0800 Subject: [et-mgmt-tools] [PATCH] Fix sparse file size off-by-one error Message-ID: # HG changeset patch # User john.levon at sun.com # Date 1228271065 28800 # Node ID ca3207be8b5da3d6f4f9f5432dfa819cfab173c8 # Parent 31aef21ff81fc33675c09ed0e03e152b963f5042 Fix sparse file size off-by-one error The Solaris loopback driver (lofi) requires files be a multiple of 512-bytes in size. Sparse files created via lseek(f, size, 0) are 1 byte larger than what is being requested. Signed-off-by: John Danielson diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -557,7 +557,7 @@ def _do_duplicate(design): design.clone_bs = 4096 sparse_copy_mode = True fd = os.open(dst_dev, os.O_WRONLY | os.O_CREAT) - os.lseek(fd, dst_siz, 0) + os.lseek(fd, dst_siz - 1, 0) os.write(fd, '\x00') os.close(fd) else: diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -488,7 +488,7 @@ class VirtualDisk(VirtualDevice): try: fd = os.open(self.path, os.O_WRONLY | os.O_CREAT) if self.sparse: - os.lseek(fd, size_bytes, 0) + os.lseek(fd, size_bytes -1, 0) os.write(fd, '\x00') if progresscb: progresscb.update(self.size) From john.levon at sun.com Wed Dec 3 02:25:39 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 02 Dec 2008 18:25:39 -0800 Subject: [et-mgmt-tools] [PATCH] Provide a common block device size utility for Solaris & Linux Message-ID: <7069ca5b2ced261f1943.1228271139@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228271102 28800 # Node ID 7069ca5b2ced261f19438d3091af89aea2441b88 # Parent ca3207be8b5da3d6f4f9f5432dfa819cfab173c8 Provide a common block device size utility for Solaris & Linux Signed-off-by: John Danielson diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -24,7 +24,6 @@ import logging import logging import urlgrabber.progress as progress import util -import commands import libvirt import Guest from VirtualDisk import VirtualDisk @@ -397,13 +396,7 @@ class CloneDesign(object): for i in lst: mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - dummy, msg = commands.getstatusoutput('fdisk -s %s' % i) - # check - if msg.isdigit() == False: - lines = msg.splitlines() - # retry eg. for the GPT disk - msg = lines[len(lines)-1] - size.append(int(msg) * 1024) + size.append(util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) @@ -457,13 +450,7 @@ class CloneDesign(object): continue mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - dummy, msg = commands.getstatusoutput('fdisk -s %s' % i) - # check - if msg.isdigit() == False: - lines = msg.splitlines() - # retry eg. for the GPT disk - msg = lines[len(lines)-1] - size.append(int(msg) * 1024) + size.append(util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -25,6 +25,8 @@ import re import re import libxml2 import logging +import commands +import stat from sys import stderr import libvirt @@ -257,6 +259,18 @@ def xml_escape(str): str = str.replace("<", "<") str = str.replace(">", ">") return str + +def blkdev_size(path): + if platform.system() == 'SunOS': + return os.stat(path)[stat.ST_SIZE] + else: + dummy, msg = commands.getstatusoutput('fdisk -s %s' % path) + # check + if msg.isdigit() == False: + lines = msg.splitlines() + # retry eg. for the GPT disk + msg = lines[len(lines)-1] + return (int(msg) * 1024) def compareMAC(p, q): """Compare two MAC addresses""" From john.levon at sun.com Wed Dec 3 02:26:02 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 02 Dec 2008 18:26:02 -0800 Subject: [et-mgmt-tools] [PATCH] Fix mount/unmount for Solaris Message-ID: # HG changeset patch # User john.levon at sun.com # Date 1228271149 28800 # Node ID a4538c6c2d6690526d80c011b46b4700c23a9ffd # Parent 7069ca5b2ced261f19438d3091af89aea2441b88 Fix mount/unmount for Solaris mount is not portable: fix for Solaris Signed-off-by: John Levon diff --git a/virtinst/ImageFetcher.py b/virtinst/ImageFetcher.py --- a/virtinst/ImageFetcher.py +++ b/virtinst/ImageFetcher.py @@ -180,14 +180,23 @@ class MountedImageFetcher(LocalImageFetc 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 = ["mount", "-o", "ro", self.location[4:], self.srcdir] + cmd = [mountcmd, "-o", "ro", self.location[4:], self.srcdir] else: if stat.S_ISBLK(os.stat(self.location)[stat.ST_MODE]): - cmd = ["mount", "-o", "ro", self.location, self.srcdir] + mountopt = "ro" else: - cmd = ["mount", "-o", "ro,loop", self.location, self.srcdir] + 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() @@ -197,7 +206,10 @@ class MountedImageFetcher(LocalImageFetc def cleanupLocation(self): logging.debug("Cleaning up mount at " + self.srcdir) - cmd = ["umount", 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) From berrange at redhat.com Wed Dec 3 09:35:09 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 3 Dec 2008 09:35:09 +0000 Subject: [et-mgmt-tools] [PATCH] Fix sparse file size off-by-one error In-Reply-To: References: Message-ID: <20081203093509.GB18245@redhat.com> On Tue, Dec 02, 2008 at 06:24:50PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228271065 28800 > # Node ID ca3207be8b5da3d6f4f9f5432dfa819cfab173c8 > # Parent 31aef21ff81fc33675c09ed0e03e152b963f5042 > Fix sparse file size off-by-one error > > The Solaris loopback driver (lofi) requires files be a multiple of > 512-bytes in size. Sparse files created via lseek(f, size, 0) are > 1 byte larger than what is being requested. > > Signed-off-by: John Danielson > > diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py > --- a/virtinst/CloneManager.py > +++ b/virtinst/CloneManager.py > @@ -557,7 +557,7 @@ def _do_duplicate(design): > design.clone_bs = 4096 > sparse_copy_mode = True > fd = os.open(dst_dev, os.O_WRONLY | os.O_CREAT) > - os.lseek(fd, dst_siz, 0) > + os.lseek(fd, dst_siz - 1, 0) > os.write(fd, '\x00') Perhaps we should just avoid the extra 1 byte write here, by switching to ftruncate, eg fd = os.open(dst_dev, os.O_WRONLY | os.O_CREAT) os.ftruncate(fd, dst_siz, 0) os.close(fd) > diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py > --- a/virtinst/VirtualDisk.py > +++ b/virtinst/VirtualDisk.py > @@ -488,7 +488,7 @@ class VirtualDisk(VirtualDevice): > try: > fd = os.open(self.path, os.O_WRONLY | os.O_CREAT) > if self.sparse: > - os.lseek(fd, size_bytes, 0) > + os.lseek(fd, size_bytes -1, 0) > os.write(fd, '\x00') Likewise here Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Wed Dec 3 09:37:57 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 3 Dec 2008 09:37:57 +0000 Subject: [et-mgmt-tools] [PATCH] Provide a common block device size utility for Solaris & Linux In-Reply-To: <7069ca5b2ced261f1943.1228271139@xenbld.SFBay.Sun.COM> References: <7069ca5b2ced261f1943.1228271139@xenbld.SFBay.Sun.COM> Message-ID: <20081203093755.GC18245@redhat.com> On Tue, Dec 02, 2008 at 06:25:39PM -0800, john.levon at sun.com wrote: > @@ -257,6 +259,18 @@ def xml_escape(str): > str = str.replace("<", "<") > str = str.replace(">", ">") > return str > + > +def blkdev_size(path): > + if platform.system() == 'SunOS': > + return os.stat(path)[stat.ST_SIZE] > + else: > + dummy, msg = commands.getstatusoutput('fdisk -s %s' % path) > + # check > + if msg.isdigit() == False: > + lines = msg.splitlines() > + # retry eg. for the GPT disk > + msg = lines[len(lines)-1] > + return (int(msg) * 1024) ACK, to the general idea of adding a common routine. The original Linux impl was kind of crazy. We could get a single portable impl for all OS by using seek(), which is how libvirt does it in its storage code. fd = os.open(path, O_RDONLY) size = os.lseek(fd, 0, SEEK_END); os.close(fd) return size Danie -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Wed Dec 3 09:39:07 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 3 Dec 2008 09:39:07 +0000 Subject: [et-mgmt-tools] [PATCH] Fix mount/unmount for Solaris In-Reply-To: References: Message-ID: <20081203093907.GD18245@redhat.com> On Tue, Dec 02, 2008 at 06:26:02PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228271149 28800 > # Node ID a4538c6c2d6690526d80c011b46b4700c23a9ffd > # Parent 7069ca5b2ced261f19438d3091af89aea2441b88 > Fix mount/unmount for Solaris > > mount is not portable: fix for Solaris ACK. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Wed Dec 3 09:49:50 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 3 Dec 2008 09:49:50 +0000 Subject: [et-mgmt-tools] HVM installs are broken? In-Reply-To: <20081203022345.GA17700@totally.trollied.org.uk> References: <20081203022345.GA17700@totally.trollied.org.uk> Message-ID: <20081203094950.GH18245@redhat.com> On Wed, Dec 03, 2008 at 02:23:45AM +0000, John Levon wrote: > > Current tip, Fedora 8: > > virt-install -d -n domu-225 -r 1024 --hvm --vnc -f > /export/guests/2008.11/root.img --os-type=windows -l > /net/heaped/export/netimage/windows/xp.iso > > Tue, 02 Dec 2008 18:36:58 DEBUG Using libvirt URI connect 'xen' > Tue, 02 Dec 2008 18:36:58 DEBUG Requesting virt method 'hvm' > Tue, 02 Dec 2008 18:36:58 DEBUG Received virt method 'hvm' > ... > Tue, 02 Dec 2008 18:36:58 DEBUG Attempting to detect distro: > ... > Tue, 02 Dec 2008 18:36:58 DEBUG Cleaning up mount at > /var/lib/xen/virtinstmnt.REF5Hf > Could not find an installable distribution at '/net/heaped/export/netimage/windows/xp.iso' > > Looks like it's no longer skipping the PV install detection for HVM > guests. Am I missing something? The -l / --location PATH|URL arg will do a kernel+initrd based install for either HVM or Paravirt - latest Xen support kernel+initrd boot of Linux HVM guests, as does KVM. For plain BIOS based boot, just use --cdrom PATH|URL Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From guyca at matrix.co.il Wed Dec 3 13:09:37 2008 From: guyca at matrix.co.il (Guy Carmin) Date: Wed, 3 Dec 2008 15:09:37 +0200 Subject: [et-mgmt-tools] virt-manager-0.6.0 Message-ID: Hi All, I've just install the new virt-manager on my F9 machine, and when tringto run: /usr/local/virt-manager-0.6.0/bin/virt-manager I got the following error: Error starting Virtual Machine Manager: invalid syntax (host.py, line 31): Traceback (most recent call last): File "/usr/local/virt-manager-0.6.0/share/virt-manager/virt-manager.py", line 346, in main() File "/usr/local/virt-manager-0.6.0/share/virt-manager/virt-manager.py", line 287, in main from virtManager.engine import vmmEngine File "/usr/local/virt-manager-0.6.0/share/virt-manager/virtManager/engine.py" , line 37, in from virtManager.host import vmmHost File "/usr/local/virt-manager-0.6.0/share/virt-manager/virtManager/host.py", line 31 from virtinst import $torage ^ SyntaxError: invalid syntax I've tried to change $torage to storage and got a similar error: Error starting Virtual Machine Manager: cannot import name storage Traceback (most recent call last): File "/usr/local/virt-manager-0.6.0/share/virt-manager/virt-manager.py", line 346, in main() File "/usr/local/virt-manager-0.6.0/share/virt-manager/virt-manager.py", line 287, in main from virtManager.engine import vmmEngine File "/usr/local/virt-manager-0.6.0/share/virt-manager/virtManager/engine.py" , line 37, in from virtManager.host import vmmHost File "/usr/local/virt-manager-0.6.0/share/virt-manager/virtManager/host.py", line 31, in from virtinst import storage ImportError: cannot import name storage Please advice. \guy -------------- next part -------------- An HTML attachment was scrubbed... URL: From crobinso at redhat.com Wed Dec 3 15:29:52 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 03 Dec 2008 10:29:52 -0500 Subject: [et-mgmt-tools] virt-manager-0.6.0 In-Reply-To: References: Message-ID: <4936A5F0.9030507@redhat.com> Guy Carmin wrote: > Hi All, > > > > I've just install the new virt-manager on my F9 machine, and when > tringto run: > > /usr/local/virt-manager-0.6.0/bin/virt-manager > > > > I got the following error: > > > > Error starting Virtual Machine Manager: invalid syntax (host.py, line > 31): > > > > Traceback (most recent call last): > > File > "/usr/local/virt-manager-0.6.0/share/virt-manager/virt-manager.py", line > 346, in > > main() > > File > "/usr/local/virt-manager-0.6.0/share/virt-manager/virt-manager.py", line > 287, in main > > from virtManager.engine import vmmEngine > > File > "/usr/local/virt-manager-0.6.0/share/virt-manager/virtManager/engine.py" > , line 37, in > > from virtManager.host import vmmHost > > File > "/usr/local/virt-manager-0.6.0/share/virt-manager/virtManager/host.py", > line 31 > > from virtinst import $torage > I have no idea why that looks like '$torage' instead of 'Storage'. The reason you should be hitting an error though is because you don't have the latest virtinst installed. If you are on F9, fully 'yum update' your system, then do: yum --enablerepo=updates-testing-newkey update virt-manager and it should pull in the latest version with some additional bugfixes. Thanks, Cole From crobinso at redhat.com Wed Dec 3 15:35:55 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 03 Dec 2008 10:35:55 -0500 Subject: [et-mgmt-tools] prompt bug In-Reply-To: <20081203014955.GA16793@totally.trollied.org.uk> References: <20081203014955.GA16793@totally.trollied.org.uk> Message-ID: <4936A75B.70903@redhat.com> John Levon wrote: > > RuntimeError: Prompting disabled, but yes/no was requested. Try --force > to force 'yes' for such prompts. Prompt was: Disk > /export/guests/2008.11/root.img is already in use by another guest! > You're trying to use a disk in use by another guest. We disabled prompting by default with the last release because it made automating installs a pain, but the result is we take a conservative approach to ambiguous situations, such as the above (also 'this sparse file, if fully allocated, will hose your disk. is that what you want?'). So, if you want it to just work, use --force. Thanks, Cole From crobinso at redhat.com Wed Dec 3 15:50:44 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 03 Dec 2008 10:50:44 -0500 Subject: [et-mgmt-tools] [PATCH] Fix pylint on Solaris In-Reply-To: <583d6aff027f0c0348f6.1228241592@xenbld.SFBay.Sun.COM> References: <583d6aff027f0c0348f6.1228241592@xenbld.SFBay.Sun.COM> Message-ID: <4936AAD4.3000409@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228241583 28800 > # Node ID 583d6aff027f0c0348f6c15919b3a2d36a40164c > # Parent bcd052e6ef9dd3a56f2cadee8198a622e3f2068d > Fix pylint on Solaris > > Use a good enough awk. > > Signed-off-by: John Levon > Applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=583d6aff027f Thanks, Cole From crobinso at redhat.com Wed Dec 3 15:51:11 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 03 Dec 2008 10:51:11 -0500 Subject: [et-mgmt-tools] [PATCH] Fix mount/unmount for Solaris In-Reply-To: References: Message-ID: <4936AAEF.7040503@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228271149 28800 > # Node ID a4538c6c2d6690526d80c011b46b4700c23a9ffd > # Parent 7069ca5b2ced261f19438d3091af89aea2441b88 > Fix mount/unmount for Solaris > > mount is not portable: fix for Solaris > > Signed-off-by: John Levon > Applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=74febd10a8a9 Thanks, Cole From crobinso at redhat.com Wed Dec 3 16:21:47 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 03 Dec 2008 11:21:47 -0500 Subject: [et-mgmt-tools] [PATCH] Fix lookup pool by path In-Reply-To: <200812021148.00833.anschneider@suse.de> References: <200811251608.25707.anschneider@suse.de> <200811281447.06174.anschneider@suse.de> <4933FDC1.4030909@redhat.com> <200812021148.00833.anschneider@suse.de> Message-ID: <4936B21B.2040901@redhat.com> Andreas Schneider wrote: > On Monday 01 December 2008 16:07:45 Cole Robinson wrote: >> Hmm, so your pool xml lists the target directory with a trailing slash? >> I'm not seeing that. What version of libvirt are you using, and can you >> provide the pools xml? > > Hi, > > I'm using virt-manager to connect to a remote host, so if I create a pool I > have to specify the path to the pool manually. > > This means you can enter as many trailing slashes as you want. So the > questions is, should the slashes be stripped during the creation of the pool > too? > > > tmp > 17e0c17a-3cd3-bc20-f1bc-7c9ffaceb255 > 0 > 0 > 0 > > > > /var/lib/libvirt/images/tmp///// > > 0700 > 0 > 0 > > > > Hmm, yes, seems like libvirt should be sanitizing the target path when the pool is defined (though virtinst could certainly do this too). Looks like there could be arbitrary '/' in the middle of the path though, so if you use something like os.path.abspath in your patch it should sanitize everything appropriately. Thank, Cole From levon at movementarian.org Wed Dec 3 16:35:45 2008 From: levon at movementarian.org (John Levon) Date: Wed, 3 Dec 2008 16:35:45 +0000 Subject: [et-mgmt-tools] prompt bug In-Reply-To: <4936A75B.70903@redhat.com> References: <20081203014955.GA16793@totally.trollied.org.uk> <4936A75B.70903@redhat.com> Message-ID: <20081203163545.GB11827@totally.trollied.org.uk> On Wed, Dec 03, 2008 at 10:35:55AM -0500, Cole Robinson wrote: > > RuntimeError: Prompting disabled, but yes/no was requested. Try --force > > to force 'yes' for such prompts. Prompt was: Disk > > /export/guests/2008.11/root.img is already in use by another guest! > > You're trying to use a disk in use by another guest. We disabled > prompting by default with the last release because it made automating > installs a pain, but the result is we take a conservative approach to > ambiguous situations, such as the above (also 'this sparse file, if > fully allocated, will hose your disk. is that what you want?'). OK, then the code needs to be fixed to just give an error, not some obscure backtrace, right? regards john From levon at movementarian.org Wed Dec 3 16:37:28 2008 From: levon at movementarian.org (John Levon) Date: Wed, 3 Dec 2008 16:37:28 +0000 Subject: [et-mgmt-tools] HVM installs are broken? In-Reply-To: <20081203094950.GH18245@redhat.com> References: <20081203022345.GA17700@totally.trollied.org.uk> <20081203094950.GH18245@redhat.com> Message-ID: <20081203163728.GC11827@totally.trollied.org.uk> On Wed, Dec 03, 2008 at 09:49:50AM +0000, Daniel P. Berrange wrote: > > virt-install -d -n domu-225 -r 1024 --hvm --vnc -f > > /export/guests/2008.11/root.img --os-type=windows -l > > /net/heaped/export/netimage/windows/xp.iso > > > > Tue, 02 Dec 2008 18:36:58 DEBUG Using libvirt URI connect 'xen' > > Tue, 02 Dec 2008 18:36:58 DEBUG Requesting virt method 'hvm' > > Tue, 02 Dec 2008 18:36:58 DEBUG Received virt method 'hvm' > > ... > > Tue, 02 Dec 2008 18:36:58 DEBUG Attempting to detect distro: > > ... > > Tue, 02 Dec 2008 18:36:58 DEBUG Cleaning up mount at > > /var/lib/xen/virtinstmnt.REF5Hf > > Could not find an installable distribution at '/net/heaped/export/netimage/windows/xp.iso' > > > > Looks like it's no longer skipping the PV install detection for HVM > > guests. Am I missing something? > > The -l / --location PATH|URL arg will do a kernel+initrd based install > for either HVM or Paravirt - latest Xen support kernel+initrd boot > of Linux HVM guests, as does KVM. This is a regression over previous releases, where -l works for both. (And that was a good fix, since people *always* accidentally use -l instead of -c and get very confused. Can it be fixed? regards john From crobinso at redhat.com Wed Dec 3 16:43:45 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 03 Dec 2008 11:43:45 -0500 Subject: [et-mgmt-tools] prompt bug In-Reply-To: <20081203163545.GB11827@totally.trollied.org.uk> References: <20081203014955.GA16793@totally.trollied.org.uk> <4936A75B.70903@redhat.com> <20081203163545.GB11827@totally.trollied.org.uk> Message-ID: <4936B741.8050609@redhat.com> John Levon wrote: > On Wed, Dec 03, 2008 at 10:35:55AM -0500, Cole Robinson wrote: > >>> RuntimeError: Prompting disabled, but yes/no was requested. Try --force >>> to force 'yes' for such prompts. Prompt was: Disk >>> /export/guests/2008.11/root.img is already in use by another guest! >> You're trying to use a disk in use by another guest. We disabled >> prompting by default with the last release because it made automating >> installs a pain, but the result is we take a conservative approach to >> ambiguous situations, such as the above (also 'this sparse file, if >> fully allocated, will hose your disk. is that what you want?'). > > OK, then the code needs to be fixed to just give an error, not some > obscure backtrace, right? > > regards > john Oh, yes, that's fair. Fixed now: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=9eb684039e4e Thanks, Cole From crobinso at redhat.com Wed Dec 3 16:46:17 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 03 Dec 2008 11:46:17 -0500 Subject: [et-mgmt-tools] HVM installs are broken? In-Reply-To: <20081203163728.GC11827@totally.trollied.org.uk> References: <20081203022345.GA17700@totally.trollied.org.uk> <20081203094950.GH18245@redhat.com> <20081203163728.GC11827@totally.trollied.org.uk> Message-ID: <4936B7D9.5090608@redhat.com> John Levon wrote: > On Wed, Dec 03, 2008 at 09:49:50AM +0000, Daniel P. Berrange wrote: > >>> virt-install -d -n domu-225 -r 1024 --hvm --vnc -f >>> /export/guests/2008.11/root.img --os-type=windows -l >>> /net/heaped/export/netimage/windows/xp.iso >>> >>> Tue, 02 Dec 2008 18:36:58 DEBUG Using libvirt URI connect 'xen' >>> Tue, 02 Dec 2008 18:36:58 DEBUG Requesting virt method 'hvm' >>> Tue, 02 Dec 2008 18:36:58 DEBUG Received virt method 'hvm' >>> ... >>> Tue, 02 Dec 2008 18:36:58 DEBUG Attempting to detect distro: >>> ... >>> Tue, 02 Dec 2008 18:36:58 DEBUG Cleaning up mount at >>> /var/lib/xen/virtinstmnt.REF5Hf >>> Could not find an installable distribution at '/net/heaped/export/netimage/windows/xp.iso' >>> >>> Looks like it's no longer skipping the PV install detection for HVM >>> guests. Am I missing something? >> The -l / --location PATH|URL arg will do a kernel+initrd based install >> for either HVM or Paravirt - latest Xen support kernel+initrd boot >> of Linux HVM guests, as does KVM. > > This is a regression over previous releases, where -l works for both. > (And that was a good fix, since people *always* accidentally use -l > instead of -c and get very confused. Can it be fixed? > > regards > john > If it worked before, I'm fine with having it work again as long as it's feasible. Both options are largely going through the same codepath anyways. - Cole From berrange at redhat.com Wed Dec 3 16:50:36 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 3 Dec 2008 16:50:36 +0000 Subject: [et-mgmt-tools] HVM installs are broken? In-Reply-To: <20081203163728.GC11827@totally.trollied.org.uk> References: <20081203022345.GA17700@totally.trollied.org.uk> <20081203094950.GH18245@redhat.com> <20081203163728.GC11827@totally.trollied.org.uk> Message-ID: <20081203165036.GO18245@redhat.com> On Wed, Dec 03, 2008 at 04:37:28PM +0000, John Levon wrote: > On Wed, Dec 03, 2008 at 09:49:50AM +0000, Daniel P. Berrange wrote: > > > > virt-install -d -n domu-225 -r 1024 --hvm --vnc -f > > > /export/guests/2008.11/root.img --os-type=windows -l > > > /net/heaped/export/netimage/windows/xp.iso > > > > > > Tue, 02 Dec 2008 18:36:58 DEBUG Using libvirt URI connect 'xen' > > > Tue, 02 Dec 2008 18:36:58 DEBUG Requesting virt method 'hvm' > > > Tue, 02 Dec 2008 18:36:58 DEBUG Received virt method 'hvm' > > > ... > > > Tue, 02 Dec 2008 18:36:58 DEBUG Attempting to detect distro: > > > ... > > > Tue, 02 Dec 2008 18:36:58 DEBUG Cleaning up mount at > > > /var/lib/xen/virtinstmnt.REF5Hf > > > Could not find an installable distribution at '/net/heaped/export/netimage/windows/xp.iso' > > > > > > Looks like it's no longer skipping the PV install detection for HVM > > > guests. Am I missing something? > > > > The -l / --location PATH|URL arg will do a kernel+initrd based install > > for either HVM or Paravirt - latest Xen support kernel+initrd boot > > of Linux HVM guests, as does KVM. > > This is a regression over previous releases, where -l works for both. > (And that was a good fix, since people *always* accidentally use -l > instead of -c and get very confused. Can it be fixed? That was a bug in a previous release. We need to have distinct meaning for them, because many distros images & hypervisors will support both kernel+initrd and BIOS based provisioning, so we need to be able to distinguish between them. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From levon at movementarian.org Wed Dec 3 17:23:35 2008 From: levon at movementarian.org (John Levon) Date: Wed, 3 Dec 2008 17:23:35 +0000 Subject: [et-mgmt-tools] HVM installs are broken? In-Reply-To: <20081203165036.GO18245@redhat.com> References: <20081203022345.GA17700@totally.trollied.org.uk> <20081203094950.GH18245@redhat.com> <20081203163728.GC11827@totally.trollied.org.uk> <20081203165036.GO18245@redhat.com> Message-ID: <20081203172335.GE11827@totally.trollied.org.uk> On Wed, Dec 03, 2008 at 04:50:36PM +0000, Daniel P. Berrange wrote: > > This is a regression over previous releases, where -l works for both. > > (And that was a good fix, since people *always* accidentally use -l > > instead of -c and get very confused. Can it be fixed? > > That was a bug in a previous release. One of those bugs users love :) > We need to have distinct meaning for them, because many distros images > & hypervisors will support both kernel+initrd and BIOS based > provisioning, so we need to be able to distinguish between them. Isn't the correct solution to add another virt type (--hvm-whatever), not make life miserable for the users? At the *very* least, can't we decide whether to try kernel+initrd based upon detected OS type? I have a queued patch that adds 'os_type' to each of the OSDistro classes. regards john From berrange at redhat.com Wed Dec 3 20:07:08 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 3 Dec 2008 20:07:08 +0000 Subject: [et-mgmt-tools] HVM installs are broken? In-Reply-To: <20081203172335.GE11827@totally.trollied.org.uk> References: <20081203022345.GA17700@totally.trollied.org.uk> <20081203094950.GH18245@redhat.com> <20081203163728.GC11827@totally.trollied.org.uk> <20081203165036.GO18245@redhat.com> <20081203172335.GE11827@totally.trollied.org.uk> Message-ID: <20081203200708.GT18245@redhat.com> On Wed, Dec 03, 2008 at 05:23:35PM +0000, John Levon wrote: > On Wed, Dec 03, 2008 at 04:50:36PM +0000, Daniel P. Berrange wrote: > > > > This is a regression over previous releases, where -l works for both. > > > (And that was a good fix, since people *always* accidentally use -l > > > instead of -c and get very confused. Can it be fixed? > > > > That was a bug in a previous release. > > One of those bugs users love :) > > > We need to have distinct meaning for them, because many distros images > > & hypervisors will support both kernel+initrd and BIOS based > > provisioning, so we need to be able to distinguish between them. > > Isn't the correct solution to add another virt type (--hvm-whatever), > not make life miserable for the users? > > At the *very* least, can't we decide whether to try kernel+initrd based > upon detected OS type? I have a queued patch that adds 'os_type' to each > of the OSDistro classes. Unfortunately it varies based on (os type + hv type + hv version). eg, Xen 3.0.3 cannot do HVM installs off kernel+initrd, but Xen 3.4.0 can, and any KVM can. We really want to prefer kernel+intrd whereever possible because it allows 100% un-attended automated kickstarts without needing a network provisioning server. Perhaps what we really need is a libvirt capabilities XML extension to indicate what boot targets are supported. We currently have 4 choices host bootloader (pygrub), kernel+initrd, BIOS boo, and process init (container based virt only). Even so we still have a problem with talking to older libvirt which didn't support this. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From levon at movementarian.org Wed Dec 3 20:21:41 2008 From: levon at movementarian.org (John Levon) Date: Wed, 3 Dec 2008 20:21:41 +0000 Subject: [et-mgmt-tools] HVM installs are broken? In-Reply-To: <20081203200708.GT18245@redhat.com> References: <20081203022345.GA17700@totally.trollied.org.uk> <20081203094950.GH18245@redhat.com> <20081203163728.GC11827@totally.trollied.org.uk> <20081203165036.GO18245@redhat.com> <20081203172335.GE11827@totally.trollied.org.uk> <20081203200708.GT18245@redhat.com> Message-ID: <20081203202141.GA20220@totally.trollied.org.uk> On Wed, Dec 03, 2008 at 08:07:08PM +0000, Daniel P. Berrange wrote: > > > We need to have distinct meaning for them, because many distros images > > > & hypervisors will support both kernel+initrd and BIOS based > > > provisioning, so we need to be able to distinguish between them. > > > > Isn't the correct solution to add another virt type (--hvm-whatever), > > not make life miserable for the users? > > > > At the *very* least, can't we decide whether to try kernel+initrd based > > upon detected OS type? I have a queued patch that adds 'os_type' to each > > of the OSDistro classes. > > Unfortunately it varies based on (os type + hv type + hv version). True. But Windows and Solaris isn't ever going to do it. regards john From pradhanparas at gmail.com Wed Dec 3 22:29:28 2008 From: pradhanparas at gmail.com (Paras pradhan) Date: Wed, 3 Dec 2008 16:29:28 -0600 Subject: [et-mgmt-tools] virt-install In-Reply-To: <8b711df40812021335u6a5b11a1pbcdab94f97da1f20@mail.gmail.com> References: <8b711df40812021045h612bad82taa3aaafbab99d5ae@mail.gmail.com> <4935A5F8.9000409@redhat.com> <8b711df40812021335u6a5b11a1pbcdab94f97da1f20@mail.gmail.com> Message-ID: <8b711df40812031429q1ba9464fv76027d865c433a0b@mail.gmail.com> On Tue, Dec 2, 2008 at 3:35 PM, Paras pradhan wrote: > > > On Tue, Dec 2, 2008 at 3:17 PM, Cole Robinson wrote: >> >> Paras pradhan wrote: >> > Hi all, >> > >> > What is causing this? >> > >> > --- >> > [root at ha1 init.d]# virt-install >> > ERROR A name is required for the virtual machine. >> > --- >> > >> > It should be run interactively. Correct? >> > >> > >> > Version is the 0.400.0 and compiled from source tar ball under CentOS 52 >> > >> >> Most prompting was removed from virt-install in the 0.400.0 release. It >> was a maintenance burden and and largely unnecessary. >> >> The minimum required options should be --name, --ram, and an install >> method (either --location, --pxe, or --cdrom). >> >> - Cole >> > > ok.. no problem with that when I can run virt-install with options. I get > stuck in the middle.. this might not be the issue with virt-install or > virt-manager. I am trying to install centos para virt guest. When I choose > to install from nfs. it then tries to determine IP address automatically. I > don't know if gets the ip or not. But the installer stops here in this > screen. > I am not being able to figure out this. > Paras. After successfull installation of guest by virt-install where does it stores the domain configuration file. I did'nt see in /etc/xen but my domU is running good. Thanks Paras. From levon at movementarian.org Wed Dec 3 23:29:36 2008 From: levon at movementarian.org (John Levon) Date: Wed, 3 Dec 2008 23:29:36 +0000 Subject: [et-mgmt-tools] Another traceback Message-ID: <20081203232936.GA25629@totally.trollied.org.uk> Instead of a nice message: Wed, 03 Dec 2008 15:41:34 DEBUG Traceback (most recent call last): File "/tmp/c/bin/virt-install", line 190, in get_disk conn=guest.conn) File "/tmp/c/lib/python2.5/site-packages/virtinst/VirtualDisk.py", line 148, in __init__ self.__validate_params() File "/tmp/c/lib/python2.5/site-packages/virtinst/VirtualDisk.py", line 454, in __validate_params "'%s'" % self.path) ValueError: size is required for non-existent disk '/export/guests/2008.11/root.img' regards john From john.levon at sun.com Wed Dec 3 02:26:23 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 02 Dec 2008 18:26:23 -0800 Subject: [et-mgmt-tools] [PATCH] Least privilege support Message-ID: <2771f870b247df02b16a.1228271183@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228271172 28800 # Node ID 2771f870b247df02b16a4d79cdf549a1ad0132aa # Parent a4538c6c2d6690526d80c011b46b4700c23a9ffd Least privilege support On Solaris, which users can run virt-install depends on their effective privilege set, not their effective UID. Signed-off-by: John Levon diff --git a/virt-clone b/virt-clone --- a/virt-clone +++ b/virt-clone @@ -185,7 +185,7 @@ def main(): logging.debug("start clone with HV " + options.connect) if options.connect is None or options.connect.lower()[0:3] == "xen": - if os.geteuid() != 0: + if not virtinst.util.privileged_user(): fail(_("Must be root to clone Xen guests")) conn = cli.getConnection(options.connect) diff --git a/virtinst/DistroManager.py b/virtinst/DistroManager.py --- a/virtinst/DistroManager.py +++ b/virtinst/DistroManager.py @@ -193,7 +193,7 @@ class DistroInstaller(Guest.Installer): "or FTP network install source, or an existing " "local file/device")) - if os.geteuid() != 0 and val.startswith("nfs:"): + if val.startswith("nfs:") and not util.privileged_user(): raise ValueError(_("NFS installations are only supported as root")) self._location = val diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -28,6 +28,7 @@ import urlgrabber.progress as progress import urlgrabber.progress as progress import util import libvirt +import platform import __builtin__ import CapabilitiesParser import VirtualDevice @@ -347,9 +348,11 @@ class Installer(object): os_type = property(get_os_type, set_os_type) def get_scratchdir(self): + if platform.system() == 'SunOS': + return '/var/tmp' if self.type == "xen" and os.path.exists(XEN_SCRATCH): return XEN_SCRATCH - if os.getuid() == 0 and os.path.exists(LIBVIRT_SCRATCH): + if util.privileged_user() and os.path.exists(LIBVIRT_SCRATCH): return LIBVIRT_SCRATCH else: return os.path.expanduser("~/.virtinst/boot") @@ -476,7 +479,7 @@ class Installer(object): fd = os.open(guest.disks[0].path, os.O_RDONLY) except OSError, (err, msg): logging.debug("Failed to open guest disk: %s" % msg) - if err == errno.EACCES and os.geteuid() != 0: + if err == errno.EACCES and not util.privileged_user(): return True # non root might not have access to block devices else: raise diff --git a/virtinst/cli.py b/virtinst/cli.py --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -118,7 +118,7 @@ def nice_exit(): def getConnection(connect): if connect and connect.lower()[0:3] == "xen": - if os.geteuid() != 0: + if not util.privileged_user(): fail(_("Must be root to create Xen guests")) if connect is None: fail(_("Could not find usable default libvirt connection.")) @@ -307,7 +307,7 @@ def digest_networks(conn, macs, bridges, # Create extra networks up to the number of nics requested if len(macs) < nics: for dummy in range(len(macs),nics): - if os.getuid() == 0: + if util.privileged_user(): net = util.default_network(conn) networks.append(net[0] + ":" + net[1]) else: diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -93,7 +93,7 @@ def default_connection(): os.path.exists("/usr/bin/qemu-kvm") or \ os.path.exists("/usr/bin/kvm") or \ os.path.exists("/usr/bin/xenner"): - if os.getuid() == 0: + if privileged_user(): return "qemu:///system" else: return "qemu:///session" @@ -509,6 +509,14 @@ def lookup_pool_by_path(conn, path): return pool return None +def privileged_user(): + """ + Return true if the user is privileged enough. On Linux, this + equates to being root. On Solaris, it's more complicated, so we + just assume we're OK. + """ + return os.uname()[0] == 'SunOS' or os.geteuid() == 0 + def _test(): import doctest doctest.testmod() From levon at movementarian.org Thu Dec 4 03:12:58 2008 From: levon at movementarian.org (John Levon) Date: Thu, 4 Dec 2008 03:12:58 +0000 Subject: [et-mgmt-tools] prompt bug In-Reply-To: <20081203163545.GB11827@totally.trollied.org.uk> References: <20081203014955.GA16793@totally.trollied.org.uk> <4936A75B.70903@redhat.com> <20081203163545.GB11827@totally.trollied.org.uk> Message-ID: <20081204031258.GA31375@totally.trollied.org.uk> On Wed, Dec 03, 2008 at 04:35:45PM +0000, John Levon wrote: > OK, then the code needs to be fixed to just give an error, not some > obscure backtrace, right? The fix isn't quite there: ERROR Prompting disabled, but yes/no was requested. Try --force to force 'yes' for such prompts. Prompt was: Disk /export/guests/2008.11/root.img is already in use by another guest! Do you really want to use the disk (yes or no)? Can't we just make it say this: Disk /export/guests/2008.11/root.img is already in use by another guest! regards john From levon at movementarian.org Thu Dec 4 03:24:16 2008 From: levon at movementarian.org (John Levon) Date: Thu, 4 Dec 2008 03:24:16 +0000 Subject: [et-mgmt-tools] [PATCH] Provide a common block device size utility for Solaris & Linux In-Reply-To: <20081203093755.GC18245@redhat.com> References: <7069ca5b2ced261f1943.1228271139@xenbld.SFBay.Sun.COM> <20081203093755.GC18245@redhat.com> Message-ID: <20081204032416.GB31375@totally.trollied.org.uk> On Wed, Dec 03, 2008 at 09:37:57AM +0000, Daniel P. Berrange wrote: > > +def blkdev_size(path): > > + if platform.system() == 'SunOS': > > + return os.stat(path)[stat.ST_SIZE] > > + else: > > + dummy, msg = commands.getstatusoutput('fdisk -s %s' % path) > > + # check > > + if msg.isdigit() == False: > > + lines = msg.splitlines() > > + # retry eg. for the GPT disk > > + msg = lines[len(lines)-1] > > + return (int(msg) * 1024) > > > ACK, to the general idea of adding a common routine. The original Linux > impl was kind of crazy. We could get a single portable impl for all > OS by using seek(), which is how libvirt does it in its storage code. Quite honestly, I wasn't entirely sure why you're using fdisk. But if you don't need to, why use lseek() when os.stat() does the job? regards john From john.levon at sun.com Thu Dec 4 03:29:02 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 03 Dec 2008 19:29:02 -0800 Subject: [et-mgmt-tools] [PATCH] Fix sparse file size off-by-one error Message-ID: # HG changeset patch # User john.levon at sun.com # Date 1228360958 28800 # Node ID d8591178ebfca87835c7c5181cd96fde303444c9 # Parent a16f24e020cec71d5d61661a2a85e7e241ffe0be Fix sparse file size off-by-one error The Solaris loopback driver (lofi) requires files be a multiple of 512-bytes in size. Sparse files created via lseek(f, size, 0) are 1 byte larger than what is being requested. Signed-off-by: John Danielson diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -557,8 +557,7 @@ def _do_duplicate(design): design.clone_bs = 4096 sparse_copy_mode = True fd = os.open(dst_dev, os.O_WRONLY | os.O_CREAT) - os.lseek(fd, dst_siz, 0) - os.write(fd, '\x00') + os.ftruncate(fd, dst_siz) os.close(fd) else: design.clone_bs = 1024*1024*10 diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -488,8 +488,7 @@ class VirtualDisk(VirtualDevice): try: fd = os.open(self.path, os.O_WRONLY | os.O_CREAT) if self.sparse: - os.lseek(fd, size_bytes, 0) - os.write(fd, '\x00') + os.ftruncate(fd, size_bytes) if progresscb: progresscb.update(self.size) else: From john.levon at sun.com Thu Dec 4 04:30:37 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 03 Dec 2008 20:30:37 -0800 Subject: [et-mgmt-tools] [PATCH] Fix tap failure Message-ID: <7f39e430409182ab85ba.1228365037@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228365022 28800 # Node ID 7f39e430409182ab85ba39b8f74382b1f9167736 # Parent 4082e2dd5f6eba6febc0fffa9bce7d7c04ba27fa Fix tap failure VirtualDisk driver name/type need setters. Signed-off-by: John Levon diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -193,11 +193,15 @@ class VirtualDisk(VirtualDevice): def get_driver_name(self): return self._driverName - driver_name = property(get_driver_name) + 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 - driver_type = property(get_driver_type) + 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 From john.levon at sun.com Thu Dec 4 04:30:53 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 03 Dec 2008 20:30:53 -0800 Subject: [et-mgmt-tools] [PATCH] Add --autocf Message-ID: # HG changeset patch # User john.levon at sun.com # Date 1228365030 28800 # Node ID d9898b68352ad1c2491a3c9697d4b34af6630fc7 # Parent fd554fd90595417dbaadb42aecc598d586b7f99e Add --autocf Add an option for passing Solaris JumpStart information. For HVM guests, this means a floppy image (!). Signed-off-by: John Levon diff --git a/man/en/virt-install.1 b/man/en/virt-install.1 --- a/man/en/virt-install.1 +++ b/man/en/virt-install.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05) +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 .\" .\" Standard preamble: .\" ======================================================================== @@ -25,11 +25,11 @@ .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- @@ -48,25 +48,22 @@ . ds R" '' 'br\} .\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. -.ie \nF \{\ +.if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} -.el \{\ -. de IX -.. -.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -132,11 +129,7 @@ .\" ======================================================================== .\" .IX Title "VIRT-INSTALL 1" -.TH VIRT-INSTALL 1 "2008-09-08" "perl v5.10.0" "Virtual Machine Install Tools" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh +.TH VIRT-INSTALL 1 "2008-12-03" "perl v5.8.8" "Virtual Machine Install Tools" .SH "NAME" virt\-install \- provision new virtual machines .SH "SYNOPSIS" @@ -200,7 +193,7 @@ Set which physical cpus the guest can us .Sp .Vb 2 \& 0,2,3,5 : Use processors 0,2,3 and 5 -\& 1\-3,5,6\-8 : Use processors 1,2,3,5,6,7 and 8 +\& 1-3,5,6-8 : Use processors 1,2,3,5,6,7 and 8 .Ve .Sp If the value 'auto' is passed, virt-install attempts to automatically determine @@ -211,7 +204,7 @@ general format of a disk string is general format of a disk string is .Sp .Vb 1 -\& \-\-disk opt1=val1,opt2=val2,... +\& --disk opt1=val1,opt2=val2,... .Ve .Sp To specify media, one of the following options is required: @@ -234,7 +227,7 @@ specifying a 'size' value. .IP "\fBvol\fR" 4 .IX Item "vol" An existing libvirt storage volume to use. This is specified as -\&'poolname:volname'. +\&'poolname/volname'. .RE .RS 4 .Sp @@ -244,6 +237,11 @@ Disk device type. Value can be 'cdrom', Disk device type. Value can be 'cdrom', 'disk', or 'floppy'. Default is \&'disk'. If a 'cdrom' is specified, and no install method is chosen, the cdrom is used as the install media. +.IP "\fBbux\fR" 4 +.IX Item "bux" +Disk bus type. Value can be 'ide', 'scsi', 'usb', 'virtio' or 'xen'. The +default is hypervisor dependent since not all hypervisors support all bus +types. .IP "\fBperms\fR" 4 .IX Item "perms" Disk permissions. Value can be 'rw' (Read/Write), 'ro' (Readonly), @@ -285,7 +283,7 @@ time taken to fully-allocate the guest v time taken to fully-allocate the guest virtual disk will be usually by balanced by faster install times inside the guest. Thus use of this optional is recommended to ensure consistently high performance and to avoid I/O errors in the guest -should the host filesystem fill up. +should the host filesystem fill up. .IP "\-m \s-1MAC\s0, \-\-mac=MAC" 4 .IX Item "-m MAC, --mac=MAC" Fixed \s-1MAC\s0 address for the guest; If this parameter is omitted, or the value @@ -341,12 +339,12 @@ parameters are specified, this will be p .IX Item "--vncport=VNCPORT" Request a permanent, statically assigned port number for the guest \s-1VNC\s0 console. Use of this option is discouraged as other guests may automatically -choose to run on this port causing a clash. +choose to run on this port causing a clash. .IP "\-\-sdl" 4 .IX Item "--sdl" Setup a virtual console in the guest and display an \s-1SDL\s0 window in the host to render the output. If the \s-1SDL\s0 window is closed the guest may -be unconditionally terminated. +be unconditionally terminated. .IP "\-\-nographics" 4 .IX Item "--nographics" Disable all interactive prompts for the guest virtual console. No graphical @@ -558,7 +556,7 @@ virtualized guest. .IP "\-\-noacpi" 4 .IX Item "--noacpi" Override the \s-1OS\s0 type / variant to disables the \s-1ACPI\s0 setting for fully -virtualized guest. +virtualized guest. .IP "\-\-arch=ARCH" 4 .IX Item "--arch=ARCH" Request a non-native \s-1CPU\s0 architecture for the guest virtual machine. @@ -593,6 +591,11 @@ An \s-1FTP\s0 server location containing .RE .RS 4 .RE +.IP "\-\-autocf \s-1CF\s0" 4 +.IX Item "--autocf CF" +Provide a path to automated install information. Currently this can +either be a path to a Solaris JumpStart floppy disk image, or an \s-1NFS\s0 +path (for network installs). .IP "\-x \s-1EXTRA\s0, \-\-extra\-args=EXTRA" 4 .IX Item "-x EXTRA, --extra-args=EXTRA" Additional kernel command line arguments to pass to the installer when @@ -627,58 +630,58 @@ booting from the host \s-1CDROM\s0, usin booting from the host \s-1CDROM\s0, using \s-1VNC\s0 server/viewer .PP .Vb 9 -\& # virt\-install \e -\& \-\-connect qemu:///system \e -\& \-\-name demo \e -\& \-\-ram 500 \e -\& \-\-disk path=/var/lib/libvirt/images/demo.img,size=5 \e -\& \-\-network network:default \e -\& \-\-accelerate \e -\& \-\-vnc \e -\& \-\-cdrom /dev/cdrom +\& # virt-install \e +\& --connect qemu:///system \e +\& --name demo \e +\& --ram 500 \e +\& --disk path=/var/lib/libvirt/images/demo.img,size=5 \e +\& --network network:default \e +\& --accelerate \e +\& --vnc \e +\& --cdrom /dev/cdrom .Ve .PP Install a Fedora 9 \s-1KVM\s0 guest, using \s-1LVM\s0 partition, virtual networking, booting from \s-1PXE\s0, using \s-1VNC\s0 server/viewer .PP .Vb 9 -\& # virt\-install \e -\& \-\-connect qemu:///system \e -\& \-\-name demo \e -\& \-\-ram 500 \e -\& \-\-disk path=/dev/HostVG/DemoVM \e -\& \-\-network network:default \e -\& \-\-accelerate \e -\& \-\-vnc \e -\& \-\-os\-variant fedora9 +\& # virt-install \e +\& --connect qemu:///system \e +\& --name demo \e +\& --ram 500 \e +\& --disk path=/dev/HostVG/DemoVM \e +\& --network network:default \e +\& --accelerate \e +\& --vnc \e +\& --os-variant fedora9 .Ve .PP Install a \s-1QEMU\s0 guest, with a real partition, for a different architecture using \s-1SDL\s0 graphics, using a remote kernel and initrd pair: .PP .Vb 9 -\& # virt\-install \e -\& \-\-connect qemu:///system \e -\& \-\-name demo \e -\& \-\-ram 500 \e -\& \-\-disk path=/dev/hdc \e -\& \-\-network bridge:eth1 \e -\& \-\-arch ppc64 \e -\& \-\-sdl \e -\& \-\-location http://download.fedora.redhat.com/pub/fedora/linux/core/6/x86_64/os/ +\& # virt-install \e +\& --connect qemu:///system \e +\& --name demo \e +\& --ram 500 \e +\& --disk path=/dev/hdc \e +\& --network bridge:eth1 \e +\& --arch ppc64 \e +\& --sdl \e +\& --location http://download.fedora.redhat.com/pub/fedora/linux/core/6/x86_64/os/ .Ve .PP Run a Live \s-1CD\s0 image under Xen fullyvirt, in diskless environment .PP .Vb 8 -\& # virt\-install \e -\& \-\-hvm \e -\& \-\-name demo \e -\& \-\-ram 500 \e -\& \-\-nodisks \e -\& \-\-livecd \e -\& \-\-vnc \e -\& \-\-cdrom /root/fedora7live.iso +\& # virt-install \e +\& --hvm \e +\& --name demo \e +\& --ram 500 \e +\& --nodisks \e +\& --livecd \e +\& --vnc \e +\& --cdrom /root/fedora7live.iso .Ve .PP Install a paravirtualized Xen guest, 500 \s-1MB\s0 of \s-1RAM\s0, a 5 \s-1GB\s0 of disk, and @@ -686,14 +689,14 @@ options: options: .PP .Vb 8 -\& # virt\-install \e -\& \-\-paravirt \e -\& \-\-name demo \e -\& \-\-ram 500 \e -\& \-\-file /var/lib/xen/images/demo.img \e -\& \-\-file\-size 6 \e -\& \-\-nographics \e -\& \-\-location http://download.fedora.redhat.com/pub/fedora/linux/core/6/x86_64/os/ +\& # virt-install \e +\& --paravirt \e +\& --name demo \e +\& --ram 500 \e +\& --file /var/lib/xen/images/demo.img \e +\& --file-size 6 \e +\& --nographics \e +\& --location http://download.fedora.redhat.com/pub/fedora/linux/core/6/x86_64/os/ .Ve .SH "AUTHOR" .IX Header "AUTHOR" diff --git a/man/en/virt-install.pod b/man/en/virt-install.pod --- a/man/en/virt-install.pod +++ b/man/en/virt-install.pod @@ -538,6 +538,12 @@ An FTP server location containing an ins An FTP server location containing an installable distribution image =back + +=item --autocf CF + +Provide a path to automated install information. Currently this can +either be a path to a Solaris JumpStart floppy disk image, or an NFS +path (for network installs). =item -x EXTRA, --extra-args=EXTRA diff --git a/virt-install b/virt-install --- a/virt-install +++ b/virt-install @@ -385,6 +385,10 @@ def parse_args(): default="", help=_("Additional arguments to pass to the kernel " "booted from --location")) + parser.add_option("", "--autocf", type="string", dest="autocf", + default=None, action="callback", + callback=check_before_store, + help=_("Guest auto-configuration path")) parser.add_option_group(insg) stog = OptionGroup(parser, _("Storage Configuration")) @@ -588,6 +592,9 @@ def main(): if options.os_variant: guest.set_os_variant(options.os_variant) continue_inst = guest.get_continue_inst() + + if options.autocf is not None: + guest.autocf = options.autocf def show_console(dom): if guest.graphics_dev: diff --git a/virtinst/FullVirtGuest.py b/virtinst/FullVirtGuest.py --- a/virtinst/FullVirtGuest.py +++ b/virtinst/FullVirtGuest.py @@ -158,6 +158,13 @@ class FullVirtGuest(Guest): 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 \ diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -524,6 +524,7 @@ class Guest(object): self._vcpus = None self._cpuset = None self._graphics_dev = None + self._autocf = None self._os_type = None self._os_variant = None @@ -562,7 +563,6 @@ class Guest(object): def set_type(self, val): self._installer.type = val type = property(get_type, set_type) - # Domain name of the guest def get_name(self): @@ -599,6 +599,19 @@ class Guest(object): self._maxmemory = val maxmemory = property(get_maxmemory, set_maxmemory) + # location of auto-install config data (Solaris jumpstart) + def get_autocf(self): + return self._autocf + def set_autocf(self, val): + if type(val) is not type("string") or len(val) == 0: + raise ValueError, _("You must specify a valid pathname to autoconfiguration data") + if val.startswith('nfs:'): + self._autocf = val + else: + if not os.path.exists(val): + raise ValueError, _("%s does not exist" % val) + self._autocf = val + autocf = property(get_autocf, set_autocf) # UUID for the guest def get_uuid(self): From john.levon at sun.com Thu Dec 4 04:31:07 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 03 Dec 2008 20:31:07 -0800 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris Message-ID: <9e299e5ee2b46b8c3b73.1228365067@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228365030 28800 # Node ID 9e299e5ee2b46b8c3b737d5394498a855f553bae # Parent d9898b68352ad1c2491a3c9697d4b34af6630fc7 Port utility functions to Solaris Port various utils to Solaris, and remove some unused ones that don't work. Signed-off-by: John Levon diff --git a/virtinst/FullVirtGuest.py b/virtinst/FullVirtGuest.py --- a/virtinst/FullVirtGuest.py +++ b/virtinst/FullVirtGuest.py @@ -38,7 +38,8 @@ class FullVirtGuest(Guest): installer = DistroManager.DistroInstaller(type = type, os_type = "hvm") Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "hd" - self.features = { "acpi": None, "pae": util.is_pae_capable(), "apic": None } + self.features = { "acpi": None, "pae": + util.is_pae_capable(connection), "apic": None } if arch is None: arch = platform.machine() self.arch = arch diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -27,6 +27,7 @@ import logging import logging import commands import stat +import popen2 from sys import stderr import libvirt @@ -56,8 +57,29 @@ def default_route(): continue return None -# Legacy for compat only. +def default_nic(): + """Return the default NIC to use, if one is specified.""" + + dev = '' + + if platform.system() != 'SunOS': + return dev + + # XXX: fails without PRIV_XVM_CONTROL + proc = popen2.Popen3(["/usr/lib/xen/bin/xenstore-read", + "device-misc/vif/default-nic"], capturestderr=True) + proc.tochild.close() + proc.wait() + out = proc.fromchild.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 @@ -70,6 +92,9 @@ def default_bridge(): 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()): @@ -100,6 +125,9 @@ def default_connection(): 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() @@ -113,31 +141,16 @@ def get_cpu_flags(): return flst return [] -def is_pae_capable(): +def is_pae_capable(conn): """Determine if a machine is PAE capable or not.""" - flags = get_cpu_flags() - if "pae" in flags: - return True - return False - -def is_hvm_capable(): - """Determine if a machine is HVM capable or not.""" - - 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") + if not conn: + conn = libvirt.open('') + return "pae" in conn.getCapabilities() def is_blktap_capable(): - #return os.path.exists("/dev/xen/blktapctrl") + if platform.system() == 'SunOS': + return False + f = open("/proc/modules") lines = f.readlines() f.close() From john.levon at sun.com Thu Dec 4 04:31:20 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 03 Dec 2008 20:31:20 -0800 Subject: [et-mgmt-tools] [PATCH] Solaris HVM support Message-ID: <7dd32b4d7915937025f4.1228365080@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228365030 28800 # Node ID 7dd32b4d7915937025f42c3519711db50e5a7ce3 # Parent 9e299e5ee2b46b8c3b737d5394498a855f553bae Solaris HVM support Make 'solaris' a first-class OS type, and select USB tablet support for the appropriate variants. Signed-off-by: John Levon diff --git a/virtinst/osdict.py b/virtinst/osdict.py --- a/virtinst/osdict.py +++ b/virtinst/osdict.py @@ -107,11 +107,29 @@ OS_TYPES = {\ }, }, +"solaris": { + "label": "Solaris", + "clock": "localtime", + "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": { \ - "solaris9": { "label": "Sun Solaris 9" }, - "solaris10": { "label": "Sun Solaris 10" }, "freebsd6": { "label": "Free BSD 6.x" , # http://www.nabble.com/Re%3A-Qemu%3A-bridging-on-FreeBSD-7.0-STABLE-p15919603.html "devices" : { From john.levon at sun.com Thu Dec 4 04:31:28 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 03 Dec 2008 20:31:28 -0800 Subject: [et-mgmt-tools] [PATCH] Add support for Solaris PV Message-ID: <35baacfe79834400949e.1228365088@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228365031 28800 # Node ID 35baacfe79834400949ebdba69f952ed873ae442 # Parent 7dd32b4d7915937025f42c3519711db50e5a7ce3 Add support for Solaris PV Solaris PV comes in two flavours: Nevada and OpenSolaris. In order to correctly build network installs for Nevada, we need to pass down guest options into OSDistro. os_type was horribly overloaded between the Installer and Guest classes, meaning two different things ('solaris' or 'hvm'). Clean this up by naming the latter 'virt_type'. Signed-off-by: John Levon diff --git a/virt-install b/virt-install --- a/virt-install +++ b/virt-install @@ -510,27 +510,27 @@ def main(): fail(_("Can't do both --hvm and --paravirt")) if options.fullvirt: - os_type = "hvm" + virt_type = "hvm" elif options.paravirt: - os_type = "xen" + virt_type = "xen" else: # This should force capabilities to give us the most sensible default - os_type = None - - logging.debug("Requesting virt method '%s'" % (os_type and os_type or \ + virt_type = None + + logging.debug("Requesting virt method '%s'" % (virt_type and virt_type or \ _("default"))) - guest = capabilities.guestForOSType(type=os_type, arch=options.arch) + guest = capabilities.guestForVirtType(type=virt_type, arch=options.arch) if guest is None: - msg = _("Unsupported virtualization type '%s' " % (os_type and os_type + msg = _("Unsupported virtualization type '%s' " % (virt_type and virt_type or _("default"))) if options.arch: msg += _("for arch '%s'" % options.arch) fail(msg) - os_type = guest.os_type - logging.debug("Received virt method '%s'" % os_type) - if os_type == "hvm": + virt_type = guest.virt_type + logging.debug("Received virt method '%s'" % virt_type) + if virt_type == "hvm": hvm = True else: hvm = False @@ -540,13 +540,13 @@ def main(): logging.debug("Hypervisor type is '%s'" % htype) if options.livecd: - installer = virtinst.LiveCDInstaller(type = htype, os_type = os_type, + installer = virtinst.LiveCDInstaller(type = htype, virt_type = virt_type, conn = conn) elif options.pxe: - installer = virtinst.PXEInstaller(type = htype, os_type = os_type, + installer = virtinst.PXEInstaller(type = htype, virt_type = virt_type, conn = conn) else: - installer = virtinst.DistroInstaller(type = htype, os_type = os_type, + installer = virtinst.DistroInstaller(type = htype, virt_type = virt_type, conn = conn) if hvm: diff --git a/virtinst/CapabilitiesParser.py b/virtinst/CapabilitiesParser.py --- a/virtinst/CapabilitiesParser.py +++ b/virtinst/CapabilitiesParser.py @@ -121,7 +121,7 @@ class Guest(object): class Guest(object): def __init__(self, node = None): # e.g. "xen" or "hvm" - self.os_type = None + self.virt_type = None # e.g. "i686" or "x86_64" self.arch = None @@ -135,8 +135,9 @@ class Guest(object): def parseXML(self, node): child = node.children while child: + # In the XML, os_type really means virt_type if child.name == "os_type": - self.os_type = child.content + self.virt_type = child.content elif child.name == "features": self.features = CapabilityFeatures(child) elif child.name == "arch": @@ -260,7 +261,7 @@ class Capabilities(object): self._fixBrokenEmulator() - def guestForOSType(self, type = None, arch = None): + def guestForVirtType(self, type = None, arch = None): if self.host is None: return None @@ -270,7 +271,7 @@ class Capabilities(object): archs = [arch] for a in archs: for g in self.guests: - if (type is None or g.os_type == type) and \ + if (type is None or g.virt_type == type) and \ (a is None or g.arch == a): return g @@ -283,7 +284,7 @@ class Capabilities(object): fixEmulator = None for g in self.guests: - if g.os_type != "hvm" or g.arch != "x86_64": + if g.virt_type != "hvm" or g.arch != "x86_64": continue for d in g.domains: if d.emulator.find("lib64") != -1: @@ -293,7 +294,7 @@ class Capabilities(object): return for g in self.guests: - if g.os_type != "hvm" or g.arch != "i686": + if g.virt_type != "hvm" or g.arch != "i686": continue for d in g.domains: if d.emulator.find("lib64") == -1: diff --git a/virtinst/DistroManager.py b/virtinst/DistroManager.py --- a/virtinst/DistroManager.py +++ b/virtinst/DistroManager.py @@ -41,6 +41,8 @@ from OSDistro import DebianDistro from OSDistro import DebianDistro from OSDistro import UbuntuDistro from OSDistro import MandrivaDistro +from OSDistro import SolarisDistro +from OSDistro import OpenSolarisDistro from OSDistro import GenericDistro def _fetcherForURI(uri, scratchdir=None): @@ -87,6 +89,11 @@ def _storeForDistro(fetcher, baseuri, ty stores.append(UbuntuDistro(baseuri, typ, scratchdir, arch)) if distro == "mandriva" or distro is None: stores.append(MandrivaDistro(baseuri, typ, scratchdir, arch)) + # XXX: this is really "nevada" + if distro == "solaris" or distro is None: + stores.append(SolarisDistro(baseuri, type, scratchdir)) + if distro == "solaris" or distro is None: + stores.append(OpenSolarisDistro(baseuri, type, scratchdir)) stores.append(GenericDistro(baseuri, typ, scratchdir, arch)) @@ -98,24 +105,6 @@ def _storeForDistro(fetcher, baseuri, ty raise ValueError, _("Could not find an installable distribution at '%s'" % baseuri) - -# Method to fetch a kernel & initrd pair for a particular distro / HV type -def acquireKernel(baseuri, progresscb, scratchdir="/var/tmp", type=None, - distro=None, arch=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) - return store.acquireKernel(fetcher, progresscb) - finally: - fetcher.cleanupLocation() # Method to fetch a bootable ISO image for a particular distro / HV type def acquireBootDisk(baseuri, progresscb, scratchdir="/var/tmp", type=None, @@ -137,9 +126,9 @@ def acquireBootDisk(baseuri, progresscb, class DistroInstaller(Guest.Installer): def __init__(self, type = "xen", location = None, boot = None, - extraargs = None, os_type = None, conn = None): + extraargs = None, virt_type = None, conn = None): Guest.Installer.__init__(self, type, location, boot, extraargs, - os_type, conn=conn) + virt_type, conn=conn) self.install = { "kernel" : "", @@ -226,6 +215,27 @@ class DistroInstaller(Guest.Installer): readOnly=True, transient=True) + # Method to fetch a kernel & initrd pair for a particular distro / HV type + def _acquire_kernel(self, guest, progresscb, distro=None, arch=None): + fetcher = _fetcherForURI(self.location, self.scratchdir) + + try: + fetcher.prepareLocation() + except ValueError, e: + raise ValueError, _("Invalid install location: ") + str(e) + + try: + store = _storeForDistro(fetcher=fetcher, baseuri=self.location, + typ=self.virt_type, progresscb=progresscb, + distro=distro, scratchdir=self.scratchdir, + arch=arch) + + os_type = store.os_type + + return store.acquireKernel(guest, fetcher, progresscb), os_type + finally: + fetcher.cleanupLocation() + def _prepare_kernel_and_initrd(self, guest, distro, meter): if self.boot is not None: # Got a local kernel/initrd already @@ -239,26 +249,29 @@ class DistroInstaller(Guest.Installer): arch = os.uname()[4] if hasattr(guest, "arch"): arch = guest.arch - (kernelfn, initrdfn, args) = acquireKernel(self.location, - meter, - scratchdir = self.scratchdir, - type = self.os_type, - distro = distro, - arch=arch) + + (kernelfn, initrdfn, args), os_type = \ + self._acquire_kernel(guest, meter, distro = distro, arch = arch) + + guest.os_type = os_type self.install["kernel"] = kernelfn self.install["initrd"] = initrdfn - if not self.extraargs is None: - self.install["extraargs"] = self.extraargs + " " + args - else: - self.install["extraargs"] = args + self.install["extraargs"] = args self._tmpfiles.append(kernelfn) self._tmpfiles.append(initrdfn) # If they're installing off a local file/device, we map it - # through to a virtual harddisk - if self.location is not None and self.location.startswith("/") and not os.path.isdir(self.location): + # through to a virtual CD or disk + + if (self.location is not None and self.location.startswith("/") + and not os.path.isdir(self.location)): + device = Guest.VirtualDisk.DEVICE_DISK + if guest._lookup_osdict_key('pv_cdrom_install'): + device = Guest.VirtualDisk.DEVICE_CDROM + self._install_disk = VirtualDisk(self.location, + device=device, readOnly=True, transient=True) @@ -294,9 +307,9 @@ class DistroInstaller(Guest.Installer): class PXEInstaller(Guest.Installer): def __init__(self, type = "xen", location = None, boot = None, - extraargs = None, os_type = None, conn = None): + extraargs = None, virt_type = None, conn = None): Guest.Installer.__init__(self, type, location, boot, extraargs, - os_type, conn=conn) + virt_type, conn=conn) def prepare(self, guest, meter, distro = None): pass diff --git a/virtinst/FullVirtGuest.py b/virtinst/FullVirtGuest.py --- a/virtinst/FullVirtGuest.py +++ b/virtinst/FullVirtGuest.py @@ -35,7 +35,7 @@ class FullVirtGuest(Guest): def __init__(self, type=None, arch=None, connection=None, hypervisorURI=None, emulator=None, installer=None): if not installer: - installer = DistroManager.DistroInstaller(type = type, os_type = "hvm") + installer = DistroManager.DistroInstaller(type = type, virt_type = "hvm") Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "hd" self.features = { "acpi": None, "pae": @@ -46,7 +46,7 @@ class FullVirtGuest(Guest): self.emulator = emulator self.loader = None - guest = self._caps.guestForOSType(type=self.installer.os_type, + guest = self._caps.guestForVirtType(type=self.installer.virt_type, arch=self.arch) if (not self.emulator) and guest: for dom in guest.domains: diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -305,12 +305,12 @@ class VirtualGraphics(object): class Installer(object): def __init__(self, type = "xen", location = None, boot = None, - extraargs = None, os_type = None, conn = None): + extraargs = None, virt_type = None, conn = None): self._location = None self._extraargs = None self._boot = None self._cdrom = False - self._os_type = os_type + self._virt_type = virt_type self._conn = conn self._install_disk = None # VirtualDisk that contains install media @@ -341,11 +341,11 @@ class Installer(object): self._type = val type = property(get_type, set_type) - def get_os_type(self): - return self._os_type - def set_os_type(self, val): - self._os_type = val - os_type = property(get_os_type, set_os_type) + def get_virt_type(self): + return self._virt_type + def set_virt_type(self, val): + self._virt_type = val + virt_type = property(get_virt_type, set_virt_type) def get_scratchdir(self): if platform.system() == 'SunOS': @@ -411,15 +411,15 @@ class Installer(object): osblob = "\n" - os_type = self.os_type + virt_type = self.virt_type # Hack for older libvirt Xen driver - if os_type == "xen" and self.type == "xen": - os_type = "linux" + if virt_type == "xen" and self.type == "xen": + virt_type = "linux" if arch: - osblob += " %s\n" % (arch, os_type) - else: - osblob += " %s\n" % os_type + osblob += " %s\n" % (arch, virt_type) + else: + osblob += " %s\n" % virt_type if loader: osblob += " %s\n" % loader diff --git a/virtinst/ImageManager.py b/virtinst/ImageManager.py --- a/virtinst/ImageManager.py +++ b/virtinst/ImageManager.py @@ -111,18 +111,18 @@ class ImageInstaller(Guest.Installer): osblob = "\n" if hvm: - os_type = "hvm" + virt_type = "hvm" else: # Hack for older libvirt Xen driver if self.type == "xen": - os_type = "linux" + virt_type = "linux" else: - os_type = "xen" + virt_type = "xen" if arch: - osblob += " %s\n" % (arch, os_type) + osblob += " %s\n" % (arch, virt_type) else: - osblob += " %s\n" % os_type + osblob += " %s\n" % virt_type if loader: osblob += " %s\n" % loader @@ -154,7 +154,7 @@ def match_boots(capabilities, boots): 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: + if b.type == g.virt_type and b.arch == g.arch: found = True for bf in b.features.names(): if not b.features[bf] & g.features[bf]: diff --git a/virtinst/LiveCDInstaller.py b/virtinst/LiveCDInstaller.py --- a/virtinst/LiveCDInstaller.py +++ b/virtinst/LiveCDInstaller.py @@ -29,10 +29,10 @@ class LiveCDInstallerException(Exception Exception.__init__(self, msg) class LiveCDInstaller(Guest.Installer): - def __init__(self, type = "xen", location = None, os_type = None, + def __init__(self, type = "xen", location = None, virt_type = None, conn = None): Guest.Installer.__init__(self, type=type, location=location, - os_type=os_type, conn=conn) + virt_type=virt_type, conn=conn) def prepare(self, guest, meter, distro = None): self.cleanup() @@ -41,7 +41,7 @@ class LiveCDInstaller(Guest.Installer): found = False for guest_caps in capabilities.guests: - if guest_caps.os_type == "hvm": + if guest_caps.virt_type == "hvm": found = True break diff --git a/virtinst/OSDistro.py b/virtinst/OSDistro.py --- a/virtinst/OSDistro.py +++ b/virtinst/OSDistro.py @@ -25,8 +25,10 @@ import re import re import tempfile import platform +import socket import ConfigParser +from virtinst import util from virtinst import _virtinst as _ def distroFromTreeinfo(fetcher, progresscb, uri, vmtype=None, @@ -83,7 +85,7 @@ class Distro: """Determine if uri points to a tree of the store's distro""" raise NotImplementedError - def acquireKernel(self, fetcher, progresscb): + def acquireKernel(self, guest, fetcher, progresscb): kernelpath = None initrdpath = None if self._hasTreeinfo(fetcher, progresscb): @@ -106,7 +108,7 @@ class Distro: "%(distro)s tree.") % \ { "distro": self.name, "type" : self.type }) - return self._kernelFetchHelper(fetcher, progresscb, kernelpath, + return self._kernelFetchHelper(fetcher, guest, progresscb, kernelpath, initrdpath) def acquireBootDisk(self, fetcher, progresscb): @@ -172,18 +174,21 @@ class Distro: return False - def _kernelFetchHelper(self, fetcher, progresscb, kernelpath, initrdpath): + 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) - if fetcher.location.startswith("/"): - # Local host path, so can't pass a location to guest - #for install method - return (kernel, initrd, "") - else: - return (kernel, initrd, "method=" + fetcher.location) + return kernel, initrd, args except: os.unlink(kernel) @@ -193,6 +198,7 @@ class GenericDistro(Distro): 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", @@ -249,12 +255,12 @@ class GenericDistro(Distro): return True return False - def acquireKernel(self, fetcher, progresscb): + 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, progresscb, + return self._kernelFetchHelper(fetcher, guest, progresscb, self._valid_kernel_path[0], self._valid_kernel_path[1]) @@ -270,6 +276,7 @@ class RedHatDistro(Distro): class RedHatDistro(Distro): name = "Red Hat" + os_type = "linux" uses_treeinfo = True _boot_iso_paths = [ "images/boot.iso" ] _hvm_kernel_paths = [ ("images/pxeboot/vmlinuz", @@ -285,6 +292,7 @@ class FedoraDistro(RedHatDistro): class FedoraDistro(RedHatDistro): name = "Fedora" + os_type = "linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): @@ -300,6 +308,7 @@ class RHELDistro(RedHatDistro): class RHELDistro(RedHatDistro): name = "Red Hat Enterprise Linux" + os_type = "linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): @@ -322,6 +331,7 @@ class CentOSDistro(RedHatDistro): class CentOSDistro(RedHatDistro): name = "CentOS" + os_type = "linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): @@ -338,6 +348,7 @@ class SLDistro(RedHatDistro): class SLDistro(RedHatDistro): name = "Scientific Linux" + os_type = "linux" _boot_iso_paths = RedHatDistro._boot_iso_paths + [ "images/SL/boot.iso" ] _hvm_kernel_paths = RedHatDistro._hvm_kernel_paths + \ [ ("images/SL/pxeboot/vmlinuz", @@ -361,6 +372,7 @@ class SuseDistro(Distro): class SuseDistro(Distro): name = "SUSE" + os_type = "linux" _boot_iso_paths = [ "boot/boot.iso" ] _hvm_kernel_paths = [] _xen_kernel_paths = [] @@ -385,11 +397,11 @@ class SuseDistro(Distro): return True return False - def acquireKernel(self, fetcher, progresscb): + def acquireKernel(self, guest, fetcher, progresscb): # If installing a fullvirt guest if self.type is None or self.type == "hvm" or \ fetcher.hasFile("boot/%s/vmlinuz-xen" % self.arch): - return Distro.acquireKernel(self, fetcher, progresscb) + 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") @@ -590,6 +602,7 @@ class DebianDistro(Distro): # daily builds: http://people.debian.org/~joeyh/d-i/ name = "Debian" + os_type = "linux" def __init__(self, uri, vmtype=None, scratchdir=None, arch=None): Distro.__init__(self, uri, vmtype, scratchdir, arch) @@ -642,6 +655,7 @@ class UbuntuDistro(DebianDistro): class UbuntuDistro(DebianDistro): name = "Ubuntu" + os_type = "linux" def _set_media_paths(self): DebianDistro._set_media_paths(self) @@ -672,6 +686,7 @@ 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")] @@ -692,3 +707,194 @@ class MandrivaDistro(Distro): 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): + 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, smfargs, kbargs) = \ + self.process_extra_args(guest.extraargs) + + bargs = '' + if kopts: + bargs += '-' + kopts + ' -' + + if guest.graphics['enabled'] == False: + bargs += ' nowin' + + if guest.autocf: + bargs += ' install' + + if kargs: + bargs += ' ' + kargs + + if guest.location.startswith('nfs:'): + try: + guestIP = socket.gethostbyaddr(guest.name)[2][0] + except: + bargs += ' dhcp' + else: + iserver = guest.location.split(':')[1] + ipath = guest.location.split(':')[2] + iserverIP = socket.gethostbyaddr(iserver)[2][0] + bargs += " -B install_media=" + iserverIP + ":" + ipath + bargs += ",host-ip=" + guestIP + droute = util.default_route(guest.nics[0].bridge) + if droute is not None: + bargs += ",router-ip=" + droute + if guest.nics[0].macaddr is not None: + 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) + bargs += ",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] + bargs += ",sysid_config=" + acf_hostip + ":" + acf_path + bargs += ",install_config=" + acf_hostip + ":" + acf_path + except: + print "failed to lookup host %s" % acf_host + else: + bargs += " -B install_media=cdrom" + + if kbargs: + bargs += "," + kbargs + + return bargs + + 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): + kernelpath = "platform/i86xpv/kernel/unix" + initrdpath = "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, kargs, smfargs, kbargs) = \ + self.process_extra_args(guest.extraargs) + + bargs = '' + if kopts: + bargs += ' -' + kopts + if kbargs: + bargs += ' -B ' + kbargs + + return bargs + + 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.initrdpath, progresscb) + return (kernel, initrd, args) + except: + os.unlink(kernel) + raise RuntimeError(_("OpenSolaris microroot not found at %s") % + self.initrdpath) diff --git a/virtinst/ParaVirtGuest.py b/virtinst/ParaVirtGuest.py --- a/virtinst/ParaVirtGuest.py +++ b/virtinst/ParaVirtGuest.py @@ -26,7 +26,7 @@ class ParaVirtGuest(Guest): class ParaVirtGuest(Guest): def __init__(self, type=None, connection=None, hypervisorURI=None, installer=None): if not installer: - installer = DistroInstaller(type = type, os_type = "linux") + installer = DistroInstaller(type = type, virt_type = "linux") Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "xvd" diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -519,6 +519,9 @@ class VirtualDisk(VirtualDevice): if self.target: disknode = self.target + if self.device == VirtualDisk.DEVICE_CDROM and disknode.startswith('xvd'): + disknode = disknode + ':cdrom' + if not disknode: raise ValueError(_("'disknode' or self.target must be set!")) diff --git a/virtinst/osdict.py b/virtinst/osdict.py --- a/virtinst/osdict.py +++ b/virtinst/osdict.py @@ -31,6 +31,7 @@ DEFAULTS = { \ "continue": False, "distro": None, "label": None, + "pv_cdrom_install": False, "devices" : { # "devname" : { "attribute" : [( ["applicable", "hv-type", list"], # "recommended value for hv-types" ),]}, @@ -110,6 +111,7 @@ OS_TYPES = {\ "solaris": { "label": "Solaris", "clock": "localtime", + "pv_cdrom_install": True, "variants": { "solaris9": { "label": "Sun Solaris 9", }, "solaris10": { "label": "Sun Solaris 10", diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -38,7 +38,17 @@ KEYBOARD_DIR = "/etc/sysconfig/keyboard" KEYBOARD_DIR = "/etc/sysconfig/keyboard" XORG_CONF = "/etc/X11/xorg.conf" -def default_route(): +def default_route(nic = None): + if platform.system() == 'SunOS': + cmd = '/usr/bin/netstat -rn' + if nic: + cmd += ' -I %s' % nic + for i in os.popen(cmd): + line = i.split() + if len(line) > 1 and line[0] == 'default': + return line[1] + return None + route_file = "/proc/net/route" d = file(route_file) From john.levon at sun.com Thu Dec 4 04:31:39 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 03 Dec 2008 20:31:39 -0800 Subject: [et-mgmt-tools] [PATCH] Fix regression with --mac option Message-ID: <09d307f7983dc9e29be7.1228365099@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228365031 28800 # Node ID 09d307f7983dc9e29be7e1fe724ef12ade1a42a2 # Parent 152e0bfb277efb24679d7c7f440df0b0f6b21529 Fix regression with --mac option Older versions of virt-install allowed a MAC address to be specified and a default network would be created. For ease of use, if the user specifies exactly one MAC address, create a default network for it. Signed-off-by: John Levon diff --git a/virtinst/cli.py b/virtinst/cli.py --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -295,6 +295,15 @@ def digest_networks(conn, macs, bridges, 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 util.privileged_user(): + 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): From john.levon at sun.com Thu Dec 4 04:31:48 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 03 Dec 2008 20:31:48 -0800 Subject: [et-mgmt-tools] [PATCH] Add vdisk support Message-ID: <152e0bfb277efb24679d.1228365108@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228365031 28800 # Node ID 152e0bfb277efb24679d7c7f440df0b0f6b21529 # Parent 35baacfe79834400949ebdba69f952ed873ae442 Add vdisk support Add support for the vdisk format used in Solaris. Signed-off-by: John Levon diff --git a/virt-install b/virt-install --- a/virt-install +++ b/virt-install @@ -189,9 +189,13 @@ def get_disk(disk, size, sparse, guest, readOnly=readOnly, device=device, bus=bus, conn=guest.conn) # Default file backed PV guests to tap driver - if d.type == virtinst.VirtualDisk.TYPE_FILE \ - and not(hvm) and virtinst.util.is_blktap_capable(): - d.driver_name = virtinst.VirtualDisk.DRIVER_TAP + if d.type == virtinst.VirtualDisk.TYPE_FILE and not(hvm): + if virtinst.util.is_blktap_capable(): + d.driver_name = virtinst.VirtualDisk.DRIVER_TAP + elif virtinst.util.is_vdisk(path): + d.driver_name = Guest.VirtualDisk.DRIVER_TAP + d.driver_type = Guest.VirtualDisk.DRIVER_TAP_VDISK + except ValueError, e: fail(_("Error with storage parameters: %s" % str(e))) diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -19,7 +19,6 @@ # MA 02110-1301 USA. import os -import stat import libxml2 import logging import urlgrabber.progress as progress @@ -394,13 +393,9 @@ class CloneDesign(object): logging.debug("original device list: %s" % (lst)) for i in lst: - mode = os.stat(i)[stat.ST_MODE] - if stat.S_ISBLK(mode): - size.append(util.blkdev_size(i)) - typ.append(False) - elif stat.S_ISREG(mode): - size.append(os.path.getsize(i)) - typ.append(True) + (t, sz) = util.stat_disk(i) + typ.append(t) + size.append(sz) logging.debug("original device size: %s" % (size)) logging.debug("original device type: %s" % (typ)) @@ -443,18 +438,9 @@ class CloneDesign(object): typ = [] for i in cln_dev_lst: - if os.path.exists(i) == False: - size.append(0) - # if not exists, create file necessary - typ.append(True) - continue - mode = os.stat(i)[stat.ST_MODE] - if stat.S_ISBLK(mode): - size.append(util.blkdev_size(i)) - typ.append(False) - elif stat.S_ISREG(mode): - size.append(os.path.getsize(i)) - typ.append(True) + (t, sz) = util.stat_disk(i) + typ.append(t) + size.append(sz) logging.debug("clone device list: %s" % (cln_dev_lst)) logging.debug("clone device size: %s" % (size)) @@ -535,6 +521,14 @@ def _do_duplicate(design): if src_dev == "/dev/null" or src_dev == dst_dev: meter.end(size) continue + + if util.is_vdisk(src_dev) or (os.path.exists(dst_dev) and util.is_vdisk(dst_dev)): + if not util.is_vdisk(src_dev) or os.path.exists(dst_dev): + raise RuntimeError, _("copying to an existing vdisk is not supported") + if not util.vdisk_clone(src_dev, dst_dev): + raise RuntimeError, _("failed to clone disk") + continue + # # create sparse file # if a destination file exists and sparse flg is True, diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -474,6 +474,9 @@ class Installer(object): or guest.disks[0].device != VirtualDisk.DEVICE_DISK: return True + if util.is_vdisk(guest.disks[0].path): + return True + # Check for the 0xaa55 signature at the end of the MBR try: fd = os.open(guest.disks[0].path, os.O_RDONLY) diff --git a/virtinst/ImageManager.py b/virtinst/ImageManager.py --- a/virtinst/ImageManager.py +++ b/virtinst/ImageManager.py @@ -101,8 +101,13 @@ class ImageInstaller(Guest.Installer): 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 + if util.is_vdisk(p): + d.driver_name = Guest.VirtualDisk.DRIVER_TAP + d.driver_type = Guest.VirtualDisk.DRIVER_TAP_VDISK + else: + if self.boot_caps.type == "xen" and util.is_blktap_capable(): + d.driver_name = Guest.VirtualDisk.DRIVER_TAP + d.target = m.target guest._install_disks.append(d) diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -68,7 +68,9 @@ class VirtualDisk(VirtualDevice): DRIVER_TAP_RAW = "aio" DRIVER_TAP_QCOW = "qcow" DRIVER_TAP_VMDK = "vmdk" - driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, DRIVER_TAP_VMDK] + DRIVER_TAP_VDISK = "vdisk" + driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, + DRIVER_TAP_VMDK, DRIVER_TAP_VDISK] DEVICE_DISK = "disk" DEVICE_CDROM = "cdrom" @@ -424,7 +426,8 @@ class VirtualDisk(VirtualDevice): or self.vol_object): logging.debug("VirtualDisk storage exists.") - if using_path and os.path.isdir(self.path): + if (using_path and os.path.isdir(self.path) and + not util.is_vdisk(self.path)): raise ValueError, _("The path must be a file or a device," " not a directory") self.__set_dev_type() @@ -476,9 +479,24 @@ class VirtualDisk(VirtualDevice): self._set_vol_object(self.vol_install.install(meter=progresscb), validate=False) return - elif self.type == VirtualDisk.TYPE_FILE and self.path is not None \ - and not os.path.exists(self.path): + elif (self.type == VirtualDisk.TYPE_FILE and self.path is not None + and os.path.exists(self.path) and util.is_vdisk(self.path)): + self._driverName = self.DRIVER_TAP + self._driverType = self.DRIVER_TAP_VDISK + return + 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 util.is_vdisk(self.path): + progresscb.update(1024) + if (not util.vdisk_create(self.path, size_bytes, "vmdk", + 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 if progresscb: progresscb.start(filename=self.path,size=long(size_bytes), \ diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -29,6 +29,7 @@ import stat import stat import popen2 from sys import stderr +from subprocess import call import libvirt from virtinst import _virtinst as _ @@ -283,17 +284,71 @@ def xml_escape(str): str = str.replace(">", ">") return str -def blkdev_size(path): - if platform.system() == 'SunOS': - return os.stat(path)[stat.ST_SIZE] - else: - dummy, msg = commands.getstatusoutput('fdisk -s %s' % path) - # check - if msg.isdigit() == False: - lines = msg.splitlines() - # retry eg. for the GPT disk - msg = lines[len(lines)-1] - return (int(msg) * 1024) +def is_vdisk(path): + if not os.path.exists("/usr/sbin/vdiskadm"): + return False + if not os.path.exists(path): + return True + if os.path.isdir(path) and \ + os.path.exists(path + "/vdisk.xml"): + return True + 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" + args = " create -t " + type + " -s " + str(size) + " " + path + try: + rc = call("/usr/sbin/vdiskadm" + args, shell=True) + if rc != 0: + return False + return True + except OSError, e: + return False + +def vdisk_clone(path, clone): + path = os.path.expanduser(path) + clone = os.path.expanduser(clone) + args = path + " " + clone + try: + rc = call("/usr/sbin/vdiskadm clone " + args, shell=True) + if rc != 0: + return False + return True + except OSError, e: + return False + +def stat_disk(path): + """Returns the tuple (isreg, size).""" + if not os.path.exists(path): + return True, 0 + + if is_vdisk(path): + size = int(commands.getoutput( + "vdiskadm prop-get -p max-size " + path)) + return True, size + + mode = os.stat(path)[stat.ST_MODE] + if stat.S_ISBLK(mode): + if platform.system() == 'SunOS': + size = os.stat(path)[stat.ST_SIZE] + else: + dummy, msg = commands.getstatusoutput('fdisk -s %s' % path) + # check + if msg.isdigit() == False: + lines = msg.splitlines() + # retry eg. for the GPT disk + msg = lines[len(lines)-1] + size = int(msg) * 1024 + return False, size + elif stat.S_ISREG(mode): + return True, os.path.getsize(path) + + return True, 0 def compareMAC(p, q): """Compare two MAC addresses""" From berrange at redhat.com Thu Dec 4 10:40:52 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 10:40:52 +0000 Subject: [et-mgmt-tools] [PATCH] Provide a common block device size utility for Solaris & Linux In-Reply-To: <20081204032416.GB31375@totally.trollied.org.uk> References: <7069ca5b2ced261f1943.1228271139@xenbld.SFBay.Sun.COM> <20081203093755.GC18245@redhat.com> <20081204032416.GB31375@totally.trollied.org.uk> Message-ID: <20081204104052.GA24539@redhat.com> On Thu, Dec 04, 2008 at 03:24:16AM +0000, John Levon wrote: > On Wed, Dec 03, 2008 at 09:37:57AM +0000, Daniel P. Berrange wrote: > > > > +def blkdev_size(path): > > > + if platform.system() == 'SunOS': > > > + return os.stat(path)[stat.ST_SIZE] > > > + else: > > > + dummy, msg = commands.getstatusoutput('fdisk -s %s' % path) > > > + # check > > > + if msg.isdigit() == False: > > > + lines = msg.splitlines() > > > + # retry eg. for the GPT disk > > > + msg = lines[len(lines)-1] > > > + return (int(msg) * 1024) > > > > > > ACK, to the general idea of adding a common routine. The original Linux > > impl was kind of crazy. We could get a single portable impl for all > > OS by using seek(), which is how libvirt does it in its storage code. > > Quite honestly, I wasn't entirely sure why you're using fdisk. But if > you don't need to, why use lseek() when os.stat() does the job? Because stat() returns 0 for the size of block devices on many UNIX including Linux. # perl -e 'use File::stat; my $f = stat("/dev/sda1"); printf "%d\n", $f->size' 0 # perl -e 'use POSIX; my $f = POSIX::open("/dev/sda1", O_RDONLY); printf "%d\n", (POSIX::lseek $f, 0, 2)' 106896384 Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Thu Dec 4 12:00:20 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:00:20 +0000 Subject: [et-mgmt-tools] [PATCH] Fix sparse file size off-by-one error In-Reply-To: References: Message-ID: <20081204120017.GD24539@redhat.com> On Wed, Dec 03, 2008 at 07:29:02PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228360958 28800 > # Node ID d8591178ebfca87835c7c5181cd96fde303444c9 > # Parent a16f24e020cec71d5d61661a2a85e7e241ffe0be > Fix sparse file size off-by-one error > > The Solaris loopback driver (lofi) requires files be a multiple of > 512-bytes in size. Sparse files created via lseek(f, size, 0) are > 1 byte larger than what is being requested. ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Thu Dec 4 12:00:41 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:00:41 +0000 Subject: [et-mgmt-tools] [PATCH] Fix tap failure In-Reply-To: <7f39e430409182ab85ba.1228365037@xenbld.SFBay.Sun.COM> References: <7f39e430409182ab85ba.1228365037@xenbld.SFBay.Sun.COM> Message-ID: <20081204120041.GE24539@redhat.com> On Wed, Dec 03, 2008 at 08:30:37PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365022 28800 > # Node ID 7f39e430409182ab85ba39b8f74382b1f9167736 > # Parent 4082e2dd5f6eba6febc0fffa9bce7d7c04ba27fa > Fix tap failure > > VirtualDisk driver name/type need setters. ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Thu Dec 4 12:03:36 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:03:36 +0000 Subject: [et-mgmt-tools] [PATCH] Add --autocf In-Reply-To: References: Message-ID: <20081204120335.GF24539@redhat.com> On Wed, Dec 03, 2008 at 08:30:53PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365030 28800 > # Node ID d9898b68352ad1c2491a3c9697d4b34af6630fc7 > # Parent fd554fd90595417dbaadb42aecc598d586b7f99e > Add --autocf > > Add an option for passing Solaris JumpStart information. For HVM > guests, this means a floppy image (!). I think its better not to add this OS specific option. You can apass the Jumpstart floppy image using the recently added generic --disk option --disk path=/path/to/image,device=floppy Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Thu Dec 4 12:06:09 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:06:09 +0000 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: <9e299e5ee2b46b8c3b73.1228365067@xenbld.SFBay.Sun.COM> References: <9e299e5ee2b46b8c3b73.1228365067@xenbld.SFBay.Sun.COM> Message-ID: <20081204120609.GG24539@redhat.com> On Wed, Dec 03, 2008 at 08:31:07PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365030 28800 > # Node ID 9e299e5ee2b46b8c3b737d5394498a855f553bae > # Parent d9898b68352ad1c2491a3c9697d4b34af6630fc7 > Port utility functions to Solaris > > Port various utils to Solaris, and remove some unused ones that don't > work. This default NIC identification won't work when virt-install is running remotely from the virt host, but I guess the user can easily specify an explicit device in this case. > @@ -100,6 +125,9 @@ def default_connection(): > return None > > def get_cpu_flags(): > + if platform.system() == 'SunOS': > + raise OSError("CPU flags not available") > + Should make a note to kill this function entirely - libvirt capabilities XML provides this data. > -def is_kvm_capable(): > - return os.path.exists("/dev/kvm") > + if not conn: > + conn = libvirt.open('') > + return "pae" in conn.getCapabilities() Yep, this is good. ACK to this patch Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Thu Dec 4 12:06:25 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:06:25 +0000 Subject: [et-mgmt-tools] [PATCH] Solaris HVM support In-Reply-To: <7dd32b4d7915937025f4.1228365080@xenbld.SFBay.Sun.COM> References: <7dd32b4d7915937025f4.1228365080@xenbld.SFBay.Sun.COM> Message-ID: <20081204120625.GH24539@redhat.com> On Wed, Dec 03, 2008 at 08:31:20PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365030 28800 > # Node ID 7dd32b4d7915937025f42c3519711db50e5a7ce3 > # Parent 9e299e5ee2b46b8c3b737d5394498a855f553bae > Solaris HVM support > > Make 'solaris' a first-class OS type, and select USB tablet support for > the appropriate variants. ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Thu Dec 4 12:06:49 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:06:49 +0000 Subject: [et-mgmt-tools] [PATCH] Fix regression with --mac option In-Reply-To: <09d307f7983dc9e29be7.1228365099@xenbld.SFBay.Sun.COM> References: <09d307f7983dc9e29be7.1228365099@xenbld.SFBay.Sun.COM> Message-ID: <20081204120649.GI24539@redhat.com> On Wed, Dec 03, 2008 at 08:31:39PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365031 28800 > # Node ID 09d307f7983dc9e29be7e1fe724ef12ade1a42a2 > # Parent 152e0bfb277efb24679d7c7f440df0b0f6b21529 > Fix regression with --mac option > > Older versions of virt-install allowed a MAC address to be specified > and a default network would be created. For ease of use, if the user > specifies exactly one MAC address, create a default network for it. ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From levon at movementarian.org Thu Dec 4 12:06:08 2008 From: levon at movementarian.org (John Levon) Date: Thu, 4 Dec 2008 12:06:08 +0000 Subject: [et-mgmt-tools] [PATCH] Add --autocf In-Reply-To: <20081204120335.GF24539@redhat.com> References: <20081204120335.GF24539@redhat.com> Message-ID: <20081204120608.GA18063@totally.trollied.org.uk> On Thu, Dec 04, 2008 at 12:03:36PM +0000, Daniel P. Berrange wrote: > > Add --autocf > > > > Add an option for passing Solaris JumpStart information. For HVM > > guests, this means a floppy image (!). > > I think its better not to add this OS specific option. You can I don't think it's OS specific. I set up kickstart a while back and it involved a lot of magic boot options with -x, why not make it easy? > apass the Jumpstart floppy image using the recently added generic > --disk option > > --disk path=/path/to/image,device=floppy And for NFS JumpStart? regards john From levon at movementarian.org Thu Dec 4 12:09:18 2008 From: levon at movementarian.org (John Levon) Date: Thu, 4 Dec 2008 12:09:18 +0000 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: <20081204120609.GG24539@redhat.com> References: <9e299e5ee2b46b8c3b73.1228365067@xenbld.SFBay.Sun.COM> <20081204120609.GG24539@redhat.com> Message-ID: <20081204120918.GB18403@totally.trollied.org.uk> On Thu, Dec 04, 2008 at 12:06:09PM +0000, Daniel P. Berrange wrote: > > Port utility functions to Solaris > > > > Port various utils to Solaris, and remove some unused ones that don't > > work. > > This default NIC identification won't work when virt-install is running > remotely from the virt host, but I guess the user can easily specify > an explicit device in this case. Yep - it's not ideal, but there's not really a better option right now. regards john From berrange at redhat.com Thu Dec 4 12:11:39 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:11:39 +0000 Subject: [et-mgmt-tools] [PATCH] Add vdisk support In-Reply-To: <152e0bfb277efb24679d.1228365108@xenbld.SFBay.Sun.COM> References: <152e0bfb277efb24679d.1228365108@xenbld.SFBay.Sun.COM> Message-ID: <20081204121139.GJ24539@redhat.com> On Wed, Dec 03, 2008 at 08:31:48PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365031 28800 > # Node ID 152e0bfb277efb24679d7c7f440df0b0f6b21529 > # Parent 35baacfe79834400949ebdba69f952ed873ae442 > Add vdisk support > > Add support for the vdisk format used in Solaris. What exactly is vdisk ? Is this the ZFS based logical volume management ? The patch looks reasonable to me anyway, though I'd like to make a note to get these vdisk operations supported in libvirt storage APIs, since we'd like to remove all this disk munging code from virtinst APIs and replace it with libvirt storage APIs. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Thu Dec 4 12:13:31 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:13:31 +0000 Subject: [et-mgmt-tools] [PATCH] Least privilege support In-Reply-To: <2771f870b247df02b16a.1228271183@xenbld.SFBay.Sun.COM> References: <2771f870b247df02b16a.1228271183@xenbld.SFBay.Sun.COM> Message-ID: <20081204121331.GK24539@redhat.com> On Tue, Dec 02, 2008 at 06:26:23PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228271172 28800 > # Node ID 2771f870b247df02b16a4d79cdf549a1ad0132aa > # Parent a4538c6c2d6690526d80c011b46b4700c23a9ffd > Least privilege support > > On Solaris, which users can run virt-install depends on their effective > privilege set, not their effective UID. ACK this looks reasonable. Hopefully more of these checks will go away as we move code out of virtinst and into formal libvirt APIs. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From levon at movementarian.org Thu Dec 4 12:16:31 2008 From: levon at movementarian.org (John Levon) Date: Thu, 4 Dec 2008 12:16:31 +0000 Subject: [et-mgmt-tools] [PATCH] Add vdisk support In-Reply-To: <20081204121139.GJ24539@redhat.com> References: <152e0bfb277efb24679d.1228365108@xenbld.SFBay.Sun.COM> <20081204121139.GJ24539@redhat.com> Message-ID: <20081204121631.GC18403@totally.trollied.org.uk> On Thu, Dec 04, 2008 at 12:11:39PM +0000, Daniel P. Berrange wrote: > > Add vdisk support > > > > Add support for the vdisk format used in Solaris. > > What exactly is vdisk ? Is this the ZFS based logical volume > management ? vdisk is basically our tap implementation and disk management tool. (So nothing to do with zfs.) > The patch looks reasonable to me anyway, though I'd like to make a note > to get these vdisk operations supported in libvirt storage APIs, since > we'd like to remove all this disk munging code from virtinst APIs and > replace it with libvirt storage APIs. Agreed. This was a forward port from old code so we haven't had a chance to look at the storage APIs at all yet. regards john From anschneider at suse.de Thu Dec 4 12:24:06 2008 From: anschneider at suse.de (Andreas Schneider) Date: Thu, 4 Dec 2008 13:24:06 +0100 Subject: [et-mgmt-tools] [PATCH] Fix lookup pool by path In-Reply-To: <4936B21B.2040901@redhat.com> References: <200811251608.25707.anschneider@suse.de> <200812021148.00833.anschneider@suse.de> <4936B21B.2040901@redhat.com> Message-ID: <200812041324.10655.anschneider@suse.de> On Wednesday 03 December 2008 17:21:47 Cole Robinson wrote: > Andreas Schneider wrote: > > On Monday 01 December 2008 16:07:45 Cole Robinson wrote: > >> Hmm, so your pool xml lists the target directory with a trailing slash? > >> I'm not seeing that. What version of libvirt are you using, and can you > >> provide the pools xml? > > > > Hi, > > > > I'm using virt-manager to connect to a remote host, so if I create a pool > > I have to specify the path to the pool manually. > > > > This means you can enter as many trailing slashes as you want. So the > > questions is, should the slashes be stripped during the creation of the > > pool too? > > > > > > tmp > > 17e0c17a-3cd3-bc20-f1bc-7c9ffaceb255 > > 0 > > 0 > > 0 > > > > > > > > /var/lib/libvirt/images/tmp///// > > > > 0700 > > 0 > > 0 > > > > > > > > Hmm, yes, seems like libvirt should be sanitizing the target path when > the pool is defined (though virtinst could certainly do this too). > > Looks like there could be arbitrary '/' in the middle of the path > though, so if you use something like os.path.abspath in your patch it > should sanitize everything appropriately. Thanks, this was the function I was looking for. I've attached an updated patch. I think it should be fixed in libvirt and virt-manager. Just to be sure that you can't run into the problem again. > > Thank, > Cole Cheers, -- andreas -- Andreas Schneider, SUSE Labs, http://www.suse.de/ SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nuernberg) -------------- next part -------------- A non-text attachment was scrubbed... Name: virtinst-0.400.0-fix-pool-lookup-by-path.patch Type: text/x-patch Size: 634 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 197 bytes Desc: This is a digitally signed message part. URL: From berrange at redhat.com Thu Dec 4 12:26:09 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:26:09 +0000 Subject: [et-mgmt-tools] [PATCH] Add --autocf In-Reply-To: <20081204120608.GA18063@totally.trollied.org.uk> References: <20081204120335.GF24539@redhat.com> <20081204120608.GA18063@totally.trollied.org.uk> Message-ID: <20081204122609.GL24539@redhat.com> On Thu, Dec 04, 2008 at 12:06:08PM +0000, John Levon wrote: > On Thu, Dec 04, 2008 at 12:03:36PM +0000, Daniel P. Berrange wrote: > > > > Add --autocf > > > > > > Add an option for passing Solaris JumpStart information. For HVM > > > guests, this means a floppy image (!). > > > > I think its better not to add this OS specific option. You can > > I don't think it's OS specific. I set up kickstart a while back and it > involved a lot of magic boot options with -x, why not make it easy? > > > apass the Jumpstart floppy image using the recently added generic > > --disk option > > > > --disk path=/path/to/image,device=floppy > > And for NFS JumpStart? How is that info passed down into the XML ? Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From berrange at redhat.com Thu Dec 4 12:37:00 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 4 Dec 2008 12:37:00 +0000 Subject: [et-mgmt-tools] [PATCH] Add support for Solaris PV In-Reply-To: <35baacfe79834400949e.1228365088@xenbld.SFBay.Sun.COM> References: <35baacfe79834400949e.1228365088@xenbld.SFBay.Sun.COM> Message-ID: <20081204123700.GM24539@redhat.com> On Wed, Dec 03, 2008 at 08:31:28PM -0800, john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365031 28800 > # Node ID 35baacfe79834400949ebdba69f952ed873ae442 > # Parent 7dd32b4d7915937025f42c3519711db50e5a7ce3 > Add support for Solaris PV > > Solaris PV comes in two flavours: Nevada and OpenSolaris. In order to > correctly build network installs for Nevada, we need to pass down guest > options into OSDistro. > > os_type was horribly overloaded between the Installer and Guest classes, > meaning two different things ('solaris' or 'hvm'). Clean this up by > naming the latter 'virt_type'. The new Installer class for Solaris looks fine to me, but I don't really like the renaming of os_type to virt_type, since its conflicting naming to the libvirt usage. 'virt type' is usually used to refer to hypervisor type, eg this bit of the XML While 'os type' is used to refer to the Operating System guest ABI linux (badly named, should really be 'xen' but this is more compatible with older libvirt) hvm (native fully virt) uml (User mode linux) Unfortunaltey the virt-install CLI flag is --os-type - should really have been --os-distro-type. So I think I'd rather we changed the insternal variables for this to be os_distro_type and os_distro_variant > @@ -239,26 +249,29 @@ class DistroInstaller(Guest.Installer): > arch = os.uname()[4] > if hasattr(guest, "arch"): > arch = guest.arch > - (kernelfn, initrdfn, args) = acquireKernel(self.location, > - meter, > - scratchdir = self.scratchdir, > - type = self.os_type, > - distro = distro, > - arch=arch) > + > + (kernelfn, initrdfn, args), os_type = \ > + self._acquire_kernel(guest, meter, distro = distro, arch = arch) > + > + guest.os_type = os_type > self.install["kernel"] = kernelfn > self.install["initrd"] = initrdfn > - if not self.extraargs is None: > - self.install["extraargs"] = self.extraargs + " " + args > - else: > - self.install["extraargs"] = args > + self.install["extraargs"] = args This chunk looks a little questionable to me - IIRC this is reverting a fix we previously made, so perhaps this is just a merge error. Baiscally the existing "extraargs" data will contain params from --extra-args command line flag, and the 'self.extraargs' needs to append more data provided by the DistroInstaller class, such as kickstart URL. This change means we loose the former. > @@ -172,18 +174,21 @@ class Distro: > > return False > > - def _kernelFetchHelper(self, fetcher, progresscb, kernelpath, initrdpath): > + 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) > - if fetcher.location.startswith("/"): > - # Local host path, so can't pass a location to guest > - #for install method > - return (kernel, initrd, "") > - else: > - return (kernel, initrd, "method=" + fetcher.location) > + return kernel, initrd, args Hmm, this existing code was dubious even before this change. method= is the Fedora / RHEL anaconda syntax for specifying install location. It should never havebeen in Distro class in the first place - instead it belongs in the RedHatDistro subclass. > @@ -692,3 +707,194 @@ class MandrivaDistro(Distro): > > 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): > + 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, smfargs, kbargs) = \ > + self.process_extra_args(guest.extraargs) > + > + bargs = '' > + if kopts: > + bargs += '-' + kopts + ' -' > + > + if guest.graphics['enabled'] == False: > + bargs += ' nowin' > + > + if guest.autocf: > + bargs += ' install' > + > + if kargs: > + bargs += ' ' + kargs > + > + if guest.location.startswith('nfs:'): > + try: > + guestIP = socket.gethostbyaddr(guest.name)[2][0] > + except: > + bargs += ' dhcp' > + else: > + iserver = guest.location.split(':')[1] > + ipath = guest.location.split(':')[2] > + iserverIP = socket.gethostbyaddr(iserver)[2][0] > + bargs += " -B install_media=" + iserverIP + ":" + ipath > + bargs += ",host-ip=" + guestIP > + droute = util.default_route(guest.nics[0].bridge) > + if droute is not None: > + bargs += ",router-ip=" + droute > + if guest.nics[0].macaddr is not None: > + 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) > + bargs += ",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] > + bargs += ",sysid_config=" + acf_hostip + ":" + acf_path > + bargs += ",install_config=" + acf_hostip + ":" + acf_path > + except: > + print "failed to lookup host %s" % acf_host > + else: > + bargs += " -B install_media=cdrom" > + > + if kbargs: > + bargs += "," + kbargs > + > + return bargs > + > + 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): > + kernelpath = "platform/i86xpv/kernel/unix" > + initrdpath = "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, kargs, smfargs, kbargs) = \ > + self.process_extra_args(guest.extraargs) > + > + bargs = '' > + if kopts: > + bargs += ' -' + kopts > + if kbargs: > + bargs += ' -B ' + kbargs > + > + return bargs > + > + 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.initrdpath, progresscb) > + return (kernel, initrd, args) > + except: > + os.unlink(kernel) > + raise RuntimeError(_("OpenSolaris microroot not found at %s") % > + self.initrdpath) These new classes seeem to be more or less independant of the bit os_type/virt_type renaming (baring the obvious fact that it uses the new names). I've no problem add this bit right away. > diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py > --- a/virtinst/VirtualDisk.py > +++ b/virtinst/VirtualDisk.py > @@ -519,6 +519,9 @@ class VirtualDisk(VirtualDevice): > > if self.target: > disknode = self.target > + if self.device == VirtualDisk.DEVICE_CDROM and disknode.startswith('xvd'): > + disknode = disknode + ':cdrom' > + This seems wrong - you should not pass "xvda:cdrom" into the libvirt XML for a disk. There is an explicit attribute for specifying CDROM media Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From levon at movementarian.org Thu Dec 4 13:00:54 2008 From: levon at movementarian.org (John Levon) Date: Thu, 4 Dec 2008 13:00:54 +0000 Subject: [et-mgmt-tools] [PATCH] Add --autocf In-Reply-To: <20081204122609.GL24539@redhat.com> References: <20081204120335.GF24539@redhat.com> <20081204120608.GA18063@totally.trollied.org.uk> <20081204122609.GL24539@redhat.com> Message-ID: <20081204130054.GA20966@totally.trollied.org.uk> On Thu, Dec 04, 2008 at 12:26:09PM +0000, Daniel P. Berrange wrote: > > And for NFS JumpStart? > > How is that info passed down into the XML ? As cmdline args, much like kickstart. regards john From sakaia at jp.fujitsu.com Thu Dec 4 12:41:19 2008 From: sakaia at jp.fujitsu.com (Atsushi SAKAI) Date: Thu, 04 Dec 2008 21:41:19 +0900 Subject: [et-mgmt-tools] [PATCH] Least privilege support In-Reply-To: <2771f870b247df02b16a.1228271183@xenbld.SFBay.Sun.COM> References: <2771f870b247df02b16a.1228271183@xenbld.SFBay.Sun.COM> Message-ID: <20081204124120.BB4B248001A@m023.s.css.fujitsu.com> Hi, John I have a question about this patch. (because of my understanding) It seems check "SunOS" only for Solaris. (It will be added some code in future?) Thanks Atsushi SAKAI john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228271172 28800 > # Node ID 2771f870b247df02b16a4d79cdf549a1ad0132aa > # Parent a4538c6c2d6690526d80c011b46b4700c23a9ffd > Least privilege support > > On Solaris, which users can run virt-install depends on their effective > privilege set, not their effective UID. > > Signed-off-by: John Levon > > diff --git a/virt-clone b/virt-clone > --- a/virt-clone > +++ b/virt-clone > @@ -185,7 +185,7 @@ def main(): > logging.debug("start clone with HV " + options.connect) > > if options.connect is None or options.connect.lower()[0:3] == "xen": > - if os.geteuid() != 0: > + if not virtinst.util.privileged_user(): > fail(_("Must be root to clone Xen guests")) > > conn = cli.getConnection(options.connect) > diff --git a/virtinst/DistroManager.py b/virtinst/DistroManager.py > --- a/virtinst/DistroManager.py > +++ b/virtinst/DistroManager.py > @@ -193,7 +193,7 @@ class DistroInstaller(Guest.Installer): > "or FTP network install source, or an existing " > "local file/device")) > > - if os.geteuid() != 0 and val.startswith("nfs:"): > + if val.startswith("nfs:") and not util.privileged_user(): > raise ValueError(_("NFS installations are only supported as root")) > > self._location = val > diff --git a/virtinst/Guest.py b/virtinst/Guest.py > --- a/virtinst/Guest.py > +++ b/virtinst/Guest.py > @@ -28,6 +28,7 @@ import urlgrabber.progress as progress > import urlgrabber.progress as progress > import util > import libvirt > +import platform > import __builtin__ > import CapabilitiesParser > import VirtualDevice > @@ -347,9 +348,11 @@ class Installer(object): > os_type = property(get_os_type, set_os_type) > > def get_scratchdir(self): > + if platform.system() == 'SunOS': > + return '/var/tmp' > if self.type == "xen" and os.path.exists(XEN_SCRATCH): > return XEN_SCRATCH > - if os.getuid() == 0 and os.path.exists(LIBVIRT_SCRATCH): > + if util.privileged_user() and os.path.exists(LIBVIRT_SCRATCH): > return LIBVIRT_SCRATCH > else: > return os.path.expanduser("~/.virtinst/boot") > @@ -476,7 +479,7 @@ class Installer(object): > fd = os.open(guest.disks[0].path, os.O_RDONLY) > except OSError, (err, msg): > logging.debug("Failed to open guest disk: %s" % msg) > - if err == errno.EACCES and os.geteuid() != 0: > + if err == errno.EACCES and not util.privileged_user(): > return True # non root might not have access to block devices > else: > raise > diff --git a/virtinst/cli.py b/virtinst/cli.py > --- a/virtinst/cli.py > +++ b/virtinst/cli.py > @@ -118,7 +118,7 @@ def nice_exit(): > > def getConnection(connect): > if connect and connect.lower()[0:3] == "xen": > - if os.geteuid() != 0: > + if not util.privileged_user(): > fail(_("Must be root to create Xen guests")) > if connect is None: > fail(_("Could not find usable default libvirt connection.")) > @@ -307,7 +307,7 @@ def digest_networks(conn, macs, bridges, > # Create extra networks up to the number of nics requested > if len(macs) < nics: > for dummy in range(len(macs),nics): > - if os.getuid() == 0: > + if util.privileged_user(): > net = util.default_network(conn) > networks.append(net[0] + ":" + net[1]) > else: > diff --git a/virtinst/util.py b/virtinst/util.py > --- a/virtinst/util.py > +++ b/virtinst/util.py > @@ -93,7 +93,7 @@ def default_connection(): > os.path.exists("/usr/bin/qemu-kvm") or \ > os.path.exists("/usr/bin/kvm") or \ > os.path.exists("/usr/bin/xenner"): > - if os.getuid() == 0: > + if privileged_user(): > return "qemu:///system" > else: > return "qemu:///session" > @@ -509,6 +509,14 @@ def lookup_pool_by_path(conn, path): > return pool > return None > > +def privileged_user(): > + """ > + Return true if the user is privileged enough. On Linux, this > + equates to being root. On Solaris, it's more complicated, so we > + just assume we're OK. > + """ > + return os.uname()[0] == 'SunOS' or os.geteuid() == 0 > + > def _test(): > import doctest > doctest.testmod() > > _______________________________________________ > et-mgmt-tools mailing list > et-mgmt-tools at redhat.com > https://www.redhat.com/mailman/listinfo/et-mgmt-tools From levon at movementarian.org Thu Dec 4 13:12:15 2008 From: levon at movementarian.org (John Levon) Date: Thu, 4 Dec 2008 13:12:15 +0000 Subject: [et-mgmt-tools] [PATCH] Add support for Solaris PV In-Reply-To: <20081204123700.GM24539@redhat.com> References: <35baacfe79834400949e.1228365088@xenbld.SFBay.Sun.COM> <20081204123700.GM24539@redhat.com> Message-ID: <20081204131215.GC20966@totally.trollied.org.uk> On Thu, Dec 04, 2008 at 12:37:00PM +0000, Daniel P. Berrange wrote: > The new Installer class for Solaris looks fine to me, but I don't really > like the renaming of os_type to virt_type, since its conflicting naming > to the libvirt usage. > > 'virt type' is usually used to refer to hypervisor type, eg this bit > of the XML > > > > How confusing. Wouldn't this be 'hyp_type' ? > Unfortunaltey the virt-install CLI flag is --os-type - should really > have been --os-distro-type. So I think I'd rather we changed the > insternal variables for this to be os_distro_type and os_distro_variant I can do this though. Anything but the current mess :) > > - if not self.extraargs is None: > > - self.install["extraargs"] = self.extraargs + " " + args > > - else: > > - self.install["extraargs"] = args > > + self.install["extraargs"] = args > > This chunk looks a little questionable to me - IIRC this is reverting a fix > we previously made, so perhaps this is just a merge error. Hmm, no, this is intentional. Solaris needs to do all sorts of mangling of extra args passed in. It's now the responsibility of the OSDistro to handle .extraargs - see the change to _kernelHelper or whatever it's called. We can't just do the pre-pending of extra args. > > + > > + if not fetcher.location.startswith("/"): > > + args += "method=" + fetcher.location > > + > > + if guest.extraargs: > > + args += guest.extraargs > > + > > try: > > initrd = fetcher.acquireFile(initrdpath, progresscb) > > - if fetcher.location.startswith("/"): > > - # Local host path, so can't pass a location to guest > > - #for install method > > - return (kernel, initrd, "") > > - else: > > - return (kernel, initrd, "method=" + fetcher.location) > > + return kernel, initrd, args > > Hmm, this existing code was dubious even before this change. method= is > the Fedora / RHEL anaconda syntax for specifying install location. It > should never havebeen in Distro class in the first place - instead it > belongs in the RedHatDistro subclass. This seems like a change to be made separately. > These new classes seeem to be more or less independant of the bit > os_type/virt_type renaming (baring the obvious fact that it uses the > new names). I've no problem add this bit right away. If you like, I can split out the os_type renaming as a separate patch. > > if self.target: > > disknode = self.target > > + if self.device == VirtualDisk.DEVICE_CDROM and disknode.startswith('xvd'): > > + disknode = disknode + ':cdrom' > > + > > This seems wrong - you should not pass "xvda:cdrom" into the libvirt > XML for a disk. There is an explicit attribute for specifying CDROM > media Ack. regards john From levon at movementarian.org Thu Dec 4 13:26:33 2008 From: levon at movementarian.org (John Levon) Date: Thu, 4 Dec 2008 13:26:33 +0000 Subject: [et-mgmt-tools] [PATCH] Least privilege support In-Reply-To: <20081204124120.BB4B248001A@m023.s.css.fujitsu.com> References: <2771f870b247df02b16a.1228271183@xenbld.SFBay.Sun.COM> <20081204124120.BB4B248001A@m023.s.css.fujitsu.com> Message-ID: <20081204132633.GD20966@totally.trollied.org.uk> On Thu, Dec 04, 2008 at 09:41:19PM +0900, Atsushi SAKAI wrote: > I have a question about this patch. > (because of my understanding) > > It seems check "SunOS" only for Solaris. > (It will be added some code in future?) Possibly. There's no generally available Python interface to test for effective Solaris privileges right now. regards john From agx at sigxcpu.org Thu Dec 4 19:33:54 2008 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Thu, 4 Dec 2008 20:33:54 +0100 Subject: [et-mgmt-tools] [PATCH] virt-manager: allow non root users for ssh:// Message-ID: <20081204193354.GA11430@bogon.ms20.nix> Hi, attached patch allows to specify a user with user at host for ssh connections in the "Add connection..." dialog. This has been requested e.g. in: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=505936 Cheers, -- Guido From agx at sigxcpu.org Thu Dec 4 19:35:20 2008 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Thu, 4 Dec 2008 20:35:20 +0100 Subject: [et-mgmt-tools] Re: [PATCH] virt-manager: allow non root users for ssh:// In-Reply-To: <20081204193354.GA11430@bogon.ms20.nix> References: <20081204193354.GA11430@bogon.ms20.nix> Message-ID: <20081204193520.GA11484@bogon.ms20.nix> On Thu, Dec 04, 2008 at 08:33:54PM +0100, Guido G?nther wrote: > Hi, > attached patch allows to specify a user with user at host for ssh > connections in the "Add connection..." dialog. This has been requested > e.g. in: > http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=505936 Patch attached now. -- Guido -------------- next part -------------- A non-text attachment was scrubbed... Name: ssh_non_root.diff Type: text/x-diff Size: 1464 bytes Desc: not available URL: From garyyuen at gmail.com Fri Dec 5 04:52:24 2008 From: garyyuen at gmail.com (Gary Yuen) Date: Fri, 5 Dec 2008 12:52:24 +0800 Subject: [et-mgmt-tools] Cft - getting started Message-ID: <13011f570812042052h4354efa1u875ccbcc1fd948d3@mail.gmail.com> Hello, I'm trying to get started with Cft. It looks terrific and is another reason I'm trying to migrate away from Debian. On a CentOS system running Xen, I'm getting the following error: [root at host init.d]# cft begin puppet /usr/lib/ruby/site_ruby/1.8/puppet/util/inifile.rb:199:in `add_section': A section with name xen already exists (RuntimeError) from /usr/lib/ruby/site_ruby/1.8/puppet/util/inifile.rb:130:in `read' from /usr/lib/ruby/site_ruby/1.8/puppet/util/inifile.rb:113:in `each_line' from /usr/lib/ruby/site_ruby/1.8/puppet/util/inifile.rb:113:in `read' from /usr/lib/ruby/site_ruby/1.8/puppet/type/yumrepo.rb:147:in `read' from /usr/lib/ruby/site_ruby/1.8/puppet/type/yumrepo.rb:145:in `each' from /usr/lib/ruby/site_ruby/1.8/puppet/type/yumrepo.rb:145:in `read' from /usr/lib/ruby/site_ruby/1.8/puppet/type/yumrepo.rb:144:in `each' from /usr/lib/ruby/site_ruby/1.8/puppet/type/yumrepo.rb:144:in `read' from /usr/lib/ruby/site_ruby/1.8/puppet/type/yumrepo.rb:106:in `inifile' from /usr/lib/ruby/site_ruby/1.8/puppet/type/yumrepo.rb:86:in `instances' from /usr/lib/ruby/site_ruby/1.8/cft/puppet.rb:19:in `genstate' from /usr/lib/ruby/site_ruby/1.8/cft/puppet.rb:8:in `each' from /usr/lib/ruby/site_ruby/1.8/cft/puppet.rb:8:in `genstate' from /usr/lib/ruby/site_ruby/1.8/cft/commands.rb:178:in `execute' from /usr/lib/ruby/site_ruby/1.8/cft/commands.rb:148:in `execute' from /usr/sbin/cft:7 Gary -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.levon at sun.com Fri Dec 5 13:37:42 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Fri, 05 Dec 2008 05:37:42 -0800 Subject: [et-mgmt-tools] [PATCH] Provide a common block device size utility for Solaris & Linux Message-ID: <89668fd908b8ee8dc8fd.1228484262@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228484251 28800 # Node ID 89668fd908b8ee8dc8fd54d89888037d8845e8d2 # Parent 862a53870d43aaa9b65d7afadaed999ca4349fea Provide a common block device size utility for Solaris & Linux. Signed-off-by: John Danielson diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -24,7 +24,6 @@ import logging import logging import urlgrabber.progress as progress import util -import commands import libvirt import Guest from VirtualDisk import VirtualDisk @@ -397,13 +396,7 @@ class CloneDesign(object): for i in lst: mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - dummy, msg = commands.getstatusoutput('fdisk -s %s' % i) - # check - if msg.isdigit() == False: - lines = msg.splitlines() - # retry eg. for the GPT disk - msg = lines[len(lines)-1] - size.append(int(msg) * 1024) + size.append(util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) @@ -457,13 +450,7 @@ class CloneDesign(object): continue mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - dummy, msg = commands.getstatusoutput('fdisk -s %s' % i) - # check - if msg.isdigit() == False: - lines = msg.splitlines() - # retry eg. for the GPT disk - msg = lines[len(lines)-1] - size.append(int(msg) * 1024) + size.append(util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -257,6 +257,15 @@ def xml_escape(str): str = str.replace("<", "<") str = str.replace(">", ">") return str + +def blkdev_size(path): + """Return the size of the block device. We can't use os.stat() as + that returns zero on many platforms.""" + fd = os.open(path, os.O_RDONLY) + # os.SEEK_END is not present on all systems + size = os.lseek(fd, 0, 2) + os.close(fd) + return size def compareMAC(p, q): """Compare two MAC addresses""" From john.levon at sun.com Fri Dec 5 13:38:09 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Fri, 05 Dec 2008 05:38:09 -0800 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris Message-ID: <271ceb01335da50c05fe.1228484289@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228484283 28800 # Node ID 271ceb01335da50c05fe6c2f54f3eb1721f51bb4 # Parent 8ad095a908ad89a0c83c94bd486647b79817acbe Port utility functions to Solaris Port various utils to Solaris, and remove some unused ones that don't work. Signed-off-by: John Levon diff --git a/virtinst/FullVirtGuest.py b/virtinst/FullVirtGuest.py --- a/virtinst/FullVirtGuest.py +++ b/virtinst/FullVirtGuest.py @@ -38,7 +38,8 @@ class FullVirtGuest(Guest): installer = DistroManager.DistroInstaller(type = type, os_type = "hvm") Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "hd" - self.features = { "acpi": None, "pae": util.is_pae_capable(), "apic": None } + self.features = { "acpi": None, "pae": + util.is_pae_capable(connection), "apic": None } if arch is None: arch = platform.machine() self.arch = arch diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -25,6 +25,7 @@ import re import re import libxml2 import logging +import popen2 from sys import stderr import libvirt @@ -54,8 +55,29 @@ def default_route(): continue return None -# Legacy for compat only. +def default_nic(): + """Return the default NIC to use, if one is specified.""" + + dev = '' + + if platform.system() != 'SunOS': + return dev + + # XXX: fails without PRIV_XVM_CONTROL + proc = popen2.Popen3(["/usr/lib/xen/bin/xenstore-read", + "device-misc/vif/default-nic"], capturestderr=True) + proc.tochild.close() + proc.wait() + out = proc.fromchild.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 @@ -68,6 +90,9 @@ def default_bridge(): 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()): @@ -98,6 +123,9 @@ def default_connection(): 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() @@ -111,31 +139,16 @@ def get_cpu_flags(): return flst return [] -def is_pae_capable(): +def is_pae_capable(conn): """Determine if a machine is PAE capable or not.""" - flags = get_cpu_flags() - if "pae" in flags: - return True - return False - -def is_hvm_capable(): - """Determine if a machine is HVM capable or not.""" - - 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") + if not conn: + conn = libvirt.open('') + return "pae" in conn.getCapabilities() def is_blktap_capable(): - #return os.path.exists("/dev/xen/blktapctrl") + if platform.system() == 'SunOS': + return False + f = open("/proc/modules") lines = f.readlines() f.close() From Gary.Pennington at sun.com Fri Dec 5 14:03:41 2008 From: Gary.Pennington at sun.com (Gary Pennington) Date: Fri, 5 Dec 2008 14:03:41 +0000 Subject: [et-mgmt-tools] Xen, Windows 2003 and APIC Message-ID: <20081205140341.GD29148@barman.uk.sun.com> Hi, I've been investigating networking performance for Windows 2003 guests on a Solaris dom0 and I've uncovered a couple of things which I don't really understand and I'm looking for some explanations. This first question is really directed at virtinst developers... Windows guests have different ACPI and APIC settings depending on which variant of Windows is to be installed: variant: unspecified -> ACPI: true, APIC: true variant: winxp -> ACPI: false, APIC: false variant: win2k -> ACPI: false, APIC: false variant: win2k3 -> ACPI: true, APIC: true variant: vista -> ACPI: true, APIC: true The question is: why don't all Windows variants have the same ACPI and APIC settings? The reason I'm curious, is that it seems like different combinations of APIC and ACPI produce different functionality in the guest and different levels of performance. I did some tests with win2k3 guests and measured networking performance using iperf. I used the same dom0 system (snv_103) and created three W2K3 guests, each with 1 CPU but different APIC and ACPI settings: apic/acpi setting results (Mb/s throughput) apic: 0 acpi: 0 834, 833 apic: 1 acpi: 1 718, 704 apic: 0 acpi: 1 872, 876 (higher numbers are better) I only had time to perform two runs (the test is the iperf-2.0.2 1MB msg test that I ran to microbenchmark TCP performance) for each guest, but you can see that there is a fairly large and consistent (across two runs for each guest) performance difference. It's about 20% faster when apic is not specified for the guest. My next question is: What is really happening when APIC is specified for a windows guest and why does performance vary so much according to whether it's specified or not? Thanks for any help or insight anyone can offer. Gary -- Gary Pennington Solaris Core OS Sun Microsystems Gary.Pennington at sun.com From Gary.Pennington at sun.com Fri Dec 5 16:57:19 2008 From: Gary.Pennington at sun.com (Gary Pennington) Date: Fri, 5 Dec 2008 16:57:19 +0000 Subject: [et-mgmt-tools] Re: [Xen-devel] Xen, Windows 2003 and APIC In-Reply-To: References: <20081205140341.GD29148@barman.uk.sun.com> Message-ID: <20081205165719.GI29148@barman.uk.sun.com> On Fri, Dec 05, 2008 at 04:42:57PM +0000, George Dunlap wrote: > IIRC, only w2k3sp2+, vista, and w2k8 have lazy TPR. Not positive > about w2k3sp1, but I think it doesn't. WinXP does not have lazy TPR > in any service pack, AFAIK. > > What service pack of w2k3 did you do those tests with? > I'm not sure, because the ISO was provided by a colleague. I think it's the original release of w2k3, with no service packs. However, what I was mostly curious about was why specifying apic when the guest was created made so much different to performance. Gary > Hopefully, sometime in the next few weeks, I'll be able to release my > 'xenalyze' tool, which will help a lot with analyzing what's really > going on with these kinds of workloads. > > -George > > On Fri, Dec 5, 2008 at 2:45 PM, Keir Fraser wrote: > > On 05/12/2008 14:03, "Gary Pennington" wrote: > > > >> My next question is: What is really happening when APIC is specified for > >> a windows guest and why does performance vary so much according to whether > >> it's specified or not? > > > > Older Windows kernels update the APIC TPR a lot, and unless you have a very > > modern Intel processor every one of those TPR updates causes a vmexit. > > > > Modern Windows (including possibly latest w2k3 service pack, but I'm not > > totally certain) includes lazy TPR, which gets rid of the vast majority of > > TPR updates, and hence will go much faster. > > > > -- Keir > > > > > > > > _______________________________________________ > > Xen-devel mailing list > > Xen-devel at lists.xensource.com > > http://lists.xensource.com/xen-devel > > > > _______________________________________________ > Xen-devel mailing list > Xen-devel at lists.xensource.com > http://lists.xensource.com/xen-devel -- Gary Pennington Solaris Core OS Sun Microsystems Gary.Pennington at sun.com From crobinso at redhat.com Sun Dec 7 04:19:54 2008 From: crobinso at redhat.com (Cole Robinson) Date: Sat, 06 Dec 2008 23:19:54 -0500 Subject: [et-mgmt-tools] [PATCH] Fix lookup pool by path In-Reply-To: <200812041324.10655.anschneider@suse.de> References: <200811251608.25707.anschneider@suse.de> <200812021148.00833.anschneider@suse.de> <4936B21B.2040901@redhat.com> <200812041324.10655.anschneider@suse.de> Message-ID: <493B4EEA.3000306@redhat.com> Andreas Schneider wrote: > On Wednesday 03 December 2008 17:21:47 Cole Robinson wrote: > >> >> Hmm, yes, seems like libvirt should be sanitizing the target path when >> the pool is defined (though virtinst could certainly do this too). >> >> Looks like there could be arbitrary '/' in the middle of the path >> though, so if you use something like os.path.abspath in your patch it >> should sanitize everything appropriately. >> > > Thanks, this was the function I was looking for. I've attached an updated > patch. I think it should be fixed in libvirt and virt-manager. Just to be sure > that you can't run into the problem again. > Agreed on the above point. I've committed your fix now: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=b66d39a23988 Thanks for the contribution! - Cole From crobinso at redhat.com Sun Dec 7 04:21:49 2008 From: crobinso at redhat.com (Cole Robinson) Date: Sat, 06 Dec 2008 23:21:49 -0500 Subject: [et-mgmt-tools] [PATCH] Fix sparse file size off-by-one error In-Reply-To: References: Message-ID: <493B4F5D.1030206@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228360958 28800 > # Node ID d8591178ebfca87835c7c5181cd96fde303444c9 > # Parent a16f24e020cec71d5d61661a2a85e7e241ffe0be > Fix sparse file size off-by-one error > > The Solaris loopback driver (lofi) requires files be a multiple of > 512-bytes in size. Sparse files created via lseek(f, size, 0) are > 1 byte larger than what is being requested. > > Signed-off-by: John Danielson > > Thanks, Applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=ed58873b537c - Cole From crobinso at redhat.com Sun Dec 7 04:22:36 2008 From: crobinso at redhat.com (Cole Robinson) Date: Sat, 06 Dec 2008 23:22:36 -0500 Subject: [et-mgmt-tools] [PATCH] Provide a common block device size utility for Solaris & Linux In-Reply-To: <89668fd908b8ee8dc8fd.1228484262@xenbld.SFBay.Sun.COM> References: <89668fd908b8ee8dc8fd.1228484262@xenbld.SFBay.Sun.COM> Message-ID: <493B4F8C.7080407@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228484251 28800 > # Node ID 89668fd908b8ee8dc8fd54d89888037d8845e8d2 > # Parent 862a53870d43aaa9b65d7afadaed999ca4349fea > Provide a common block device size utility for Solaris & Linux. > > Signed-off-by: John Danielson > > Thanks, applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=13390c95ae0a - Cole From crobinso at redhat.com Sun Dec 7 04:24:04 2008 From: crobinso at redhat.com (Cole Robinson) Date: Sat, 06 Dec 2008 23:24:04 -0500 Subject: [et-mgmt-tools] [PATCH] Least privilege support In-Reply-To: <2771f870b247df02b16a.1228271183@xenbld.SFBay.Sun.COM> References: <2771f870b247df02b16a.1228271183@xenbld.SFBay.Sun.COM> Message-ID: <493B4FE4.4080306@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228271172 28800 > # Node ID 2771f870b247df02b16a4d79cdf549a1ad0132aa > # Parent a4538c6c2d6690526d80c011b46b4700c23a9ffd > Least privilege support > > On Solaris, which users can run virt-install depends on their effective > privilege set, not their effective UID. > > Signed-off-by: John Levon > > Thanks, applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=4ff5f60b8f52 - Cole From crobinso at redhat.com Sun Dec 7 04:24:59 2008 From: crobinso at redhat.com (Cole Robinson) Date: Sat, 06 Dec 2008 23:24:59 -0500 Subject: [et-mgmt-tools] [PATCH] Fix tap failure In-Reply-To: <7f39e430409182ab85ba.1228365037@xenbld.SFBay.Sun.COM> References: <7f39e430409182ab85ba.1228365037@xenbld.SFBay.Sun.COM> Message-ID: <493B501B.1060100@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365022 28800 > # Node ID 7f39e430409182ab85ba39b8f74382b1f9167736 > # Parent 4082e2dd5f6eba6febc0fffa9bce7d7c04ba27fa > Fix tap failure > > VirtualDisk driver name/type need setters. > > Signed-off-by: John Levon > > > Thanks, applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=e9148dda8c9c - Cole From crobinso at redhat.com Sun Dec 7 04:43:11 2008 From: crobinso at redhat.com (Cole Robinson) Date: Sat, 06 Dec 2008 23:43:11 -0500 Subject: [et-mgmt-tools] [PATCH] Fix regression with --mac option In-Reply-To: <09d307f7983dc9e29be7.1228365099@xenbld.SFBay.Sun.COM> References: <09d307f7983dc9e29be7.1228365099@xenbld.SFBay.Sun.COM> Message-ID: <493B545F.501@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365031 28800 > # Node ID 09d307f7983dc9e29be7e1fe724ef12ade1a42a2 > # Parent 152e0bfb277efb24679d7c7f440df0b0f6b21529 > Fix regression with --mac option > > Older versions of virt-install allowed a MAC address to be specified > and a default network would be created. For ease of use, if the user > specifies exactly one MAC address, create a default network for it. > > Signed-off-by: John Levon > > Thanks, applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=2707387564df - Cole From crobinso at redhat.com Sun Dec 7 05:07:55 2008 From: crobinso at redhat.com (Cole Robinson) Date: Sun, 07 Dec 2008 00:07:55 -0500 Subject: [et-mgmt-tools] [PATCH] Solaris HVM support In-Reply-To: <7dd32b4d7915937025f4.1228365080@xenbld.SFBay.Sun.COM> References: <7dd32b4d7915937025f4.1228365080@xenbld.SFBay.Sun.COM> Message-ID: <493B5A2B.3020106@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365030 28800 > # Node ID 7dd32b4d7915937025f42c3519711db50e5a7ce3 > # Parent 9e299e5ee2b46b8c3b737d5394498a855f553bae > Solaris HVM support > > Make 'solaris' a first-class OS type, and select USB tablet support for > the appropriate variants. > > Signed-off-by: John Levon > > Thanks, applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=f6d8999365a9 Though this needed some extra work to be back compatible with the previous OS dictionary layout (virt-install --os-type unix --os-variant solaris9 would now be busted.) I committed a fix for this: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=419fb59763dc - Cole From john.levon at sun.com Sun Dec 7 16:29:36 2008 From: john.levon at sun.com (John Levon) Date: Sun, 7 Dec 2008 16:29:36 +0000 Subject: [et-mgmt-tools] [PATCH] Solaris HVM support In-Reply-To: <493B5A2B.3020106@redhat.com> References: <7dd32b4d7915937025f4.1228365080@xenbld.SFBay.Sun.COM> <493B5A2B.3020106@redhat.com> Message-ID: <20081207162936.GA28286@barman.uk.sun.com> On Sun, Dec 07, 2008 at 12:07:55AM -0500, Cole Robinson wrote: > Though this needed some extra work to be back compatible with the previous > OS dictionary layout (virt-install --os-type unix --os-variant solaris9 > would now be busted.) I committed a fix for this: > > http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=419fb59763dc Great, thanks! john From franta at hanzlici.cz Sun Dec 7 17:34:41 2008 From: franta at hanzlici.cz (Frantisek Hanzlik) Date: Sun, 07 Dec 2008 18:34:41 +0100 Subject: [et-mgmt-tools] How send special keystrokes to guest (w2k8) system? Message-ID: <493C0931.8050302@hanzlici.cz> I just install w2k8 server guest at Fedora 10 host (HW:FS PRIMERGY SX330S1, 2x Quad Opteron 2352 with virtualization support) with kvm virtualization. All works probably fine, but I cann't send keystrokes as CTRL+ALT+DEL to guest. I tried: - disable handling special keys (CTRL+ALT+) in X server (settable in GNOME keyboard properties) - use "Send key" feature in virt-manager v0.6.0 (offers sending CTRL+ALT+DEL, CTRL+ALT+Backspace, Printscreen and CTRL+ALT+Fx keystrokes) - somewhere mentioned CTRL+CTRL+CTRL+ALT+DEL combination but all without success. Probably I'm doing something wrong, can someone push me forward? On host I use Fedora 10 distro, 2.6.27.7-130.fc10.i686 SMP kernel, kvm-74-6.fc10.i386, libvirt-0.5.1-1.fc10.i386, virt-manager-0.6.0-4.fc10.i386 -- Thanks in advance, Franta Hanzlik From crobinso at redhat.com Mon Dec 8 15:56:17 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 08 Dec 2008 10:56:17 -0500 Subject: [et-mgmt-tools] [PATCH 0/2]: virt-manager: Revamp preferences dialog Message-ID: <493D43A1.5000407@redhat.com> Hi, The following 2 patches update the virt-manager preferences dialog. The dialog now uses a tabbed view, providing an easy path for adding new options. New options are also added for disabling stats polling, per stats catagories (disk I/O, net I/O, cpu usage, memory usage). Thanks, Cole From crobinso at redhat.com Mon Dec 8 15:58:02 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 08 Dec 2008 10:58:02 -0500 Subject: [et-mgmt-tools] [PATCH 1/2]: New preferences dialog UI In-Reply-To: <493D43A1.5000407@redhat.com> References: <493D43A1.5000407@redhat.com> Message-ID: <493D440A.4050608@redhat.com> That attached patch updates the virt-manager preferences dialog UI to use a tabbed view. This makes the dialog easily extendible and hopefully will encourage adding more global preference options. UI is also added for the new enable/disable stats polling options. They are hooked up the their underlying gconf entries, but they don't have any effect (handled by the next patch). Some screenshots: http://fedorapeople.org/~crobinso/virt-manager/vmm-prefs-1.png http://fedorapeople.org/~crobinso/virt-manager/vmm-prefs-2.png Thanks, Cole -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: virt-manager-new-prefs-01-patch URL: From crobinso at redhat.com Mon Dec 8 15:58:38 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 08 Dec 2008 10:58:38 -0500 Subject: [et-mgmt-tools] [PATCH 2/2]: Hook up enable/disable stats polling options In-Reply-To: <493D43A1.5000407@redhat.com> References: <493D43A1.5000407@redhat.com> Message-ID: <493D442E.2090204@redhat.com> The attached patch hooks up the new preferences options to enable/disable stats polling. When polling is disabled, performance graphs in the VM Details->Overview tab are labeled as 'Disabled'. The graphs continue to update, but all the data passed to it is 0: http://fedorapeople.org/~crobinso/virt-manager/vmm-stats-disabled.png Also, if the associated stats column is visible in the manager window when the user disables polling, the manager column disappears. The View-> entry for that stats type is also disabled, with a tooltip informing the user that polling is disabled in the preferences dialog. Thanks, Cole -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: virt-manager-new-prefs-02-patch URL: From crobinso at redhat.com Tue Dec 9 01:17:39 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 08 Dec 2008 20:17:39 -0500 Subject: [et-mgmt-tools] Re: [PATCH] virt-manager: allow non root users for ssh:// In-Reply-To: <20081204193520.GA11484@bogon.ms20.nix> References: <20081204193354.GA11430@bogon.ms20.nix> <20081204193520.GA11484@bogon.ms20.nix> Message-ID: <493DC733.4070306@redhat.com> Guido G?nther wrote: > On Thu, Dec 04, 2008 at 08:33:54PM +0100, Guido G?nther wrote: > >> Hi, >> attached patch allows to specify a user with user at host for ssh >> connections in the "Add connection..." dialog. This has been requested >> e.g. in: >> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=505936 >> > Patch attached now. > -- Guido > Whoops, I applied this over the weekend but forgot to respond: http://hg.et.redhat.com/virt/applications/virt-manager--devel?cs=a1e97ce0a1c8 Thanks, Cole From crobinso at redhat.com Tue Dec 9 01:55:13 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 08 Dec 2008 20:55:13 -0500 Subject: [et-mgmt-tools] [PATCH] Add --autocf In-Reply-To: <20081204120608.GA18063@totally.trollied.org.uk> References: <20081204120335.GF24539@redhat.com> <20081204120608.GA18063@totally.trollied.org.uk> Message-ID: <493DD001.2040808@redhat.com> John Levon wrote: > On Thu, Dec 04, 2008 at 12:03:36PM +0000, Daniel P. Berrange wrote: > > >>> Add --autocf >>> >>> Add an option for passing Solaris JumpStart information. For HVM >>> guests, this means a floppy image (!). >>> >> I think its better not to add this OS specific option. You can >> > > I don't think it's OS specific. I set up kickstart a while back and it > involved a lot of magic boot options with -x, why not make it easy? > > >> apass the Jumpstart floppy image using the recently added generic >> --disk option >> >> --disk path=/path/to/image,device=floppy >> > > And for NFS JumpStart? > I wouldn't be opposed to adding support for this, provided it is in a sufficiently generalized manner that we could reuse the command line and API to add support for specifying a kickstart, autoyast, etc. Something like: --auto-install type=autocf,media=http://example.com/foo.img The data should also be associated with the Installer class, rather than the Guest class. - Cole From crobinso at redhat.com Tue Dec 9 02:20:23 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 08 Dec 2008 21:20:23 -0500 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: <271ceb01335da50c05fe.1228484289@xenbld.SFBay.Sun.COM> References: <271ceb01335da50c05fe.1228484289@xenbld.SFBay.Sun.COM> Message-ID: <493DD5E7.20207@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228484283 28800 > # Node ID 271ceb01335da50c05fe6c2f54f3eb1721f51bb4 > # Parent 8ad095a908ad89a0c83c94bd486647b79817acbe > Port utility functions to Solaris > > Port various utils to Solaris, and remove some unused ones that don't > work. > > Signed-off-by: John Levon > > Unfortunately, 'util' is part of the public API, so removing dead functions isn't a good idea. Granted, we probably have a grand total of 3 API users (virt cli tools, virt-manager, koan), but I think it's better to just play by the rules. I'm certainly not opposed to moving those functions away from the still relevant code and clearly labeling them as deprecated. It might be a good idea to make an internal util file, so we have an alternate place to dump utility methods without them automatically entering the public API. > diff --git a/virtinst/FullVirtGuest.py b/virtinst/FullVirtGuest.py > --- a/virtinst/FullVirtGuest.py > +++ b/virtinst/FullVirtGuest.py > @@ -38,7 +38,8 @@ class FullVirtGuest(Guest): > installer = DistroManager.DistroInstaller(type = type, os_type = "hvm") > Guest.__init__(self, type, connection, hypervisorURI, installer) > self.disknode = "hd" > - self.features = { "acpi": None, "pae": util.is_pae_capable(), "apic": None } > + self.features = { "acpi": None, "pae": > + util.is_pae_capable(connection), "apic": None } > if arch is None: > arch = platform.machine() > self.arch = arch > diff --git a/virtinst/util.py b/virtinst/util.py > --- a/virtinst/util.py > +++ b/virtinst/util.py > @@ -25,6 +25,7 @@ import re > import re > import libxml2 > import logging > +import popen2 > from sys import stderr > > import libvirt > @@ -54,8 +55,29 @@ def default_route(): > continue > return None > > -# Legacy for compat only. > +def default_nic(): > + """Return the default NIC to use, if one is specified.""" > + > Since this seems only be used for the public default_bridge function, this is a candidate for an internal util file. > + dev = '' > + > + if platform.system() != 'SunOS': > + return dev > + > + # XXX: fails without PRIV_XVM_CONTROL > + proc = popen2.Popen3(["/usr/lib/xen/bin/xenstore-read", > + "device-misc/vif/default-nic"], capturestderr=True) > The 'subprocess' module is intended to replace popen2. We aren't really using it in the codebase yet, but it's worth mentioning. Certainly not a deal breaker. > + proc.tochild.close() > + proc.wait() > + out = proc.fromchild.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 > @@ -68,6 +90,9 @@ def default_bridge(): > 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()): > @@ -98,6 +123,9 @@ def default_connection(): > 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() > @@ -111,31 +139,16 @@ def get_cpu_flags(): > return flst > return [] > > -def is_pae_capable(): > +def is_pae_capable(conn): > If altering the command list here, please make conn optional to maintain back compat. > """Determine if a machine is PAE capable or not.""" > - flags = get_cpu_flags() > - if "pae" in flags: > - return True > - return False > - > -def is_hvm_capable(): > - """Determine if a machine is HVM capable or not.""" > - > - 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") > + if not conn: > + conn = libvirt.open('') > + return "pae" in conn.getCapabilities() > > def is_blktap_capable(): > - #return os.path.exists("/dev/xen/blktapctrl") > + if platform.system() == 'SunOS': > + return False > + > f = open("/proc/modules") > lines = f.readlines() > f.close() > > Thanks, Cole From crobinso at redhat.com Tue Dec 9 02:29:20 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 08 Dec 2008 21:29:20 -0500 Subject: [et-mgmt-tools] How send special keystrokes to guest (w2k8) system? In-Reply-To: <493C0931.8050302@hanzlici.cz> References: <493C0931.8050302@hanzlici.cz> Message-ID: <493DD800.50704@redhat.com> Frantisek Hanzlik wrote: > I just install w2k8 server guest at Fedora 10 host (HW:FS PRIMERGY > SX330S1, > 2x Quad Opteron 2352 with virtualization support) with kvm > virtualization. > All works probably fine, but I cann't send keystrokes as CTRL+ALT+DEL > to guest. I tried: > > - disable handling special keys (CTRL+ALT+) in X server (settable in > GNOME keyboard properties) > > - use "Send key" feature in virt-manager v0.6.0 (offers sending > CTRL+ALT+DEL, > CTRL+ALT+Backspace, Printscreen and CTRL+ALT+Fx keystrokes) > > - somewhere mentioned CTRL+CTRL+CTRL+ALT+DEL combination > > but all without success. Probably I'm doing something wrong, can someone > push me forward? > > On host I use Fedora 10 distro, 2.6.27.7-130.fc10.i686 SMP kernel, > kvm-74-6.fc10.i386, libvirt-0.5.1-1.fc10.i386, > virt-manager-0.6.0-4.fc10.i386 > I don't know of any specific issues wrt Win2008. Most likely this is either an issue at the gtk-vnc or kvm level. Please file a bug against gtk-vnc in fedora 10, and we can try to triage it as appropriate from there: https://bugzilla.redhat.com/enter_bug.cgi?alias=&assigned_to=&attachurl=&blocked=&bug_file_loc=http%3A%2F%2F&bug_severity=medium&bug_status=NEW&cf_build_id=&cf_cust_facing=---&cf_devel_whiteboard=&cf_fixed_in=&cf_internal_whiteboard=&cf_issuetracker=&cf_qa_whiteboard=&cf_release_notes=&comment=Description%20of%20problem%3A%0D%0A%0D%0A%0D%0AVersion-Release%20number%20of%20selected%20component%20(if%20applicable)%3A%0D%0A%0D%0A%0D%0AHow%20reproducible%3A%0D%0A%0D%0A%0D%0ASteps%20to%20Reproduce%3A%0D%0A1.%0D%0A2.%0D%0A3.%0D%0A%20%20%0D%0AActual%20results%3A%0D%0A%0D%0A%0D%0AExpected%20results%3A%0D%0A%0D%0A%0D%0AAdditional%20info%3A&component=gtk-vnc&contenttypeentry=&contenttypemethod=autodetect&contenttypeselection=text%2Fplain&data=&deadline=&dependson=&description=&estimated_time=0.0&external_bug_id=&external_id=0&flag_type-16=X&flag_type-65=X&flag_type-66=X&flag_type-67=X&form_name=enter_bug&keywords=&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=Linux&priority=low&product=Fedora&qa_contact=&rep_platform=All&short_desc=&status_whiteboard=&target_milestone=---&version=10 Thanks, Cole From crobinso at redhat.com Tue Dec 9 03:01:11 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 08 Dec 2008 22:01:11 -0500 Subject: [et-mgmt-tools] Xen, Windows 2003 and APIC In-Reply-To: <20081205140341.GD29148@barman.uk.sun.com> References: <20081205140341.GD29148@barman.uk.sun.com> Message-ID: <493DDF77.2080305@redhat.com> Gary Pennington wrote: > Hi, > > I've been investigating networking performance for Windows 2003 guests > on a Solaris dom0 and I've uncovered a couple of things which I don't > really understand and I'm looking for some explanations. > > This first question is really directed at virtinst developers... > > Windows guests have different ACPI and APIC settings depending on which > variant of Windows is to be installed: > > variant: unspecified -> ACPI: true, APIC: true > variant: winxp -> ACPI: false, APIC: false > variant: win2k -> ACPI: false, APIC: false > variant: win2k3 -> ACPI: true, APIC: true > variant: vista -> ACPI: true, APIC: true > > The question is: why don't all Windows variants have the same ACPI and APIC > settings? > > One of the motivations for the ACPI = False, was that when installing those versions of windows with ACPI enabled, the installer required manual intervention. The user had to hit F5 or something in a small time frame and specify a non-default HAL, otherwise the install would just freeze. Well, that's what I recall anyways. I can't seem to find a bz about the issue, and the hg history isn't much help. I have no idea if APIC played a part in the above issue, or why it's off for winxp or win2000. Thanks, Cole From crobinso at redhat.com Tue Dec 9 03:09:16 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 08 Dec 2008 22:09:16 -0500 Subject: [et-mgmt-tools] [PATCH] Add vdisk support In-Reply-To: <152e0bfb277efb24679d.1228365108@xenbld.SFBay.Sun.COM> References: <152e0bfb277efb24679d.1228365108@xenbld.SFBay.Sun.COM> Message-ID: <493DE15C.2040702@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228365031 28800 > # Node ID 152e0bfb277efb24679d7c7f440df0b0f6b21529 > # Parent 35baacfe79834400949ebdba69f952ed873ae442 > Add vdisk support > > Add support for the vdisk format used in Solaris. > > Signed-off-by: John Levon > > diff --git a/virt-install b/virt-install > --- a/virt-install > +++ b/virt-install > @@ -189,9 +189,13 @@ def get_disk(disk, size, sparse, guest, > readOnly=readOnly, device=device, bus=bus, > conn=guest.conn) > # Default file backed PV guests to tap driver > - if d.type == virtinst.VirtualDisk.TYPE_FILE \ > - and not(hvm) and virtinst.util.is_blktap_capable(): > - d.driver_name = virtinst.VirtualDisk.DRIVER_TAP > + if d.type == virtinst.VirtualDisk.TYPE_FILE and not(hvm): > + if virtinst.util.is_blktap_capable(): > + d.driver_name = virtinst.VirtualDisk.DRIVER_TAP > + elif virtinst.util.is_vdisk(path): > + d.driver_name = Guest.VirtualDisk.DRIVER_TAP > + d.driver_type = Guest.VirtualDisk.DRIVER_TAP_VDISK > + > Hmm, this whole block should probably be moved into the VirtualDisk class, and used to set the default driver if the user doesn't specify one. But it's not a blocker. > except ValueError, e: > fail(_("Error with storage parameters: %s" % str(e))) > > diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py > --- a/virtinst/CloneManager.py > +++ b/virtinst/CloneManager.py > @@ -19,7 +19,6 @@ > # MA 02110-1301 USA. > > import os > -import stat > import libxml2 > import logging > import urlgrabber.progress as progress > @@ -394,13 +393,9 @@ class CloneDesign(object): > logging.debug("original device list: %s" % (lst)) > > for i in lst: > - mode = os.stat(i)[stat.ST_MODE] > - if stat.S_ISBLK(mode): > - size.append(util.blkdev_size(i)) > - typ.append(False) > - elif stat.S_ISREG(mode): > - size.append(os.path.getsize(i)) > - typ.append(True) > + (t, sz) = util.stat_disk(i) > + typ.append(t) > + size.append(sz) > This, and all the other stat_disk code, seems like a separate cleanup. Could we get this in a separate patch? > logging.debug("original device size: %s" % (size)) > logging.debug("original device type: %s" % (typ)) > > @@ -443,18 +438,9 @@ class CloneDesign(object): > typ = [] > > for i in cln_dev_lst: > - if os.path.exists(i) == False: > - size.append(0) > - # if not exists, create file necessary > - typ.append(True) > - continue > - mode = os.stat(i)[stat.ST_MODE] > - if stat.S_ISBLK(mode): > - size.append(util.blkdev_size(i)) > - typ.append(False) > - elif stat.S_ISREG(mode): > - size.append(os.path.getsize(i)) > - typ.append(True) > + (t, sz) = util.stat_disk(i) > + typ.append(t) > + size.append(sz) > > logging.debug("clone device list: %s" % (cln_dev_lst)) > logging.debug("clone device size: %s" % (size)) > @@ -535,6 +521,14 @@ def _do_duplicate(design): > if src_dev == "/dev/null" or src_dev == dst_dev: > meter.end(size) > continue > + > + if util.is_vdisk(src_dev) or (os.path.exists(dst_dev) and util.is_vdisk(dst_dev)): > + if not util.is_vdisk(src_dev) or os.path.exists(dst_dev): > + raise RuntimeError, _("copying to an existing vdisk is not supported") > + if not util.vdisk_clone(src_dev, dst_dev): > + raise RuntimeError, _("failed to clone disk") > + continue > + > # > # create sparse file > # if a destination file exists and sparse flg is True, > diff --git a/virtinst/Guest.py b/virtinst/Guest.py > --- a/virtinst/Guest.py > +++ b/virtinst/Guest.py > @@ -474,6 +474,9 @@ class Installer(object): > or guest.disks[0].device != VirtualDisk.DEVICE_DISK: > return True > > + if util.is_vdisk(guest.disks[0].path): > + return True > + > # Check for the 0xaa55 signature at the end of the MBR > try: > fd = os.open(guest.disks[0].path, os.O_RDONLY) > diff --git a/virtinst/ImageManager.py b/virtinst/ImageManager.py > --- a/virtinst/ImageManager.py > +++ b/virtinst/ImageManager.py > @@ -101,8 +101,13 @@ class ImageInstaller(Guest.Installer): > 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 > + if util.is_vdisk(p): > + d.driver_name = Guest.VirtualDisk.DRIVER_TAP > + d.driver_type = Guest.VirtualDisk.DRIVER_TAP_VDISK > + else: > + if self.boot_caps.type == "xen" and util.is_blktap_capable(): > + d.driver_name = Guest.VirtualDisk.DRIVER_TAP > + > d.target = m.target > > guest._install_disks.append(d) > diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py > --- a/virtinst/VirtualDisk.py > +++ b/virtinst/VirtualDisk.py > @@ -68,7 +68,9 @@ class VirtualDisk(VirtualDevice): > DRIVER_TAP_RAW = "aio" > DRIVER_TAP_QCOW = "qcow" > DRIVER_TAP_VMDK = "vmdk" > - driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, DRIVER_TAP_VMDK] > + DRIVER_TAP_VDISK = "vdisk" > + driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, > + DRIVER_TAP_VMDK, DRIVER_TAP_VDISK] > > DEVICE_DISK = "disk" > DEVICE_CDROM = "cdrom" > @@ -424,7 +426,8 @@ class VirtualDisk(VirtualDevice): > or self.vol_object): > logging.debug("VirtualDisk storage exists.") > > - if using_path and os.path.isdir(self.path): > + if (using_path and os.path.isdir(self.path) and > + not util.is_vdisk(self.path)): > raise ValueError, _("The path must be a file or a device," > " not a directory") > self.__set_dev_type() > @@ -476,9 +479,24 @@ class VirtualDisk(VirtualDevice): > self._set_vol_object(self.vol_install.install(meter=progresscb), > validate=False) > return > - elif self.type == VirtualDisk.TYPE_FILE and self.path is not None \ > - and not os.path.exists(self.path): > + elif (self.type == VirtualDisk.TYPE_FILE and self.path is not None > + and os.path.exists(self.path) and util.is_vdisk(self.path)): > + self._driverName = self.DRIVER_TAP > + self._driverType = self.DRIVER_TAP_VDISK > This could use a debug statement stating we are forcing the vdisk driver. > + return > + 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 util.is_vdisk(self.path): > + progresscb.update(1024) > + if (not util.vdisk_create(self.path, size_bytes, "vmdk", > + 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 > > if progresscb: > progresscb.start(filename=self.path,size=long(size_bytes), \ > diff --git a/virtinst/util.py b/virtinst/util.py > --- a/virtinst/util.py > +++ b/virtinst/util.py > @@ -29,6 +29,7 @@ import stat > import stat > import popen2 > from sys import stderr > +from subprocess import call > > import libvirt > from virtinst import _virtinst as _ > @@ -283,17 +284,71 @@ def xml_escape(str): > str = str.replace(">", ">") > return str > > -def blkdev_size(path): > - if platform.system() == 'SunOS': > - return os.stat(path)[stat.ST_SIZE] > - else: > - dummy, msg = commands.getstatusoutput('fdisk -s %s' % path) > - # check > - if msg.isdigit() == False: > - lines = msg.splitlines() > - # retry eg. for the GPT disk > - msg = lines[len(lines)-1] > - return (int(msg) * 1024) > +def is_vdisk(path): > + if not os.path.exists("/usr/sbin/vdiskadm"): > + return False > + if not os.path.exists(path): > + return True > + if os.path.isdir(path) and \ > + os.path.exists(path + "/vdisk.xml"): > + return True > + 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" > + args = " create -t " + type + " -s " + str(size) + " " + path > + try: > + rc = call("/usr/sbin/vdiskadm" + args, shell=True) > + if rc != 0: > + return False > + return True > + except OSError, e: > + return False > + > +def vdisk_clone(path, clone): > + path = os.path.expanduser(path) > + clone = os.path.expanduser(clone) > + args = path + " " + clone > + try: > + rc = call("/usr/sbin/vdiskadm clone " + args, shell=True) > + if rc != 0: > + return False > + return True > + except OSError, e: > + return False > + > These two can be moved to VirtualDisk and CloneManager respectively as non class functions. Please prefix them with an underscore to mark them as private. > +def stat_disk(path): > + """Returns the tuple (isreg, size).""" > + if not os.path.exists(path): > + return True, 0 > + > + if is_vdisk(path): > + size = int(commands.getoutput( > + "vdiskadm prop-get -p max-size " + path)) > + return True, size > + > + mode = os.stat(path)[stat.ST_MODE] > + if stat.S_ISBLK(mode): > + if platform.system() == 'SunOS': > + size = os.stat(path)[stat.ST_SIZE] > + else: > + dummy, msg = commands.getstatusoutput('fdisk -s %s' % path) > + # check > + if msg.isdigit() == False: > + lines = msg.splitlines() > + # retry eg. for the GPT disk > + msg = lines[len(lines)-1] > + size = int(msg) * 1024 > + return False, size > + elif stat.S_ISREG(mode): > + return True, os.path.getsize(path) > + > + return True, 0 > > def compareMAC(p, q): > """Compare two MAC addresses"" Thanks, Cole From berrange at redhat.com Tue Dec 9 10:29:04 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 9 Dec 2008 10:29:04 +0000 Subject: [et-mgmt-tools] [PATCH] Add --autocf In-Reply-To: <493DD001.2040808@redhat.com> References: <20081204120335.GF24539@redhat.com> <20081204120608.GA18063@totally.trollied.org.uk> <493DD001.2040808@redhat.com> Message-ID: <20081209102904.GA15102@redhat.com> On Mon, Dec 08, 2008 at 08:55:13PM -0500, Cole Robinson wrote: > John Levon wrote: > > On Thu, Dec 04, 2008 at 12:03:36PM +0000, Daniel P. Berrange wrote: > > > > > >>> Add --autocf > >>> > >>> Add an option for passing Solaris JumpStart information. For HVM > >>> guests, this means a floppy image (!). > >>> > >> I think its better not to add this OS specific option. You can > >> > > > > I don't think it's OS specific. I set up kickstart a while back and it > > involved a lot of magic boot options with -x, why not make it easy? > > > > > >> apass the Jumpstart floppy image using the recently added generic > >> --disk option > >> > >> --disk path=/path/to/image,device=floppy > >> > > > > And for NFS JumpStart? > > > > I wouldn't be opposed to adding support for this, provided it is in a > sufficiently generalized manner that we could reuse the command line > and API to add support for specifying a kickstart, autoyast, etc. > Something like: > > --auto-install type=autocf,media=http://example.com/foo.img I just don't see what value this gives over the existing --extra-args media=http://example.com/foo.img or whatever the OS wants. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From franta at hanzlici.cz Tue Dec 9 10:38:28 2008 From: franta at hanzlici.cz (Frantisek Hanzlik) Date: Tue, 09 Dec 2008 11:38:28 +0100 Subject: [et-mgmt-tools] How send special keystrokes to guest (w2k8) system? In-Reply-To: <493DD800.50704@redhat.com> References: <493C0931.8050302@hanzlici.cz> <493DD800.50704@redhat.com> Message-ID: <493E4AA4.1010506@hanzlici.cz> Cole Robinson wrote: > Frantisek Hanzlik wrote: >> I just install w2k8 server guest at Fedora 10 host (HW:FS PRIMERGY >> SX330S1, >> 2x Quad Opteron 2352 with virtualization support) with kvm >> virtualization. >> All works probably fine, but I cann't send keystrokes as CTRL+ALT+DEL >> to guest. I tried: >> >> - disable handling special keys (CTRL+ALT+) in X server (settable in >> GNOME keyboard properties) >> >> - use "Send key" feature in virt-manager v0.6.0 (offers sending >> CTRL+ALT+DEL, >> CTRL+ALT+Backspace, Printscreen and CTRL+ALT+Fx keystrokes) >> >> - somewhere mentioned CTRL+CTRL+CTRL+ALT+DEL combination >> >> but all without success. Probably I'm doing something wrong, can someone >> push me forward? >> >> On host I use Fedora 10 distro, 2.6.27.7-130.fc10.i686 SMP kernel, >> kvm-74-6.fc10.i386, libvirt-0.5.1-1.fc10.i386, >> virt-manager-0.6.0-4.fc10.i386 >> > > I don't know of any specific issues wrt Win2008. Most likely this is > either an issue at the gtk-vnc or kvm level. Please file a bug against > gtk-vnc in fedora 10, and we can try to triage it as appropriate from > there: > > https://bugzilla.redhat.com/enter_bug.cgi?alias=&assigned_to=&attachurl=&blocked=&bug_file_loc=http%3A%2F%2F&bug_severity=medium&bug_status=NEW&cf_build_id=&cf_cust_facing=---&cf_devel_whiteboard=&cf_fixed_in=&cf_internal_whiteboard=&cf_issuetracker=&cf_qa_whiteboard=&cf_release_notes=&comment=Description%20of%20problem%3A%0D%0A%0D%0A%0D%0AVersion-Release%20number%20of%20selected%20component%20(if%20applicable)%3A%0D%0A%0D%0A%0D%0AHow%20reproducible%3A%0D%0A%0D%0A%0D%0ASteps%20to%20Reproduce%3A%0D%0A1.%0D%0A2.%0D%0A3.%0D%0A%20%20%0D%0AActual%20results%3A%0D%0A%0D%0A%0D%0AExpected%20results%3A%0D%0A%0D%0A%0D%0AAdditional%20info%3A&component=gtk-vnc&contenttypeentry=&contenttypemethod=autodetect&contenttypeselection=text%2Fplain&data=&deadline=&dependson=&description=&estimated_time=0.0&external_bug_id=&external_id=0&flag_type-16=X&flag_type-65=X&flag_type-66=X&flag_type-67=X&form_name=enter_bug&keywords=&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=Li nux&priority=low&product=Fedora&qa_contact=&rep_platform=All&short_desc=&status_whiteboard=&target_milestone=---&version=10 > > Thanks, > Cole > Hi Cole, thanks for Your help, You will right, when I compile and instal actual gtk-vnc v0.3.8 (without any additional patches), then all three above mentioned ways work fine. I fill bugzilla report about this issue. I'm too excited, how long and pretty URL You are able do! :)) -- best regards Franti?ek Hanzl?k == Lu?n? 502 Linux/Unix/Novell/Inter-/Net Tel: +420-373729699 == == 33209 ?t?novice e-mail:franta at hanzlici.cz Fax: +420-373729699 == == Czech Republic http://hanzlici.cz/ GSM: +420-604117319 == From berrange at redhat.com Tue Dec 9 10:46:54 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 9 Dec 2008 10:46:54 +0000 Subject: [et-mgmt-tools] How send special keystrokes to guest (w2k8) system? In-Reply-To: <493DD800.50704@redhat.com> References: <493C0931.8050302@hanzlici.cz> <493DD800.50704@redhat.com> Message-ID: <20081209104654.GC15102@redhat.com> On Mon, Dec 08, 2008 at 09:29:20PM -0500, Cole Robinson wrote: > > I don't know of any specific issues wrt Win2008. Most likely this is > either an issue at the gtk-vnc or kvm level. Please file a bug against > gtk-vnc in fedora 10, and we can try to triage it as appropriate from > there: > > https://bugzilla.redhat.com/enter_bug.cgi?alias=&assigned_to=&attachurl=&blocked=&bug_file_loc=http%3A%2F%2F&bug_severity=medium&bug_status=NEW&cf_build_id=&cf_cust_facing=---&cf_devel_whiteboard=&cf_fixed_in=&cf_internal_whiteboard=&cf_issuetracker=&cf_qa_whiteboard=&cf_release_notes=&comment=Description%20of%20problem%3A%0D%0A%0D%0A%0D%0AVersion-Release%20number%20of%20selected%20component%20(if%20applicable)%3A%0D%0A%0D%0A%0D%0AHow%20reproducible%3A%0D%0A%0D%0A%0D%0ASteps%20to%20Reproduce%3A%0D%0A1.%0D%0A2.%0D%0A3.%0D%0A%20%20%0D%0AActual%20results%3A%0D%0A%0D%0A%0D%0AExpected%20results%3A%0D%0A%0D%0A%0D%0AAdditional%20info%3A&component=gtk-vnc&contenttypeentry=&contenttypemethod=autodetect&contenttypeselection=text%2Fplain&data=&deadline=&dependson=&description=&estimated_time=0.0&external_bug_id=&external_id=0&flag_type-16=X&flag_type-65=X&flag_type-66=X&flag_type-67=X&form_name=enter_bug&keywords=&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=Linu > x&priority=low&product=Fedora&qa_contact=&rep_platform=All&short_desc=&status_whiteboard=&target_milestone=---&version=10 Errr, allow me to introduce you to http://ur1.ca/ Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From levon at movementarian.org Tue Dec 9 12:21:14 2008 From: levon at movementarian.org (John Levon) Date: Tue, 9 Dec 2008 12:21:14 +0000 Subject: [et-mgmt-tools] [PATCH] Add --autocf In-Reply-To: <20081209102904.GA15102@redhat.com> References: <20081204120335.GF24539@redhat.com> <20081204120608.GA18063@totally.trollied.org.uk> <493DD001.2040808@redhat.com> <20081209102904.GA15102@redhat.com> Message-ID: <20081209122114.GA20487@totally.trollied.org.uk> On Tue, Dec 09, 2008 at 10:29:04AM +0000, Daniel P. Berrange wrote: > I just don't see what value this gives over the existing > > --extra-args media=http://example.com/foo.img > > or whatever the OS wants. You're forgetting the specification of the networking setup needed in many cases. I'm supposed to remember the exact command lines needed for each OS's variant of automated install? Have you seen what old Solaris's cmdline looks like? virt-install should be fall-over easy to use. regards john From john.levon at sun.com Tue Dec 9 12:33:51 2008 From: john.levon at sun.com (John Levon) Date: Tue, 9 Dec 2008 12:33:51 +0000 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: <493DD5E7.20207@redhat.com> References: <271ceb01335da50c05fe.1228484289@xenbld.SFBay.Sun.COM> <493DD5E7.20207@redhat.com> Message-ID: <20081209123351.GA10806@barman.uk.sun.com> On Mon, Dec 08, 2008 at 09:20:23PM -0500, Cole Robinson wrote: > Unfortunately, 'util' is part of the public API, so removing dead > functions isn't a good idea. Granted, we probably have a grand total > of 3 API users (virt cli tools, virt-manager, koan), but I think it's > better to just play by the rules. I'm certainly not opposed to moving OK. > It might be a good idea to make an internal util file, so we have an > alternate place to dump utility methods without them automatically > entering the public API. How are we supposed to know what's in the public API and what isn't? Is it automatically any file ever used by virt-manager? It seems to me like everything should be moved wholesale into a new directory, and anything legacy left in place (forwarded on to the new implementation if needed). It doesn't seem feasible to maintain code to provide an unspecified API forever! What name do you want for the internal util file? regards john From john.levon at sun.com Tue Dec 9 12:47:26 2008 From: john.levon at sun.com (John Levon) Date: Tue, 9 Dec 2008 12:47:26 +0000 Subject: [et-mgmt-tools] [PATCH] Add vdisk support In-Reply-To: <493DE15C.2040702@redhat.com> References: <152e0bfb277efb24679d.1228365108@xenbld.SFBay.Sun.COM> <493DE15C.2040702@redhat.com> Message-ID: <20081209124726.GB10806@barman.uk.sun.com> On Mon, Dec 08, 2008 at 10:09:16PM -0500, Cole Robinson wrote: > > for i in lst: > > - mode = os.stat(i)[stat.ST_MODE] > > - if stat.S_ISBLK(mode): > > - size.append(util.blkdev_size(i)) > > - typ.append(False) > > - elif stat.S_ISREG(mode): > > - size.append(os.path.getsize(i)) > > - typ.append(True) > > + (t, sz) = util.stat_disk(i) > > + typ.append(t) > > + size.append(sz) > > This, and all the other stat_disk code, seems like a separate cleanup. > Could we get this in a separate patch? It's not exactly an exciting change without the vdisk part, but OK. > > + elif (self.type == VirtualDisk.TYPE_FILE and self.path is not None > > + and os.path.exists(self.path) and util.is_vdisk(self.path)): > > + self._driverName = self.DRIVER_TAP > > + self._driverType = self.DRIVER_TAP_VDISK > > > > This could use a debug statement stating we are forcing the vdisk > driver. I'll add a debug statement, but we're not forcing it: if we detect a vdisk, then we know we will have to use vdisk to read it. > > +def vdisk_create(path, size, kind, sparse = True): > > +def vdisk_clone(path, clone): > > These two can be moved to VirtualDisk and CloneManager respectively > as non class functions. Please prefix them with an underscore to > mark them as private. OK. regards john From crobinso at redhat.com Tue Dec 9 12:59:39 2008 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 09 Dec 2008 07:59:39 -0500 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: <20081209123351.GA10806@barman.uk.sun.com> References: <271ceb01335da50c05fe.1228484289@xenbld.SFBay.Sun.COM> <493DD5E7.20207@redhat.com> <20081209123351.GA10806@barman.uk.sun.com> Message-ID: <493E6BBB.9020804@redhat.com> John Levon wrote: > On Mon, Dec 08, 2008 at 09:20:23PM -0500, Cole Robinson wrote: > > >> Unfortunately, 'util' is part of the public API, so removing dead >> functions isn't a good idea. Granted, we probably have a grand total >> of 3 API users (virt cli tools, virt-manager, koan), but I think it's >> better to just play by the rules. I'm certainly not opposed to moving >> > > OK. > > >> It might be a good idea to make an internal util file, so we have an >> alternate place to dump utility methods without them automatically >> entering the public API. >> > > How are we supposed to know what's in the public API and what isn't? Is > it automatically any file ever used by virt-manager? > > It seems to me like everything should be moved wholesale into a new > directory, and anything legacy left in place (forwarded on to the new > implementation if needed). It doesn't seem feasible to maintain code > to provide an unspecified API forever! > > Anything that is explicitly exported via __init__.py is public. That covers *Guest, *Installer, all the VirtualDevices, CloneManager, and the util file. Anything marked with an underscore is an explicit way to mark something private in a public module or class. We don't need to maintain this old code if it's been replace. Just put a comment that they are deprecated, and when we get around to building out formal API docs, it will be clear. > What name do you want for the internal util file? > > privutil? internal_util? No preference as long as it's obvious. Thanks, Cole From john.levon at sun.com Tue Dec 9 20:43:38 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 09 Dec 2008 12:43:38 -0800 Subject: [et-mgmt-tools] [PATCH] Fix get_graphics() Message-ID: <3a48e2d3594b3e7e1d24.1228855418@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228851589 28800 # Node ID 3a48e2d3594b3e7e1d24147f3325ab6024557504 # Parent 419fb59763dc86b8f6abf26e4fb7ba6f7ba54182 Fix get_graphics() The key needs to be 'enabled' not 'enabled '. Signed-off-by: John Levon diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -717,7 +717,7 @@ class Guest(object): # Deprecated: Should set guest.graphics_dev = VirtualGraphics(...) def get_graphics(self): if self._graphics_dev is None: - return { "enabled " : False } + return { "enabled" : False } return { "enabled" : True, "type" : self._graphics_dev, \ "keymap" : self._graphics_dev.keymap} def set_graphics(self, val): From john.levon at sun.com Tue Dec 9 20:44:03 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 09 Dec 2008 12:44:03 -0800 Subject: [et-mgmt-tools] [PATCH] Add utility function for stat() of disks Message-ID: <50ca2624e7ef5713153e.1228855443@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228851945 28800 # Node ID 50ca2624e7ef5713153ef85c012326fdae125b7f # Parent 29d8886362e2993eaf26cf8d4e948b2de4b8d9ec Add utility function for stat() of disks Signed-off-by: John Levon diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -19,7 +19,6 @@ # MA 02110-1301 USA. import os -import stat import libxml2 import logging import urlgrabber.progress as progress @@ -394,13 +393,9 @@ class CloneDesign(object): logging.debug("original device list: %s" % (lst)) for i in lst: - mode = os.stat(i)[stat.ST_MODE] - if stat.S_ISBLK(mode): - size.append(_util.blkdev_size(i)) - typ.append(False) - elif stat.S_ISREG(mode): - size.append(os.path.getsize(i)) - typ.append(True) + (t, sz) = _util.stat_disk(i) + typ.append(t) + size.append(sz) logging.debug("original device size: %s" % (size)) logging.debug("original device type: %s" % (typ)) @@ -443,18 +438,9 @@ class CloneDesign(object): typ = [] for i in cln_dev_lst: - if os.path.exists(i) == False: - size.append(0) - # if not exists, create file necessary - typ.append(True) - continue - mode = os.stat(i)[stat.ST_MODE] - if stat.S_ISBLK(mode): - size.append(_util.blkdev_size(i)) - typ.append(False) - elif stat.S_ISREG(mode): - size.append(os.path.getsize(i)) - typ.append(True) + (t, sz) = _util.stat_disk(i) + typ.append(t) + size.append(sz) logging.debug("clone device list: %s" % (cln_dev_lst)) logging.debug("clone device size: %s" % (size)) diff --git a/virtinst/_util.py b/virtinst/_util.py --- a/virtinst/_util.py +++ b/virtinst/_util.py @@ -22,6 +22,7 @@ import platform import platform import random import os.path +import stat import re import libxml2 import logging @@ -280,14 +281,24 @@ def xml_escape(str): str = str.replace(">", ">") return str -def blkdev_size(path): - """Return the size of the block device. We can't use os.stat() as - that returns zero on many platforms.""" - fd = os.open(path, os.O_RDONLY) - # os.SEEK_END is not present on all systems - size = os.lseek(fd, 0, 2) - os.close(fd) - return size +def stat_disk(path): + """Returns the tuple (isreg, size).""" + if not os.path.exists(path): + return True, 0 + + mode = os.stat(path)[stat.ST_MODE] + + # os.path.getsize('/dev/..') can be zero on some platforms + if stat.S_ISBLK(mode): + fd = os.open(path, os.O_RDONLY) + # os.SEEK_END is not present on all systems + size = os.lseek(fd, 0, 2) + os.close(fd) + return False, size + elif stat.S_ISREG(mode): + return True, os.path.getsize(path) + + return True, 0 def compareMAC(p, q): """Compare two MAC addresses""" From john.levon at sun.com Tue Dec 9 20:43:50 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 09 Dec 2008 12:43:50 -0800 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris Message-ID: <29d8886362e2993eaf26.1228855430@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228851891 28800 # Node ID 29d8886362e2993eaf26cf8d4e948b2de4b8d9ec # Parent 3a48e2d3594b3e7e1d24147f3325ab6024557504 Port utility functions to Solaris Create _util.py for private details of the implementation, along with a shim for back compatibility. Port the utilities to Solaris. Signed-off-by: John Levon diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -23,7 +23,7 @@ import libxml2 import libxml2 import logging import urlgrabber.progress as progress -import util +import _util import libvirt import Guest from VirtualDisk import VirtualDisk @@ -263,7 +263,7 @@ class CloneDesign(object): node[0].setContent(self._clone_uuid) else: while 1: - uuid = util.uuidToString(util.randomUUID()) + uuid = _util.uuidToString(_util.randomUUID()) if self._check_uuid(uuid) == True: continue else: @@ -278,7 +278,7 @@ class CloneDesign(object): node[0].setContent(self._clone_mac[i-1]) except Exception: while 1: - mac = util.randomMAC(typ) + mac = _util.randomMAC(typ) dummy, msg = self._check_mac(mac) if msg is not None: continue @@ -396,7 +396,7 @@ class CloneDesign(object): for i in lst: mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - size.append(util.blkdev_size(i)) + size.append(_util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) @@ -450,7 +450,7 @@ class CloneDesign(object): continue mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - size.append(util.blkdev_size(i)) + size.append(_util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) diff --git a/virtinst/DistroManager.py b/virtinst/DistroManager.py --- a/virtinst/DistroManager.py +++ b/virtinst/DistroManager.py @@ -22,7 +22,7 @@ import logging import os -import util +import _util import Guest from VirtualDisk import VirtualDisk from virtinst import _virtinst as _ @@ -158,7 +158,7 @@ class DistroInstaller(Guest.Installer): logging.debug("DistroInstaller location is a (poolname, volname)" " tuple") elif os.path.exists(os.path.abspath(val)) \ - and (not self.conn or not util.is_uri_remote(self.conn.getURI())): + 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) @@ -178,8 +178,8 @@ class DistroInstaller(Guest.Installer): elif (val.startswith("http://") or val.startswith("ftp://") or val.startswith("nfs:")): logging.debug("DistroInstaller location is a network source.") - elif self.conn and util.is_storage_capable(self.conn) and \ - util.is_uri_remote(self.conn.getURI()): + elif self.conn and _util.is_storage_capable(self.conn) and \ + _util.is_uri_remote(self.conn.getURI()): # If conn is specified, pass the path to a VirtualDisk object # and see what comes back try: @@ -193,7 +193,7 @@ class DistroInstaller(Guest.Installer): "or FTP network install source, or an existing " "local file/device")) - if val.startswith("nfs:") and not util.privileged_user(): + if val.startswith("nfs:") and not _util.privileged_user(): raise ValueError(_("NFS installations are only supported as root")) self._location = val diff --git a/virtinst/FullVirtGuest.py b/virtinst/FullVirtGuest.py --- a/virtinst/FullVirtGuest.py +++ b/virtinst/FullVirtGuest.py @@ -20,7 +20,7 @@ # MA 02110-1301 USA. import os -import util +import _util import DistroManager import logging import time @@ -38,7 +38,8 @@ class FullVirtGuest(Guest): installer = DistroManager.DistroInstaller(type = type, os_type = "hvm") Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "hd" - self.features = { "acpi": None, "pae": util.is_pae_capable(), "apic": None } + self.features = { "acpi": None, "pae": + _util.is_pae_capable(connection), "apic": None } if arch is None: arch = platform.machine() self.arch = arch diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -26,7 +26,7 @@ import re import re import libxml2 import urlgrabber.progress as progress -import util +import _util import libvirt import platform import __builtin__ @@ -131,7 +131,7 @@ class VirtualNetworkInterface(VirtualDev logging.warn("conflict_net: Failed to lookup domain %d" % name) # get the Host's NIC MACaddress - hostdevs = util.get_host_network_devices() + 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.")) @@ -145,7 +145,7 @@ class VirtualNetworkInterface(VirtualDev def setup(self, conn): if self.macaddr is None: while 1: - self.macaddr = util.randomMAC(type=conn.getType().lower()) + self.macaddr = _util.randomMAC(type=conn.getType().lower()) if self.is_conflict_net(conn)[1] is not None: continue else: @@ -159,7 +159,7 @@ class VirtualNetworkInterface(VirtualDev raise RuntimeError(msg) if not self.bridge and self.type == "bridge": - self.bridge = util.default_bridge() + self.bridge = _util.default_bridge() def get_xml_config(self): src_xml = "" @@ -192,7 +192,7 @@ class VirtualNetworkInterface(VirtualDev try: 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: + if macaddr and _util.compareMAC(self.macaddr, macaddr) == 0: count += 1 finally: if ctx is not None: @@ -250,7 +250,7 @@ class VirtualGraphics(object): return self._keymap def set_keymap(self, val): if not val: - val = util.default_keymap() + val = _util.default_keymap() if not val or type(val) != type("string"): raise ValueError, _("Keymap must be a string") if len(val) > 16: @@ -352,7 +352,7 @@ class Installer(object): return '/var/tmp' if self.type == "xen" and os.path.exists(XEN_SCRATCH): return XEN_SCRATCH - if util.privileged_user() and os.path.exists(LIBVIRT_SCRATCH): + if _util.privileged_user() and os.path.exists(LIBVIRT_SCRATCH): return LIBVIRT_SCRATCH else: return os.path.expanduser("~/.virtinst/boot") @@ -407,7 +407,7 @@ class Installer(object): conn=None, kernel=None, bootdev=None): osblob = "" if not isinstall and not ishvm: - return "%s" % util.pygrub_path(conn) + return "%s" % _util.pygrub_path(conn) osblob = "\n" @@ -425,9 +425,9 @@ class Installer(object): osblob += " %s\n" % loader if isinstall and kernel and kernel["kernel"]: - osblob += " %s\n" % util.xml_escape(kernel["kernel"]) - osblob += " %s\n" % util.xml_escape(kernel["initrd"]) - osblob += " %s\n" % util.xml_escape(kernel["extraargs"]) + osblob += " %s\n" % _util.xml_escape(kernel["kernel"]) + osblob += " %s\n" % _util.xml_escape(kernel["initrd"]) + osblob += " %s\n" % _util.xml_escape(kernel["extraargs"]) elif bootdev is not None: osblob += " \n" % bootdev @@ -466,7 +466,7 @@ class Installer(object): @type L{Guest} """ - if util.is_uri_remote(guest.conn.getURI()): + if _util.is_uri_remote(guest.conn.getURI()): # XXX: Use block peek for this? return True @@ -479,7 +479,7 @@ class Installer(object): fd = os.open(guest.disks[0].path, os.O_RDONLY) except OSError, (err, msg): logging.debug("Failed to open guest disk: %s" % msg) - if err == errno.EACCES and not util.privileged_user(): + if err == errno.EACCES and not _util.privileged_user(): return True # non root might not have access to block devices else: raise @@ -624,7 +624,7 @@ class Guest(object): def get_vcpus(self): return self._vcpus def set_vcpus(self, val): - maxvcpus = util.get_max_vcpus(self.conn, self.type) + 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: @@ -642,7 +642,7 @@ class Guest(object): if re.match("^[0-9,-]*$", val) is None: raise ValueError, _("cpuset can only contain numeric, ',', or '-' characters") - pcpus = util.get_phy_cpus(self.conn) + pcpus = _util.get_phy_cpus(self.conn) for c in val.split(','): if c.find('-') != -1: (x, y) = c.split('-') @@ -1061,7 +1061,7 @@ class Guest(object): def _set_defaults(self): if self.uuid is None: while 1: - self.uuid = util.uuidToString(util.randomUUID()) + self.uuid = _util.uuidToString(_util.randomUUID()) try: if self.conn.lookupByUUIDString(self.uuid) is not None: continue diff --git a/virtinst/ImageManager.py b/virtinst/ImageManager.py --- a/virtinst/ImageManager.py +++ b/virtinst/ImageManager.py @@ -23,7 +23,7 @@ import CapabilitiesParser as Cap import CapabilitiesParser as Cap from VirtualDisk import VirtualDisk import os -import util +import _util from virtinst import _virtinst as _ class ImageInstallerException(Exception): @@ -101,7 +101,7 @@ class ImageInstaller(Guest.Installer): d = VirtualDisk(p, s, device = device, type = VirtualDisk.TYPE_FILE) - if self.boot_caps.type == "xen" and util.is_blktap_capable(): + if self.boot_caps.type == "xen" and _util.is_blktap_capable(): d.driver_name = VirtualDisk.DRIVER_TAP d.target = m.target @@ -127,9 +127,9 @@ class ImageInstaller(Guest.Installer): if loader: osblob += " %s\n" % loader if self.boot_caps.kernel: - osblob += " %s\n" % util.xml_escape(self._abspath(self.boot_caps.kernel)) - osblob += " %s\n" % util.xml_escape(self._abspath(self.boot_caps.initrd)) - osblob += " %s\n" % util.xml_escape(self.boot_caps.cmdline) + osblob += " %s\n" % _util.xml_escape(self._abspath(self.boot_caps.kernel)) + osblob += " %s\n" % _util.xml_escape(self._abspath(self.boot_caps.initrd)) + osblob += " %s\n" % _util.xml_escape(self.boot_caps.cmdline) osblob += " " elif hvm: if self.boot_caps.bootdev: @@ -137,7 +137,7 @@ class ImageInstaller(Guest.Installer): osblob += " " elif self.boot_caps.loader == "pygrub" or (self.boot_caps.loader is None and self.boot_caps.type == "xen"): osblob += " \n" - osblob += " %s" % util.pygrub_path(conn) + osblob += " %s" % _util.pygrub_path(conn) return osblob diff --git a/virtinst/Storage.py b/virtinst/Storage.py --- a/virtinst/Storage.py +++ b/virtinst/Storage.py @@ -52,7 +52,7 @@ import logging import logging from xml.sax.saxutils import escape -import util +import _util from virtinst import _virtinst as _ DEFAULT_DEV_TARGET = "/dev" @@ -112,7 +112,7 @@ class StorageObject(object): 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): + if not _util.is_storage_capable(val): raise ValueError(_("Passed connection is not libvirt storage " "capable")) self._conn = val @@ -278,7 +278,7 @@ class StoragePool(StorageObject): self._source_path = None if not uuid: self._uuid = None - self._random_uuid = util.uuidToString(util.randomUUID()) + self._random_uuid = _util.uuidToString(_util.randomUUID()) # Properties used by all pools def get_type(self): @@ -705,7 +705,7 @@ class StorageVolume(StorageObject): 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")) + 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, @@ -756,7 +756,7 @@ class StorageVolume(StorageObject): 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): + if not _util.is_storage_capable(conn): raise ValueError(_("Connection does not support storage " "management.")) try: diff --git a/virtinst/VirtualDevice.py b/virtinst/VirtualDevice.py --- a/virtinst/VirtualDevice.py +++ b/virtinst/VirtualDevice.py @@ -22,7 +22,7 @@ import libvirt import libvirt import CapabilitiesParser -import util +import _util from virtinst import _virtinst as _ class VirtualDevice(object): @@ -45,7 +45,7 @@ class VirtualDevice(object): self.__remote = None if self.conn: - self.__remote = util.is_uri_remote(self.conn.getURI()) + self.__remote = _util.is_uri_remote(self.conn.getURI()) self._caps = None if self.conn: diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -24,7 +24,7 @@ import logging import logging import libvirt -import util +import _util import Storage from VirtualDevice import VirtualDevice from virtinst import _virtinst as _ @@ -302,7 +302,7 @@ class VirtualDisk(VirtualDevice): "('poolname', 'volname')")) if not self.conn: raise ValueError(_("'volName' requires a passed connection.")) - if not util.is_storage_capable(self.conn): + if not _util.is_storage_capable(self.conn): raise ValueError(_("Connection does not support storage lookup.")) try: pool = self.conn.storagePoolLookupByName(name_tuple[0]) @@ -321,7 +321,7 @@ class VirtualDisk(VirtualDevice): def __check_if_path_managed(self): vol = None verr = None - pool = util.lookup_pool_by_path(self.conn, + pool = _util.lookup_pool_by_path(self.conn, os.path.dirname(self.path)) if pool: try: @@ -378,7 +378,7 @@ class VirtualDisk(VirtualDevice): # if no obj: if remote, error storage_capable = False if self.conn: - storage_capable = util.is_storage_capable(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.") @@ -528,7 +528,7 @@ class VirtualDisk(VirtualDevice): elif self.path: path = self.path if path: - path = util.xml_escape(path) + path = _util.xml_escape(path) ret = " \n" % { "type": self.type, "device": self.device } if not(self.driver_name is None): diff --git a/virtinst/_util.py b/virtinst/_util.py new file mode 100644 --- /dev/null +++ b/virtinst/_util.py @@ -0,0 +1,543 @@ +# +# 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. + +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 _ +from virtinst import CapabilitiesParser + + +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.""" + + 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 privileged_user(): + 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_blktap_capable(): + if platform.system() == 'SunOS': + return False + + 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 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 blkdev_size(path): + """Return the size of the block device. We can't use os.stat() as + that returns zero on many platforms.""" + fd = os.open(path, os.O_RDONLY) + # os.SEEK_END is not present on all systems + size = os.lseek(fd, 0, 2) + os.close(fd) + return size + +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 + keymap = "en-us" + 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 and keytable.keytable.has_key(kt.lower()): + keymap = keytable.keytable[kt] + else: + logging.debug("Didn't find keymap '%s' in keytable!" % kt) + 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): + """return the xpath from the passed xml""" + doc = None + ctx = None + result = None + try: + doc = libxml2.parseDoc(xml) + ctx = doc.xpathNewContext() + ret = ctx.xpathEval(path) + val = None + if ret != None: + if type(ret) == list: + if len(ret) == 1: + val = ret[0].content + else: + val = ret + result = val + 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. + @return virStoragePool object if found, None otherwise + """ + if not is_storage_capable(conn): + return None + + pool_list = conn.listStoragePools() + conn.listDefinedStoragePools() + for name in pool_list: + pool = conn.storagePoolLookupByName(name) + xml_path = get_xml_path(pool.XMLDesc(0), "/pool/target/path") + if os.path.abspath(xml_path) == path: + return pool + return None + +def privileged_user(): + """ + Return true if the user is privileged enough. On Linux, this + equates to being root. On Solaris, it's more complicated, so we + just assume we're OK. + """ + return os.uname()[0] == 'SunOS' or os.geteuid() == 0 + +def _test(): + import doctest + doctest.testmod() + +if __name__ == "__main__": + _test() diff --git a/virtinst/cli.py b/virtinst/cli.py --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -26,7 +26,7 @@ from optparse import OptionValueError, O from optparse import OptionValueError, OptionParser import libvirt -import util +import _util from virtinst import CapabilitiesParser, VirtualNetworkInterface, \ VirtualGraphics, VirtualAudio from virtinst import _virtinst as _ @@ -118,7 +118,7 @@ def nice_exit(): def getConnection(connect): if connect and connect.lower()[0:3] == "xen": - if not util.privileged_user(): + if not _util.privileged_user(): fail(_("Must be root to create Xen guests")) if connect is None: fail(_("Could not find usable default libvirt connection.")) @@ -298,8 +298,8 @@ def digest_networks(conn, macs, bridges, # With just one mac, create a default network if one is not # specified. if len(macs) == 1 and len(networks) == 0: - if util.privileged_user(): - net = util.default_network(conn) + if _util.privileged_user(): + net = _util.default_network(conn) networks.append(net[0] + ":" + net[1]) else: networks.append("user") @@ -316,8 +316,8 @@ def digest_networks(conn, macs, bridges, # Create extra networks up to the number of nics requested if len(macs) < nics: for dummy in range(len(macs),nics): - if util.privileged_user(): - net = util.default_network(conn) + if _util.privileged_user(): + net = _util.default_network(conn) networks.append(net[0] + ":" + net[1]) else: networks.append("user") diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -1,5 +1,3 @@ -# -# Utility functions used for guest installation # # Copyright 2006 Red Hat, Inc. # Jeremy Katz @@ -19,107 +17,60 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA. +# +# WARNING: this file sadly forms part of the public API. Do not add +# anything to this file! The file for internal utility functions is +# _util.py +# + import platform -import random -import os.path -import re -import libxml2 -import logging -from sys import stderr +import os -import libvirt -from virtinst import _virtinst as _ -from virtinst import CapabilitiesParser +from virtinst import _util KEYBOARD_DIR = "/etc/sysconfig/keyboard" XORG_CONF = "/etc/X11/xorg.conf" -def default_route(): - route_file = "/proc/net/route" - d = file(route_file) +default_route = _util.default_route +default_bridge = _util.default_bridge +default_network = _util.default_network +default_connection = _util.default_connection +get_cpu_flags = _util.get_cpu_flags +is_pae_capable = _util.is_pae_capable +is_blktap_capable = _util.is_blktap_capable +get_default_arch = _util.get_default_arch +randomMAC = _util.randomMAC +randomUUID = _util.randomUUID +uuidToString = _util.uuidToString +uuidFromString = _util.uuidFromString +get_host_network_devices = _util.get_host_network_devices +get_max_vcpus = _util.get_max_vcpus +get_phy_cpus = _util.get_phy_cpus +xml_escape = _util.xml_escape +compareMAC = _util.compareMAC +default_keymap = _util.default_keymap +pygrub_path = _util.pygrub_path +uri_split = _util.uri_split +is_uri_remote = _util.is_uri_remote +get_uri_hostname = _util.get_uri_hostname +get_uri_transport = _util.get_uri_transport +get_uri_driver = _util.get_uri_driver +is_storage_capable = _util.is_storage_capable +get_xml_path = _util.get_xml_path +lookup_pool_by_path = _util.lookup_pool_by_path +privileged_user = _util.privileged_user - 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 - -# Legacy for compat only. -def default_bridge(): - 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): - 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") and os.path.exists("/proc/xen"): - return "xen" - elif 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 privileged_user(): - return "qemu:///system" - else: - return "qemu:///session" - return None - -def get_cpu_flags(): - 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(): - """Determine if a machine is PAE capable or not.""" - flags = get_cpu_flags() - if "pae" in flags: - return True - return False +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 is_hvm_capable(): """Determine if a machine is HVM capable or not.""" + if platform.system() == 'SunOS': + raise OSError("CPU flags not available") caps = "" if os.path.exists("/sys/hypervisor/properties/capabilities"): @@ -133,389 +84,3 @@ def is_kqemu_capable(): def is_kvm_capable(): return os.path.exists("/dev/kvm") - -def is_blktap_capable(): - #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 blkdev_size(path): - """Return the size of the block device. We can't use os.stat() as - that returns zero on many platforms.""" - fd = os.open(path, os.O_RDONLY) - # os.SEEK_END is not present on all systems - size = os.lseek(fd, 0, 2) - os.close(fd) - return size - -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 - keymap = "en-us" - 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 and keytable.keytable.has_key(kt.lower()): - keymap = keytable.keytable[kt] - else: - logging.debug("Didn't find keymap '%s' in keytable!" % kt) - 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): - """return the xpath from the passed xml""" - doc = None - ctx = None - result = None - try: - doc = libxml2.parseDoc(xml) - ctx = doc.xpathNewContext() - ret = ctx.xpathEval(path) - val = None - if ret != None: - if type(ret) == list: - if len(ret) == 1: - val = ret[0].content - else: - val = ret - result = val - 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. - @return virStoragePool object if found, None otherwise - """ - if not is_storage_capable(conn): - return None - - pool_list = conn.listStoragePools() + conn.listDefinedStoragePools() - for name in pool_list: - pool = conn.storagePoolLookupByName(name) - xml_path = get_xml_path(pool.XMLDesc(0), "/pool/target/path") - if os.path.abspath(xml_path) == path: - return pool - return None - -def privileged_user(): - """ - Return true if the user is privileged enough. On Linux, this - equates to being root. On Solaris, it's more complicated, so we - just assume we're OK. - """ - return os.uname()[0] == 'SunOS' or os.geteuid() == 0 - -def _test(): - import doctest - doctest.testmod() - -if __name__ == "__main__": - _test() From john.levon at sun.com Tue Dec 9 20:44:25 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 09 Dec 2008 12:44:25 -0800 Subject: [et-mgmt-tools] [PATCH] Various disk-related virt-convert fixes Message-ID: <644c0a3190fdf77cc88c.1228855465@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228852674 28800 # Node ID 644c0a3190fdf77cc88cf576abbd7d189254c784 # Parent 4bf39a99d7e438d9ee331cc8b0e10a3aec40ed24 Various disk-related virt-convert fixes. Fix a number of issues with disk handling. Signed-off-by: John Levon diff --git a/virt-convert b/virt-convert --- a/virt-convert +++ b/virt-convert @@ -49,7 +49,8 @@ def parse_args(): opts.add_option("-i", "--input-format", action="store", dest="input_format", help=("Input format, e.g. 'vmx'")) opts.add_option("-o", "--output-format", action="store", - dest="output_format", help=("Output format, e.g. 'virt-image'")) + dest="output_format", default="virt-image", + help=("Output format, e.g. 'virt-image'")) opts.add_option("-D", "--disk-format", action="store", dest="disk_format", help=("Output disk format")) opts.add_option("-v", "--hvm", action="store_true", dest="fullvirt", @@ -89,8 +90,6 @@ def parse_args(): options.output_file = args[1] options.output_dir = os.path.dirname(os.path.realpath(args[1])) - if not options.output_format: - opts.error(("Output format must be defined")) if options.output_format not in formats.formats(): opts.error(("Unknown output format \"%s\"" % options.output_format)) if options.output_format not in formats.output_formats(): diff --git a/virtconv/diskcfg.py b/virtconv/diskcfg.py --- a/virtconv/diskcfg.py +++ b/virtconv/diskcfg.py @@ -40,7 +40,7 @@ disk_suffixes = { disk_suffixes = { DISK_FORMAT_RAW: ".raw", DISK_FORMAT_VMDK: ".vmdk", - DISK_FORMAT_VDISK: ".vdisk.xml", + DISK_FORMAT_VDISK: ".vdisk", } qemu_formats = { @@ -80,6 +80,18 @@ def run_cmd(cmd): proc.tochild.close() ret = proc.wait() return ret, proc.fromchild.readlines(), proc.childerr.readlines() + +def run_vdiskadm(args): + """Run vdiskadm, returning the output.""" + ret, stdout, stderr = run_cmd([ "/usr/sbin/vdiskadm" ] + args) + + if ret != 0: + raise RuntimeError("Disk conversion failed with " + "exit status %d: %s" % (ret, "".join(stderr))) + if len(stderr): + print >> sys.stderr, stderr + + return stdout class disk(object): """Definition of an individual disk instance.""" @@ -101,6 +113,8 @@ class disk(object): for path in self.clean: if os.path.isfile(path): os.remove(path) + if os.path.isdir(path): + os.removedirs(path) self.clean = [] @@ -110,142 +124,151 @@ class disk(object): ensuredirs(outfile) shutil.copy(infile, outfile) - def copy(self, indir, outdir, out_format): - """ - Copy the underlying disk files to a destination, if necessary. - Return True if we need a further conversion step. - """ - - if os.path.isabs(self.path): - return False - - need_copy = False - need_convert = False - - if self.format == out_format: - need_convert = False - need_copy = (indir != outdir) - else: - if out_format == DISK_FORMAT_NONE: - need_copy = (indir != outdir) - need_convert = False - else: - need_copy = (indir != outdir and out_format == DISK_FORMAT_VDISK) - need_convert = True - - if need_copy: - if out_format == DISK_FORMAT_VDISK: - # copy any sub-files for the disk as well as the disk - # itself - ret, stdout, stderr = run_cmd(["/usr/lib/xen/bin/vdiskadm", "import", - "-npqf", os.path.join(indir, self.path)]) - - if ret != 0: - raise RuntimeError("Disk conversion failed with " - "exit status %d: %s" % (ret, "".join(stderr))) - if len(stderr): - print >> sys.stderr, stderr - - stubpath = os.path.dirname(self.path) - - for item in stdout: - typ, path = item.strip().split(':', 1) - if not (typ == "snapshot" or typ == "file"): - continue - infile = os.path.join(indir, stubpath, path) - outfile = os.path.join(outdir, stubpath, path) - self.copy_file(infile, outfile) - - return need_convert - - # this is not correct for all VMDK files, but it will have - # to do for now - self.copy_file(os.path.join(indir, self.path), - os.path.join(outdir, self.path)) - - return need_convert - - def convert(self, indir, outdir, output_format): - """ - Convert a disk into the requested format if possible, in the - given output directory. Raises RuntimeError or other - failures. - """ - - if self.type != DISK_TYPE_DISK: - return - - out_format = disk_format_names[output_format] - indir = os.path.normpath(os.path.abspath(indir)) - outdir = os.path.normpath(os.path.abspath(outdir)) - - need_convert = self.copy(indir, outdir, out_format) - if not need_convert: - return - - relin = self.path + def out_file(self, out_format): + """Return the relative path of the output file.""" relout = self.path.replace(disk_suffixes[self.format], disk_suffixes[out_format]) - absin = os.path.join(indir, relin) - absout = os.path.join(outdir, relout) - - if not (out_format == DISK_FORMAT_VDISK or - out_format == DISK_FORMAT_RAW or out_format == DISK_FORMAT_VMDK): - raise NotImplementedError("Cannot convert to disk format %s" % - output_format) - - ensuredirs(absout) - - if out_format != DISK_FORMAT_VDISK: - - self.clean += [ absout ] - - ret, stdout, stderr = run_cmd(["qemu-img", "convert", "-O", - qemu_formats[out_format], absin, absout]) - if ret != 0: - raise RuntimeError("Disk conversion failed with " - "exit status %d: %s" % (ret, "".join(stderr))) - if len(stderr): - print >> sys.stderr, stderr - - self.path = relout - self.format = out_format - return - - # - # The presumption is that the top-level disk name can't contain - # spaces, but the sub-disks can. We don't want to break an - # existing config if we're doing it in-place, so be careful - # about copying versus moving. - # - spath = re.sub(r'\s', '_', relin) - if spath != relin: - infile = os.path.join(outdir, relin) - outfile = os.path.join(outdir, spath) - if indir == outdir: - shutil.copy(infile, outfile) - else: - shutil.move(infile, outfile) - self.path = spath - relin = spath - - ret, stdout, stderr = run_cmd(["/usr/lib/xen/bin/vdiskadm", "import", - "-fp", os.path.join(outdir, relin)]) - + return re.sub(r'\s', '_', relout) + + def vdisk_convert(self, absin, absout): + """ + Import the given disk into vdisk, including any sub-files as + necessary. + """ + + stdout = run_vdiskadm([ "import", "-fnp", absin, absout ]) + + for item in stdout: + ignore, path = item.strip().split(':', 1) + self.clean += [ os.path.join(absout, path) ] + + run_vdiskadm([ "import", "-fp", absin, absout ]) + + def qemu_convert(self, absin, absout, out_format): + """ + Use qemu-img to convert the given disk. Note that at least some + version of qemu-img cannot handle multi-file VMDKs, so this can + easily go wrong. + """ + + self.clean += [ absout ] + + ret, ignore, stderr = run_cmd(["qemu-img", "convert", "-O", + qemu_formats[out_format], absin, absout]) if ret != 0: raise RuntimeError("Disk conversion failed with " "exit status %d: %s" % (ret, "".join(stderr))) if len(stderr): print >> sys.stderr, stderr - stubpath = os.path.dirname(relin) - - for item in stdout: - typ, path = item.strip().split(':', 1) - if typ == "store": - path = os.path.join(stubpath, path) - self.clean += [ os.path.join(outdir, path) ] - self.format = out_format + def copy(self, indir, outdir, out_format): + """ + If needed, copy top-level disk files to outdir. If the copy is + done, then self.path is updated as needed. + + Returns (input_in_outdir, need_conversion) + """ + + need_conversion = (out_format != DISK_FORMAT_NONE and + self.format != out_format) + + if os.path.isabs(self.path): + return True, need_conversion + + relin = self.path + absin = os.path.join(indir, relin) + relout = self.out_file(self.format) + absout = os.path.join(outdir, relout) + + # + # If we're going to use vdiskadm, it's much smarter; don't + # attempt any copies. + # + if out_format == DISK_FORMAT_VDISK: + return False, True + + # + # If we're using the same directory, just account for any spaces + # in the disk filename and we're done. + # + if indir == outdir: + if relin != relout: + # vdisks cannot have spaces + if self.format == DISK_FORMAT_VDISK: + raise RuntimeError("Disk conversion failed: " + "invalid vdisk '%s'" % self.path) + self.clean += [ absout ] + self.copy_file(absin, absout) + self.path = relout + return True, need_conversion + + # + # If we're not performing any conversion, just copy the file. + # XXX: This can go wrong for multi-part disks! + # + if not need_conversion: + self.clean += [ absout ] + self.copy_file(absin, absout) + self.path = relout + return True, False + + # + # We're doing a conversion step, so we can rely upon convert() + # to place something in outdir. + # + return False, True + + def convert(self, indir, outdir, output_format): + """ + Convert a disk into the requested format if possible, in the + given output directory. Raises RuntimeError or other failures. + """ + + if self.type != DISK_TYPE_DISK: + return + + out_format = disk_format_names[output_format] + + if os.getenv("VIRTCONV_TEST_NO_DISK_CONVERSION"): + self.path = self.out_file(self.format) + return + + if not (out_format == DISK_FORMAT_NONE or + out_format == DISK_FORMAT_VDISK or + out_format == DISK_FORMAT_RAW): + raise NotImplementedError("Cannot convert to disk format %s" % + output_format) + + indir = os.path.normpath(os.path.abspath(indir)) + outdir = os.path.normpath(os.path.abspath(outdir)) + + input_in_outdir, need_conversion = self.copy(indir, outdir, out_format) + + if not need_conversion: + assert(input_in_outdir) + return + + if os.path.isabs(self.path): + raise NotImplementedError("Cannot convert disk with absolute" + "path %s" % self.path) + + if input_in_outdir: + indir = outdir + + relin = self.path + absin = os.path.join(indir, relin) + relout = self.out_file(out_format) + absout = os.path.join(outdir, relout) + + ensuredirs(absout) + + if out_format == DISK_FORMAT_VDISK: + self.vdisk_convert(absin, absout) + else: + self.qemu_convert(absin, absout, out_format) + + self.format = out_format + self.path = relout def disk_formats(): """ diff --git a/virtconv/parsers/virtimage.py b/virtconv/parsers/virtimage.py --- a/virtconv/parsers/virtimage.py +++ b/virtconv/parsers/virtimage.py @@ -262,8 +262,9 @@ class virtimage_parser(formats.parser): if not vm.memory: raise ValueError("VM must have a memory setting") - # xend wants the name to match r'^[A-Za-z0-9_\-\.\:\/\+]+$' - vmname = re.sub(r'[^A-Za-z0-9_.:/+-]+', '_', vm.name) + # xend wants the name to match r'^[A-Za-z0-9_\-\.\:\/\+]+$', and + # the schema agrees. + vmname = re.sub(r'[^A-Za-z0-9_\-\.:\/\+]+', '_', vm.name) # Hmm. Any interface is a good interface? interface = None diff --git a/virtconv/parsers/vmx.py b/virtconv/parsers/vmx.py --- a/virtconv/parsers/vmx.py +++ b/virtconv/parsers/vmx.py @@ -96,12 +96,12 @@ def parse_netdev_entry(vm, fullkey, valu # "vlance", "vmxnet", "e1000" if key == "virtualdev": - vm.netdevs[inst].driver = value + vm.netdevs[inst].driver = lvalue if key == "addresstype" and lvalue == "generated": vm.netdevs[inst].mac = "auto" # we ignore .generatedAddress for auto mode if key == "address": - vm.netdevs[inst].mac = value + vm.netdevs[inst].mac = lvalue def parse_disk_entry(vm, fullkey, value): """ @@ -124,7 +124,10 @@ def parse_disk_entry(vm, fullkey, value) # Does anyone else think it's scary that we're still doing things # like this? if bus == "ide": - inst = int(inst) + int(bus_nr) * 2 + inst = int(bus_nr) * 2 + (int(inst) % 2) + elif bus == "scsi": + inst = int(bus_nr) * 16 + (int(inst) % 16) + devid = (bus, inst) if not vm.disks.get(devid): From john.levon at sun.com Tue Dec 9 20:44:38 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 09 Dec 2008 12:44:38 -0800 Subject: [et-mgmt-tools] [PATCH] Add support for Solaris PV Message-ID: <5f97d4577a145a71c0b0.1228855478@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228854334 28800 # Node ID 5f97d4577a145a71c0b0ac1d50b0721caa5317ab # Parent 7c692c15dc049d8e62c47ec897ab08979760e032 Add support for Solaris PV Solaris PV comes in two flavours: Nevada and OpenSolaris. In order to correctly build network installs for Nevada, we need to pass down guest options into OSDistro. Signed-off-by: John Levon diff --git a/virtinst/DistroManager.py b/virtinst/DistroManager.py --- a/virtinst/DistroManager.py +++ b/virtinst/DistroManager.py @@ -41,6 +41,8 @@ from OSDistro import DebianDistro from OSDistro import DebianDistro from OSDistro import UbuntuDistro from OSDistro import MandrivaDistro +from OSDistro import SolarisDistro +from OSDistro import OpenSolarisDistro from OSDistro import GenericDistro def _fetcherForURI(uri, scratchdir=None): @@ -87,6 +89,11 @@ def _storeForDistro(fetcher, baseuri, ty stores.append(UbuntuDistro(baseuri, typ, scratchdir, arch)) if distro == "mandriva" or distro is None: stores.append(MandrivaDistro(baseuri, typ, scratchdir, arch)) + # XXX: this is really "nevada" + if distro == "solaris" or distro is None: + stores.append(SolarisDistro(baseuri, type, scratchdir)) + if distro == "solaris" or distro is None: + stores.append(OpenSolarisDistro(baseuri, type, scratchdir)) stores.append(GenericDistro(baseuri, typ, scratchdir, arch)) @@ -100,7 +107,7 @@ def _storeForDistro(fetcher, baseuri, ty # Method to fetch a kernel & initrd pair for a particular distro / HV type -def acquireKernel(baseuri, progresscb, scratchdir="/var/tmp", type=None, +def acquireKernel(guest, baseuri, progresscb, scratchdir="/var/tmp", type=None, distro=None, arch=None): fetcher = _fetcherForURI(baseuri, scratchdir) @@ -113,7 +120,8 @@ def acquireKernel(baseuri, progresscb, s store = _storeForDistro(fetcher=fetcher, baseuri=baseuri, typ=type, progresscb=progresscb, distro=distro, scratchdir=scratchdir, arch=arch) - return store.acquireKernel(fetcher, progresscb) + + return store.acquireKernel(guest, fetcher, progresscb), store.os_type finally: fetcher.cleanupLocation() @@ -239,26 +247,30 @@ class DistroInstaller(Guest.Installer): arch = os.uname()[4] if hasattr(guest, "arch"): arch = guest.arch - (kernelfn, initrdfn, args) = acquireKernel(self.location, - meter, - scratchdir = self.scratchdir, - type = self.os_type, - distro = distro, - arch=arch) + + (kernelfn, initrdfn, args), os_type = acquireKernel(guest, + self.location, meter, scratchdir=self.scratchdir, + type=self.os_type, distro=distro, arch=arch) + + guest.os_type = os_type self.install["kernel"] = kernelfn self.install["initrd"] = initrdfn - if not self.extraargs is None: - self.install["extraargs"] = self.extraargs + " " + args - else: - self.install["extraargs"] = args + self.install["extraargs"] = args self._tmpfiles.append(kernelfn) self._tmpfiles.append(initrdfn) # If they're installing off a local file/device, we map it - # through to a virtual harddisk - if self.location is not None and self.location.startswith("/") and not os.path.isdir(self.location): + # through to a virtual CD or disk + + if (self.location is not None and self.location.startswith("/") + and not os.path.isdir(self.location)): + device = Guest.VirtualDisk.DEVICE_DISK + if guest._lookup_osdict_key('pv_cdrom_install'): + device = Guest.VirtualDisk.DEVICE_CDROM + self._install_disk = VirtualDisk(self.location, + device=device, readOnly=True, transient=True) diff --git a/virtinst/OSDistro.py b/virtinst/OSDistro.py --- a/virtinst/OSDistro.py +++ b/virtinst/OSDistro.py @@ -25,8 +25,10 @@ import re import re import tempfile import platform +import socket import ConfigParser +from virtinst import _util from virtinst import _virtinst as _ def distroFromTreeinfo(fetcher, progresscb, uri, vmtype=None, @@ -83,7 +85,7 @@ class Distro: """Determine if uri points to a tree of the store's distro""" raise NotImplementedError - def acquireKernel(self, fetcher, progresscb): + def acquireKernel(self, guest, fetcher, progresscb): kernelpath = None initrdpath = None if self._hasTreeinfo(fetcher, progresscb): @@ -106,7 +108,7 @@ class Distro: "%(distro)s tree.") % \ { "distro": self.name, "type" : self.type }) - return self._kernelFetchHelper(fetcher, progresscb, kernelpath, + return self._kernelFetchHelper(fetcher, guest, progresscb, kernelpath, initrdpath) def acquireBootDisk(self, fetcher, progresscb): @@ -172,18 +174,21 @@ class Distro: return False - def _kernelFetchHelper(self, fetcher, progresscb, kernelpath, initrdpath): + 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) - if fetcher.location.startswith("/"): - # Local host path, so can't pass a location to guest - #for install method - return (kernel, initrd, "") - else: - return (kernel, initrd, "method=" + fetcher.location) + return kernel, initrd, args except: os.unlink(kernel) @@ -193,6 +198,7 @@ class GenericDistro(Distro): 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", @@ -249,12 +255,12 @@ class GenericDistro(Distro): return True return False - def acquireKernel(self, fetcher, progresscb): + 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, progresscb, + return self._kernelFetchHelper(fetcher, guest, progresscb, self._valid_kernel_path[0], self._valid_kernel_path[1]) @@ -270,6 +276,7 @@ class RedHatDistro(Distro): class RedHatDistro(Distro): name = "Red Hat" + os_type = "linux" uses_treeinfo = True _boot_iso_paths = [ "images/boot.iso" ] _hvm_kernel_paths = [ ("images/pxeboot/vmlinuz", @@ -285,6 +292,7 @@ class FedoraDistro(RedHatDistro): class FedoraDistro(RedHatDistro): name = "Fedora" + os_type = "linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): @@ -300,6 +308,7 @@ class RHELDistro(RedHatDistro): class RHELDistro(RedHatDistro): name = "Red Hat Enterprise Linux" + os_type = "linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): @@ -322,6 +331,7 @@ class CentOSDistro(RedHatDistro): class CentOSDistro(RedHatDistro): name = "CentOS" + os_type = "linux" def isValidStore(self, fetcher, progresscb): if self._hasTreeinfo(fetcher, progresscb): @@ -338,6 +348,7 @@ class SLDistro(RedHatDistro): class SLDistro(RedHatDistro): name = "Scientific Linux" + os_type = "linux" _boot_iso_paths = RedHatDistro._boot_iso_paths + [ "images/SL/boot.iso" ] _hvm_kernel_paths = RedHatDistro._hvm_kernel_paths + \ [ ("images/SL/pxeboot/vmlinuz", @@ -361,6 +372,7 @@ class SuseDistro(Distro): class SuseDistro(Distro): name = "SUSE" + os_type = "linux" _boot_iso_paths = [ "boot/boot.iso" ] _hvm_kernel_paths = [] _xen_kernel_paths = [] @@ -385,11 +397,11 @@ class SuseDistro(Distro): return True return False - def acquireKernel(self, fetcher, progresscb): + def acquireKernel(self, guest, fetcher, progresscb): # If installing a fullvirt guest if self.type is None or self.type == "hvm" or \ fetcher.hasFile("boot/%s/vmlinuz-xen" % self.arch): - return Distro.acquireKernel(self, fetcher, progresscb) + 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") @@ -590,6 +602,7 @@ class DebianDistro(Distro): # daily builds: http://people.debian.org/~joeyh/d-i/ name = "Debian" + os_type = "linux" def __init__(self, uri, vmtype=None, scratchdir=None, arch=None): Distro.__init__(self, uri, vmtype, scratchdir, arch) @@ -642,6 +655,7 @@ class UbuntuDistro(DebianDistro): class UbuntuDistro(DebianDistro): name = "Ubuntu" + os_type = "linux" def _set_media_paths(self): DebianDistro._set_media_paths(self) @@ -672,6 +686,7 @@ 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")] @@ -692,3 +707,192 @@ class MandrivaDistro(Distro): 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): + 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, 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. + 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.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 + 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): + kernelpath = "platform/i86xpv/kernel/unix" + initrdpath = "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, kargs, smfargs, kbargs) = \ + self.process_extra_args(guest.extraargs) + + args = '' + if kopts: + args += '-' + kopts + if kbargs: + args += ' -B ' + kbargs + + 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.initrdpath, progresscb) + return (kernel, initrd, args) + except: + os.unlink(kernel) + raise RuntimeError(_("OpenSolaris microroot not found at %s") % + self.initrdpath) diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -555,6 +555,7 @@ class VirtualDisk(VirtualDevice): if self.target: disknode = self.target + if not disknode: raise ValueError(_("'disknode' or self.target must be set!")) diff --git a/virtinst/osdict.py b/virtinst/osdict.py --- a/virtinst/osdict.py +++ b/virtinst/osdict.py @@ -31,6 +31,7 @@ DEFAULTS = { \ "continue": False, "distro": None, "label": None, + "pv_cdrom_install": False, "devices" : { # "devname" : { "attribute" : [( ["applicable", "hv-type", list"], # "recommended value for hv-types" ),]}, @@ -146,6 +147,7 @@ OS_TYPES = {\ "solaris": { "label": "Solaris", "clock": "localtime", + "pv_cdrom_install": True, "variants": { "solaris9": { "label": "Sun Solaris 9", }, "solaris10": { "label": "Sun Solaris 10", From john.levon at sun.com Tue Dec 9 20:44:15 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Tue, 09 Dec 2008 12:44:15 -0800 Subject: [et-mgmt-tools] [PATCH] Add vdisk support Message-ID: <4bf39a99d7e438d9ee33.1228855455@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228852538 28800 # Node ID 4bf39a99d7e438d9ee331cc8b0e10a3aec40ed24 # Parent 50ca2624e7ef5713153ef85c012326fdae125b7f Add vdisk support Add support for the vdisk format used in Solaris. Signed-off-by: John Levon diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -21,6 +21,7 @@ import os import os import libxml2 import logging +import subprocess import urlgrabber.progress as progress import _util import libvirt @@ -492,6 +493,15 @@ def start_duplicate(design): logging.debug("start_duplicate out") +def _vdisk_clone(path, clone): + path = os.path.expanduser(path) + clone = os.path.expanduser(clone) + try: + rc = subprocess.call([ '/usr/sbin/vdiskadm', 'clone', path, clone ]) + return rc == 0 + except OSError, e: + return False + # # Now this Cloning method is reading and writing devices. # For future, there are many cloning methods (e.g. fork snapshot cmd). @@ -521,6 +531,14 @@ def _do_duplicate(design): if src_dev == "/dev/null" or src_dev == dst_dev: meter.end(size) continue + + if _util.is_vdisk(src_dev) or (os.path.exists(dst_dev) and _util.is_vdisk(dst_dev)): + if not _util.is_vdisk(src_dev) or os.path.exists(dst_dev): + raise RuntimeError, _("copying to an existing vdisk is not supported") + if not _vdisk_clone(src_dev, dst_dev): + raise RuntimeError, _("failed to clone disk") + continue + # # create sparse file # if a destination file exists and sparse flg is True, diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -474,6 +474,9 @@ class Installer(object): or guest.disks[0].device != VirtualDisk.DEVICE_DISK: return True + if _util.is_vdisk(guest.disks[0].path): + return True + # Check for the 0xaa55 signature at the end of the MBR try: fd = os.open(guest.disks[0].path, os.O_RDONLY) diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -20,6 +20,7 @@ # MA 02110-1301 USA. import os, stat, statvfs +import subprocess import libxml2 import logging import libvirt @@ -28,6 +29,20 @@ import Storage import Storage from VirtualDevice import VirtualDevice from virtinst import _virtinst as _ + +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, e: + return False class VirtualDisk(VirtualDevice): """ @@ -68,7 +83,9 @@ class VirtualDisk(VirtualDevice): DRIVER_TAP_RAW = "aio" DRIVER_TAP_QCOW = "qcow" DRIVER_TAP_VMDK = "vmdk" - driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, DRIVER_TAP_VMDK] + DRIVER_TAP_VDISK = "vdisk" + driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, + DRIVER_TAP_VMDK, DRIVER_TAP_VDISK] DEVICE_DISK = "disk" DEVICE_CDROM = "cdrom" @@ -143,6 +160,10 @@ class VirtualDisk(VirtualDevice): if volName: self.__lookup_vol_name(volName) + if self._type == self.TYPE_FILE and _util.is_vdisk(self._path): + self._driverName = self.DRIVER_TAP + self._driverType = self.DRIVER_TAP_VDISK + self.__validate_params() @@ -285,6 +306,9 @@ class VirtualDisk(VirtualDevice): dtype = self.TYPE_BLOCK else: dtype = self.TYPE_FILE + if _util.is_vdisk(self.path): + self._driverName = self.DRIVER_TAP + self._driverType = self.DRIVER_TAP_VDISK logging.debug("Detected storage as type '%s'" % dtype) if self.type is not None and dtype != self.type: @@ -424,7 +448,8 @@ class VirtualDisk(VirtualDevice): or self.vol_object): logging.debug("VirtualDisk storage exists.") - if using_path and os.path.isdir(self.path): + if (using_path and os.path.isdir(self.path) and + not _util.is_vdisk(self.path)): raise ValueError, _("The path must be a file or a device," " not a directory") self.__set_dev_type() @@ -476,13 +501,24 @@ class VirtualDisk(VirtualDevice): self._set_vol_object(self.vol_install.install(meter=progresscb), validate=False) return - elif self.type == VirtualDisk.TYPE_FILE and self.path is not None \ - and not os.path.exists(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): + progresscb.update(1024) + if (not _vdisk_create(self.path, size_bytes, "vmdk", + 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: diff --git a/virtinst/_util.py b/virtinst/_util.py --- a/virtinst/_util.py +++ b/virtinst/_util.py @@ -27,6 +27,7 @@ import libxml2 import libxml2 import logging import subprocess +import commands from sys import stderr import libvirt @@ -281,10 +282,25 @@ def xml_escape(str): str = str.replace(">", ">") return str +def is_vdisk(path): + if not os.path.exists("/usr/sbin/vdiskadm"): + return False + if not os.path.exists(path): + return True + if os.path.isdir(path) and \ + os.path.exists(path + "/vdisk.xml"): + return True + return False + def stat_disk(path): """Returns the tuple (isreg, size).""" if not os.path.exists(path): return True, 0 + + if is_vdisk(path): + size = int(commands.getoutput( + "vdiskadm prop-get -p max-size " + path)) + return True, size mode = os.stat(path)[stat.ST_MODE] From crobinso at redhat.com Tue Dec 9 21:40:42 2008 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 09 Dec 2008 16:40:42 -0500 Subject: [et-mgmt-tools] [PATCH] Fix get_graphics() In-Reply-To: <3a48e2d3594b3e7e1d24.1228855418@xenbld.SFBay.Sun.COM> References: <3a48e2d3594b3e7e1d24.1228855418@xenbld.SFBay.Sun.COM> Message-ID: <493EE5DA.80502@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228851589 28800 > # Node ID 3a48e2d3594b3e7e1d24147f3325ab6024557504 > # Parent 419fb59763dc86b8f6abf26e4fb7ba6f7ba54182 > Fix get_graphics() > > The key needs to be 'enabled' not 'enabled '. > Thanks, applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=159018031462 - Cole From crobinso at redhat.com Tue Dec 9 22:13:05 2008 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 09 Dec 2008 17:13:05 -0500 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: <29d8886362e2993eaf26.1228855430@xenbld.SFBay.Sun.COM> References: <29d8886362e2993eaf26.1228855430@xenbld.SFBay.Sun.COM> Message-ID: <493EED71.4070504@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228851891 28800 > # Node ID 29d8886362e2993eaf26cf8d4e948b2de4b8d9ec > # Parent 3a48e2d3594b3e7e1d24147f3325ab6024557504 > Port utility functions to Solaris > Hmm, 90% of this patch is a huge mechanical change which has nothing to do with this commit subject. I think it's better to separate the two changes. > Create _util.py for private details of the implementation, along with a > shim for back compatibility. > > Port the utilities to Solaris. > > Signed-off-by: John Levon > > diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py > --- a/virtinst/CloneManager.py > +++ b/virtinst/CloneManager.py > @@ -23,7 +23,7 @@ import libxml2 > import libxml2 > import logging > import urlgrabber.progress as progress > -import util > +import _util Rather than s/util/_util/ everywhere, I'd prefer: import _util as util Lot less churn, and the only potential downside is confusion browsing the source, but I don't think it's a problem. > diff --git a/virtinst/util.py b/virtinst/util.py > --- a/virtinst/util.py > +++ b/virtinst/util.py > @@ -1,5 +1,3 @@ > -# > -# Utility functions used for guest installation > # > # Copyright 2006 Red Hat, Inc. > # Jeremy Katz > @@ -19,107 +17,60 @@ > # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, > # MA 02110-1301 USA. > > +# > +# WARNING: this file sadly forms part of the public API. Do not add > +# anything to this file! The file for internal utility functions is > +# _util.py > +# > + > import platform > -import random > -import os.path > -import re > -import libxml2 > -import logging > -from sys import stderr > +import os > > -import libvirt > -from virtinst import _virtinst as _ > -from virtinst import CapabilitiesParser > +from virtinst import _util > > > KEYBOARD_DIR = "/etc/sysconfig/keyboard" > XORG_CONF = "/etc/X11/xorg.conf" > > -def default_route(): > - route_file = "/proc/net/route" > - d = file(route_file) > +default_route = _util.default_route > +default_bridge = _util.default_bridge > +default_network = _util.default_network > +default_connection = _util.default_connection > +get_cpu_flags = _util.get_cpu_flags > +is_pae_capable = _util.is_pae_capable > +is_blktap_capable = _util.is_blktap_capable > +get_default_arch = _util.get_default_arch > +randomMAC = _util.randomMAC > +randomUUID = _util.randomUUID > +uuidToString = _util.uuidToString > +uuidFromString = _util.uuidFromString > +get_host_network_devices = _util.get_host_network_devices > +get_max_vcpus = _util.get_max_vcpus > +get_phy_cpus = _util.get_phy_cpus > +xml_escape = _util.xml_escape > +compareMAC = _util.compareMAC > +default_keymap = _util.default_keymap > +pygrub_path = _util.pygrub_path > +uri_split = _util.uri_split > +is_uri_remote = _util.is_uri_remote > +get_uri_hostname = _util.get_uri_hostname > +get_uri_transport = _util.get_uri_transport > +get_uri_driver = _util.get_uri_driver > +is_storage_capable = _util.is_storage_capable > +get_xml_path = _util.get_xml_path > +lookup_pool_by_path = _util.lookup_pool_by_path > +privileged_user = _util.privileged_user > Hmm, this isn't exactly how I saw it happening. I figured we would have _util be for nonpublic functions only: we can change or remove anything in that file at will. The original 'util' though needs to maintain api compat for its functions, even if they are deprecated and left to rot. That would mean 'util' would stay the same. '_util' would have whatever new functions you are adding, and the equivalent of the above block of code. Anyone needing a utility function for just the library will add it to _util, and if we ever want to make a private utility public, just move it to 'util'. Am I missing some benefit of the above approach? Or are we just on different pages? (My intention really isn't to be a pest :) ) Thanks, Cole From levon at movementarian.org Tue Dec 9 22:25:57 2008 From: levon at movementarian.org (John Levon) Date: Tue, 9 Dec 2008 22:25:57 +0000 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: <493EED71.4070504@redhat.com> References: <29d8886362e2993eaf26.1228855430@xenbld.SFBay.Sun.COM> <493EED71.4070504@redhat.com> Message-ID: <20081209222557.GA29497@totally.trollied.org.uk> On Tue, Dec 09, 2008 at 05:13:05PM -0500, Cole Robinson wrote: > > Port utility functions to Solaris > > Hmm, 90% of this patch is a huge mechanical change which has nothing > to do with this commit subject. I think it's better to separate > the two changes. Seems like busy work to me quite frankly. You can diff util.py versus _util.py to get the changes easily enough (I tried a rename, but hg was playing silly buggers). > Rather than s/util/_util/ everywhere, I'd prefer: > > import _util as util > > Lot less churn, and the only potential downside is confusion > browsing the source, but I don't think it's a problem. It's already confusing enough, please let's not make it worse. > > +lookup_pool_by_path = _util.lookup_pool_by_path > > +privileged_user = _util.privileged_user > > Hmm, this isn't exactly how I saw it happening. I figured we would have > _util be for nonpublic functions only: we can change or remove anything > in that file at will. The original 'util' though needs to maintain api > compat for its functions, even if they are deprecated and left to rot. The public API has been clearly moving towards an OO approach. This makes perfect sense to me: if I want to interact with a disk, use VirtualDisk. Anything new in virtinst.util is a bug - can you name a situation where it's sensible for something to be added there as part of the API? The very name 'util' basically 'random stuff'. > Am I missing some benefit of the above approach? APIs are really hard to maintain when they're commingled amongst a bunch of other completely unstable code, especially when it's not even documented. Locking away the contents of util.py and never changing it again[1] makes it really hard to *NOT* maintain the API - any patch touches that file implies the patch is broken. Even maintainers as illustrious as your good self need help in spotting mistakes. regards john [1] yes, I'd like to do this will ALL the legacy API, but I admit that's most likely a bridge too far From crobinso at redhat.com Wed Dec 10 03:45:15 2008 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 09 Dec 2008 22:45:15 -0500 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: <20081209222557.GA29497@totally.trollied.org.uk> References: <29d8886362e2993eaf26.1228855430@xenbld.SFBay.Sun.COM> <493EED71.4070504@redhat.com> <20081209222557.GA29497@totally.trollied.org.uk> Message-ID: <493F3B4B.6000006@redhat.com> John Levon wrote: > On Tue, Dec 09, 2008 at 05:13:05PM -0500, Cole Robinson wrote: > > >>> Port utility functions to Solaris >>> >> Hmm, 90% of this patch is a huge mechanical change which has nothing >> to do with this commit subject. I think it's better to separate >> the two changes. >> > > Seems like busy work to me quite frankly. You can diff util.py versus > _util.py to get the changes easily enough (I tried a rename, but hg was > playing silly buggers). > > I really don't think it's unreasonable to ask that these two unrelated changes be split. The commits will be more self contained, and it will be easier for review. >> Rather than s/util/_util/ everywhere, I'd prefer: >> >> import _util as util >> >> Lot less churn, and the only potential downside is confusion >> browsing the source, but I don't think it's a problem. >> > > It's already confusing enough, please let's not make it worse. > > I won't disagree with that. >>> +lookup_pool_by_path = _util.lookup_pool_by_path >>> +privileged_user = _util.privileged_user >>> >> Hmm, this isn't exactly how I saw it happening. I figured we would have >> _util be for nonpublic functions only: we can change or remove anything >> in that file at will. The original 'util' though needs to maintain api >> compat for its functions, even if they are deprecated and left to rot. >> > > The public API has been clearly moving towards an OO approach. This > makes perfect sense to me: if I want to interact with a disk, use > VirtualDisk. Anything new in virtinst.util is a bug - can you name a > situation where it's sensible for something to be added there as part of > the API? The very name 'util' basically 'random stuff'. > > Yes, that's fair. Thinking of it that way, there will always be a better solution than dumping something in 'util'. >> Am I missing some benefit of the above approach? >> > > APIs are really hard to maintain when they're commingled amongst a bunch > of other completely unstable code, especially when it's not even > documented. I completely agree with this, that's why my suggestion was to keep the public and private functions in separate files. Moving everything to the private file seems like it would only encourage confusion between what is public and what is private, increasing the likelyhood that someone would inadvertently break API. > Locking away the contents of util.py and never changing it > again[1] makes it really hard to *NOT* maintain the API - any patch touches > that file implies the patch is broken. > I don't follow this. By moving the actual content to _util.py, API can _still_ be broken: someone could add a new function argument without a default value. I think we can both agree that one of the biggest failures of this code base is a lack of documentation. It can be a total frustration trying to cleanup and fix things, not knowing how the pieces interact. I've been trying to remedy this as I go. Dealing with 'util' is an important step, and I'm not trying to push back on it. Thanks, Cole From levon at movementarian.org Wed Dec 10 12:43:37 2008 From: levon at movementarian.org (John Levon) Date: Wed, 10 Dec 2008 12:43:37 +0000 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: <493F3B4B.6000006@redhat.com> References: <29d8886362e2993eaf26.1228855430@xenbld.SFBay.Sun.COM> <493EED71.4070504@redhat.com> <20081209222557.GA29497@totally.trollied.org.uk> <493F3B4B.6000006@redhat.com> Message-ID: <20081210124337.GA9079@totally.trollied.org.uk> On Tue, Dec 09, 2008 at 10:45:15PM -0500, Cole Robinson wrote: > >> Hmm, 90% of this patch is a huge mechanical change which has nothing > >> to do with this commit subject. I think it's better to separate > >> the two changes. > > I really don't think it's unreasonable to ask that these two unrelated > changes be split. The commits will be more self contained, and it will > be easier for review. Hmpph, OK. > > Locking away the contents of util.py and never changing it > > again[1] makes it really hard to *NOT* maintain the API - any patch touches > > that file implies the patch is broken. > > I don't follow this. By moving the actual content to _util.py, API can > _still_ be broken: someone could add a new function argument without > a default value. I was really referring to someone inadvertently *adding* to the API. I'll go ahead and move most stuff back to util.py. regards john From crobinso at redhat.com Wed Dec 10 15:04:51 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 10 Dec 2008 10:04:51 -0500 Subject: [et-mgmt-tools] [PATCH] Various disk-related virt-convert fixes In-Reply-To: <644c0a3190fdf77cc88c.1228855465@xenbld.SFBay.Sun.COM> References: <644c0a3190fdf77cc88c.1228855465@xenbld.SFBay.Sun.COM> Message-ID: <493FDA93.5000901@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228852674 28800 > # Node ID 644c0a3190fdf77cc88cf576abbd7d189254c784 > # Parent 4bf39a99d7e438d9ee331cc8b0e10a3aec40ed24 > Various disk-related virt-convert fixes. > > Fix a number of issues with disk handling. > Applied: http://hg.et.redhat.com/virt/applications/virtinst--devel?cs=10a5001f9200 Thanks, Cole From crobinso at redhat.com Wed Dec 10 15:05:58 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 10 Dec 2008 10:05:58 -0500 Subject: [et-mgmt-tools] [PATCH] Add utility function for stat() of disks In-Reply-To: <50ca2624e7ef5713153e.1228855443@xenbld.SFBay.Sun.COM> References: <50ca2624e7ef5713153e.1228855443@xenbld.SFBay.Sun.COM> Message-ID: <493FDAD6.2040501@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228851945 28800 > # Node ID 50ca2624e7ef5713153ef85c012326fdae125b7f > # Parent 29d8886362e2993eaf26cf8d4e948b2de4b8d9ec > Add utility function for stat() of disks > ACK to this, I'll commit it once the util stuff is sorted out. Thanks, Cole From john.levon at sun.com Wed Dec 10 15:42:31 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 10 Dec 2008 07:42:31 -0800 Subject: [et-mgmt-tools] [PATCH] Fossilize public virtinst.util API Message-ID: <5101328492a7092d4a3f.1228923751@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228922588 28800 # Node ID 5101328492a7092d4a3f376914b5ffd67b9fdf47 # Parent 1590180314624d0d919b61652b0474fd653b5078 Fossilize public virtinst.util API Make virtinst.util API frozen, and move the utility functions into a private namespace away from the prying eyes of API clients. As a consequence, create a User class for checking privileges. Signed-off-by: John Levon diff --git a/virt-clone b/virt-clone --- a/virt-clone +++ b/virt-clone @@ -29,6 +29,7 @@ import locale import locale import virtinst.cli as cli from virtinst.cli import fail +from virtinst.User import User locale.setlocale(locale.LC_ALL, '') gettext.bindtextdomain(virtinst.gettext_app, virtinst.gettext_dir) @@ -184,9 +185,8 @@ def main(): logging.debug("start clone with HV " + options.connect) - if options.connect is None or options.connect.lower()[0:3] == "xen": - if not virtinst.util.privileged_user(): - fail(_("Must be root to clone Xen guests")) + if not User.current().has_priv(User.PRIV_CLONE, options.connect): + fail(_("Must be privileged to clone Xen guests")) conn = cli.getConnection(options.connect) design = clmgr.CloneDesign(connection=conn) diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -23,7 +23,7 @@ import libxml2 import libxml2 import logging import urlgrabber.progress as progress -import util +import _util import libvirt import Guest from VirtualDisk import VirtualDisk @@ -263,7 +263,7 @@ class CloneDesign(object): node[0].setContent(self._clone_uuid) else: while 1: - uuid = util.uuidToString(util.randomUUID()) + uuid = _util.uuidToString(_util.randomUUID()) if self._check_uuid(uuid) == True: continue else: @@ -278,7 +278,7 @@ class CloneDesign(object): node[0].setContent(self._clone_mac[i-1]) except Exception: while 1: - mac = util.randomMAC(typ) + mac = _util.randomMAC(typ) dummy, msg = self._check_mac(mac) if msg is not None: continue @@ -396,7 +396,7 @@ class CloneDesign(object): for i in lst: mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - size.append(util.blkdev_size(i)) + size.append(_util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) @@ -450,7 +450,7 @@ class CloneDesign(object): continue mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - size.append(util.blkdev_size(i)) + size.append(_util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) diff --git a/virtinst/DistroManager.py b/virtinst/DistroManager.py --- a/virtinst/DistroManager.py +++ b/virtinst/DistroManager.py @@ -22,9 +22,10 @@ import logging import os -import util +import _util import Guest from VirtualDisk import VirtualDisk +from User import User from virtinst import _virtinst as _ import virtinst @@ -158,7 +159,7 @@ class DistroInstaller(Guest.Installer): logging.debug("DistroInstaller location is a (poolname, volname)" " tuple") elif os.path.exists(os.path.abspath(val)) \ - and (not self.conn or not util.is_uri_remote(self.conn.getURI())): + 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) @@ -178,8 +179,8 @@ class DistroInstaller(Guest.Installer): elif (val.startswith("http://") or val.startswith("ftp://") or val.startswith("nfs:")): logging.debug("DistroInstaller location is a network source.") - elif self.conn and util.is_storage_capable(self.conn) and \ - util.is_uri_remote(self.conn.getURI()): + elif self.conn and _util.is_storage_capable(self.conn) and \ + _util.is_uri_remote(self.conn.getURI()): # If conn is specified, pass the path to a VirtualDisk object # and see what comes back try: @@ -193,8 +194,9 @@ class DistroInstaller(Guest.Installer): "or FTP network install source, or an existing " "local file/device")) - if val.startswith("nfs:") and not util.privileged_user(): - raise ValueError(_("NFS installations are only supported as root")) + if (val.startswith("nfs:") and not + User.current().has_priv(User.PRIV_NFS_MOUNT, self.conn.getURI())): + raise ValueError(_('Privilege is required for NFS installations')) self._location = val location = property(get_location, set_location) diff --git a/virtinst/FullVirtGuest.py b/virtinst/FullVirtGuest.py --- a/virtinst/FullVirtGuest.py +++ b/virtinst/FullVirtGuest.py @@ -20,7 +20,7 @@ # MA 02110-1301 USA. import os -import util +import _util import DistroManager import logging import time @@ -38,7 +38,7 @@ class FullVirtGuest(Guest): installer = DistroManager.DistroInstaller(type = type, os_type = "hvm") Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "hd" - self.features = { "acpi": None, "pae": util.is_pae_capable(), "apic": None } + self.features = { "acpi": None, "pae": _util.is_pae_capable(), "apic": None } if arch is None: arch = platform.machine() self.arch = arch diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -26,7 +26,7 @@ import re import re import libxml2 import urlgrabber.progress as progress -import util +import _util import libvirt import platform import __builtin__ @@ -131,7 +131,7 @@ class VirtualNetworkInterface(VirtualDev logging.warn("conflict_net: Failed to lookup domain %d" % name) # get the Host's NIC MACaddress - hostdevs = util.get_host_network_devices() + 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.")) @@ -145,7 +145,7 @@ class VirtualNetworkInterface(VirtualDev def setup(self, conn): if self.macaddr is None: while 1: - self.macaddr = util.randomMAC(type=conn.getType().lower()) + self.macaddr = _util.randomMAC(type=conn.getType().lower()) if self.is_conflict_net(conn)[1] is not None: continue else: @@ -159,7 +159,7 @@ class VirtualNetworkInterface(VirtualDev raise RuntimeError(msg) if not self.bridge and self.type == "bridge": - self.bridge = util.default_bridge() + self.bridge = _util.default_bridge() def get_xml_config(self): src_xml = "" @@ -192,7 +192,7 @@ class VirtualNetworkInterface(VirtualDev try: 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: + if macaddr and _util.compareMAC(self.macaddr, macaddr) == 0: count += 1 finally: if ctx is not None: @@ -250,7 +250,7 @@ class VirtualGraphics(object): return self._keymap def set_keymap(self, val): if not val: - val = util.default_keymap() + val = _util.default_keymap() if not val or type(val) != type("string"): raise ValueError, _("Keymap must be a string") if len(val) > 16: @@ -352,7 +352,7 @@ class Installer(object): return '/var/tmp' if self.type == "xen" and os.path.exists(XEN_SCRATCH): return XEN_SCRATCH - if util.privileged_user() and os.path.exists(LIBVIRT_SCRATCH): + if os.geteuid() == 0 and os.path.exists(LIBVIRT_SCRATCH): return LIBVIRT_SCRATCH else: return os.path.expanduser("~/.virtinst/boot") @@ -407,7 +407,7 @@ class Installer(object): conn=None, kernel=None, bootdev=None): osblob = "" if not isinstall and not ishvm: - return "%s" % util.pygrub_path(conn) + return "%s" % _util.pygrub_path(conn) osblob = "\n" @@ -425,9 +425,9 @@ class Installer(object): osblob += " %s\n" % loader if isinstall and kernel and kernel["kernel"]: - osblob += " %s\n" % util.xml_escape(kernel["kernel"]) - osblob += " %s\n" % util.xml_escape(kernel["initrd"]) - osblob += " %s\n" % util.xml_escape(kernel["extraargs"]) + osblob += " %s\n" % _util.xml_escape(kernel["kernel"]) + osblob += " %s\n" % _util.xml_escape(kernel["initrd"]) + osblob += " %s\n" % _util.xml_escape(kernel["extraargs"]) elif bootdev is not None: osblob += " \n" % bootdev @@ -466,7 +466,7 @@ class Installer(object): @type L{Guest} """ - if util.is_uri_remote(guest.conn.getURI()): + if _util.is_uri_remote(guest.conn.getURI()): # XXX: Use block peek for this? return True @@ -479,7 +479,7 @@ class Installer(object): fd = os.open(guest.disks[0].path, os.O_RDONLY) except OSError, (err, msg): logging.debug("Failed to open guest disk: %s" % msg) - if err == errno.EACCES and not util.privileged_user(): + if err == errno.EACCES and os.geteuid() != 0: return True # non root might not have access to block devices else: raise @@ -624,7 +624,7 @@ class Guest(object): def get_vcpus(self): return self._vcpus def set_vcpus(self, val): - maxvcpus = util.get_max_vcpus(self.conn, self.type) + 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: @@ -642,7 +642,7 @@ class Guest(object): if re.match("^[0-9,-]*$", val) is None: raise ValueError, _("cpuset can only contain numeric, ',', or '-' characters") - pcpus = util.get_phy_cpus(self.conn) + pcpus = _util.get_phy_cpus(self.conn) for c in val.split(','): if c.find('-') != -1: (x, y) = c.split('-') @@ -1061,7 +1061,7 @@ class Guest(object): def _set_defaults(self): if self.uuid is None: while 1: - self.uuid = util.uuidToString(util.randomUUID()) + self.uuid = _util.uuidToString(_util.randomUUID()) try: if self.conn.lookupByUUIDString(self.uuid) is not None: continue diff --git a/virtinst/ImageManager.py b/virtinst/ImageManager.py --- a/virtinst/ImageManager.py +++ b/virtinst/ImageManager.py @@ -23,7 +23,7 @@ import CapabilitiesParser as Cap import CapabilitiesParser as Cap from VirtualDisk import VirtualDisk import os -import util +import _util from virtinst import _virtinst as _ class ImageInstallerException(Exception): @@ -101,7 +101,7 @@ class ImageInstaller(Guest.Installer): d = VirtualDisk(p, s, device = device, type = VirtualDisk.TYPE_FILE) - if self.boot_caps.type == "xen" and util.is_blktap_capable(): + if self.boot_caps.type == "xen" and _util.is_blktap_capable(): d.driver_name = VirtualDisk.DRIVER_TAP d.target = m.target @@ -127,9 +127,9 @@ class ImageInstaller(Guest.Installer): if loader: osblob += " %s\n" % loader if self.boot_caps.kernel: - osblob += " %s\n" % util.xml_escape(self._abspath(self.boot_caps.kernel)) - osblob += " %s\n" % util.xml_escape(self._abspath(self.boot_caps.initrd)) - osblob += " %s\n" % util.xml_escape(self.boot_caps.cmdline) + osblob += " %s\n" % _util.xml_escape(self._abspath(self.boot_caps.kernel)) + osblob += " %s\n" % _util.xml_escape(self._abspath(self.boot_caps.initrd)) + osblob += " %s\n" % _util.xml_escape(self.boot_caps.cmdline) osblob += " " elif hvm: if self.boot_caps.bootdev: @@ -137,7 +137,7 @@ class ImageInstaller(Guest.Installer): osblob += " " elif self.boot_caps.loader == "pygrub" or (self.boot_caps.loader is None and self.boot_caps.type == "xen"): osblob += " \n" - osblob += " %s" % util.pygrub_path(conn) + osblob += " %s" % _util.pygrub_path(conn) return osblob diff --git a/virtinst/Storage.py b/virtinst/Storage.py --- a/virtinst/Storage.py +++ b/virtinst/Storage.py @@ -52,7 +52,7 @@ import logging import logging from xml.sax.saxutils import escape -import util +import _util from virtinst import _virtinst as _ DEFAULT_DEV_TARGET = "/dev" @@ -112,7 +112,7 @@ class StorageObject(object): 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): + if not _util.is_storage_capable(val): raise ValueError(_("Passed connection is not libvirt storage " "capable")) self._conn = val @@ -278,7 +278,7 @@ class StoragePool(StorageObject): self._source_path = None if not uuid: self._uuid = None - self._random_uuid = util.uuidToString(util.randomUUID()) + self._random_uuid = _util.uuidToString(_util.randomUUID()) # Properties used by all pools def get_type(self): @@ -705,7 +705,7 @@ class StorageVolume(StorageObject): 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")) + 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, @@ -756,7 +756,7 @@ class StorageVolume(StorageObject): 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): + if not _util.is_storage_capable(conn): raise ValueError(_("Connection does not support storage " "management.")) try: diff --git a/virtinst/VirtualDevice.py b/virtinst/VirtualDevice.py --- a/virtinst/VirtualDevice.py +++ b/virtinst/VirtualDevice.py @@ -22,7 +22,7 @@ import libvirt import libvirt import CapabilitiesParser -import util +import _util from virtinst import _virtinst as _ class VirtualDevice(object): @@ -45,7 +45,7 @@ class VirtualDevice(object): self.__remote = None if self.conn: - self.__remote = util.is_uri_remote(self.conn.getURI()) + self.__remote = _util.is_uri_remote(self.conn.getURI()) self._caps = None if self.conn: diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -24,7 +24,7 @@ import logging import logging import libvirt -import util +import _util import Storage from VirtualDevice import VirtualDevice from virtinst import _virtinst as _ @@ -302,7 +302,7 @@ class VirtualDisk(VirtualDevice): "('poolname', 'volname')")) if not self.conn: raise ValueError(_("'volName' requires a passed connection.")) - if not util.is_storage_capable(self.conn): + if not _util.is_storage_capable(self.conn): raise ValueError(_("Connection does not support storage lookup.")) try: pool = self.conn.storagePoolLookupByName(name_tuple[0]) @@ -321,7 +321,7 @@ class VirtualDisk(VirtualDevice): def __check_if_path_managed(self): vol = None verr = None - pool = util.lookup_pool_by_path(self.conn, + pool = _util.lookup_pool_by_path(self.conn, os.path.dirname(self.path)) if pool: try: @@ -378,7 +378,7 @@ class VirtualDisk(VirtualDevice): # if no obj: if remote, error storage_capable = False if self.conn: - storage_capable = util.is_storage_capable(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.") @@ -528,7 +528,7 @@ class VirtualDisk(VirtualDevice): elif self.path: path = self.path if path: - path = util.xml_escape(path) + path = _util.xml_escape(path) ret = " \n" % { "type": self.type, "device": self.device } if not(self.driver_name is None): diff --git a/virtinst/__init__.py b/virtinst/__init__.py --- a/virtinst/__init__.py +++ b/virtinst/__init__.py @@ -34,3 +34,4 @@ from LiveCDInstaller import LiveCDInstal from LiveCDInstaller import LiveCDInstaller from ImageManager import ImageInstaller from CloneManager import CloneDesign +from User import User diff --git a/virtinst/util.py b/virtinst/_util.py copy from virtinst/util.py copy to virtinst/_util.py --- a/virtinst/_util.py +++ b/virtinst/_util.py @@ -1,5 +1,3 @@ -# -# Utility functions used for guest installation # # Copyright 2006 Red Hat, Inc. # Jeremy Katz @@ -18,246 +16,17 @@ # 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 random -import os.path -import re -import libxml2 -import logging -from sys import stderr +# +# Internal utility functions. These do NOT form part of the API and must +# not be used by clients. +# -import libvirt -from virtinst import _virtinst as _ -from virtinst import CapabilitiesParser +import os +from virtinst import util -KEYBOARD_DIR = "/etc/sysconfig/keyboard" -XORG_CONF = "/etc/X11/xorg.conf" - -def default_route(): - 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 - -# Legacy for compat only. -def default_bridge(): - 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): - 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") and os.path.exists("/proc/xen"): - return "xen" - elif 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 privileged_user(): - return "qemu:///system" - else: - return "qemu:///session" - return None - -def get_cpu_flags(): - 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(): - """Determine if a machine is PAE capable or not.""" - flags = get_cpu_flags() - if "pae" in flags: - return True - return False - -def is_hvm_capable(): - """Determine if a machine is HVM capable or not.""" - - 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(): - #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 blkdev_size(path): """Return the size of the block device. We can't use os.stat() as that returns zero on many platforms.""" @@ -267,255 +36,33 @@ def blkdev_size(path): os.close(fd) return size -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 - keymap = "en-us" - 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 and keytable.keytable.has_key(kt.lower()): - keymap = keytable.keytable[kt] - else: - logging.debug("Didn't find keymap '%s' in keytable!" % kt) - 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): - """return the xpath from the passed xml""" - doc = None - ctx = None - result = None - try: - doc = libxml2.parseDoc(xml) - ctx = doc.xpathNewContext() - ret = ctx.xpathEval(path) - val = None - if ret != None: - if type(ret) == list: - if len(ret) == 1: - val = ret[0].content - else: - val = ret - result = val - 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. - @return virStoragePool object if found, None otherwise - """ - if not is_storage_capable(conn): - return None - - pool_list = conn.listStoragePools() + conn.listDefinedStoragePools() - for name in pool_list: - pool = conn.storagePoolLookupByName(name) - xml_path = get_xml_path(pool.XMLDesc(0), "/pool/target/path") - if os.path.abspath(xml_path) == path: - return pool - return None - -def privileged_user(): - """ - Return true if the user is privileged enough. On Linux, this - equates to being root. On Solaris, it's more complicated, so we - just assume we're OK. - """ - return os.uname()[0] == 'SunOS' or os.geteuid() == 0 - -def _test(): - import doctest - doctest.testmod() - -if __name__ == "__main__": - _test() +# +# These functions accidentally ended up in the API under virtinst.util +# +default_route = util.default_route +default_bridge = util.default_bridge +default_network = util.default_network +default_connection = util.default_connection +get_cpu_flags = util.get_cpu_flags +is_pae_capable = util.is_pae_capable +is_blktap_capable = util.is_blktap_capable +get_default_arch = util.get_default_arch +randomMAC = util.randomMAC +randomUUID = util.randomUUID +uuidToString = util.uuidToString +uuidFromString = util.uuidFromString +get_host_network_devices = util.get_host_network_devices +get_max_vcpus = util.get_max_vcpus +get_phy_cpus = util.get_phy_cpus +xml_escape = util.xml_escape +compareMAC = util.compareMAC +default_keymap = util.default_keymap +pygrub_path = util.pygrub_path +uri_split = util.uri_split +is_uri_remote = util.is_uri_remote +get_uri_hostname = util.get_uri_hostname +get_uri_transport = util.get_uri_transport +get_uri_driver = util.get_uri_driver +is_storage_capable = util.is_storage_capable +get_xml_path = util.get_xml_path +lookup_pool_by_path = util.lookup_pool_by_path diff --git a/virtinst/cli.py b/virtinst/cli.py --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -26,9 +26,9 @@ from optparse import OptionValueError, O from optparse import OptionValueError, OptionParser import libvirt -import util +import _util from virtinst import CapabilitiesParser, VirtualNetworkInterface, \ - VirtualGraphics, VirtualAudio + VirtualGraphics, VirtualAudio, User from virtinst import _virtinst as _ MIN_RAM = 64 @@ -117,9 +117,8 @@ def nice_exit(): sys.exit(0) def getConnection(connect): - if connect and connect.lower()[0:3] == "xen": - if not util.privileged_user(): - fail(_("Must be root to create Xen guests")) + 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.")) @@ -298,8 +297,8 @@ def digest_networks(conn, macs, bridges, # With just one mac, create a default network if one is not # specified. if len(macs) == 1 and len(networks) == 0: - if util.privileged_user(): - net = util.default_network(conn) + 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") @@ -316,8 +315,8 @@ def digest_networks(conn, macs, bridges, # Create extra networks up to the number of nics requested if len(macs) < nics: for dummy in range(len(macs),nics): - if util.privileged_user(): - net = util.default_network(conn) + 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") diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -18,6 +18,14 @@ # 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 @@ -30,6 +38,7 @@ import libvirt import libvirt from virtinst import _virtinst as _ from virtinst import CapabilitiesParser +from virtinst import User KEYBOARD_DIR = "/etc/sysconfig/keyboard" @@ -54,7 +63,6 @@ def default_route(): continue return None -# Legacy for compat only. def default_bridge(): rt = default_route() if rt is None: @@ -91,7 +99,7 @@ def default_connection(): os.path.exists("/usr/bin/qemu-kvm") or \ os.path.exists("/usr/bin/kvm") or \ os.path.exists("/usr/bin/xenner"): - if privileged_user(): + if User.current().has_priv(User.PRIV_QEMU_SYSTEM): return "qemu:///system" else: return "qemu:///session" @@ -258,15 +266,6 @@ def xml_escape(str): str = str.replace(">", ">") return str -def blkdev_size(path): - """Return the size of the block device. We can't use os.stat() as - that returns zero on many platforms.""" - fd = os.open(path, os.O_RDONLY) - # os.SEEK_END is not present on all systems - size = os.lseek(fd, 0, 2) - os.close(fd) - return size - def compareMAC(p, q): """Compare two MAC addresses""" pa = p.split(":") @@ -505,14 +504,6 @@ def lookup_pool_by_path(conn, path): return pool return None -def privileged_user(): - """ - Return true if the user is privileged enough. On Linux, this - equates to being root. On Solaris, it's more complicated, so we - just assume we're OK. - """ - return os.uname()[0] == 'SunOS' or os.geteuid() == 0 - def _test(): import doctest doctest.testmod() From john.levon at sun.com Wed Dec 10 15:56:27 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 10 Dec 2008 07:56:27 -0800 Subject: [et-mgmt-tools] [PATCH] Fossilize public virtinst.util API Message-ID: <1f7482ff5250d388c7b2.1228924587@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228924505 28800 # Node ID 1f7482ff5250d388c7b22376304002ce16a01301 # Parent 10a5001f9200d6377e8f016fd67c24c16742a9ad Fossilize public virtinst.util API Make virtinst.util API frozen, and move the utility functions into a private namespace away from the prying eyes of API clients. As a consequence, create a User class for checking privileges. Signed-off-by: John Levon diff --git a/virt-clone b/virt-clone --- a/virt-clone +++ b/virt-clone @@ -29,6 +29,7 @@ import locale import locale import virtinst.cli as cli from virtinst.cli import fail +from virtinst.User import User locale.setlocale(locale.LC_ALL, '') gettext.bindtextdomain(virtinst.gettext_app, virtinst.gettext_dir) @@ -184,9 +185,8 @@ def main(): logging.debug("start clone with HV " + options.connect) - if options.connect is None or options.connect.lower()[0:3] == "xen": - if not virtinst.util.privileged_user(): - fail(_("Must be root to clone Xen guests")) + if not User.current().has_priv(User.PRIV_CLONE, options.connect): + fail(_("Must be privileged to clone Xen guests")) conn = cli.getConnection(options.connect) design = clmgr.CloneDesign(connection=conn) diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -23,7 +23,7 @@ import libxml2 import libxml2 import logging import urlgrabber.progress as progress -import util +import _util import libvirt import Guest from VirtualDisk import VirtualDisk @@ -263,7 +263,7 @@ class CloneDesign(object): node[0].setContent(self._clone_uuid) else: while 1: - uuid = util.uuidToString(util.randomUUID()) + uuid = _util.uuidToString(_util.randomUUID()) if self._check_uuid(uuid) == True: continue else: @@ -278,7 +278,7 @@ class CloneDesign(object): node[0].setContent(self._clone_mac[i-1]) except Exception: while 1: - mac = util.randomMAC(typ) + mac = _util.randomMAC(typ) dummy, msg = self._check_mac(mac) if msg is not None: continue @@ -396,7 +396,7 @@ class CloneDesign(object): for i in lst: mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - size.append(util.blkdev_size(i)) + size.append(_util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) @@ -450,7 +450,7 @@ class CloneDesign(object): continue mode = os.stat(i)[stat.ST_MODE] if stat.S_ISBLK(mode): - size.append(util.blkdev_size(i)) + size.append(_util.blkdev_size(i)) typ.append(False) elif stat.S_ISREG(mode): size.append(os.path.getsize(i)) diff --git a/virtinst/DistroManager.py b/virtinst/DistroManager.py --- a/virtinst/DistroManager.py +++ b/virtinst/DistroManager.py @@ -22,9 +22,10 @@ import logging import os -import util +import _util import Guest from VirtualDisk import VirtualDisk +from User import User from virtinst import _virtinst as _ import virtinst @@ -158,7 +159,7 @@ class DistroInstaller(Guest.Installer): logging.debug("DistroInstaller location is a (poolname, volname)" " tuple") elif os.path.exists(os.path.abspath(val)) \ - and (not self.conn or not util.is_uri_remote(self.conn.getURI())): + 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) @@ -178,8 +179,8 @@ class DistroInstaller(Guest.Installer): elif (val.startswith("http://") or val.startswith("ftp://") or val.startswith("nfs:")): logging.debug("DistroInstaller location is a network source.") - elif self.conn and util.is_storage_capable(self.conn) and \ - util.is_uri_remote(self.conn.getURI()): + elif self.conn and _util.is_storage_capable(self.conn) and \ + _util.is_uri_remote(self.conn.getURI()): # If conn is specified, pass the path to a VirtualDisk object # and see what comes back try: @@ -193,8 +194,9 @@ class DistroInstaller(Guest.Installer): "or FTP network install source, or an existing " "local file/device")) - if val.startswith("nfs:") and not util.privileged_user(): - raise ValueError(_("NFS installations are only supported as root")) + if (val.startswith("nfs:") and not + User.current().has_priv(User.PRIV_NFS_MOUNT, self.conn.getURI())): + raise ValueError(_('Privilege is required for NFS installations')) self._location = val location = property(get_location, set_location) diff --git a/virtinst/FullVirtGuest.py b/virtinst/FullVirtGuest.py --- a/virtinst/FullVirtGuest.py +++ b/virtinst/FullVirtGuest.py @@ -20,7 +20,7 @@ # MA 02110-1301 USA. import os -import util +import _util import DistroManager import logging import time @@ -38,7 +38,7 @@ class FullVirtGuest(Guest): installer = DistroManager.DistroInstaller(type = type, os_type = "hvm") Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "hd" - self.features = { "acpi": None, "pae": util.is_pae_capable(), "apic": None } + self.features = { "acpi": None, "pae": _util.is_pae_capable(), "apic": None } if arch is None: arch = platform.machine() self.arch = arch diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -26,7 +26,7 @@ import re import re import libxml2 import urlgrabber.progress as progress -import util +import _util import libvirt import platform import __builtin__ @@ -131,7 +131,7 @@ class VirtualNetworkInterface(VirtualDev logging.warn("conflict_net: Failed to lookup domain %d" % name) # get the Host's NIC MACaddress - hostdevs = util.get_host_network_devices() + 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.")) @@ -145,7 +145,7 @@ class VirtualNetworkInterface(VirtualDev def setup(self, conn): if self.macaddr is None: while 1: - self.macaddr = util.randomMAC(type=conn.getType().lower()) + self.macaddr = _util.randomMAC(type=conn.getType().lower()) if self.is_conflict_net(conn)[1] is not None: continue else: @@ -159,7 +159,7 @@ class VirtualNetworkInterface(VirtualDev raise RuntimeError(msg) if not self.bridge and self.type == "bridge": - self.bridge = util.default_bridge() + self.bridge = _util.default_bridge() def get_xml_config(self): src_xml = "" @@ -192,7 +192,7 @@ class VirtualNetworkInterface(VirtualDev try: 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: + if macaddr and _util.compareMAC(self.macaddr, macaddr) == 0: count += 1 finally: if ctx is not None: @@ -250,7 +250,7 @@ class VirtualGraphics(object): return self._keymap def set_keymap(self, val): if not val: - val = util.default_keymap() + val = _util.default_keymap() if not val or type(val) != type("string"): raise ValueError, _("Keymap must be a string") if len(val) > 16: @@ -352,7 +352,7 @@ class Installer(object): return '/var/tmp' if self.type == "xen" and os.path.exists(XEN_SCRATCH): return XEN_SCRATCH - if util.privileged_user() and os.path.exists(LIBVIRT_SCRATCH): + if os.geteuid() == 0 and os.path.exists(LIBVIRT_SCRATCH): return LIBVIRT_SCRATCH else: return os.path.expanduser("~/.virtinst/boot") @@ -407,7 +407,7 @@ class Installer(object): conn=None, kernel=None, bootdev=None): osblob = "" if not isinstall and not ishvm: - return "%s" % util.pygrub_path(conn) + return "%s" % _util.pygrub_path(conn) osblob = "\n" @@ -425,9 +425,9 @@ class Installer(object): osblob += " %s\n" % loader if isinstall and kernel and kernel["kernel"]: - osblob += " %s\n" % util.xml_escape(kernel["kernel"]) - osblob += " %s\n" % util.xml_escape(kernel["initrd"]) - osblob += " %s\n" % util.xml_escape(kernel["extraargs"]) + osblob += " %s\n" % _util.xml_escape(kernel["kernel"]) + osblob += " %s\n" % _util.xml_escape(kernel["initrd"]) + osblob += " %s\n" % _util.xml_escape(kernel["extraargs"]) elif bootdev is not None: osblob += " \n" % bootdev @@ -466,7 +466,7 @@ class Installer(object): @type L{Guest} """ - if util.is_uri_remote(guest.conn.getURI()): + if _util.is_uri_remote(guest.conn.getURI()): # XXX: Use block peek for this? return True @@ -479,7 +479,7 @@ class Installer(object): fd = os.open(guest.disks[0].path, os.O_RDONLY) except OSError, (err, msg): logging.debug("Failed to open guest disk: %s" % msg) - if err == errno.EACCES and not util.privileged_user(): + if err == errno.EACCES and os.geteuid() != 0: return True # non root might not have access to block devices else: raise @@ -624,7 +624,7 @@ class Guest(object): def get_vcpus(self): return self._vcpus def set_vcpus(self, val): - maxvcpus = util.get_max_vcpus(self.conn, self.type) + 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: @@ -642,7 +642,7 @@ class Guest(object): if re.match("^[0-9,-]*$", val) is None: raise ValueError, _("cpuset can only contain numeric, ',', or '-' characters") - pcpus = util.get_phy_cpus(self.conn) + pcpus = _util.get_phy_cpus(self.conn) for c in val.split(','): if c.find('-') != -1: (x, y) = c.split('-') @@ -1061,7 +1061,7 @@ class Guest(object): def _set_defaults(self): if self.uuid is None: while 1: - self.uuid = util.uuidToString(util.randomUUID()) + self.uuid = _util.uuidToString(_util.randomUUID()) try: if self.conn.lookupByUUIDString(self.uuid) is not None: continue diff --git a/virtinst/ImageManager.py b/virtinst/ImageManager.py --- a/virtinst/ImageManager.py +++ b/virtinst/ImageManager.py @@ -23,7 +23,7 @@ import CapabilitiesParser as Cap import CapabilitiesParser as Cap from VirtualDisk import VirtualDisk import os -import util +import _util from virtinst import _virtinst as _ class ImageInstallerException(Exception): @@ -101,7 +101,7 @@ class ImageInstaller(Guest.Installer): d = VirtualDisk(p, s, device = device, type = VirtualDisk.TYPE_FILE) - if self.boot_caps.type == "xen" and util.is_blktap_capable(): + if self.boot_caps.type == "xen" and _util.is_blktap_capable(): d.driver_name = VirtualDisk.DRIVER_TAP d.target = m.target @@ -127,9 +127,9 @@ class ImageInstaller(Guest.Installer): if loader: osblob += " %s\n" % loader if self.boot_caps.kernel: - osblob += " %s\n" % util.xml_escape(self._abspath(self.boot_caps.kernel)) - osblob += " %s\n" % util.xml_escape(self._abspath(self.boot_caps.initrd)) - osblob += " %s\n" % util.xml_escape(self.boot_caps.cmdline) + osblob += " %s\n" % _util.xml_escape(self._abspath(self.boot_caps.kernel)) + osblob += " %s\n" % _util.xml_escape(self._abspath(self.boot_caps.initrd)) + osblob += " %s\n" % _util.xml_escape(self.boot_caps.cmdline) osblob += " " elif hvm: if self.boot_caps.bootdev: @@ -137,7 +137,7 @@ class ImageInstaller(Guest.Installer): osblob += " " elif self.boot_caps.loader == "pygrub" or (self.boot_caps.loader is None and self.boot_caps.type == "xen"): osblob += " \n" - osblob += " %s" % util.pygrub_path(conn) + osblob += " %s" % _util.pygrub_path(conn) return osblob diff --git a/virtinst/Storage.py b/virtinst/Storage.py --- a/virtinst/Storage.py +++ b/virtinst/Storage.py @@ -52,7 +52,7 @@ import logging import logging from xml.sax.saxutils import escape -import util +import _util from virtinst import _virtinst as _ DEFAULT_DEV_TARGET = "/dev" @@ -112,7 +112,7 @@ class StorageObject(object): 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): + if not _util.is_storage_capable(val): raise ValueError(_("Passed connection is not libvirt storage " "capable")) self._conn = val @@ -278,7 +278,7 @@ class StoragePool(StorageObject): self._source_path = None if not uuid: self._uuid = None - self._random_uuid = util.uuidToString(util.randomUUID()) + self._random_uuid = _util.uuidToString(_util.randomUUID()) # Properties used by all pools def get_type(self): @@ -705,7 +705,7 @@ class StorageVolume(StorageObject): 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")) + 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, @@ -756,7 +756,7 @@ class StorageVolume(StorageObject): 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): + if not _util.is_storage_capable(conn): raise ValueError(_("Connection does not support storage " "management.")) try: diff --git a/virtinst/User.py b/virtinst/User.py new file mode 100644 --- /dev/null +++ b/virtinst/User.py @@ -0,0 +1,74 @@ +# +# 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 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) diff --git a/virtinst/VirtualDevice.py b/virtinst/VirtualDevice.py --- a/virtinst/VirtualDevice.py +++ b/virtinst/VirtualDevice.py @@ -22,7 +22,7 @@ import libvirt import libvirt import CapabilitiesParser -import util +import _util from virtinst import _virtinst as _ class VirtualDevice(object): @@ -45,7 +45,7 @@ class VirtualDevice(object): self.__remote = None if self.conn: - self.__remote = util.is_uri_remote(self.conn.getURI()) + self.__remote = _util.is_uri_remote(self.conn.getURI()) self._caps = None if self.conn: diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -24,7 +24,7 @@ import logging import logging import libvirt -import util +import _util import Storage from VirtualDevice import VirtualDevice from virtinst import _virtinst as _ @@ -302,7 +302,7 @@ class VirtualDisk(VirtualDevice): "('poolname', 'volname')")) if not self.conn: raise ValueError(_("'volName' requires a passed connection.")) - if not util.is_storage_capable(self.conn): + if not _util.is_storage_capable(self.conn): raise ValueError(_("Connection does not support storage lookup.")) try: pool = self.conn.storagePoolLookupByName(name_tuple[0]) @@ -321,7 +321,7 @@ class VirtualDisk(VirtualDevice): def __check_if_path_managed(self): vol = None verr = None - pool = util.lookup_pool_by_path(self.conn, + pool = _util.lookup_pool_by_path(self.conn, os.path.dirname(self.path)) if pool: try: @@ -378,7 +378,7 @@ class VirtualDisk(VirtualDevice): # if no obj: if remote, error storage_capable = False if self.conn: - storage_capable = util.is_storage_capable(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.") @@ -528,7 +528,7 @@ class VirtualDisk(VirtualDevice): elif self.path: path = self.path if path: - path = util.xml_escape(path) + path = _util.xml_escape(path) ret = " \n" % { "type": self.type, "device": self.device } if not(self.driver_name is None): diff --git a/virtinst/__init__.py b/virtinst/__init__.py --- a/virtinst/__init__.py +++ b/virtinst/__init__.py @@ -34,3 +34,4 @@ from LiveCDInstaller import LiveCDInstal from LiveCDInstaller import LiveCDInstaller from ImageManager import ImageInstaller from CloneManager import CloneDesign +from User import User diff --git a/virtinst/util.py b/virtinst/_util.py copy from virtinst/util.py copy to virtinst/_util.py --- a/virtinst/_util.py +++ b/virtinst/_util.py @@ -1,5 +1,3 @@ -# -# Utility functions used for guest installation # # Copyright 2006 Red Hat, Inc. # Jeremy Katz @@ -18,246 +16,17 @@ # 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 random -import os.path -import re -import libxml2 -import logging -from sys import stderr +# +# Internal utility functions. These do NOT form part of the API and must +# not be used by clients. +# -import libvirt -from virtinst import _virtinst as _ -from virtinst import CapabilitiesParser +import os +from virtinst import util -KEYBOARD_DIR = "/etc/sysconfig/keyboard" -XORG_CONF = "/etc/X11/xorg.conf" - -def default_route(): - 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 - -# Legacy for compat only. -def default_bridge(): - 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): - 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") and os.path.exists("/proc/xen"): - return "xen" - elif 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 privileged_user(): - return "qemu:///system" - else: - return "qemu:///session" - return None - -def get_cpu_flags(): - 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(): - """Determine if a machine is PAE capable or not.""" - flags = get_cpu_flags() - if "pae" in flags: - return True - return False - -def is_hvm_capable(): - """Determine if a machine is HVM capable or not.""" - - 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(): - #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 blkdev_size(path): """Return the size of the block device. We can't use os.stat() as that returns zero on many platforms.""" @@ -267,255 +36,33 @@ def blkdev_size(path): os.close(fd) return size -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 - keymap = "en-us" - 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 and keytable.keytable.has_key(kt.lower()): - keymap = keytable.keytable[kt] - else: - logging.debug("Didn't find keymap '%s' in keytable!" % kt) - 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): - """return the xpath from the passed xml""" - doc = None - ctx = None - result = None - try: - doc = libxml2.parseDoc(xml) - ctx = doc.xpathNewContext() - ret = ctx.xpathEval(path) - val = None - if ret != None: - if type(ret) == list: - if len(ret) == 1: - val = ret[0].content - else: - val = ret - result = val - 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. - @return virStoragePool object if found, None otherwise - """ - if not is_storage_capable(conn): - return None - - pool_list = conn.listStoragePools() + conn.listDefinedStoragePools() - for name in pool_list: - pool = conn.storagePoolLookupByName(name) - xml_path = get_xml_path(pool.XMLDesc(0), "/pool/target/path") - if os.path.abspath(xml_path) == path: - return pool - return None - -def privileged_user(): - """ - Return true if the user is privileged enough. On Linux, this - equates to being root. On Solaris, it's more complicated, so we - just assume we're OK. - """ - return os.uname()[0] == 'SunOS' or os.geteuid() == 0 - -def _test(): - import doctest - doctest.testmod() - -if __name__ == "__main__": - _test() +# +# These functions accidentally ended up in the API under virtinst.util +# +default_route = util.default_route +default_bridge = util.default_bridge +default_network = util.default_network +default_connection = util.default_connection +get_cpu_flags = util.get_cpu_flags +is_pae_capable = util.is_pae_capable +is_blktap_capable = util.is_blktap_capable +get_default_arch = util.get_default_arch +randomMAC = util.randomMAC +randomUUID = util.randomUUID +uuidToString = util.uuidToString +uuidFromString = util.uuidFromString +get_host_network_devices = util.get_host_network_devices +get_max_vcpus = util.get_max_vcpus +get_phy_cpus = util.get_phy_cpus +xml_escape = util.xml_escape +compareMAC = util.compareMAC +default_keymap = util.default_keymap +pygrub_path = util.pygrub_path +uri_split = util.uri_split +is_uri_remote = util.is_uri_remote +get_uri_hostname = util.get_uri_hostname +get_uri_transport = util.get_uri_transport +get_uri_driver = util.get_uri_driver +is_storage_capable = util.is_storage_capable +get_xml_path = util.get_xml_path +lookup_pool_by_path = util.lookup_pool_by_path diff --git a/virtinst/cli.py b/virtinst/cli.py --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -26,9 +26,9 @@ from optparse import OptionValueError, O from optparse import OptionValueError, OptionParser import libvirt -import util +import _util from virtinst import CapabilitiesParser, VirtualNetworkInterface, \ - VirtualGraphics, VirtualAudio + VirtualGraphics, VirtualAudio, User from virtinst import _virtinst as _ MIN_RAM = 64 @@ -117,9 +117,8 @@ def nice_exit(): sys.exit(0) def getConnection(connect): - if connect and connect.lower()[0:3] == "xen": - if not util.privileged_user(): - fail(_("Must be root to create Xen guests")) + 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.")) @@ -298,8 +297,8 @@ def digest_networks(conn, macs, bridges, # With just one mac, create a default network if one is not # specified. if len(macs) == 1 and len(networks) == 0: - if util.privileged_user(): - net = util.default_network(conn) + 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") @@ -316,8 +315,8 @@ def digest_networks(conn, macs, bridges, # Create extra networks up to the number of nics requested if len(macs) < nics: for dummy in range(len(macs),nics): - if util.privileged_user(): - net = util.default_network(conn) + 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") diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -18,6 +18,14 @@ # 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 @@ -30,6 +38,7 @@ import libvirt import libvirt from virtinst import _virtinst as _ from virtinst import CapabilitiesParser +from virtinst import User KEYBOARD_DIR = "/etc/sysconfig/keyboard" @@ -54,7 +63,6 @@ def default_route(): continue return None -# Legacy for compat only. def default_bridge(): rt = default_route() if rt is None: @@ -91,7 +99,7 @@ def default_connection(): os.path.exists("/usr/bin/qemu-kvm") or \ os.path.exists("/usr/bin/kvm") or \ os.path.exists("/usr/bin/xenner"): - if privileged_user(): + if User.current().has_priv(User.PRIV_QEMU_SYSTEM): return "qemu:///system" else: return "qemu:///session" @@ -258,15 +266,6 @@ def xml_escape(str): str = str.replace(">", ">") return str -def blkdev_size(path): - """Return the size of the block device. We can't use os.stat() as - that returns zero on many platforms.""" - fd = os.open(path, os.O_RDONLY) - # os.SEEK_END is not present on all systems - size = os.lseek(fd, 0, 2) - os.close(fd) - return size - def compareMAC(p, q): """Compare two MAC addresses""" pa = p.split(":") @@ -505,14 +504,6 @@ def lookup_pool_by_path(conn, path): return pool return None -def privileged_user(): - """ - Return true if the user is privileged enough. On Linux, this - equates to being root. On Solaris, it's more complicated, so we - just assume we're OK. - """ - return os.uname()[0] == 'SunOS' or os.geteuid() == 0 - def _test(): import doctest doctest.testmod() From crobinso at redhat.com Wed Dec 10 19:23:30 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 10 Dec 2008 14:23:30 -0500 Subject: [et-mgmt-tools] [PATCH] Fossilize public virtinst.util API In-Reply-To: <1f7482ff5250d388c7b2.1228924587@xenbld.SFBay.Sun.COM> References: <1f7482ff5250d388c7b2.1228924587@xenbld.SFBay.Sun.COM> Message-ID: <49401732.70207@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228924505 28800 > # Node ID 1f7482ff5250d388c7b22376304002ce16a01301 > # Parent 10a5001f9200d6377e8f016fd67c24c16742a9ad > Fossilize public virtinst.util API > > Make virtinst.util API frozen, and move the utility functions into a > private namespace away from the prying eyes of API clients. > > As a consequence, create a User class for checking privileges. > Thanks! Applied now: http://hg.et.redhat.com/cgi-bin/hg-virt.cgi/applications/virtinst--devel/rev/dd39b8a72e72 - Cole From john.levon at sun.com Wed Dec 10 19:34:21 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 10 Dec 2008 11:34:21 -0800 Subject: [et-mgmt-tools] [PATCH] Add utility function for stat() of disks Message-ID: <8638073ea45665c75319.1228937661@xenbld.SFBay.Sun.COM> # HG changeset patch # User john.levon at sun.com # Date 1228937605 28800 # Node ID 8638073ea45665c7531931515636a862f684c2a5 # Parent e9045f3ae5b2243a9ee00f0913c2dcefdddd7c36 Add utility function for stat() of disks Signed-off-by: John Levon diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -19,7 +19,6 @@ # MA 02110-1301 USA. import os -import stat import libxml2 import logging import urlgrabber.progress as progress @@ -394,13 +393,9 @@ class CloneDesign(object): logging.debug("original device list: %s" % (lst)) for i in lst: - mode = os.stat(i)[stat.ST_MODE] - if stat.S_ISBLK(mode): - size.append(_util.blkdev_size(i)) - typ.append(False) - elif stat.S_ISREG(mode): - size.append(os.path.getsize(i)) - typ.append(True) + (t, sz) = _util.stat_disk(i) + typ.append(t) + size.append(sz) logging.debug("original device size: %s" % (size)) logging.debug("original device type: %s" % (typ)) @@ -443,18 +438,9 @@ class CloneDesign(object): typ = [] for i in cln_dev_lst: - if os.path.exists(i) == False: - size.append(0) - # if not exists, create file necessary - typ.append(True) - continue - mode = os.stat(i)[stat.ST_MODE] - if stat.S_ISBLK(mode): - size.append(_util.blkdev_size(i)) - typ.append(False) - elif stat.S_ISREG(mode): - size.append(os.path.getsize(i)) - typ.append(True) + (t, sz) = _util.stat_disk(i) + typ.append(t) + size.append(sz) logging.debug("clone device list: %s" % (cln_dev_lst)) logging.debug("clone device size: %s" % (size)) diff --git a/virtinst/_util.py b/virtinst/_util.py --- a/virtinst/_util.py +++ b/virtinst/_util.py @@ -23,10 +23,30 @@ # not be used by clients. # +import stat import os from virtinst import util +def stat_disk(path): + """Returns the tuple (isreg, size).""" + if not os.path.exists(path): + return True, 0 + + mode = os.stat(path)[stat.ST_MODE] + + # os.path.getsize('/dev/..') can be zero on some platforms + if stat.S_ISBLK(mode): + fd = os.open(path, os.O_RDONLY) + # os.SEEK_END is not present on all systems + size = os.lseek(fd, 0, 2) + os.close(fd) + return False, size + elif stat.S_ISREG(mode): + return True, os.path.getsize(path) + + return True, 0 + def blkdev_size(path): """Return the size of the block device. We can't use os.stat() as that returns zero on many platforms.""" From john.levon at sun.com Wed Dec 10 19:34:31 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 10 Dec 2008 11:34:31 -0800 Subject: [et-mgmt-tools] [PATCH] Add vdisk support Message-ID: # HG changeset patch # User john.levon at sun.com # Date 1228937605 28800 # Node ID fa56f55633ea7af14af4dd260a00b020a69a2fea # Parent 8638073ea45665c7531931515636a862f684c2a5 Add vdisk support Add support for the vdisk format used in Solaris. Signed-off-by: John Levon diff --git a/virtinst/CloneManager.py b/virtinst/CloneManager.py --- a/virtinst/CloneManager.py +++ b/virtinst/CloneManager.py @@ -21,6 +21,7 @@ import os import os import libxml2 import logging +import subprocess import urlgrabber.progress as progress import _util import libvirt @@ -492,6 +493,15 @@ def start_duplicate(design): logging.debug("start_duplicate out") +def _vdisk_clone(path, clone): + path = os.path.expanduser(path) + clone = os.path.expanduser(clone) + try: + rc = subprocess.call([ '/usr/sbin/vdiskadm', 'clone', path, clone ]) + return rc == 0 + except OSError, e: + return False + # # Now this Cloning method is reading and writing devices. # For future, there are many cloning methods (e.g. fork snapshot cmd). @@ -521,6 +531,14 @@ def _do_duplicate(design): if src_dev == "/dev/null" or src_dev == dst_dev: meter.end(size) continue + + if _util.is_vdisk(src_dev) or (os.path.exists(dst_dev) and _util.is_vdisk(dst_dev)): + if not _util.is_vdisk(src_dev) or os.path.exists(dst_dev): + raise RuntimeError, _("copying to an existing vdisk is not supported") + if not _vdisk_clone(src_dev, dst_dev): + raise RuntimeError, _("failed to clone disk") + continue + # # create sparse file # if a destination file exists and sparse flg is True, diff --git a/virtinst/Guest.py b/virtinst/Guest.py --- a/virtinst/Guest.py +++ b/virtinst/Guest.py @@ -474,6 +474,9 @@ class Installer(object): or guest.disks[0].device != VirtualDisk.DEVICE_DISK: return True + if _util.is_vdisk(guest.disks[0].path): + return True + # Check for the 0xaa55 signature at the end of the MBR try: fd = os.open(guest.disks[0].path, os.O_RDONLY) diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -20,6 +20,7 @@ # MA 02110-1301 USA. import os, stat, statvfs +import subprocess import libxml2 import logging import libvirt @@ -28,6 +29,20 @@ import Storage import Storage from VirtualDevice import VirtualDevice from virtinst import _virtinst as _ + +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, e: + return False class VirtualDisk(VirtualDevice): """ @@ -68,7 +83,9 @@ class VirtualDisk(VirtualDevice): DRIVER_TAP_RAW = "aio" DRIVER_TAP_QCOW = "qcow" DRIVER_TAP_VMDK = "vmdk" - driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, DRIVER_TAP_VMDK] + DRIVER_TAP_VDISK = "vdisk" + driver_types = [DRIVER_TAP_RAW, DRIVER_TAP_QCOW, + DRIVER_TAP_VMDK, DRIVER_TAP_VDISK] DEVICE_DISK = "disk" DEVICE_CDROM = "cdrom" @@ -143,6 +160,10 @@ class VirtualDisk(VirtualDevice): if volName: self.__lookup_vol_name(volName) + if self._type == self.TYPE_FILE and _util.is_vdisk(self._path): + self._driverName = self.DRIVER_TAP + self._driverType = self.DRIVER_TAP_VDISK + self.__validate_params() @@ -285,6 +306,9 @@ class VirtualDisk(VirtualDevice): dtype = self.TYPE_BLOCK else: dtype = self.TYPE_FILE + if _util.is_vdisk(self.path): + self._driverName = self.DRIVER_TAP + self._driverType = self.DRIVER_TAP_VDISK logging.debug("Detected storage as type '%s'" % dtype) if self.type is not None and dtype != self.type: @@ -424,7 +448,8 @@ class VirtualDisk(VirtualDevice): or self.vol_object): logging.debug("VirtualDisk storage exists.") - if using_path and os.path.isdir(self.path): + if (using_path and os.path.isdir(self.path) and + not _util.is_vdisk(self.path)): raise ValueError, _("The path must be a file or a device," " not a directory") self.__set_dev_type() @@ -476,13 +501,24 @@ class VirtualDisk(VirtualDevice): self._set_vol_object(self.vol_install.install(meter=progresscb), validate=False) return - elif self.type == VirtualDisk.TYPE_FILE and self.path is not None \ - and not os.path.exists(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): + progresscb.update(1024) + if (not _vdisk_create(self.path, size_bytes, "vmdk", + 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: diff --git a/virtinst/_util.py b/virtinst/_util.py --- a/virtinst/_util.py +++ b/virtinst/_util.py @@ -23,15 +23,31 @@ # not be used by clients. # +import commands import stat import os from virtinst import util +def is_vdisk(path): + if not os.path.exists("/usr/sbin/vdiskadm"): + return False + if not os.path.exists(path): + return True + if os.path.isdir(path) and \ + os.path.exists(path + "/vdisk.xml"): + return True + return False + def stat_disk(path): """Returns the tuple (isreg, size).""" if not os.path.exists(path): return True, 0 + + if is_vdisk(path): + size = int(commands.getoutput( + "vdiskadm prop-get -p max-size " + path)) + return True, size mode = os.stat(path)[stat.ST_MODE] From john.levon at sun.com Wed Dec 10 19:34:12 2008 From: john.levon at sun.com (john.levon at sun.com) Date: Wed, 10 Dec 2008 11:34:12 -0800 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris Message-ID: # HG changeset patch # User john.levon at sun.com # Date 1228937605 28800 # Node ID e9045f3ae5b2243a9ee00f0913c2dcefdddd7c36 # Parent a1b50ecb6ecef44f3a86bd27da53a8f14687dc38 Port utility functions to Solaris Port the utility functions to Solaris. Signed-off-by: John Levon diff --git a/virtinst/FullVirtGuest.py b/virtinst/FullVirtGuest.py --- a/virtinst/FullVirtGuest.py +++ b/virtinst/FullVirtGuest.py @@ -38,7 +38,8 @@ class FullVirtGuest(Guest): installer = DistroManager.DistroInstaller(type = type, os_type = "hvm") Guest.__init__(self, type, connection, hypervisorURI, installer) self.disknode = "hd" - self.features = { "acpi": None, "pae": _util.is_pae_capable(), "apic": None } + self.features = { "acpi": None, "pae": + _util.is_pae_capable(connection), "apic": None } if arch is None: arch = platform.machine() self.arch = arch diff --git a/virtinst/util.py b/virtinst/util.py --- a/virtinst/util.py +++ b/virtinst/util.py @@ -33,6 +33,7 @@ import re import re import libxml2 import logging +import subprocess from sys import stderr import libvirt @@ -44,7 +45,19 @@ KEYBOARD_DIR = "/etc/sysconfig/keyboard" KEYBOARD_DIR = "/etc/sysconfig/keyboard" XORG_CONF = "/etc/X11/xorg.conf" -def default_route(): +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) @@ -63,7 +76,29 @@ def default_route(): 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 @@ -76,6 +111,9 @@ def default_bridge(): 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()): @@ -93,12 +131,16 @@ def default_network(conn): return ["network", "default"] def default_connection(): - if os.path.exists("/var/lib/xend") and os.path.exists("/proc/xen"): - return "xen" - elif 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 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: @@ -106,6 +148,9 @@ def default_connection(): 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() @@ -119,15 +164,16 @@ def get_cpu_flags(): return flst return [] -def is_pae_capable(): +def is_pae_capable(conn = None): """Determine if a machine is PAE capable or not.""" - flags = get_cpu_flags() - if "pae" in flags: - return True - return False + 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"): @@ -143,6 +189,9 @@ 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() From crobinso at redhat.com Thu Dec 11 15:43:32 2008 From: crobinso at redhat.com (Cole Robinson) Date: Thu, 11 Dec 2008 10:43:32 -0500 Subject: [et-mgmt-tools] [PATCH] Port utility functions to Solaris In-Reply-To: References: Message-ID: <49413524.1070002@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228937605 28800 > # Node ID e9045f3ae5b2243a9ee00f0913c2dcefdddd7c36 > # Parent a1b50ecb6ecef44f3a86bd27da53a8f14687dc38 > Port utility functions to Solaris > > Port the utility functions to Solaris. > > Signed-off-by: John Levon > Thanks, applied. - Cole From crobinso at redhat.com Thu Dec 11 15:43:57 2008 From: crobinso at redhat.com (Cole Robinson) Date: Thu, 11 Dec 2008 10:43:57 -0500 Subject: [et-mgmt-tools] [PATCH] Add utility function for stat() of disks In-Reply-To: <8638073ea45665c75319.1228937661@xenbld.SFBay.Sun.COM> References: <8638073ea45665c75319.1228937661@xenbld.SFBay.Sun.COM> Message-ID: <4941353D.5090404@redhat.com> john.levon at sun.com wrote: > # HG changeset patch > # User john.levon at sun.com > # Date 1228937605 28800 > # Node ID 8638073ea45665c7531931515636a862f684c2a5 > # Parent e9045f3ae5b2243a9ee00f0913c2dcefdddd7c36 > Add utility function for stat() of disks > > Signed-off-by: John Levon > Applied now. Thanks, Cole From mark.juszczec at gmail.com Sat Dec 13 21:51:26 2008 From: mark.juszczec at gmail.com (Mark juszczec) Date: Sat, 13 Dec 2008 16:51:26 -0500 Subject: [et-mgmt-tools] virt-p2v error Message-ID: Hi folks I have my laptop's hard drive partitioned so I can dual boot Fedora Core 9 and WindowsXP: I want to make a vitrual machine out of the XP installation and run it on the FC9 side. Google turned up virt-p2v as the way to do that. I tried and it failed. Message like: shwithstatus: mount -o ro '/dev/sda1' /mnt/root mount: unknown filesystem type 'ntfs' partition detection: /dev/sda1 is Unknown are all over virt-p2v.log What do I have to do to get virt-p2v to recognize my ntfs Windows XP partition? Any help would be greatly appreciated. Thanks. Mark -- http://www.geocities.com/juszczec/shawJCCkarate.html http://myspace.com/juszczeckarate -------------- next part -------------- An HTML attachment was scrubbed... URL: From shemminger at vyatta.com Mon Dec 15 21:06:11 2008 From: shemminger at vyatta.com (Stephen Hemminger) Date: Mon, 15 Dec 2008 13:06:11 -0800 Subject: [et-mgmt-tools] virtual network devices Message-ID: <20081215130611.17e685cc@extreme> Trying to clear up some problems I went in and deleted the virtual network device. Edit->Host Details->Virtual Networks But now there is no way to add a new one (Add) is greyed out. This is on Ubuntu Ibex and using KVM. Where is the configuration located so it can be fixed? From crobinso at redhat.com Mon Dec 15 21:12:34 2008 From: crobinso at redhat.com (Cole Robinson) Date: Mon, 15 Dec 2008 16:12:34 -0500 Subject: [et-mgmt-tools] virtual network devices In-Reply-To: <20081215130611.17e685cc@extreme> References: <20081215130611.17e685cc@extreme> Message-ID: <4946C842.7020603@redhat.com> Stephen Hemminger wrote: > Trying to clear up some problems I went in and deleted the > virtual network device. Edit->Host Details->Virtual Networks > > But now there is no way to add a new one (Add) is greyed out. > This is on Ubuntu Ibex and using KVM. > > Where is the configuration located so it can be fixed? > Is virt-manager definitely 'connected' to the hypervisor? The status field for the connection in the main virt-manager view should read 'Connected'. If so, are you connected to a remote machine? That was at one point disabled needlessly, but is fixed upstream (and in the current release). The fix is here: http://hg.et.redhat.com/cgi-bin/hg-virt.cgi/applications/virt-manager--devel/rev/d7f8c862ae0f - Cole From shemminger at vyatta.com Mon Dec 15 21:50:11 2008 From: shemminger at vyatta.com (Stephen Hemminger) Date: Mon, 15 Dec 2008 13:50:11 -0800 Subject: [et-mgmt-tools] virtual network devices In-Reply-To: <4946C842.7020603@redhat.com> References: <20081215130611.17e685cc@extreme> <4946C842.7020603@redhat.com> Message-ID: <20081215135011.45c64961@extreme> On Mon, 15 Dec 2008 16:12:34 -0500 Cole Robinson wrote: > Stephen Hemminger wrote: > > Trying to clear up some problems I went in and deleted the > > virtual network device. Edit->Host Details->Virtual Networks > > > > But now there is no way to add a new one (Add) is greyed out. > > This is on Ubuntu Ibex and using KVM. > > > > Where is the configuration located so it can be fixed? > > > > Is virt-manager definitely 'connected' to the hypervisor? The status > field for the connection in the main virt-manager view should read > 'Connected'. It comes up Disconnected and then becomes Active. All machines are on localhost. > If so, are you connected to a remote machine? That was at one point > disabled needlessly, but is fixed upstream (and in the current release). > The fix is here: > > http://hg.et.redhat.com/cgi-bin/hg-virt.cgi/applications/virt-manager--devel/rev/d7f8c862ae0f > > - Cole > From crobinso at redhat.com Tue Dec 16 15:29:29 2008 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 16 Dec 2008 10:29:29 -0500 Subject: [et-mgmt-tools] virtual network devices In-Reply-To: <20081215135011.45c64961@extreme> References: <20081215130611.17e685cc@extreme> <4946C842.7020603@redhat.com> <20081215135011.45c64961@extreme> Message-ID: <4947C959.1060704@redhat.com> Stephen Hemminger wrote: > On Mon, 15 Dec 2008 16:12:34 -0500 > Cole Robinson wrote: > >> Stephen Hemminger wrote: >>> Trying to clear up some problems I went in and deleted the >>> virtual network device. Edit->Host Details->Virtual Networks >>> >>> But now there is no way to add a new one (Add) is greyed out. >>> This is on Ubuntu Ibex and using KVM. >>> >>> Where is the configuration located so it can be fixed? >>> >> Is virt-manager definitely 'connected' to the hypervisor? The status >> field for the connection in the main virt-manager view should read >> 'Connected'. > > It comes up Disconnected and then becomes Active. > > All machines are on localhost. > Sorry, I missed the simpler case. Are you running as non-root? Libvirt virtual networks require altering iptables rules and other fun stuff that regular users can't access. Thanks, Cole From arayamajhi at unmc.edu Tue Dec 16 17:03:09 2008 From: arayamajhi at unmc.edu (Atul Rayamajhi) Date: Tue, 16 Dec 2008 11:03:09 -0600 Subject: [et-mgmt-tools] AUTO: Atul Rayamajhi/ITS/UNMC/UNEBR is out of the office. (returning 12/18/2008) Message-ID: I am out of the office until 12/18/2008. I will respond to your message when I return. If you have any question on server please contact Joe Ziskovsky at jziskovs at unmc.edu and for Software Application please contact Steve Pera at spera at unmc.edu Note: This is an automated response to your message "et-mgmt-tools Digest, Vol 28, Issue 28" sent on 12/16/2008 11:00:40 AM. This is the only notification you will receive while this person is away. From plc at novell.com Tue Dec 16 20:50:22 2008 From: plc at novell.com (Pat Campbell) Date: Tue, 16 Dec 2008 13:50:22 -0700 Subject: [et-mgmt-tools][PATCH]:virt-viewer: Load "Send key" menu from XML file Message-ID: <4948148E.6090702@novell.com> Attached patch modifies virt-viewer so that it acquires the "Send key" menu contents from an xml file and allows user to load a browsed for keymap def file while running. Patch is based on hg tip, changeset: 44:92da1556bbf9 Signed-off-by: Pat Campbell -------------- next part -------------- A non-text attachment was scrubbed... Name: virt-viewer-sendkey.patch Type: text/x-patch Size: 33212 bytes Desc: not available URL: From berrange at redhat.com Wed Dec 17 12:36:11 2008 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 17 Dec 2008 12:36:11 +0000 Subject: [et-mgmt-tools][PATCH]:virt-viewer: Load "Send key" menu from XML file In-Reply-To: <4948148E.6090702@novell.com> References: <4948148E.6090702@novell.com> Message-ID: <20081217123611.GF13455@redhat.com> On Tue, Dec 16, 2008 at 01:50:22PM -0700, Pat Campbell wrote: > > Attached patch modifies virt-viewer so that it acquires the "Send key" > menu contents from an xml file and allows user to load a browsed for > keymap def file while running. I like the idea of making it configurable, but not the idea of having the user create & load XML files for this. If a user wants a custom send-key set, they'll likely want it preserved and used across all instances of virt-viewer automatically every time it is started rather than having to load the file. I think we should store the custom send-key sets in GConf, rather than XML files, and at the bottom of the 'send key' menu have an final entry 'Edit keys...' which pops up a dialog allowing the user to add or remove keys from the menu. Just letting them enter the key name (which we can validate by just doing a lookup on the string they enter). GConf would ensure changes in one instance are instant applied to all other running instances. If we want to get adventurous later on we could add 'profiles' to define a set of keys, allowing switching between profiles, and remember which profile is associated with each VM UUID. This would allow user to have one set of keys for Windows VMs, with anothe for Linux, and another for BSD or whatever. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From plc at novell.com Wed Dec 17 15:05:32 2008 From: plc at novell.com (Patrick Campbell) Date: Wed, 17 Dec 2008 08:05:32 -0700 Subject: [et-mgmt-tools][PATCH]:virt-viewer: Load "Send key" menu from XML file In-Reply-To: <20081217123611.GF13455@redhat.com> References: <4948148E.6090702@novell.com> <20081217123611.GF13455@redhat.com> Message-ID: <4949153C.40704@novell.com> Daniel P. Berrange wrote: > On Tue, Dec 16, 2008 at 01:50:22PM -0700, Pat Campbell wrote: > >> Attached patch modifies virt-viewer so that it acquires the "Send key" >> menu contents from an xml file and allows user to load a browsed for >> keymap def file while running. >> > > I like the idea of making it configurable, but not the idea of having > the user create & load XML files for this. > I agree that creating them is an issue, a keymap specific editor within virt-viewer would be the ideal. As to loading them I was thinking of a usage scenario where a user has multiple unique VM to monitor or view. For instance a Linux, Windows XP and a NetWare box. Each of these systems have different keys sequences, enough so that one map might get rather lengthy. In this scenario I thought they would use a bash function for each type: nwviewer() { virt-viewer -k netware.xml "$1";} lviewer() {virt-viewer -k linux.xml "$1";} winxpviewer() {virt-viewer -k winxp.xml "$1";} A little cumbersome but works. For the general case your profile idea below would remove the need for this. > If a user wants a custom send-key set, they'll likely want it preserved > and used across all instances of virt-viewer automatically every time > it is started rather than having to load the file. > In general they would always want the same custom set but I think they need an easy command line option to load an alternative set when necessary. I guess my bias for command line options as opposed to clicking around menus is showing here. > I think we should store the custom send-key sets in GConf, rather than > XML files, and at the bottom of the 'send key' menu have an final > entry 'Edit keys...' which pops up a dialog allowing the user to add > or remove keys from the menu. Just letting them enter the key name (which > we can validate by just doing a lookup on the string they enter). GConf > would ensure changes in one instance are instant applied to all other > running instances. > Not familiar with GConf, will look into that. > If we want to get adventurous later on we could add 'profiles' to define > a set of keys, allowing switching between profiles, and remember which > profile is associated with each VM UUID. This would allow user to have > one set of keys for Windows VMs, with anothe for Linux, and another > for BSD or whatever. > > Daniel > Thanks for the feedback and suggestions. Pat From crobinso at redhat.com Wed Dec 17 20:28:36 2008 From: crobinso at redhat.com (Cole Robinson) Date: Wed, 17 Dec 2008 15:28:36 -0500 Subject: [et-mgmt-tools] [PATCH 0/2]: virt-manager: Revamp preferences dialog In-Reply-To: <493D43A1.5000407@redhat.com> References: <493D43A1.5000407@redhat.com> Message-ID: <494960F4.2040905@redhat.com> Cole Robinson wrote: > Hi, > > The following 2 patches update the virt-manager preferences dialog. The > dialog now uses a tabbed view, providing an easy path for adding new > options. New options are also added for disabling stats polling, per > stats catagories (disk I/O, net I/O, cpu usage, memory usage). > This is pushed now. Thanks, Cole From halsaadi at thoughtworks.com Fri Dec 19 06:49:46 2008 From: halsaadi at thoughtworks.com (Hadi Al-Saadi) Date: Fri, 19 Dec 2008 12:19:46 +0530 Subject: [et-mgmt-tools] cluster Message-ID: HI, How i can i do physical CPU cluster with more then physical Host, with Virtual Machine Manger , so i can have more then CPU running. -Regards Hadi -------------- next part -------------- An HTML attachment was scrubbed... URL: From halsaadi at thoughtworks.com Fri Dec 19 20:44:54 2008 From: halsaadi at thoughtworks.com (Hadi Al-Saadi) Date: Sat, 20 Dec 2008 02:14:54 +0530 Subject: [et-mgmt-tools] cpu cluster Message-ID: hi, can i cluster more then one physical Host cpu with Virtual Machine Manger, so they can act as one Host, for example: i have 4 system, Each one 4 cpu, i want to cluster them togathere and make them act as one Big host, so i can creats my vms under one big host. -------------- next part -------------- An HTML attachment was scrubbed... URL: From felix.schwarz at oss.schwarz.eu Sun Dec 28 14:47:29 2008 From: felix.schwarz at oss.schwarz.eu (Felix Schwarz) Date: Sun, 28 Dec 2008 15:47:29 +0100 Subject: [et-mgmt-tools] Updated German localization for virt-manager Message-ID: <49579181.2010608@oss.schwarz.eu> Hi, I just noticed some spelling errors in the German translation for virt-manager so I fixed at least some of them (there are enough left, just in case someone else likes to contribute ;-). fs -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: spelling.patch URL: From Owen.Mann at interactivedata.com Sun Dec 28 15:00:48 2008 From: Owen.Mann at interactivedata.com (Owen.Mann at interactivedata.com) Date: 28-Dec-2008 10:00:48 EST Subject: [et-mgmt-tools] is out of the office. Message-ID: <200812281516.mBSFGEI5025741@mx3.redhat.com> I will be out of the office starting 12/22/2008 and will not return until 12/29/2008. I will be out of the office until Monday, Dec 29. ----------------------------------------- ******************************************************* This message (including any files transmitted with it) may contain confidential and/or proprietary information, is the property of Interactive Data Corporation and/or its subsidiaries, and is directed only to the addressee(s). If you are not the designated recipient or have reason to believe you received this message in error, please delete this message from your system and notify the sender immediately. An unintended recipient's disclosure, copying, distribution, or use of this message or any attachments is prohibited and may be unlawful. *******************************************************