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) { async GetTargetByTargetID(target_id) {
let targets = await this.ListTargets(); let targets = await this.ListTargets();
let target = targets.find((i) => { let target = targets.find((i) => {
@ -237,18 +342,30 @@ class SynologyHttpClient {
//is_soft_feas_ignored: false, //is_soft_feas_ignored: false,
is_soft_feas_ignored: true, is_soft_feas_ignored: true,
}; };
try {
await this.do_request("GET", "entry.cgi", iscsi_lun_delete); await this.do_request("GET", "entry.cgi", iscsi_lun_delete);
} catch (err) {
/** // } catch (err) {
* 18990710 = already gone // /**
* LUN_BAD_LUN_UUID = 18990505 // * 18990710 = already gone
* LUN_NO_SUCH_SNAPSHOT = 18990532 // * LUN_BAD_LUN_UUID = 18990505
*/ // * LUN_NO_SUCH_SNAPSHOT = 18990532
if (![18990505].includes(err.body.error.code)) { // *//*
throw err; // 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 = {}) { async CreateTarget(data = {}) {
@ -311,9 +428,9 @@ class SynologyHttpClient {
/** /**
* 18990710 = non-existant * 18990710 = non-existant
*/ */
if (![18990710].includes(err.body.error.code)) { //if (![18990710].includes(err.body.error.code)) {
throw err; throw err;
} //}
} }
} }
@ -324,7 +441,7 @@ class SynologyHttpClient {
version: 1, version: 1,
}; };
await this.do_request( return await this.do_request(
"GET", "GET",
"entry.cgi", "entry.cgi",
Object.assign({}, iscsi_lun_extend, { uuid: uuid, new_size: size }) Object.assign({}, iscsi_lun_extend, { uuid: uuid, new_size: size })

View File

@ -53,8 +53,8 @@ class ControllerSynologyDriver extends CsiBaseDriver {
"CREATE_DELETE_VOLUME", "CREATE_DELETE_VOLUME",
//"PUBLISH_UNPUBLISH_VOLUME", //"PUBLISH_UNPUBLISH_VOLUME",
//"LIST_VOLUMES", //"LIST_VOLUMES",
//"GET_CAPACITY", "GET_CAPACITY",
//"CREATE_DELETE_SNAPSHOT", "CREATE_DELETE_SNAPSHOT",
//"LIST_SNAPSHOTS", //"LIST_SNAPSHOTS",
//"CLONE_VOLUME", //"CLONE_VOLUME",
//"PUBLISH_READONLY", //"PUBLISH_READONLY",
@ -69,7 +69,7 @@ class ControllerSynologyDriver extends CsiBaseDriver {
//"UNKNOWN", //"UNKNOWN",
"STAGE_UNSTAGE_VOLUME", "STAGE_UNSTAGE_VOLUME",
"GET_VOLUME_STATS", "GET_VOLUME_STATS",
//"EXPAND_VOLUME" "EXPAND_VOLUME",
]; ];
} }
} }
@ -407,13 +407,15 @@ class ControllerSynologyDriver extends CsiBaseDriver {
let iscsiName = driver.buildIscsiName(name); let iscsiName = driver.buildIscsiName(name);
let iqn = driver.options.iscsi.baseiqn + iscsiName; let iqn = driver.options.iscsi.baseiqn + iscsiName;
response = await httpClient.GetTargetByIQN(iqn); let target = await httpClient.GetTargetByIQN(iqn);
if (response) { if (target) {
await httpClient.DeleteTarget(response.target_id); await httpClient.DeleteTarget(target.target_id);
} }
response = await httpClient.GetLunUUIDByName(iscsiName); let lun_uuid = await httpClient.GetLunUUIDByName(iscsiName);
await httpClient.DeleteLun(response); if (lun_uuid) {
await httpClient.DeleteLun(lun_uuid);
}
break; break;
default: default:
throw new GrpcError( throw new GrpcError(
@ -523,10 +525,33 @@ class ControllerSynologyDriver extends CsiBaseDriver {
* @param {*} call * @param {*} call
*/ */
async GetCapacity(call) { async GetCapacity(call) {
throw new GrpcError( // throw new GrpcError(
grpc.status.UNIMPLEMENTED, // grpc.status.UNIMPLEMENTED,
`operation not supported by driver` // `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 * @param {*} call
*/ */
async CreateSnapshot(call) { async CreateSnapshot(call) {
throw new GrpcError(
grpc.status.UNIMPLEMENTED,
`operation not supported by driver`
);
const driver = this; const driver = this;
const httpClient = await driver.getHttpClient();
// both these are required // both these are required
let source_volume_id = call.request.source_volume_id; 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 { return {
snapshot: { snapshot: {
@ -605,7 +667,7 @@ class ControllerSynologyDriver extends CsiBaseDriver {
* is needed to create a volume from this snapshot. * is needed to create a volume from this snapshot.
*/ */
size_bytes: 0, size_bytes: 0,
snapshot_id, snapshot_id: `/lun/${lun.lun_id}/${response.body.data.snapshot_uuid}`,
source_volume_id: source_volume_id, source_volume_id: source_volume_id,
//https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto //https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto
creation_time: { creation_time: {
@ -624,12 +686,13 @@ class ControllerSynologyDriver extends CsiBaseDriver {
* @param {*} call * @param {*} call
*/ */
async DeleteSnapshot(call) { async DeleteSnapshot(call) {
throw new GrpcError( // throw new GrpcError(
grpc.status.UNIMPLEMENTED, // grpc.status.UNIMPLEMENTED,
`operation not supported by driver` // `operation not supported by driver`
); // );
const driver = this; const driver = this;
const httpClient = await driver.getHttpClient();
const snapshot_id = call.request.snapshot_id; 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 {}; return {};
} }