Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-master @ 3ecf6786

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 constants
43
from ganeti import errors
44
from ganeti import ssconf
45
from ganeti import utils
46

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

    
54

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

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

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

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

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

    
76
  return options, args
77

    
78

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

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

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

    
105

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

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

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

    
133

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

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

    
146

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

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

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

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

    
170
  result = fn(master_netdev, master_ip, debug)
171
  sys.exit(result)
172

    
173

    
174
if __name__ == '__main__':
175
  main()