Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-master @ eee1fa2d

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 b15d625f Iustin Pop
  if utils.TcpPing(master_ip, constants.DEFAULT_NODED_PORT):
110 b15d625f Iustin Pop
    if utils.TcpPing(master_ip, constants.DEFAULT_NODED_PORT,
111 b15d625f Iustin Pop
                     source=constants.LOCALHOST_IP_ADDRESS):
112 880478f8 Iustin Pop
      # we already have the ip:
113 880478f8 Iustin Pop
      if debug:
114 880478f8 Iustin Pop
        sys.stderr.write("Notice: already started.\n")
115 880478f8 Iustin Pop
      return EXIT_OK
116 880478f8 Iustin Pop
    else:
117 880478f8 Iustin Pop
      return EXIT_DUPLICATE_IP
118 880478f8 Iustin Pop
  result = utils.RunCmd(["ip", "address", "add", "%s/32" % master_ip,
119 880478f8 Iustin Pop
                         "dev", master_netdev, "label",
120 880478f8 Iustin Pop
                         "%s:0" % master_netdev])
121 880478f8 Iustin Pop
  if result.failed:
122 880478f8 Iustin Pop
    if debug:
123 880478f8 Iustin Pop
      sys.stderr.write("Can't activate master IP: %s\n" % result.output)
124 880478f8 Iustin Pop
    return EXIT_SOME_ERROR
125 880478f8 Iustin Pop
126 880478f8 Iustin Pop
  result = utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev,
127 880478f8 Iustin Pop
                         "-s", master_ip, master_ip])
128 880478f8 Iustin Pop
  # we'll ignore the exit code of arping
129 880478f8 Iustin Pop
  return EXIT_OK
130 880478f8 Iustin Pop
131 880478f8 Iustin Pop
132 880478f8 Iustin Pop
def StopMaster(master_netdev, master_ip, debug):
133 880478f8 Iustin Pop
  """Stops the master.
134 880478f8 Iustin Pop
135 880478f8 Iustin Pop
  """
136 880478f8 Iustin Pop
  result = utils.RunCmd(["ip", "address", "del", "%s/32" % master_ip,
137 880478f8 Iustin Pop
                         "dev", master_netdev])
138 880478f8 Iustin Pop
  if result.failed:
139 880478f8 Iustin Pop
    if debug:
140 880478f8 Iustin Pop
      sys.stderr.write("Can't remove the master IP, error: %s" % result.output)
141 880478f8 Iustin Pop
    # but otherwise ignore the failure
142 880478f8 Iustin Pop
  return EXIT_OK
143 880478f8 Iustin Pop
144 880478f8 Iustin Pop
145 880478f8 Iustin Pop
def main():
146 880478f8 Iustin Pop
  """Main function.
147 880478f8 Iustin Pop
148 880478f8 Iustin Pop
  """
149 880478f8 Iustin Pop
  options, args = ParseOptions()
150 880478f8 Iustin Pop
  debug = options.debug
151 89e1fc26 Iustin Pop
  try:
152 89e1fc26 Iustin Pop
    myself = utils.HostInfo()
153 89e1fc26 Iustin Pop
  except errors.ResolverError, err:
154 89e1fc26 Iustin Pop
    sys.stderr.write("Cannot resolve my own name (%s)\n" % err.args[0])
155 89e1fc26 Iustin Pop
    return EXIT_NODESETUP_ERROR
156 89e1fc26 Iustin Pop
157 880478f8 Iustin Pop
  result = CheckNodeSetup(debug)
158 880478f8 Iustin Pop
  if not result:
159 880478f8 Iustin Pop
    if debug:
160 880478f8 Iustin Pop
      sys.stderr.write("Node configuration incomplete.\n")
161 880478f8 Iustin Pop
    return EXIT_NODESETUP_ERROR
162 880478f8 Iustin Pop
163 880478f8 Iustin Pop
  master_node, master_netdev, master_ip = result
164 89e1fc26 Iustin Pop
  if myself.name != master_node and args[0] == "start":
165 880478f8 Iustin Pop
    if debug:
166 880478f8 Iustin Pop
      sys.stderr.write("Not master, ignoring request.\n")
167 880478f8 Iustin Pop
    return EXIT_NOTMASTER
168 880478f8 Iustin Pop
169 880478f8 Iustin Pop
  if args[0] == "start":
170 880478f8 Iustin Pop
    fn = StartMaster
171 880478f8 Iustin Pop
  else:
172 880478f8 Iustin Pop
    fn = StopMaster
173 880478f8 Iustin Pop
174 3ecf6786 Iustin Pop
  result = fn(master_netdev, master_ip, debug)
175 3ecf6786 Iustin Pop
  sys.exit(result)
176 880478f8 Iustin Pop
177 880478f8 Iustin Pop
178 3ecf6786 Iustin Pop
if __name__ == '__main__':
179 3ecf6786 Iustin Pop
  main()