Adding ability to relaunch jobs
Adding the ability to relaunch a job from a given job-execution (job configuration is preserved and editable). There are options to either launch on an existing or a new cluster. Implements: blueprint job-relaunch Change-Id: Ibc93beb0ebd0cbb6d6afe0e30ee82c0a43b4f93f
This commit is contained in:
parent
bbba154c49
commit
4f0a2df306
|
@ -15,11 +15,14 @@
|
|||
|
||||
import logging
|
||||
|
||||
from django.core import urlresolvers
|
||||
from django.utils import http
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import tables
|
||||
|
||||
from savannadashboard.api.client import client as savannaclient
|
||||
from savannadashboard.jobs import tables as j_t
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -37,6 +40,35 @@ class DeleteJobExecution(tables.BatchAction):
|
|||
savanna.job_executions.delete(obj_id)
|
||||
|
||||
|
||||
class ReLaunchJobExistingCluster(j_t.ChoosePlugin):
|
||||
name = "relaunch-job-existing"
|
||||
verbose_name = _("Relaunch On Existing Cluster")
|
||||
action_present = _("Launch")
|
||||
action_past = _("Launched")
|
||||
data_type_singular = _("Job")
|
||||
data_type_plural = _("Jobs")
|
||||
url = "horizon:savanna:jobs:launch-job"
|
||||
classes = ('ajax-modal', 'btn-launch')
|
||||
|
||||
def get_link_url(self, datum):
|
||||
base_url = urlresolvers.reverse(self.url)
|
||||
|
||||
params = http.urlencode({'job_id': datum.job_id,
|
||||
'job_execution_id': datum.id})
|
||||
return "?".join([base_url, params])
|
||||
|
||||
|
||||
class ReLaunchJobNewCluster(ReLaunchJobExistingCluster):
|
||||
name = "relaunch-job-new"
|
||||
verbose_name = _("Relaunch On New Cluster")
|
||||
action_present = _("Launch")
|
||||
action_past = _("Launched")
|
||||
data_type_singular = _("Job")
|
||||
data_type_plural = _("Jobs")
|
||||
url = "horizon:savanna:jobs:choose-plugin"
|
||||
classes = ('ajax-modal', 'btn-launch')
|
||||
|
||||
|
||||
class UpdateRow(tables.Row):
|
||||
ajax = True
|
||||
|
||||
|
@ -77,4 +109,6 @@ class JobExecutionsTable(tables.DataTable):
|
|||
status_columns = ["status"]
|
||||
verbose_name = _("Job Executions")
|
||||
table_actions = [DeleteJobExecution]
|
||||
row_actions = [DeleteJobExecution]
|
||||
row_actions = [DeleteJobExecution,
|
||||
ReLaunchJobExistingCluster,
|
||||
ReLaunchJobNewCluster]
|
||||
|
|
|
@ -18,12 +18,18 @@ from django.conf.urls.defaults import patterns
|
|||
from django.conf.urls.defaults import url
|
||||
|
||||
import savannadashboard.job_executions.views as views
|
||||
from savannadashboard.jobs import views as job_views
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', views.JobExecutionsView.as_view(),
|
||||
name='index'),
|
||||
url(r'^$', views.JobExecutionsView.as_view(),
|
||||
name='job-executions'),
|
||||
url(r'^launch-job$',
|
||||
job_views.LaunchJobView.as_view()),
|
||||
url(r'^launch-job-new-cluster$',
|
||||
job_views.LaunchJobNewClusterView.as_view()),
|
||||
url(r'^(?P<job_execution_id>[^/]+)$',
|
||||
views.JobExecutionDetailsView.as_view(),
|
||||
name='details'))
|
||||
|
|
|
@ -138,6 +138,17 @@ class JobConfigAction(workflows.Action):
|
|||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(JobConfigAction, self).__init__(request, *args, **kwargs)
|
||||
job_ex_id = request.REQUEST.get("job_execution_id")
|
||||
if job_ex_id is not None:
|
||||
client = savannaclient(request)
|
||||
job_ex_id = request.REQUEST.get("job_execution_id")
|
||||
job_configs = client.job_executions.get(job_ex_id).job_configs
|
||||
self.fields['job_configs'].initial =\
|
||||
json.dumps(job_configs['configs'])
|
||||
self.fields['job_params'].initial =\
|
||||
json.dumps(job_configs['params'])
|
||||
self.fields['job_args'].initial =\
|
||||
json.dumps(job_configs['args'])
|
||||
|
||||
def populate_property_name_choices(self, request, context):
|
||||
client = savannaclient(request)
|
||||
|
@ -238,9 +249,44 @@ class SelectHadoopPluginAction(t_flows.SelectPluginAction):
|
|||
self.fields["job_id"] = forms.ChoiceField(
|
||||
label=_("Plugin name"),
|
||||
required=True,
|
||||
initial=request.GET["job_id"],
|
||||
initial=request.GET.get("job_id") or request.POST.get("job_id"),
|
||||
widget=forms.HiddenInput(attrs={"class": "hidden_create_field"}))
|
||||
|
||||
self.fields["job_configs"] = forms.ChoiceField(
|
||||
label=_("Job configs"),
|
||||
required=True,
|
||||
widget=forms.HiddenInput(attrs={"class": "hidden_create_field"}))
|
||||
|
||||
self.fields["job_args"] = forms.ChoiceField(
|
||||
label=_("Job args"),
|
||||
required=True,
|
||||
widget=forms.HiddenInput(attrs={"class": "hidden_create_field"}))
|
||||
|
||||
self.fields["job_params"] = forms.ChoiceField(
|
||||
label=_("Job params"),
|
||||
required=True,
|
||||
widget=forms.HiddenInput(attrs={"class": "hidden_create_field"}))
|
||||
|
||||
job_ex_id = request.REQUEST.get("job_execution_id")
|
||||
if job_ex_id is not None:
|
||||
self.fields["job_execution_id"] = forms.ChoiceField(
|
||||
label=_("Job Execution Id"),
|
||||
required=True,
|
||||
initial=request.REQUEST.get("job_execution_id"),
|
||||
widget=forms.HiddenInput(
|
||||
attrs={"class": "hidden_create_field"}))
|
||||
|
||||
client = savannaclient(request)
|
||||
job_ex_id = request.REQUEST.get("job_execution_id")
|
||||
job_configs = client.job_executions.get(job_ex_id).job_configs
|
||||
|
||||
self.fields["job_configs"].initial =\
|
||||
json.dumps(job_configs["configs"])
|
||||
self.fields["job_params"].initial =\
|
||||
json.dumps(job_configs["params"])
|
||||
self.fields["job_args"].initial =\
|
||||
json.dumps(job_configs["args"])
|
||||
|
||||
class Meta:
|
||||
name = _("Select plugin and hadoop version for cluster")
|
||||
help_text_template = ("cluster_templates/_create_general_help.html")
|
||||
|
|
|
@ -12,4 +12,55 @@
|
|||
{{ job_executions_table.render }}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
addHorizonLoadEvent(function () {
|
||||
|
||||
horizon.modals.addModalInitFunction(function (modal) {
|
||||
if ($(modal).find(".nav-tabs").find("li").size() == 1) {
|
||||
// hide tab bar for plugin/version modal wizard
|
||||
$('div#modal_wrapper ul.nav-tabs').hide();
|
||||
}
|
||||
|
||||
$(".hidden_nodegroups_field").val("");
|
||||
$(".hidden_configure_field").val("");
|
||||
|
||||
lower_limit = 0;
|
||||
$(".count-field").change();
|
||||
|
||||
if ($(modal).find(".hidden_create_field").length > 0) {
|
||||
var form = $(".hidden_create_field").closest("form");
|
||||
var successful = false;
|
||||
form.submit(function (e) {
|
||||
var newElement = $("<a id='hiddenbutton' class='btn btn-small ajax-modal' style='display:none'/>");
|
||||
var oldHref = $("#job_executions__action_delete")[0].href;
|
||||
var plugin = $("#id_plugin_name option:selected").val();
|
||||
var version = $("#id_" + plugin + "_version option:selected").val();
|
||||
var job_id = $("#id_job_id").val();
|
||||
var job_execution_id = $("#id_job_execution_id").val();
|
||||
form.find(".close").click();
|
||||
newElement.attr("href", "launch-job-new-cluster?" +
|
||||
"plugin_name=" + encodeURIComponent(plugin) +
|
||||
"&hadoop_version=" + encodeURIComponent(version) +
|
||||
"&job_id=" + encodeURIComponent(job_id) +
|
||||
"&job_execution_id=" + encodeURIComponent(job_execution_id));
|
||||
newElement.appendTo("#main_content");
|
||||
$("#hiddenbutton").click();
|
||||
return false;
|
||||
});
|
||||
$(".plugin_version_choice").closest(".control-group").hide();
|
||||
}
|
||||
|
||||
//display version for selected plugin
|
||||
$(document).on('change', '.plugin_name_choice', switch_versions);
|
||||
function switch_versions() {
|
||||
$(".plugin_version_choice").closest(".control-group").hide();
|
||||
var plugin = $(this);
|
||||
$("." + plugin.val() + "_version_choice").closest(".control-group").show();
|
||||
}
|
||||
$(".plugin_name_choice").change();
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
<tr id_attr="$id">
|
||||
<div class="input control-group">
|
||||
<td><input style="display: inline" field="key" list="properties" placeholder="Select property name"
|
||||
onkeyup="trySetValue(this)" onchange="trySetValue(this)" onclick="trySetValue(this)"/></td>
|
||||
onkeyup="trySetValue(this)" onchange="trySetValue(this)" onclick="trySetValue(this)"
|
||||
value="$name"/></td>
|
||||
<td><input style="display: inline; margin-left:10px; margin-right:10px" field="value" class="input-medium"
|
||||
onkeyup="set_props()" onchange="set_props()" onclick="set_props()"/></td>
|
||||
onkeyup="set_props()" onchange="set_props()" onclick="set_props()"
|
||||
value="$value"/></td>
|
||||
<td><input style="display: inline; margin-top:-10px" type="button" class="btn btn-danger"
|
||||
onclick="delete_prop(this)" value="Remove"/></td>
|
||||
</div>
|
||||
|
@ -14,9 +16,11 @@
|
|||
<tr id_attr="$id">
|
||||
<div class="input control-group">
|
||||
<td><input style="display: inline" field="key"
|
||||
onkeyup="set_props()" onchange="set_props()" onclick="set_props()"/></td>
|
||||
onkeyup="set_props()" onchange="set_props()" onclick="set_props()"
|
||||
value="$name"/></td>
|
||||
<td><input style="display: inline; margin-left:10px; margin-right:10px" field="value" class="input-medium"
|
||||
onkeyup="set_props()" onchange="set_props()" onclick="set_props()"/></td>
|
||||
onkeyup="set_props()" onchange="set_props()" onclick="set_props()"
|
||||
value="$value"/></td>
|
||||
<td><input style="display: inline; margin-top:-10px" type="button" class="btn btn-danger"
|
||||
onclick="delete_prop(this)" value="Remove"/></td>
|
||||
</div>
|
||||
|
@ -57,14 +61,19 @@
|
|||
});
|
||||
}
|
||||
|
||||
function add_prop(target) {
|
||||
function add_prop(target, name, value) {
|
||||
var name = (typeof name === 'undefined') ? '' : name;
|
||||
var value = (typeof value === 'undefined') ? '' : value;
|
||||
$("#" + target + " table").show();
|
||||
var id = get_next_id(target);
|
||||
var tmpl_from = target == "params" ? "args" : target;
|
||||
var template = $("#" + tmpl_from + "_template").text()
|
||||
.replace(/\$id/g, id);
|
||||
template = template.replace(/\$name/g, name);
|
||||
template = template.replace(/\$value/g, value);
|
||||
$("#" + target + " tbody").append(template);
|
||||
set_props();
|
||||
return id
|
||||
}
|
||||
function delete_prop(el) {
|
||||
var tr = $(el).parents("tr")[0];
|
||||
|
@ -97,6 +106,15 @@
|
|||
return res;
|
||||
}
|
||||
|
||||
function load_prior_configs() {
|
||||
for(targ in targets) {
|
||||
var configs = JSON.parse($("#id_job_" + targets[targ]).val());
|
||||
for(conf in configs) {
|
||||
add_prop(targets[targ], conf, configs[conf]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
properties = {};
|
||||
$("label[for=id_property_name]").hide();
|
||||
$("#id_property_name").hide().find("option")
|
||||
|
@ -127,6 +145,7 @@
|
|||
.replace(/\$target/g, target));
|
||||
});
|
||||
$("#job_cfg table").hide();
|
||||
load_prior_configs();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue