horizon/openstack_dashboard/static/app/core/images/steps/create-volume/create-volume.controller.sp...

467 lines
14 KiB
JavaScript

/**
*
* 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.
*/
(function () {
'use strict';
describe('horizon.app.core.images.controller.CreateVolumeController', function () {
var controller, quotaChartDefaults, $scope, $filter, getAbsoluteLimitsSpy, nova;
var cinder = {
getVolumeTypes: function() {
return {
success: function(callback) {
return callback({items: [{name: 'volumeType'}, {name: 'lvmdriver-1'}]});
}
};
},
getDefaultVolumeType: function() {
return {
success: function(callback) {
return callback({name: 'lvmdriver-1'});
}
};
},
getAbsoluteLimits: function() {
return;
}
};
beforeEach(module('horizon.app.core.images'));
beforeEach(module('horizon.framework.widgets.charts'));
beforeEach(module('horizon.framework.util.filters'));
beforeEach(inject(function ($injector, _$rootScope_, _$filter_) {
nova = {
getAvailabilityZones: function() {
return {
success: function(callback) {
return callback({ items: [{zoneName: 'zone1'}] });
}
};
}
};
$scope = _$rootScope_.$new();
$scope.image = {
name: 'ImageName',
size: 1024
};
$scope.volumeForm = {
$setValidity : function() {
return;
}
};
controller = $injector.get('$controller');
quotaChartDefaults = $injector.get('horizon.framework.widgets.charts.quotaChartDefaults');
$filter = _$filter_;
getAbsoluteLimitsSpy = spyOn(cinder, 'getAbsoluteLimits');
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 20,
totalVolumesUsed: 10,
maxTotalVolumes: 50,
totalGigabytesUsed: 10
});
}
});
spyOn($scope, '$watch').and.callThrough();
spyOn($scope, '$emit').and.callThrough();
spyOn($scope.volumeForm, '$setValidity');
}));
function createController() {
return controller('horizon.app.core.images.steps.CreateVolumeController', {
$scope: $scope,
$filter: $filter,
'horizon.app.core.openstack-service-api.cinder' : cinder,
'horizon.app.core.openstack-service-api.nova' : nova,
'horizon.framework.widgets.charts.quotaChartDefaults': quotaChartDefaults
});
}
it('should initialize default values using cinder and nova apis', function() {
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 2,
totalVolumesUsed: 1,
maxTotalVolumes: 5,
totalGigabytesUsed: 1
});
}
});
var ctrl = createController();
expect(ctrl.volumeTypes).toEqual([{name: 'volumeType'}, {name: 'lvmdriver-1'}]);
expect(ctrl.availabilityZones).toEqual(['zone1']);
expect(ctrl.image).toEqual({
name: 'ImageName',
size: 1024
});
expect(ctrl.sourceImage).toEqual('ImageName (1.00 KB)');
expect(ctrl.volume.size).toEqual(1);
expect(ctrl.volumeType).toEqual({name: 'lvmdriver-1'});
expect(ctrl.maxTotalVolumeGigabytes).toEqual(2);
expect(ctrl.maxTotalVolumes).toEqual(5);
expect(ctrl.totalVolumesUsed).toEqual(1);
});
it('should setup the storage graph with default values', function() {
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 2,
totalVolumesUsed: 1,
maxTotalVolumes: 5,
totalGigabytesUsed: 1
});
}
});
var ctrl = createController();
var graph = ctrl.storageQuota;
expect(graph.title).toEqual('Volume and Snapshot Quota (GB)');
expect(graph.maxLimit).toEqual(2);
expect(graph.label).toEqual('100%');
var current = graph.data[0];
expect(current.label).toEqual('Current Usage');
expect(current.value).toEqual(1);
expect(current.colorClass).toEqual('usage');
var added = graph.data[1];
expect(added.label).toEqual('Added');
expect(added.value).toEqual(1);
expect(added.colorClass).toEqual('added');
var remaining = graph.data[2];
expect(remaining.label).toEqual('Remaining');
expect(remaining.value).toEqual(0);
expect(remaining.colorClass).toEqual('remaining');
});
it('should setup the volume quota instance graph with default values', function() {
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 2,
totalVolumesUsed: 1,
maxTotalVolumes: 5,
totalGigabytesUsed: 1
});
}
});
var ctrl = createController();
var graph = ctrl.volumeQuota;
expect(graph.title).toEqual('Volume Quota');
expect(graph.maxLimit).toEqual(5);
expect(graph.data[0].value).toBe(1);
expect(graph.data[1].value).toBe(1);
// It's 40% because the two values above are added together
// and taken over the maxTotal (2/5).
expect(graph.label).toEqual('40%');
var current = graph.data[0];
expect(current).toEqual({label: 'Current Usage', value: 1, colorClass: 'usage'});
var added = graph.data[1];
expect(added).toEqual({label: 'Added', value: 1, colorClass: 'added'});
var remaining = graph.data[2];
expect(remaining).toEqual({label: 'Remaining', value: 3, colorClass: 'remaining'});
});
it('should update storage stats on volume size change', function() {
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 2,
totalVolumesUsed: 1,
maxTotalVolumes: 5,
totalGigabytesUsed: 1
});
}
});
var ctrl = createController();
var graph = ctrl.storageQuota;
var current = graph.data[0];
var added = graph.data[1];
var remaining = graph.data[2];
ctrl.volume.size = 2;
$scope.$apply();
expect(current.value).toEqual(1);
expect(added.value).toEqual(2);
expect(remaining.value).toEqual(0);
expect(graph.label).toEqual('150%');
expect(graph.maxLimit).toEqual(2);
expect(graph.overMax).toBeTruthy();
});
it('should not change if volume size is 0', function() {
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 2,
totalVolumesUsed: 1,
maxTotalVolumes: 5,
totalGigabytesUsed: 1
});
}
});
var ctrl = createController();
var graph = ctrl.storageQuota;
var current = graph.data[0];
var added = graph.data[1];
var remaining = graph.data[2];
ctrl.volume.size = 0;
$scope.$apply();
expect(current.value).toEqual(1);
expect(added.value).toEqual(0);
expect(remaining.value).toEqual(1);
expect(graph.label).toEqual('50%');
expect(graph.maxLimit).toEqual(2);
});
it('should not change if volume size is < 0', function() {
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 2,
totalVolumesUsed: 1,
maxTotalVolumes: 5,
totalGigabytesUsed: 1
});
}
});
var ctrl = createController();
var graph = ctrl.storageQuota;
var current = graph.data[0];
var added = graph.data[1];
var remaining = graph.data[2];
ctrl.volume.size = -1;
$scope.$apply();
expect(current.value).toEqual(current.value);
expect(added.value).toEqual(added.value);
expect(remaining.value).toEqual(remaining.value);
expect(graph.label).toEqual(graph.label);
expect(graph.maxLimit).toEqual(graph.maxLimit);
});
it('should emit volumeChanged event when a volume attribute is changed', function() {
var ctrl = createController();
$scope.$apply();
$scope.$emit.calls.reset();
ctrl.volume.name = 'nova2';
$scope.$apply();
expect($scope.$emit.calls.count()).toEqual(1);
});
it('should set the validity of the volume size input field based on the limit', function() {
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 2,
totalVolumesUsed: 1,
maxTotalVolumes: 5,
totalGigabytesUsed: 1
});
}
});
var ctrl = createController();
var graph = ctrl.storageQuota;
var current = graph.data[0];
var added = graph.data[1];
ctrl.volume.size = 2;
$scope.$apply();
expect(current.value).toEqual(1);
expect(added.value).toEqual(2);
expect(graph.maxLimit).toEqual(2);
expect(graph.overMax).toBeTruthy();
expect($scope.volumeForm.$setValidity.calls.argsFor(1)).toEqual(['volumeSize', false]);
});
it('should deregister the storage watcher when the destroy event is thrown', function() {
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 2,
totalVolumesUsed: 1,
maxTotalVolumes: 5,
totalGigabytesUsed: 1
});
}
});
var ctrl = createController();
var graph = ctrl.storageQuota;
var current = graph.data[0];
var added = graph.data[1];
var remaining = graph.data[2];
$scope.$emit('$destroy');
ctrl.volume.size = 2;
$scope.$apply();
expect(current.value).toEqual(1);
expect(added.value).toEqual(1);
expect(remaining.value).toEqual(0);
expect(graph.label).toEqual('100%');
expect(graph.maxLimit).toEqual(2);
expect(graph.overMax).toBeFalsy();
});
it('should deregister the volume watcher when the destroy event is thrown', function() {
var ctrl = createController();
$scope.$emit('$destroy');
$scope.$emit.calls.reset();
ctrl.volume.size = 100;
$scope.$apply();
expect($scope.$emit).not.toHaveBeenCalled();
});
it('should emit a changed volume event when the user changes the volume', function() {
var ctrl = createController();
$scope.$apply();
ctrl.volume.size = 100;
var emittedEventArgs = $scope.$emit.calls.argsFor(0);
var expectedVolume = {
size: 100,
name: ctrl.image.name,
description: '',
volume_type: 'lvmdriver-1',
availability_zone: 'zone1', // pre-selects first
metadata: {},
image_id: ctrl.image.id,
snapshot_id: null,
source_volid: null
};
expect(emittedEventArgs[0]).toEqual('horizon.app.core.images.VOLUME_CHANGED');
expect(emittedEventArgs[1]).toEqual(expectedVolume);
});
it('not default the availability_zone if none present', function() {
nova.getAvailabilityZones = function() {
return {
success: function(callback) {
return callback({ items: [] });
}
};
};
var ctrl = createController();
$scope.$apply();
ctrl.volume.size = 100;
var emittedEventArgs = $scope.$emit.calls.argsFor(0);
var expectedVolume = {
size: 100,
name: ctrl.image.name,
description: '',
volume_type: 'lvmdriver-1',
availability_zone: '',
metadata: {},
image_id: ctrl.image.id,
snapshot_id: null,
source_volid: null
};
expect(emittedEventArgs[0]).toEqual('horizon.app.core.images.VOLUME_CHANGED');
expect(emittedEventArgs[1]).toEqual(expectedVolume);
});
it('should emit changed volume events even if the volume name is empty', function() {
var ctrl = createController();
$scope.$apply();
ctrl.volumeType.name = '';
$scope.$emit.calls.reset();
ctrl.volume.name = '';
$scope.$apply();
expect($scope.$emit.calls.count()).toEqual(2);
});
it('should not update the graph if wrong values are given for volume size', function () {
getAbsoluteLimitsSpy.and.returnValue({
success: function(callback) {
return callback({
maxTotalVolumeGigabytes: 2,
totalVolumesUsed: 1,
maxTotalVolumes: 5,
totalGigabytesUsed: 1
});
}
});
var ctrl = createController();
expect(ctrl.volume.size).toBe(1);
var graph = ctrl.storageQuota;
var current = graph.data[0];
var added = graph.data[1];
var remaining = graph.data[2];
expect(current.value).toEqual(1);
expect(added.value).toEqual(1);
expect(remaining.value).toEqual(0);
expect(graph.label).toEqual('100%');
expect(graph.maxLimit).toEqual(2);
expect(graph.overMax).toBeFalsy();
ctrl.volume.size = -5;
$scope.$apply();
expect(current.value).toEqual(1);
expect(added.value).toEqual(1);
expect(remaining.value).toEqual(0);
expect(graph.label).toEqual('100%');
expect(graph.maxLimit).toEqual(2);
expect(graph.overMax).toBeFalsy();
});
});
})();