Merge "Adds EDP support in the UI"

This commit is contained in:
Jenkins 2013-08-22 09:06:01 +00:00 committed by Gerrit Code Review
commit a3e23583e3
45 changed files with 1348 additions and 0 deletions

View File

@ -1,4 +1,5 @@
Alexander Kuznetsov <akuznetsov@mirantis.com>
Chad Roberts <croberts@redhat.com>
Dmitry Mescheryakov <dmescheryakov@mirantis.com>
Nikita Konovalov <nkonovalov@mirantis.com>
Nikolay Mahotkin <nmakhotkin@mirantis.com>

View File

@ -19,8 +19,11 @@ import logging
from savannadashboard.api import cluster_templates
from savannadashboard.api import clusters
from savannadashboard.api import data_sources
from savannadashboard.api import httpclient
from savannadashboard.api import images
from savannadashboard.api import job_origins
from savannadashboard.api import jobs
from savannadashboard.api import node_group_templates
from savannadashboard.api import plugins
from savannadashboard.utils import importutils
@ -69,3 +72,6 @@ class Client(object):
NodeGroupTemplateManager(self))
self.plugins = plugins.PluginManager(self)
self.images = images.ImageManager(self)
self.jobs = jobs.JobManager(self)
self.job_origins = job_origins.JobOriginManager(self)
self.data_sources = data_sources.DataSourceManager(self)

View File

@ -0,0 +1,49 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 savannadashboard.api import base
class DataSource(base.Resource):
resource_name = 'Data Source'
defaults = {'description': ''}
class DataSourceManager(base.ResourceManager):
resource_class = DataSource
def create(self, name, description, data_source_type,
url, credential_user, credential_pass):
data = {
'name': name,
'description': description,
'type': data_source_type,
'url': url,
'credentials': {'user': credential_user,
'password': credential_pass}
}
self._create('/data-sources', data)
def list(self):
return self._list('/data-sources', 'data_sources')
def get(self, data_source_id):
return self._get('/data-sources/%s' % data_source_id,
'resource')
def delete(self, data_source_id):
self._delete('/data-sources/%s' % data_source_id)

View File

@ -0,0 +1,51 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 savannadashboard.api import base
class JobOrigin(base.Resource):
resource_name = 'Job Origin'
defaults = {'description': ''}
class JobOriginManager(base.ResourceManager):
resource_class = JobOrigin
def create(self, name, storage_type, username, password,
location, description):
data = {
'credentials': {'user': username,
'password': password
},
'name': name,
'description': description,
'storage_type': storage_type,
'url': location
}
self._create('/job-origins', data)
def list(self):
return self._list('/job-origins', 'job_origins')
def get(self, job_origin_id):
return self._get('/job-origins/%s' % job_origin_id,
'resource')
def delete(self, job_origin_id):
self._delete('/job-origins/%s' % job_origin_id)

View File

@ -0,0 +1,50 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 savannadashboard.api import base
class Job(base.Resource):
resource_name = 'Job'
defaults = {'description': ''}
class JobManager(base.ResourceManager):
resource_class = Job
def create(self, name, description, job_type,
input_type, output_type, job_origin_id):
data = {
'name': name,
'description': description,
'type': job_type,
'input_type': input_type,
'output_type': output_type,
'job_origin_id': job_origin_id
}
self._create('/jobs', data)
def list(self):
return self._list('/jobs', 'jobs')
def get(self, job_id):
return self._get('/jobs/%s' % job_id,
'resource')
def delete(self, job_id):
self._delete('/jobs/%s' % job_id)

View File

@ -31,6 +31,9 @@ class SavannaDashboard(horizon.Dashboard):
panels = ('clusters',
'cluster_templates',
'nodegroup_templates',
'jobs',
'job_origins',
'data_sources',
'image_registry',
'plugins')
default_panel = 'clusters'

View File

@ -0,0 +1,30 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 savannadashboard import dashboard
class DataSourcesPanel(horizon.Panel):
name = _("Data Sources")
slug = 'data_sources'
dashboard.SavannaDashboard.register(DataSourcesPanel)

View File

@ -0,0 +1,63 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 savannadashboard.api import client as savannaclient
LOG = logging.getLogger(__name__)
class CreateDataSource(tables.LinkAction):
name = "create data source"
verbose_name = _("Create Data Source")
url = "horizon:savanna:data_sources:create-data-source"
classes = ("btn-launch", "ajax-modal")
class DeleteDataSource(tables.BatchAction):
name = "delete"
action_present = _("Delete")
action_past = _("Deleted")
data_type_singular = _("Data source")
data_type_plural = _("Data sources")
classes = ('btn-danger', 'btn-terminate')
def action(self, request, obj_id):
savanna = savannaclient.Client(request)
savanna.data_sources.delete(obj_id)
class DataSourcesTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Name"),
link=("horizon:savanna:data_sources:details"))
type = tables.Column("type",
verbose_name=_("Type"))
description = tables.Column("description",
verbose_name=_("Description"))
class Meta:
name = "data_sources"
verbose_name = _("Data Sources")
table_actions = (CreateDataSource,
DeleteDataSource)
row_actions = (DeleteDataSource,)

View File

@ -0,0 +1,44 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 tabs
from savannadashboard.api import client as savannaclient
LOG = logging.getLogger(__name__)
class GeneralTab(tabs.Tab):
name = _("General Info")
slug = "data_source_details_tab"
template_name = ("data_sources/_details.html")
def get_context_data(self, request):
data_source_id = self.tab_group.kwargs['data_source_id']
savanna = savannaclient.Client(request)
data_source = savanna.data_sources.get(data_source_id)
return {"data_source": data_source}
class DataSourceDetailsTabs(tabs.TabGroup):
slug = "data_source_details"
tabs = (GeneralTab,)
sticky = True

View File

@ -0,0 +1,34 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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.defaults import patterns
from django.conf.urls.defaults import url
import savannadashboard.data_sources.views as views
urlpatterns = patterns('',
url(r'^$', views.DataSourcesView.as_view(),
name='index'),
url(r'^$', views.DataSourcesView.as_view(),
name='data-sources'),
url(r'^create-data-source$',
views.CreateDataSourceView.as_view(),
name='create-data-source'),
url(r'^(?P<data_source_id>[^/]+)$',
views.DataSourceDetailsView.as_view(),
name='details'))

View File

@ -0,0 +1,64 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 horizon import tables
from horizon import tabs
from horizon import workflows
from savannadashboard.api import client as savannaclient
from savannadashboard.data_sources.tables import DataSourcesTable
import savannadashboard.data_sources.tabs as _tabs
import savannadashboard.data_sources.workflows.create as create_flow
LOG = logging.getLogger(__name__)
class DataSourcesView(tables.DataTableView):
table_class = DataSourcesTable
template_name = 'data_sources/data_sources.html'
def get_data(self):
savanna = savannaclient.Client(self.request)
data_sources = savanna.data_sources.list()
return data_sources
class FakeDataSource(object):
pass
class CreateDataSourceView(workflows.WorkflowView):
workflow_class = create_flow.CreateDataSource
success_url = \
"horizon:savanna:data-sources:create-data-source"
classes = ("ajax-modal")
template_name = "data_sources/create.html"
class DataSourceDetailsView(tabs.TabView):
tab_group_class = _tabs.DataSourceDetailsTabs
template_name = 'data_sources/details.html'
def get_context_data(self, **kwargs):
context = super(DataSourceDetailsView, self)\
.get_context_data(**kwargs)
return context
def get_data(self):
pass

View File

@ -0,0 +1,92 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 as _
from horizon import forms
from horizon import workflows
from savannadashboard.api import client as savannaclient
LOG = logging.getLogger(__name__)
class GeneralConfigAction(workflows.Action):
data_source_name = forms.CharField(label=_("Name"),
required=True)
data_source_type = forms.ChoiceField(
label=_("Data Source Type"),
required=True,
choices=[("swift", "Swift")],
widget=forms.Select(attrs={"class": "data_source_type_choice"}))
data_source_url = forms.CharField(label=_("URL"),
required=True)
data_source_credential_user = forms.CharField(label=_("Origin username"),)
data_source_credential_pass = forms.CharField(
widget=forms.PasswordInput(attrs={'autocomplete': 'off'}),
label=_("Origin password"))
data_source_description = forms.CharField(
label=_("Description"),
required=False,
widget=forms.Textarea)
def __init__(self, request, *args, **kwargs):
super(GeneralConfigAction, self).__init__(request, *args, **kwargs)
class Meta:
name = _("Create Data Source")
help_text_template = \
("data_sources/_create_data_source_help.html")
class GeneralConfig(workflows.Step):
action_class = GeneralConfigAction
contributes = ("hidden_configure_field", )
def contribute(self, data, context):
for k, v in data.items():
context["general_" + k] = v
return context
class CreateDataSource(workflows.Workflow):
slug = "create_data_source"
name = _("Create Data Source")
finalize_button_name = _("Create")
success_message = _("Data source created")
failure_message = _("Could not create data source")
success_url = "horizon:savanna:data_sources:index"
default_steps = (GeneralConfig, )
def handle(self, request, context):
savanna = savannaclient.Client(request)
savanna.data_sources.create(
context["general_data_source_name"],
context["general_data_source_description"],
context["general_data_source_type"],
context["general_data_source_url"],
context["general_data_source_credential_user"],
context["general_data_source_credential_pass"])
return True

View File

View File

@ -0,0 +1,30 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 savannadashboard import dashboard
class JobOriginsPanel(horizon.Panel):
name = _("Job Origins")
slug = 'job_origins'
dashboard.SavannaDashboard.register(JobOriginsPanel)

View File

@ -0,0 +1,63 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 savannadashboard.api import client as savannaclient
LOG = logging.getLogger(__name__)
class CreateJobOrigin(tables.LinkAction):
name = "create job origin"
verbose_name = _("Create Job Origin")
url = "horizon:savanna:job_origins:create-job-origin"
classes = ("btn-launch", "ajax-modal")
class DeleteJobOrigin(tables.BatchAction):
name = "delete"
action_present = _("Delete")
action_past = _("Deleted")
data_type_singular = _("Job origin")
data_type_plural = _("Job origins")
classes = ('btn-danger', 'btn-terminate')
def action(self, request, obj_id):
savanna = savannaclient.Client(request)
savanna.job_origins.delete(obj_id)
class JobOriginsTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Name"),
link=("horizon:savanna:job_origins:details"))
type = tables.Column("type",
verbose_name=_("Type"))
description = tables.Column("description",
verbose_name=_("Description"))
class Meta:
name = "job_origins"
verbose_name = _("Job Origins")
table_actions = (CreateJobOrigin,
DeleteJobOrigin)
row_actions = (DeleteJobOrigin,)

View File

@ -0,0 +1,44 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 tabs
from savannadashboard.api import client as savannaclient
LOG = logging.getLogger(__name__)
class GeneralTab(tabs.Tab):
name = _("General Info")
slug = "job_origin_details_tab"
template_name = ("job_origins/_details.html")
def get_context_data(self, request):
job_origin_id = self.tab_group.kwargs['job_id']
savanna = savannaclient.Client(request)
job_origin = savanna.job_origins.get(job_origin_id)
return {"job_origin": job_origin}
class JobOriginDetailsTabs(tabs.TabGroup):
slug = "job_origin_details"
tabs = (GeneralTab,)
sticky = True

View File

@ -0,0 +1,34 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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.defaults import patterns
from django.conf.urls.defaults import url
import savannadashboard.job_origins.views as views
urlpatterns = patterns('',
url(r'^$', views.JobOriginsView.as_view(),
name='index'),
url(r'^$', views.JobOriginsView.as_view(),
name='job-origins'),
url(r'^create-job-origin$',
views.CreateJobOriginView.as_view(),
name='create-job-origin'),
url(r'^(?P<job_id>[^/]+)$',
views.JobOriginDetailsView.as_view(),
name='details'))

View File

@ -0,0 +1,61 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 horizon import tables
from horizon import tabs
from horizon import workflows
from savannadashboard.api import client as savannaclient
from savannadashboard.job_origins.tables import JobOriginsTable
import savannadashboard.job_origins.tabs as _tabs
import savannadashboard.job_origins.workflows.create as create_flow
LOG = logging.getLogger(__name__)
class JobOriginsView(tables.DataTableView):
table_class = JobOriginsTable
template_name = 'job_origins/job_origins.html'
def get_data(self):
savanna = savannaclient.Client(self.request)
job_origins = savanna.job_origins.list()
return job_origins
class CreateJobOriginView(workflows.WorkflowView):
workflow_class = create_flow.CreateJobOrigin
success_url = \
"horizon:savanna:job-origins:create-job-origin"
classes = ("ajax-modal")
template_name = "job_origins/create.html"
class JobOriginDetailsView(tabs.TabView):
tab_group_class = _tabs.JobOriginDetailsTabs
template_name = 'job_origins/details.html'
def get_context_data(self, **kwargs):
context = super(JobOriginDetailsView, self)\
.get_context_data(**kwargs)
return context
def get_data(self):
pass

View File

@ -0,0 +1,96 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 as _
from horizon import forms
from horizon import workflows
from savannadashboard.api import client as savannaclient
LOG = logging.getLogger(__name__)
class GeneralConfigAction(workflows.Action):
job_origin_name = forms.CharField(label=_("Name"),
required=True)
job_origin_credential_user = forms.CharField(label=_("Origin username"),
required=True)
job_origin_credential_pass = forms.CharField(
widget=forms.PasswordInput(attrs={'autocomplete': 'off'}),
label=_("Origin password"),
required=True)
job_storage_type = forms.ChoiceField(
label=_("Job Storage Type"),
required=True,
choices=[("internal", "Savanna DB"),
("swift", "Swift"),
("hdfs", "HDFS")],
widget=forms.Select(
attrs={"class": "job_storage_type_choice"}))
job_origin_location = forms.CharField(label=_("Job Storage Location"),
required=True)
job_origin_description = forms.CharField(label=_("Description"),
required=False,
widget=forms.Textarea)
def __init__(self, request, *args, **kwargs):
super(GeneralConfigAction, self).__init__(request, *args, **kwargs)
class Meta:
name = _("Create Job Origin")
help_text_template = \
("job_origins/_create_job_origin_help.html")
class GeneralConfig(workflows.Step):
action_class = GeneralConfigAction
contributes = ("hidden_configure_field", )
def contribute(self, data, context):
for k, v in data.items():
context["general_" + k] = v
return context
class CreateJobOrigin(workflows.Workflow):
slug = "create_job_origin"
name = _("Create Job Origin")
finalize_button_name = _("Create")
success_message = _("Job origin created")
failure_message = _("Could not create job origin")
success_url = "horizon:savanna:job_origins:index"
default_steps = (GeneralConfig, )
def handle(self, request, context):
savanna = savannaclient.Client(request)
savanna.job_origins.create(
context["general_job_origin_name"],
context["general_job_storage_type"],
context["general_job_origin_credential_user"],
context["general_job_origin_credential_pass"],
context["general_job_origin_location"],
context["general_job_origin_description"])
return True

View File

View File

@ -0,0 +1,30 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 savannadashboard import dashboard
class JobsPanel(horizon.Panel):
name = _("Jobs")
slug = 'jobs'
dashboard.SavannaDashboard.register(JobsPanel)

View File

@ -0,0 +1,63 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 savannadashboard.api import client as savannaclient
LOG = logging.getLogger(__name__)
class CreateJob(tables.LinkAction):
name = "create job"
verbose_name = _("Create Job")
url = "horizon:savanna:jobs:create-job"
classes = ("btn-launch", "ajax-modal")
class DeleteJob(tables.BatchAction):
name = "delete"
action_present = _("Delete")
action_past = _("Deleted")
data_type_singular = _("Job")
data_type_plural = _("Jobs")
classes = ('btn-danger', 'btn-terminate')
def action(self, request, obj_id):
savanna = savannaclient.Client(request)
savanna.jobs.delete(obj_id)
class JobsTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Name"),
link=("horizon:savanna:jobs:details"))
type = tables.Column("type",
verbose_name=_("Type"))
description = tables.Column("description",
verbose_name=_("Description"))
class Meta:
name = "jobs"
verbose_name = _("Jobs")
table_actions = (CreateJob,
DeleteJob)
row_actions = (DeleteJob,)

View File

@ -0,0 +1,44 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 tabs
from savannadashboard.api import client as savannaclient
LOG = logging.getLogger(__name__)
class GeneralTab(tabs.Tab):
name = _("General Info")
slug = "job_details_tab"
template_name = ("jobs/_details.html")
def get_context_data(self, request):
job_id = self.tab_group.kwargs['job_id']
savanna = savannaclient.Client(request)
job = savanna.jobs.get(job_id)
return {"job": job}
class JobDetailsTabs(tabs.TabGroup):
slug = "job_details"
tabs = (GeneralTab,)
sticky = True

View File

@ -0,0 +1,34 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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.defaults import patterns
from django.conf.urls.defaults import url
import savannadashboard.jobs.views as views
urlpatterns = patterns('',
url(r'^$', views.JobsView.as_view(),
name='index'),
url(r'^$', views.JobsView.as_view(),
name='jobs'),
url(r'^create-job$',
views.CreateJobView.as_view(),
name='create-job'),
url(r'^(?P<job_id>[^/]+)$',
views.JobDetailsView.as_view(),
name='details'))

View File

@ -0,0 +1,61 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 horizon import tables
from horizon import tabs
from horizon import workflows
from savannadashboard.api import client as savannaclient
from savannadashboard.jobs.tables import JobsTable
import savannadashboard.jobs.tabs as _tabs
import savannadashboard.jobs.workflows.create as create_flow
LOG = logging.getLogger(__name__)
class JobsView(tables.DataTableView):
table_class = JobsTable
template_name = 'jobs/jobs.html'
def get_data(self):
savanna = savannaclient.Client(self.request)
jobs = savanna.jobs.list()
return jobs
class CreateJobView(workflows.WorkflowView):
workflow_class = create_flow.CreateJob
success_url = \
"horizon:savanna:jobs:create-job"
classes = ("ajax-modal")
template_name = "jobs/create.html"
class JobDetailsView(tabs.TabView):
tab_group_class = _tabs.JobDetailsTabs
template_name = 'jobs/details.html'
def get_context_data(self, **kwargs):
context = super(JobDetailsView, self)\
.get_context_data(**kwargs)
return context
def get_data(self):
pass

View File

@ -0,0 +1,110 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 Red Hat Inc.
#
# 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 as _
from horizon import forms
from horizon import workflows
from savannadashboard.api import client as savannaclient
LOG = logging.getLogger(__name__)
class GeneralConfigAction(workflows.Action):
job_name = forms.CharField(label=_("Job Name"),
required=True)
job_type = forms.ChoiceField(
label=_("Job Type"),
required=True,
choices=[("Pig", "Pig"), ("Hive", "Hive"),
("Oozie", "Oozie"), ("Jar", "Jar"),
("StreamingAPI", "Streaming API")],
widget=forms.Select(attrs={"class": "job_type_choice"}))
job_input_type = forms.ChoiceField(
label=_("Input Type"),
required=True,
choices=[("swift", "Swift")],
widget=forms.Select(attrs={"class": "job_input_type_choice"}))
job_output_type = forms.ChoiceField(
label=_("Output Type"),
required=True,
choices=[("swift", "Swift")],
widget=forms.Select(attrs={"class": "job_output_type_choice"}))
job_origin = forms.ChoiceField(
label=_("Job Origin"),
required=True,
initial=(None, "None"),
widget=forms.Select(attrs={"class": "job_origin_choice"}))
job_description = forms.CharField(label=_("Job Description"),
required=False,
widget=forms.Textarea)
def __init__(self, request, *args, **kwargs):
super(GeneralConfigAction, self).__init__(request, *args, **kwargs)
def populate_job_origin_choices(self, request, context):
savanna = savannaclient.Client(request)
job_origins = savanna.job_origins.list()
choices = [(job_origin.id, job_origin.name)
for job_origin in job_origins]
return choices
class Meta:
name = _("Create Job")
help_text_template = \
("jobs/_create_job_help.html")
class GeneralConfig(workflows.Step):
action_class = GeneralConfigAction
def contribute(self, data, context):
for k, v in data.items():
context["general_" + k] = v
return context
class CreateJob(workflows.Workflow):
slug = "create_job"
name = _("Create Job")
finalize_button_name = _("Create")
success_message = _("Job created")
failure_message = _("Could not create job")
success_url = "horizon:savanna:jobs:index"
default_steps = (GeneralConfig, )
def handle(self, request, context):
savanna = savannaclient.Client(request)
savanna.jobs.create(
context["general_job_name"],
context["general_job_description"],
context["general_job_type"],
context["general_job_input_type"],
context["general_job_output_type"],
context["general_job_origin"])
return True

View File

@ -0,0 +1,20 @@
{% load i18n sizeformat %}
<h3>{% trans "Data Source Overview" %}</h3>
<div class="status row-fluid detail">
<dl>
<dt>{% trans "Name" %}</dt>
<dd>{{ data_source.name }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ data_source.id }}</dd>
<dt>{% trans "Type" %}</dt>
<dd>{{ data_source.type }}</dd>
<dt>{% trans "URL" %}</dt>
<dd>{{ data_source.url }}</dd>
<dt>{% trans "Tenant id" %}</dt>
<dd>{{ data_source.tenant_id }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ data_source.description|default:"None" }}</dd>
<dt>{% trans "Create time" %}</dt>
<dd>{{ data_source.created_at }}</dd>
</dl>
</div>

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Create Data Source" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Savanna - Create Data Source") %}
{% endblock page_header %}
{% block main %}
{% include 'horizon/common/_workflow.html' %}
{% endblock %}<!DOCTYPE html>

View File

@ -0,0 +1,15 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Savanna" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Savanna - Data Sources") %}
{% endblock page_header %}
{% block main %}
<div class="cluster_templates">
{{ data_sources_table.render }}
</div>
{% endblock %}

View File

@ -0,0 +1,15 @@
{% extends 'base.html' %}
{% load i18n sizeformat %}
{% block title %}{% trans "Data Source Details" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Savanna - Data Source Details") %}
{% endblock page_header %}
{% block main %}
<div class="row-fluid">
<div class="span12">
{{ tab_group.render }}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,24 @@
{% load i18n sizeformat %}
<h3>{% trans "Job Origin Overview" %}</h3>
<div class="status row-fluid detail">
<dl>
<dt>{% trans "Name" %}</dt>
<dd>{{ job_origin.name }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ job_origin.id }}</dd>
<dt>{% trans "URL" %}</dt>
<dd>{{ job_origin.url }}</dd>
<dt>{% trans "Storage type" %}</dt>
<dd>{{ job_origin.storage_type }}</dd>
<dt>{% trans "Username" %}</dt>
<dd>{{ job_origin.credentials.user|default:"None" }}</dd>
<dt>{% trans "Password" %}</dt>
<dd>{{ job_origin.credentials.password|default:"None" }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ job_origin.description|default:"None" }}</dd>
<dt>{% trans "Tenant id" %}</dt>
<dd>{{ job_origin.tenant_id }}</dd>
<dt>{% trans "Create time" %}</dt>
<dd>{{ job_origin.created_at }}</dd>
</dl>
</div>

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Create Job Origin" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Savanna - Create Job Origin") %}
{% endblock page_header %}
{% block main %}
{% include 'horizon/common/_workflow.html' %}
{% endblock %}<!DOCTYPE html>

View File

@ -0,0 +1,15 @@
{% extends 'base.html' %}
{% load i18n sizeformat %}
{% block title %}{% trans "Job Origin Details" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Savanna - Job Origin Details") %}
{% endblock page_header %}
{% block main %}
<div class="row-fluid">
<div class="span12">
{{ tab_group.render }}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,15 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Savanna" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Savanna - Job Origins") %}
{% endblock page_header %}
{% block main %}
<div class="cluster_templates">
{{ job_origins_table.render }}
</div>
{% endblock %}

View File

@ -0,0 +1,24 @@
{% load i18n sizeformat %}
<h3>{% trans "Job Overview" %}</h3>
<div class="status row-fluid detail">
<dl>
<dt>{% trans "Name" %}</dt>
<dd>{{ job.name }}</dd>
<dt>{% trans "Id" %}</dt>
<dd>{{ job.id }}</dd>
<dt>{% trans "Type" %}</dt>
<dd>{{ job.type }}</dd>
<dt>{% trans "Input type" %}</dt>
<dd>{{ job.input_type }}</dd>
<dt>{% trans "Output type" %}</dt>
<dd>{{ job.output_type }}</dd>
<dt>{% trans "Job origin id" %}</dt>
<dd>{{ job.job_origin_id }}</dd>
<dt>{% trans "Tenant id" %}</dt>
<dd>{{ job.tenant_id }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ job.description|default:"None" }}</dd>
<dt>{% trans "Create time" %}</dt>
<dd>{{ job.created_at }}</dd>
</dl>
</div>

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Create Job" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Savanna - Create Job") %}
{% endblock page_header %}
{% block main %}
{% include 'horizon/common/_workflow.html' %}
{% endblock %}<!DOCTYPE html>

View File

@ -0,0 +1,15 @@
{% extends 'base.html' %}
{% load i18n sizeformat %}
{% block title %}{% trans "Job Details" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Savanna - Job Details") %}
{% endblock page_header %}
{% block main %}
<div class="row-fluid">
<div class="span12">
{{ tab_group.render }}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,15 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Savanna" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Savanna - Job") %}
{% endblock page_header %}
{% block main %}
<div class="cluster_templates">
{{ jobs_table.render }}
</div>
{% endblock %}