Merge "Add more Nova API features for NG Instances"
This commit is contained in:
commit
77a804ea4b
openstack_dashboard
api/rest
static/app/core/openstack-service-api
test/api_tests
@ -13,12 +13,16 @@
|
||||
# limitations under the License.
|
||||
"""API over the nova service.
|
||||
"""
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.utils import http as utils_http
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views import generic
|
||||
|
||||
from horizon import exceptions as hz_exceptions
|
||||
|
||||
from novaclient import exceptions
|
||||
|
||||
from openstack_dashboard import api
|
||||
@ -27,6 +31,24 @@ from openstack_dashboard.api.rest import urls
|
||||
from openstack_dashboard.api.rest import utils as rest_utils
|
||||
from openstack_dashboard.usage import quotas
|
||||
|
||||
import six
|
||||
|
||||
|
||||
@urls.register
|
||||
class Snapshots(generic.View):
|
||||
"""API for nova snapshots.
|
||||
"""
|
||||
url_regex = r'nova/snapshots/$'
|
||||
|
||||
@rest_utils.ajax(data_required=True)
|
||||
def post(self, request):
|
||||
instance_id = request.DATA['instance_id']
|
||||
name = request.DATA['name']
|
||||
result = api.nova.snapshot_create(request,
|
||||
instance_id=instance_id,
|
||||
name=name)
|
||||
return result
|
||||
|
||||
|
||||
@urls.register
|
||||
class Keypairs(generic.View):
|
||||
@ -177,6 +199,146 @@ class Limits(generic.View):
|
||||
return result
|
||||
|
||||
|
||||
@urls.register
|
||||
class ServerActions(generic.View):
|
||||
"""API over all server actions.
|
||||
"""
|
||||
url_regex = r'nova/servers/(?P<server_id>[^/]+)/actions/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request, server_id):
|
||||
"""Get a list of server actions.
|
||||
|
||||
The listing result is an object with property "items". Each item is
|
||||
an action taken against the given server.
|
||||
|
||||
Example GET:
|
||||
http://localhost/api/nova/servers/abcd/actions/
|
||||
"""
|
||||
actions = api.nova.instance_action_list(request, server_id)
|
||||
return {'items': [s.to_dict() for s in actions]}
|
||||
|
||||
|
||||
@urls.register
|
||||
class SecurityGroups(generic.View):
|
||||
"""API over all server security groups.
|
||||
"""
|
||||
url_regex = r'nova/servers/(?P<server_id>[^/]+)/security-groups/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request, server_id):
|
||||
"""Get a list of server security groups.
|
||||
|
||||
The listing result is an object with property "items". Each item is
|
||||
security group associated with this server.
|
||||
|
||||
Example GET:
|
||||
http://localhost/api/nova/servers/abcd/security-groups/
|
||||
"""
|
||||
groups = api.network.server_security_groups(request, server_id)
|
||||
return {'items': [s.to_dict() for s in groups]}
|
||||
|
||||
|
||||
@urls.register
|
||||
class Volumes(generic.View):
|
||||
"""API over all server volumes.
|
||||
"""
|
||||
url_regex = r'nova/servers/(?P<server_id>[^/]+)/volumes/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request, server_id):
|
||||
"""Get a list of server volumes.
|
||||
|
||||
The listing result is an object with property "items". Each item is
|
||||
a volume.
|
||||
|
||||
Example GET:
|
||||
http://localhost/api/nova/servers/abcd/volumes/
|
||||
"""
|
||||
volumes = api.nova.instance_volumes_list(request, server_id)
|
||||
return {'items': [s.to_dict() for s in volumes]}
|
||||
|
||||
|
||||
@urls.register
|
||||
class RemoteConsoleInfo(generic.View):
|
||||
"""API for remote console information.
|
||||
"""
|
||||
url_regex = r'nova/servers/(?P<server_id>[^/]+)/console-info/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def post(self, request, server_id):
|
||||
"""Gets information about an available remote console for the given
|
||||
server.
|
||||
|
||||
Example POST:
|
||||
http://localhost/api/nova/servers/abcd/console-info/
|
||||
"""
|
||||
console_type = request.DATA.get('console_type', 'AUTO')
|
||||
CONSOLES = OrderedDict([('VNC', api.nova.server_vnc_console),
|
||||
('SPICE', api.nova.server_spice_console),
|
||||
('RDP', api.nova.server_rdp_console),
|
||||
('SERIAL', api.nova.server_serial_console)])
|
||||
|
||||
"""Get a tuple of console url and console type."""
|
||||
if console_type == 'AUTO':
|
||||
check_consoles = CONSOLES
|
||||
else:
|
||||
try:
|
||||
check_consoles = {console_type: CONSOLES[console_type]}
|
||||
except KeyError:
|
||||
msg = _('Console type "%s" not supported.') % console_type
|
||||
raise hz_exceptions.NotAvailable(msg)
|
||||
|
||||
# Ugly workaround due novaclient API change from 2.17 to 2.18.
|
||||
try:
|
||||
httpnotimplemented = exceptions.HttpNotImplemented
|
||||
except AttributeError:
|
||||
httpnotimplemented = exceptions.HTTPNotImplemented
|
||||
|
||||
for con_type, api_call in six.iteritems(check_consoles):
|
||||
try:
|
||||
console = api_call(request, server_id)
|
||||
# If not supported, don't log it to avoid lot of errors in case
|
||||
# of AUTO.
|
||||
except httpnotimplemented:
|
||||
continue
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if con_type == 'SERIAL':
|
||||
console_url = console.url
|
||||
else:
|
||||
console_url = "%s&%s(%s)" % (
|
||||
console.url,
|
||||
utils_http.urlencode({'title': _("Console")}),
|
||||
server_id)
|
||||
|
||||
return {"type": con_type, "url": console_url}
|
||||
raise hz_exceptions.NotAvailable(_('No available console found.'))
|
||||
|
||||
|
||||
@urls.register
|
||||
class ConsoleOutput(generic.View):
|
||||
"""API for console output.
|
||||
"""
|
||||
url_regex = r'nova/servers/(?P<server_id>[^/]+)/console-output/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def post(self, request, server_id):
|
||||
"""Get a list of lines of console output.
|
||||
|
||||
The listing result is an object with property "items". Each item is
|
||||
a line of output from the server.
|
||||
|
||||
Example GET:
|
||||
http://localhost/api/nova/servers/abcd/console-output/
|
||||
"""
|
||||
log_length = request.DATA.get('length', 100)
|
||||
console_lines = api.nova.server_console_output(request, server_id,
|
||||
tail_length=log_length)
|
||||
return {"lines": [x for x in console_lines.split('\n')]}
|
||||
|
||||
|
||||
@urls.register
|
||||
class Servers(generic.View):
|
||||
"""API over all servers.
|
||||
@ -186,7 +348,7 @@ class Servers(generic.View):
|
||||
_optional_create = [
|
||||
'block_device_mapping', 'block_device_mapping_v2', 'nics', 'meta',
|
||||
'availability_zone', 'instance_count', 'admin_pass', 'disk_config',
|
||||
'config_drive', 'scheduler_hints'
|
||||
'config_drive'
|
||||
]
|
||||
|
||||
@rest_utils.ajax()
|
||||
@ -267,6 +429,27 @@ class Server(generic.View):
|
||||
"""
|
||||
return api.nova.server_get(request, server_id).to_dict()
|
||||
|
||||
@rest_utils.ajax(data_required=True)
|
||||
def post(self, request, server_id):
|
||||
"""Perform a change to a server
|
||||
"""
|
||||
operation = request.DATA.get('operation', 'none')
|
||||
operations = {
|
||||
'stop': api.nova.server_stop,
|
||||
'start': api.nova.server_start,
|
||||
'pause': api.nova.server_pause,
|
||||
'unpause': api.nova.server_unpause,
|
||||
'suspend': api.nova.server_suspend,
|
||||
'resume': api.nova.server_resume,
|
||||
'hard_reboot': lambda r, s: api.nova.server_reboot(r, s, False),
|
||||
'soft_reboot': lambda r, s: api.nova.server_reboot(r, s, True),
|
||||
}
|
||||
return operations[operation](request, server_id)
|
||||
|
||||
@rest_utils.ajax()
|
||||
def delete(self, request, server_id):
|
||||
api.nova.server_delete(request, server_id)
|
||||
|
||||
|
||||
@urls.register
|
||||
class ServerGroups(generic.View):
|
||||
|
@ -83,11 +83,13 @@
|
||||
// The following retrieves the first argument of the first call to the
|
||||
// error spy. This exposes the inner function that, when invoked,
|
||||
// allows us to inspect the error call and the message given.
|
||||
var innerFunc = promise.error.calls.argsFor(0)[0];
|
||||
expect(innerFunc).toBeDefined();
|
||||
spyOn(toastService, 'add');
|
||||
innerFunc({status: 500});
|
||||
expect(toastService.add).toHaveBeenCalledWith(config.messageType || 'error', config.error);
|
||||
if (config.error) {
|
||||
var innerFunc = promise.error.calls.argsFor(0)[0];
|
||||
expect(innerFunc).toBeDefined();
|
||||
spyOn(toastService, 'add');
|
||||
innerFunc({status: 500});
|
||||
expect(toastService.add).toHaveBeenCalledWith(config.messageType || 'error', config.error);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -39,6 +39,11 @@
|
||||
function novaAPI(apiService, toastService, $window) {
|
||||
|
||||
var service = {
|
||||
getActionList: getActionList,
|
||||
getConsoleLog: getConsoleLog,
|
||||
getConsoleInfo: getConsoleInfo,
|
||||
getServerVolumes: getServerVolumes,
|
||||
getServerSecurityGroups: getServerSecurityGroups,
|
||||
getKeypairs: getKeypairs,
|
||||
createKeypair: createKeypair,
|
||||
getAvailabilityZones: getAvailabilityZones,
|
||||
@ -47,6 +52,15 @@
|
||||
getServer: getServer,
|
||||
getServers: getServers,
|
||||
getServerGroups: getServerGroups,
|
||||
deleteServer: deleteServer,
|
||||
pauseServer: pauseServer,
|
||||
unpauseServer: unpauseServer,
|
||||
suspendServer: suspendServer,
|
||||
resumeServer: resumeServer,
|
||||
softRebootServer: softRebootServer,
|
||||
hardRebootServer: hardRebootServer,
|
||||
startServer: startServer,
|
||||
stopServer: stopServer,
|
||||
getExtensions: getExtensions,
|
||||
getFlavors: getFlavors,
|
||||
getFlavor: getFlavor,
|
||||
@ -65,7 +79,8 @@
|
||||
getDefaultQuotaSets: getDefaultQuotaSets,
|
||||
setDefaultQuotaSets: setDefaultQuotaSets,
|
||||
getEditableQuotas: getEditableQuotas,
|
||||
updateProjectQuota: updateProjectQuota
|
||||
updateProjectQuota: updateProjectQuota,
|
||||
createServerSnapshot: createServerSnapshot
|
||||
};
|
||||
|
||||
return service;
|
||||
@ -264,6 +279,146 @@
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* @name deleteServer
|
||||
* @description
|
||||
* Delete a single server by ID.
|
||||
*
|
||||
* @param {String} serverId
|
||||
* Server to delete
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function deleteServer(serverId, suppressError) {
|
||||
var promise = apiService.delete('/api/nova/servers/' + serverId);
|
||||
|
||||
return suppressError ? promise : promise.error(function() {
|
||||
var msg = gettext('Unable to delete the server with id: %(id)s');
|
||||
toastService.add('error', interpolate(msg, { id: serverId }, true));
|
||||
});
|
||||
}
|
||||
|
||||
function serverStateOperation(operation, serverId, suppressError, errMsg) {
|
||||
var instruction = {"operation": operation};
|
||||
var promise = apiService.post('/api/nova/servers/' + serverId, instruction);
|
||||
|
||||
return suppressError ? promise : promise.error(function() {
|
||||
toastService.add('error', interpolate(errMsg, { id: serverId }, true));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @name startServer
|
||||
* @description
|
||||
* Start a single server by ID.
|
||||
*
|
||||
* @param {String} serverId
|
||||
* Server to start
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function startServer(serverId, suppressError) {
|
||||
return serverStateOperation('start', serverId, suppressError,
|
||||
gettext('Unable to start the server with id: %(id)s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name pauseServer
|
||||
* @description
|
||||
* Pause a single server by ID.
|
||||
*
|
||||
* @param {String} serverId
|
||||
* Server to pause
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function pauseServer(serverId, suppressError) {
|
||||
return serverStateOperation('pause', serverId, suppressError,
|
||||
gettext('Unable to pause the server with id: %(id)s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name unpauseServer
|
||||
* @description
|
||||
* Un-Pause a single server by ID.
|
||||
*
|
||||
* @param {String} serverId
|
||||
* Server to unpause
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function unpauseServer(serverId, suppressError) {
|
||||
return serverStateOperation('unpause', serverId, suppressError,
|
||||
gettext('Unable to unpause the server with id: %(id)s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name suspendServer
|
||||
* @description
|
||||
* Suspend a single server by ID.
|
||||
*
|
||||
* @param {String} serverId
|
||||
* Server to suspend
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function suspendServer(serverId, suppressError) {
|
||||
return serverStateOperation('suspend', serverId, suppressError,
|
||||
gettext('Unable to suspend the server with id: %(id)s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name resumeServer
|
||||
* @description
|
||||
* Resumes a single server by ID.
|
||||
*
|
||||
* @param {String} serverId
|
||||
* Server to resume
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function resumeServer(serverId, suppressError) {
|
||||
return serverStateOperation('resume', serverId, suppressError,
|
||||
gettext('Unable to resume the server with id: %(id)s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name softRebootServer
|
||||
* @description
|
||||
* Soft-reboots a single server by ID.
|
||||
*
|
||||
* @param {String} serverId
|
||||
* Server to reboot
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function softRebootServer(serverId, suppressError) {
|
||||
return serverStateOperation('soft_reboot', serverId, suppressError,
|
||||
gettext('Unable to soft-reboot the server with id: %(id)s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name hardRebootServer
|
||||
* @description
|
||||
* Hard-reboots a single server by ID.
|
||||
*
|
||||
* @param {String} serverId
|
||||
* Server to reboot
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function hardRebootServer(serverId, suppressError) {
|
||||
return serverStateOperation('hard_reboot', serverId, suppressError,
|
||||
gettext('Unable to hard-reboot the server with id: %(id)s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name stopServer
|
||||
* @description
|
||||
* Stop a single server by ID.
|
||||
*
|
||||
* @param {String} serverId
|
||||
* Server to stop
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function stopServer(serverId, suppressError) {
|
||||
return serverStateOperation('stop', serverId, suppressError,
|
||||
gettext('Unable to stop the server with id: %(id)s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name getExtensions
|
||||
* @param {Object} config - A configuration object
|
||||
@ -636,5 +791,109 @@
|
||||
return getCreateKeypairUrl(keyPairName) + "?regenerate=true";
|
||||
}
|
||||
|
||||
/**
|
||||
* @name createServerSnapshot
|
||||
* @param {Object} newSnapshot - The new server snapshot
|
||||
* @description
|
||||
* Create a server snapshot using the parameters supplied in the
|
||||
* newSnapshot. The required parameters:
|
||||
*
|
||||
* "name", "instance_id"
|
||||
* All strings
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function createServerSnapshot(newSnapshot) {
|
||||
return apiService.post('/api/nova/snapshots/', newSnapshot)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to create the server snapshot.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name getActionList
|
||||
* @param {String} ID - The server ID
|
||||
* @description
|
||||
* Retrieves a list of actions performed on the server.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function getActionList(instanceId) {
|
||||
return apiService.get('/api/nova/servers/' + instanceId + '/actions/')
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to load the server actions.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name getConsoleLog
|
||||
* @param {String} instanceId - The server ID
|
||||
* @param {Number} length - The number of lines to retrieve (optional)
|
||||
* @description
|
||||
* Retrieves a list of most recent console log lines from the server.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function getConsoleLog(instanceId, length) {
|
||||
var config = {};
|
||||
if (length) {
|
||||
config.length = length;
|
||||
}
|
||||
return apiService.post('/api/nova/servers/' + instanceId + '/console-output/', config)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to load the server console log.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name getConsoleInfo
|
||||
* @param {String} instanceId - The server ID
|
||||
* @param {String} type - The type of console to use (optional)
|
||||
* @description
|
||||
* Retrieves information used to get to a remote console for the given host.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function getConsoleInfo(instanceId, type) {
|
||||
var config = {};
|
||||
if (type) {
|
||||
config.console_type = type;
|
||||
}
|
||||
return apiService.post('/api/nova/servers/' + instanceId + '/console-info/', config)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to load the server console info.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name getServerVolumes
|
||||
* @param {String} instanceId - The server ID
|
||||
* @description
|
||||
* Retrieves information about volumes associated with the server
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function getServerVolumes(instanceId) {
|
||||
return apiService.get('/api/nova/servers/' + instanceId + '/volumes/')
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to load the server volumes.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name getServerSecurityGroups
|
||||
* @param {String} ID - The server ID
|
||||
* @description
|
||||
* Retrieves information about security groups associated with the server
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function getServerSecurityGroups(instanceId) {
|
||||
return apiService.get('/api/nova/servers/' + instanceId + '/security-groups/')
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to load the server security groups.'));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}());
|
||||
|
@ -46,6 +46,63 @@
|
||||
"path": "/api/nova/services/",
|
||||
"error": "Unable to retrieve the nova services."
|
||||
},
|
||||
{
|
||||
"func": "getConsoleLog",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/123/console-output/",
|
||||
"data": {
|
||||
"length": 6
|
||||
},
|
||||
"error": "Unable to load the server console log.",
|
||||
"testInput": [123, 6]
|
||||
},
|
||||
{
|
||||
"func": "getActionList",
|
||||
"method": "get",
|
||||
"path": "/api/nova/servers/123/actions/",
|
||||
"error": "Unable to load the server actions.",
|
||||
"testInput": [123]
|
||||
},
|
||||
{
|
||||
"func": "getConsoleLog",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/123/console-output/",
|
||||
"data": {},
|
||||
"error": "Unable to load the server console log.",
|
||||
"testInput": [123]
|
||||
},
|
||||
{
|
||||
"func": "getConsoleInfo",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/123/console-info/",
|
||||
"data": {
|
||||
"console_type": "VNC"
|
||||
},
|
||||
"error": "Unable to load the server console info.",
|
||||
"testInput": [123, "VNC"]
|
||||
},
|
||||
{
|
||||
"func": "getConsoleInfo",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/123/console-info/",
|
||||
"data": {},
|
||||
"error": "Unable to load the server console info.",
|
||||
"testInput": [123]
|
||||
},
|
||||
{
|
||||
"func": "getServerVolumes",
|
||||
"method": "get",
|
||||
"path": "/api/nova/servers/123/volumes/",
|
||||
"error": "Unable to load the server volumes.",
|
||||
"testInput": [123]
|
||||
},
|
||||
{
|
||||
"func": "getServerSecurityGroups",
|
||||
"method": "get",
|
||||
"path": "/api/nova/servers/123/security-groups/",
|
||||
"error": "Unable to load the server security groups.",
|
||||
"testInput": [123]
|
||||
},
|
||||
{
|
||||
"func": "getKeypairs",
|
||||
"method": "get",
|
||||
@ -76,6 +133,98 @@
|
||||
{}
|
||||
]
|
||||
},
|
||||
{
|
||||
"func": "deleteServer",
|
||||
"method": "delete",
|
||||
"path": "/api/nova/servers/12",
|
||||
"error": "Unable to delete the server with id: 12",
|
||||
"testInput": [12]
|
||||
},
|
||||
{
|
||||
"func": "deleteServer",
|
||||
"method": "delete",
|
||||
"path": "/api/nova/servers/12",
|
||||
"testInput": [12, true]
|
||||
},
|
||||
{
|
||||
"func": "createServerSnapshot",
|
||||
"method": "post",
|
||||
"path": "/api/nova/snapshots/",
|
||||
"data": {info: 12},
|
||||
"error": "Unable to create the server snapshot.",
|
||||
"testInput": [{info: 12}]
|
||||
},
|
||||
{
|
||||
"func": "startServer",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/12",
|
||||
"data": { operation: 'start' },
|
||||
"error": "Unable to start the server with id: 12",
|
||||
"testInput": [12]
|
||||
},
|
||||
{
|
||||
"func": "stopServer",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/12",
|
||||
"data": { operation: 'stop' },
|
||||
"error": "Unable to stop the server with id: 12",
|
||||
"testInput": [12]
|
||||
},
|
||||
{
|
||||
"func": "stopServer",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/12",
|
||||
"data": { operation: 'stop' },
|
||||
"testInput": [12, true]
|
||||
},
|
||||
{
|
||||
"func": "pauseServer",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/12",
|
||||
"data": { operation: 'pause' },
|
||||
"error": "Unable to pause the server with id: 12",
|
||||
"testInput": [12]
|
||||
},
|
||||
{
|
||||
"func": "unpauseServer",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/12",
|
||||
"data": { operation: 'unpause' },
|
||||
"error": "Unable to unpause the server with id: 12",
|
||||
"testInput": [12]
|
||||
},
|
||||
{
|
||||
"func": "suspendServer",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/12",
|
||||
"data": { operation: 'suspend' },
|
||||
"error": "Unable to suspend the server with id: 12",
|
||||
"testInput": [12]
|
||||
},
|
||||
{
|
||||
"func": "resumeServer",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/12",
|
||||
"data": { operation: 'resume' },
|
||||
"error": "Unable to resume the server with id: 12",
|
||||
"testInput": [12]
|
||||
},
|
||||
{
|
||||
"func": "softRebootServer",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/12",
|
||||
"data": { operation: 'soft_reboot' },
|
||||
"error": "Unable to soft-reboot the server with id: 12",
|
||||
"testInput": [12]
|
||||
},
|
||||
{
|
||||
"func": "hardRebootServer",
|
||||
"method": "post",
|
||||
"path": "/api/nova/servers/12",
|
||||
"data": { operation: 'hard_reboot' },
|
||||
"error": "Unable to hard-reboot the server with id: 12",
|
||||
"testInput": [12]
|
||||
},
|
||||
{
|
||||
"func": "getAvailabilityZones",
|
||||
"method": "get",
|
||||
@ -329,6 +478,12 @@
|
||||
"error": "Unable to delete the flavor with id: 42",
|
||||
"testInput": [42]
|
||||
},
|
||||
{
|
||||
"func": "deleteFlavor",
|
||||
"method": "delete",
|
||||
"path": "/api/nova/flavors/42/",
|
||||
"testInput": [42, true]
|
||||
},
|
||||
{
|
||||
"func": "getDefaultQuotaSets",
|
||||
"method": "get",
|
||||
|
@ -26,6 +26,150 @@ from novaclient import exceptions
|
||||
|
||||
|
||||
class NovaRestTestCase(test.TestCase):
|
||||
#
|
||||
# Snapshots
|
||||
#
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_snapshots_create(self, nc):
|
||||
body = '{"instance_id": "1234", "name": "foo"}'
|
||||
request = self.mock_rest_request(body=body)
|
||||
nc.snapshot_create.return_value = {'id': 'abcd', 'name': 'foo'}
|
||||
response = nova.Snapshots().post(request)
|
||||
self.assertStatusCode(response, 200)
|
||||
self.assertEqual(response.json, {'id': 'abcd', 'name': 'foo'})
|
||||
nc.snapshot_create.assert_called_once_with(request,
|
||||
instance_id='1234',
|
||||
name='foo')
|
||||
|
||||
#
|
||||
# Server Actions
|
||||
#
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_serveractions_list(self, nc):
|
||||
request = self.mock_rest_request()
|
||||
nc.instance_action_list.return_value = [
|
||||
mock.Mock(**{'to_dict.return_value': {'id': '1'}}),
|
||||
mock.Mock(**{'to_dict.return_value': {'id': '2'}}),
|
||||
]
|
||||
response = nova.ServerActions().get(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
self.assertEqual(response.json, {'items': [{'id': '1'}, {'id': '2'}]})
|
||||
nc.instance_action_list.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_server_start(self, nc):
|
||||
request = self.mock_rest_request(body='{"operation": "start"}')
|
||||
response = nova.Server().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
nc.server_start.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_server_stop(self, nc):
|
||||
request = self.mock_rest_request(body='{"operation": "stop"}')
|
||||
response = nova.Server().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
nc.server_stop.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_server_pause(self, nc):
|
||||
request = self.mock_rest_request(body='{"operation": "pause"}')
|
||||
response = nova.Server().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
nc.server_pause.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_server_unpause(self, nc):
|
||||
request = self.mock_rest_request(body='{"operation": "unpause"}')
|
||||
response = nova.Server().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
nc.server_unpause.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_server_suspend(self, nc):
|
||||
request = self.mock_rest_request(body='{"operation": "suspend"}')
|
||||
response = nova.Server().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
nc.server_suspend.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_server_resume(self, nc):
|
||||
request = self.mock_rest_request(body='{"operation": "resume"}')
|
||||
response = nova.Server().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
nc.server_resume.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_server_hard_reboot(self, nc):
|
||||
request = self.mock_rest_request(body='{"operation": "hard_reboot"}')
|
||||
response = nova.Server().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
nc.server_reboot.assert_called_once_with(request, 'MegaMan', False)
|
||||
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_server_soft_reboot(self, nc):
|
||||
request = self.mock_rest_request(body='{"operation": "soft_reboot"}')
|
||||
response = nova.Server().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
nc.server_reboot.assert_called_once_with(request, 'MegaMan', True)
|
||||
|
||||
#
|
||||
# Security Groups
|
||||
#
|
||||
@mock.patch.object(nova.api, 'network')
|
||||
def test_securitygroups_list(self, nc):
|
||||
request = self.mock_rest_request()
|
||||
nc.server_security_groups.return_value = [
|
||||
mock.Mock(**{'to_dict.return_value': {'id': '1'}}),
|
||||
mock.Mock(**{'to_dict.return_value': {'id': '2'}}),
|
||||
]
|
||||
response = nova.SecurityGroups().get(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
self.assertEqual(response.json, {'items': [{'id': '1'}, {'id': '2'}]})
|
||||
nc.server_security_groups.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
#
|
||||
# Console Output
|
||||
#
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_console_output(self, nc):
|
||||
request = self.mock_rest_request(body='{"length": 50}')
|
||||
nc.server_console_output.return_value = "this\nis\ncool"
|
||||
response = nova.ConsoleOutput().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
self.assertEqual(response.json, {'lines': ["this", "is", "cool"]})
|
||||
nc.server_console_output.assert_called_once_with(request,
|
||||
'MegaMan',
|
||||
tail_length=50)
|
||||
|
||||
#
|
||||
# Remote Console Info
|
||||
#
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_console_info(self, nc):
|
||||
request = self.mock_rest_request(body='{"console_type": "SERIAL"}')
|
||||
retval = mock.Mock(**{"url": "http://here.com"})
|
||||
nc.server_serial_console.return_value = retval
|
||||
response = nova.RemoteConsoleInfo().post(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
self.assertEqual(response.json,
|
||||
{"type": "SERIAL", "url": "http://here.com"})
|
||||
nc.server_serial_console.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
#
|
||||
# Volumes
|
||||
#
|
||||
@mock.patch.object(nova.api, 'nova')
|
||||
def test_volumes_list(self, nc):
|
||||
request = self.mock_rest_request()
|
||||
nc.instance_volumes_list.return_value = [
|
||||
mock.Mock(**{'to_dict.return_value': {'id': '1'}}),
|
||||
mock.Mock(**{'to_dict.return_value': {'id': '2'}}),
|
||||
]
|
||||
response = nova.Volumes().get(request, 'MegaMan')
|
||||
self.assertStatusCode(response, 200)
|
||||
self.assertEqual(response.json, {'items': [{'id': '1'}, {'id': '2'}]})
|
||||
nc.instance_volumes_list.assert_called_once_with(request, 'MegaMan')
|
||||
|
||||
#
|
||||
# Keypairs
|
||||
#
|
||||
|
Loading…
x
Reference in New Issue
Block a user