Add angular server group details page
This patch adds angular server group details page to show details of the given server group, also shows the server group members under the current server group. Change-Id: I5b903972dd4fc5c9f1b52f97bdd7e0852d7d00d3 Partial-Implements: blueprint ng-server-groups
This commit is contained in:
parent
37647dd318
commit
940ff111a1
@ -31,7 +31,8 @@ MICROVERSION_FEATURES = {
|
|||||||
"locked_attribute": ["2.9", "2.42"],
|
"locked_attribute": ["2.9", "2.42"],
|
||||||
"instance_description": ["2.19", "2.42"],
|
"instance_description": ["2.19", "2.42"],
|
||||||
"remote_console_mks": ["2.8", "2.53"],
|
"remote_console_mks": ["2.8", "2.53"],
|
||||||
"servergroup_soft_policies": ["2.15", "2.60"]
|
"servergroup_soft_policies": ["2.15", "2.60"],
|
||||||
|
"servergroup_user_info": ["2.13", "2.60"]
|
||||||
},
|
},
|
||||||
"cinder": {
|
"cinder": {
|
||||||
"consistency_groups": ["2.0", "3.10"],
|
"consistency_groups": ["2.0", "3.10"],
|
||||||
|
@ -943,6 +943,13 @@ def server_group_delete(request, servergroup_id):
|
|||||||
novaclient(request).server_groups.delete(servergroup_id)
|
novaclient(request).server_groups.delete(servergroup_id)
|
||||||
|
|
||||||
|
|
||||||
|
@profiler.trace
|
||||||
|
def server_group_get(request, servergroup_id):
|
||||||
|
microversion = get_microversion(request, "servergroup_user_info")
|
||||||
|
return novaclient(request, version=microversion).server_groups.get(
|
||||||
|
servergroup_id)
|
||||||
|
|
||||||
|
|
||||||
@profiler.trace
|
@profiler.trace
|
||||||
def service_list(request, binary=None):
|
def service_list(request, binary=None):
|
||||||
return novaclient(request).services.list(binary=binary)
|
return novaclient(request).services.list(binary=binary)
|
||||||
|
@ -460,6 +460,14 @@ class ServerGroup(generic.View):
|
|||||||
"""
|
"""
|
||||||
api.nova.server_group_delete(request, servergroup_id)
|
api.nova.server_group_delete(request, servergroup_id)
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def get(self, request, servergroup_id):
|
||||||
|
"""Get a specific server group
|
||||||
|
|
||||||
|
http://localhost/api/nova/servergroups/1
|
||||||
|
"""
|
||||||
|
return api.nova.server_group_get(request, servergroup_id).to_dict()
|
||||||
|
|
||||||
|
|
||||||
@urls.register
|
@urls.register
|
||||||
class ServerMetadata(generic.View):
|
class ServerMetadata(generic.View):
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
createServer: createServer,
|
createServer: createServer,
|
||||||
getServer: getServer,
|
getServer: getServer,
|
||||||
getServers: getServers,
|
getServers: getServers,
|
||||||
|
getServerGroup: getServerGroup,
|
||||||
getServerGroups: getServerGroups,
|
getServerGroups: getServerGroups,
|
||||||
createServerGroup: createServerGroup,
|
createServerGroup: createServerGroup,
|
||||||
deleteServerGroup: deleteServerGroup,
|
deleteServerGroup: deleteServerGroup,
|
||||||
@ -318,6 +319,21 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name getServerGroup
|
||||||
|
* @description
|
||||||
|
* Get a single server group by ID
|
||||||
|
* @param {string} id
|
||||||
|
* Specifies the id of the server group to request.
|
||||||
|
* @returns {Object} The result of the API call
|
||||||
|
*/
|
||||||
|
function getServerGroup(id) {
|
||||||
|
return apiService.get('/api/nova/servergroups/' + id)
|
||||||
|
.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to retrieve the server group.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name getServerGroups
|
* @name getServerGroups
|
||||||
* @description
|
* @description
|
||||||
|
@ -296,6 +296,15 @@
|
|||||||
"path": "/api/nova/servers/",
|
"path": "/api/nova/servers/",
|
||||||
"error": "Unable to retrieve instances."
|
"error": "Unable to retrieve instances."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"func": "getServerGroup",
|
||||||
|
"method": "get",
|
||||||
|
"path": "/api/nova/servergroups/17",
|
||||||
|
"error": "Unable to retrieve the server group.",
|
||||||
|
"testInput": [
|
||||||
|
'17'
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"func": 'getServerGroups',
|
"func": 'getServerGroups',
|
||||||
"method": 'get',
|
"method": 'get',
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc overview
|
||||||
|
* @ngname horizon.app.core.server_groups.details
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Provides details features for server groups.
|
||||||
|
*/
|
||||||
|
angular
|
||||||
|
.module('horizon.app.core.server_groups.details', [
|
||||||
|
'horizon.framework.conf',
|
||||||
|
'horizon.app.core'
|
||||||
|
])
|
||||||
|
.run(registerServerGroupDetails);
|
||||||
|
|
||||||
|
registerServerGroupDetails.$inject = [
|
||||||
|
'horizon.app.core.server_groups.basePath',
|
||||||
|
'horizon.app.core.server_groups.resourceType',
|
||||||
|
'horizon.app.core.server_groups.service',
|
||||||
|
'horizon.framework.conf.resource-type-registry.service'
|
||||||
|
];
|
||||||
|
|
||||||
|
function registerServerGroupDetails(
|
||||||
|
basePath,
|
||||||
|
serverGroupResourceType,
|
||||||
|
serverGroupService,
|
||||||
|
registry
|
||||||
|
) {
|
||||||
|
registry.getResourceType(serverGroupResourceType)
|
||||||
|
.setLoadFunction(serverGroupService.getServerGroupPromise)
|
||||||
|
.detailsViews.append({
|
||||||
|
id: 'serverGroupDetailsOverview',
|
||||||
|
name: gettext('Overview'),
|
||||||
|
template: basePath + 'details/overview.html'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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('server group details module', function() {
|
||||||
|
it('should exist', function() {
|
||||||
|
expect(angular.module('horizon.app.core.server_groups.details')).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
var registry, resource;
|
||||||
|
beforeEach(module('horizon.framework'));
|
||||||
|
beforeEach(module('horizon.app.core.server_groups'));
|
||||||
|
beforeEach(inject(function($injector) {
|
||||||
|
registry = $injector.get('horizon.framework.conf.resource-type-registry.service');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be loaded', function() {
|
||||||
|
resource = registry.getResourceType('OS::Nova::ServerGroup');
|
||||||
|
expect(resource.detailsViews[0].id).toBe('serverGroupDetailsOverview');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* 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";
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('horizon.app.core.server_groups')
|
||||||
|
.controller('ServerGroupOverviewController', ServerGroupOverviewController);
|
||||||
|
|
||||||
|
ServerGroupOverviewController.$inject = [
|
||||||
|
'$scope',
|
||||||
|
'horizon.app.core.openstack-service-api.nova',
|
||||||
|
'horizon.app.core.openstack-service-api.userSession',
|
||||||
|
'horizon.app.core.server_groups.resourceType',
|
||||||
|
'horizon.app.core.server_groups.service',
|
||||||
|
'horizon.framework.conf.resource-type-registry.service'
|
||||||
|
];
|
||||||
|
|
||||||
|
function ServerGroupOverviewController(
|
||||||
|
$scope,
|
||||||
|
nova,
|
||||||
|
userSession,
|
||||||
|
serverGroupResourceTypeCode,
|
||||||
|
serverGroupsService,
|
||||||
|
registry
|
||||||
|
) {
|
||||||
|
var ctrl = this;
|
||||||
|
|
||||||
|
nova.isFeatureSupported(
|
||||||
|
'servergroup_user_info').then(onGetServerGroupProperties);
|
||||||
|
|
||||||
|
function onGetServerGroupProperties(response) {
|
||||||
|
var properties = ['id', 'name', 'policy'];
|
||||||
|
if (response.data) {
|
||||||
|
properties.splice(2, 0, 'project_id', 'user_id');
|
||||||
|
}
|
||||||
|
ctrl.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl.resourceType = registry.getResourceType(serverGroupResourceTypeCode);
|
||||||
|
ctrl.tableConfig = {
|
||||||
|
selectAll: false,
|
||||||
|
expand: false,
|
||||||
|
trackId: 'id',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
id: 'name',
|
||||||
|
title: gettext('Instance Name'),
|
||||||
|
priority: 1,
|
||||||
|
sortDefault: true,
|
||||||
|
urlFunction: serverGroupsService.getInstanceDetailsPath
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'id',
|
||||||
|
title: gettext('Instance ID'),
|
||||||
|
priority: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.context.loadPromise.then(onGetServerGroup);
|
||||||
|
|
||||||
|
function onGetServerGroup(servergroup) {
|
||||||
|
ctrl.servergroup = servergroup.data;
|
||||||
|
if (ctrl.servergroup.members.length) {
|
||||||
|
// The server group members only contains the instance id,
|
||||||
|
// does not contain other information of the instance, we
|
||||||
|
// need to get the list of instances and then get the specified
|
||||||
|
// instance from the list based on id.
|
||||||
|
nova.getServers().then(function getServer(servers) {
|
||||||
|
var members = [];
|
||||||
|
ctrl.servergroup.members.forEach(function(member) {
|
||||||
|
for (var i = 0; i < servers.data.items.length; i++) {
|
||||||
|
var server = servers.data.items[i];
|
||||||
|
if (member === server.id) {
|
||||||
|
members.push(server);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ctrl.members = members;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ctrl.members = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
userSession.get().then(setProject);
|
||||||
|
|
||||||
|
function setProject(session) {
|
||||||
|
ctrl.projectId = session.project_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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('server group overview controller', function() {
|
||||||
|
var $controller, $q, $timeout, nova, session;
|
||||||
|
var sessionObj = {project_id: '10'};
|
||||||
|
|
||||||
|
beforeEach(module('horizon.app.core.server_groups'));
|
||||||
|
beforeEach(module('horizon.framework.conf'));
|
||||||
|
beforeEach(inject(function($injector) {
|
||||||
|
$controller = $injector.get('$controller');
|
||||||
|
$q = $injector.get('$q');
|
||||||
|
$timeout = $injector.get('$timeout');
|
||||||
|
session = $injector.get('horizon.app.core.openstack-service-api.userSession');
|
||||||
|
nova = $injector.get('horizon.app.core.openstack-service-api.nova');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('sets ctrl.members when server group members length === 0', inject(function() {
|
||||||
|
var deferred = $q.defer();
|
||||||
|
var serverGroupDeferred = $q.defer();
|
||||||
|
var serversDeferred = $q.defer();
|
||||||
|
var sessionDeferred = $q.defer();
|
||||||
|
deferred.resolve({data: { data: true}});
|
||||||
|
serverGroupDeferred.resolve({data: {members: ['1', '2']}});
|
||||||
|
serversDeferred.resolve({data: { items: [{'id': '1'}, {'id': '2'}]}});
|
||||||
|
sessionDeferred.resolve(sessionObj);
|
||||||
|
spyOn(nova, 'isFeatureSupported').and.returnValue(deferred.promise);
|
||||||
|
spyOn(nova, 'getServerGroup').and.returnValue(serverGroupDeferred.promise);
|
||||||
|
spyOn(nova, 'getServers').and.returnValue(serversDeferred.promise);
|
||||||
|
spyOn(session, 'get').and.returnValue(sessionDeferred.promise);
|
||||||
|
var ctrl = $controller('ServerGroupOverviewController',
|
||||||
|
{
|
||||||
|
'$scope': {context: {loadPromise: serverGroupDeferred.promise}}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$timeout.flush();
|
||||||
|
expect(ctrl.properties).toBeDefined();
|
||||||
|
expect(ctrl.members[0]).toEqual({'id': '1'});
|
||||||
|
expect(ctrl.projectId).toBe(sessionObj.project_id);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('sets ctrl.members when server group members length > 0', inject(function() {
|
||||||
|
var deferred = $q.defer();
|
||||||
|
var serverGroupDeferred = $q.defer();
|
||||||
|
var serversDeferred = $q.defer();
|
||||||
|
var sessionDeferred = $q.defer();
|
||||||
|
deferred.resolve({data: { data: true}});
|
||||||
|
serverGroupDeferred.resolve({data: {members: []}});
|
||||||
|
serversDeferred.resolve({data: { items: [{'id': '1'}, {'id': '2'}]}});
|
||||||
|
sessionDeferred.resolve(sessionObj);
|
||||||
|
spyOn(nova, 'isFeatureSupported').and.returnValue(deferred.promise);
|
||||||
|
spyOn(nova, 'getServerGroup').and.returnValue(serverGroupDeferred.promise);
|
||||||
|
spyOn(nova, 'getServers').and.returnValue(serversDeferred.promise);
|
||||||
|
spyOn(session, 'get').and.returnValue(sessionDeferred.promise);
|
||||||
|
var ctrl = $controller('ServerGroupOverviewController',
|
||||||
|
{
|
||||||
|
'$scope': {context: {loadPromise: serverGroupDeferred.promise}}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$timeout.flush();
|
||||||
|
expect(ctrl.properties).toBeDefined();
|
||||||
|
expect(ctrl.members).toEqual([]);
|
||||||
|
expect(ctrl.projectId).toBe(sessionObj.project_id);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
})();
|
@ -0,0 +1,17 @@
|
|||||||
|
<div ng-controller="ServerGroupOverviewController as ctrl">
|
||||||
|
<hz-resource-property-list
|
||||||
|
resource-type-name="OS::Nova::ServerGroup"
|
||||||
|
cls="dl-horizontal"
|
||||||
|
item="ctrl.servergroup"
|
||||||
|
property-groups="[ctrl.properties]">
|
||||||
|
</hz-resource-property-list>
|
||||||
|
<h2 class="h4">{$ ::'Server Group Members' | translate $}</h2>
|
||||||
|
<hr>
|
||||||
|
<dl class="dl-horizontal">
|
||||||
|
<hz-dynamic-table
|
||||||
|
config="ctrl.tableConfig"
|
||||||
|
items="ctrl.members"
|
||||||
|
table="ctrl">
|
||||||
|
</hz-dynamic-table>
|
||||||
|
</dl>
|
||||||
|
</div>
|
@ -27,7 +27,8 @@
|
|||||||
.module('horizon.app.core.server_groups', [
|
.module('horizon.app.core.server_groups', [
|
||||||
'horizon.framework.conf',
|
'horizon.framework.conf',
|
||||||
'horizon.app.core',
|
'horizon.app.core',
|
||||||
'horizon.app.core.server_groups.actions'
|
'horizon.app.core.server_groups.actions',
|
||||||
|
'horizon.app.core.server_groups.details'
|
||||||
])
|
])
|
||||||
.constant('horizon.app.core.server_groups.resourceType', 'OS::Nova::ServerGroup')
|
.constant('horizon.app.core.server_groups.resourceType', 'OS::Nova::ServerGroup')
|
||||||
.run(run)
|
.run(run)
|
||||||
@ -50,7 +51,8 @@
|
|||||||
.append({
|
.append({
|
||||||
id: 'name',
|
id: 'name',
|
||||||
priority: 1,
|
priority: 1,
|
||||||
sortDefault: true
|
sortDefault: true,
|
||||||
|
urlFunction: serverGroupsService.getDetailsPath
|
||||||
})
|
})
|
||||||
// The name is not unique, so we need to show the ID to
|
// The name is not unique, so we need to show the ID to
|
||||||
// distinguish.
|
// distinguish.
|
||||||
@ -89,28 +91,43 @@
|
|||||||
return {
|
return {
|
||||||
name: gettext('Name'),
|
name: gettext('Name'),
|
||||||
id: gettext('ID'),
|
id: gettext('ID'),
|
||||||
policy: gettext('Policy')
|
policy: gettext('Policy'),
|
||||||
|
project_id: gettext('Project ID'),
|
||||||
|
user_id: gettext('User ID')
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
config.$inject = [
|
config.$inject = [
|
||||||
|
'$provide',
|
||||||
'$windowProvider',
|
'$windowProvider',
|
||||||
'$routeProvider'
|
'$routeProvider',
|
||||||
|
'horizon.app.core.detailRoute'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name config
|
* @name config
|
||||||
|
* @param {Object} $provide
|
||||||
* @param {Object} $windowProvider
|
* @param {Object} $windowProvider
|
||||||
* @param {Object} $routeProvider
|
* @param {Object} $routeProvider
|
||||||
|
* @param {String} detailRoute
|
||||||
* @description Routes used by this module.
|
* @description Routes used by this module.
|
||||||
* @returns {undefined} Returns nothing
|
* @returns {undefined} Returns nothing
|
||||||
*/
|
*/
|
||||||
function config($windowProvider, $routeProvider) {
|
function config($provide, $windowProvider, $routeProvider, detailRoute) {
|
||||||
var path = $windowProvider.$get().STATIC_URL + 'app/core/server_groups/';
|
var path = $windowProvider.$get().STATIC_URL + 'app/core/server_groups/';
|
||||||
|
$provide.constant('horizon.app.core.server_groups.basePath', path);
|
||||||
|
|
||||||
$routeProvider.when('/project/server_groups', {
|
$routeProvider.when('/project/server_groups', {
|
||||||
templateUrl: path + 'panel.html'
|
templateUrl: path + 'panel.html'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$routeProvider.when('/project/server_groups/:id', {
|
||||||
|
redirectTo: goToAngularDetails
|
||||||
|
});
|
||||||
|
|
||||||
|
function goToAngularDetails(params) {
|
||||||
|
return detailRoute + 'OS::Nova::ServerGroup/' + params.id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -19,25 +19,56 @@
|
|||||||
.factory('horizon.app.core.server_groups.service', serverGroupsService);
|
.factory('horizon.app.core.server_groups.service', serverGroupsService);
|
||||||
|
|
||||||
serverGroupsService.$inject = [
|
serverGroupsService.$inject = [
|
||||||
|
'$window',
|
||||||
|
'horizon.app.core.detailRoute',
|
||||||
'horizon.app.core.openstack-service-api.nova'
|
'horizon.app.core.openstack-service-api.nova'
|
||||||
];
|
];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @ngdoc factory
|
* @ngdoc factory
|
||||||
* @name horizon.app.core.server_groups.service
|
* @name horizon.app.core.server_groups.service
|
||||||
*
|
|
||||||
* @description
|
* @description
|
||||||
* This service provides functions that are used through the Server Groups
|
* This service provides functions that are used through the Server Groups
|
||||||
* features. These are primarily used in the module registrations
|
* features. These are primarily used in the module registrations
|
||||||
* but do not need to be restricted to such use. Each exposed function
|
* but do not need to be restricted to such use. Each exposed function
|
||||||
* is documented below.
|
* is documented below.
|
||||||
*/
|
*/
|
||||||
function serverGroupsService(nova) {
|
function serverGroupsService($window, detailRoute, nova) {
|
||||||
return {
|
return {
|
||||||
getServerGroupsPromise: getServerGroupsPromise,
|
getDetailsPath: getDetailsPath,
|
||||||
getServerGroupPolicies: getServerGroupPolicies
|
getInstanceDetailsPath: getInstanceDetailsPath,
|
||||||
|
getServerGroupPolicies: getServerGroupPolicies,
|
||||||
|
getServerGroupPromise: getServerGroupPromise,
|
||||||
|
getServerGroupsPromise: getServerGroupsPromise
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @ngdoc function
|
||||||
|
* @name getDetailsPath
|
||||||
|
* @param item {Object} - The server group object
|
||||||
|
* @description
|
||||||
|
* Given a server group object, returns the relative path to the details
|
||||||
|
* view.
|
||||||
|
*/
|
||||||
|
function getDetailsPath(item) {
|
||||||
|
return detailRoute + 'OS::Nova::ServerGroup/' + item.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @ngdoc function
|
||||||
|
* @name getInstanceDetailsPath
|
||||||
|
* @param item {Object} - The instance object
|
||||||
|
* @description
|
||||||
|
* Given an instance object, returns the relative path to the details
|
||||||
|
* view.
|
||||||
|
*/
|
||||||
|
function getInstanceDetailsPath(item) {
|
||||||
|
// The current instances page only contains the django
|
||||||
|
// version, if we add angular instances pages in the future,
|
||||||
|
// the url here also needs to be modified accordingly.
|
||||||
|
return $window.WEBROOT + 'project/instances/' + item.id + '/';
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @ngdoc function
|
* @ngdoc function
|
||||||
* @name getServerGroupPolicies
|
* @name getServerGroupPolicies
|
||||||
@ -61,6 +92,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @ngdoc function
|
||||||
|
* @name getServerGroupPromise
|
||||||
|
* @description
|
||||||
|
* Given an id, returns a promise for the server group data.
|
||||||
|
*/
|
||||||
|
function getServerGroupPromise(identifier) {
|
||||||
|
return nova.getServerGroup(identifier).then(modifyResponse);
|
||||||
|
|
||||||
|
function modifyResponse(response) {
|
||||||
|
return getServerGroupPolicies().then(modifyItem);
|
||||||
|
|
||||||
|
function modifyItem(policies) {
|
||||||
|
response.data.policy = policies[response.data.policies[0]];
|
||||||
|
return {data: response.data};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @ngdoc function
|
* @ngdoc function
|
||||||
* @name getServerGroupsPromise
|
* @name getServerGroupsPromise
|
||||||
|
@ -16,16 +16,61 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
describe('server groups service', function() {
|
describe('server groups service', function() {
|
||||||
var $q, $timeout, nova, service;
|
var $q, $timeout, $window, detailRoute, nova, service;
|
||||||
|
|
||||||
beforeEach(module('horizon.app.core.server_groups'));
|
beforeEach(module('horizon.app.core.server_groups'));
|
||||||
beforeEach(inject(function($injector) {
|
beforeEach(inject(function($injector) {
|
||||||
$q = $injector.get('$q');
|
$q = $injector.get('$q');
|
||||||
$timeout = $injector.get('$timeout');
|
$timeout = $injector.get('$timeout');
|
||||||
|
$window = $injector.get('$window');
|
||||||
|
detailRoute = $injector.get('horizon.app.core.detailRoute');
|
||||||
nova = $injector.get('horizon.app.core.openstack-service-api.nova');
|
nova = $injector.get('horizon.app.core.openstack-service-api.nova');
|
||||||
service = $injector.get('horizon.app.core.server_groups.service');
|
service = $injector.get('horizon.app.core.server_groups.service');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it("getDetailsPath creates urls using the item's ID", function() {
|
||||||
|
var item = {id: '11'};
|
||||||
|
expect(service.getDetailsPath(item)).toBe(detailRoute + 'OS::Nova::ServerGroup/11');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("getInstanceDetailsPath creates urls using the item's ID", function() {
|
||||||
|
$window.WEBROOT = '/dashboard/';
|
||||||
|
var item = {id: "12"};
|
||||||
|
expect(service.getInstanceDetailsPath(item)).toBe('/dashboard/project/instances/12/');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getServerGroupPromise', function() {
|
||||||
|
it("provides a promise when soft policies are supported", inject(function() {
|
||||||
|
var deferred = $q.defer();
|
||||||
|
var deferredPolicies = $q.defer();
|
||||||
|
spyOn(nova, 'getServerGroup').and.returnValue(deferred.promise);
|
||||||
|
spyOn(nova, 'isFeatureSupported').and.returnValue(deferredPolicies.promise);
|
||||||
|
var result = service.getServerGroupPromise({});
|
||||||
|
deferred.resolve({data: {id: '13', policies: ['affinity']}});
|
||||||
|
deferredPolicies.resolve({data: true});
|
||||||
|
$timeout.flush();
|
||||||
|
|
||||||
|
expect(nova.getServerGroup).toHaveBeenCalled();
|
||||||
|
expect(nova.isFeatureSupported).toHaveBeenCalled();
|
||||||
|
expect(result.$$state.value.data.id).toBe('13');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("provides a promise when soft policies are not supported", inject(function() {
|
||||||
|
var deferred = $q.defer();
|
||||||
|
var deferredPolicies = $q.defer();
|
||||||
|
spyOn(nova, 'getServerGroup').and.returnValue(deferred.promise);
|
||||||
|
spyOn(nova, 'isFeatureSupported').and.returnValue(deferredPolicies.promise);
|
||||||
|
var result = service.getServerGroupPromise({});
|
||||||
|
deferred.resolve({data: {id: '15', policies: ['affinity']}});
|
||||||
|
deferredPolicies.resolve({data: false});
|
||||||
|
$timeout.flush();
|
||||||
|
|
||||||
|
expect(nova.getServerGroup).toHaveBeenCalled();
|
||||||
|
expect(nova.isFeatureSupported).toHaveBeenCalled();
|
||||||
|
expect(result.$$state.value.data.id).toBe('15');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
describe('getServerGroupsPromise', function() {
|
describe('getServerGroupsPromise', function() {
|
||||||
it("provides a promise when soft policies are supported", inject(function() {
|
it("provides a promise when soft policies are supported", inject(function() {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
|
@ -395,6 +395,18 @@ class NovaRestTestCase(test.TestCase):
|
|||||||
nova.ServerGroup().delete(request, "1")
|
nova.ServerGroup().delete(request, "1")
|
||||||
self.mock_server_group_delete.assert_called_once_with(request, "1")
|
self.mock_server_group_delete.assert_called_once_with(request, "1")
|
||||||
|
|
||||||
|
@test.create_mocks({api.nova: ['server_group_get']})
|
||||||
|
def test_server_group_get_single(self):
|
||||||
|
request = self.mock_rest_request()
|
||||||
|
servergroup = self.server_groups.first()
|
||||||
|
self.mock_server_group_get.return_value = servergroup
|
||||||
|
|
||||||
|
response = nova.ServerGroup().get(request, "1")
|
||||||
|
|
||||||
|
self.assertStatusCode(response, 200)
|
||||||
|
self.assertEqual(servergroup.to_dict(), response.json)
|
||||||
|
self.mock_server_group_get.assert_called_once_with(request, "1")
|
||||||
|
|
||||||
#
|
#
|
||||||
# Server Metadata
|
# Server Metadata
|
||||||
#
|
#
|
||||||
|
@ -667,3 +667,15 @@ class ComputeApiTests(test.APIMockTestCase):
|
|||||||
|
|
||||||
self.assertIsNone(api_val)
|
self.assertIsNone(api_val)
|
||||||
novaclient.server_groups.delete.assert_called_once_with(servergroup_id)
|
novaclient.server_groups.delete.assert_called_once_with(servergroup_id)
|
||||||
|
|
||||||
|
def test_server_group_get(self):
|
||||||
|
servergroup = self.server_groups.first()
|
||||||
|
novaclient = self.stub_novaclient()
|
||||||
|
self._mock_current_version(novaclient, '2.45')
|
||||||
|
novaclient.server_groups.get.return_value = servergroup
|
||||||
|
|
||||||
|
ret_val = api.nova.server_group_get(self.request, servergroup.id)
|
||||||
|
|
||||||
|
self.assertEqual(ret_val.id, servergroup.id)
|
||||||
|
novaclient.versions.get_current.assert_called_once_with()
|
||||||
|
novaclient.server_groups.get.assert_called_once_with(servergroup.id)
|
||||||
|
@ -5,5 +5,6 @@ features:
|
|||||||
This blueprint add angular server groups panel below the
|
This blueprint add angular server groups panel below the
|
||||||
Project->Compute panel group. The panel turns on if Nova API
|
Project->Compute panel group. The panel turns on if Nova API
|
||||||
extension 'ServerGroups' is available. It displays information about
|
extension 'ServerGroups' is available. It displays information about
|
||||||
server groups.
|
server groups. The details page for each server group also shows
|
||||||
|
information about instances of that server group.
|
||||||
Supported actions: create, delete.
|
Supported actions: create, delete.
|
||||||
|
Loading…
Reference in New Issue
Block a user