synology snapshots, getcapacity, misc
This commit is contained in:
		
							parent
							
								
									c761b426d4
								
							
						
					
					
						commit
						66a22d718f
					
				|  | @ -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 }) | ||||
|  |  | |||
|  | @ -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 {}; | ||||
|   } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue