public async Task <Vm> Delete(string id) { //Implemented by stopping vm (if necessary), unregistering vm, and deleting vm folder //This protects the base disk from deletion. When we get vvols, and a data provider //with instance-clone of vvols, every vm will have its own disk, and we can just //delete the vm. await Connect(); Vm vm = _vmCache[id]; string tag = vm.Name.Tag(); _logger.LogDebug($"Delete: stopping vm {vm.Name}"); await Stop(id); vm.State = VmPowerState.Off; _logger.LogDebug($"Delete: unregistering vm {vm.Name}"); await _netman.Unprovision(vm.AsVim()); await _vim.UnregisterVMAsync(vm.AsVim()); string folder = vm.Path.Substring(0, vm.Path.LastIndexOf('/')); _logger.LogDebug($"Delete: deleting vm folder {folder}"); await _vim.DeleteDatastoreFile_TaskAsync(_sic.fileManager, folder, _datacenter); _vmCache.TryRemove(vm.Id, out vm); await _netman.Clean(tag); vm.Status = "initialized"; return(vm); }
public async Task <Vm> Start(string id) { await Connect(); Vm vm = _vmCache[id]; _logger.LogDebug($"Starting vm {vm.Name}"); if (vm.State != VmPowerState.Running) { ManagedObjectReference task = await _vim.PowerOnVM_TaskAsync(vm.AsVim(), null); TaskInfo info = await WaitForVimTask(task); vm.State = (info.state == TaskInfoState.success) ? VmPowerState.Running : vm.State; if (vm.State != VmPowerState.Running) { throw new Exception(info.error.localizedMessage); } //apply guestinfo for annotations await ReconfigureVm(id, "guest", "", ""); } _vmCache.TryUpdate(vm.Id, vm, vm); return(vm); }
public async Task <Vm> AnswerVmQuestion(string id, string question, string answer) { await Connect(); Vm vm = _vmCache[id]; await _vim.AnswerVMAsync(vm.AsVim(), question, answer); vm.Question = null; return(vm); }
public async Task <string> GetTicket(string id) { await Connect(); Vm vm = _vmCache[id]; _logger.LogDebug($"Aquiring mks ticket for vm {vm.Name}"); var ticket = await _vim.AcquireTicketAsync(vm.AsVim(), "webmks"); string port = (ticket.portSpecified && ticket.port != 443) ? $":{ticket.port}" : ""; return($"wss://{ticket.host ?? _config.Host}{port}/ticket/{ticket.ticket}"); }
public async Task <Vm> Deploy(VmTemplate template) { Vm vm = null; await Connect(); _logger.LogDebug("deploy: validate portgroups..."); await _netman.Provision(template); _logger.LogDebug("deploy: transform template..."); //var transformer = new VCenterTransformer { DVSuuid = _dvsuuid }; VirtualMachineConfigSpec vmcs = Transform.TemplateToVmSpec( template, _config.VmStore.Replace("{host}", _hostPrefix), _dvsuuid ); _logger.LogDebug("deploy: create vm..."); ManagedObjectReference task = await _vim.CreateVM_TaskAsync(_vms, vmcs, _pool, null); TaskInfo info = await WaitForVimTask(task); if (info.state == TaskInfoState.success) { _logger.LogDebug("deploy: load vm..."); await Task.Delay(200); vm = await GetVirtualMachine((ManagedObjectReference)info.result); _logger.LogDebug("deploy: create snapshot..."); task = await _vim.CreateSnapshot_TaskAsync( vm.AsVim(), "Root Snap", "Created by TopoMojo Deploy at " + DateTime.UtcNow.ToString("s") + "Z", false, false); info = await WaitForVimTask(task); if (template.AutoStart && info.state == TaskInfoState.success) { _logger.LogDebug("deploy: start vm..."); vm = await Start(vm.Id); } } else { throw new Exception(info.error.localizedMessage); } return(vm); }
public async Task <Vm> Revert(string id) { await Connect(); Vm vm = _vmCache[id]; _logger.LogDebug($"Stopping vm {vm.Name}"); ManagedObjectReference task = await _vim.RevertToCurrentSnapshot_TaskAsync( vm.AsVim(), null, false); TaskInfo info = await WaitForVimTask(task); if (vm.State == VmPowerState.Running) { await Start(id); } _vmCache.TryUpdate(vm.Id, vm, vm); return(vm); }
public async Task <Vm> Stop(string id) { await Connect(); Vm vm = _vmCache[id]; _logger.LogDebug($"Stopping vm {vm.Name}"); if (vm.State == VmPowerState.Running) { ManagedObjectReference task = await _vim.PowerOffVM_TaskAsync(vm.AsVim()); TaskInfo info = await WaitForVimTask(task); vm.State = (info.state == TaskInfoState.success) ? VmPowerState.Off : vm.State; if (vm.State == VmPowerState.Running) { throw new Exception(info.error.localizedMessage); } } _vmCache.TryUpdate(vm.Id, vm, vm); return(vm); }
//id, feature (iso, net, boot, guest), label, value public async Task <Vm> ReconfigureVm(string id, string feature, string label, string newvalue) { await Connect(); int index = 0; if (int.TryParse(label, out index)) { label = ""; } Vm vm = _vmCache[id]; RetrievePropertiesResponse response = await _vim.RetrievePropertiesAsync( _props, FilterFactory.VmFilter(vm.AsVim(), "config")); ObjectContent[] oc = response.returnval; VirtualMachineConfigInfo config = (VirtualMachineConfigInfo)oc[0].GetProperty("config"); VirtualMachineConfigSpec vmcs = new VirtualMachineConfigSpec(); switch (feature) { case "iso": VirtualCdrom cdrom = (VirtualCdrom)((label.HasValue()) ? config.hardware.device.Where(o => o.deviceInfo.label == label).SingleOrDefault() : config.hardware.device.OfType <VirtualCdrom>().ToArray()[index]); if (cdrom != null) { if (cdrom.backing.GetType() != typeof(VirtualCdromIsoBackingInfo)) { cdrom.backing = new VirtualCdromIsoBackingInfo(); } ((VirtualCdromIsoBackingInfo)cdrom.backing).fileName = newvalue; cdrom.connectable = new VirtualDeviceConnectInfo { connected = true, startConnected = true }; vmcs.deviceChange = new VirtualDeviceConfigSpec[] { new VirtualDeviceConfigSpec { device = cdrom, operation = VirtualDeviceConfigSpecOperation.edit, operationSpecified = true } }; } break; case "net": case "eth": VirtualEthernetCard card = (VirtualEthernetCard)((label.HasValue()) ? config.hardware.device.Where(o => o.deviceInfo.label == label).SingleOrDefault() : config.hardware.device.OfType <VirtualEthernetCard>().ToArray()[index]); if (card != null) { if (newvalue.StartsWith("_none_")) { card.connectable = new VirtualDeviceConnectInfo() { connected = false, startConnected = false, }; } else { _netman.UpdateEthernetCardBacking(card, newvalue); card.connectable.connected = true; } vmcs.deviceChange = new VirtualDeviceConfigSpec[] { new VirtualDeviceConfigSpec { device = card, operation = VirtualDeviceConfigSpecOperation.edit, operationSpecified = true } }; } break; case "boot": int delay = 0; if (Int32.TryParse(newvalue, out delay)) { vmcs.AddBootOption(delay); } break; case "guest": if (newvalue.HasValue() && !newvalue.EndsWith("\n")) { newvalue += "\n"; } vmcs.annotation = config.annotation + newvalue; if (vm.State == VmPowerState.Running && vmcs.annotation.HasValue()) { vmcs.AddGuestInfo(Regex.Split(vmcs.annotation, "\r\n|\r|\n")); } break; default: throw new Exception("Invalid change request."); //break; } ManagedObjectReference task = await _vim.ReconfigVM_TaskAsync(vm.AsVim(), vmcs); TaskInfo info = await WaitForVimTask(task); if (info.state == TaskInfoState.error) { throw new Exception(info.error.localizedMessage); } return(await GetVirtualMachine(vm.AsVim())); }
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); }