openclient
Version:
An opinionated client for RESTful APIs (particularly OpenStack's).
145 lines (122 loc) • 4.97 kB
JavaScript
var async = require('async'),
base = require("../../client/base"),
error = require("../../client/error"),
urljoin = require("../../client/utils").urljoin;
var VolumeManager = base.Manager.extend({
namespace: "volumes",
get_base_url: function (params) {
var base_url = this._super(params);
if (params.detail) {
base_url = this.urljoin(base_url, 'detail');
}
return base_url;
},
all: function (params, callback) {
if (typeof params.detail === "undefined") params.detail = true;
return this._super(params, callback);
},
del: function (params, callback) {
// Allows smart selection of delete vs. force_delete if the volume status
// is passed in as part of params.data.
if (params.data && params.data.status) {
var status = params.data.status.toLowerCase();
delete params.data.status;
if (status !== "available" && status !== "error") {
return this.force_del(params, callback);
}
}
return this._super(params, callback);
},
_action: function (params, action, info, callback) {
var url = urljoin(this.get_base_url(params), params.id || params.data.id, "action");
if (params.data && params.data.id) delete params.data.id;
params = this.prepare_params(params, url, "singular");
params.data[action] = info || null;
return this.client.post(params, callback);
},
force_del: function (params, callback) { return this._action(params, "os-force_delete", null, callback); },
set_available_status: function (params, callback) { return this._action(params, "os-reset_status", {status: "available"}, callback); },
set_error_status: function (params, callback) { return this._action(params, "os-reset_status", {status: "error"}, callback); },
attach: function (params, callback) {
// NOTE: THIS DOES NOT MIRROR PYTHON-CINDERCLIENT'S ATTACH METHOD.
// Unlike python-cinderclient, this method *actually* attaches the
// volume to the instance.
var Nova = require("../../nova/v1.1/client"); // Avoid circular imports.
var nova = new Nova(this.client);
params.data.volumeId = params.id || params.data.id;
params.id = params.data.instance_uuid;
params.data.device = params.data.mountpoint || null;
if (params.data.id) delete params.data.id;
delete params.data.instance_uuid;
return nova.servers.attach(params, callback);
},
detach: function (params, callback) {
// NOTE: THIS DOES NOT MIRROR PYTHON-CINDERCLIENT'S DETACH METHOD.
// Unlike python-cinderclient, this method *actually* detaches the
// volume from the instance.
var Nova = require("../../nova/v1.1/client"); // Avoid circular imports.
var manager = this,
nova = new Nova(this.client),
vol_id = params.id || params.data.id;
if (!params.data || !params.data.instance_uuid) {
// Get volume w/ all attachments.
manager.get({
id: vol_id,
success: function (volume) {
// Detach all of them in parallel.
if (volume.attachments.length) {
var calls = [];
volume.attachments.forEach(function (attachment) {
calls.push(function (next) {
nova.servers.detach({
id: attachment.server_id,
data: {
volumeId: vol_id
},
success: function () {
next();
},
error: function (err, xhr) {
next({err: err, xhr: xhr});
}
});
});
});
async.parallel(calls, function (async_err) {
if (async_err) return manager.safe_complete(async_err.err, null, async_err.xhr, params, callback);
manager.safe_complete(null, null, {status: 202}, params, callback);
});
} else {
manager.safe_complete(null, null, {status: 202}, params, callback);
}
},
error: function (err, xhr) {
manager.safe_complete(err, null, xhr, params, callback);
}
});
} else {
return nova.servers.detach({
id: params.data.instance_uuid,
data: {
volumeId: vol_id
},
success: params.success,
error: params.error
}, callback);
}
},
_rpc_to_api: function (rpc) {
// Utility method to convert an RPC "notification"-style object into one
// which resembles data returned by the API for compatibility purposes.
var api = {};
api.id = rpc.volume_id;
api.display_name = rpc.display_name;
api.created_at = rpc.created_at.replace(/\s/g, '').replace(/(\d{4})-(\d{2})-(\d{2})([\d:]+)+.*/, "$1-$2-$3T$4Z");
api.size = rpc.size;
api.snapshot_id = rpc.snapshot_id;
api.status = rpc.status;
api["os-vol-tenant-attr:tenant_id"] = rpc.tenant_id;
return api;
}
});
module.exports = VolumeManager;