Comment formatting updates.
[ganeti-local] / scripts / gnt-cluster
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 import sys
23 from optparse import make_option
24 import pprint
25
26 from ganeti.cli import *
27 from ganeti import opcodes
28
29
30 def InitCluster(opts, args):
31   """Initialize the cluster.
32
33   Args:
34     opts - class with options as members
35     args - list of arguments, expected to be [clustername]
36
37   """
38   op = opcodes.OpInitCluster(cluster_name=args[0],
39                              secondary_ip=opts.secondary_ip,
40                              hypervisor_type=opts.hypervisor_type,
41                              vg_name=opts.vg_name,
42                              mac_prefix=opts.mac_prefix,
43                              def_bridge=opts.def_bridge,
44                              master_netdev=opts.master_netdev)
45   SubmitOpCode(op)
46   return 0
47
48
49 def DestroyCluster(opts, args):
50   """Destroy the cluster.
51
52   Args:
53     opts - class with options as members
54
55   """
56   if not opts.yes_do_it:
57     print ("Destroying a cluster is irreversibly. If you really want destroy"
58            " this cluster, supply the --yes-do-it option.")
59     return 1
60
61   op = opcodes.OpDestroyCluster()
62   SubmitOpCode(op)
63   return 0
64
65
66 def ShowClusterVersion(opts, args):
67   """Write version of ganeti software to the standard output.
68
69   Args:
70     opts - class with options as members
71
72   """
73   op = opcodes.OpQueryClusterInfo()
74   result = SubmitOpCode(op)
75   print ("Software version: %s" % result["software_version"])
76   print ("Internode protocol: %s" % result["protocol_version"])
77   print ("Configuration format: %s" % result["config_version"])
78   print ("OS api version: %s" % result["os_api_version"])
79   print ("Export interface: %s" % result["export_version"])
80   return 0
81
82
83 def ShowClusterMaster(opts, args):
84   """Write name of master node to the standard output.
85
86   Args:
87     opts - class with options as members
88
89   """
90   op = opcodes.OpQueryClusterInfo()
91   result = SubmitOpCode(op)
92   print (result["master"])
93   return 0
94
95
96 def ShowClusterConfig(opts, args):
97   """Shows cluster information.
98
99   """
100   op = opcodes.OpQueryClusterInfo()
101   result = SubmitOpCode(op)
102
103   print ("Cluster name: %s" % result["name"])
104
105   print ("Architecture: %s (%s)" %
106             (result["architecture"][0], result["architecture"][1]))
107
108   print ("Master node: %s" % result["master"])
109
110   print ("Instances:")
111   for name, node in result["instances"]:
112     print ("  - %s (on %s)" % (name, node))
113   print ("Nodes:")
114   for name in result["nodes"]:
115     print ("  - %s" % name)
116
117   return 0
118
119
120 def ClusterCopyFile(opts, args):
121   """Copy a file from master to some nodes.
122
123   Args:
124     opts - class with options as members
125     args - list containing a single element, the file name
126   Opts used:
127     nodes - list containing the name of target nodes; if empty, all nodes
128
129   """
130   op = opcodes.OpClusterCopyFile(filename=args[0], nodes=opts.nodes)
131   SubmitOpCode(op)
132   return 0
133
134
135 def RunClusterCommand(opts, args):
136   """Run a command on some nodes.
137
138   Args:
139     opts - class with options as members
140     args - the command list as a list
141   Opts used:
142     nodes: list containing the name of target nodes; if empty, all nodes
143
144   """
145   command = " ".join(args)
146   nodes = opts.nodes
147   op = opcodes.OpRunClusterCommand(command=command, nodes=nodes)
148   result = SubmitOpCode(op)
149   for node, sshcommand, output, exit_code in result:
150     print ("------------------------------------------------")
151     print ("node: %s" % node)
152     print ("command: %s" % sshcommand)
153     print ("%s" % output)
154     print ("return code = %s" % exit_code)
155
156
157 def VerifyCluster(opts, args):
158   """Verify integrity of cluster, performing various test on nodes.
159
160   Args:
161     opts - class with options as members
162
163   """
164   op = opcodes.OpVerifyCluster()
165   result = SubmitOpCode(op)
166   return result
167
168
169 def MasterFailover(opts, args):
170   """Failover the master node.
171
172   This command, when run on a non-master node, will cause the current
173   master to cease being master, and the non-master to become new
174   master.
175
176   """
177   op = opcodes.OpMasterFailover()
178   SubmitOpCode(op)
179
180
181 # this is an option common to more than one command, so we declare
182 # it here and reuse it
183 node_option = make_option("-n", "--node", action="append", dest="nodes",
184                           help="Node to copy to (if not given, all nodes)"
185                           ", can be given multiple times", metavar="<node>",
186                           default=[])
187
188 commands = {
189   'init': (InitCluster, ARGS_ONE,
190            [DEBUG_OPT,
191             make_option("-s", "--secondary-ip", dest="secondary_ip",
192                         help="Specify the secondary ip for this node;"
193                         " if given, the entire cluster must have secondary"
194                         " addresses",
195                         metavar="ADDRESS", default=None),
196             make_option("-t", "--hypervisor-type", dest="hypervisor_type",
197                         help="Specify the hypervisor type (xen-3.0, fake)",
198                         metavar="TYPE", choices=["xen-3.0", "fake"],
199                         default="xen-3.0",),
200             make_option("-m", "--mac-prefix", dest="mac_prefix",
201                         help="Specify the mac prefix for the instance IP"
202                         " addresses, in the format XX:XX:XX",
203                         metavar="PREFIX",
204                         default="aa:00:00",),
205             make_option("-g", "--vg-name", dest="vg_name",
206                         help="Specify the volume group name "
207                         " (cluster-wide) for disk allocation [xenvg]",
208                         metavar="VG",
209                         default="xenvg",),
210             make_option("-b", "--bridge", dest="def_bridge",
211                         help="Specify the default bridge name (cluster-wide)"
212                         " to connect the instances to [xen-br0]",
213                         metavar="BRIDGE",
214                         default="xen-br0",),
215             make_option("--master-netdev", dest="master_netdev",
216                         help="Specify the node interface (cluster-wide)"
217                         " on which the master IP address will be added "
218                         " [xen-br0]",
219                         metavar="NETDEV",
220                         default="xen-br0",),
221             ],
222            "[opts...] <cluster_name>",
223            "Initialises a new cluster configuration"),
224   'destroy': (DestroyCluster, ARGS_NONE,
225               [DEBUG_OPT,
226                make_option("--yes-do-it", dest="yes_do_it",
227                            help="Destroy cluster",
228                            action="store_true"),
229               ],
230               "", "Destroy cluster"),
231   'verify': (VerifyCluster, ARGS_NONE, [DEBUG_OPT],
232              "", "Does a check on the cluster configuration"),
233   'masterfailover': (MasterFailover, ARGS_NONE, [DEBUG_OPT],
234                      "", "Makes the current node the master"),
235   'version': (ShowClusterVersion, ARGS_NONE, [DEBUG_OPT],
236               "", "Shows the cluster version"),
237   'getmaster': (ShowClusterMaster, ARGS_NONE, [DEBUG_OPT],
238                 "", "Shows the cluster master"),
239   'copyfile': (ClusterCopyFile, ARGS_ONE, [DEBUG_OPT, node_option],
240                "[-n node...] <filename>",
241                "Copies a file to all (or only some) nodes"),
242   'command': (RunClusterCommand, ARGS_ATLEAST(1), [DEBUG_OPT, node_option],
243               "[-n node...] <command>",
244               "Runs a command on all (or only some) nodes"),
245   'info': (ShowClusterConfig, ARGS_NONE, [DEBUG_OPT],
246                  "", "Show cluster configuration"),
247   }
248
249 if __name__ == '__main__':
250   retcode = GenericMain(commands)
251   sys.exit(retcode)