diff --git a/client-api/api_lib/pvcapi.py b/client-api/api_lib/pvcapi.py index a5d512b2..2ab428bf 100755 --- a/client-api/api_lib/pvcapi.py +++ b/client-api/api_lib/pvcapi.py @@ -941,6 +941,23 @@ def ceph_volume_add(pool, name, size): } return flask.jsonify(output), retcode +def ceph_volume_clone(pool, name, source_volume): + """ + Clone a Ceph RBD volume to a new volume on the PVC Ceph storage cluster. + """ + zk_conn = pvc_common.startZKConnection(config['coordinators']) + retflag, retdata = pvc_ceph.clone_volume(zk_conn, pool, source_volume, name) + if retflag: + retcode = 200 + else: + retcode = 400 + + pvc_common.stopZKConnection(zk_conn) + output = { + 'message': retdata.replace('\"', '\'') + } + return flask.jsonify(output), retcode + def ceph_volume_resize(pool, name, size): """ Resize an existing Ceph RBD volume in the PVC Ceph storage cluster. diff --git a/client-api/pvc-api.py b/client-api/pvc-api.py index 51e3dde1..0254adeb 100755 --- a/client-api/pvc-api.py +++ b/client-api/pvc-api.py @@ -809,13 +809,25 @@ def api_ceph_volume_root(): else: return flask.jsonify({"message":"ERROR: A pool name must be spcified."}), 400 + # Get source_volume + if 'source_volume' in flask.request.values: + source_volume = flask.request.values['source_volume'] + else: + source_volume = None + # Get volume size if 'size' in flask.request.values: size = flask.request.values['size'] + elif source_volume: + # We ignore size if we're cloning a volume + size = None else: return flask.jsonify({"message":"ERROR: A volume size in bytes (or with an M/G/T suffix) must be specified."}), 400 - return pvcapi.ceph_volume_add(pool, volume, size) + if source_volume: + return pvcapi.ceph_volume_clone(pool, volume, source_volume) + else: + return pvcapi.ceph_volume_add(pool, volume, size) @api.route('/api/v1/storage/ceph/volume//', methods=['GET', 'PUT', 'DELETE']) @authenticator diff --git a/docs/manuals/api.md b/docs/manuals/api.md index c17c5e2e..18937ddb 100644 --- a/docs/manuals/api.md +++ b/docs/manuals/api.md @@ -633,10 +633,14 @@ Remove a Ceph RBD pool `` from the storage cluster. Return a JSON document containing information about all Ceph RBD volumes in the storage cluster. If `pool` is specified, return a JSON document containing information about all Ceph RBD volumes in Ceph RBD pool `pool`. If `limit` is specified, return a JSON document containing information about all Ceph RBD volumes with names matching `limit` as fuzzy regex. ###### `POST` - * Mandatory values: `volume`, `pool`, `size` - * Optional values: N/A + * Mandatory values: `volume`, `pool` + * Optional values: `size`, `source_volume` -Add a new Ceph RBD volume `` to Ceph RBD pool ``. `size` must be a valid size, in bytes or a single-character metric prefix of bytes, e.g. `1073741824` (1GB), `4096M`, or `20G`. +Add a new Ceph RBD volume `` to Ceph RBD pool ``. + +If `source_volume` is specified, clone the specified source volume into the new volume; when using this option, `size` is ignored. + +The value for `size` is mandatory if not cloning from a `source_volume`, and must be a valid storage size, in bytes or a single-character metric prefix of bytes, e.g. `1073741824` (1GB), `4096M`, or `20G`. PVC uses multiples of 1024 (MiB, GiB, etc.) consistently. #### `/api/v1/storage/ceph/volume//` * Methods: `GET`, `PUT`, `DELETE`