diff --git a/sahara_dashboard/api/sahara.py b/sahara_dashboard/api/sahara.py index 8803b535..4733010c 100644 --- a/sahara_dashboard/api/sahara.py +++ b/sahara_dashboard/api/sahara.py @@ -134,6 +134,7 @@ def nodegroup_template_create(request, name, plugin_name, hadoop_version, availability_zone=False, volumes_availability_zone=False, volume_type=None, + image_id=None, is_proxy_gateway=False, volume_local_to_instance=False, use_autoconfig=None, @@ -156,6 +157,7 @@ def nodegroup_template_create(request, name, plugin_name, hadoop_version, availability_zone=availability_zone, volumes_availability_zone=volumes_availability_zone, volume_type=volume_type, + image_id=image_id, is_proxy_gateway=is_proxy_gateway, volume_local_to_instance=volume_local_to_instance, use_autoconfig=use_autoconfig, @@ -194,7 +196,8 @@ def nodegroup_template_update(request, ngt_id, name, plugin_name, use_autoconfig=None, shares=None, is_protected=None, - is_public=None): + is_public=None, + image_id=None): return client(request).node_group_templates.update( ng_template_id=ngt_id, name=name, @@ -217,7 +220,8 @@ def nodegroup_template_update(request, ngt_id, name, plugin_name, use_autoconfig=use_autoconfig, shares=shares, is_public=is_public, - is_protected=is_protected) + is_protected=is_protected, + image_id=image_id) def cluster_template_create(request, name, plugin_name, hadoop_version, diff --git a/sahara_dashboard/content/data_processing/clusters/clusters/workflows/create.py b/sahara_dashboard/content/data_processing/clusters/clusters/workflows/create.py index dd02c1a4..31125f93 100644 --- a/sahara_dashboard/content/data_processing/clusters/clusters/workflows/create.py +++ b/sahara_dashboard/content/data_processing/clusters/clusters/workflows/create.py @@ -118,27 +118,7 @@ class GeneralConfigAction(workflows.Action): ) def populate_image_choices(self, request, context): - try: - all_images = saharaclient.image_list(request) - - plugin, hadoop_version = whelpers.\ - get_plugin_and_hadoop_version(request) - - details = saharaclient.plugin_get_version_details(request, - plugin, - hadoop_version) - - choices = [(image.id, image.name) for image in all_images - if (set(details.required_image_tags). - issubset(set(image.tags)))] - except Exception: - exceptions.handle(request, - _("Unable to fetch image choices.")) - choices = [] - if not choices: - choices.append(("", _("No Images Available"))) - - return choices + return whelpers.populate_image_choices(self, request, context) def populate_keypair_choices(self, request, context): try: @@ -236,13 +216,13 @@ class ConfigureCluster(whelpers.StatusFormatMixin, workflows.Workflow): cluster_template_id = context["general_cluster_template"] or None user_keypair = context["general_keypair"] or None - + image_id = context["general_image"] or None saharaclient.cluster_create( request, context["general_cluster_name"], plugin, hadoop_version, cluster_template_id=cluster_template_id, - default_image_id=context["general_image"], + default_image_id=image_id, description=context["general_description"], node_groups=node_groups, user_keypair_id=user_keypair, diff --git a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/tabs.py b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/tabs.py index 4701a2e5..2ab68713 100644 --- a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/tabs.py +++ b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/tabs.py @@ -85,11 +85,22 @@ class GeneralTab(tabs.Tab): exceptions.handle(request, _("Unable to fetch floating ip pools.")) + base_image_name = None + if template.image_id: + try: + base_image_name = saharaclient.image_get( + request, template.image_id).name + except Exception: + exceptions.handle(request, + _("Unable to fetch Base Image with id: %s.") + % template.image_id) + security_groups = helpers.get_security_groups( request, template.security_groups) return {"template": template, "flavor": flavor, "floating_ip_pool_name": floating_ip_pool_name, + "base_image_name": base_image_name, "security_groups": security_groups} def _get_floating_ip_pool_name(self, request, pool_id): diff --git a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/tests.py b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/tests.py index 791fca42..f8694b91 100644 --- a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/tests.py +++ b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/tests.py @@ -176,6 +176,7 @@ class DataProcessingNodeGroupTests(test.TestCase): 'node_configs': {}, 'floating_ip_pool': None, 'security_groups': [], + 'image_id': None, 'auto_security_group': True, 'availability_zone': None, 'is_proxy_gateway': False, @@ -281,7 +282,7 @@ class DataProcessingNodeGroupTests(test.TestCase): shares=[], is_protected=False, is_public=False, - ).AndReturn(True) + image_id=ngt.image_id).AndReturn(True) self.mox.ReplayAll() diff --git a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/copy.py b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/copy.py index 77ae7ed1..b5122186 100644 --- a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/copy.py +++ b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/copy.py @@ -83,6 +83,7 @@ class CopyNodegroupTemplate(create_flow.ConfigureNodegroupTemplate): 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 + g_fields["image"].initial = self.template.image_id if self.template.floating_ip_pool: g_fields['floating_ip_pool'].initial = ( diff --git a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/create.py b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/create.py index a4089ea9..ed34748e 100644 --- a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/create.py +++ b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/create.py @@ -39,6 +39,8 @@ from sahara_dashboard.content.data_processing.utils \ from sahara_dashboard.content.data_processing.utils \ import workflow_helpers +BASE_IMAGE_URL = "horizon:project:data_processing.clusters:register" + class GeneralConfigAction(workflows.Action): nodegroup_name = forms.CharField(label=_("Template Name")) @@ -121,6 +123,10 @@ class GeneralConfigAction(workflows.Action): }) ) + image = forms.DynamicChoiceField(label=_("Base Image"), + required=False, + add_item_link=BASE_IMAGE_URL) + hidden_configure_field = forms.CharField( required=False, widget=forms.HiddenInput(attrs={"class": "hidden_configure_field"})) @@ -216,6 +222,10 @@ class GeneralConfigAction(workflows.Action): if az.zoneState['available']]) return az_list + def populate_image_choices(self, request, context): + return workflow_helpers.populate_image_choices(self, request, context, + empty_choice=True) + def get_help_text(self): extra = dict() plugin, hadoop_version = ( @@ -500,6 +510,8 @@ class ConfigureNodegroupTemplate(workflow_helpers.ServiceParametersWorkflow, ngt_shares = context.get('ngt_shares', []) + image_id = context["general_image"] or None + ngt = saharaclient.nodegroup_template_create( request, name=context["general_nodegroup_name"], @@ -522,8 +534,8 @@ class ConfigureNodegroupTemplate(workflow_helpers.ServiceParametersWorkflow, use_autoconfig=context['general_use_autoconfig'], shares=ngt_shares, is_public=context['general_is_public'], - is_protected=context['general_is_protected'] - ) + is_protected=context['general_is_protected'], + image_id=image_id) hlps = helpers.Helpers(request) if hlps.is_from_guide(): diff --git a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/edit.py b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/edit.py index 3cfd76cf..3d7c89bf 100644 --- a/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/edit.py +++ b/sahara_dashboard/content/data_processing/clusters/nodegroup_templates/workflows/edit.py @@ -77,6 +77,8 @@ class EditNodegroupTemplate(copy_flow.CopyNodegroupTemplate): ngt_shares = context.get('ngt_shares', []) + image_id = context["general_image"] or None + saharaclient.nodegroup_template_update( request=request, ngt_id=self.template_id, @@ -100,7 +102,8 @@ class EditNodegroupTemplate(copy_flow.CopyNodegroupTemplate): is_proxy_gateway=context["general_proxygateway"], shares=ngt_shares, is_public=context['general_is_public'], - is_protected=context['general_is_protected']) + is_protected=context['general_is_protected'], + image_id=image_id) return True except api_base.APIException as e: self.error_description = str(e.message) diff --git a/sahara_dashboard/content/data_processing/clusters/templates/nodegroup_templates/_details.html b/sahara_dashboard/content/data_processing/clusters/templates/nodegroup_templates/_details.html index 32da0e52..4ba08740 100644 --- a/sahara_dashboard/content/data_processing/clusters/templates/nodegroup_templates/_details.html +++ b/sahara_dashboard/content/data_processing/clusters/templates/nodegroup_templates/_details.html @@ -14,6 +14,12 @@
{{ template.is_public|yesno }}
{% trans "Protected" %}
{{ template.is_protected|yesno }}
+
{% trans "Base Image" %}
+ {% if template.image_id and base_image_name %} +
{{ base_image_name }}
+ {% else %} +
{% trans "No image specified" %}
+ {% endif %}
diff --git a/sahara_dashboard/content/data_processing/utils/workflow_helpers.py b/sahara_dashboard/content/data_processing/utils/workflow_helpers.py index b4169aca..ab12ec95 100644 --- a/sahara_dashboard/content/data_processing/utils/workflow_helpers.py +++ b/sahara_dashboard/content/data_processing/utils/workflow_helpers.py @@ -18,10 +18,13 @@ from django.utils import safestring from django.utils.translation import ugettext_lazy as _ import six +from horizon import exceptions from horizon import forms from horizon import workflows from openstack_dashboard.api import network +from sahara_dashboard.api import sahara as saharaclient + LOG = logging.getLogger(__name__) @@ -216,6 +219,30 @@ def clean_node_group(node_group): return node_group_copy +def populate_image_choices(self, request, context, empty_choice=False): + try: + all_images = saharaclient.image_list(request) + + plugin, hadoop_version = get_plugin_and_hadoop_version(request) + + details = saharaclient.plugin_get_version_details(request, + plugin, + hadoop_version) + choices = [(image.id, image.name) for image in all_images + if (set(details.required_image_tags). + issubset(set(image.tags)))] + except Exception: + exceptions.handle(request, + _("Unable to fetch image choices.")) + choices = [] + if empty_choice: + choices = [(None, _('No image specified'))] + choices + if not choices: + choices.append(("", _("No Images Available"))) + + return choices + + class PluginAndVersionMixin(object): def _generate_plugin_version_fields(self, sahara): plugins = sahara.plugins.list()