diff --git a/muranodashboard/datagrids.py b/muranodashboard/datagrids.py index 293697268..2312210d8 100644 --- a/muranodashboard/datagrids.py +++ b/muranodashboard/datagrids.py @@ -53,8 +53,8 @@ class RadioColumn(Column): class NodeDataGrid(DataGrid): name = Column('Node', sortable=False) - is_sync = CheckColumn('Sync') - is_primary = RadioColumn('Primary') + isSync = CheckColumn('Sync') + isMaster = RadioColumn('Primary') def __init__(self, request, data): self.pk = PK() @@ -68,7 +68,7 @@ class NodeDataGrid(DataGrid): super(NodeDataGrid, self).__init__(request, FakeQuerySet( Node, items=items), optimize_sorts=False) self.default_sort = [] - self.default_columns = ['name', 'is_sync', 'is_primary'] + self.default_columns = ['name', 'isSync', 'isMaster'] # hack def load_state(self, render_context=None): diff --git a/muranodashboard/models.py b/muranodashboard/models.py index 121ae5e99..6b03d79ef 100644 --- a/muranodashboard/models.py +++ b/muranodashboard/models.py @@ -73,6 +73,5 @@ class FakeQuerySet(EmptyQuerySet): class Node(models.Model): id = models.IntegerField(primary_key=True) name = models.CharField(max_length=20) - is_primary = models.BooleanField(default=False) - is_sync = models.BooleanField(default=False) - is_async = models.BooleanField(default=False) + isMaster = models.BooleanField(default=False) + isSync = models.BooleanField(default=False) diff --git a/muranodashboard/panel/services/7-mssqlcluster.yaml b/muranodashboard/panel/services/7-mssqlcluster.yaml index c3cf0c5a8..86bc995b6 100644 --- a/muranodashboard/panel/services/7-mssqlcluster.yaml +++ b/muranodashboard/panel/services/7-mssqlcluster.yaml @@ -6,7 +6,15 @@ description: >- Microsoft SQL Failover Cluster Server unitTemplates: - - {} + - isMaster: true + isSync: true + name: 'node#' + - isMaster: false + isSync: true + name: 'node#' + - isMaster: false + isSync: false + name: 'node#' forms: - serviceConfiguration: @@ -130,7 +138,7 @@ forms: minValue: 2 maxValue: 5 initial: 2 - attributeNames: units + attributeNames: false helpText: Enter an integer value between 2 and 5 description: Microsoft SQL Failover Cluster includes up to 5 instances. - name: unitNamingPattern @@ -153,6 +161,7 @@ forms: - name: nodes type: datagrid label: Nodes + initial: {YAQL: $.clusterConfiguration.dcInstances} description: >- Configure cluster instances. Cluster node quantity can be set with 'Add' and 'Remove' buttons. Configure Sync mode by diff --git a/muranodashboard/panel/services/fields.py b/muranodashboard/panel/services/fields.py index f3ce3d7de..db48032b5 100644 --- a/muranodashboard/panel/services/fields.py +++ b/muranodashboard/panel/services/fields.py @@ -30,10 +30,10 @@ import copy def with_request(func): - def update(self, initial): + def update(self, initial, **kwargs): request = initial.get('request') if request: - func(self, request, initial) + func(self, request, **kwargs) else: raise forms.ValidationError("Can't get a request information") return update @@ -128,14 +128,27 @@ class InstanceCountField(IntegerField): def postclean(self, form, data): value = [] if hasattr(self, 'value'): + templates = form.get_unit_templates(data) for dc in range(self.value): - templates = form.get_unit_templates(data) if dc < len(templates) - 1: - value.append(templates[dc]) + template = templates[dc] else: - value.append(templates[-1]) + template = templates[-1] + value.append(self.interpolate_number(template, dc + 1)) return value + @staticmethod + def interpolate_number(spec, number): + """Replaces all '#' occurrences with given number.""" + def interpolate(spec): + if type(spec) == dict: + return dict((k, interpolate(v)) for (k, v) in spec.iteritems()) + elif type(spec) in (str, unicode) and '#' in spec: + return spec.replace('#', '{0}').format(number) + else: + return spec + return interpolate(spec) + class DataGridField(forms.MultiValueField, CustomPropertiesField): def __init__(self, *args, **kwargs): @@ -148,16 +161,12 @@ class DataGridField(forms.MultiValueField, CustomPropertiesField): return data_list[1] @with_request - def update(self, request, initial): + def update(self, request, **kwargs): self.widget.update_request(request) - nodes = [] - instance_count = initial.get('instance_count') - if instance_count: - for index in xrange(instance_count): - nodes.append({'name': 'node' + str(index + 1), - 'is_sync': index < 2, - 'is_primary': index == 0}) - self.initial = json.dumps(nodes) + # hack to use json string instead of python dict get by YAQL + data = kwargs['form'].service.cleaned_data + data['clusterConfiguration']['dcInstances'] = json.dumps( + data['clusterConfiguration']['dcInstances']) class ChoiceField(forms.ChoiceField, CustomPropertiesField): @@ -166,7 +175,7 @@ class ChoiceField(forms.ChoiceField, CustomPropertiesField): class DomainChoiceField(ChoiceField): @with_request - def update(self, request, initial): + def update(self, request, **kwargs): self.choices = [("", "Not in domain")] link = request.__dict__['META']['HTTP_REFERER'] environment_id = re.search( @@ -179,7 +188,7 @@ class DomainChoiceField(ChoiceField): class FlavorChoiceField(ChoiceField): @with_request - def update(self, request, initial): + def update(self, request, **kwargs): self.choices = [(flavor.name, flavor.name) for flavor in novaclient(request).flavors.list()] for flavor in self.choices: @@ -190,7 +199,7 @@ class FlavorChoiceField(ChoiceField): class ImageChoiceField(ChoiceField): @with_request - def update(self, request, initial): + def update(self, request, **kwargs): try: # public filter removed images, _more = glance.image_list_detailed(request) @@ -227,7 +236,7 @@ class ImageChoiceField(ChoiceField): class AZoneChoiceField(ChoiceField): @with_request - def update(self, request, initial): + def update(self, request, **kwargs): try: availability_zones = novaclient(request).availability_zones.\ list(detailed=False) @@ -272,7 +281,7 @@ class ClusterIPField(CharField): return perform_checking @with_request - def update(self, request, initial): + def update(self, request, **kwargs): try: network_list = novaclient(request).networks.list() ip_ranges = [network.cidr for network in network_list] diff --git a/muranodashboard/panel/services/forms.py b/muranodashboard/panel/services/forms.py index 63c22c913..a8379f8a0 100644 --- a/muranodashboard/panel/services/forms.py +++ b/muranodashboard/panel/services/forms.py @@ -40,7 +40,7 @@ class UpdatableFieldsForm(forms.Form): for name, field in self.fields.iteritems(): if hasattr(field, 'update'): - field.update(self.initial) + field.update(self.initial, form=self) if not field.required: field.widget.attrs['placeholder'] = 'Optional' diff --git a/muranodashboard/panel/views.py b/muranodashboard/panel/views.py index 28c7d375a..5805145a3 100644 --- a/muranodashboard/panel/views.py +++ b/muranodashboard/panel/views.py @@ -61,13 +61,9 @@ class Wizard(ModalFormMixin, SessionWizardView): for form in form_list[1:]: form.extract_attributes(attributes) - # hack to fill units with data from nodes datagrid + # hack to destringify nodes into units if 'nodes' in attributes: - units = [] - for node in json.loads(attributes['nodes']): - units.append({'isMaster': node['is_primary'], - 'isSync': node['is_sync']}) - attributes['units'] = units + attributes['units'] = json.loads(attributes['nodes']) del attributes['nodes'] try: @@ -80,8 +76,8 @@ class Wizard(ModalFormMixin, SessionWizardView): except Exception: redirect = reverse("horizon:project:murano:index") exceptions.handle(self.request, - _('Sorry, you can\'t create service right now.', - redirect=redirect)) + _('Sorry, you can\'t create service right now.'), + redirect=redirect) else: message = "The %s service successfully created." % slug messages.success(self.request, message) @@ -91,14 +87,6 @@ class Wizard(ModalFormMixin, SessionWizardView): init_dict = {} if step != 'service_choice': init_dict['request'] = self.request - - # hack to pass number of nodes from one form to another - if step == 'ms-sql-server-cluster-2': - form_id = 'ms-sql-server-cluster-1' - form_data = self.storage.data['step_data'].get(form_id, {}) - instance_count = form_data.get(form_id + '-dcInstances') - if instance_count: - init_dict['instance_count'] = int(instance_count[0]) return self.initial_dict.get(step, init_dict) def get_context_data(self, form, **kwargs): diff --git a/muranodashboard/static/muranodashboard/js/datagridfield.js b/muranodashboard/static/muranodashboard/js/datagridfield.js index a6d527eb9..f3c807b75 100644 --- a/muranodashboard/static/muranodashboard/js/datagridfield.js +++ b/muranodashboard/static/muranodashboard/js/datagridfield.js @@ -122,8 +122,8 @@ $(function() { } data.push({ name: trimLabel($(tr).children().eq(0).text()), - is_sync: getInputVal($(tr).children().eq(1)), - is_primary: getInputVal($(tr).children().eq(2)) + isSync: getInputVal($(tr).children().eq(1)), + isMaster: getInputVal($(tr).children().eq(2)) }) }); $('input.gridfield-hidden').val(JSON.stringify(data));