Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-master @ 619fdc8e

History | View | Annotate | Download (4.9 kB)

1 880478f8 Iustin Pop
#!/usr/bin/python
2 880478f8 Iustin Pop
#
3 880478f8 Iustin Pop
4 880478f8 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 880478f8 Iustin Pop
#
6 880478f8 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 880478f8 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 880478f8 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 880478f8 Iustin Pop
# (at your option) any later version.
10 880478f8 Iustin Pop
#
11 880478f8 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 880478f8 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 880478f8 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 880478f8 Iustin Pop
# General Public License for more details.
15 880478f8 Iustin Pop
#
16 880478f8 Iustin Pop
# You should have received a copy of the GNU General Public License
17 880478f8 Iustin Pop
# along with this program; if not, write to the Free Software
18 880478f8 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 880478f8 Iustin Pop
# 02110-1301, USA.
20 880478f8 Iustin Pop
21 880478f8 Iustin Pop
22 880478f8 Iustin Pop
"""Ganeti master script
23 880478f8 Iustin Pop
24 880478f8 Iustin Pop
Exit codes, for both start and stop:
25 880478f8 Iustin Pop
  - 0: master setup successful
26 880478f8 Iustin Pop
  - 1: some generic error (this exit code can also be thrown by exceptions)
27 880478f8 Iustin Pop
  - 11: node is not master, nothing to do
28 880478f8 Iustin Pop
  - 12: node setup incomplete, cannot start
29 880478f8 Iustin Pop
  - 13: node should be master, but someone has the ip address already
30 880478f8 Iustin Pop
31 880478f8 Iustin Pop
Only exit codes 0 and 11 represent an ok state. Code 1 was left for
32 880478f8 Iustin Pop
generic errors as other python code can cause exit with code 1.
33 880478f8 Iustin Pop
34 880478f8 Iustin Pop
"""
35 880478f8 Iustin Pop
36 880478f8 Iustin Pop
import os
37 880478f8 Iustin Pop
import sys
38 880478f8 Iustin Pop
import socket
39 880478f8 Iustin Pop
40 880478f8 Iustin Pop
from optparse import OptionParser
41 880478f8 Iustin Pop
42 880478f8 Iustin Pop
from ganeti import constants
43 880478f8 Iustin Pop
from ganeti import errors
44 880478f8 Iustin Pop
from ganeti import ssconf
45 880478f8 Iustin Pop
from ganeti import utils
46 880478f8 Iustin Pop
47 880478f8 Iustin Pop
EXIT_OK = 0
48 880478f8 Iustin Pop
EXIT_SOME_ERROR = 1
49 38242904 Iustin Pop
EXIT_NOTMASTER = constants.EXIT_NOTMASTER
50 619fdc8e Iustin Pop
EXIT_NODESETUP_ERROR = constants.EXIT_NODESETUP_ERROR
51 880478f8 Iustin Pop
EXIT_DUPLICATE_IP = 13
52 880478f8 Iustin Pop
EXIT_ARGS_ERROR = 14
53 880478f8 Iustin Pop
54 880478f8 Iustin Pop
55 880478f8 Iustin Pop
def ParseOptions():
56 880478f8 Iustin Pop
  """Parse the command line options.
57 880478f8 Iustin Pop
58 880478f8 Iustin Pop
  Returns:
59 880478f8 Iustin Pop
    (options, args) as from OptionParser.parse_args()
60 880478f8 Iustin Pop
61 880478f8 Iustin Pop
  """
62 880478f8 Iustin Pop
  parser = OptionParser(description="Ganeti master",
63 880478f8 Iustin Pop
                        usage="%prog [-d]",
64 880478f8 Iustin Pop
                        version="%%prog (ganeti) %s" %
65 880478f8 Iustin Pop
                        constants.RELEASE_VERSION)
66 880478f8 Iustin Pop
67 880478f8 Iustin Pop
  parser.add_option("-d", "--debug", dest="debug",
68 880478f8 Iustin Pop
                    help="Enable some debug messages",
69 880478f8 Iustin Pop
                    default=False, action="store_true")
70 880478f8 Iustin Pop
  options, args = parser.parse_args()
71 880478f8 Iustin Pop
72 880478f8 Iustin Pop
  if len(args) != 1 or args[0] not in ("start", "stop"):
73 880478f8 Iustin Pop
    sys.stderr.write("Usage: %s [-d] start|stop\n" % sys.argv[0])
74 880478f8 Iustin Pop
    sys.exit(EXIT_ARGS_ERROR)
75 880478f8 Iustin Pop
76 880478f8 Iustin Pop
  return options, args
77 880478f8 Iustin Pop
78 880478f8 Iustin Pop
79 880478f8 Iustin Pop
def CheckNodeSetup(debug):
80 880478f8 Iustin Pop
  """Checks the node setup.
81 880478f8 Iustin Pop
82 880478f8 Iustin Pop
  If the node setup if ok, this function will return the tuple
83 880478f8 Iustin Pop
  (master_hostname, master_netdev, master_ip). Otherwise the return
84 880478f8 Iustin Pop
  value will be None.
85 880478f8 Iustin Pop
86 880478f8 Iustin Pop
  """
87 880478f8 Iustin Pop
  for fname in (constants.SSL_CERT_FILE,):
88 880478f8 Iustin Pop
    if not os.path.isfile(fname):
89 880478f8 Iustin Pop
      if debug:
90 880478f8 Iustin Pop
        sys.stderr.write("Missing config file %s.\n" % fname)
91 880478f8 Iustin Pop
      return None
92 880478f8 Iustin Pop
  try:
93 880478f8 Iustin Pop
    ss = ssconf.SimpleStore()
94 880478f8 Iustin Pop
    port = ss.GetNodeDaemonPort()
95 880478f8 Iustin Pop
    pwdata = ss.GetNodeDaemonPassword()
96 880478f8 Iustin Pop
    master_name = ss.GetMasterNode()
97 880478f8 Iustin Pop
    master_netdev = ss.GetMasterNetdev()
98 880478f8 Iustin Pop
    master_ip = ss.GetMasterIP()
99 880478f8 Iustin Pop
  except errors.ConfigurationError, err:
100 880478f8 Iustin Pop
    if debug:
101 880478f8 Iustin Pop
      sys.stderr.write("Cluster configuration incomplete: '%s'\n" % str(err))
102 880478f8 Iustin Pop
    return None
103 880478f8 Iustin Pop
  return (master_name, master_netdev, master_ip)
104 880478f8 Iustin Pop
105 880478f8 Iustin Pop
106 880478f8 Iustin Pop
def StartMaster(master_netdev, master_ip, debug):
107 880478f8 Iustin Pop
  """Starts the master.
108 880478f8 Iustin Pop
109 880478f8 Iustin Pop
  """
110 880478f8 Iustin Pop
  result = utils.RunCmd(["fping", "-q", master_ip])
111 880478f8 Iustin Pop
  if not result.failed:
112 880478f8 Iustin Pop
    r2 = utils.RunCmd(["fping", "-q", "-S127.0.0.1", master_ip])
113 3ecf6786 Iustin Pop
    if not r2.failed:
114 880478f8 Iustin Pop
      # we already have the ip:
115 880478f8 Iustin Pop
      if debug:
116 880478f8 Iustin Pop
        sys.stderr.write("Notice: already started.\n")
117 880478f8 Iustin Pop
      return EXIT_OK
118 880478f8 Iustin Pop
    else:
119 880478f8 Iustin Pop
      return EXIT_DUPLICATE_IP
120 880478f8 Iustin Pop
  result = utils.RunCmd(["ip", "address", "add", "%s/32" % master_ip,
121 880478f8 Iustin Pop
                         "dev", master_netdev, "label",
122 880478f8 Iustin Pop
                         "%s:0" % master_netdev])
123 880478f8 Iustin Pop
  if result.failed:
124 880478f8 Iustin Pop
    if debug:
125 880478f8 Iustin Pop
      sys.stderr.write("Can't activate master IP: %s\n" % result.output)
126 880478f8 Iustin Pop
    return EXIT_SOME_ERROR
127 880478f8 Iustin Pop
128 880478f8 Iustin Pop
  result = utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev,
129 880478f8 Iustin Pop
                         "-s", master_ip, master_ip])
130 880478f8 Iustin Pop
  # we'll ignore the exit code of arping
131 880478f8 Iustin Pop
  return EXIT_OK
132 880478f8 Iustin Pop
133 880478f8 Iustin Pop
134 880478f8 Iustin Pop
def StopMaster(master_netdev, master_ip, debug):
135 880478f8 Iustin Pop
  """Stops the master.
136 880478f8 Iustin Pop
137 880478f8 Iustin Pop
  """
138 880478f8 Iustin Pop
  result = utils.RunCmd(["ip", "address", "del", "%s/32" % master_ip,
139 880478f8 Iustin Pop
                         "dev", master_netdev])
140 880478f8 Iustin Pop
  if result.failed:
141 880478f8 Iustin Pop
    if debug:
142 880478f8 Iustin Pop
      sys.stderr.write("Can't remove the master IP, error: %s" % result.output)
143 880478f8 Iustin Pop
    # but otherwise ignore the failure
144 880478f8 Iustin Pop
  return EXIT_OK
145 880478f8 Iustin Pop
146 880478f8 Iustin Pop
147 880478f8 Iustin Pop
def main():
148 880478f8 Iustin Pop
  """Main function.
149 880478f8 Iustin Pop
150 880478f8 Iustin Pop
  """
151 880478f8 Iustin Pop
  options, args = ParseOptions()
152 880478f8 Iustin Pop
  debug = options.debug
153 880478f8 Iustin Pop
  result = CheckNodeSetup(debug)
154 880478f8 Iustin Pop
  if not result:
155 880478f8 Iustin Pop
    if debug:
156 880478f8 Iustin Pop
      sys.stderr.write("Node configuration incomplete.\n")
157 880478f8 Iustin Pop
    return EXIT_NODESETUP_ERROR
158 880478f8 Iustin Pop
159 880478f8 Iustin Pop
  master_node, master_netdev, master_ip = result
160 880478f8 Iustin Pop
  if socket.gethostname() != master_node and args[0] == "start":
161 880478f8 Iustin Pop
    if debug:
162 880478f8 Iustin Pop
      sys.stderr.write("Not master, ignoring request.\n")
163 880478f8 Iustin Pop
    return EXIT_NOTMASTER
164 880478f8 Iustin Pop
165 880478f8 Iustin Pop
  if args[0] == "start":
166 880478f8 Iustin Pop
    fn = StartMaster
167 880478f8 Iustin Pop
  else:
168 880478f8 Iustin Pop
    fn = StopMaster
169 880478f8 Iustin Pop
170 3ecf6786 Iustin Pop
  result = fn(master_netdev, master_ip, debug)
171 3ecf6786 Iustin Pop
  sys.exit(result)
172 880478f8 Iustin Pop
173 880478f8 Iustin Pop
174 3ecf6786 Iustin Pop
if __name__ == '__main__':
175 3ecf6786 Iustin Pop
  main()