Package ganeti :: Package watcher :: Module nodemaint
[hide private]
[frames] | no frames]

Source Code for Module ganeti.watcher.nodemaint

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Google Inc. 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are 
  9  # met: 
 10  # 
 11  # 1. Redistributions of source code must retain the above copyright notice, 
 12  # this list of conditions and the following disclaimer. 
 13  # 
 14  # 2. Redistributions in binary form must reproduce the above copyright 
 15  # notice, this list of conditions and the following disclaimer in the 
 16  # documentation and/or other materials provided with the distribution. 
 17  # 
 18  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 19  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 20  # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 21  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 22  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 23  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 24  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 25  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 26  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 27  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 28  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29   
 30   
 31  """Module doing node maintenance for Ganeti watcher. 
 32   
 33  """ 
 34   
 35  import logging 
 36   
 37  from ganeti import constants 
 38  from ganeti import errors 
 39  from ganeti import hypervisor 
 40  from ganeti import netutils 
 41  from ganeti import ssconf 
 42  from ganeti import utils 
 43  from ganeti import confd 
 44  from ganeti.storage import drbd 
 45   
 46  import ganeti.confd.client # pylint: disable=W0611 
47 48 49 -class NodeMaintenance(object):
50 """Talks to confd daemons and possible shutdown instances/drbd devices. 51 52 """
53 - def __init__(self):
54 self.store_cb = confd.client.StoreResultCallback() 55 self.filter_cb = confd.client.ConfdFilterCallback(self.store_cb) 56 self.confd_client = confd.client.GetConfdClient(self.filter_cb)
57 58 @staticmethod
59 - def ShouldRun():
60 """Checks whether node maintenance should run. 61 62 """ 63 try: 64 return ssconf.SimpleStore().GetMaintainNodeHealth() 65 except errors.ConfigurationError, err: 66 logging.error("Configuration error, not activating node maintenance: %s", 67 err) 68 return False
69 70 @staticmethod
72 """Compute list of hypervisor/running instances. 73 74 """ 75 hyp_list = ssconf.SimpleStore().GetHypervisorList() 76 hvparams = ssconf.SimpleStore().GetHvparams() 77 results = [] 78 for hv_name in hyp_list: 79 try: 80 hv = hypervisor.GetHypervisor(hv_name) 81 ilist = hv.ListInstances(hvparams=hvparams) 82 results.extend([(iname, hv_name) for iname in ilist]) 83 except: # pylint: disable=W0702 84 logging.error("Error while listing instances for hypervisor %s", 85 hv_name, exc_info=True) 86 return results
87 88 @staticmethod
89 - def GetUsedDRBDs():
90 """Get list of used DRBD minors. 91 92 """ 93 return drbd.DRBD8.GetUsedDevs()
94 95 @classmethod
96 - def DoMaintenance(cls, role):
97 """Maintain the instance list. 98 99 """ 100 if role == constants.CONFD_NODE_ROLE_OFFLINE: 101 inst_running = cls.GetRunningInstances() 102 cls.ShutdownInstances(inst_running) 103 drbd_running = cls.GetUsedDRBDs() 104 cls.ShutdownDRBD(drbd_running) 105 else: 106 logging.debug("Not doing anything for role %s", role)
107 108 @staticmethod
109 - def ShutdownInstances(inst_running):
110 """Shutdown running instances. 111 112 """ 113 names_running = set([i[0] for i in inst_running]) 114 if names_running: 115 logging.info("Following instances should not be running," 116 " shutting them down: %s", utils.CommaJoin(names_running)) 117 # this dictionary will collapse duplicate instance names (only 118 # xen pvm/vhm) into a single key, which is fine 119 i2h = dict(inst_running) 120 for name in names_running: 121 hv_name = i2h[name] 122 hv = hypervisor.GetHypervisor(hv_name) 123 hv.StopInstance(None, force=True, name=name)
124 125 @staticmethod
126 - def ShutdownDRBD(drbd_running):
127 """Shutdown active DRBD devices. 128 129 """ 130 if drbd_running: 131 logging.info("Following DRBD minors should not be active," 132 " shutting them down: %s", utils.CommaJoin(drbd_running)) 133 for minor in drbd_running: 134 drbd.DRBD8.ShutdownAll(minor)
135
136 - def Exec(self):
137 """Check node status versus cluster desired state. 138 139 """ 140 if not constants.ENABLE_CONFD: 141 logging.warning("Confd use not enabled, cannot do maintenance") 142 return 143 144 my_name = netutils.Hostname.GetSysName() 145 req = \ 146 confd.client.ConfdClientRequest(type=constants.CONFD_REQ_NODE_ROLE_BYNAME, 147 query=my_name) 148 self.confd_client.SendRequest(req, async=False, coverage=-1) 149 timed_out, _, _ = self.confd_client.WaitForReply(req.rsalt) 150 if not timed_out: 151 # should have a valid response 152 status, result = self.store_cb.GetResponse(req.rsalt) 153 assert status, "Missing result but received replies" 154 if not self.filter_cb.consistent[req.rsalt]: 155 logging.warning("Inconsistent replies, not doing anything") 156 return 157 self.DoMaintenance(result.server_reply.answer) 158 else: 159 logging.warning("Confd query timed out, cannot do maintenance actions")
160