Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-master @ 38242904

History | View | Annotate | Download (4.9 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
import socket
39

    
40
from optparse import OptionParser
41

    
42
from ganeti import logger
43
from ganeti import constants
44
from ganeti import errors
45
from ganeti import ssconf
46
from ganeti import utils
47

    
48
EXIT_OK = 0
49
EXIT_SOME_ERROR = 1
50
EXIT_NOTMASTER = constants.EXIT_NOTMASTER
51
EXIT_NODESETUP_ERROR = 12
52
EXIT_DUPLICATE_IP = 13
53
EXIT_ARGS_ERROR = 14
54

    
55

    
56
def ParseOptions():
57
  """Parse the command line options.
58

    
59
  Returns:
60
    (options, args) as from OptionParser.parse_args()
61

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

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

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

    
77
  return options, args
78

    
79

    
80
def CheckNodeSetup(debug):
81
  """Checks the node setup.
82

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

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

    
106

    
107
def StartMaster(master_netdev, master_ip, debug):
108
  """Starts the master.
109

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

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

    
134

    
135
def StopMaster(master_netdev, master_ip, debug):
136
  """Stops the master.
137

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

    
147

    
148
def main():
149
  """Main function.
150

    
151
  """
152
  options, args = ParseOptions()
153
  debug = options.debug
154
  result = CheckNodeSetup(debug)
155
  if not result:
156
    if debug:
157
      sys.stderr.write("Node configuration incomplete.\n")
158
    return EXIT_NODESETUP_ERROR
159

    
160
  master_node, master_netdev, master_ip = result
161
  if socket.gethostname() != master_node and args[0] == "start":
162
    if debug:
163
      sys.stderr.write("Not master, ignoring request.\n")
164
    return EXIT_NOTMASTER
165

    
166
  if args[0] == "start":
167
    fn = StartMaster
168
  else:
169
    fn = StopMaster
170

    
171
  return fn(master_netdev, master_ip, debug)
172

    
173

    
174
if __name__=='__main__':
175
  exit_code = main()
176
  sys.exit(exit_code)