The implementation of getHostInfo makes some assumptions that are not true in Xen. Specifically, it uses the resources that the host OS (dom0) reports as the actual resources available to guests. This is usually not the case. The memory size reported by /proc/meminfo is the amount dedicated to dom0, i.e. TotalMemory- Sum(GuestMemory). Also, the number of CPUs reported by "os.sysconf('SC_NPROCESSORS_ONLN')" is the number that dom0 is configured to use, which may be less than the total number available. The proper way to get info about the host in Xen is "xm info".

Perhaps this function should be moved to the VmControl class, so that it can be overridden by implementations that get the info in different ways. Patch is below. It also includes some changes to the xen code. Xen now supports different methods of booting via hints.






diff -r 3f66cc24ef92 trunk/etc/TashiDefaults.cfg
--- a/trunk/etc/TashiDefaults.cfg       Fri Apr 17 10:53:55 2009 -0400
+++ b/trunk/etc/TashiDefaults.cfg       Fri Apr 17 13:58:55 2009 -0400
@@ -78,6 +78,9 @@ useMigrateArgument = False
 [XenPV]
 vmNamePrefix = tashi
 transientdir = /tmp
+defaultVmType = kernel
+defaultKernel = /boot/vmlinuz-xen
+defaultRamdisk = /boot/initrd-xen

 [Vfs]
 prefix = /var/tmp/
diff -r 3f66cc24ef92 trunk/src/tashi/nodemanager/nodemanagerservice.py
--- a/trunk/src/tashi/nodemanager/nodemanagerservice.py Fri Apr 17 10:53:55 2009 -0400 +++ b/trunk/src/tashi/nodemanager/nodemanagerservice.py Fri Apr 17 13:58:55 2009 -0400
@@ -98,29 +98,7 @@ class NodeManagerService(object):
                else:
                        success()
                return True
-       
-       def getHostInfo(self):
-               host = Host()
-               host.id = self.id
-               host.name = socket.gethostname()
- memoryStr = os.popen2("head -n 1 /proc/meminfo | awk '{print $2 \" \" $3}'")[1].read().strip()
-               if (memoryStr[-2:] == "kB"):
-                       host.memory = int(memoryStr[:-2])/1024
-               elif (memoryStr[-2:] == "mB"):
-                       host.memory = int(memoryStr[:-2])
-               elif (memoryStr[-2:] == "gB"):
-                       host.memory = int(memoryStr[:-2])*1024
-               elif (memoryStr[-2:] == " B"):
-                       host.memory = int(memoryStr[:-2])/(1024*1024)
-               else:
- self.log.warning('Unable to determine amount of physical memory - reporting 0')
-                       host.memory = 0
-               host.cores = os.sysconf("SC_NPROCESSORS_ONLN")
-               host.up = True
-               host.decayed = False
-               host.version = version
-               return host
-       
+
        def backupVmInfoAndFlushNotifyCM(self):
cm = ConnectionManager(clustermanagerservice.Client, self.cmPort) [self.cmHost]
                while True:
@@ -158,7 +136,7 @@ class NodeManagerService(object):
                while True:
                        start = time.time()
                        try:
-                               host = self.getHostInfo()
+                               host = self.vmm.getHostInfo(self)
                                instances = self.instances.values()
                                self.id = cm.registerNodeManager(host, 
instances)
                        except Exception, e:
diff -r 3f66cc24ef92 trunk/src/tashi/nodemanager/vmcontrol/qemu.py
--- a/trunk/src/tashi/nodemanager/vmcontrol/qemu.py Fri Apr 17 10:53:55 2009 -0400 +++ b/trunk/src/tashi/nodemanager/vmcontrol/qemu.py Fri Apr 17 13:58:55 2009 -0400
@@ -29,7 +29,7 @@ import time

 from tashi.services.ttypes import *
 from tashi.util import broken, logged, scrubString, boolean
-from vmcontrolinterface import VmControlInterface
+from vmcontrolbase import VmControlBase

 log = logging.getLogger(__file__)

@@ -79,7 +79,7 @@ def controlConsole(child, port):
                #print "Thread exiting"
                pass

-class Qemu(VmControlInterface):
+class Qemu(VmControlBase):
        """This class implements the VmControlInterface for Qemu/KVM"""
        
        def __init__(self, config, dfs, nm):
diff -r 3f66cc24ef92 trunk/src/tashi/nodemanager/vmcontrol/ vmcontrolbase.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/tashi/nodemanager/vmcontrol/vmcontrolbase.py Fri Apr 17 13:58:55 2009 -0400
@@ -0,0 +1,49 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+import socket
+from tashi.services.ttypes import Host
+from vmcontrolinterface import VmControlInterface
+
+class VmControlBase(VmControlInterface):
+    '''Base class for VmControl types.  Implements default versions of
+    common functions.'''
+       
+    def getHostInfo(self, nodemanager):
+        print 'called gethostinfo'
+        host = Host()
+        host.id = nodemanager.id
+        host.name = socket.gethostname()
+ memoryStr = os.popen2("head -n 1 /proc/meminfo | awk '{print $2 \" \" $3}'")[1].read().strip()
+        if (memoryStr[-2:] == "kB"):
+            host.memory = int(memoryStr[:-2])/1024
+        elif (memoryStr[-2:] == "mB"):
+            host.memory = int(memoryStr[:-2])
+        elif (memoryStr[-2:] == "gB"):
+            host.memory = int(memoryStr[:-2])*1024
+        elif (memoryStr[-2:] == " B"):
+            host.memory = int(memoryStr[:-2])/(1024*1024)
+        else:
+ self.log.warning('Unable to determine amount of physical memory - reporting 0')
+            host.memory = 0
+        host.cores = os.sysconf("SC_NPROCESSORS_ONLN")
+        host.up = True
+        host.decayed = False
+        host.version = version
+        return host
+
diff -r 3f66cc24ef92 trunk/src/tashi/nodemanager/vmcontrol/ vmcontrolinterface.py --- a/trunk/src/tashi/nodemanager/vmcontrol/vmcontrolinterface.py Fri Apr 17 10:53:55 2009 -0400 +++ b/trunk/src/tashi/nodemanager/vmcontrol/vmcontrolinterface.py Fri Apr 17 13:58:55 2009 -0400
@@ -79,3 +79,6 @@ class VmControlInterface(object):
        def listVms(self):
                """Returns a list of vmIds to the caller"""
                raise NotImplementedError
+        def getHostInfo(self):
+                """Returns a Host object for the current host"""
+                raise NotImplementedError
diff -r 3f66cc24ef92 trunk/src/tashi/nodemanager/vmcontrol/xenpv.py
--- a/trunk/src/tashi/nodemanager/vmcontrol/xenpv.py Fri Apr 17 10:53:55 2009 -0400 +++ b/trunk/src/tashi/nodemanager/vmcontrol/xenpv.py Fri Apr 17 13:58:55 2009 -0400
@@ -22,11 +22,12 @@ import time
 import time
 import threading
 import logging
+import socket

-from vmcontrolinterface import VmControlInterface
+from vmcontrolbase import VmControlBase
from tashi.services.ttypes import Errors, InstanceState, TashiException
 from tashi.services.ttypes import Instance, Host
-from tashi import boolean, convertExceptions, ConnectionManager
+from tashi import boolean, convertExceptions, ConnectionManager, version
 from tashi.util import isolatedRPC

 import tashi.parallel
@@ -90,7 +91,6 @@ def listVms(prefix='tashi'):
                instance.memory = int(vminfo['memory'])
                instance.cores = int(vminfo['cores'])
                instance.disks = []
-
                r[instance.vmId] = instance
        return r

@@ -98,17 +98,16 @@ def listVms(prefix='tashi'):



-class XenPV(VmControlInterface, threading.Thread):
+class XenPV(VmControlBase, threading.Thread):
        def __init__(self, config, dfs, cm):
                threading.Thread.__init__(self)
-               if self.__class__ is VmControlInterface:
-                       raise NotImplementedError
                self.config = config
                self.dfs = dfs
                self.cm = cm

-               self.vmNamePrefix = self.config.get("XenPV", "vmNamePrefix")
+               self.vmNamePrefix = self.config.get('XenPV', 'vmNamePrefix')
                self.transientDir = self.config.get('XenPV', 'transientDir')
+ self.defaultVmType = self.config.get('XenPV', 'defaultVmType')

                self.newvms = listVms(self.vmNamePrefix)
                self.hostId = -1
@@ -142,7 +141,6 @@ class XenPV(VmControlInterface, threadin
                        if not self.newvms.has_key(vmId):
                                print 'WARNING: found vm that should be 
managed, but is not'
                                # FIXME: log that
-                       

        def run(self):
                while(True):
@@ -153,24 +151,61 @@ class XenPV(VmControlInterface, threadin
 # a lot easier
 ########################################
        def createXenConfig(self, vmName,
-                           image, macAddr, memory, cores):
+                           image, macAddr, memory, cores, hints):
                fn = os.path.join("/tmp", vmName)
+                vmType = hints.get('vmtype', self.defaultVmType)
+                print 'starting vm with type: ', vmType
+                bootstr = ''
+                if vmType == 'pvgrub':
+                        # FIXME: untested, requires Xen 3.3
+                        bootstr = '''
+kernel = '/usr/lib/xen/boot/pv-grub-x86_64.gz'
+extra = '(hd0,0)/grub/menu.lst'
+'''
+                elif vmType == 'pygrub':
+                        bootstr = '''
+bootloader="/usr/bin/pygrub"
+'''
+                elif vmType == 'kernel':
+                        kernel = hints.get('kernel', None)
+                        ramdisk = hints.get('ramdisk', None)
+                        if kernel == None:
+                                try:
+ kernel = self.config.get('XenPV', 'defaultKernel')
+                                except:
+ raise Exception, "vmtype=kernel requires kernel= argument"
+                        bootstr = "kernel=\"%s\"\n"%kernel
+                        if ramdisk == None:
+                                try:
+ ramdisk = self.config.get('XenPV', 'defaultRamdisk')
+                                except:
+                                        ramdisk = None
+                        if ramdisk != None:
+ bootstr = bootstr + "ramdisk = \"%s \"\n"%ramdisk
+                elif vmType == 'hvm':
+ # FIXME: untested, I don't have any hvm domains set up
+                        bootstr = '''
+import os, re
+arch = os.uname()[4]
+if re.search('63', arch):
+    arch_libdir = 'lib64'
+else:
+    arch_libdir = 'lib'
+kernel = '/usr/lib/xen/boot/hvmlocader'
+builder = 'hvm'
+'''
+                else:
+ raise Exception, "Unknown vmType in hints: %s"%vmType
                cfgstr = """
-# kernel="/boot/vmlinuz-2.6.24-17-xen"
-# ramdisk="/boot/initrd.img-2.6.24-17-xen"
-bootloader="/usr/bin/pygrub"
 disk=['tap:qcow:%s,xvda1,w']
 vif = [ 'mac=%s' ]
-# vif = ['ip=172.19.158.1']
-# vif = ['']
 memory=%i
-#cpus is a list of cpus for pinning, this is not what we want
-#cpus=%i
+vcpus=%i
 root="/dev/xvda1"
 extra='xencons=tty'
 """%(image, macAddr, memory, cores)
                f = open(fn, "w")
-               f.write(cfgstr)
+               f.write(bootstr+cfgstr)
                f.close()
                return fn
        def deleteXenConfig(self, vmName):
@@ -213,7 +248,8 @@ extra='xencons=tty'
                                          instance.disks[0].local,
                                          instance.nics[0].mac,
                                          instance.memory,
-                                         instance.cores)
+                                         instance.cores,
+                                          instance.hints)
                cmd = "xm create %s"%fn
                r = os.system(cmd)
 #              self.deleteXenConfig(name)
@@ -349,8 +385,10 @@ extra='xencons=tty'


        @synchronizedmethod
-       def getHostInfo(self):
+       def getHostInfo(self, nodemanager):
                host = Host()
+                host.id = nodemanager.id
+                host.name = socket.gethostname()
memp = subprocess.Popen("xm info | awk '/^total_memory/ { print $3 }' ",
                                        shell = True,
                                        stdout = subprocess.PIPE)
@@ -361,6 +399,9 @@ extra='xencons=tty'
                                        stdout = subprocess.PIPE)
                cores = corep.stdout.readline()
                host.cores = int(cores)
+                host.up = True
+                host.decayed = False
+                host.version = version
                return host


Reply via email to