Merge "ACL support in Sahara UI"

This commit is contained in:
Jenkins 2016-02-10 16:03:20 +00:00 committed by Gerrit Code Review
commit b3dec2d07a
35 changed files with 630 additions and 61 deletions

View File

@ -139,7 +139,9 @@ def nodegroup_template_create(request, name, plugin_name, hadoop_version,
is_proxy_gateway=False,
volume_local_to_instance=False,
use_autoconfig=None,
shares=None):
shares=None,
is_public=None,
is_protected=None):
return client(request).node_group_templates.create(
name=name,
plugin_name=plugin_name,
@ -159,7 +161,9 @@ def nodegroup_template_create(request, name, plugin_name, hadoop_version,
is_proxy_gateway=is_proxy_gateway,
volume_local_to_instance=volume_local_to_instance,
use_autoconfig=use_autoconfig,
shares=shares)
shares=shares,
is_public=is_public,
is_protected=is_protected)
def nodegroup_template_list(request, search_opts=None):
@ -184,13 +188,15 @@ def nodegroup_template_update(request, ngt_id, name, plugin_name,
volumes_size=None, node_processes=None,
node_configs=None, floating_ip_pool=None,
security_groups=None, auto_security_group=False,
availability_zone=False,
volumes_availability_zone=False,
availability_zone=None,
volumes_availability_zone=None,
volume_type=None,
is_proxy_gateway=False,
volume_local_to_instance=False,
use_autoconfig=None,
shares=None):
shares=None,
is_protected=None,
is_public=None):
return client(request).node_group_templates.update(
ng_template_id=ngt_id,
name=name,
@ -211,14 +217,17 @@ def nodegroup_template_update(request, ngt_id, name, plugin_name,
is_proxy_gateway=is_proxy_gateway,
volume_local_to_instance=volume_local_to_instance,
use_autoconfig=use_autoconfig,
shares=shares)
shares=shares,
is_public=is_public,
is_protected=is_protected)
def cluster_template_create(request, name, plugin_name, hadoop_version,
description=None, cluster_configs=None,
node_groups=None, anti_affinity=None,
net_id=None, use_autoconfig=None,
shares=None):
shares=None,
is_public=None, is_protected=None):
return client(request).cluster_templates.create(
name=name,
plugin_name=plugin_name,
@ -229,7 +238,9 @@ def cluster_template_create(request, name, plugin_name, hadoop_version,
anti_affinity=anti_affinity,
net_id=net_id,
use_autoconfig=use_autoconfig,
shares=shares)
shares=shares,
is_public=is_public,
is_protected=is_protected)
def cluster_template_list(request, search_opts=None):
@ -248,7 +259,8 @@ def cluster_template_update(request, ct_id, name, plugin_name,
hadoop_version, description=None,
cluster_configs=None, node_groups=None,
anti_affinity=None, net_id=None,
use_autoconfig=None, shares=None):
use_autoconfig=None, shares=None,
is_public=None, is_protected=None):
try:
template = client(request).cluster_templates.update(
cluster_template_id=ct_id,
@ -261,7 +273,10 @@ def cluster_template_update(request, ct_id, name, plugin_name,
anti_affinity=anti_affinity,
net_id=net_id,
use_autoconfig=use_autoconfig,
shares=shares)
shares=shares,
is_public=is_public,
is_protected=is_protected
)
except APIException as e:
raise exceptions.Conflict(e)
@ -272,7 +287,8 @@ def cluster_create(request, name, plugin_name, hadoop_version,
cluster_template_id=None, default_image_id=None,
is_transient=None, description=None, cluster_configs=None,
node_groups=None, user_keypair_id=None, anti_affinity=None,
net_id=None, count=None, use_autoconfig=None):
net_id=None, count=None, use_autoconfig=None,
is_public=None, is_protected=None):
return client(request).clusters.create(
name=name,
plugin_name=plugin_name,
@ -287,7 +303,9 @@ def cluster_create(request, name, plugin_name, hadoop_version,
anti_affinity=anti_affinity,
net_id=net_id,
count=count,
use_autoconfig=use_autoconfig)
use_autoconfig=use_autoconfig,
is_public=is_public,
is_protected=is_protected)
def cluster_scale(request, cluster_id, scale_object):
@ -321,14 +339,17 @@ def cluster_update(request, cluster_id, name=None, description=None,
def data_source_create(request, name, description, ds_type, url,
credential_user=None, credential_pass=None):
credential_user=None, credential_pass=None,
is_public=None, is_protected=None):
return client(request).data_sources.create(
name=name,
description=description,
data_source_type=ds_type,
url=url,
credential_user=credential_user,
credential_pass=credential_pass)
credential_pass=credential_pass,
is_public=is_public,
is_protected=is_protected)
def data_source_list(request, search_opts=None):
@ -347,12 +368,16 @@ def data_source_update(request, ds_id, data):
return client(request).data_sources.update(ds_id, data)
def job_binary_create(request, name, url, description, extra):
def job_binary_create(request, name, url, description, extra,
is_public=None, is_protected=None):
return client(request).job_binaries.create(
name=name,
url=url,
description=description,
extra=extra)
extra=extra,
is_public=is_public,
is_protected=is_protected,
)
def job_binary_list(request, search_opts=None):
@ -397,14 +422,22 @@ def job_binary_internal_delete(request, jbi_id):
client(request).job_binary_internals.delete(job_binary_id=jbi_id)
def job_create(request, name, j_type, mains, libs, description, interface):
def job_create(request, name, j_type, mains, libs, description, interface,
is_public=None, is_protected=None):
return client(request).jobs.create(
name=name,
type=j_type,
mains=mains,
libs=libs,
description=description,
interface=interface)
interface=interface,
is_public=is_public,
is_protected=is_protected)
def job_update(request, job_id, is_public=None, is_protected=None):
return client(request).jobs.update(job_id=job_id, is_public=is_public,
is_protected=is_protected)
def job_list(request, search_opts=None):
@ -425,14 +458,23 @@ def job_get_configs(request, job_type):
def job_execution_create(request, job_id, cluster_id,
input_id, output_id, configs,
interface):
interface, is_public=None, is_protected=None):
return client(request).job_executions.create(
job_id=job_id,
cluster_id=cluster_id,
input_id=input_id,
output_id=output_id,
configs=configs,
interface=interface)
interface=interface,
is_public=is_public,
is_protected=is_protected,
)
def job_execution_update(request, jbe_id, is_public=None, is_protected=None):
return client(request).job_executions.update(job_execution_id=jbe_id,
is_public=is_public,
is_protected=is_protected)
def _resolve_job_execution_names(job_execution, cluster=None,

View File

@ -20,6 +20,8 @@ from django.utils.translation import ungettext_lazy
from horizon import tables
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
class ClusterTemplatesFilterAction(tables.FilterAction):
@ -114,6 +116,38 @@ def render_node_groups(cluster_template):
return node_groups
def change_cluster_templates_rules_method(request, clt_id, **kwargs):
clt = saharaclient.cluster_template_get(request, clt_id)
update_required_fields = ('name', 'plugin_name', 'hadoop_version')
for field in update_required_fields:
kwargs[field] = getattr(clt, field)
saharaclient.cluster_template_update(request, clt_id, **kwargs)
class MakePublic(acl_utils.MakePublic):
def change_rule_method(self, request, datum_id, **update_kwargs):
change_cluster_templates_rules_method(
request, datum_id, **update_kwargs)
class MakePrivate(acl_utils.MakePrivate):
def change_rule_method(self, request, datum_id, **update_kwargs):
change_cluster_templates_rules_method(
request, datum_id, **update_kwargs)
class MakeProtected(acl_utils.MakeProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
change_cluster_templates_rules_method(
request, datum_id, **update_kwargs)
class MakeUnProtected(acl_utils.MakeUnProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
change_cluster_templates_rules_method(
request, datum_id, **update_kwargs)
class ClusterTemplatesTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Name"),
@ -138,8 +172,10 @@ class ClusterTemplatesTable(tables.DataTable):
ConfigureClusterTemplate,
DeleteTemplate,
ClusterTemplatesFilterAction,)
table_actions_menu = (MakePublic, MakePrivate,
MakeProtected, MakeUnProtected)
row_actions = (CreateCluster,
EditTemplate,
CopyTemplate,
DeleteTemplate,)
DeleteTemplate, MakePublic, MakePrivate,
MakeProtected, MakeUnProtected)

View File

@ -4,6 +4,8 @@
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ template.name }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ template.tenant_id }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ template.id }}</dd>
<dt>{% trans "Description" %}</dt>
@ -16,6 +18,10 @@
<dd>{{ template.hadoop_version }}</dd>
<dt>{% trans "Use auto-configuration" %}</dt>
<dd>{{ template.use_autoconfig }}</dd>
<dt>{% trans "Public" %}</dt>
<dd>{{ template.is_public|yesno }}</dd>
<dt>{% trans "Protected" %}</dt>
<dd>{{ template.is_protected|yesno }}</dd>
</dl>
<dl class="dl-horizontal">
<dt>{% trans "Anti-affinity enabled for" %}</dt>

View File

@ -134,7 +134,9 @@ class DataProcessingClusterTemplateTests(test.TestCase):
node_groups=ct.node_groups,
anti_affinity=ct.anti_affinity,
use_autoconfig=False,
shares=ct.shares)\
shares=ct.shares,
is_public=False,
is_protected=False) \
.AndReturn(new_ct)
self.mox.ReplayAll()

View File

@ -91,11 +91,17 @@ class CopyClusterTemplate(create_flow.ConfigureClusterTemplate):
fields['use_autoconfig'].initial = (
self.template.use_autoconfig)
fields["description"].initial = self.template.description
elif isinstance(step, create_flow.SelectClusterShares):
fields = step.action.fields
fields["shares"].initial = (
self._get_share_defaults(fields["shares"].choices)
)
fields['is_public'].initial = (
self.template.is_public)
fields['is_protected'].initial = (
self.template.is_protected)
except Exception:
exceptions.handle(request,
_("Unable to fetch template to copy."))

View File

@ -27,6 +27,8 @@ from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils import helpers as helpers
from sahara_dashboard.content.data_processing. \
utils import anti_affinity as aa
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
import sahara_dashboard.content.data_processing. \
utils.workflow_helpers as whelpers
@ -108,6 +110,9 @@ class GeneralConfigAction(workflows.Action):
initial=True,
)
is_public = acl_utils.get_is_public_form(_("cluster template"))
is_protected = acl_utils.get_is_protected_form(_("cluster template"))
anti_affinity = aa.anti_affinity_field()
def __init__(self, request, *args, **kwargs):
@ -378,7 +383,9 @@ class ConfigureClusterTemplate(whelpers.ServiceParametersWorkflow,
node_groups,
context["anti_affinity_info"],
use_autoconfig=context['general_use_autoconfig'],
shares=ct_shares
shares=ct_shares,
is_public=context['general_is_public'],
is_protected=context['general_is_protected']
)
hlps = helpers.Helpers(request)

View File

@ -93,7 +93,9 @@ class EditClusterTemplate(copy_flow.CopyClusterTemplate):
node_groups=node_groups,
anti_affinity=context["anti_affinity_info"],
use_autoconfig=context['general_use_autoconfig'],
shares=ct_shares
shares=ct_shares,
is_public=context['general_is_public'],
is_protected=context['general_is_protected']
)
return True
except exceptions.Conflict as e:

View File

@ -21,6 +21,8 @@ from horizon import tables
from horizon.tables import base as tables_base
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
from saharaclient.api import base as api_base
@ -145,6 +147,26 @@ class ConfigureCluster(tables.LinkAction):
attrs = {"style": "display: none"}
class MakePublic(acl_utils.MakePublic):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.cluster_update(request, datum_id, **update_kwargs)
class MakePrivate(acl_utils.MakePrivate):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.cluster_update(request, datum_id, **update_kwargs)
class MakeProtected(acl_utils.MakeProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.cluster_update(request, datum_id, **update_kwargs)
class MakeUnProtected(acl_utils.MakeUnProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.cluster_update(request, datum_id, **update_kwargs)
class ClustersTable(tables.DataTable):
name = tables.Column("name",
@ -178,6 +200,9 @@ class ClustersTable(tables.DataTable):
ConfigureCluster,
DeleteCluster,
ClustersFilterAction)
table_actions_menu = (MakePublic, MakePrivate,
MakeProtected, MakeUnProtected)
row_actions = (ScaleCluster,
UpdateClusterShares,
DeleteCluster,)
DeleteCluster, MakePublic, MakePrivate,
MakeProtected, MakeUnProtected)

View File

@ -43,7 +43,6 @@ class GeneralTab(tabs.Tab):
try:
sahara = saharaclient.client(request)
cluster = sahara.clusters.get(cluster_id)
for info_key, info_val in cluster.info.items():
for key, val in info_val.items():
if str(val).startswith(('http://', 'https://')):

View File

@ -4,6 +4,8 @@
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ cluster.name }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ cluster.tenant_id }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ cluster.id }}</dd>
<dt>{% trans "Description" %}</dt>
@ -48,6 +50,10 @@
<dd>{{ cluster.user_keypair_id }}</dd>
<dt>{% trans "Use auto-configuration" %}</dt>
<dd>{{ cluster.use_autoconfig }}</dd>
<dt>{% trans "Public" %}</dt>
<dd>{{ cluster.is_public|yesno }}</dd>
<dt>{% trans "Protected" %}</dt>
<dd>{{ cluster.is_protected|yesno }}</dd>
</dl>
<dl class="dl-horizontal">
<dt>{% trans "Anti-affinity enabled for" %}</dt>

View File

@ -17,6 +17,8 @@ from horizon import workflows
from openstack_dashboard.api import nova
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
from sahara_dashboard.content.data_processing.utils import neutron_support
import sahara_dashboard.content.data_processing.utils. \
workflow_helpers as whelpers
@ -104,6 +106,11 @@ class GeneralConfigAction(workflows.Action):
request, {})
)
self.fields['is_public'] = acl_utils.get_is_public_form(
_("cluster"))
self.fields['is_protected'] = acl_utils.get_is_protected_form(
_("cluster"))
self.fields["plugin_name"] = forms.CharField(
widget=forms.HiddenInput(),
initial=plugin
@ -244,7 +251,10 @@ class ConfigureCluster(whelpers.StatusFormatMixin, workflows.Workflow):
node_groups=node_groups,
user_keypair_id=user_keypair,
count=context['general_cluster_count'],
net_id=context.get("general_neutron_management_network", None))
net_id=context.get("general_neutron_management_network", None),
is_public=context['general_is_public'],
is_protected=context['general_is_protected']
)
return True
except api_base.APIException as e:
self.error_description = str(e)

View File

@ -17,6 +17,8 @@ from django.utils.translation import ungettext_lazy
from horizon import tables
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
class CreateDataSource(tables.LinkAction):
@ -55,6 +57,30 @@ class EditDataSource(tables.LinkAction):
classes = ("ajax-modal",)
class MakePublic(acl_utils.MakePublic):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.data_source_update(
request, datum_id, update_kwargs)
class MakePrivate(acl_utils.MakePrivate):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.data_source_update(
request, datum_id, update_kwargs)
class MakeProtected(acl_utils.MakeProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.data_source_update(
request, datum_id, update_kwargs)
class MakeUnProtected(acl_utils.MakeUnProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.data_source_update(
request, datum_id, update_kwargs)
class DataSourcesTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Name"),
@ -70,5 +96,13 @@ class DataSourcesTable(tables.DataTable):
verbose_name = _("Data Sources")
table_actions = (CreateDataSource,
DeleteDataSource)
table_actions_menu = (MakePublic,
MakePrivate,
MakeProtected,
MakeUnProtected)
row_actions = (DeleteDataSource,
EditDataSource,)
EditDataSource,
MakePublic,
MakePrivate,
MakeProtected,
MakeUnProtected)

View File

@ -4,6 +4,8 @@
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ data_source.name }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ data_source.tenant_id }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ data_source.id }}</dd>
<dt>{% trans "Type" %}</dt>
@ -12,6 +14,10 @@
<dd>{{ data_source.url }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ data_source.description|default:_("None") }}</dd>
<dt>{% trans "Public" %}</dt>
<dd>{{ data_source.is_public|yesno }}</dd>
<dt>{% trans "Protected" %}</dt>
<dd>{{ data_source.is_protected|yesno }}</dd>
<dt>{% trans "Create time" %}</dt>
<dd>{{ data_source.created_at }}</dd>
</dl>

View File

@ -77,14 +77,18 @@ class DataProcessingDataSourceTests(test.TestCase):
data_source.type,
data_source.url,
"",
"") \
"",
is_public=False,
is_protected=False) \
.AndReturn(self.data_sources.first())
self.mox.ReplayAll()
form_data = {
'data_source_url': data_source.url,
'data_source_name': data_source.name,
'data_source_description': data_source.description,
'data_source_type': data_source.type
'data_source_type': data_source.type,
'is_public': False,
'is_protected': False,
}
res = self.client.post(CREATE_URL, form_data)
self.assertNoFormErrors(res)
@ -100,7 +104,9 @@ class DataProcessingDataSourceTests(test.TestCase):
'credentials': {'user': '', 'pass': ''},
'type': data_source.type,
'name': data_source.name,
'description': data_source.description
'description': data_source.description,
'is_public': False,
'is_protected': False,
}
api.sahara.data_source_get(IsA(http.HttpRequest),
IsA(six.text_type)) \
@ -115,7 +121,7 @@ class DataProcessingDataSourceTests(test.TestCase):
'data_source_url': data_source.url,
'data_source_name': data_source.name,
'data_source_description': data_source.description,
'data_source_type': data_source.type
'data_source_type': data_source.type,
}
res = self.client.post(EDIT_URL, form_data)
@ -138,7 +144,8 @@ class DataProcessingDataSourceTests(test.TestCase):
IsA(six.text_type),
IsA(six.text_type),
IsA(str),
"", "").AndReturn(True)
"", "", is_public=False,
is_protected=False).AndReturn(True)
api.manila.share_list(IsA(http.HttpRequest)).AndReturn(shares)
self.mox.ReplayAll()

View File

@ -19,7 +19,11 @@ from horizon import workflows
from sahara_dashboard.api import manila as manilaclient
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils import helpers
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
from sahara_dashboard.content.data_processing \
.utils import helpers
class GeneralConfigAction(workflows.Action):
@ -76,6 +80,9 @@ class GeneralConfigAction(workflows.Action):
required=False,
widget=forms.Textarea(attrs={'rows': 4}))
is_public = acl_utils.get_is_public_form(_("data source"))
is_protected = acl_utils.get_is_protected_form(_("data source"))
def __init__(self, request, *args, **kwargs):
super(GeneralConfigAction, self).__init__(request, *args, **kwargs)
@ -145,7 +152,10 @@ class CreateDataSource(workflows.Workflow):
context["general_data_source_type"],
context["source_url"],
context.get("general_data_source_credential_user", None),
context.get("general_data_source_credential_pass", None))
context.get("general_data_source_credential_pass", None),
is_public=context['general_is_public'],
is_protected=context['general_is_protected']
)
hlps = helpers.Helpers(request)
if hlps.is_from_guide():

View File

@ -38,6 +38,8 @@ class EditDataSource(create.CreateDataSource):
"data_source_credential_user": None,
"data_source_credential_pass": None,
"data_source_manila_share": None,
'is_public': "is_public",
'is_protected': "is_protected"
}
def __init__(self, request, context_seed, entry_point, *args, **kwargs):
@ -80,7 +82,9 @@ class EditDataSource(create.CreateDataSource):
None),
"pass": context.get("general_data_source_credential_pass",
None)
}
},
"is_public": context['general_is_public'],
"is_protected": context['general_is_protected']
}
return saharaclient.data_source_update(request,
self.data_source_id,

View File

@ -26,6 +26,8 @@ from horizon import messages
from sahara_dashboard.api import manila as manilaclient
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
class LabeledInput(widgets.TextInput):
@ -158,6 +160,11 @@ class JobBinaryCreateForm(forms.SelfHandlingForm):
required=False,
widget=forms.Textarea()))
self.fields["is_public"] = acl_utils.get_is_public_form(
_("job binary"))
self.fields["is_protected"] = acl_utils.get_is_protected_form(
_("job binary"))
self.fields["job_binary_type"].choices =\
[("internal-db", "Internal database"),
("swift", "Swift")]
@ -241,7 +248,10 @@ class JobBinaryCreateForm(forms.SelfHandlingForm):
context["job_binary_name"],
bin_url,
context["job_binary_description"],
extra)
extra,
is_public=context['is_public'],
is_protected=context['is_protected']
)
messages.success(request, "Successfully created job binary")
return bin_object
except Exception:
@ -333,6 +343,8 @@ class JobBinaryEditForm(JobBinaryCreateForm):
'job_binary_username': None,
'job_binary_manila_share': None,
'job_binary_manila_path': None,
'is_public': 'is_public',
'is_protected': 'is_protected',
}
def handle(self, request, context):
@ -348,6 +360,8 @@ class JobBinaryEditForm(JobBinaryCreateForm):
"description": context["job_binary_description"],
"extra": extra,
"url": bin_url,
'is_public': context['is_public'],
'is_protected': context['is_protected']
}
bin_object = saharaclient.job_binary_update(

View File

@ -17,6 +17,8 @@ from django.utils.translation import ungettext_lazy
from horizon import tables
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
from saharaclient.api import base as api_base
@ -79,6 +81,26 @@ class EditJobBinary(tables.LinkAction):
classes = ("btn-edit", "ajax-modal",)
class MakePublic(acl_utils.MakePublic):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_binary_update(request, datum_id, update_kwargs)
class MakePrivate(acl_utils.MakePrivate):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_binary_update(request, datum_id, update_kwargs)
class MakeProtected(acl_utils.MakeProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_binary_update(request, datum_id, update_kwargs)
class MakeUnProtected(acl_utils.MakeUnProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_binary_update(request, datum_id, update_kwargs)
class JobBinariesTable(tables.DataTable):
name = tables.Column(
"name",
@ -93,5 +115,11 @@ class JobBinariesTable(tables.DataTable):
name = "job_binaries"
verbose_name = _("Job Binaries")
table_actions = (CreateJobBinary,
DeleteJobBinary)
row_actions = (DeleteJobBinary, DownloadJobBinary, EditJobBinary)
DeleteJobBinary,)
table_actions_menu = (MakePublic,
MakePrivate,
MakeProtected,
MakeUnProtected)
row_actions = (DeleteJobBinary, DownloadJobBinary, EditJobBinary,
MakePublic, MakePrivate, MakeProtected,
MakeUnProtected)

View File

@ -4,12 +4,18 @@
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ job_binary.name }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ job_binary.tenant_id }}</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 "Public" %}</dt>
<dd>{{ job_binary.is_public|yesno }}</dd>
<dt>{% trans "Protected" %}</dt>
<dd>{{ job_binary.is_protected|yesno }}</dd>
<dt>{% trans "Create time" %}</dt>
<dd>{{ job_binary.created_at|parse_isotime }}</dd>
</dl>

View File

@ -26,6 +26,8 @@ from horizon import tables
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing. \
jobs import tables as j_t
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
class JobExecutionsFilterAction(tables.FilterAction):
@ -128,6 +130,26 @@ class UpdateRow(tables.Row):
messages.error(request, _("Unable to update row"))
class MakePublic(acl_utils.MakePublic):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_execution_update(request, datum_id, **update_kwargs)
class MakePrivate(acl_utils.MakePrivate):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_execution_update(request, datum_id, **update_kwargs)
class MakeProtected(acl_utils.MakeProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_execution_update(request, datum_id, **update_kwargs)
class MakeUnProtected(acl_utils.MakeUnProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_execution_update(request, datum_id, **update_kwargs)
class JobExecutionsTable(tables.DataTable):
class StatusColumn(tables.Column):
def get_raw_data(self, datum):
@ -211,6 +233,10 @@ class JobExecutionsTable(tables.DataTable):
table_actions = [JobExecutionGuide,
DeleteJobExecution,
JobExecutionsFilterAction]
table_actions_menu = [MakePublic, MakePrivate,
MakeProtected, MakeUnProtected]
row_actions = [DeleteJobExecution,
ReLaunchJobExistingCluster,
ReLaunchJobNewCluster]
ReLaunchJobNewCluster,
MakePublic, MakePrivate,
MakeProtected, MakeUnProtected]

View File

@ -6,8 +6,14 @@
<dd>{{ job_execution.info.status }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ job_execution.id }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ job_execution.tenant_id }}</dd>
<dt>{% trans "Job Template" %}</dt>
<dd><a href="{% url 'horizon:project:data_processing.jobs:details' job_execution.job_id %}">{{ object_names.job_name }}</a></dd>
<dt>{% trans "Public" %}</dt>
<dd>{{ job_execution.is_public|yesno }}</dd>
<dt>{% trans "Protected" %}</dt>
<dd>{{ job_execution.is_protected|yesno }}</dd>
{% if job_execution.input_id %}
<dt>{% trans "Input Data Source" %}</dt>
<dd><a href="{% url 'horizon:project:data_processing.data_sources:details' job_execution.input_id %}">{{ object_names.input_name }}</a> ({{ object_names.input_url }})</dd>

View File

@ -19,6 +19,8 @@ from django.utils.translation import ungettext_lazy
from horizon import tables
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
class JobsFilterAction(tables.FilterAction):
@ -96,6 +98,26 @@ class ChoosePlugin(tables.LinkAction):
return "?".join([base_url, params])
class MakePublic(acl_utils.MakePublic):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_update(request, datum_id, **update_kwargs)
class MakePrivate(acl_utils.MakePrivate):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_update(request, datum_id, **update_kwargs)
class MakeProtected(acl_utils.MakeProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_update(request, datum_id, **update_kwargs)
class MakeUnProtected(acl_utils.MakeUnProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
saharaclient.job_update(request, datum_id, **update_kwargs)
class JobsTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Name"),
@ -109,4 +131,8 @@ class JobsTable(tables.DataTable):
name = "jobs"
verbose_name = _("Job Templates")
table_actions = (CreateJob, DeleteJob, JobsFilterAction,)
row_actions = (LaunchJobExistingCluster, ChoosePlugin, DeleteJob,)
table_actions_menu = [MakePublic, MakePrivate, MakeProtected,
MakeUnProtected]
row_actions = (LaunchJobExistingCluster, ChoosePlugin, DeleteJob,
MakePublic, MakePrivate, MakeProtected,
MakeUnProtected)

View File

@ -4,12 +4,18 @@
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ job.name }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ job.tenant_id }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ job.id }}</dd>
<dt>{% trans "Type" %}</dt>
<dd>{{ job.type }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ job.description|default:_("None") }}</dd>
<dt>{% trans "Public" %}</dt>
<dd>{{ job.is_public|yesno }}</dd>
<dt>{% trans "Protected" %}</dt>
<dd>{{ job.is_protected|yesno }}</dd>
<dt>{% trans "Mains" %}</dt>
{% for main in job.mains %}
<dd><a href="{% url 'horizon:project:data_processing.job_binaries:details' main.id %}">{{ main.name }}</a></dd>

View File

@ -54,7 +54,8 @@ class DataProcessingJobTests(test.TestCase):
api.sahara.job_binary_list(IsA(http.HttpRequest)).AndReturn([])
api.sahara.job_create(IsA(http.HttpRequest),
'test', 'Pig', [], [], 'test create',
interface=[])
interface=[], is_public=False,
is_protected=False)
api.sahara.job_types_list(IsA(http.HttpRequest)) \
.AndReturn(self.job_types.list())
self.mox.ReplayAll()
@ -96,7 +97,9 @@ class DataProcessingJobTests(test.TestCase):
"value_type": "string",
"required": False,
"default": "A value"
}])
}],
is_public=False,
is_protected=False)
api.sahara.job_types_list(IsA(http.HttpRequest)) \
.AndReturn(self.job_types.list())
self.mox.ReplayAll()
@ -173,7 +176,10 @@ class DataProcessingJobTests(test.TestCase):
IsA(six.text_type),
IsA(six.text_type),
IsA(dict),
IsA(dict)).AndReturn(job_execution)
IsA(dict),
is_public=False,
is_protected=False).AndReturn(
job_execution)
self.mox.ReplayAll()
url = reverse('horizon:project:data_processing.jobs:launch-job')

View File

@ -22,6 +22,8 @@ from horizon import workflows
from sahara_dashboard.content.data_processing \
.utils import helpers
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
import sahara_dashboard.content.data_processing \
.utils.workflow_helpers as whelpers
from sahara_dashboard.api import sahara as saharaclient
@ -99,6 +101,8 @@ class GeneralConfigAction(workflows.Action):
job_description = forms.CharField(label=_("Description"),
required=False,
widget=forms.Textarea(attrs={'rows': 4}))
is_public = acl_utils.get_is_public_form(_("job"))
is_protected = acl_utils.get_is_protected_form(_("job"))
def __init__(self, request, context, *args, **kwargs):
super(GeneralConfigAction,
@ -264,7 +268,10 @@ class CreateJob(workflows.Workflow):
main_locations,
lib_locations,
context["job_description"],
interface=interface)
interface=interface,
is_public=context['is_public'],
is_protected=context['is_protected']
)
hlps = helpers.Helpers(request)
if hlps.is_from_guide():

View File

@ -25,6 +25,8 @@ import sahara_dashboard.content.data_processing. \
cluster_templates.workflows.create as t_flows
import sahara_dashboard.content.data_processing. \
clusters.workflows.create as c_flow
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
import sahara_dashboard.content.data_processing. \
utils.workflow_helpers as whelpers
@ -105,6 +107,9 @@ class JobExecutionExistingGeneralConfigAction(JobExecutionGeneralConfigAction):
initial=(None, "None"),
widget=forms.Select(attrs={"class": "cluster_choice"}))
is_public = acl_utils.get_is_public_form(_("job"))
is_protected = acl_utils.get_is_protected_form(_("job"))
def populate_cluster_choices(self, request, context):
try:
clusters = saharaclient.cluster_list(request)
@ -501,7 +506,10 @@ class LaunchJob(workflows.Workflow):
context["job_general_job_input"],
context["job_general_job_output"],
context["job_config"],
interface)
interface,
is_public=context['job_general_is_public'],
is_protected=context['job_general_is_protected']
)
return True
@ -621,7 +629,10 @@ class LaunchJobNewCluster(workflows.Workflow):
context["job_general_job_input"],
context["job_general_job_output"],
context["job_config"],
interface)
interface,
is_public=context['job_general_is_public'],
is_protected=context['job_general_is_protected']
)
except Exception:
exceptions.handle(request,
_("Unable to launch job."))

View File

@ -16,7 +16,10 @@ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from horizon import tables
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
class NodeGroupTemplatesFilterAction(tables.FilterAction):
@ -80,6 +83,40 @@ class DeleteTemplate(tables.DeleteAction):
saharaclient.nodegroup_template_delete(request, template_id)
def change_node_group_templates_rules_method(request, ngt_id, **kwargs):
ngt = saharaclient.nodegroup_template_get(request, ngt_id)
update_required_fields = ('name', 'plugin_name',
'hadoop_version', 'flavor_id')
for field in update_required_fields:
kwargs[field] = getattr(ngt, field)
saharaclient.nodegroup_template_update(request, ngt_id, **kwargs)
class MakePublic(acl_utils.MakePublic):
def change_rule_method(self, request, datum_id, **update_kwargs):
change_node_group_templates_rules_method(
request, datum_id, **update_kwargs)
class MakePrivate(acl_utils.MakePrivate):
def change_rule_method(self, request, datum_id, **update_kwargs):
change_node_group_templates_rules_method(
request, datum_id, **update_kwargs)
class MakeProtected(acl_utils.MakeProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
change_node_group_templates_rules_method(
request, datum_id, **update_kwargs)
class MakeUnProtected(acl_utils.MakeUnProtected):
def change_rule_method(self, request, datum_id, **update_kwargs):
change_node_group_templates_rules_method(
request, datum_id, **update_kwargs)
class NodegroupTemplatesTable(tables.DataTable):
name = tables.Column(
"name",
@ -101,6 +138,9 @@ class NodegroupTemplatesTable(tables.DataTable):
ConfigureNodegroupTemplate,
DeleteTemplate,
NodeGroupTemplatesFilterAction,)
table_actions_menu = (MakePublic, MakePrivate, MakeProtected,
MakeUnProtected)
row_actions = (EditTemplate,
CopyTemplate,
DeleteTemplate)
DeleteTemplate, MakePublic, MakePrivate, MakeProtected,
MakeUnProtected)

View File

@ -4,10 +4,17 @@
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ template.name }}</dd>
<dt>{% trans "Project Id" %}</dt>
<dd>{{ template.tenant_id }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ template.id }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ template.description|default:_("None") }}</dd>
<dt>{% trans "Public" %}</dt>
<dd>{{ template.is_public|yesno }}</dd>
<dt>{% trans "Protected" %}</dt>
<dd>{{ template.is_protected|yesno }}</dd>
</dl>
<dl class="dl-horizontal">
<dt>{% trans "Flavor" %}</dt>

View File

@ -181,7 +181,9 @@ class DataProcessingNodeGroupTests(test.TestCase):
'availability_zone': None,
'is_proxy_gateway': False,
'use_autoconfig': True,
'shares': []}) \
'shares': [],
'is_public': False,
'is_protected': False})\
.AndReturn(True)
self.mox.ReplayAll()
@ -205,7 +207,9 @@ class DataProcessingNodeGroupTests(test.TestCase):
'security_autogroup': True,
'processes': 'HDFS:namenode',
'use_autoconfig': True,
'shares': []})
'shares': [],
'is_public': False,
'is_protected': False})
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
@ -275,7 +279,10 @@ class DataProcessingNodeGroupTests(test.TestCase):
availability_zone=None,
use_autoconfig=True,
is_proxy_gateway=False,
shares=[]).AndReturn(True)
shares=[],
is_protected=False,
is_public=False,
).AndReturn(True)
self.mox.ReplayAll()

View File

@ -82,6 +82,8 @@ class CopyNodegroupTemplate(create_flow.ConfigureNodegroupTemplate):
g_fields['volume_local_to_instance'].initial = volume_local_to_instance
g_fields["proxygateway"].initial = self.template.is_proxy_gateway
g_fields["use_autoconfig"].initial = self.template.use_autoconfig
g_fields["is_public"].initial = self.template.is_public
g_fields['is_protected'].initial = self.template.is_protected
if self.template.floating_ip_pool:
g_fields['floating_ip_pool'].initial = (

View File

@ -34,6 +34,8 @@ from openstack_dashboard.dashboards.project.volumes \
from sahara_dashboard.api import manila as manilaclient
from sahara_dashboard.api import sahara as saharaclient
from sahara_dashboard.content.data_processing.utils \
import acl as acl_utils
from sahara_dashboard.content.data_processing.utils \
import helpers
from sahara_dashboard.content.data_processing.utils \
@ -161,6 +163,11 @@ class GeneralConfigAction(workflows.Action):
"access other cluster instances."),
required=False)
self.fields['is_public'] = acl_utils.get_is_public_form(
_("node group template"))
self.fields['is_protected'] = acl_utils.get_is_protected_form(
_("node group template"))
self.fields["plugin_name"] = forms.CharField(
widget=forms.HiddenInput(),
initial=plugin
@ -516,7 +523,10 @@ class ConfigureNodegroupTemplate(workflow_helpers.ServiceParametersWorkflow,
is_proxy_gateway=context["general_proxygateway"],
availability_zone=context["general_availability_zone"],
use_autoconfig=context['general_use_autoconfig'],
shares=ngt_shares)
shares=ngt_shares,
is_public=context['general_is_public'],
is_protected=context['general_is_protected']
)
hlps = helpers.Helpers(request)
if hlps.is_from_guide():

View File

@ -99,7 +99,9 @@ class EditNodegroupTemplate(copy_flow.CopyNodegroupTemplate):
availability_zone=context["general_availability_zone"],
use_autoconfig=context['general_use_autoconfig'],
is_proxy_gateway=context["general_proxygateway"],
shares=ngt_shares)
shares=ngt_shares,
is_public=context['general_is_public'],
is_protected=context['general_is_protected'])
return True
except api_base.APIException as e:
self.error_description = str(e.message)

View File

@ -0,0 +1,141 @@
# 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 abc
import functools
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from horizon import exceptions
from horizon import forms
from horizon import tables
MESSAGE_MAPPING_PRESENT = {
'public': functools.partial(
ungettext_lazy,
u"Make public",
u"Make public"),
'private': functools.partial(
ungettext_lazy,
u"Make private",
u"Make private"),
'protected': functools.partial(
ungettext_lazy,
u"Make protected",
u"Make protected"),
'unprotected': functools.partial(
ungettext_lazy,
u"Make unprotected",
u"Make unprotected"),
}
MESSAGE_MAPPING_PAST = {
'public': functools.partial(
ungettext_lazy,
u"Made public",
u"Made public"),
'private': functools.partial(
ungettext_lazy,
u"Made private",
u"Made private"),
'protected': functools.partial(
ungettext_lazy,
u"Made protected",
u"Made protected"),
'unprotected': functools.partial(
ungettext_lazy,
u"Made unprotected",
u"Made unprotected"),
}
class RuleChangeAction(tables.BatchAction):
rule = "no-rule"
def action_present(self, count):
return MESSAGE_MAPPING_PRESENT[self.rule](count)
def action_past(self, count):
return MESSAGE_MAPPING_PAST[self.rule](count)
def action(self, request, datum_id):
try:
update_kwargs = {}
if self.rule in ['public', 'private']:
update_kwargs['is_public'] = self.rule == "public"
if self.rule in ["protected", "unprotected"]:
update_kwargs['is_protected'] = self.rule == "protected"
self.change_rule_method(request, datum_id, **update_kwargs)
except Exception as e:
exceptions.handle(request, e)
raise
class MakePublic(RuleChangeAction):
name = "make_public"
rule = "public"
@abc.abstractmethod
def change_rule_method(self, request, datum_id, **update_kwargs):
pass
class MakePrivate(RuleChangeAction):
name = "make_private"
rule = "private"
@abc.abstractmethod
def change_rule_method(self, request, datum_id, **update_kwargs):
pass
class MakeProtected(RuleChangeAction):
name = "make_protected"
rule = "protected"
@abc.abstractmethod
def change_rule_method(self, request, datum_id, **update_kwargs):
pass
class MakeUnProtected(RuleChangeAction):
name = "make_unprotected"
rule = "unprotected"
@abc.abstractmethod
def change_rule_method(self, request, datum_id, **update_kwargs):
pass
def get_is_public_form(object_type):
return forms.BooleanField(
label=_("Public"),
help_text=_("If selected, {object_type} will be shared across the "
"tenants").format(object_type=object_type),
required=False,
widget=forms.CheckboxInput(),
initial=False,
)
def get_is_protected_form(object_type):
return forms.BooleanField(
label=_("Protected"),
help_text=_("If selected, {object_type} will be protected from "
"modifications until this will be unselected").format(
object_type=object_type),
required=False,
widget=forms.CheckboxInput(),
initial=False)

View File

@ -36,13 +36,17 @@ class SaharaApiTest(test.SaharaAPITestCase):
net_id=None,
node_groups=None,
plugin_name='fake_plugin',
user_keypair_id=None) \
user_keypair_id=None,
is_public=False,
is_protected=False) \
.AndReturn({"Clusters": ['cluster1', 'cluster2']})
self.mox.ReplayAll()
ret_val = api.sahara.cluster_create(self.request,
'name',
'fake_plugin',
'1.0.0',
count=2)
count=2,
is_public=False,
is_protected=False)
self.assertEqual(2, len(ret_val['Clusters']))

View File

@ -134,6 +134,8 @@ def data(TEST):
"is_proxy_gateway": False,
"use_autoconfig": True,
"shares": [],
'is_public': False,
'is_protected': False,
}
ngt1 = node_group_templates.NodeGroupTemplate(
@ -153,6 +155,8 @@ def data(TEST):
"name": "sample-cluster-template",
"neutron_management_network": None,
"use_autoconfig": True,
'is_public': False,
'is_protected': False,
"node_groups": [
{
"count": 1,
@ -179,6 +183,8 @@ def data(TEST):
"volumes_availability_zone": None,
"use_autoconfig": True,
"is_proxy_gateway": False,
'is_public': False,
'is_protected': False,
},
{
"count": 2,
@ -201,7 +207,9 @@ def data(TEST):
"volume_local_to_instance": False,
"volumes_availability_zone": None,
"use_autoconfig": True,
"is_proxy_gateway": False
"is_proxy_gateway": False,
'is_public': False,
'is_protected': False,
}
],
"shares": [],
@ -230,6 +238,8 @@ def data(TEST):
"name": "cercluster",
"neutron_management_network": None,
"use_autoconfig": True,
"is_public": False,
"is_protected": False,
"node_groups": [
{
"count": 1,
@ -388,7 +398,9 @@ def data(TEST):
"tenant_id": "429ad8447c2d47bc8e0382d244e1d1df",
"type": "swift",
"updated_at": None,
"url": "swift://example.sahara/output"
"url": "swift://example.sahara/output",
'is_public': False,
'is_protected': False
}
data_source2_dict = {
@ -399,7 +411,9 @@ def data(TEST):
"tenant_id": "429ad8447c2d47bc8e0382d244e1d1df",
"type": "hdfs",
"updated_at": None,
"url": "hdfs://example.sahara/output"
"url": "hdfs://example.sahara/output",
'is_public': False,
'is_protected': False
}
data_source1 = data_sources.DataSources(
@ -417,7 +431,9 @@ def data(TEST):
"name": "example.pig",
"tenant_id": "429ad8447c2d47bc8e0382d244e1d1df",
"updated_at": None,
"url": "internal-db://80121dea-f8bd-4ad3-bcc7-096f4bfc722d"
"url": "internal-db://80121dea-f8bd-4ad3-bcc7-096f4bfc722d",
'is_public': False,
'is_protected': False
}
job_binary2_dict = {
@ -427,7 +443,9 @@ def data(TEST):
"name": "example with spaces.pig",
"tenant_id": "429ad8447c2d47bc8e0382d244e1d1df",
"updated_at": None,
"url": "internal-db://abcdef56-1234-abcd-abcd-defabcdaedcb"
"url": "internal-db://abcdef56-1234-abcd-abcd-defabcdaedcb",
'is_public': False,
'is_protected': False
}
job_binary3_dict = {