Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-master @ 6e06b36c

History | View | Annotate | Download (5.1 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
39 880478f8 Iustin Pop
from optparse import OptionParser
40 880478f8 Iustin Pop
41 880478f8 Iustin Pop
from ganeti import constants
42 880478f8 Iustin Pop
from ganeti import errors
43 880478f8 Iustin Pop
from ganeti import ssconf
44 880478f8 Iustin Pop
from ganeti import utils
45 880478f8 Iustin Pop
46 880478f8 Iustin Pop
EXIT_OK = 0
47 880478f8 Iustin Pop
EXIT_SOME_ERROR = 1
48 38242904 Iustin Pop
EXIT_NOTMASTER = constants.EXIT_NOTMASTER
49 619fdc8e Iustin Pop
EXIT_NODESETUP_ERROR = constants.EXIT_NODESETUP_ERROR
50 880478f8 Iustin Pop
EXIT_DUPLICATE_IP = 13
51 880478f8 Iustin Pop
EXIT_ARGS_ERROR = 14
52 880478f8 Iustin Pop
53 880478f8 Iustin Pop
54 880478f8 Iustin Pop
def ParseOptions():
55 880478f8 Iustin Pop
  """Parse the command line options.
56 880478f8 Iustin Pop
57 880478f8 Iustin Pop
  Returns:
58 880478f8 Iustin Pop
    (options, args) as from OptionParser.parse_args()
59 880478f8 Iustin Pop
60 880478f8 Iustin Pop
  """
61 880478f8 Iustin Pop
  parser = OptionParser(description="Ganeti master",
62 880478f8 Iustin Pop
                        usage="%prog [-d]",
63 880478f8 Iustin Pop
                        version="%%prog (ganeti) %s" %
64 880478f8 Iustin Pop
                        constants.RELEASE_VERSION)
65 880478f8 Iustin Pop
66 880478f8 Iustin Pop
  parser.add_option("-d", "--debug", dest="debug",
67 880478f8 Iustin Pop
                    help="Enable some debug messages",
68 880478f8 Iustin Pop
                    default=False, action="store_true")
69 880478f8 Iustin Pop
  options, args = parser.parse_args()
70 880478f8 Iustin Pop
71 880478f8 Iustin Pop
  if len(args) != 1 or args[0] not in ("start", "stop"):
72 880478f8 Iustin Pop
    sys.stderr.write("Usage: %s [-d] start|stop\n" % sys.argv[0])
73 880478f8 Iustin Pop
    sys.exit(EXIT_ARGS_ERROR)
74 880478f8 Iustin Pop
75 880478f8 Iustin Pop
  return options, args
76 880478f8 Iustin Pop
77 880478f8 Iustin Pop
78 880478f8 Iustin Pop
def CheckNodeSetup(debug):
79 880478f8 Iustin Pop
  """Checks the node setup.
80 880478f8 Iustin Pop
81 880478f8 Iustin Pop
  If the node setup if ok, this function will return the tuple
82 880478f8 Iustin Pop
  (master_hostname, master_netdev, master_ip). Otherwise the return
83 880478f8 Iustin Pop
  value will be None.
84 880478f8 Iustin Pop
85 880478f8 Iustin Pop
  """
86 880478f8 Iustin Pop
  for fname in (constants.SSL_CERT_FILE,):
87 880478f8 Iustin Pop
    if not os.path.isfile(fname):
88 880478f8 Iustin Pop
      if debug:
89 880478f8 Iustin Pop
        sys.stderr.write("Missing config file %s.\n" % fname)
90 880478f8 Iustin Pop
      return None
91 880478f8 Iustin Pop
  try:
92 880478f8 Iustin Pop
    ss = ssconf.SimpleStore()
93 880478f8 Iustin Pop
    port = ss.GetNodeDaemonPort()
94 880478f8 Iustin Pop
    pwdata = ss.GetNodeDaemonPassword()
95 880478f8 Iustin Pop
    master_name = ss.GetMasterNode()
96 880478f8 Iustin Pop
    master_netdev = ss.GetMasterNetdev()
97 880478f8 Iustin Pop
    master_ip = ss.GetMasterIP()
98 880478f8 Iustin Pop
  except errors.ConfigurationError, err:
99 880478f8 Iustin Pop
    if debug:
100 880478f8 Iustin Pop
      sys.stderr.write("Cluster configuration incomplete: '%s'\n" % str(err))
101 880478f8 Iustin Pop
    return None
102 880478f8 Iustin Pop
  return (master_name, master_netdev, master_ip)
103 880478f8 Iustin Pop
104 880478f8 Iustin Pop
105 880478f8 Iustin Pop
def StartMaster(master_netdev, master_ip, debug):
106 880478f8 Iustin Pop
  """Starts the master.
107 880478f8 Iustin Pop
108 880478f8 Iustin Pop
  """
109 16abfbc2 Alexander Schreiber
  if utils.TcpPing(utils.HostInfo().name, master_ip,
110 16abfbc2 Alexander Schreiber
                   constants.DEFAULT_NODED_PORT):
111 16abfbc2 Alexander Schreiber
    if utils.TcpPing(constants.LOCALHOST_IP_ADDRESS, master_ip,
112 16abfbc2 Alexander Schreiber
                     constants.DEFAULT_NODED_PORT):
113 880478f8 Iustin Pop
      # we already have the ip:
114 880478f8 Iustin Pop
      if debug:
115 880478f8 Iustin Pop
        sys.stderr.write("Notice: already started.\n")
116 880478f8 Iustin Pop
      return EXIT_OK
117 880478f8 Iustin Pop
    else:
118 880478f8 Iustin Pop
      return EXIT_DUPLICATE_IP
119 880478f8 Iustin Pop
  result = utils.RunCmd(["ip", "address", "add", "%s/32" % master_ip,
120 880478f8 Iustin Pop
                         "dev", master_netdev, "label",
121 880478f8 Iustin Pop
                         "%s:0" % master_netdev])
122 880478f8 Iustin Pop
  if result.failed:
123 880478f8 Iustin Pop
    if debug:
124 880478f8 Iustin Pop
      sys.stderr.write("Can't activate master IP: %s\n" % result.output)
125 880478f8 Iustin Pop
    return EXIT_SOME_ERROR
126 880478f8 Iustin Pop
127 880478f8 Iustin Pop
  result = utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev,
128 880478f8 Iustin Pop
                         "-s", master_ip, master_ip])
129 880478f8 Iustin Pop
  # we'll ignore the exit code of arping
130 880478f8 Iustin Pop
  return EXIT_OK
131 880478f8 Iustin Pop
132 880478f8 Iustin Pop
133 880478f8 Iustin Pop
def StopMaster(master_netdev, master_ip, debug):
134 880478f8 Iustin Pop
  """Stops the master.
135 880478f8 Iustin Pop
136 880478f8 Iustin Pop
  """
137 880478f8 Iustin Pop
  result = utils.RunCmd(["ip", "address", "del", "%s/32" % master_ip,
138 880478f8 Iustin Pop
                         "dev", master_netdev])
139 880478f8 Iustin Pop
  if result.failed:
140 880478f8 Iustin Pop
    if debug:
141 880478f8 Iustin Pop
      sys.stderr.write("Can't remove the master IP, error: %s" % result.output)
142 880478f8 Iustin Pop
    # but otherwise ignore the failure
143 880478f8 Iustin Pop
  return EXIT_OK
144 880478f8 Iustin Pop
145 880478f8 Iustin Pop
146 880478f8 Iustin Pop
def main():
147 880478f8 Iustin Pop
  """Main function.
148 880478f8 Iustin Pop
149 880478f8 Iustin Pop
  """
150 880478f8 Iustin Pop
  options, args = ParseOptions()
151 880478f8 Iustin Pop
  debug = options.debug
152 89e1fc26 Iustin Pop
  try:
153 89e1fc26 Iustin Pop
    myself = utils.HostInfo()
154 89e1fc26 Iustin Pop
  except errors.ResolverError, err:
155 89e1fc26 Iustin Pop
    sys.stderr.write("Cannot resolve my own name (%s)\n" % err.args[0])
156 89e1fc26 Iustin Pop
    return EXIT_NODESETUP_ERROR
157 89e1fc26 Iustin Pop
158 880478f8 Iustin Pop
  result = CheckNodeSetup(debug)
159 880478f8 Iustin Pop
  if not result:
160 880478f8 Iustin Pop
    if debug:
161 880478f8 Iustin Pop
      sys.stderr.write("Node configuration incomplete.\n")
162 880478f8 Iustin Pop
    return EXIT_NODESETUP_ERROR
163 880478f8 Iustin Pop
164 880478f8 Iustin Pop
  master_node, master_netdev, master_ip = result
165 89e1fc26 Iustin Pop
  if myself.name != master_node and args[0] == "start":
166 880478f8 Iustin Pop
    if debug:
167 880478f8 Iustin Pop
      sys.stderr.write("Not master, ignoring request.\n")
168 880478f8 Iustin Pop
    return EXIT_NOTMASTER
169 880478f8 Iustin Pop
170 880478f8 Iustin Pop
  if args[0] == "start":
171 880478f8 Iustin Pop
    fn = StartMaster
172 880478f8 Iustin Pop
  else:
173 880478f8 Iustin Pop
    fn = StopMaster
174 880478f8 Iustin Pop
175 3ecf6786 Iustin Pop
  result = fn(master_netdev, master_ip, debug)
176 3ecf6786 Iustin Pop
  sys.exit(result)
177 880478f8 Iustin Pop
178 880478f8 Iustin Pop
179 3ecf6786 Iustin Pop
if __name__ == '__main__':
180 3ecf6786 Iustin Pop
  main()