diff --git a/Source/Api/Api.csproj b/Source/Api/Api.csproj index 809e808..ebd6551 100644 --- a/Source/Api/Api.csproj +++ b/Source/Api/Api.csproj @@ -30,7 +30,7 @@ - + diff --git a/Source/Api/Controllers/ClonesController.cs b/Source/Api/Controllers/ClonesController.cs new file mode 100644 index 0000000..df32918 --- /dev/null +++ b/Source/Api/Controllers/ClonesController.cs @@ -0,0 +1,74 @@ +using Api.Core; +using Api.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using ROOT.Zfs.Public; +using ROOT.Zfs.Public.Arguments.Dataset; +using ROOT.Zfs.Public.Data; +using System.Collections.Generic; +using ROOT.Zfs.Public.Data.Datasets; +using System.Linq; +using ROOT.Zfs.Public.Arguments.Snapshots; + +namespace Api.Controllers +{ + /// + /// Contains methods for manipulating clones of snapshots, i.e. + /// datasets that is clones of a snapshot + /// + [Authorize] + [ApiController] + public class ClonesController : ApiControllerBase + { + private readonly IZfs _zfs; + + /// + public ClonesController(IZfsAccessor zfsAccessor) + { + _zfs = zfsAccessor.Zfs; + } + + /// + /// Lists datasets that are clones of snapshots + /// + /// A list of datasets that are clones + [HttpGet("/api/zfs/clones")] + public Response> ListClones() + { + DatasetListArgs args = new DatasetListArgs + { + DatasetTypes = DatasetTypes.Filesystem | DatasetTypes.Volume + }; + var datasets = _zfs.Datasets.List(args); + var clones = datasets.Where(d => d.IsClone); + return new Response> { Data = clones }; + } + + [HttpPost("/api/zfs/clones/{dataset}/{snapshot}")] + public Response CreateClone(string dataset, string snapshot, [FromBody] CloneRequest request) + { + var args = new SnapshotCloneArgs { Dataset = dataset, Snapshot = snapshot, TargetDataset = request.Dataset }; + if (request.Properties != null && request.Properties.Length > 0) + { + var properties = request.Properties.Select(p => new PropertyValue { Property = p.Name, Value = p.Value }).ToList(); + args.Properties = properties; + } + _zfs.Snapshots.Clone(args); + return new Response(); + } + + /// + /// Promotes a clone into an independent dataset. + /// When you promote a clone, it reverses the relationship between the original dataset and the clone. + /// So the clone becomes the "master" and the original becomes a dependent dataset + /// + /// The name of the dataset that should be promoted from a clone to its own dataset + [HttpPut("/api/zfs/clones/{name}")] + public Response PromoteClone(string name) + { + var args = new PromoteArgs { Name = name }; + _zfs.Datasets.Promote(args); + return new Response(); + } + } +} diff --git a/Source/Api/Models/CloneRequest.cs b/Source/Api/Models/CloneRequest.cs new file mode 100644 index 0000000..6fc09b9 --- /dev/null +++ b/Source/Api/Models/CloneRequest.cs @@ -0,0 +1,19 @@ +namespace Api.Models +{ + /// + /// Encapsulates the data required to clone a dataset to be independent + /// + public class CloneRequest + { + /// + /// Name of the dataset that should be promoted + /// + public string Dataset { get; set; } + + /// + /// Optional properties to set on the promoted dataset, if they should be different from original + /// + public PropertyData[] Properties { get; set; } + + } +}