瀏覽代碼

storage-node-v2: Add `delete storage bucket` command.

Shamil Gadelshin 3 年之前
父節點
當前提交
16875a3a9e

+ 96 - 37
storage-node-v2/README.md

@@ -29,14 +29,15 @@ USAGE
 # Commands
 <!-- commands -->
 * [`storage-node dev:init`](#storage-node-devinit)
+* [`storage-node dev:multihash`](#storage-node-devmultihash)
 * [`storage-node dev:upload`](#storage-node-devupload)
-* [`storage-node dev:verify-bag-id [FILE]`](#storage-node-devverify-bag-id-file)
+* [`storage-node dev:verify-bag-id`](#storage-node-devverify-bag-id)
 * [`storage-node help [COMMAND]`](#storage-node-help-command)
 * [`storage-node leader:create-bucket`](#storage-node-leadercreate-bucket)
+* [`storage-node leader:delete-bucket [FILE]`](#storage-node-leaderdelete-bucket-file)
 * [`storage-node leader:update-bag`](#storage-node-leaderupdate-bag)
 * [`storage-node leader:update-bag-limit`](#storage-node-leaderupdate-bag-limit)
 * [`storage-node leader:update-voucher-limits`](#storage-node-leaderupdate-voucher-limits)
-* [`storage-node multihash`](#storage-node-multihash)
 * [`storage-node operator:accept-invitation`](#storage-node-operatoraccept-invitation)
 * [`storage-node server [FILE]`](#storage-node-server-file)
 
@@ -49,11 +50,30 @@ USAGE
   $ storage-node dev:init
 
 OPTIONS
-  -h, --help  show CLI help
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
 ```
 
 _See code: [src/commands/dev/init.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/dev/init.ts)_
 
+## `storage-node dev:multihash`
+
+Creates a multihash (blake3) for a file.
+
+```
+USAGE
+  $ storage-node dev:multihash
+
+OPTIONS
+  -f, --file=file  (required) Path for a hashing file.
+  -h, --help       show CLI help
+```
+
+_See code: [src/commands/dev/multihash.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/dev/multihash.ts)_
+
 ## `storage-node dev:upload`
 
 Upload data object (development mode only).
@@ -63,25 +83,54 @@ USAGE
   $ storage-node dev:upload
 
 OPTIONS
-  -c, --cid=cid    (required) Data object IPFS content ID.
-  -h, --help       show CLI help
-  -s, --size=size  (required) Data object size.
+  -c, --cid=cid            (required) Data object IPFS content ID.
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -s, --size=size          (required) Data object size.
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
 ```
 
 _See code: [src/commands/dev/upload.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/dev/upload.ts)_
 
-## `storage-node dev:verify-bag-id [FILE]`
+## `storage-node dev:verify-bag-id`
 
-describe the command here
+The command verifies bag id supported by the storage node. Requires chain connection.
 
 ```
 USAGE
-  $ storage-node dev:verify-bag-id [FILE]
+  $ storage-node dev:verify-bag-id
 
 OPTIONS
-  -f, --force
-  -h, --help       show CLI help
-  -n, --name=name  name to print
+  -h, --help
+      show CLI help
+
+  -i, --bagId=bagId
+      (required) 
+             Bag ID. Format: {bag_type}:{sub_type}:{id}.
+             - Bag types: 'static', 'dynamic'
+             - Sub types: 'static:council', 'static:wg', 'dynamic:member', 'dynamic:channel'
+             - Id: 
+               - absent for 'static:council'
+               - working group name for 'static:wg'
+               - integer for 'dynamic:member' and 'dynamic:channel'
+             Examples:
+             - static:council
+             - static:wg:storage
+             - dynamic:member:4
+
+  -k, --keyfile=keyfile
+      Key file for the account. Mandatory in non-dev environment.
+
+  -m, --dev
+      Use development mode
+
+  -p, --password=password
+      Key file password (optional).
+
+  -u, --apiUrl=apiUrl
+      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
 ```
 
 _See code: [src/commands/dev/verify-bag-id.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/dev/verify-bag-id.ts)_
@@ -113,17 +162,34 @@ USAGE
 
 OPTIONS
   -a, --allow              Accepts new bags
-  -d, --dev                Use development mode
   -h, --help               show CLI help
   -i, --invited=invited    Invited storage operator ID (storage WG worker ID)
   -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
   -n, --number=number      Storage bucket max total objects number
   -p, --password=password  Key file password (optional).
   -s, --size=size          Storage bucket max total objects size
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
 ```
 
 _See code: [src/commands/leader/create-bucket.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/create-bucket.ts)_
 
+## `storage-node leader:delete-bucket [FILE]`
+
+describe the command here
+
+```
+USAGE
+  $ storage-node leader:delete-bucket [FILE]
+
+OPTIONS
+  -f, --force
+  -h, --help       show CLI help
+  -n, --name=name  name to print
+```
+
+_See code: [src/commands/leader/delete-bucket.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/delete-bucket.ts)_
+
 ## `storage-node leader:update-bag`
 
 Add/remove a storage bucket from a bag (adds by default).
@@ -136,9 +202,6 @@ OPTIONS
   -b, --bucket=bucket
       (required) Storage bucket ID
 
-  -d, --dev
-      Use development mode
-
   -h, --help
       show CLI help
 
@@ -159,11 +222,17 @@ OPTIONS
   -k, --keyfile=keyfile
       Key file for the account. Mandatory in non-dev environment.
 
+  -m, --dev
+      Use development mode
+
   -p, --password=password
       Key file password (optional).
 
   -r, --remove
       Remove a bucket from the bag
+
+  -u, --apiUrl=apiUrl
+      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
 ```
 
 _See code: [src/commands/leader/update-bag.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-bag.ts)_
@@ -177,11 +246,12 @@ USAGE
   $ storage-node leader:update-bag-limit
 
 OPTIONS
-  -d, --dev                Use development mode
   -h, --help               show CLI help
   -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
   -l, --limit=limit        (required) New StorageBucketsPerBagLimit value
+  -m, --dev                Use development mode
   -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
 ```
 
 _See code: [src/commands/leader/update-bag-limit.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-bag-limit.ts)_
@@ -195,31 +265,17 @@ USAGE
   $ storage-node leader:update-voucher-limits
 
 OPTIONS
-  -d, --dev                Use development mode
   -h, --help               show CLI help
   -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
   -o, --objects=objects    (required) New 'max voucher object number limit' value
   -p, --password=password  Key file password (optional).
   -s, --size=size          (required) New 'max voucher object size limit' value
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
 ```
 
 _See code: [src/commands/leader/update-voucher-limits.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-voucher-limits.ts)_
 
-## `storage-node multihash`
-
-Creates a multihash (blake3) for a file.
-
-```
-USAGE
-  $ storage-node multihash
-
-OPTIONS
-  -f, --file=file  (required) Path for a hashing file.
-  -h, --help       show CLI help
-```
-
-_See code: [src/commands/multihash.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/multihash.ts)_
-
 ## `storage-node operator:accept-invitation`
 
 Accept pending storage bucket invitation.
@@ -230,10 +286,11 @@ USAGE
 
 OPTIONS
   -b, --bucket=bucket      (required) Storage bucket ID
-  -d, --dev                Use development mode
   -h, --help               show CLI help
   -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
   -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
   -w, --worker=worker      (required) Storage operator worker ID
 ```
 
@@ -248,12 +305,14 @@ USAGE
   $ storage-node server [FILE]
 
 OPTIONS
-  -d, --dev                Use development mode
+  -d, --uploads=uploads    (required) Data uploading directory (absolute path).
   -h, --help               show CLI help
   -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -o, --port=port          (required) Server port.
   -p, --password=password  Key file password (optional).
-  -p, --port=port          (required) Server port.
-  -u, --uploads=uploads    (required) Data uploading directory.
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+  -w, --worker=worker      (required) Storage provider worker ID
 ```
 
 _See code: [src/commands/server.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/server.ts)_

+ 9 - 0
storage-node-v2/src/command-base/ApiCommandBase.ts

@@ -100,4 +100,13 @@ export default abstract class ApiCommandBase extends Command {
 
     return account
   }
+
+  exitAfterRuntimeCall(success: boolean): never {
+    let exitCode = ExitCodes.OK
+    if (!success) {
+      exitCode = ExitCodes.UnsuccessfulRuntimeCall
+    }
+
+    this.exit(exitCode)
+  }
 }

+ 2 - 1
storage-node-v2/src/command-base/ExitCodes.ts

@@ -4,6 +4,7 @@ enum ExitCodes {
   InvalidParameters = 100,
   DevelopmentModeOnly,
   FileError,
-  ApiError = 1000,
+  ApiError = 200,
+  UnsuccessfulRuntimeCall,
 }
 export = ExitCodes

+ 3 - 1
storage-node-v2/src/commands/leader/create-bucket.ts

@@ -39,7 +39,7 @@ export default class LeaderCreateBucket extends ApiCommandBase {
     const account = this.getAccount(flags)
     const api = await this.getApi()
 
-    await createStorageBucket(
+    const success = await createStorageBucket(
       api,
       account,
       invitedWorker,
@@ -47,5 +47,7 @@ export default class LeaderCreateBucket extends ApiCommandBase {
       objectSize,
       objectNumber
     )
+
+    this.exitAfterRuntimeCall(success)
   }
 }

+ 35 - 0
storage-node-v2/src/commands/leader/delete-bucket.ts

@@ -0,0 +1,35 @@
+import { deleteStorageBucket } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+export default class LeaderDeleteBucket extends ApiCommandBase {
+  static description = `Deletes a storage bucket. Requires storage working group leader permissions.`
+
+  static flags = {
+    bucketId: flags.integer({
+      char: 'i',
+      required: true,
+      description: 'Storage bucket ID',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderDeleteBucket)
+
+    const storageBucketId = flags.bucketId
+
+    logger.info('Deleting storage bucket...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    const success = await deleteStorageBucket(api, account, storageBucketId)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 3 - 1
storage-node-v2/src/commands/leader/update-bag-limit.ts

@@ -28,6 +28,8 @@ export default class LeaderUpdateBagLimit extends ApiCommandBase {
     const limit = flags.limit ?? 0
 
     const api = await this.getApi()
-    await updateStorageBucketsPerBagLimit(api, account, limit)
+    const success = await updateStorageBucketsPerBagLimit(api, account, limit)
+
+    this.exitAfterRuntimeCall(success)
   }
 }

+ 9 - 1
storage-node-v2/src/commands/leader/update-bag.ts

@@ -52,6 +52,14 @@ export default class LeaderUpdateBag extends ApiCommandBase {
     const api = await this.getApi()
     const bagId = parseBagId(api, flags.bagId)
 
-    await updateStorageBucketsForBag(api, bagId, account, bucket, flags.remove)
+    const success = await updateStorageBucketsForBag(
+      api,
+      bagId,
+      account,
+      bucket,
+      flags.remove
+    )
+
+    this.exitAfterRuntimeCall(success)
   }
 }

+ 3 - 1
storage-node-v2/src/commands/leader/update-voucher-limits.ts

@@ -34,11 +34,13 @@ export default class LeaderUpdateVoucherLimits extends ApiCommandBase {
     const sizeLimit = flags.size ?? 0
 
     const api = await this.getApi()
-    await updateStorageBucketsVoucherMaxLimits(
+    const success = await updateStorageBucketsVoucherMaxLimits(
       api,
       account,
       sizeLimit,
       objectsLimit
     )
+
+    this.exitAfterRuntimeCall(success)
   }
 }

+ 8 - 1
storage-node-v2/src/commands/operator/accept-invitation.ts

@@ -34,6 +34,13 @@ export default class OperatorAcceptInvitation extends ApiCommandBase {
     const account = this.getAccount(flags)
 
     const api = await this.getApi()
-    await acceptStorageBucketInvitation(api, account, worker, bucket)
+    const success = await acceptStorageBucketInvitation(
+      api,
+      account,
+      worker,
+      bucket
+    )
+
+    this.exitAfterRuntimeCall(success)
   }
 }

+ 36 - 7
storage-node-v2/src/services/runtime/extrinsics.ts

@@ -13,7 +13,7 @@ export async function createStorageBucket(
   allowedNewBags = true,
   sizeLimit = 0,
   objectsLimit = 0
-): Promise<void> {
+): Promise<boolean> {
   try {
     const invitedWorkerValue = api.createType('Option<WorkerId>', invitedWorker)
 
@@ -25,7 +25,10 @@ export async function createStorageBucket(
     ])
   } catch (err) {
     logger.error(`Api Error: ${err}`)
+    return false
   }
+
+  return true
 }
 
 export async function acceptStorageBucketInvitation(
@@ -33,7 +36,7 @@ export async function acceptStorageBucketInvitation(
   account: KeyringPair,
   workerId: number,
   storageBucketId: number
-): Promise<void> {
+): Promise<boolean> {
   try {
     await sendAndFollowNamedTx(
       api,
@@ -44,18 +47,18 @@ export async function acceptStorageBucketInvitation(
     )
   } catch (err) {
     logger.error(`Api Error: ${err}`)
+    return false
   }
+  return true
 }
 
-// TODO: Add dynamic bag parameter
-
 export async function updateStorageBucketsForBag(
   api: ApiPromise,
   bagId: BagId,
   account: KeyringPair,
   bucketId: number,
   removeBucket: boolean
-): Promise<void> {
+): Promise<boolean> {
   try {
     let addBuckets: CodecArg
     let removeBuckets: CodecArg
@@ -75,7 +78,10 @@ export async function updateStorageBucketsForBag(
     )
   } catch (err) {
     logger.error(`Api Error: ${err}`)
+    return false
   }
+
+  return true
 }
 
 export async function uploadDataObjects(
@@ -139,7 +145,7 @@ export async function updateStorageBucketsPerBagLimit(
   api: ApiPromise,
   account: KeyringPair,
   newLimit: number
-): Promise<void> {
+): Promise<boolean> {
   try {
     await sendAndFollowNamedTx(
       api,
@@ -148,8 +154,11 @@ export async function updateStorageBucketsPerBagLimit(
       'updateStorageBucketsPerBagLimit',
       [newLimit]
     )
+
+    return true
   } catch (err) {
     logger.error(`Api Error: ${err}`)
+    return false
   }
 }
 
@@ -158,7 +167,7 @@ export async function updateStorageBucketsVoucherMaxLimits(
   account: KeyringPair,
   newSizeLimit: number,
   newObjectLimit: number
-): Promise<void> {
+): Promise<boolean> {
   try {
     await sendAndFollowNamedTx(
       api,
@@ -169,5 +178,25 @@ export async function updateStorageBucketsVoucherMaxLimits(
     )
   } catch (err) {
     logger.error(`Api Error: ${err}`)
+    return false
+  }
+
+  return true
+}
+
+export async function deleteStorageBucket(
+  api: ApiPromise,
+  account: KeyringPair,
+  bucketId: number
+): Promise<boolean> {
+  try {
+    await sendAndFollowNamedTx(api, account, 'storage', 'deleteStorageBucket', [
+      bucketId,
+    ])
+  } catch (err) {
+    logger.error(`Api Error: ${err}`)
+    return false
   }
+
+  return true
 }