[Sahara] Support Cinder availability zones
Add an optional field in the node group template page. It is used for selecting the availability zone where to create volumes. Change-Id: I94a92425884fe0611b9bf7439030bd226b25f72c Implements: blueprint support-cinder-availability-zones
This commit is contained in:
parent
b6fcedb449
commit
734290410c
@ -96,18 +96,23 @@ def nodegroup_template_create(request, name, plugin_name, hadoop_version,
|
|||||||
node_processes=None, node_configs=None,
|
node_processes=None, node_configs=None,
|
||||||
floating_ip_pool=None, security_groups=None,
|
floating_ip_pool=None, security_groups=None,
|
||||||
auto_security_group=False,
|
auto_security_group=False,
|
||||||
availability_zone=False):
|
availability_zone=False,
|
||||||
return client(request).node_group_templates.create(name, plugin_name,
|
volumes_availability_zone=False):
|
||||||
hadoop_version,
|
return client(request).node_group_templates.create(
|
||||||
flavor_id, description,
|
name,
|
||||||
volumes_per_node,
|
plugin_name,
|
||||||
volumes_size,
|
hadoop_version,
|
||||||
node_processes,
|
flavor_id,
|
||||||
node_configs,
|
description,
|
||||||
floating_ip_pool,
|
volumes_per_node,
|
||||||
security_groups,
|
volumes_size,
|
||||||
auto_security_group,
|
node_processes,
|
||||||
availability_zone)
|
node_configs,
|
||||||
|
floating_ip_pool,
|
||||||
|
security_groups,
|
||||||
|
auto_security_group,
|
||||||
|
availability_zone,
|
||||||
|
volumes_availability_zone)
|
||||||
|
|
||||||
|
|
||||||
def nodegroup_template_list(request):
|
def nodegroup_template_list(request):
|
||||||
@ -132,20 +137,24 @@ def nodegroup_template_update(request, ngt_id, name, plugin_name,
|
|||||||
volumes_size=None, node_processes=None,
|
volumes_size=None, node_processes=None,
|
||||||
node_configs=None, floating_ip_pool=None,
|
node_configs=None, floating_ip_pool=None,
|
||||||
security_groups=None, auto_security_group=False,
|
security_groups=None, auto_security_group=False,
|
||||||
availability_zone=False):
|
availability_zone=False,
|
||||||
return client(request).node_group_templates.update(ngt_id, name,
|
volumes_availability_zone=False):
|
||||||
plugin_name,
|
return client(request).node_group_templates.update(
|
||||||
hadoop_version,
|
ngt_id,
|
||||||
flavor_id,
|
name,
|
||||||
description,
|
plugin_name,
|
||||||
volumes_per_node,
|
hadoop_version,
|
||||||
volumes_size,
|
flavor_id,
|
||||||
node_processes,
|
description,
|
||||||
node_configs,
|
volumes_per_node,
|
||||||
floating_ip_pool,
|
volumes_size,
|
||||||
security_groups,
|
node_processes,
|
||||||
auto_security_group,
|
node_configs,
|
||||||
availability_zone)
|
floating_ip_pool,
|
||||||
|
security_groups,
|
||||||
|
auto_security_group,
|
||||||
|
availability_zone,
|
||||||
|
volumes_availability_zone)
|
||||||
|
|
||||||
|
|
||||||
def cluster_template_create(request, name, plugin_name, hadoop_version,
|
def cluster_template_create(request, name, plugin_name, hadoop_version,
|
||||||
|
@ -71,6 +71,10 @@
|
|||||||
<dd>{{ template.volumes_per_node }}</dd>
|
<dd>{{ template.volumes_per_node }}</dd>
|
||||||
<dt>{% trans "Volumes size" %}</dt>
|
<dt>{% trans "Volumes size" %}</dt>
|
||||||
<dd>{{ template.volumes_size }}</dd>
|
<dd>{{ template.volumes_size }}</dd>
|
||||||
|
{% if template.volumes_availability_zone %}
|
||||||
|
<dt>{% trans "Volumes Availability Zone" %}</dt>
|
||||||
|
<dd>{{ template.volumes_availability_zone }}</dd>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<h6>{% trans "Ephemeral drive" %}</h6>
|
<h6>{% trans "Ephemeral drive" %}</h6>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -61,9 +61,11 @@
|
|||||||
if (show) {
|
if (show) {
|
||||||
$(".volume_per_node_field").closest(".form-group").show();
|
$(".volume_per_node_field").closest(".form-group").show();
|
||||||
$(".volume_size_field").closest(".form-group").show();
|
$(".volume_size_field").closest(".form-group").show();
|
||||||
|
$(".volumes_availability_zone_field").closest(".form-group").show();
|
||||||
} else {
|
} else {
|
||||||
$(".volume_per_node_field").closest(".form-group").hide();
|
$(".volume_per_node_field").closest(".form-group").hide();
|
||||||
$(".volume_size_field").closest(".form-group").hide();
|
$(".volume_size_field").closest(".form-group").hide();
|
||||||
|
$(".volumes_availability_zone_field").closest(".form-group").hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +143,7 @@ class DataProcessingNodeGroupTests(test.TestCase):
|
|||||||
'flavor_id': flavor.id,
|
'flavor_id': flavor.id,
|
||||||
'volumes_per_node': None,
|
'volumes_per_node': None,
|
||||||
'volumes_size': None,
|
'volumes_size': None,
|
||||||
|
'volumes_availability_zone': None,
|
||||||
'node_processes': ['namenode'],
|
'node_processes': ['namenode'],
|
||||||
'node_configs': {},
|
'node_configs': {},
|
||||||
'floating_ip_pool': None,
|
'floating_ip_pool': None,
|
||||||
@ -165,6 +166,7 @@ class DataProcessingNodeGroupTests(test.TestCase):
|
|||||||
'storage': 'ephemeral_drive',
|
'storage': 'ephemeral_drive',
|
||||||
'volumes_per_node': 0,
|
'volumes_per_node': 0,
|
||||||
'volumes_size': 0,
|
'volumes_size': 0,
|
||||||
|
'volumes_availability_zone': None,
|
||||||
'floating_ip_pool': None,
|
'floating_ip_pool': None,
|
||||||
'security_autogroup': True,
|
'security_autogroup': True,
|
||||||
'processes': 'HDFS:namenode'})
|
'processes': 'HDFS:namenode'})
|
||||||
|
@ -64,6 +64,8 @@ class CopyNodegroupTemplate(create_flow.ConfigureNodegroupTemplate):
|
|||||||
g_fields["storage"].initial = storage
|
g_fields["storage"].initial = storage
|
||||||
g_fields["volumes_per_node"].initial = volumes_per_node
|
g_fields["volumes_per_node"].initial = volumes_per_node
|
||||||
g_fields["volumes_size"].initial = volumes_size
|
g_fields["volumes_size"].initial = volumes_size
|
||||||
|
g_fields["volumes_availability_zone"].initial = \
|
||||||
|
template.volumes_availability_zone
|
||||||
|
|
||||||
if template.floating_ip_pool:
|
if template.floating_ip_pool:
|
||||||
g_fields['floating_ip_pool'].initial = template.floating_ip_pool
|
g_fields['floating_ip_pool'].initial = template.floating_ip_pool
|
||||||
|
@ -28,6 +28,8 @@ from openstack_dashboard.dashboards.project.data_processing.utils \
|
|||||||
import workflow_helpers
|
import workflow_helpers
|
||||||
from openstack_dashboard.dashboards.project.instances \
|
from openstack_dashboard.dashboards.project.instances \
|
||||||
import utils as nova_utils
|
import utils as nova_utils
|
||||||
|
from openstack_dashboard.dashboards.project.volumes \
|
||||||
|
import utils as cinder_utils
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -70,6 +72,13 @@ class GeneralConfigAction(workflows.Action):
|
|||||||
widget=forms.TextInput(attrs={"class": "volume_size_field"})
|
widget=forms.TextInput(attrs={"class": "volume_size_field"})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
volumes_availability_zone = forms.ChoiceField(
|
||||||
|
label=_("Volumes Availability Zone"),
|
||||||
|
help_text=_("Create volumes in this availability zone."),
|
||||||
|
required=False,
|
||||||
|
widget=forms.Select(attrs={"class": "volumes_availability_zone_field"})
|
||||||
|
)
|
||||||
|
|
||||||
hidden_configure_field = forms.CharField(
|
hidden_configure_field = forms.CharField(
|
||||||
required=False,
|
required=False,
|
||||||
widget=forms.HiddenInput(attrs={"class": "hidden_configure_field"}))
|
widget=forms.HiddenInput(attrs={"class": "hidden_configure_field"}))
|
||||||
@ -137,6 +146,13 @@ class GeneralConfigAction(workflows.Action):
|
|||||||
if az.zoneState['available']])
|
if az.zoneState['available']])
|
||||||
return az_list
|
return az_list
|
||||||
|
|
||||||
|
def populate_volumes_availability_zone_choices(self, request, context):
|
||||||
|
az_list = [(None, _('No availability zone specified'))]
|
||||||
|
az_list.extend([(az.zoneName, az.zoneName)
|
||||||
|
for az in cinder_utils.availability_zone_list(request)
|
||||||
|
if az.zoneState['available']])
|
||||||
|
return az_list
|
||||||
|
|
||||||
def get_help_text(self):
|
def get_help_text(self):
|
||||||
extra = dict()
|
extra = dict()
|
||||||
plugin, hadoop_version = (
|
plugin, hadoop_version = (
|
||||||
@ -275,10 +291,13 @@ class ConfigureNodegroupTemplate(workflow_helpers.ServiceParametersWorkflow,
|
|||||||
|
|
||||||
volumes_per_node = None
|
volumes_per_node = None
|
||||||
volumes_size = None
|
volumes_size = None
|
||||||
|
volumes_availability_zone = None
|
||||||
|
|
||||||
if context["general_storage"] == "cinder_volume":
|
if context["general_storage"] == "cinder_volume":
|
||||||
volumes_per_node = context["general_volumes_per_node"]
|
volumes_per_node = context["general_volumes_per_node"]
|
||||||
volumes_size = context["general_volumes_size"]
|
volumes_size = context["general_volumes_size"]
|
||||||
|
volumes_availability_zone = \
|
||||||
|
context["general_volumes_availability_zone"]
|
||||||
|
|
||||||
saharaclient.nodegroup_template_create(
|
saharaclient.nodegroup_template_create(
|
||||||
request,
|
request,
|
||||||
@ -289,6 +308,7 @@ class ConfigureNodegroupTemplate(workflow_helpers.ServiceParametersWorkflow,
|
|||||||
flavor_id=context["general_flavor"],
|
flavor_id=context["general_flavor"],
|
||||||
volumes_per_node=volumes_per_node,
|
volumes_per_node=volumes_per_node,
|
||||||
volumes_size=volumes_size,
|
volumes_size=volumes_size,
|
||||||
|
volumes_availability_zone=volumes_availability_zone,
|
||||||
node_processes=processes,
|
node_processes=processes,
|
||||||
node_configs=configs_dict,
|
node_configs=configs_dict,
|
||||||
floating_ip_pool=context.get("general_floating_ip_pool"),
|
floating_ip_pool=context.get("general_floating_ip_pool"),
|
||||||
|
29
openstack_dashboard/dashboards/project/volumes/utils.py
Normal file
29
openstack_dashboard/dashboards/project/volumes/utils.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# 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 _
|
||||||
|
|
||||||
|
from horizon import exceptions
|
||||||
|
|
||||||
|
from openstack_dashboard import api
|
||||||
|
|
||||||
|
|
||||||
|
def availability_zone_list(request):
|
||||||
|
"""Utility method to retrieve a list of availability zones."""
|
||||||
|
try:
|
||||||
|
if api.cinder.extension_supported(request, 'AvailabilityZones'):
|
||||||
|
return api.cinder.availability_zone_list(request)
|
||||||
|
return []
|
||||||
|
except Exception:
|
||||||
|
exceptions.handle(request,
|
||||||
|
_('Unable to retrieve volumes availability zones.'))
|
||||||
|
return []
|
@ -126,7 +126,8 @@ def data(TEST):
|
|||||||
"volume_mount_prefix": "/volumes/disk",
|
"volume_mount_prefix": "/volumes/disk",
|
||||||
"volumes_per_node": 0,
|
"volumes_per_node": 0,
|
||||||
"volumes_size": 0,
|
"volumes_size": 0,
|
||||||
"security_groups": []
|
"security_groups": [],
|
||||||
|
"volumes_availability_zone": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
ngt1 = node_group_templates.NodeGroupTemplate(
|
ngt1 = node_group_templates.NodeGroupTemplate(
|
||||||
@ -165,7 +166,8 @@ def data(TEST):
|
|||||||
"updated_at": None,
|
"updated_at": None,
|
||||||
"volume_mount_prefix": "/volumes/disk",
|
"volume_mount_prefix": "/volumes/disk",
|
||||||
"volumes_per_node": 0,
|
"volumes_per_node": 0,
|
||||||
"volumes_size": 0
|
"volumes_size": 0,
|
||||||
|
"volumes_availability_zone": None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"count": 2,
|
"count": 2,
|
||||||
@ -183,7 +185,8 @@ def data(TEST):
|
|||||||
"updated_at": None,
|
"updated_at": None,
|
||||||
"volume_mount_prefix": "/volumes/disk",
|
"volume_mount_prefix": "/volumes/disk",
|
||||||
"volumes_per_node": 0,
|
"volumes_per_node": 0,
|
||||||
"volumes_size": 0
|
"volumes_size": 0,
|
||||||
|
"volumes_availability_zone": None,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plugin_name": "vanilla",
|
"plugin_name": "vanilla",
|
||||||
@ -243,7 +246,8 @@ def data(TEST):
|
|||||||
"volume_mount_prefix": "/volumes/disk",
|
"volume_mount_prefix": "/volumes/disk",
|
||||||
"volumes_per_node": 0,
|
"volumes_per_node": 0,
|
||||||
"volumes_size": 0,
|
"volumes_size": 0,
|
||||||
"security_groups": []
|
"security_groups": [],
|
||||||
|
"volumes_availability_zone": None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"count": 2,
|
"count": 2,
|
||||||
@ -284,7 +288,8 @@ def data(TEST):
|
|||||||
"volume_mount_prefix": "/volumes/disk",
|
"volume_mount_prefix": "/volumes/disk",
|
||||||
"volumes_per_node": 0,
|
"volumes_per_node": 0,
|
||||||
"volumes_size": 0,
|
"volumes_size": 0,
|
||||||
"security_groups": ["b7857890-09bf-4ee0-a0d5-322d7a6978bf"]
|
"security_groups": ["b7857890-09bf-4ee0-a0d5-322d7a6978bf"],
|
||||||
|
"volumes_availability_zone": None,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plugin_name": "vanilla",
|
"plugin_name": "vanilla",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user