public async Task <Vm> Save(string id) { await Connect(); Vm vm = _vmCache[id]; //protect stock disks; only save a disk if it is local to the workspace //i.e. the disk folder matches the workspaceId if (vm.Name.Tag().HasValue() && !vm.DiskPath.Contains(vm.Name.Tag())) { throw new InvalidOperationException("External templates must be cloned into local templates in order to be saved."); } _logger.LogDebug($"Save: get current snap for vm {vm.Name}"); //Get the current snapshot mor ManagedObjectReference mor = null; RetrievePropertiesResponse response = await _vim.RetrievePropertiesAsync( _props, FilterFactory.VmFilter(vm.AsVim(), "snapshot")); ObjectContent[] oc = response.returnval; mor = ((VirtualMachineSnapshotInfo)oc.First().GetProperty("snapshot")).currentSnapshot as ManagedObjectReference; // if (oc.Length > 0 && oc[0].propSet.Length > 0 && oc[0].propSet[0].val != null) // mor = ((VirtualMachineSnapshotInfo)oc[0].propSet[0].val).currentSnapshot; //add new snapshot _logger.LogDebug($"Save: add new snap for vm {vm.Name}"); ManagedObjectReference task = await _vim.CreateSnapshot_TaskAsync( vm.AsVim(), "Root Snap", "Created by TopoMojo Save at " + DateTime.UtcNow.ToString("s") + "Z", false, false); TaskInfo info = await WaitForVimTask(task); //remove previous snapshot if (mor != null) { _logger.LogDebug($"Save: remove previous snap for vm {vm.Name}"); task = await _vim.RemoveSnapshot_TaskAsync(mor, false, true); await Task.Delay(500); info = await GetVimTaskInfo(task); if (info.state == TaskInfoState.error) { throw new Exception(info.error.localizedMessage); } if (info.progress < 100) { var t = new VimHostTask { Task = task, Action = "saving", WhenCreated = DateTime.UtcNow }; vm.Task = new VmTask { Name = t.Action, WhenCreated = t.WhenCreated, Progress = t.Progress }; _tasks.Add(vm.Id, t); } } _vmCache.TryUpdate(vm.Id, vm, vm); return(vm); }