Merge pull request #105 from huntermm18/next

synology snapshots, getcapacity, misc
This commit is contained in:
Travis Glenn Hansen 2021-07-26 20:17:26 -06:00 committed by GitHub
commit 5c27e3296d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 230 additions and 38 deletions

View File

@ -143,6 +143,111 @@ class SynologyHttpClient {
}
}
async GetLunIDByName(name) {
const lun_list = {
api: "SYNO.Core.ISCSI.LUN",
version: "1",
method: "list",
};
let response = await this.do_request("GET", "entry.cgi", lun_list);
let lun = response.body.data.luns.find((i) => {
return i.name == name;
});
if (lun) {
return lun.lun_id;
}
}
async GetLunByName(name) {
const lun_list = {
api: "SYNO.Core.ISCSI.LUN",
version: "1",
method: "list",
};
let response = await this.do_request("GET", "entry.cgi", lun_list);
let lun = response.body.data.luns.find((i) => {
return i.name == name;
});
if (lun) {
return lun;
}
}
async GetSnapshotByLunIDAndName(lun_id, name) {
const get_snapshot_info = {
lid: lun_id, //check?
api: "SYNO.Core.Storage.iSCSILUN",
method: "load_snapshot",
version: 1,
};
let response = await this.do_request("GET", "entry.cgi", get_snapshot_info);
if (response.body.data) {
let snapshot = response.body.data.find((i) => {
return i.desc == name;
});
if (snapshot) {
return snapshot;
}
}
}
async GetSnapshotByLunIDAndSnapshotUUID(lun_id, snapshot_uuid) {
const get_snapshot_info = {
lid: lun_id, //check?
api: "SYNO.Core.Storage.iSCSILUN",
method: "load_snapshot",
version: 1,
};
let response = await this.do_request("GET", "entry.cgi", get_snapshot_info);
if (response.body.data) {
let snapshot = response.body.data.find((i) => {
return i.uuid == snapshot_uuid;
});
if (snapshot) {
return snapshot;
}
}
}
async DeleteSnapshot(snapshot_uuid) {
const iscsi_snapshot_delete = {
api: "SYNO.Core.ISCSI.LUN",
method: "delete_snapshot",
version: 1,
snapshot_uuid: snapshot_uuid, // snapshot_id
deleted_by: "democratic_csi", // ?
};
let response = await this.do_request(
"GET",
"entry.cgi",
iscsi_snapshot_delete
);
// return?
}
async GetVolumeInfo(volume_path) {
let data = {
api: "SYNO.Core.Storage.Volume",
method: "get",
version: "1",
//volume_path: "/volume1",
volume_path,
};
return await this.do_request("GET", "entry.cgi", data);
}
async GetTargetByTargetID(target_id) {
let targets = await this.ListTargets();
let target = targets.find((i) => {
@ -237,18 +342,30 @@ class SynologyHttpClient {
//is_soft_feas_ignored: false,
is_soft_feas_ignored: true,
};
try {
await this.do_request("GET", "entry.cgi", iscsi_lun_delete);
} catch (err) {
/**
* 18990710 = already gone
* LUN_BAD_LUN_UUID = 18990505
* LUN_NO_SUCH_SNAPSHOT = 18990532
*/
if (![18990505].includes(err.body.error.code)) {
throw err;
}
}
await this.do_request("GET", "entry.cgi", iscsi_lun_delete);
// } catch (err) {
// /**
// * 18990710 = already gone
// * LUN_BAD_LUN_UUID = 18990505
// * LUN_NO_SUCH_SNAPSHOT = 18990532
// *//*
// if (![18990505].includes(err.body.error.code)) {
// throw err;
// }
// }
// */
}
async CreateSnapshot(data) {
data = Object.assign({}, data, {
api: "SYNO.Core.ISCSI.LUN",
method: "take_snapshot",
version: 1,
});
return await this.do_request("GET", "entry.cgi", data);
}
async CreateTarget(data = {}) {
@ -311,9 +428,9 @@ class SynologyHttpClient {
/**
* 18990710 = non-existant
*/
if (![18990710].includes(err.body.error.code)) {
throw err;
}
//if (![18990710].includes(err.body.error.code)) {
throw err;
//}
}
}
@ -324,7 +441,7 @@ class SynologyHttpClient {
version: 1,
};
await this.do_request(
return await this.do_request(
"GET",
"entry.cgi",
Object.assign({}, iscsi_lun_extend, { uuid: uuid, new_size: size })

View File

@ -53,8 +53,8 @@ class ControllerSynologyDriver extends CsiBaseDriver {
"CREATE_DELETE_VOLUME",
//"PUBLISH_UNPUBLISH_VOLUME",
//"LIST_VOLUMES",
//"GET_CAPACITY",
//"CREATE_DELETE_SNAPSHOT",
"GET_CAPACITY",
"CREATE_DELETE_SNAPSHOT",
//"LIST_SNAPSHOTS",
//"CLONE_VOLUME",
//"PUBLISH_READONLY",
@ -69,7 +69,7 @@ class ControllerSynologyDriver extends CsiBaseDriver {
//"UNKNOWN",
"STAGE_UNSTAGE_VOLUME",
"GET_VOLUME_STATS",
//"EXPAND_VOLUME"
"EXPAND_VOLUME",
];
}
}
@ -407,13 +407,15 @@ class ControllerSynologyDriver extends CsiBaseDriver {
let iscsiName = driver.buildIscsiName(name);
let iqn = driver.options.iscsi.baseiqn + iscsiName;
response = await httpClient.GetTargetByIQN(iqn);
if (response) {
await httpClient.DeleteTarget(response.target_id);
let target = await httpClient.GetTargetByIQN(iqn);
if (target) {
await httpClient.DeleteTarget(target.target_id);
}
response = await httpClient.GetLunUUIDByName(iscsiName);
await httpClient.DeleteLun(response);
let lun_uuid = await httpClient.GetLunUUIDByName(iscsiName);
if (lun_uuid) {
await httpClient.DeleteLun(lun_uuid);
}
break;
default:
throw new GrpcError(
@ -523,10 +525,33 @@ class ControllerSynologyDriver extends CsiBaseDriver {
* @param {*} call
*/
async GetCapacity(call) {
throw new GrpcError(
grpc.status.UNIMPLEMENTED,
`operation not supported by driver`
// throw new GrpcError(
// grpc.status.UNIMPLEMENTED,
// `operation not supported by driver`
// );
const driver = this;
const httpClient = await driver.getHttpClient();
if (!driver.options.synology.location) {
throw new GrpcError(
grpc.status.FAILED_PRECONDITION,
`invalid configuration: missing location`
);
}
if (call.request.volume_capabilities) {
const result = this.assertCapabilities(call.request.volume_capabilities);
if (result.valid !== true) {
return { available_capacity: 0 };
}
}
let response = await httpClient.GetVolumeInfo(
driver.options.synology.location
);
return { available_capacity: response.body.data.volume.size_free_byte };
}
/**
@ -558,11 +583,8 @@ class ControllerSynologyDriver extends CsiBaseDriver {
* @param {*} call
*/
async CreateSnapshot(call) {
throw new GrpcError(
grpc.status.UNIMPLEMENTED,
`operation not supported by driver`
);
const driver = this;
const httpClient = await driver.getHttpClient();
// both these are required
let source_volume_id = call.request.source_volume_id;
@ -596,7 +618,47 @@ class ControllerSynologyDriver extends CsiBaseDriver {
);
}
// TODO: create snapshot here
// create snapshot here
let iscsiName = driver.buildIscsiName(source_volume_id);
let lun = await httpClient.GetLunByName(iscsiName);
if (!lun) {
throw new GrpcError(
grpc.status.INVALID_ARGUMENT,
`invalid source_volume_id: ${source_volume_id}`
);
}
// check for already exists
let snapshot = await httpClient.GetSnapshotByLunIDAndName(lun.lun_id, name);
if (snapshot) {
return {
snapshot: {
/**
* The purpose of this field is to give CO guidance on how much space
* is needed to create a volume from this snapshot.
*/
size_bytes: 0,
snapshot_id: `/lun/${lun.lun_id}/${snapshot.uuid}`, // add shanpshot_uuid //fixme
source_volume_id: source_volume_id,
//https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto
creation_time: {
seconds: snapshot.time,
nanos: 0,
},
ready_to_use: true,
},
};
}
let data = Object.assign({}, driver.options.iscsi.lunSnapshotAttributes, {
src_lun_uuid: lun.uuid,
taken_by: "democratic-csi",
description: name, //check
});
let response = await httpClient.CreateSnapshot(data);
return {
snapshot: {
@ -605,7 +667,7 @@ class ControllerSynologyDriver extends CsiBaseDriver {
* is needed to create a volume from this snapshot.
*/
size_bytes: 0,
snapshot_id,
snapshot_id: `/lun/${lun.lun_id}/${response.body.data.snapshot_uuid}`,
source_volume_id: source_volume_id,
//https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto
creation_time: {
@ -624,12 +686,13 @@ class ControllerSynologyDriver extends CsiBaseDriver {
* @param {*} call
*/
async DeleteSnapshot(call) {
throw new GrpcError(
grpc.status.UNIMPLEMENTED,
`operation not supported by driver`
);
// throw new GrpcError(
// grpc.status.UNIMPLEMENTED,
// `operation not supported by driver`
// );
const driver = this;
const httpClient = await driver.getHttpClient();
const snapshot_id = call.request.snapshot_id;
@ -640,7 +703,19 @@ class ControllerSynologyDriver extends CsiBaseDriver {
);
}
// TODO: delete snapshot here
let parts = snapshot_id.split("/");
let lun_id = parts[2];
let snapshot_uuid = parts[3];
// TODO: delete snapshot
let snapshot = await httpClient.GetSnapshotByLunIDAndSnapshotUUID(
lun_id,
snapshot_uuid
);
if (snapshot) {
await httpClient.DeleteSnapshot(snapshot.uuid);
}
return {};
}