소스 검색

qmemman: reformat code, especially comments

Indent comments to match code indentation to make it readable. Also,
wrap long lines. Fix few typos in comments.

No functional change.
Marek Marczykowski-Górecki 6 년 전
부모
커밋
8e288d9f81
2개의 변경된 파일151개의 추가작업 그리고 112개의 파일을 삭제
  1. 48 34
      qubes/qmemman/__init__.py
  2. 103 78
      qubes/qmemman/algo.py

+ 48 - 34
qubes/qmemman/__init__.py

@@ -39,13 +39,14 @@ class DomainState:
     def __init__(self, id):
         self.memory_current = 0     # the current memory size
         self.memory_actual = None   # the current memory allocation (what VM
-                                    #  is using or can use at any time)
-        self.memory_maximum = None	#the maximum memory size
-        self.mem_used = None		#used memory, computed based on meminfo
-        self.id = id			#domain id
-        self.last_target = 0		#the last memset target
-        self.no_progress = False    #no react to memset
-        self.slow_memset_react = False #slow react to memset (after few tries still above target)
+                                    # is using or can use at any time)
+        self.memory_maximum = None  # the maximum memory size
+        self.mem_used = None		# used memory, computed based on meminfo
+        self.id = id			    # domain id
+        self.last_target = 0		# the last memset target
+        self.no_progress = False    # no react to memset
+        self.slow_memset_react = False  # slow react to memset (after few
+                                        # tries still above target)
 
     def __repr__(self):
         return self.__dict__.__repr__()
@@ -61,9 +62,11 @@ class SystemState(object):
         self.BALOON_DELAY = 0.1
         self.XEN_FREE_MEM_LEFT = 50*1024*1024
         self.XEN_FREE_MEM_MIN = 25*1024*1024
-        # Overhead of per-page Xen structures, taken from OpenStack nova/virt/xenapi/driver.py
+        # Overhead of per-page Xen structures, taken from OpenStack
+        # nova/virt/xenapi/driver.py
         # see https://wiki.openstack.org/wiki/XenServer/Overhead
-        # we divide total and free physical memory by this to get "assignable" memory
+        # we divide total and free physical memory by this to get
+        # "assignable" memory
         self.MEM_OVERHEAD_FACTOR = 1.0 / 1.00781
         try:
             self.ALL_PHYS_MEM = int(self.xc.physinfo()['total_memory']*1024 * self.MEM_OVERHEAD_FACTOR)
@@ -108,7 +111,7 @@ class SystemState(object):
                 xen_free, assigned_but_unused, self.domdict))
         return xen_free - assigned_but_unused
 
-#refresh information on memory assigned to all domains
+    # refresh information on memory assigned to all domains
     def refresh_memactual(self):
         for domain in self.xc.domain_getinfo():
             id = str(domain['domid'])
@@ -125,18 +128,21 @@ class SystemState(object):
                     self.domdict[id].memory_maximum = int(self.domdict[id].memory_maximum)*1024
                 else:
                     self.domdict[id].memory_maximum = self.ALL_PHYS_MEM
-# the previous line used to be
-#                    self.domdict[id].memory_maximum = domain['maxmem_kb']*1024
-# but domain['maxmem_kb'] changes in self.mem_set as well, and this results in
-# the memory never increasing
-# in fact, the only possible case of nonexisting memory/static-max is dom0
-# see #307
+                    # the previous line used to be
+                    #   self.domdict[id].memory_maximum = domain[
+                    #       'maxmem_kb']*1024
+                    # but domain['maxmem_kb'] changes in self.mem_set as well,
+                    # and this results in the memory never increasing
+                    # in fact, the only possible case of nonexisting
+                    # memory/static-max is dom0
+                    # see #307
 
     def clear_outdated_error_markers(self):
         # Clear outdated errors
         for i in self.domdict.keys():
             if self.domdict[i].slow_memset_react and \
-                    self.domdict[i].memory_actual <= self.domdict[i].last_target + self.XEN_FREE_MEM_LEFT/4:
+                    self.domdict[i].memory_actual <= \
+                    self.domdict[i].last_target + self.XEN_FREE_MEM_LEFT/4:
                 dom_name = self.xs.read('', '/local/domain/%s/name' % str(i))
                 if dom_name is not None:
                     # TODO: report it somewhere, qubesd or elsewhere
@@ -144,19 +150,21 @@ class SystemState(object):
                 self.domdict[i].slow_memset_react = False
 
             if self.domdict[i].no_progress and \
-                    self.domdict[i].memory_actual <= self.domdict[i].last_target + self.XEN_FREE_MEM_LEFT/4:
+                    self.domdict[i].memory_actual <= \
+                    self.domdict[i].last_target + self.XEN_FREE_MEM_LEFT/4:
                 dom_name = self.xs.read('', '/local/domain/%s/name' % str(i))
                 if dom_name is not None:
                     # TODO: report it somewhere, qubesd or elsewhere
                     pass
                 self.domdict[i].no_progress = False
 
-#the below works (and is fast), but then 'xm list' shows unchanged memory value
+    # the below works (and is fast), but then 'xm list' shows unchanged
+    # memory value
     def mem_set(self, id, val):
         self.log.info('mem-set domain {} to {}'.format(id, val))
         self.domdict[id].last_target = val
-#can happen in the middle of domain shutdown
-#apparently xc.lowlevel throws exceptions too
+        # can happen in the middle of domain shutdown
+        # apparently xc.lowlevel throws exceptions too
         try:
             self.xc.domain_setmaxmem(int(id), int(val/1024) + 1024) # LIBXL_MAXMEM_CONSTANT=1024
             self.xc.domain_set_target_mem(int(id), int(val/1024))
@@ -164,8 +172,8 @@ class SystemState(object):
             pass
         self.xs.write('', '/local/domain/' + id + '/memory/target', str(int(val/1024)))
 
-# this is called at the end of ballooning, when we have Xen free mem already
-# make sure that past mem_set will not decrease Xen free mem
+    # this is called at the end of ballooning, when we have Xen free mem already
+    # make sure that past mem_set will not decrease Xen free mem
     def inhibit_balloon_up(self):
         self.log.debug('inhibit_balloon_up()')
         for i in self.domdict.keys():
@@ -175,7 +183,8 @@ class SystemState(object):
                     'Preventing balloon up to {}'.format(dom.last_target))
                 self.mem_set(i, dom.memory_actual)
 
-#perform memory ballooning, across all domains, to add "memsize" to Xen free memory
+    # perform memory ballooning, across all domains, to add "memsize" to Xen
+    #  free memory
     def do_balloon(self, memsize):
         self.log.info('do_balloon(memsize={!r})'.format(memsize))
         CHECK_PERIOD_S = 3
@@ -213,7 +222,8 @@ class SystemState(object):
             if prev_memory_actual is not None:
                 for i in prev_memory_actual.keys():
                     if prev_memory_actual[i] == self.domdict[i].memory_actual:
-                        #domain not responding to memset requests, remove it from donors
+                        # domain not responding to memset requests, remove it
+                        #  from donors
                         self.domdict[i].no_progress = True
                         self.log.info('domain {} stuck at {}'.format(i, self.domdict[i].memory_actual))
             memset_reqs = qubes.qmemman.algo.balloon(memsize + self.XEN_FREE_MEM_LEFT - xenfree, self.domdict)
@@ -238,8 +248,8 @@ class SystemState(object):
             self.domdict[domid], untrusted_meminfo_key)
         self.do_balance()
 
-#is the computed balance request big enough ?
-#so that we do not trash with small adjustments
+    # is the computed balance request big enough ?
+    # so that we do not trash with small adjustments
     def is_balance_req_significant(self, memset_reqs, xenfree):
         self.log.debug(
             'is_balance_req_significant(memset_reqs={}, xenfree={})'.format(
@@ -261,7 +271,8 @@ class SystemState(object):
             total_memory_transfer += abs(memory_change)
             pref = qubes.qmemman.algo.prefmem(self.domdict[dom])
 
-            if last_target > 0 and last_target < pref and memory_change > MIN_MEM_CHANGE_WHEN_UNDER_PREF:
+            if 0 < last_target < pref and \
+                    memory_change > MIN_MEM_CHANGE_WHEN_UNDER_PREF:
                 self.log.info(
                     'dom {} is below pref, allowing balance'.format(dom))
                 return True
@@ -303,7 +314,7 @@ class SystemState(object):
             dom, mem = rq
             # Force to always have at least 0.9*self.XEN_FREE_MEM_LEFT (some
             # margin for rounding errors). Before giving memory to
-            # domain, ensure that others have gived it back.
+            # domain, ensure that others have gave it back.
             # If not - wait a little.
             ntries = 5
             while self.get_free_xen_memory() - (mem - self.domdict[dom].memory_actual) < 0.9*self.XEN_FREE_MEM_LEFT:
@@ -318,11 +329,12 @@ class SystemState(object):
                     for rq2 in memset_reqs:
                         dom2, mem2 = rq2
                         if dom2 == dom:
-                            # All donors have been procesed
-                             break
+                            # All donors have been processed
+                            break
                         # allow some small margin
                         if self.domdict[dom2].memory_actual > self.domdict[dom2].last_target + self.XEN_FREE_MEM_LEFT/4:
-                            # VM didn't react to memory request at all, remove from donors
+                            # VM didn't react to memory request at all,
+                            # remove from donors
                             if prev_memactual[dom2] == self.domdict[dom2].memory_actual:
                                 self.log.warning(
                                     'dom {!r} didnt react to memory request'
@@ -333,7 +345,8 @@ class SystemState(object):
                                 self.domdict[dom2].no_progress = True
                                 dom_name = self.xs.read('', '/local/domain/%s/name' % str(dom2))
                                 if dom_name is not None:
-                                    # TODO: report it somewhere, qubesd or elsewhere
+                                    # TODO: report it somewhere, qubesd or
+                                    # elsewhere
                                     pass
                             else:
                                 self.log.warning('dom {!r} still hold more'
@@ -344,7 +357,8 @@ class SystemState(object):
                                 self.domdict[dom2].slow_memset_react = True
                                 dom_name = self.xs.read('', '/local/domain/%s/name' % str(dom2))
                                 if dom_name is not None:
-                                    # TODO: report it somewhere, qubesd or elsewhere
+                                    # TODO: report it somewhere, qubesd or
+                                    # elsewhere
                                     pass
                     self.mem_set(dom, self.get_free_xen_memory() + self.domdict[dom].memory_actual - self.XEN_FREE_MEM_LEFT)
                     return

+ 103 - 78
qubes/qmemman/algo.py

@@ -26,14 +26,14 @@ import string
 # This are only defaults - can be overridden by QMemmanServer with values from
 # config file
 CACHE_FACTOR = 1.3
-MIN_PREFMEM = 200*1024*1024
-DOM0_MEM_BOOST = 350*1024*1024
-
+MIN_PREFMEM = 200 * 1024 * 1024
+DOM0_MEM_BOOST = 350 * 1024 * 1024
 
 log = logging.getLogger('qmemman.daemon.algo')
 
-#untrusted meminfo size is taken from xenstore key, thus its size is limited
-#so splits do not require excessive memory
+
+# untrusted meminfo size is taken from xenstore key, thus its size is limited
+# so splits do not require excessive memory
 def sanitize_and_parse_meminfo(untrusted_meminfo):
     if not untrusted_meminfo:
         return None
@@ -62,22 +62,21 @@ def sanitize_and_parse_meminfo(untrusted_meminfo):
         # sanitize end
         meminfo = untrusted_dict
         return (meminfo['MemTotal'] -
-            meminfo['MemFree'] - meminfo['Cached'] - meminfo['Buffers'] +
-            meminfo['SwapTotal'] - meminfo['SwapFree']) * 1024
-
+                meminfo['MemFree'] - meminfo['Cached'] - meminfo['Buffers'] +
+                meminfo['SwapTotal'] - meminfo['SwapFree']) * 1024
 
     return None
 
 
 def is_meminfo_suspicious(untrusted_meminfo):
     log.debug('is_meminfo_suspicious('
-        'untrusted_meminfo={!r})'.format(untrusted_meminfo))
+              'untrusted_meminfo={!r})'.format(untrusted_meminfo))
     ret = False
 
     # check whether the required keys exist and are not negative
     try:
         for i in ('MemTotal', 'MemFree', 'Buffers', 'Cached',
-                'SwapTotal', 'SwapFree'):
+        'SwapTotal', 'SwapFree'):
             val = int(untrusted_meminfo[i])
             if val < 0:
                 ret = True
@@ -88,8 +87,9 @@ def is_meminfo_suspicious(untrusted_meminfo):
     if untrusted_meminfo['SwapTotal'] < untrusted_meminfo['SwapFree']:
         ret = True
     if untrusted_meminfo['MemTotal'] < \
-            untrusted_meminfo['MemFree'] + \
-            untrusted_meminfo['Cached'] + untrusted_meminfo['Buffers']:
+                            untrusted_meminfo['MemFree'] + \
+                            untrusted_meminfo['Cached'] + untrusted_meminfo[
+                'Buffers']:
         ret = True
     # we could also impose some limits on all the above values
     # but it has little purpose - all the domain can gain by passing e.g.
@@ -97,7 +97,8 @@ def is_meminfo_suspicious(untrusted_meminfo):
     # it can be achieved with legal values, too, and it will not allow to
     # starve existing domains, by design
     if ret:
-        log.warning('suspicious meminfo untrusted_meminfo={!r}'.format(untrusted_meminfo))
+        log.warning('suspicious meminfo untrusted_meminfo={!r}'.format(
+            untrusted_meminfo))
     return ret
 
 
@@ -107,20 +108,26 @@ def refresh_meminfo_for_domain(domain, untrusted_xenstore_key):
 
 
 def prefmem(domain):
-#dom0 is special, as it must have large cache, for vbds. Thus, give it a special boost
+    # dom0 is special, as it must have large cache, for vbds. Thus, give it
+    # a special boost
     if domain.id == '0':
-        return min(domain.mem_used*CACHE_FACTOR + DOM0_MEM_BOOST, domain.memory_maximum)
-    return max(min(domain.mem_used*CACHE_FACTOR, domain.memory_maximum), MIN_PREFMEM)
+        return min(domain.mem_used * CACHE_FACTOR + DOM0_MEM_BOOST,
+            domain.memory_maximum)
+    return max(min(domain.mem_used * CACHE_FACTOR, domain.memory_maximum),
+        MIN_PREFMEM)
+
 
 def memory_needed(domain):
-#do not change
-#in balance(), "distribute total_available_memory proportionally to mempref" relies on this exact formula
+    # do not change
+    # in balance(), "distribute total_available_memory proportionally to
+    # mempref" relies on this exact formula
     ret = prefmem(domain) - domain.memory_actual
     return ret
 
-#prepare list of (domain, memory_target) pairs that need to be passed
-#to "xm memset" equivalent in order to obtain "memsize" of memory
-#return empty list when the request cannot be satisfied
+
+# prepare list of (domain, memory_target) pairs that need to be passed
+# to "xm memset" equivalent in order to obtain "memsize" of memory
+# return empty list when the request cannot be satisfied
 def balloon(memsize, domain_dictionary):
     log.debug('balloon(memsize={!r}, domain_dictionary={!r})'.format(
         memsize, domain_dictionary))
@@ -137,31 +144,35 @@ def balloon(memsize, domain_dictionary):
         if need < 0:
             log.info('balloon: dom {} has actual memory {}'.format(i,
                 domain_dictionary[i].memory_actual))
-            donors.append((i,-need))
-            available-=need
+            donors.append((i, -need))
+            available -= need
 
     log.info('req={} avail={} donors={!r}'.format(memsize, available, donors))
 
-    if available<memsize:
+    if available < memsize:
         return ()
-    scale = 1.0*memsize/available
+    scale = 1.0 * memsize / available
     for donors_iter in donors:
-        id, mem = donors_iter
-        memborrowed = mem*scale*REQ_SAFETY_NET_FACTOR
-        log.info('borrow {} from {}'.format(memborrowed, id))
-        memtarget = int(domain_dictionary[id].memory_actual - memborrowed)
-        request.append((id, memtarget))
+        dom_id, mem = donors_iter
+        memborrowed = mem * scale * REQ_SAFETY_NET_FACTOR
+        log.info('borrow {} from {}'.format(memborrowed, dom_id))
+        memtarget = int(domain_dictionary[dom_id].memory_actual - memborrowed)
+        request.append((dom_id, memtarget))
     return request
-# REQ_SAFETY_NET_FACTOR is a bit greater that 1. So that if the domain yields a bit less than requested, due
-# to e.g. rounding errors, we will not get stuck. The surplus will return to the VM during "balance" call.
 
 
-#redistribute positive "total_available_memory" of memory between domains, proportionally to prefmem
+# REQ_SAFETY_NET_FACTOR is a bit greater that 1. So that if the domain
+# yields a bit less than requested, due to e.g. rounding errors, we will not
+# get stuck. The surplus will return to the VM during "balance" call.
+
+
+# redistribute positive "total_available_memory" of memory between domains,
+# proportionally to prefmem
 def balance_when_enough_memory(domain_dictionary,
         xen_free_memory, total_mem_pref, total_available_memory):
     log.info('balance_when_enough_memory(xen_free_memory={!r}, '
-        'total_mem_pref={!r}, total_available_memory={!r})'.format(
-            xen_free_memory, total_mem_pref, total_available_memory))
+             'total_mem_pref={!r}, total_available_memory={!r})'.format(
+        xen_free_memory, total_mem_pref, total_available_memory))
 
     target_memory = {}
     # memory not assigned because of static max
@@ -172,20 +183,21 @@ def balance_when_enough_memory(domain_dictionary,
             continue
         if domain_dictionary[i].no_progress:
             continue
-#distribute total_available_memory proportionally to mempref
-        scale = 1.0*prefmem(domain_dictionary[i])/total_mem_pref
-        target_nonint = prefmem(domain_dictionary[i]) + scale*total_available_memory
-#prevent rounding errors
-        target = int(0.999*target_nonint)
-#do not try to give more memory than static max
+        # distribute total_available_memory proportionally to mempref
+        scale = 1.0 * prefmem(domain_dictionary[i]) / total_mem_pref
+        target_nonint = prefmem(
+            domain_dictionary[i]) + scale * total_available_memory
+        # prevent rounding errors
+        target = int(0.999 * target_nonint)
+        # do not try to give more memory than static max
         if target > domain_dictionary[i].memory_maximum:
-            left_memory += target-domain_dictionary[i].memory_maximum
+            left_memory += target - domain_dictionary[i].memory_maximum
             target = domain_dictionary[i].memory_maximum
         else:
-# count domains which can accept more memory
+            # count domains which can accept more memory
             acceptors_count += 1
         target_memory[i] = target
-# distribute left memory across all acceptors
+    # distribute left memory across all acceptors
     while left_memory > 0 and acceptors_count > 0:
         log.info('left_memory={} acceptors_count={}'.format(
             left_memory, acceptors_count))
@@ -195,9 +207,10 @@ def balance_when_enough_memory(domain_dictionary,
         for i in target_memory.keys():
             target = target_memory[i]
             if target < domain_dictionary[i].memory_maximum:
-                memory_bonus = int(0.999*(left_memory/acceptors_count))
-                if target+memory_bonus >= domain_dictionary[i].memory_maximum:
-                    new_left_memory += target+memory_bonus - domain_dictionary[i].memory_maximum
+                memory_bonus = int(0.999 * (left_memory / acceptors_count))
+                if target + memory_bonus >= domain_dictionary[i].memory_maximum:
+                    new_left_memory += target + memory_bonus - \
+                                       domain_dictionary[i].memory_maximum
                     target = domain_dictionary[i].memory_maximum
                     new_acceptors_count -= 1
                 else:
@@ -205,82 +218,92 @@ def balance_when_enough_memory(domain_dictionary,
             target_memory[i] = target
         left_memory = new_left_memory
         acceptors_count = new_acceptors_count
-# split target_memory dictionary to donors and acceptors
-#  this is needed to first get memory from donors and only then give it to acceptors
+    # split target_memory dictionary to donors and acceptors
+    # this is needed to first get memory from donors and only then give it
+    # to acceptors
     donors_rq = list()
     acceptors_rq = list()
     for i in target_memory.keys():
         target = target_memory[i]
-        if (target < domain_dictionary[i].memory_actual):
+        if target < domain_dictionary[i].memory_actual:
             donors_rq.append((i, target))
         else:
             acceptors_rq.append((i, target))
 
-#    print 'balance(enough): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq
+    # print 'balance(enough): xen_free_memory=', xen_free_memory, \
+    #  'requests:', donors_rq + acceptors_rq
     return donors_rq + acceptors_rq
 
 
-#when not enough mem to make everyone be above prefmem, make donors be at prefmem, and
-#redistribute anything left between acceptors
+# when not enough mem to make everyone be above prefmem, make donors be at
+# prefmem, and redistribute anything left between acceptors
 def balance_when_low_on_memory(domain_dictionary,
         xen_free_memory, total_mem_pref_acceptors, donors, acceptors):
     log.debug('balance_when_low_on_memory(xen_free_memory={!r}, '
         'total_mem_pref_acceptors={!r}, donors={!r}, acceptors={!r})'.format(
-            xen_free_memory, total_mem_pref_acceptors, donors, acceptors))
+         xen_free_memory, total_mem_pref_acceptors, donors, acceptors))
     donors_rq = list()
     acceptors_rq = list()
     squeezed_mem = xen_free_memory
     for i in donors:
         avail = -memory_needed(domain_dictionary[i])
-        if avail < 10*1024*1024:
-            #probably we have already tried making it exactly at prefmem, give up
+        if avail < 10 * 1024 * 1024:
+            # probably we have already tried making it exactly at prefmem,
+            # give up
             continue
         squeezed_mem -= avail
         donors_rq.append((i, prefmem(domain_dictionary[i])))
-#the below can happen if initially xen free memory is below 50M
+    # the below can happen if initially xen free memory is below 50M
     if squeezed_mem < 0:
         return donors_rq
     for i in acceptors:
-        scale = 1.0*prefmem(domain_dictionary[i])/total_mem_pref_acceptors
-        target_nonint = domain_dictionary[i].memory_actual + scale*squeezed_mem
-#do not try to give more memory than static max
-        target = min(int(0.999*target_nonint), domain_dictionary[i].memory_maximum)
+        scale = 1.0 * prefmem(domain_dictionary[i]) / total_mem_pref_acceptors
+        target_nonint = \
+            domain_dictionary[i].memory_actual + scale * squeezed_mem
+        # do not try to give more memory than static max
+        target = \
+            min(int(0.999 * target_nonint), domain_dictionary[i].memory_maximum)
         acceptors_rq.append((i, target))
-#    print 'balance(low): xen_free_memory=', xen_free_memory, 'requests:', donors_rq + acceptors_rq
+    # print 'balance(low): xen_free_memory=', xen_free_memory, 'requests:',
+    # donors_rq + acceptors_rq
     return donors_rq + acceptors_rq
 
 
-#redistribute memory across domains
-#called when one of domains update its 'meminfo' xenstore key
-#return the list of (domain, memory_target) pairs to be passed to
-#"xm memset" equivalent
+# redistribute memory across domains
+# called when one of domains update its 'meminfo' xenstore key
+# return the list of (domain, memory_target) pairs to be passed to
+# "xm memset" equivalent
 def balance(xen_free_memory, domain_dictionary):
     log.debug('balance(xen_free_memory={!r}, domain_dictionary={!r})'.format(
         xen_free_memory, domain_dictionary))
 
-#sum of all memory requirements - in other words, the difference between
-#memory required to be added to domains (acceptors) to make them be at their
-#preferred memory, and memory that can be taken from domains (donors) that
-#can provide memory. So, it can be negative when plenty of memory.
+    # sum of all memory requirements - in other words, the difference between
+    # memory required to be added to domains (acceptors) to make them be
+    # at their preferred memory, and memory that can be taken from domains
+    # (donors) that can provide memory. So, it can be negative when plenty
+    # of memory.
     total_memory_needed = 0
 
-#sum of memory preferences of all domains
+    # sum of memory preferences of all domains
     total_mem_pref = 0
 
-#sum of memory preferences of all domains that require more memory
+    # sum of memory preferences of all domains that require more memory
     total_mem_pref_acceptors = 0
 
-    donors = list()	# domains that can yield memory
+    donors = list()  # domains that can yield memory
     acceptors = list()  # domains that require more memory
-#pass 1: compute the above "total" values
+    # pass 1: compute the above "total" values
     for i in domain_dictionary.keys():
         if domain_dictionary[i].mem_used is None:
             continue
         if domain_dictionary[i].no_progress:
             continue
         need = memory_needed(domain_dictionary[i])
-#        print 'domain' , i, 'act/pref', domain_dictionary[i].memory_actual, prefmem(domain_dictionary[i]), 'need=', need
-        if need < 0 or domain_dictionary[i].memory_actual >= domain_dictionary[i].memory_maximum:
+        # print 'domain' , i, 'act/pref', \
+        #  domain_dictionary[i].memory_actual, prefmem(domain_dictionary[i]), \
+        #  'need=', need
+        if need < 0 or domain_dictionary[i].memory_actual >= \
+                domain_dictionary[i].memory_maximum:
             donors.append(i)
         else:
             acceptors.append(i)
@@ -290,6 +313,8 @@ def balance(xen_free_memory, domain_dictionary):
 
     total_available_memory = xen_free_memory - total_memory_needed
     if total_available_memory > 0:
-        return balance_when_enough_memory(domain_dictionary, xen_free_memory, total_mem_pref, total_available_memory)
+        return balance_when_enough_memory(domain_dictionary, xen_free_memory,
+            total_mem_pref, total_available_memory)
     else:
-        return balance_when_low_on_memory(domain_dictionary, xen_free_memory, total_mem_pref_acceptors, donors, acceptors)
+        return balance_when_low_on_memory(domain_dictionary, xen_free_memory,
+            total_mem_pref_acceptors, donors, acceptors)