ia64/xen-unstable

changeset 8161:e0d01dd6c4ca

Move the dom0 ballooning-out code from the xm create handler and into the
server, where it can be used on reboot and migrate as well as create.
Ballooning bugs may still exist (it is unclear) but this is certainly a good
step in the right direction.

Ignore the memory and maxmem entries in the store for dom0 when restarting.
This means that the value in use at the time becomes the configured target.
This should fix the bug whereby dom0_mem settings on the command line are
being overridden by (older) entries in the store.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Thu Dec 01 03:39:23 2005 +0000 (2005-12-01)
parents 2e3051c01757
children 5358eceec5ea
files tools/python/xen/xend/XendCheckpoint.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/balloon.py tools/python/xen/xm/create.py
line diff
     1.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Thu Dec 01 03:32:39 2005 +0000
     1.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Thu Dec 01 03:39:23 2005 +0000
     1.3 @@ -18,6 +18,7 @@ import xen.util.auxbin
     1.4  
     1.5  import xen.lowlevel.xc
     1.6  
     1.7 +import balloon
     1.8  from XendError import XendError
     1.9  from XendLogging import log
    1.10  
    1.11 @@ -131,6 +132,8 @@ def restore(xd, fd):
    1.12              raise XendError(
    1.13                  "not a valid guest state file: pfn count out of range")
    1.14  
    1.15 +        balloon.free(xc.pages_to_kib(nr_pfns))
    1.16 +
    1.17          cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
    1.18                          xc.handle(), fd, dominfo.getDomid(), nr_pfns,
    1.19                          store_port, console_port])
    1.20 @@ -213,4 +216,4 @@ def slurp(infile):
    1.21          if line == "":
    1.22              break
    1.23          else:
    1.24 -            log.error('%s', line)
    1.25 +            log.error('%s', line.strip())
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Dec 01 03:32:39 2005 +0000
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Dec 01 03:39:23 2005 +0000
     2.3 @@ -33,6 +33,7 @@ import xen.lowlevel.xc
     2.4  from xen.util import asserts
     2.5  from xen.util.blkif import blkdev_uname_to_file
     2.6  
     2.7 +import balloon
     2.8  import image
     2.9  import sxp
    2.10  import uuid
    2.11 @@ -226,13 +227,13 @@ def recreate(xeninfo, priv):
    2.12                  'Uuid in store does not match uuid for existing domain %d: '
    2.13                  '%s != %s' % (domid, uuid2_str, xeninfo['uuid']))
    2.14  
    2.15 -        vm = XendDomainInfo(xeninfo, domid, dompath, True)
    2.16 +        vm = XendDomainInfo(xeninfo, domid, dompath, True, priv)
    2.17  
    2.18      except Exception, exn:
    2.19          if priv:
    2.20              log.warn(str(exn))
    2.21  
    2.22 -        vm = XendDomainInfo(xeninfo, domid, dompath, True)
    2.23 +        vm = XendDomainInfo(xeninfo, domid, dompath, True, priv)
    2.24          vm.removeDom()
    2.25          vm.removeVm()
    2.26          vm.storeVmDetails()
    2.27 @@ -369,7 +370,8 @@ def dom_get(dom):
    2.28  
    2.29  class XendDomainInfo:
    2.30  
    2.31 -    def __init__(self, info, domid = None, dompath = None, augment = False):
    2.32 +    def __init__(self, info, domid = None, dompath = None, augment = False,
    2.33 +                 priv = False):
    2.34  
    2.35          self.info = info
    2.36  
    2.37 @@ -387,7 +389,7 @@ class XendDomainInfo:
    2.38          self.dompath = dompath
    2.39  
    2.40          if augment:
    2.41 -            self.augmentInfo()
    2.42 +            self.augmentInfo(priv)
    2.43  
    2.44          self.validateInfo()
    2.45  
    2.46 @@ -443,7 +445,7 @@ class XendDomainInfo:
    2.47          return 1
    2.48  
    2.49  
    2.50 -    def augmentInfo(self):
    2.51 +    def augmentInfo(self, priv):
    2.52          """Augment self.info, as given to us through {@link #recreate}, with
    2.53          values taken from the store.  This recovers those values known to xend
    2.54          but not to the hypervisor.
    2.55 @@ -452,8 +454,15 @@ class XendDomainInfo:
    2.56              if not self.infoIsSet(name) and val is not None:
    2.57                  self.info[name] = val
    2.58  
    2.59 -        map(lambda x, y: useIfNeeded(x[0], y), VM_STORE_ENTRIES,
    2.60 -            self.readVMDetails(VM_STORE_ENTRIES))
    2.61 +        if priv:
    2.62 +            entries = VM_STORE_ENTRIES[:]
    2.63 +            entries.remove(('memory', int))
    2.64 +            entries.remove(('maxmem', int))
    2.65 +        else:
    2.66 +            entries = VM_STORE_ENTRIES
    2.67 +
    2.68 +        map(lambda x, y: useIfNeeded(x[0], y), entries,
    2.69 +            self.readVMDetails(entries))
    2.70  
    2.71          device = []
    2.72          for c in controllerClasses:
    2.73 @@ -842,6 +851,9 @@ class XendDomainInfo:
    2.74          """Set the memory target of this domain.
    2.75          @param target In MiB.
    2.76          """
    2.77 +        log.debug("Setting memory target of domain %s (%d) to %d MiB.",
    2.78 +                  self.info['name'], self.domid, target)
    2.79 +        
    2.80          self.info['memory'] = target
    2.81          self.storeVm("memory", target)
    2.82          self.storeDom("memory/target", target << 10)
    2.83 @@ -1105,6 +1117,7 @@ class XendDomainInfo:
    2.84              xc.domain_setcpuweight(self.domid, self.info['cpu_weight'])
    2.85  
    2.86              m = self.image.getDomainMemory(self.info['memory'] * 1024)
    2.87 +            balloon.free(m)
    2.88              xc.domain_setmaxmem(self.domid, m)
    2.89              xc.domain_memory_increase_reservation(self.domid, m, 0, 0)
    2.90  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/python/xen/xend/balloon.py	Thu Dec 01 03:39:23 2005 +0000
     3.3 @@ -0,0 +1,97 @@
     3.4 +#===========================================================================
     3.5 +# This library is free software; you can redistribute it and/or
     3.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
     3.7 +# License as published by the Free Software Foundation.
     3.8 +#
     3.9 +# This library is distributed in the hope that it will be useful,
    3.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    3.12 +# Lesser General Public License for more details.
    3.13 +#
    3.14 +# You should have received a copy of the GNU Lesser General Public
    3.15 +# License along with this library; if not, write to the Free Software
    3.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.17 +#============================================================================
    3.18 +# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
    3.19 +# Copyright (C) 2005 XenSource Ltd
    3.20 +#============================================================================
    3.21 +
    3.22 +
    3.23 +import time
    3.24 +
    3.25 +import xen.lowlevel.xc
    3.26 +
    3.27 +import XendDomain
    3.28 +import XendRoot
    3.29 +from XendLogging import log
    3.30 +from XendError import VmError
    3.31 +
    3.32 +
    3.33 +PROC_XEN_BALLOON = "/proc/xen/balloon"
    3.34 +BALLOON_OUT_SLACK = 1 # MiB.  We need this because the physinfo details are
    3.35 +                      # rounded.
    3.36 +
    3.37 +
    3.38 +def free(required):
    3.39 +    """Balloon out memory from the privileged domain so that there is the
    3.40 +    specified required amount (in KiB) free.
    3.41 +    """
    3.42 +    
    3.43 +    xc = xen.lowlevel.xc.xc()
    3.44 +    xroot = XendRoot.instance()
    3.45 +
    3.46 +    try:
    3.47 +        free_mem = xc.physinfo()['free_memory']
    3.48 +        need_mem = (required + 1023) / 1024 + BALLOON_OUT_SLACK
    3.49 +
    3.50 +        log.debug("Balloon: free %d; need %d.", free_mem, need_mem)
    3.51 +        
    3.52 +        if free_mem >= need_mem:
    3.53 +            return
    3.54 +
    3.55 +        dom0_min_mem = xroot.get_dom0_min_mem()
    3.56 +        if dom0_min_mem == 0:
    3.57 +            raise VmError('Not enough free memory and dom0_min_mem is 0.')
    3.58 +
    3.59 +        dom0_alloc = _get_dom0_alloc()
    3.60 +        dom0_new_alloc = dom0_alloc - (need_mem - free_mem)
    3.61 +        if dom0_new_alloc < dom0_min_mem:
    3.62 +            raise VmError(
    3.63 +                ('I need %d MiB, but dom0_min_mem is %d and shrinking to '
    3.64 +                 '%d MiB would leave only %d MiB free.') %
    3.65 +                (need_mem, dom0_min_mem, dom0_min_mem,
    3.66 +                 free_mem + (dom0_alloc - dom0_min_mem)))
    3.67 +
    3.68 +        dom0 = XendDomain.instance().privilegedDomain()
    3.69 +        dom0.setMemoryTarget(dom0_new_alloc)
    3.70 +
    3.71 +        timeout = 20 # 2 sec
    3.72 +        while timeout > 0:
    3.73 +            time.sleep(0.1)
    3.74 +
    3.75 +            free_mem = xc.physinfo()['free_memory']
    3.76 +            if free_mem >= need_mem:
    3.77 +                return
    3.78 +
    3.79 +            timeout -= 1
    3.80 +
    3.81 +        raise VmError('The privileged domain did not balloon!')
    3.82 +    finally:
    3.83 +        del xc
    3.84 +
    3.85 +
    3.86 +def _get_dom0_alloc():
    3.87 +    """Return current allocation memory of dom0 (in MiB). Return 0 on error"""
    3.88 +
    3.89 +    f = file(PROC_XEN_BALLOON, 'r')
    3.90 +    try:
    3.91 +        line = f.readline()
    3.92 +        for x in line.split():
    3.93 +            for n in x:
    3.94 +                if not n.isdigit():
    3.95 +                    break
    3.96 +            else:
    3.97 +                return int(x) / 1024
    3.98 +        return 0
    3.99 +    finally:
   3.100 +        f.close()
     4.1 --- a/tools/python/xen/xm/create.py	Thu Dec 01 03:32:39 2005 +0000
     4.2 +++ b/tools/python/xen/xm/create.py	Thu Dec 01 03:39:23 2005 +0000
     4.3 @@ -798,57 +798,6 @@ def make_domain(opts, config):
     4.4      opts.info("Started domain %s" % (dom))
     4.5      return int(sxp.child_value(dominfo, 'domid'))
     4.6  
     4.7 -def get_dom0_alloc():
     4.8 -    """Return current allocation memory of dom0 (in MB). Return 0 on error"""
     4.9 -    PROC_XEN_BALLOON = "/proc/xen/balloon"
    4.10 -
    4.11 -    f = open(PROC_XEN_BALLOON, "r")
    4.12 -    line = f.readline()
    4.13 -    for x in line.split():
    4.14 -        for n in x:
    4.15 -            if not n.isdigit():
    4.16 -                break
    4.17 -        else:
    4.18 -            f.close()
    4.19 -            return int(x)/1024
    4.20 -    f.close()
    4.21 -    return 0
    4.22 -
    4.23 -def balloon_out(dom0_min_mem, opts):
    4.24 -    """Balloon out memory from dom0 if necessary"""
    4.25 -    SLACK = 4
    4.26 -    timeout = 20 # 2s
    4.27 -    ret = 1
    4.28 -
    4.29 -    xc = xen.lowlevel.xc.xc()
    4.30 -    free_mem = xc.physinfo()['free_pages'] / 256
    4.31 -    domU_need_mem = opts.vals.memory + SLACK 
    4.32 -
    4.33 -    # we already have enough free memory, return success
    4.34 -    if free_mem >= domU_need_mem:
    4.35 -        del xc
    4.36 -        return 0
    4.37 -
    4.38 -    dom0_cur_alloc = get_dom0_alloc()
    4.39 -    dom0_new_alloc = dom0_cur_alloc - (domU_need_mem - free_mem)
    4.40 -    if dom0_new_alloc < dom0_min_mem:
    4.41 -        dom0_new_alloc = dom0_min_mem
    4.42 -
    4.43 -    server.xend_domain_mem_target_set(0, dom0_new_alloc)
    4.44 -
    4.45 -    while timeout > 0:
    4.46 -        time.sleep(0.1) # sleep 100ms
    4.47 -
    4.48 -        free_mem = xc.physinfo()['free_pages'] / 256
    4.49 -        if free_mem >= domU_need_mem:
    4.50 -            ret = 0
    4.51 -            break
    4.52 -        timeout -= 1
    4.53 -
    4.54 -    del xc
    4.55 -    return ret
    4.56 -
    4.57 -
    4.58  def parseCommandLine(argv):
    4.59      gopts.reset()
    4.60      args = gopts.parse(argv)
    4.61 @@ -891,15 +840,6 @@ def main(argv):
    4.62      if opts.vals.dryrun:
    4.63          PrettyPrint.prettyprint(config)
    4.64      else:
    4.65 -        from xen.xend import XendRoot
    4.66 -
    4.67 -        xroot = XendRoot.instance()
    4.68 -
    4.69 -        dom0_min_mem = xroot.get_dom0_min_mem()
    4.70 -        if dom0_min_mem != 0:
    4.71 -            if balloon_out(dom0_min_mem, opts):
    4.72 -                err("cannot allocate enough memory for domain")
    4.73 -
    4.74          dom = make_domain(opts, config)
    4.75          if opts.vals.console_autoconnect:
    4.76              console.execConsole(dom)