diff --git a/src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs b/src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs index a859b5b2c..38dbd1cb5 100644 --- a/src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs +++ b/src/ApiService/ApiService/onefuzzlib/ProxyOperations.cs @@ -1,7 +1,6 @@ using System.Threading.Tasks; using ApiService.OneFuzzLib.Orm; using Azure.Data.Tables; -using Azure.ResourceManager.Compute; using Azure.ResourceManager.Compute.Models; using Azure.Storage.Sas; using Microsoft.OneFuzz.Service.OneFuzzLib.Orm; @@ -175,7 +174,13 @@ public class ProxyOperations : StatefulOrm, IPr if (vmData != null) { if (vmData.ProvisioningState == "Failed") { - return await SetProvisionFailed(proxy, vmData); + var failedVmData = await _context.VmOperations.GetVmWithInstanceView(vm.Name); + if (failedVmData is null) { + // this should exist since we just loaded the VM above + throw new InvalidOperationException("Unable to load instance-view data for VM"); + } + + return await SetProvisionFailed(proxy, failedVmData.InstanceView); } else { await SaveProxyConfig(proxy); return await SetState(proxy, VmState.ExtensionsLaunch); @@ -207,8 +212,8 @@ public class ProxyOperations : StatefulOrm, IPr } } - private async System.Threading.Tasks.Task SetProvisionFailed(Proxy proxy, VirtualMachineData vmData) { - var errors = GetErrors(proxy, vmData).ToArray(); + private async System.Threading.Tasks.Task SetProvisionFailed(Proxy proxy, VirtualMachineInstanceView? instanceView) { + var errors = GetErrors(proxy, instanceView).ToArray(); return await SetFailed(proxy, new Error(ErrorCode.PROXY_FAILED, errors)); } @@ -223,8 +228,7 @@ public class ProxyOperations : StatefulOrm, IPr } - private static IEnumerable GetErrors(Proxy proxy, VirtualMachineData vmData) { - var instanceView = vmData.InstanceView; + private static IEnumerable GetErrors(Proxy proxy, VirtualMachineInstanceView? instanceView) { yield return "provisioning failed"; if (instanceView is null) { yield break; @@ -262,13 +266,18 @@ public class ProxyOperations : StatefulOrm, IPr var config = await _context.ConfigOperations.Fetch(); var vm = GetVm(proxy, config); var vmData = await _context.VmOperations.GetVm(vm.Name); - if (vmData is null) { return await SetFailed(proxy, new Error(ErrorCode.PROXY_FAILED, new[] { "azure not able to find vm" })); } if (vmData.ProvisioningState == "Failed") { - return await SetProvisionFailed(proxy, vmData); + var failedVmData = await _context.VmOperations.GetVmWithInstanceView(vm.Name); + if (failedVmData is null) { + // this should exist since we just loaded the VM above + throw new InvalidOperationException("Unable to load instance-view data for VM"); + } + + return await SetProvisionFailed(proxy, failedVmData.InstanceView); } var ip = await _context.IpOperations.GetPublicIp(vmData.NetworkProfile.NetworkInterfaces[0].Id); diff --git a/src/ApiService/ApiService/onefuzzlib/ReproOperations.cs b/src/ApiService/ApiService/onefuzzlib/ReproOperations.cs index 76b0e76f6..ee041c03f 100644 --- a/src/ApiService/ApiService/onefuzzlib/ReproOperations.cs +++ b/src/ApiService/ApiService/onefuzzlib/ReproOperations.cs @@ -1,7 +1,7 @@ using System.Globalization; using System.Threading.Tasks; using ApiService.OneFuzzLib.Orm; -using Azure.ResourceManager.Compute; +using Azure.ResourceManager.Compute.Models; namespace Microsoft.OneFuzz.Service; @@ -10,7 +10,7 @@ public interface IReproOperations : IStatefulOrm { public IAsyncEnumerable SearchStates(IEnumerable? states); - public Async.Task SetFailed(Repro repro, VirtualMachineData vmData); + public Async.Task SetFailed(Repro repro, VirtualMachineInstanceView instanceView); public Async.Task SetError(Repro repro, Error result); @@ -131,7 +131,13 @@ public class ReproOperations : StatefulOrm, IRe var vmData = await _context.VmOperations.GetVm(vm.Name); if (vmData != null) { if (vmData.ProvisioningState == "Failed") { - return await _context.ReproOperations.SetFailed(repro, vmData); + var failedVmData = await _context.VmOperations.GetVmWithInstanceView(vm.Name); + if (failedVmData is null) { + // this should exist since we just loaded the VM above + throw new InvalidOperationException("Unable to fetch instance-view data for VM"); + } + + return await _context.ReproOperations.SetFailed(repro, failedVmData.InstanceView); } else { var scriptResult = await BuildReproScript(repro); if (!scriptResult.IsOk) { @@ -181,7 +187,13 @@ public class ReproOperations : StatefulOrm, IRe } if (vmData.ProvisioningState == "Failed") { - return await _context.ReproOperations.SetFailed(repro, vmData); + var failedVmData = await _context.VmOperations.GetVmWithInstanceView(vm.Name); + if (failedVmData is null) { + // this should exist since we loaded the VM above + throw new InvalidOperationException("Unable to find instance-view data fro VM"); + } + + return await _context.ReproOperations.SetFailed(repro, failedVmData.InstanceView); } if (string.IsNullOrEmpty(repro.Ip)) { @@ -209,8 +221,8 @@ public class ReproOperations : StatefulOrm, IRe return repro; } - public async Async.Task SetFailed(Repro repro, VirtualMachineData vmData) { - var errors = vmData.InstanceView.Statuses + public async Async.Task SetFailed(Repro repro, VirtualMachineInstanceView instanceView) { + var errors = instanceView.Statuses .Where(status => status.Level.HasValue && string.Equals(status.Level?.ToString(), "error", StringComparison.OrdinalIgnoreCase)) .Select(status => $"{status.Code} {status.DisplayStatus} {status.Message}") .ToArray(); diff --git a/src/ApiService/ApiService/onefuzzlib/VmOperations.cs b/src/ApiService/ApiService/onefuzzlib/VmOperations.cs index 8eaf7af69..a93251b35 100644 --- a/src/ApiService/ApiService/onefuzzlib/VmOperations.cs +++ b/src/ApiService/ApiService/onefuzzlib/VmOperations.cs @@ -13,6 +13,8 @@ public interface IVmOperations { Task GetVm(string name); + Task GetVmWithInstanceView(string name); + Async.Task Delete(Vm vm); Async.Task Create(Vm vm); @@ -65,22 +67,31 @@ public class VmOperations : IVmOperations { } public async Task GetVm(string name) { - // _logTracer.Debug($"getting vm: {name}"); try { - var result = await _context.Creds.GetResourceGroupResource().GetVirtualMachineAsync(name, InstanceViewTypes.InstanceView); - if (result == null) { + var result = await _context.Creds.GetResourceGroupResource().GetVirtualMachineAsync(name); + if (result is null || !result.Value.HasData) { return null; } - if (result.Value.HasData) { - return result.Value.Data; - } + return result.Value.Data; } catch (RequestFailedException) { - // _logTracer.Debug($"vm does not exist {ex}); + // TODO: we shouldn't hide this error, only if it doesn't exist return null; } + } - return null; + public async Task GetVmWithInstanceView(string name) { + try { + var result = await _context.Creds.GetResourceGroupResource().GetVirtualMachineAsync(name, InstanceViewTypes.InstanceView); + if (result is null || !result.Value.HasData) { + return null; + } + + return result.Value.Data; + } catch (RequestFailedException) { + // TODO: we shouldn't hide this error, only if it doesn't exist + return null; + } } public async Async.Task Delete(Vm vm) {