fuel-ui/static/plugins/vmware/vmware_models.js

319 lines
9.4 KiB
JavaScript

/*
* Copyright 2015 Mirantis, Inc.
*
* 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 _ from 'underscore';
import i18n from 'i18n';
import Backbone from 'backbone';
import models from 'models';
var VmWareModels = {};
VmWareModels.isRegularField = (field) => {
return _.includes(['text', 'password', 'checkbox', 'select', 'file'], field.type);
};
// models for testing restrictions
var restrictionModels = {};
// Test regex using regex cache
var regexCache = {};
function testRegex(regexText, value) {
if (!regexCache[regexText]) {
regexCache[regexText] = new RegExp(regexText);
}
return regexCache[regexText].test(value);
}
var BaseModel = Backbone.Model
.extend(models.superMixin)
.extend(models.cacheMixin)
.extend(models.restrictionMixin)
.extend({
constructorName: 'BaseModel',
cacheFor: 60 * 1000,
toJSON() {
return _.omit(this.attributes, 'metadata');
},
validate() {
var result = {};
_.each(this.attributes.metadata, (field) => {
if (!VmWareModels.isRegularField(field) || field.type === 'checkbox') {
return;
}
var isDisabled = this.checkRestrictions(restrictionModels, undefined, field);
if (isDisabled.result) {
return;
}
var value = this.get(field.name);
if (field.regex) {
if (!testRegex(field.regex.source, value)) {
result[field.name] = field.regex.error;
}
}
});
return _.isEmpty(result) ? null : result;
},
testRestrictions() {
var results = {
hide: {},
disable: {}
};
var metadata = this.get('metadata');
_.each(metadata, (field) => {
var disableResult = this.checkRestrictions(restrictionModels, undefined, field);
results.disable[field.name] = disableResult;
var hideResult = this.checkRestrictions(restrictionModels, 'hide', field);
results.hide[field.name] = hideResult;
});
return results;
}
});
var BaseCollection = Backbone.Collection
.extend(models.superMixin)
.extend(models.cacheMixin)
.extend({
constructorName: 'BaseCollection',
model: BaseModel,
cacheFor: 60 * 1000,
isValid() {
this.validationError = this.validate();
return this.validationError;
},
validate() {
var errors = _.compact(this.models.map((model) => {
model.isValid();
return model.validationError;
}));
return _.isEmpty(errors) ? null : errors;
},
testRestrictions() {
_.invokeMap(this.models, 'testRestrictions', restrictionModels);
},
invokeMap(path, ...args) {
_.invokeMap(this.models, path, ...args);
}
});
VmWareModels.NovaCompute = BaseModel.extend({
constructorName: 'NovaCompute',
checkEmptyTargetNode() {
var targetNode = this.get('target_node');
if (targetNode.current && targetNode.current.id === 'invalid') {
this.validationError = this.validationError || {};
this.validationError.target_node = i18n('vmware.invalid_target_node');
}
},
checkDuplicateField(keys, fieldName) {
/*jshint validthis:true */
var fieldValue = this.get(fieldName);
if (fieldValue.length > 0 && keys[fieldName] && keys[fieldName][fieldValue]) {
this.validationError = this.validationError || {};
this.validationError[fieldName] = i18n('vmware.duplicate_value');
}
keys[fieldName] = keys[fieldName] || {};
keys[fieldName][fieldValue] = true;
},
checkDuplicates(keys) {
this.checkDuplicateField(keys, 'vsphere_cluster');
this.checkDuplicateField(keys, 'service_name');
var targetNode = this.get('target_node') || {};
if (targetNode.current) {
if (targetNode.current.id && targetNode.current.id !== 'controllers' &&
keys.target_node && keys.target_node[targetNode.current.id]) {
this.validationError = this.validationError || {};
this.validationError.target_node = i18n('vmware.duplicate_value');
}
keys.target_node = keys.target_node || {};
keys.target_node[targetNode.current.id] = true;
}
}
});
var NovaComputes = BaseCollection.extend({
constructorName: 'NovaComputes',
model: VmWareModels.NovaCompute,
validate() {
this._super('validate', arguments);
var keys = {vsphere_clusters: {}, service_names: {}};
this.invokeMap('checkDuplicates', keys);
this.invokeMap('checkEmptyTargetNode');
var errors = _.compact(this.map('validationError'));
return _.isEmpty(errors) ? null : errors;
}
});
var AvailabilityZone = BaseModel.extend({
constructorName: 'AvailabilityZone',
constructor(data) {
Backbone.Model.apply(this, arguments);
if (data) {
this.set(this.parse(data));
}
},
parse(response) {
var result = {};
var metadata = response.metadata;
result.metadata = metadata;
// regular fields
_.each(metadata, (field) => {
if (VmWareModels.isRegularField(field)) {
result[field.name] = response[field.name];
}
});
// nova_computes
var novaMetadata = _.find(metadata, {name: 'nova_computes'});
var novaValues = _.clone(response.nova_computes);
novaValues = _.map(novaValues, (value) => {
value.metadata = novaMetadata.fields;
return new VmWareModels.NovaCompute(value);
});
result.nova_computes = new NovaComputes(novaValues);
return result;
},
toJSON() {
var result = _.omit(this.attributes, 'metadata', 'nova_computes');
result.nova_computes = this.get('nova_computes').toJSON();
return result;
},
validate() {
var errors = _.merge({}, BaseModel.prototype.validate.call(this));
var novaComputes = this.get('nova_computes');
novaComputes.isValid();
if (novaComputes.validationError) {
errors.nova_computes = novaComputes.validationError;
}
return _.isEmpty(errors) ? null : errors;
}
});
var AvailabilityZones = BaseCollection.extend({
constructorName: 'AvailabilityZones',
model: AvailabilityZone
});
VmWareModels.Glance = BaseModel.extend({constructorName: 'Glance'});
VmWareModels.VCenter = BaseModel.extend({
constructorName: 'VCenter',
url() {
return '/api/v1/clusters/' + this.id + '/vmware_attributes' +
(this.loadDefaults ? '/defaults' : '');
},
parse(response) {
if (!response.editable || !response.editable.metadata || !response.editable.value) {
return null;
}
var metadata = response.editable.metadata || [];
var value = response.editable.value || {};
// Availability Zone(s)
var azMetadata = _.find(metadata, {name: 'availability_zones'});
var azValues = _.clone(value.availability_zones);
azValues = _.map(azValues, (value) => {
value.metadata = azMetadata.fields;
return value;
});
// Glance
var glanceMetadata = _.find(metadata, {name: 'glance'});
var glanceValue = _.extend(_.clone(value.glance), {metadata: glanceMetadata.fields});
return {
metadata: metadata,
availability_zones: new AvailabilityZones(azValues),
glance: new VmWareModels.Glance(glanceValue)
};
},
beforeSave() {
this.get('availability_zones').each((availabilityZone) => {
availabilityZone.get('nova_computes').each((novaCompute) => {
novaCompute.set({vsphere_cluster: novaCompute.get('vsphere_cluster').trim()});
});
});
},
isFilled() {
var result = this.get('availability_zones') && this.get('glance');
return !!result;
},
toJSON() {
if (!this.isFilled()) {
return {};
}
return {
editable: {
value: {
availability_zones: this.get('availability_zones').toJSON(),
glance: this.get('glance').toJSON()
}
}
};
},
validate() {
if (!this.isFilled()) {
return null;
}
var errors = {};
_.each(this.get('metadata'), (field) => {
var model = this.get(field.name);
// do not validate disabled restrictions
var isDisabled = this.checkRestrictions(restrictionModels, undefined, field);
if (isDisabled.result) {
return;
}
model.isValid();
if (model.validationError) {
errors[field.name] = model.validationError;
}
});
// check unassigned nodes exist
var assignedNodes = {};
var availabilityZones = this.get('availability_zones') || [];
availabilityZones.each((zone) => {
var novaComputes = zone.get('nova_computes') || [];
novaComputes.each((compute) => {
var targetNode = compute.get('target_node');
assignedNodes[targetNode.current.id] = targetNode.current.label;
});
});
var unassignedNodes = restrictionModels.cluster.get('nodes').filter((node) => {
return _.includes(node.get('pending_roles'), 'compute-vmware') &&
!assignedNodes[node.get('hostname')];
});
if (unassignedNodes.length > 0) {
errors.unassigned_nodes = unassignedNodes;
}
return _.isEmpty(errors) ? null : errors;
},
setModels(models) {
restrictionModels = models;
return this;
}
});
export default VmWareModels;