Brad P. Crochet 3742ba77a7 Do not sync parameters across roles
Wholesale syncing of the parameters across roles doesn't work. There are
some parameters that can be different depending on the role. For one,
NeutronPublicInterface might be different depending on the node's role.
This patch comments out the sync. Future might involve creating a
white/blacklist for which params should/should not be synced.

Change-Id: I66be8126e0160aaa0af2f49b7d5fce705e720f52
2015-07-30 15:23:38 -04:00

287 lines
10 KiB
Python

# -*- coding: utf8 -*-
#
# 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 json
import logging
import django.forms
from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext_lazy as _
import horizon.exceptions
import horizon.forms
import horizon.messages
from tuskar_ui import api
import tuskar_ui.forms
from tuskar_ui.utils import utils
LOG = logging.getLogger(__name__)
VIRT_TYPE_CHOICES = [
('kvm', _("Baremetal (kvm)")),
('qemu', _("Virtualized (qemu)")),
]
NEUTRON_PUBLIC_INTERFACE_CHOICES = [
('em2', _("Baremetal (em2)")),
('eth0', _("Virtualized (eth0)")),
]
CINDER_ISCSI_HELPER_CHOICES = [
('tgtadm', _('tgtadm')),
('lioadm', _('lioadm')),
]
class ParameterAwareMixin(object):
parameter = None
def parameter_fields(request, prefix=None, read_only=False):
fields = SortedDict()
plan = api.tuskar.Plan.get_the_plan(request)
parameters = plan.parameter_list(include_key_parameters=False)
for p in parameters:
if prefix and not p.name.startswith(prefix):
continue
Field = django.forms.CharField
field_kwargs = {}
widget = None
if read_only:
if p.hidden:
widget = tuskar_ui.forms.StaticTextPasswordWidget
else:
widget = tuskar_ui.forms.StaticTextWidget
else:
if p.hidden:
widget = django.forms.PasswordInput(render_value=True)
elif p.parameter_type == 'number':
Field = django.forms.IntegerField
elif p.parameter_type == 'boolean':
Field = django.forms.BooleanField
elif (p.parameter_type == 'string' and
p.get_constraint_by_type('allowed_values')):
Field = django.forms.ChoiceField
field_kwargs['choices'] = [
(choice, choice) for choice in
p.get_constraint_by_type('allowed_values')['definition']]
elif (p.parameter_type in ['json', 'comma_delimited_list'] or
'Certificate' in p.name):
widget = django.forms.Textarea
fields[p.name] = Field(
required=False,
label=_parameter_label(p),
initial=p.value,
widget=widget,
**field_kwargs
)
fields[p.name].__class__ = type('ParameterAwareField',
(ParameterAwareMixin, Field), {})
fields[p.name].parameter = p
return fields
def _parameter_label(parameter):
return tuskar_ui.forms.label_with_tooltip(
parameter.label or utils.de_camel_case(parameter.stripped_name),
parameter.description)
class ServiceConfig(horizon.forms.SelfHandlingForm):
def __init__(self, *args, **kwargs):
super(ServiceConfig, self).__init__(*args, **kwargs)
self.fields.update(parameter_fields(self.request, read_only=True))
def global_fieldset(self):
return tuskar_ui.forms.fieldset(self, prefix='^(?!.*::)')
def controller_fieldset(self):
return tuskar_ui.forms.fieldset(self, prefix='Controller-1')
def compute_fieldset(self):
return tuskar_ui.forms.fieldset(self, prefix='Compute-1')
def block_storage_fieldset(self):
return tuskar_ui.forms.fieldset(self, prefix='Cinder-Storage-1')
def object_storage_fieldset(self):
return tuskar_ui.forms.fieldset(self, prefix='Swift-Storage-1')
def ceph_storage_fieldset(self):
return tuskar_ui.forms.fieldset(self, prefix='Ceph-Storage-1')
def handle():
pass
class AdvancedEditServiceConfig(ServiceConfig):
def __init__(self, *args, **kwargs):
super(AdvancedEditServiceConfig, self).__init__(*args, **kwargs)
self.fields.update(parameter_fields(self.request))
def handle(self, request, data):
plan = api.tuskar.Plan.get_the_plan(self.request)
# TODO(bcrochet): Commenting this out.
# For advanced config, we should have a whitelist of which params
# must be synced across roles.
# data = self._sync_common_params_across_roles(plan, data)
try:
plan.patch(request, plan.uuid, data)
except Exception as e:
horizon.exceptions.handle(
request,
_("Unable to update the service configuration."))
LOG.exception(e)
return False
else:
horizon.messages.success(
request,
_("Service configuration updated."))
return True
@staticmethod
def _sync_common_params_across_roles(plan, parameters_dict):
for (p_key, p_value) in parameters_dict.iteritems():
for role in plan.role_list:
role_parameter_key = (role.parameter_prefix +
api.tuskar.strip_prefix(p_key))
if role_parameter_key in parameters_dict:
parameters_dict[role_parameter_key] = p_value
return parameters_dict
class SimpleEditServiceConfig(horizon.forms.SelfHandlingForm):
virt_type = django.forms.ChoiceField(
label=_("Deployment Type"),
choices=VIRT_TYPE_CHOICES,
required=True,
help_text=_('If you are testing OpenStack in a virtual machine, '
'you must configure Compute to use qemu without KVM '
'and hardware virtualization.'))
neutron_public_interface = django.forms.ChoiceField(
label=_("Public Interface"),
choices=NEUTRON_PUBLIC_INTERFACE_CHOICES,
required=True,
help_text=_('What interface to bridge onto br-ex for network nodes. '
'If you are testing OpenStack in a virtual machine'
'you must configure interface to eth0.'))
snmp_password = django.forms.CharField(
label=_("SNMP Password"),
required=True,
help_text=_('The user password for SNMPd with readonly '
'rights running on all Overcloud nodes'),
widget=django.forms.PasswordInput(render_value=True))
cloud_name = django.forms.CharField(
label=_("Cloud name"),
required=True,
initial="overcloud",
help_text=_('The DNS name of this cloud. '
'E.g. ci-overcloud.tripleo.org'))
cinder_iscsi_helper = django.forms.ChoiceField(
label=_("Cinder ISCSI helper"),
choices=CINDER_ISCSI_HELPER_CHOICES,
required=True,
help_text=_('The iSCSI helper to use with cinder.'))
ntp_server = django.forms.CharField(
label=_("NTP server"),
required=False,
initial="",
help_text=_('Address of the NTP server. If blank, public NTP servers '
'will be used.'))
extra_config = django.forms.CharField(
label=_("Extra Config"),
required=False,
widget=django.forms.Textarea(attrs={'rows': 2}),
help_text=("Additional configuration to inject into the cluster."
"The data format of this field is JSON."
"See http://git.io/PuwLXQ for more information."))
def clean_extra_config(self):
data = self.cleaned_data['extra_config']
try:
json.loads(data)
except Exception as json_error:
raise django.forms.ValidationError(
_("%(err_msg)s"), params={'err_msg': json_error.message})
return data
@staticmethod
def _load_additional_parameters(plan, data, form_key, param_name):
params = {}
param_value = data.get(form_key)
# Set the same parameter and value in all roles.
for role in plan.role_list:
key = role.parameter_prefix + param_name
if key in [parameter.name
for parameter in role.parameter_list(plan)]:
params[key] = param_value
return params
def handle(self, request, data):
plan = api.tuskar.Plan.get_the_plan(self.request)
compute_prefix = plan.get_role_by_name('Compute').parameter_prefix
controller_prefix = plan.get_role_by_name(
'Controller').parameter_prefix
cinder_prefix = plan.get_role_by_name(
'Cinder-Storage').parameter_prefix
virt_type = data.get('virt_type')
neutron_public_interface = data.get('neutron_public_interface')
cloud_name = data.get('cloud_name')
cinder_iscsi_helper = data.get('cinder_iscsi_helper')
ntp_server = data.get('ntp_server')
parameters = {
compute_prefix + 'NovaComputeLibvirtType': virt_type,
controller_prefix + 'CinderISCSIHelper': cinder_iscsi_helper,
cinder_prefix + 'CinderISCSIHelper': cinder_iscsi_helper,
controller_prefix + 'CloudName': cloud_name,
controller_prefix + 'NeutronPublicInterface':
neutron_public_interface,
compute_prefix + 'NeutronPublicInterface':
neutron_public_interface,
controller_prefix + 'NtpServer':
ntp_server,
compute_prefix + 'NtpServer':
ntp_server,
}
parameters.update(self._load_additional_parameters(
plan, data,
'snmp_password', 'SnmpdReadonlyUserPassword'))
parameters.update(self._load_additional_parameters(
plan, data,
'extra_config', 'ExtraConfig'))
try:
plan.patch(request, plan.uuid, parameters)
except Exception as e:
horizon.exceptions.handle(
request,
_("Unable to update the service configuration."))
LOG.exception(e)
return False
else:
horizon.messages.success(
request,
_("Service configuration updated."))
return True