Adding Job Binaries panel for Sahara
The Job Binaries panel allows for creating/uploading files that will serve as executables or libraries for Elastic Data Processing jobs. This code was originally from: https://github.com/openstack/sahara-dashboard Change-Id: I4e7b265a7d3292d7cec395bf2ff11fd546f06360 Partial-Implements: blueprint merge-sahara-dashboard Co-Authored-By: Nikita Konovalov <nkonovalov@mirantis.com> Co-Authored-By: Dmitry Mescheryakov <dmescheryakov@mirantis.com>
This commit is contained in:
parent
991882ca4a
commit
f25628d91c
@ -65,7 +65,8 @@ class DataProcessingPanels(horizon.PanelGroup):
|
||||
'data_processing.nodegroup_templates',
|
||||
'data_processing.cluster_templates',
|
||||
'data_processing.clusters',
|
||||
'data_processing.data_sources', )
|
||||
'data_processing.data_sources',
|
||||
'data_processing.job_binaries', )
|
||||
|
||||
|
||||
class Project(horizon.Dashboard):
|
||||
|
@ -0,0 +1,197 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
from django.forms import util
|
||||
from django.forms import widgets
|
||||
from django import template
|
||||
from django.template import defaultfilters
|
||||
from django.utils.encoding import force_unicode
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
|
||||
from openstack_dashboard.api import sahara as saharaclient
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LabeledInput(widgets.Input):
|
||||
def render(self, name, values, attrs=None):
|
||||
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
|
||||
output = "<span id='%s'>%s</span>%s" %\
|
||||
("id_%s_label" % name,
|
||||
"internal-db://",
|
||||
('<input%s />' % util.flatatt(final_attrs)))
|
||||
return mark_safe(output)
|
||||
|
||||
|
||||
class JobBinaryCreateForm(forms.SelfHandlingForm):
|
||||
NEW_SCRIPT = "%%%NEWSCRIPT%%%"
|
||||
UPLOAD_BIN = "%%%UPLOADFILE%%%"
|
||||
|
||||
job_binary_name = forms.CharField(label=_("Name"))
|
||||
|
||||
job_binary_type = forms.ChoiceField(label=_("Storage type"))
|
||||
|
||||
job_binary_url = forms.CharField(label=_("URL"),
|
||||
required=False,
|
||||
widget=LabeledInput())
|
||||
job_binary_internal = forms.ChoiceField(label=_("Internal binary"),
|
||||
required=False)
|
||||
|
||||
job_binary_file = forms.FileField(label=_("Upload File"),
|
||||
required=False)
|
||||
|
||||
job_binary_script_name = forms.CharField(label=_("Script name"),
|
||||
required=False)
|
||||
|
||||
job_binary_script = forms.CharField(label=_("Script text"),
|
||||
required=False,
|
||||
widget=forms.Textarea())
|
||||
|
||||
job_binary_username = forms.CharField(label=_("Username"),
|
||||
required=False)
|
||||
|
||||
job_binary_password = forms.CharField(label=_("Password"),
|
||||
required=False,
|
||||
widget=forms.PasswordInput(
|
||||
attrs={'autocomplete': 'off'}))
|
||||
|
||||
job_binary_description = forms.CharField(label=_("Description"),
|
||||
required=False,
|
||||
widget=forms.Textarea())
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(JobBinaryCreateForm, self).__init__(request, *args, **kwargs)
|
||||
|
||||
self.help_text_template = ("project/data_processing.job_binaries/"
|
||||
"_create_job_binary_help.html")
|
||||
|
||||
self.fields["job_binary_type"].choices =\
|
||||
[("internal-db", "Internal database"),
|
||||
("swift", "Swift")]
|
||||
|
||||
self.fields["job_binary_internal"].choices =\
|
||||
self.populate_job_binary_internal_choices(request)
|
||||
|
||||
def populate_job_binary_internal_choices(self, request):
|
||||
try:
|
||||
job_binaries = saharaclient.job_binary_internal_list(request)
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_("Failed to get list of internal binaries."))
|
||||
job_binaries = []
|
||||
|
||||
choices = [(job_binary.id, job_binary.name)
|
||||
for job_binary in job_binaries]
|
||||
choices.insert(0, (self.NEW_SCRIPT, '*Create a script'))
|
||||
choices.insert(0, (self.UPLOAD_BIN, '*Upload a new file'))
|
||||
|
||||
return choices
|
||||
|
||||
def handle(self, request, context):
|
||||
try:
|
||||
extra = {}
|
||||
bin_url = "%s://%s" % (context["job_binary_type"],
|
||||
context["job_binary_url"])
|
||||
if(context["job_binary_type"] == "internal-db"):
|
||||
bin_url = self.handle_internal(request, context)
|
||||
elif(context["job_binary_type"] == "swift"):
|
||||
extra = self.handle_swift(request, context)
|
||||
|
||||
saharaclient.job_binary_create(
|
||||
request,
|
||||
context["job_binary_name"],
|
||||
bin_url,
|
||||
context["job_binary_description"],
|
||||
extra)
|
||||
messages.success(request, "Successfully created job binary")
|
||||
return True
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_("Unable to create job binary"))
|
||||
return False
|
||||
|
||||
def get_help_text(self, extra_context=None):
|
||||
text = ""
|
||||
extra_context = extra_context or {}
|
||||
if self.help_text_template:
|
||||
tmpl = template.loader.get_template(self.help_text_template)
|
||||
context = template.RequestContext(self.request, extra_context)
|
||||
text += tmpl.render(context)
|
||||
else:
|
||||
text += defaultfilters.linebreaks(force_unicode(self.help_text))
|
||||
return defaultfilters.safe(text)
|
||||
|
||||
class Meta:
|
||||
name = _("Create Job Binary")
|
||||
help_text_template = ("project/data_processing.job_binaries/"
|
||||
"_create_job_binary_help.html")
|
||||
|
||||
def handle_internal(self, request, context):
|
||||
result = ""
|
||||
|
||||
bin_id = context["job_binary_internal"]
|
||||
if(bin_id == self.UPLOAD_BIN):
|
||||
try:
|
||||
result = saharaclient.job_binary_internal_create(
|
||||
request,
|
||||
self.get_unique_binary_name(
|
||||
request, request.FILES["job_binary_file"].name),
|
||||
request.FILES["job_binary_file"].read())
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_("Unable to upload job binary"))
|
||||
return None
|
||||
elif(bin_id == self.NEW_SCRIPT):
|
||||
try:
|
||||
result = saharaclient.job_binary_internal_create(
|
||||
request,
|
||||
self.get_unique_binary_name(
|
||||
request, context["job_binary_script_name"]),
|
||||
context["job_binary_script"])
|
||||
except Exception:
|
||||
exceptions.handle(request,
|
||||
_("Unable to create job binary"))
|
||||
return None
|
||||
|
||||
bin_id = result.id
|
||||
return "internal-db://%s" % bin_id
|
||||
|
||||
def handle_swift(self, request, context):
|
||||
username = context["job_binary_username"]
|
||||
password = context["job_binary_password"]
|
||||
|
||||
extra = {
|
||||
"user": username,
|
||||
"password": password
|
||||
}
|
||||
return extra
|
||||
|
||||
def get_unique_binary_name(self, request, base_name):
|
||||
try:
|
||||
internals = saharaclient.job_binary_internal_list(request)
|
||||
except Exception:
|
||||
internals = []
|
||||
exceptions.handle(request,
|
||||
_("Failed to fetch internal binary list"))
|
||||
names = [internal.name for internal in internals]
|
||||
if base_name in names:
|
||||
return "%s_%s" % (base_name, uuid.uuid1())
|
||||
return base_name
|
@ -0,0 +1,27 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import horizon
|
||||
|
||||
from openstack_dashboard.dashboards.project import dashboard
|
||||
|
||||
|
||||
class JobBinariesPanel(horizon.Panel):
|
||||
name = _("Job Binaries")
|
||||
slug = 'data_processing.job_binaries'
|
||||
permissions = ('openstack.services.data_processing',)
|
||||
|
||||
|
||||
dashboard.Project.register(JobBinariesPanel)
|
@ -0,0 +1,79 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import tables
|
||||
|
||||
from openstack_dashboard.api import sahara as saharaclient
|
||||
|
||||
from saharaclient.api import base as api_base
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CreateJobBinary(tables.LinkAction):
|
||||
name = "create job binary"
|
||||
verbose_name = _("Create Job Binary")
|
||||
url = "horizon:project:data_processing.job_binaries:create-job-binary"
|
||||
classes = ("btn-launch", "ajax-modal")
|
||||
|
||||
|
||||
class DeleteJobBinary(tables.BatchAction):
|
||||
name = "delete"
|
||||
action_present = _("Delete")
|
||||
action_past = _("Deleted")
|
||||
data_type_singular = _("Job binary")
|
||||
data_type_plural = _("Job binaries")
|
||||
classes = ('btn-danger', 'btn-terminate')
|
||||
|
||||
def action(self, request, obj_id):
|
||||
jb = saharaclient.job_binary_get(request, obj_id)
|
||||
(jb_type, jb_internal_id) = jb.url.split("://")
|
||||
if jb_type == "internal-db":
|
||||
try:
|
||||
saharaclient.job_binary_internal_delete(request,
|
||||
jb_internal_id)
|
||||
except api_base.APIException:
|
||||
# nothing to do for job-binary-internal if
|
||||
# it does not exist.
|
||||
pass
|
||||
|
||||
saharaclient.job_binary_delete(request, obj_id)
|
||||
|
||||
|
||||
class DownloadJobBinary(tables.LinkAction):
|
||||
name = "download job binary"
|
||||
verbose_name = _("Download Job Binary")
|
||||
url = "horizon:project:data_processing.job_binaries:download"
|
||||
classes = ("btn-edit")
|
||||
|
||||
|
||||
class JobBinariesTable(tables.DataTable):
|
||||
name = tables.Column("name",
|
||||
verbose_name=_("Name"),
|
||||
link=("horizon:project:data_processing.job_binaries:details"))
|
||||
type = tables.Column("url",
|
||||
verbose_name=_("Url"))
|
||||
description = tables.Column("description",
|
||||
verbose_name=_("Description"))
|
||||
|
||||
class Meta:
|
||||
name = "job_binaries"
|
||||
verbose_name = _("Job Binaries")
|
||||
table_actions = (CreateJobBinary,
|
||||
DeleteJobBinary)
|
||||
row_actions = (DeleteJobBinary, DownloadJobBinary)
|
@ -0,0 +1,45 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
|
||||
from openstack_dashboard.api import sahara as saharaclient
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class JobBinaryDetailsTab(tabs.Tab):
|
||||
name = _("General Info")
|
||||
slug = "job_binaries_details_tab"
|
||||
template_name = ("project/data_processing.job_binaries/_details.html")
|
||||
|
||||
def get_context_data(self, request):
|
||||
job_binary_id = self.tab_group.kwargs['job_binary_id']
|
||||
try:
|
||||
job_binary = saharaclient.job_binary_get(request, job_binary_id)
|
||||
except Exception:
|
||||
job_binary = {}
|
||||
exceptions.handle(request,
|
||||
_("Unable to fetch job binary."))
|
||||
return {"job_binary": job_binary}
|
||||
|
||||
|
||||
class JobBinaryDetailsTabs(tabs.TabGroup):
|
||||
slug = "job_binary_details"
|
||||
tabs = (JobBinaryDetailsTab,)
|
||||
sticky = True
|
@ -0,0 +1,27 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
|
||||
{% load url from future %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_id %}create-job-binary{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:data_processing.job_binaries:create-job-binary' %}{% endblock %}
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Create Job Binary" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="form-help-block">
|
||||
{{ form.get_help_text }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" id="upload_file_btn" type="submit" value="{% trans "Create" %}"/>
|
||||
<a href="{% url 'horizon:project:data_processing.job_binaries:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -0,0 +1,32 @@
|
||||
{% load i18n horizon %}
|
||||
<div class="well">
|
||||
<p>
|
||||
{% blocktrans %}<b>Important</b>: The name that you give your job binary will be the name used in your job execution.
|
||||
If your binary requires a particular name or extension (ie: ".jar"), be sure to include it here.{% endblocktrans %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans %}Select the storage type for your job binary.{% endblocktrans %}
|
||||
<ul>
|
||||
<li>{% blocktrans %}Data Processing internal database{% endblocktrans %}</li>
|
||||
<li>{% blocktrans %}Swift{% endblocktrans %}</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans %}For Data Processing internal job binaries, you may choose from the following:{% endblocktrans %}
|
||||
<ul>
|
||||
<li>{% blocktrans %}Choose an existing file{% endblocktrans %}</li>
|
||||
<li>{% blocktrans %}Upload a new file{% endblocktrans %}</li>
|
||||
<li>{% blocktrans %}Create a script to be uploaded dynamically{% endblocktrans %}</ul>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans %}For Object Store job binaries, you must:{% endblocktrans %}
|
||||
<ul>
|
||||
<li>{% blocktrans %}Enter the URL for the file{% endblocktrans %}</li>
|
||||
<li>{% blocktrans %}Enter the username and password required to access that file{% endblocktrans %}</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans %}You may also enter an optional description for your job binary.{% endblocktrans %}
|
||||
</p>
|
||||
</div>
|
@ -0,0 +1,19 @@
|
||||
{% load i18n %}
|
||||
<h3>{% trans "Job Binary Overview" %}</h3>
|
||||
<div class="status row-fluid detail">
|
||||
<dl>
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd>{{ job_binary.name }}</dd>
|
||||
<dt>{% trans "ID" %}</dt>
|
||||
<dd>{{ job_binary.id }}</dd>
|
||||
<dt>{% trans "URL" %}</dt>
|
||||
<dd>{{ job_binary.url }}</dd>
|
||||
<dt>{% trans "Description" %}</dt>
|
||||
<dd>{{ job_binary.description|default:_("None") }}</dd>
|
||||
<dt>{% trans "Project id" %}</dt>
|
||||
<dd>{{ job_binary.tenant_id }}</dd>
|
||||
<dt>{% trans "Create time" %}</dt>
|
||||
<dd>{{ job_binary.created_at }}</dd>
|
||||
</dl>
|
||||
<a href="{% url 'horizon:project:data_processing.job_binaries:download' job_binary.id %}">{% trans "Download job binary" %}</a>
|
||||
</div>
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Create Job Binary" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Create Job Binary") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/data_processing.job_binaries/_create.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,15 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Job Binary Details" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Job Binary Details") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -0,0 +1,25 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Data Processing" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Job Binaries") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<style type="text/css">
|
||||
#id_job_binary_url {
|
||||
width: 200px !important; }
|
||||
.form-help-block {
|
||||
float: left;
|
||||
text-align: left;
|
||||
width: 300px; }
|
||||
</style>
|
||||
|
||||
<div class="job_binaries">
|
||||
{{ job_binaries_table.render }}
|
||||
</div>
|
||||
|
||||
{% include "project/data_processing.job_binaries/job_binaries_form_script.html" %}
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,74 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
addHorizonLoadEvent(function () {
|
||||
horizon.modals.addModalInitFunction(function (modal) {
|
||||
hide_extra_fields();
|
||||
function hide_extra_fields() {
|
||||
$("[name=job_binary_username]").closest(".control-group").hide();
|
||||
$("[name=job_binary_password]").closest(".control-group").hide();
|
||||
$("[name=job_binary_file]").closest(".control-group").hide();
|
||||
$("[name=job_binary_url]").closest(".control-group").hide();
|
||||
$("[name=job_binary_internal]").closest(".control-group").hide();
|
||||
}
|
||||
$("#id_job_binary_type").change(function() {
|
||||
var label = $("#id_job_binary_url_label");
|
||||
var bin_file = $("[name=job_binary_file]").closest(".control-group");
|
||||
var bin_choice = $("[name=job_binary_internal]").closest(".control-group");
|
||||
var bin_url = $("[name=job_binary_url]").closest(".control-group");
|
||||
var username = $("[name=job_binary_username]").closest(".control-group");
|
||||
var password = $("[name=job_binary_password]").closest(".control-group");
|
||||
var script_name = $("[name=job_binary_script_name]").closest(".control-group");
|
||||
var script_text = $("[name=job_binary_script]").closest(".control-group");
|
||||
switch($(this).val()) {
|
||||
case "internal-db":
|
||||
label.html("internal-db://");
|
||||
username.hide();
|
||||
password.hide();
|
||||
bin_file.show();
|
||||
bin_choice.show();
|
||||
bin_url.hide();
|
||||
script_name.hide();
|
||||
script_text.hide();
|
||||
break;
|
||||
case "swift":
|
||||
username.show();
|
||||
password.show();
|
||||
bin_file.hide();
|
||||
bin_choice.hide();
|
||||
bin_url.show();
|
||||
label.html("swift://");
|
||||
script_name.hide();
|
||||
script_text.hide();
|
||||
break;
|
||||
}
|
||||
});
|
||||
$("#id_job_binary_type").change();
|
||||
|
||||
$("[name=job_binary_internal]").change(function() {
|
||||
var bin_file = $("[name=job_binary_file]").closest(".control-group");
|
||||
var bin_choice = $("[name=job_binary_internal]").closest(".control-group");
|
||||
var bin_url = $("[name=job_binary_url]").closest(".control-group");
|
||||
var script_name = $("[name=job_binary_script_name]").closest(".control-group");
|
||||
var script_text = $("[name=job_binary_script]").closest(".control-group");
|
||||
switch($(this).val()) {
|
||||
case "%%%NEWSCRIPT%%%":
|
||||
bin_file.hide();
|
||||
script_name.show();
|
||||
script_text.show();
|
||||
break;
|
||||
case "%%%UPLOADFILE%%%":
|
||||
bin_file.show();
|
||||
script_name.hide();
|
||||
script_text.hide();
|
||||
break;
|
||||
default:
|
||||
bin_file.hide();
|
||||
script_name.hide();
|
||||
script_text.hide();
|
||||
break;
|
||||
}
|
||||
});
|
||||
$("#job_binary_internal").change();
|
||||
});
|
||||
});
|
||||
</script>
|
@ -0,0 +1,80 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django import http
|
||||
|
||||
from mox import IsA # noqa
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
INDEX_URL = reverse('horizon:project:data_processing.job_binaries:index')
|
||||
DETAILS_URL = reverse(
|
||||
'horizon:project:data_processing.job_binaries:details', args=['id'])
|
||||
|
||||
|
||||
class DataProcessingJobBinaryTests(test.TestCase):
|
||||
@test.create_stubs({api.sahara: ('job_binary_list',)})
|
||||
def test_index(self):
|
||||
api.sahara.job_binary_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.job_binaries.list())
|
||||
self.mox.ReplayAll()
|
||||
res = self.client.get(INDEX_URL)
|
||||
self.assertTemplateUsed(res,
|
||||
'project/data_processing.job_binaries/job_binaries.html')
|
||||
self.assertContains(res, 'Job Binaries')
|
||||
self.assertContains(res, 'Name')
|
||||
self.assertContains(res, 'example.pig')
|
||||
|
||||
@test.create_stubs({api.sahara: ('job_binary_get',)})
|
||||
def test_details(self):
|
||||
api.sahara.job_binary_get(IsA(http.HttpRequest), IsA(unicode)) \
|
||||
.AndReturn(self.job_binaries.list()[0])
|
||||
self.mox.ReplayAll()
|
||||
res = self.client.get(DETAILS_URL)
|
||||
self.assertTemplateUsed(res,
|
||||
'project/data_processing.job_binaries/details.html')
|
||||
self.assertContains(res, 'Job Binary Details')
|
||||
|
||||
@test.create_stubs({api.sahara: ('job_binary_list',
|
||||
'job_binary_get',
|
||||
'job_binary_internal_delete',
|
||||
'job_binary_delete',)})
|
||||
def test_delete(self):
|
||||
jb_list = (api.sahara.job_binary_list(IsA(http.HttpRequest))
|
||||
.AndReturn(self.job_binaries.list()))
|
||||
api.sahara.job_binary_get(IsA(http.HttpRequest), IsA(unicode)) \
|
||||
.AndReturn(self.job_binaries.list()[0])
|
||||
api.sahara.job_binary_delete(IsA(http.HttpRequest), jb_list[0].id)
|
||||
int_id = jb_list[0].url.split("//")[1]
|
||||
api.sahara.job_binary_internal_delete(IsA(http.HttpRequest), int_id)
|
||||
self.mox.ReplayAll()
|
||||
form_data = {"action": "job_binaries__delete__%s" % jb_list[0].id}
|
||||
res = self.client.post(INDEX_URL, form_data)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.sahara: ('job_binary_get',
|
||||
'job_binary_get_file')})
|
||||
def test_download(self):
|
||||
jb = api.sahara.job_binary_get(IsA(http.HttpRequest), IsA(unicode)) \
|
||||
.AndReturn(self.job_binaries.list()[0])
|
||||
api.sahara.job_binary_get_file(IsA(http.HttpRequest), jb.id) \
|
||||
.AndReturn("TEST FILE CONTENT")
|
||||
self.mox.ReplayAll()
|
||||
|
||||
context = {'job_binary_id': jb.id}
|
||||
url = reverse('horizon:project:data_processing.job_binaries:download',
|
||||
kwargs={'job_binary_id': jb.id})
|
||||
res = self.client.get(url, context)
|
||||
self.assertTrue(res.has_header('content-disposition'))
|
@ -0,0 +1,35 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
from django.conf.urls import patterns # noqa
|
||||
from django.conf.urls import url # noqa
|
||||
|
||||
import openstack_dashboard.dashboards.project.data_processing. \
|
||||
job_binaries.views as views
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', views.JobBinariesView.as_view(),
|
||||
name='index'),
|
||||
url(r'^$', views.JobBinariesView.as_view(),
|
||||
name='job-binaries'),
|
||||
url(r'^create-job-binary$',
|
||||
views.CreateJobBinaryView.as_view(),
|
||||
name='create-job-binary'),
|
||||
url(r'^(?P<job_binary_id>[^/]+)$',
|
||||
views.JobBinaryDetailsView.as_view(),
|
||||
name='details'),
|
||||
url(r'^(?P<job_binary_id>[^/]+)/download/$',
|
||||
views.DownloadJobBinaryView.as_view(),
|
||||
name='download'))
|
@ -0,0 +1,93 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django import http
|
||||
from django.template import defaultfilters
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views import generic
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tables
|
||||
from horizon import tabs
|
||||
|
||||
from openstack_dashboard.api import sahara as saharaclient
|
||||
|
||||
import openstack_dashboard.dashboards.project.data_processing. \
|
||||
job_binaries.forms as job_binary_forms
|
||||
from openstack_dashboard.dashboards.project.data_processing.job_binaries \
|
||||
import tables as jb_tables
|
||||
import openstack_dashboard.dashboards.project.data_processing.job_binaries. \
|
||||
tabs as _tabs
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class JobBinariesView(tables.DataTableView):
|
||||
table_class = jb_tables.JobBinariesTable
|
||||
template_name = 'project/data_processing.job_binaries/job_binaries.html'
|
||||
|
||||
def get_data(self):
|
||||
try:
|
||||
job_binaries = saharaclient.job_binary_list(self.request)
|
||||
except Exception:
|
||||
job_binaries = []
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch job binary list."))
|
||||
return job_binaries
|
||||
|
||||
|
||||
class CreateJobBinaryView(forms.ModalFormView):
|
||||
form_class = job_binary_forms.JobBinaryCreateForm
|
||||
success_url = reverse_lazy(
|
||||
'horizon:project:data_processing.job_binaries:index')
|
||||
classes = ("ajax-modal")
|
||||
template_name = "project/data_processing.job_binaries/create.html"
|
||||
|
||||
|
||||
class JobBinaryDetailsView(tabs.TabView):
|
||||
tab_group_class = _tabs.JobBinaryDetailsTabs
|
||||
template_name = 'project/data_processing.job_binaries/details.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(JobBinaryDetailsView, self)\
|
||||
.get_context_data(**kwargs)
|
||||
return context
|
||||
|
||||
def get_data(self):
|
||||
pass
|
||||
|
||||
|
||||
class DownloadJobBinaryView(generic.View):
|
||||
def get(self, request, job_binary_id=None):
|
||||
try:
|
||||
jb = saharaclient.job_binary_get(request, job_binary_id)
|
||||
data = saharaclient.job_binary_get_file(request, job_binary_id)
|
||||
except Exception:
|
||||
redirect = reverse(
|
||||
'horizon:project:data_processing.job_binaries:index')
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to fetch job binary: %(exc)s'),
|
||||
redirect=redirect)
|
||||
|
||||
response = http.HttpResponse(mimetype='application/binary')
|
||||
response['Content-Disposition'] = \
|
||||
'attachment; filename=%s' % defaultfilters.slugify(jb.name)
|
||||
response.write(data)
|
||||
response['Content-Length'] = str(len(data))
|
||||
return response
|
@ -15,6 +15,7 @@ from openstack_dashboard.test.test_data import utils
|
||||
from saharaclient.api import cluster_templates
|
||||
from saharaclient.api import clusters
|
||||
from saharaclient.api import data_sources
|
||||
from saharaclient.api import job_binaries
|
||||
from saharaclient.api import node_group_templates
|
||||
from saharaclient.api import plugins
|
||||
|
||||
@ -25,6 +26,7 @@ def data(TEST):
|
||||
TEST.cluster_templates = utils.TestDataContainer()
|
||||
TEST.clusters = utils.TestDataContainer()
|
||||
TEST.data_sources = utils.TestDataContainer()
|
||||
TEST.job_binaries = utils.TestDataContainer()
|
||||
|
||||
plugin1_dict = {
|
||||
"description": "vanilla plugin",
|
||||
@ -261,3 +263,18 @@ def data(TEST):
|
||||
data_sources.DataSourceManager(None), data_source2_dict)
|
||||
TEST.data_sources.add(data_source1)
|
||||
TEST.data_sources.add(data_source2)
|
||||
|
||||
#Job Binaries
|
||||
job_binary1_dict = {
|
||||
"created_at": "2014-06-05 18:15:15.581285",
|
||||
"description": "",
|
||||
"id": "3f3a07ac-7d6f-49e8-8669-40b25ee891b7",
|
||||
"name": "example.pig",
|
||||
"tenant_id": "429ad8447c2d47bc8e0382d244e1d1df",
|
||||
"updated_at": None,
|
||||
"url": "internal-db://80121dea-f8bd-4ad3-bcc7-096f4bfc722d"
|
||||
}
|
||||
|
||||
job_binary1 = job_binaries.JobBinaries(
|
||||
job_binaries.JobBinariesManager(None), job_binary1_dict)
|
||||
TEST.job_binaries.add(job_binary1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user