1
2
3 import sys
4 import time
5
6 from starcluster import config
7 from starcluster import static
8 from starcluster import exception
9 from starcluster import optcomplete
10 from starcluster.templates import user_msgs
11 from starcluster.logger import log
12
13 from completers import ClusterCompleter
14
15
17 """
18 start [options] <cluster_tag>
19
20 Start a new cluster
21
22 Example:
23
24 $ starcluster start mynewcluster
25
26 This will launch a cluster named "mynewcluster" using the settings from
27 the default cluster template defined in the configuration file. The
28 default cluster template is specified by the 'default_template' option in
29 the [global] section of the config. To use another template besides the
30 default use the --cluster-template option:
31
32 $ starcluster start --cluster-template largecluster mynewcluster
33
34 This will do the same thing only using the settings from the "largecluster"
35 cluster template defined in the config.
36 """
37 names = ['start']
38
39 tag = None
40
42 cfg = config.StarClusterConfig().load()
43 templates = cfg.get_cluster_names().keys()
44 opt = parser.add_option("-c", "--cluster-template", action="store",
45 dest="cluster_template", choices=templates,
46 default=None,
47 help="cluster template to use " + \
48 "from the config file")
49 parser.add_option("-x", "--no-create", dest="no_create",
50 action="store_true", default=False,
51 help="Do not launch new EC2 instances when " + \
52 "starting cluster (use existing instances instead)")
53 parser.add_option("-o", "--create-only", dest="create_only",
54 action="store_true", default=False,
55 help="Only launch/start EC2 instances, " + \
56 "do not perform any setup routines")
57 parser.add_option("-v", "--validate-only", dest="validate_only",
58 action="store_true", default=False,
59 help="Only validate cluster settings, do " + \
60 "not start a cluster")
61 parser.add_option("-V", "--skip-validation", dest="validate",
62 action="store_false", default=True,
63 help="Do not validate cluster settings")
64 parser.add_option("-l", "--login-master", dest="login_master",
65 action="store_true", default=False,
66 help="ssh to ec2 cluster master node after launch")
67 parser.add_option("-q", "--disable-queue", dest="disable_queue",
68 action="store_true", default=None,
69 help="Do not configure a queueing system (SGE)")
70 parser.add_option("-r", "--refresh-interval", dest="refresh_interval",
71 type="int", action="callback", default=None,
72 callback=self._positive_int,
73 help="Refresh interval when waiting for cluster " + \
74 "nodes to come up (default: 30)")
75 parser.add_option("-b", "--bid", dest="spot_bid", action="store",
76 type="float", default=None,
77 help="Requests spot instances instead of flat " + \
78 "rate instances. Uses SPOT_BID as max bid for " + \
79 "the request.")
80 if optcomplete:
81 opt.completer = optcomplete.ListCompleter(opt.choices)
82 parser.add_option("-d", "--description", dest="cluster_description",
83 action="store", type="string",
84 default="Cluster requested at %s" % \
85 time.strftime("%Y%m%d%H%M"),
86 help="brief description of cluster")
87 parser.add_option("-s", "--cluster-size", dest="cluster_size",
88 action="callback", type="int", default=None,
89 callback=self._positive_int,
90 help="number of ec2 instances to launch")
91 parser.add_option("-u", "--cluster-user", dest="cluster_user",
92 action="store", type="string", default=None,
93 help="name of user to create on cluster " + \
94 "(defaults to sgeadmin)")
95 opt = parser.add_option("-S", "--cluster-shell", dest="cluster_shell",
96 action="store",
97 choices=static.AVAILABLE_SHELLS.keys(),
98 default=None,
99 help="shell for cluster user " + \
100 "(defaults to bash)")
101 if optcomplete:
102 opt.completer = optcomplete.ListCompleter(opt.choices)
103 parser.add_option("-m", "--master-image-id", dest="master_image_id",
104 action="store", type="string", default=None,
105 help="AMI to use when launching master")
106 parser.add_option("-n", "--node-image-id", dest="node_image_id",
107 action="store", type="string", default=None,
108 help="AMI to use when launching nodes")
109 parser.add_option("-I", "--master-instance-type",
110 dest="master_instance_type", action="store",
111 choices=static.INSTANCE_TYPES.keys(), default=None,
112 help="specify machine type for the master instance")
113 opt = parser.add_option("-i", "--node-instance-type",
114 dest="node_instance_type", action="store",
115 choices=static.INSTANCE_TYPES.keys(),
116 default=None,
117 help="specify machine type for the node " + \
118 "instances")
119 if optcomplete:
120 opt.completer = optcomplete.ListCompleter(opt.choices)
121 parser.add_option("-a", "--availability-zone",
122 dest="availability_zone", action="store",
123 type="string", default=None,
124 help="availability zone to launch ec2 instances in")
125 parser.add_option("-k", "--keyname", dest="keyname", action="store",
126 type="string", default=None,
127 help="name of the AWS keypair to use when " + \
128 "launching the cluster")
129 parser.add_option("-K", "--key-location", dest="key_location",
130 action="store", type="string", default=None,
131 metavar="FILE",
132 help="path to ssh private key used for this cluster")
133
136
138 if len(args) != 1:
139 self.parser.error("please specify a <cluster_tag>")
140 tag = self.tag = args[0]
141 create = not self.opts.no_create
142 create_only = self.opts.create_only
143 cluster_exists = self.cm.get_cluster_or_none(tag)
144 validate = self.opts.validate
145 validate_running = self.opts.no_create
146 validate_only = self.opts.validate_only
147 if cluster_exists and create:
148 stopped_ebs = cluster_exists.is_cluster_stopped()
149 is_ebs = False
150 if not stopped_ebs:
151 is_ebs = cluster_exists.is_ebs_cluster()
152 raise exception.ClusterExists(tag, is_ebs=is_ebs,
153 stopped_ebs=stopped_ebs)
154 if not cluster_exists and not create:
155 raise exception.ClusterDoesNotExist(tag)
156 scluster = None
157 if cluster_exists:
158 validate_running = True
159 scluster = self.cm.get_cluster(tag)
160 log.info(
161 "Using original template used to launch cluster '%s'" % \
162 scluster.cluster_tag)
163 else:
164 template = self.opts.cluster_template
165 if not template:
166 template = self.cm.get_default_cluster_template()
167 log.info("Using default cluster template: %s" % template)
168 scluster = self.cm.get_cluster_template(template, tag)
169 scluster.update(self.specified_options_dict)
170 if not self.opts.refresh_interval:
171 interval = self.cfg.globals.get("refresh_interval")
172 scluster.refresh_interval = interval
173 if validate:
174 try:
175 scluster._validate(validate_running=validate_running)
176 except exception.ClusterValidationError:
177 if not cluster_exists:
178 log.error(
179 'settings for cluster template "%s" are not valid:' % \
180 template)
181 raise
182 else:
183 log.warn("SKIPPING VALIDATION - USE AT YOUR OWN RISK")
184 if validate_only:
185 return
186 if self.opts.spot_bid is not None and not self.opts.no_create:
187 cmd = ' '.join(sys.argv[1:])
188 cmd = cmd.replace('--no-create', '').replace('-x', '')
189 cmd += ' -x'
190 msg = user_msgs.spotmsg % {'cmd': cmd,
191 'size': scluster.cluster_size,
192 'tag': tag}
193 self.warn_experimental(msg, num_secs=5)
194 self.catch_ctrl_c()
195 scluster.start(create=create, create_only=create_only, validate=False)
196 if self.opts.login_master:
197 scluster.ssh_to_master()
198