Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-master @ 89e1fc26

History | View | Annotate | Download (5.1 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2006, 2007 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""Ganeti master script
23

    
24
Exit codes, for both start and stop:
25
  - 0: master setup successful
26
  - 1: some generic error (this exit code can also be thrown by exceptions)
27
  - 11: node is not master, nothing to do
28
  - 12: node setup incomplete, cannot start
29
  - 13: node should be master, but someone has the ip address already
30

    
31
Only exit codes 0 and 11 represent an ok state. Code 1 was left for
32
generic errors as other python code can cause exit with code 1.
33

    
34
"""
35

    
36
import os
37
import sys
38

    
39
from optparse import OptionParser
40

    
41
from ganeti import constants
42
from ganeti import errors
43
from ganeti import ssconf
44
from ganeti import utils
45

    
46
EXIT_OK = 0
47
EXIT_SOME_ERROR = 1
48
EXIT_NOTMASTER = constants.EXIT_NOTMASTER
49
EXIT_NODESETUP_ERROR = constants.EXIT_NODESETUP_ERROR
50
EXIT_DUPLICATE_IP = 13
51
EXIT_ARGS_ERROR = 14
52

    
53

    
54
def ParseOptions():
55
  """Parse the command line options.
56

    
57
  Returns:
58
    (options, args) as from OptionParser.parse_args()
59

    
60
  """
61
  parser = OptionParser(description="Ganeti master",
62
                        usage="%prog [-d]",
63
                        version="%%prog (ganeti) %s" %
64
                        constants.RELEASE_VERSION)
65

    
66
  parser.add_option("-d", "--debug", dest="debug",
67
                    help="Enable some debug messages",
68
                    default=False, action="store_true")
69
  options, args = parser.parse_args()
70

    
71
  if len(args) != 1 or args[0] not in ("start", "stop"):
72
    sys.stderr.write("Usage: %s [-d] start|stop\n" % sys.argv[0])
73
    sys.exit(EXIT_ARGS_ERROR)
74

    
75
  return options, args
76

    
77

    
78
def CheckNodeSetup(debug):
79
  """Checks the node setup.
80

    
81
  If the node setup if ok, this function will return the tuple
82
  (master_hostname, master_netdev, master_ip). Otherwise the return
83
  value will be None.
84

    
85
  """
86
  for fname in (constants.SSL_CERT_FILE,):
87
    if not os.path.isfile(fname):
88
      if debug:
89
        sys.stderr.write("Missing config file %s.\n" % fname)
90
      return None
91
  try:
92
    ss = ssconf.SimpleStore()
93
    port = ss.GetNodeDaemonPort()
94
    pwdata = ss.GetNodeDaemonPassword()
95
    master_name = ss.GetMasterNode()
96
    master_netdev = ss.GetMasterNetdev()
97
    master_ip = ss.GetMasterIP()
98
  except errors.ConfigurationError, err:
99
    if debug:
100
      sys.stderr.write("Cluster configuration incomplete: '%s'\n" % str(err))
101
    return None
102
  return (master_name, master_netdev, master_ip)
103

    
104

    
105
def StartMaster(master_netdev, master_ip, debug):
106
  """Starts the master.
107

    
108
  """
109
  result = utils.RunCmd(["fping", "-q", master_ip])
110
  if not result.failed:
111
    r2 = utils.RunCmd(["fping", "-q", "-S127.0.0.1", master_ip])
112
    if not r2.failed:
113
      # we already have the ip:
114
      if debug:
115
        sys.stderr.write("Notice: already started.\n")
116
      return EXIT_OK
117
    else:
118
      return EXIT_DUPLICATE_IP
119
  result = utils.RunCmd(["ip", "address", "add", "%s/32" % master_ip,
120
                         "dev", master_netdev, "label",
121
                         "%s:0" % master_netdev])
122
  if result.failed:
123
    if debug:
124
      sys.stderr.write("Can't activate master IP: %s\n" % result.output)
125
    return EXIT_SOME_ERROR
126

    
127
  result = utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev,
128
                         "-s", master_ip, master_ip])
129
  # we'll ignore the exit code of arping
130
  return EXIT_OK
131

    
132

    
133
def StopMaster(master_netdev, master_ip, debug):
134
  """Stops the master.
135

    
136
  """
137
  result = utils.RunCmd(["ip", "address", "del", "%s/32" % master_ip,
138
                         "dev", master_netdev])
139
  if result.failed:
140
    if debug:
141
      sys.stderr.write("Can't remove the master IP, error: %s" % result.output)
142
    # but otherwise ignore the failure
143
  return EXIT_OK
144

    
145

    
146
def main():
147
  """Main function.
148

    
149
  """
150
  options, args = ParseOptions()
151
  debug = options.debug
152
  try:
153
    myself = utils.HostInfo()
154
  except errors.ResolverError, err:
155
    sys.stderr.write("Cannot resolve my own name (%s)\n" % err.args[0])
156
    return EXIT_NODESETUP_ERROR
157

    
158
  result = CheckNodeSetup(debug)
159
  if not result:
160
    if debug:
161
      sys.stderr.write("Node configuration incomplete.\n")
162
    return EXIT_NODESETUP_ERROR
163

    
164
  master_node, master_netdev, master_ip = result
165
  if myself.name != master_node and args[0] == "start":
166
    if debug:
167
      sys.stderr.write("Not master, ignoring request.\n")
168
    return EXIT_NOTMASTER
169

    
170
  if args[0] == "start":
171
    fn = StartMaster
172
  else:
173
    fn = StopMaster
174

    
175
  result = fn(master_netdev, master_ip, debug)
176
  sys.exit(result)
177

    
178

    
179
if __name__ == '__main__':
180
  main()