1
2
3 from starcluster.logger import log
4 from starcluster import exception
5
6 from completers import ClusterCompleter
7
8
10 """
11 stop [options] <cluster_tag> ...
12
13 Stop a running EBS-backed cluster
14
15 Example:
16
17 $ starcluster stop mycluster
18
19 The above command will put all flat-rate EBS-backed nodes in 'mycluster'
20 into a 'stopped' state preserving the local disks. You can then use the
21 start command with the -x (--no-create) option to resume the cluster later
22 on without losing data on the local disks:
23
24 $ starcluster start -x mycluster
25
26 This will 'start' all 'stopped' non-spot EBS-backed instances and
27 reconfigure the cluster.
28
29 In general, all nodes in the cluster must be 'stoppable' meaning all nodes
30 are backed by flat-rate EBS-backed instances. If any 'unstoppable' nodes
31 are found an error is raised. A node is 'unstoppable' if it is backed by
32 either a spot or S3-backed instance.
33
34 However, if the cluster contains a mix of 'stoppable' and 'unstoppable'
35 nodes you can stop all stoppable nodes and terminate any unstoppable nodes
36 using the --terminate-unstoppable (-t) option:
37
38 $ starcluster stop --terminate-unstoppable mycluster
39
40 This will stop all nodes that can be stopped and terminate the rest.
41 """
42 names = ['stop']
43
45 parser.add_option("-c", "--confirm", dest="confirm",
46 action="store_true", default=False,
47 help="Do not prompt for confirmation, "
48 "just stop the cluster")
49 parser.add_option("-t", "--terminate-unstoppable",
50 dest="terminate_unstoppable", action="store_true",
51 default=False, help="Terminate nodes that are not "
52 "stoppable (i.e. spot or S3-backed nodes)")
53
55 if not args:
56 cls = [c.cluster_tag for c in
57 self.cm.get_clusters(load_plugins=False,
58 load_receipt=False)]
59 msg = "please specify a cluster"
60 if cls:
61 opts = ', '.join(cls)
62 msg = " ".join([msg, '(options:', opts, ')'])
63 self.parser.error(msg)
64 for cluster_name in args:
65 cl = self.cm.get_cluster(cluster_name)
66 is_stoppable = cl.is_stoppable()
67 if not is_stoppable:
68 has_stoppable_nodes = cl.has_stoppable_nodes()
69 if not self.opts.terminate_unstoppable and has_stoppable_nodes:
70 raise exception.BaseException(
71 "Cluster '%s' contains 'stoppable' and 'unstoppable' "
72 "nodes. Your options are:\n\n"
73 "1. Use the --terminate-unstoppable option to "
74 "stop all 'stoppable' nodes and terminate all "
75 "'unstoppable' nodes\n\n"
76 "2. Use the 'terminate' command to destroy the "
77 "cluster.\n\nPass --help for more info." %
78 cluster_name)
79 if not has_stoppable_nodes:
80 raise exception.BaseException(
81 "Cluster '%s' does not contain any 'stoppable' nodes "
82 "and can only be terminated. Please use the "
83 "'terminate' command instead to destroy the cluster."
84 "\n\nPass --help for more info" % cluster_name)
85 if not self.opts.confirm:
86 resp = raw_input("Stop cluster %s (y/n)? " % cluster_name)
87 if resp not in ['y', 'Y', 'yes']:
88 log.info("Aborting...")
89 continue
90 cl.stop_cluster(self.opts.terminate_unstoppable)
91 log.warn("All non-spot, EBS-backed nodes are now in a "
92 "'stopped' state")
93 log.warn("You can restart this cluster by passing -x "
94 "to the 'start' command")
95 log.warn("Use the 'terminate' command to *completely* "
96 "terminate this cluster")
97