ia64/xen-unstable

view tools/python/xen/xend/balloon.py @ 9562:508cb44338f5

When dom0 fails to balloon enough memory to allow a new domain to start,
an exception is thrown. The test that decides which exception to throw
is backwards, resulting in strange error messages. The attached patch
fixes the problem.

Signed-off-by: Charles Coffing <ccoffing@novell.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Apr 01 10:52:47 2006 +0100 (2006-04-01)
parents cc303cdf8809
children 93db1b536f38
line source
1 #===========================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
16 # Copyright (C) 2005 XenSource Ltd
17 #============================================================================
20 import time
22 import xen.lowlevel.xc
24 import XendDomain
25 import XendRoot
26 from XendLogging import log
27 from XendError import VmError
30 PROC_XEN_BALLOON = '/proc/xen/balloon'
32 BALLOON_OUT_SLACK = 1 # MiB. We need this because the physinfo details are
33 # rounded.
34 RETRY_LIMIT = 10
35 ##
36 # The time to sleep between retries grows linearly, using this value (in
37 # seconds). When the system is lightly loaded, memory should be scrubbed and
38 # returned to the system very quickly, whereas when it is loaded, the system
39 # needs idle time to get the scrubbing done. This linear growth accommodates
40 # such requirements.
41 SLEEP_TIME_GROWTH = 0.1
43 # A mapping between easy-to-remember labels and the more verbose
44 # label actually shown in the PROC_XEN_BALLOON file.
45 labels = { 'current' : 'Current allocation',
46 'target' : 'Requested target',
47 'low-balloon' : 'Low-mem balloon',
48 'high-balloon' : 'High-mem balloon',
49 'limit' : 'Xen hard limit' }
51 def _get_proc_balloon(label):
52 """Returns the value for the named label. Returns None if the label was
53 not found or the value was non-numeric."""
55 f = file(PROC_XEN_BALLOON, 'r')
56 try:
57 for line in f:
58 keyvalue = line.split(':')
59 if keyvalue[0] == label:
60 values = keyvalue[1].split()
61 if values[0].isdigit():
62 return int(values[0])
63 else:
64 return None
65 return None
66 finally:
67 f.close()
69 def get_dom0_current_alloc():
70 """Returns the current memory allocation (in MiB) of dom0."""
72 kb = _get_proc_balloon(labels['current'])
73 if kb == None:
74 raise VmError('Failed to query current memory allocation of dom0.')
75 return kb / 1024
77 def get_dom0_target_alloc():
78 """Returns the target memory allocation (in MiB) of dom0."""
80 kb = _get_proc_balloon(labels['target'])
81 if kb == None:
82 raise VmError('Failed to query target memory allocation of dom0.')
83 return kb / 1024
85 def free(required):
86 """Balloon out memory from the privileged domain so that there is the
87 specified required amount (in KiB) free.
88 """
90 # We check whether there is enough free memory, and if not, instruct dom0
91 # to balloon out to free some up. Memory freed by a destroyed domain may
92 # not appear in the free_memory field immediately, because it needs to be
93 # scrubbed before it can be released to the free list, which is done
94 # asynchronously by Xen; ballooning is asynchronous also. No matter where
95 # we expect the free memory to come from, therefore, we need to wait for
96 # it to become available.
97 #
98 # We are not allowed to balloon below dom0_min_mem, or if dom0_min_mem
99 # is 0, we cannot balloon at all. Memory can still become available
100 # through a rebooting domain, however.
101 #
102 # Eventually, we time out (presumably because there really isn't enough
103 # free memory).
104 #
105 # We don't want to set the memory target (triggering a watch) when that
106 # has already been done, but we do want to respond to changing memory
107 # usage, so we recheck the required alloc each time around the loop, but
108 # track the last used value so that we don't trigger too many watches.
110 need_mem = (required + 1023) / 1024 + BALLOON_OUT_SLACK
112 xroot = XendRoot.instance()
113 xc = xen.lowlevel.xc.xc()
115 try:
116 dom0_min_mem = xroot.get_dom0_min_mem()
118 retries = 0
119 sleep_time = SLEEP_TIME_GROWTH
120 last_new_alloc = None
121 while retries < RETRY_LIMIT:
122 free_mem = xc.physinfo()['free_memory']
124 if free_mem >= need_mem:
125 log.debug("Balloon: free %d; need %d; done.", free_mem,
126 need_mem)
127 return
129 if retries == 0:
130 log.debug("Balloon: free %d; need %d.", free_mem, need_mem)
132 if dom0_min_mem > 0:
133 dom0_alloc = get_dom0_current_alloc()
134 new_alloc = dom0_alloc - (need_mem - free_mem)
136 if (new_alloc >= dom0_min_mem and
137 new_alloc != last_new_alloc):
138 log.debug("Balloon: setting dom0 target to %d.",
139 new_alloc)
140 dom0 = XendDomain.instance().privilegedDomain()
141 dom0.setMemoryTarget(new_alloc)
142 last_new_alloc = new_alloc
143 # Continue to retry, waiting for ballooning.
145 time.sleep(sleep_time)
146 retries += 1
147 sleep_time += SLEEP_TIME_GROWTH
149 # Not enough memory; diagnose the problem.
150 if dom0_min_mem == 0:
151 raise VmError(('Not enough free memory and dom0_min_mem is 0, so '
152 'I cannot release any more. I need %d MiB but '
153 'only have %d.') %
154 (need_mem, free_mem))
155 elif new_alloc < dom0_min_mem:
156 raise VmError(
157 ('I need %d MiB, but dom0_min_mem is %d and shrinking to '
158 '%d MiB would leave only %d MiB free.') %
159 (need_mem, dom0_min_mem, dom0_min_mem,
160 free_mem + dom0_alloc - dom0_min_mem))
161 else:
162 raise VmError('The privileged domain did not balloon!')
164 finally:
165 del xc