# Snapshot & Restore
> Note: Based on thin-provisioning of volumes. Please refer to [thin-provisioning proposal doc](https://github.com/topolvm/topolvm/pull/442).
## Goals
Allow users to create thin-snapshots from thinly-provisioned logical volumes.
These thin-snapshots, then set the foundation for allowing creation of snapshots and clones of persistent volume claims.
* **Allow Snapshot Creation**: Enable users to take snapshots of PVs that are provisioned by TopoLVM.
* **Restoring Snapshots**: Based on a volumesnapshot, a new PVC can be created that contains the contents of the snapshot.
* **Create Clones**: Allow users to create PVC to PVC clones; in which the clones are independent of the parent volumes.
## Introduction
### Thin-Snapshots
* Snapshots of thin LVs are efficient because the data blocks common to a thin LV and its snapshot are shared.
* As common data blocks are shared, A thin snapshot volume can reduce disk usage when there are multiple snapshots of the same origin volume.
* The thin snapshot volume is independent of parent volume deletion; and can be used independently just like a standalone volume.
* These thin logical volumes can be activated as `Read-Only` copies of the parent, and provided to kubernetes users as a VolumeSnapshotContent.
### Creating PVC Clones using thin-snapshots
* By design, a thin-snapshot of thin-volumes behave just as a new thinly-provisioned volume which is pre-populated with data from the parent.
* Thus, this thin-snapshot can be then provided to an user for Read-Write operations; on which, writes are performed on a Copy-On-Write basis (fast clones!).
* These thin logical volumes can be activated as `Read-Write` copies of the parent, and provided to kubernetes users as a PersistentVolume object.
* The PVC Clones created using thin-snapshots will also be `copy-on-write`, so increasing the number of clones of the origin should yield no major slowdown.
> Note: Although both kubernetes snapshots and clones are thin-snapshots internally, their access is set by activating them for required permissions. So, a snapshot is just activated for Read-Only mode, on the other hand, clones are activated to allow Read-Write operations by a user.
### Restoring thin-snapshots
* Thin snapshot volumes can be used as a logical volume origin for another snapshot. This allows for an arbitrary depth of recursive snapshots (snapshots of snapshots of snapshots ... )
* Blocks common to recursive snapshots are also shared in the thin pool. There is no limit to or degradation from sequences of snapshots.
* To provide a restored PVC to the user, we create another thin-provisioned snapshot of the available snapshot; and since lvm snapshots, by design, are writable, so they can be provided to users to use as a volume for a new PVC.
* This way, we also don't lose the identity of the snapshot after restoring; so we can restore a snapshot multiple times, to create multiple copies.
* These thin snapshot volumes are activated as `Read-Write` copies of the parent, and provided to kubernetes users as a PersistentVolume object.

> Note: The Snapshots, Restored volumes and Clones are all independent of their parent deletion.
## Flow of Operations for Snapshot Creation
* An user creates a `VolumeSnapshot` custom resource.
* The `snapshot-controller` which was watching the `VolumeSnapshot` object, sends a `Create VolumesnapshotContent` req to the api-server.
* The `external-snapshotter` kubernetes sidecar receives this request, and then sends a `CreateSnapshot` gRPC call to TopoLVM CSI driver.
* This `CreateSnapshot` request is received by the `topolovm-controller` which then create a `LogicalVolume` CR.
* `topolvm-node` on the target node finds the earlier created `LogicalVolume` CR.
* `topolvm-node` sends a volume create request to lvmd to create a thin-snapshot from the thin-volume datasource.
* `lvmd` creates an LVM logical volume as requested.
* `topolvm-node` updates the status of LogicalVolume.
* `topolvm-controller` finds the updated status of LogicalVolume.
* `topolvm-controller` sends the success (or failure) to `external-snapshotter` sidecar.
## Proposed LogicalVolume CR for Snapshots
```yaml
apiVersion: topolvm.cybozu.com/v1
kind: LogicalVolume
metadata:
name: snapcontent-b083470e-8293-47cc-810d-9561bd1754e6 # restore pv name
annotations:
spec:
name: snapcontent-b083470e-8293-47cc-810d-9561bd1754e6
nodeName: 192.168.26.40
# 'snapshot' is an optional field, that needs to specified only
# in case of snapshot logical volume creation.
snapshot:
# 'type' specifies if the snapshot will be thick or thin provisioned.
type: thin
# 'dataSource' specifies the volumeID of the parent logical volume.
dataSource: <string>
# 'accessType' specifies how the user intents to consume the
# thin-snapshot logical volume.
# If the thin-snap lv is to be provided to user as a snapshot,
# the accessType will be Read-Only.
# On the other hand, if the lv is to be given as a persistent volume,
# the accessType should be set to allow Read-Write operations.
accessType: ro
status:
volumeID: <Store the volume id of the lvm snapshot as same as existing LV.>
```
### Alternate Design of LogicalVolume CR for Snapshots
```yaml
apiVersion: topolvm.cybozu.com/v1
kind: LogicalVolume
metadata:
name: snapcontent-b083470e-8293-47cc-810d-9561bd1754e6
annotations:
spec:
name: snapcontent-b083470e-8293-47cc-810d-9561bd1754e6
nodeName: 192.168.26.40
# type: optional parameter, needs to be mentioned only in case of snapshots
type: thin-snapshot
accessType: ro
# dataSource field is nil when normal allocation. It specifies the volumeID of the parent logical volume(if present).
dataSource: <string>
status:
volumeID: <Store the volume id of the lvm snapshot as same as existing LV.>
```
## Proposed LogicalVolume CR for Restore operation
```yaml
apiVersion: topolvm.cybozu.com/v1
kind: LogicalVolume
metadata:
name: pvc-42041aee-79a2-4184-91aa-5e1df6068b9f # restore pv name
annotations:
spec:
name: pvc-42041aee-79a2-4184-91aa-5e1df6068b9f
nodeName: 192.168.26.40
# 'snapshot' is an optional field, that needs to specified only
# in case of snapshot logical volume creation.
snapshot:
# 'type' specifies if the snapshot will be thick or thin provisioned.
type: thin
# 'dataSource' specifies the volumeID of the parent logical volume.
dataSource: <string>
# 'accessType' specifies how the user intents to consume the
# thin-snapshot logical volume.
# If the thin-snap lv is to be provided to user as a snapshot,
# the accessType can be Read-Only.
# On the other hand, if the lv is to be given as a persistent volume (clone/restore),
# the accessType should be set to allow Read-Write operations.
accessType: rw
status:
volumeID: <Store the volume id of the lvm snapshot as same as existing LV.>
```
### Alternate LogicalVolume CR for Restore operation
```yaml
apiVersion: topolvm.cybozu.com/v1
kind: LogicalVolume
metadata:
name: pvc-42041aee-79a2-4184-91aa-5e1df6068b9f # restore pv name
annotations:
spec:
name: pvc-42041aee-79a2-4184-91aa-5e1df6068b9f
nodeName: 192.168.26.40
type: thin-snapshot
# 'accessType' specifies how the user intents to consume the
# thin-snapshot logical volume.
# If the thin-snap lv is to be provided to user as a snapshot,
# the accessType can be Read-Only.
# On the other hand, if the lv is to be given as a persistent volume,
# the accessType should be set to allow Read-Write operations.
accessType: rw
# dataSource field is nil when normal allocation.
# It specifies the volumeID of the parent logical volume.
dataSource: <string>
status:
volumeID: <Store the volume id of the lvm snapshot as same as existing LV.>
```
## LV Operations
* Snapshot creation from a thinly-provisioned volume:
```bash
$ lvcreate -s --name thinsnap VG0/thinvolume
```
* Activation of a logical volume
* A thinly-provisioned snapshot will be activated as Read-Only for snapshots and Read-Write for Clone/Restore scenarios.
For e.g: Activating a logical volume for Read-Write operations:
```bash
$ lvchange -ay -K VG0/thinsnap
```
* Restoring a Snapshot
```bash
$ lvcreate -s --name thin-restored VG0/thinsnap
```
## Deployment Changes
* Add `external-snapshotter` sidecar.
* Perform `snapshot-controller` deployment.
## Metrics and Monitoring
Should be already covered during adding support for `thin` logical volumes. See [thin-provisioning proposal doc](https://github.com/topolvm/topolvm/pull/442).
## Additional Notes
* When creating a thin snapshot volume, you do not specify the size of the volume.
* Thin snapshot volumes are not supported across the nodes in a cluster. The snapshot volume must be exclusively activated on only one cluster node.
# Cloning
On creation of a thinly-provisioned snapshot volume from the parent, it becomes an independent thinly-provisioned volume.
By design, thin-snapshots of thin-volumes behave as new thinly-provisioned volumes which are pre-populated with data from the parent.
Thus, this thin-snapshot can be then provided to an user for rw operations(clones); on which, writes are performed on a Copy-On-Write basis (fast clones!).

## Proposed LogicalVolume CR for Clone operation
```yaml
apiVersion: topolvm.cybozu.com/v1
kind: LogicalVolume
metadata:
name: pvc-42041aee-79a2-4184-91aa-5e1df6068b9f # restore pv name
annotations:
spec:
name: pvc-42041aee-79a2-4184-91aa-5e1df6068b9f
nodeName: 192.168.26.40
# 'snapshot' is an optional field, that needs to specified only
# in case of snapshot logical volume creation.
snapshot:
# 'type' specifies if the snapshot will be thick or thin provisioned.
type: thin
# 'dataSource' specifies the volumeID of the data source.
dataSource: <string>
# 'accessType' specifies how the user intents to consume the
# thin-snapshot logical volume.
# If the thin-snap lv is to be provided to user as a snapshot,
# the accessType can be Read-Only.
# On the other hand, if the lv is to be given as a persistent volume (clone/restore),
# the accessType should be set to allow Read-Write operations.
accessType: rw
status:
volumeID: <Store the volume id of the lvm snapshot as same as existing LV.>
```
### Alternate LogicalVolume CR for Clone operations
```yaml
apiVersion: topolvm.cybozu.com/v1
kind: LogicalVolume
metadata:
name: pvc-42041aee-79a2-4184-91aa-5e1df6068b9f # clone pv name
annotations:
spec:
name: pvc-42041aee-79a2-4184-91aa-5e1df6068b9f
nodeName: 192.168.26.40
type: thin-snapshot
accessType: rw
# dataSource field is nil when normal allocation.
dataSource: <string>
status:
volumeID: <Store the volume id of the lvm snapshot as same as existing LV.>
```
## Deployment Changes
No deployment changes required for adding support for cloning feature.
## Metrics and Monitoring
Should be already covered during adding support for `thin` logical volumes.
## Open Questions
- Should we only allow thick snapshot creation for thick volumes and thin-snapshots for thinly-provsioned volumes?
- If yes, then we don't need to specify `type` parameter for snapshot volumes in the LogicalVolume CR; as we can assume thin-snapshots if the parent is a thinly-provisioned volume.