Commit 38242904 authored by Iustin Pop's avatar Iustin Pop
Browse files

Make the ganeti-watcher exit gracefully if it's not run on the master.

Reviewed-by: imsnah
parent 83120a01
......@@ -47,7 +47,7 @@ from ganeti import utils
EXIT_OK = 0
EXIT_SOME_ERROR = 1
EXIT_NOTMASTER = 11
EXIT_NOTMASTER = constants.EXIT_NOTMASTER
EXIT_NODESETUP_ERROR = 12
EXIT_DUPLICATE_IP = 13
EXIT_ARGS_ERROR = 14
......
......@@ -39,16 +39,21 @@ import sys
import time
import fcntl
import errno
import socket
from optparse import OptionParser
from ganeti import utils
from ganeti import constants
from ganeti import ssconf
class Error(Exception):
"""Generic custom error class."""
pass
class NotMasterError(Error):
"""Exception raised when this host is not the master."""
def Indent(s, prefix='| '):
......@@ -57,6 +62,7 @@ def Indent(s, prefix='| '):
Args:
s: The string to indent
prefix: The string to prepend each line.
"""
return "%s%s\n" % (prefix, ('\n' + prefix).join(s.splitlines()))
......@@ -68,6 +74,7 @@ def DoCmd(cmd):
cmd: the command to run.
Raises CommandError with verbose commentary on error.
"""
res = utils.RunCmd(cmd)
......@@ -97,6 +104,7 @@ class RestarterState(object):
Remove(name): remove record given by name, if exists.
Save(name): saves all records to file, releases lock and closes file.
"""
def __init__(self):
# The two-step dance below is necessary to allow both opening existing
......@@ -128,6 +136,7 @@ class RestarterState(object):
Args:
instance - the instance to look up.
"""
assert self.statefile
......@@ -141,6 +150,7 @@ class RestarterState(object):
Args:
instance - the instance being restarted
"""
assert self.statefile
......@@ -149,12 +159,13 @@ class RestarterState(object):
self.inst_map[instance.name] = (when, 1 + self.NumberOfAttempts(instance))
def Remove(self, instance):
"""Update state to reflect that a machine is running, i.e. remove record
"""Update state to reflect that a machine is running, i.e. remove record.
Args:
instance - the instance to remove from books
This method removes the record for a named instance
This method removes the record for a named instance.
"""
assert self.statefile
......@@ -163,6 +174,7 @@ class RestarterState(object):
def Save(self):
"""Save records to file, then unlock and close file.
"""
assert self.statefile
......@@ -194,6 +206,7 @@ class Instance(object):
class InstanceList(object):
"""The set of Virtual Machine instances on a cluster.
"""
cmd = ['gnt-instance', 'list', '--lock-retries=15',
'-o', 'name,admin_state,oper_state', '--no-headers', '--separator=:']
......@@ -221,6 +234,7 @@ class InstanceList(object):
class Message(object):
"""Encapsulation of a notice or error message.
"""
def __init__(self, level, msg):
self.level = level
......@@ -237,13 +251,19 @@ class Restarter(object):
The calling program should periodically instantiate me and call Run().
This will traverse the list of instances, and make up to MAXTRIES attempts
to restart machines that are down.
"""
def __init__(self):
sstore = ssconf.SimpleStore()
master = sstore.GetMasterNode()
if master != socket.gethostname():
raise NotMasterError, ("This is not the master node")
self.instances = InstanceList()
self.messages = []
def Run(self):
"""Make a pass over the list of instances, restarting downed ones.
"""
notepad = RestarterState()
......@@ -284,11 +304,11 @@ class Restarter(object):
notepad.Save()
def WriteReport(self, logfile):
"""
Log all messages to file.
"""Log all messages to file.
Args:
logfile: file object open for writing (the log file)
"""
for msg in self.messages:
print >> logfile, str(msg)
......@@ -326,6 +346,10 @@ def main():
restarter = Restarter()
restarter.Run()
restarter.WriteReport(sys.stdout)
except NotMasterError:
if options.debug:
sys.stderr.write("Not master, exiting.\n")
sys.exit(constants.EXIT_NOTMASTER)
except Error, err:
print err
......
......@@ -108,3 +108,6 @@ NODE_CONFIGFILES = [NODE_INITD_SCRIPT,
# import/export config options
INISECT_EXP = "export"
INISECT_INS = "instance"
# common exit codes
EXIT_NOTMASTER = 11
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment