src/templates/builders/delete.html \
src/templates/builders/edit.html \
src/templates/builders/index.html \
- src/templates/builders/show.html
+ src/templates/builders/show.html \
+ src/templates/builders/start.html \
+ src/templates/builders/stop.html
templates_buildersdir = $(templatesdir)/builders
# Start all builders that have been allocated at least one job
for builder in builders_to_be_launched:
tasks.create_task(
- builder.start(wait=wait),
+ builder.start(auto=True, wait=wait),
)
# Shutdown the rest
for builder in builders_to_be_shut_down:
tasks.create_task(
- builder.stop(wait=wait),
+ builder.stop(auto=True, wait=wait),
)
# Stats
if self.instance:
return self.instance.state.get("Name")
- async def start(self, wait=True):
+ async def start(self, auto=False, wait=True):
"""
Starts the instance on AWS
"""
if await self.is_running():
return
- # Don't start when in maintenance mode
- if self.maintenance:
+ # Don't start automatically when in maintenance mode
+ if auto and self.maintenance:
log.warning("Won't start %s in maintenance mode" % self)
return
except botocore.exceptions.ClientError as e:
log.warning("Could not change instance type of %s: %s" % (self, e))
- async def stop(self, wait=True):
+ async def stop(self, auto=False, wait=True):
"""
Stops this instance on AWS
"""
if await self.is_shutting_down() or await self.is_shut_down():
return
- # Don't stop when in maintenance mode
- if self.maintenance:
+ # Don't stop automatically when in maintenance mode
+ if auto and self.maintenance:
log.warning("Won't stop %s in maintenance mode" % self)
return
<a class="button is-danger" href="/builders/{{ builder.hostname }}/delete">
{{ _("Delete") }}
</a>
+
+ {# Maintenance Mode Actions #}
+ {% if builder.maintenance %}
+ {% if is_running %}
+ <a class="button is-danger" href="/builders/{{ builder.hostname }}/stop">
+ {{ _("Stop") }}
+ </a>
+ {% elif is_shut_down %}
+ <a class="button is-success" href="/builders/{{ builder.hostname }}/start">
+ {{ _("Start") }}
+ </a>
+ {% end %}
+ {% end %}
</div>
</section>
{% end %}
--- /dev/null
+{% extends "../modal.html" %}
+
+{% block title %}{{ _("Start Builder") }} - {{ builder }}{% end block %}
+
+{% block breadcrumbs %}
+ <nav class="breadcrumb" aria-label="breadcrumbs">
+ <ul>
+ <li>
+ <a href="/builders">{{ _("Builders") }}</a>
+ </li>
+ <li>
+ <a href="/builders/{{ builder.hostname }}">{{ builder }}</a>
+ </li>
+ <li class="is-active">
+ <a href="#" aria-current="page">{{ _("Start") }}</a>
+ </li>
+ </ul>
+ </nav>
+{% end block %}
+
+{% block modal_title %}
+ <h4 class="title is-4">{{ _("Start Builder") }}</h4>
+ <h6 class="subtitle is-6">{{ builder }}</h6>
+{% end block %}
+
+{% block modal %}
+ <form method="POST" action="">
+ {% raw xsrf_form_html() %}
+
+ <div class="content">
+ <p>
+ {{ _("Do you want to manually start %s?") % builder }}
+ </p>
+ </div>
+
+ {# Submit! #}
+ <div class="field">
+ <button type="submit" class="button is-success is-fullwidth">
+ {{ _("Start") }}
+ </button>
+ </div>
+ </form>
+{% end block %}
--- /dev/null
+{% extends "../modal.html" %}
+
+{% block title %}{{ _("Stop Builder") }} - {{ builder }}{% end block %}
+
+{% block breadcrumbs %}
+ <nav class="breadcrumb" aria-label="breadcrumbs">
+ <ul>
+ <li>
+ <a href="/builders">{{ _("Builders") }}</a>
+ </li>
+ <li>
+ <a href="/builders/{{ builder.hostname }}">{{ builder }}</a>
+ </li>
+ <li class="is-active">
+ <a href="#" aria-current="page">{{ _("Stop") }}</a>
+ </li>
+ </ul>
+ </nav>
+{% end block %}
+
+{% block modal_title %}
+ <h4 class="title is-4">{{ _("Stop Builder") }}</h4>
+ <h6 class="subtitle is-6">{{ builder }}</h6>
+{% end block %}
+
+{% block modal %}
+ <form method="POST" action="">
+ {% raw xsrf_form_html() %}
+
+ <div class="content">
+ <p>
+ {{ _("Do you want to manually stop %s?") % builder }}
+ </p>
+ </div>
+
+ {# Submit! #}
+ <div class="field">
+ <button type="submit" class="button is-danger is-fullwidth">
+ {{ _("Stop") }}
+ </button>
+ </div>
+ </form>
+{% end block %}
(r"/builders/([A-Za-z0-9\-\.]+)", builders.ShowHandler),
(r"/builders/([A-Za-z0-9\-\.]+)/delete", builders.DeleteHandler),
(r"/builders/([A-Za-z0-9\-\.]+)/edit", builders.BuilderEditHandler),
+ (r"/builders/([A-Za-z0-9\-\.]+)/start", builders.StartHandler),
(r"/builders/([A-Za-z0-9\-\.]+)/stats", builders.StatsHandler),
+ (r"/builders/([A-Za-z0-9\-\.]+)/stop", builders.StopHandler),
(r"/api/v1/builders/control", builders.APIv1ControlHandler),
# Distributions
class ShowHandler(base.BaseHandler):
- def get(self, hostname):
+ async def get(self, hostname):
builder = self.backend.builders.get_by_name(hostname)
if not builder:
raise tornado.web.HTTPError(404, "Could not find builder %s" % hostname)
- self.render("builders/show.html", builder=builder)
+ # Fetch status
+ args = {
+ "is_running" : await builder.is_running(),
+ "is_shut_down" : await builder.is_shut_down(),
+ }
+
+ self.render("builders/show.html", builder=builder, **args)
class CreateHandler(base.BaseHandler):
self.redirect("/builders")
+class StartHandler(base.BaseHandler):
+ @tornado.web.authenticated
+ def get(self, name):
+ builder = self.backend.builders.get_by_name(name)
+ if not builder:
+ raise tornado.web.HTTPError(404, "Builder not found: %s" % name)
+
+ # Check permissions
+ if not builder.has_perm(self.current_user):
+ raise tornado.web.HTTPError(403)
+
+ # Builders must be in maintenance mode
+ if not builder.maintenance:
+ raise tornado.web.HTTPError(400, "%s is not in maintenance mode" % builder)
+
+ self.render("builders/start.html", builder=builder)
+
+ @tornado.web.authenticated
+ async def post(self, name):
+ builder = self.backend.builders.get_by_name(name)
+ if not builder:
+ raise tornado.web.HTTPError(404, "Builder not found: %s" % name)
+
+ # Check permissions
+ if not builder.has_perm(self.current_user):
+ raise tornado.web.HTTPError(403)
+
+ # Builders must be in maintenance mode
+ if not builder.maintenance:
+ raise tornado.web.HTTPError(400, "%s is not in maintenance mode" % builder)
+
+ # Start the builder
+ try:
+ await builder.start(wait=False)
+
+ # XXX what do we do when this fails?
+ except:
+ raise
+
+ self.redirect("/builders/%s" % builder.hostname)
+
+
+class StopHandler(base.BaseHandler):
+ @tornado.web.authenticated
+ def get(self, name):
+ builder = self.backend.builders.get_by_name(name)
+ if not builder:
+ raise tornado.web.HTTPError(404, "Builder not found: %s" % name)
+
+ # Check permissions
+ if not builder.has_perm(self.current_user):
+ raise tornado.web.HTTPError(403)
+
+ # Builders must be in maintenance mode
+ if not builder.maintenance:
+ raise tornado.web.HTTPError(400, "%s is not in maintenance mode" % builder)
+
+ self.render("builders/stop.html", builder=builder)
+
+ @tornado.web.authenticated
+ async def post(self, name):
+ builder = self.backend.builders.get_by_name(name)
+ if not builder:
+ raise tornado.web.HTTPError(404, "Builder not found: %s" % name)
+
+ # Check permissions
+ if not builder.has_perm(self.current_user):
+ raise tornado.web.HTTPError(403)
+
+ # Builders must be in maintenance mode
+ if not builder.maintenance:
+ raise tornado.web.HTTPError(400, "%s is not in maintenance mode" % builder)
+
+ # Stop the builder
+ try:
+ await builder.stop(wait=False)
+
+ # XXX what do we do when this fails?
+ except:
+ raise
+
+ self.redirect("/builders/%s" % builder.hostname)
+
+
class StatsModule(ui_modules.UIModule):
def render(self, builder):
return self.render_string("builders/modules/stats.html", builder=builder)