public VmssOperations(ILogTracer log, IOnefuzzContext context, IMemoryCache cache) { _log = log; _creds = context.Creds; _imageOps = context.ImageOperations; _serviceConfig = context.ServiceConfiguration; _cache = cache; }
public static async Task <ImagesListResponse> FindImageByTagNameAsync(this IImageOperations imageOperations, string tagName) { if (imageOperations == null) { throw new ArgumentNullException(nameof(imageOperations)); } IList <ImagesListResponse> images = await imageOperations.ListImagesAsync( new ImagesListParameters() ); // Always retrieve the latest image. return(images .Where(image => image.RepoTags != null && image.RepoTags.Contains(tagName) ) .OrderByDescending(image => image.Created) .FirstOrDefault()); }
public async Task <OneFuzzResult <Os> > GetOs(string region, string image) { string?name = null; try { var parsed = _context.Creds.ParseResourceId(image); parsed = await _context.Creds.GetData(parsed); if (string.Equals(parsed.Id.ResourceType, "galleries", StringComparison.OrdinalIgnoreCase)) { try { // This is not _exactly_ the same as the python code // because in C# we don't have access to child_name_1 var gallery = await _context.Creds.GetResourceGroupResource().GetGalleries().GetAsync( parsed.Data.Name ); var galleryImage = gallery.Value.GetGalleryImages() .ToEnumerable() .Where(galleryImage => string.Equals(galleryImage.Id, parsed.Id, StringComparison.OrdinalIgnoreCase)) .First(); galleryImage = await galleryImage.GetAsync(); name = galleryImage.Data?.OSType?.ToString().ToLowerInvariant() !; } catch (Exception ex) when( ex is RequestFailedException || ex is NullReferenceException ) { return(OneFuzzResult <Os> .Error( ErrorCode.INVALID_IMAGE, ex.ToString() )); } } else { try { name = (await _context.Creds.GetResourceGroupResource().GetImages().GetAsync( parsed.Data.Name )).Value.Data.StorageProfile.OSDisk.OSType.ToString().ToLowerInvariant(); } catch (Exception ex) when( ex is RequestFailedException || ex is NullReferenceException ) { return(OneFuzzResult <Os> .Error( ErrorCode.INVALID_IMAGE, ex.ToString() )); } } } catch (FormatException) { var imageInfo = IImageOperations.GetImageInfo(image); try { var subscription = await _context.Creds.ArmClient.GetDefaultSubscriptionAsync(); string version; if (string.Equals(imageInfo.Version, "latest", StringComparison.Ordinal)) { version = (await subscription.GetVirtualMachineImagesAsync( region, imageInfo.Publisher, imageInfo.Offer, imageInfo.Sku, top: 1 ).FirstAsync()).Name; } else { version = imageInfo.Version; } name = (await subscription.GetVirtualMachineImageAsync( region, imageInfo.Publisher, imageInfo.Offer, imageInfo.Sku , version )).Value.OSDiskImageOperatingSystem.ToString().ToLower(); } catch (RequestFailedException ex) { return(OneFuzzResult <Os> .Error( ErrorCode.INVALID_IMAGE, ex.ToString() )); } } if (name != null) { name = string.Concat(name[0].ToString().ToUpper(), name.AsSpan(1)); if (Enum.TryParse(name, out Os os)) { return(OneFuzzResult <Os> .Ok(os)); } } return(OneFuzzResult <Os> .Error( ErrorCode.INVALID_IMAGE, $"Unexpected image os type: {name}" )); }
public static void DeleteImage(this IImageOperations operations, string name, ImageDeleteParameters parameters) { operations.DeleteImageAsync(name, parameters).Wait(); }
public static IList <ImagesListResponse> ListImages(this IImageOperations operations, ImagesListParameters parameters) { return(operations.ListImagesAsync(parameters).Result); }
public static Stream PushImage(this IImageOperations operations, string name, ImagePushParameters parameters, AuthConfig authConfig) { return(operations.PushImageAsync(name, parameters, authConfig).Result); }
public static Stream PullImage(this IImageOperations operations, ImagesPullParameters parameters, AuthConfig authConfig) { return(operations.PullImageAsync(parameters, authConfig).Result); }
/// <summary> /// /// </summary> public HomeController(IImageOperations imageOperations) { _imageOperations = imageOperations; }
public async Async.Task <OneFuzzResultVoid> CreateVmss( string location, Guid name, string vmSku, long vmCount, string image, string networkId, bool?spotInstance, bool ephemeralOsDisks, IList <VirtualMachineScaleSetExtensionData>?extensions, string password, string sshPublicKey, IDictionary <string, string> tags) { var vmss = await GetVmss(name); if (vmss is not null) { return(OneFuzzResultVoid.Ok); } _log.Info($"creating VM name: {name}, vm_sku: {vmSku}, vm_count: {vmCount}, image: {image}, subnet: {networkId}, spot_instance: {spotInstance}"); var getOsResult = await _imageOps.GetOs(location, image); if (!getOsResult.IsOk) { return(getOsResult.ErrorV); } var vmssData = new VirtualMachineScaleSetData(location) { DoNotRunExtensionsOnOverprovisionedVms = false, Sku = new ComputeSku() { Name = vmSku }, Overprovision = false, SinglePlacementGroup = false, UpgradePolicy = new UpgradePolicy() { Mode = UpgradeMode.Manual }, Identity = new ManagedServiceIdentity(managedServiceIdentityType: ManagedServiceIdentityType.UserAssigned), }; vmssData.Identity.UserAssignedIdentities.Add(_creds.GetScalesetIdentityResourcePath(), new UserAssignedIdentity()); vmssData.VirtualMachineProfile = new VirtualMachineScaleSetVmProfile() { Priority = VirtualMachinePriorityTypes.Regular }; var imageRef = new ImageReference(); if (image.StartsWith('/')) { imageRef.Id = image; } else { var info = IImageOperations.GetImageInfo(image); imageRef.Publisher = info.Publisher; imageRef.Offer = info.Offer; imageRef.Sku = info.Sku; imageRef.Version = info.Version; } vmssData.VirtualMachineProfile.StorageProfile = new VirtualMachineScaleSetStorageProfile() { ImageReference = imageRef }; vmssData.VirtualMachineProfile.OSProfile = new VirtualMachineScaleSetOSProfile() { ComputerNamePrefix = "node", AdminUsername = "******" }; var networkConfiguration = new VirtualMachineScaleSetNetworkConfiguration("onefuzz-nic") { Primary = true }; var ipConfig = new VirtualMachineScaleSetIPConfiguration("onefuzz-ip-config"); ipConfig.SubnetId = new ResourceIdentifier(networkId); networkConfiguration.IPConfigurations.Add(ipConfig); vmssData.VirtualMachineProfile.NetworkProfile = new VirtualMachineScaleSetNetworkProfile(); vmssData.VirtualMachineProfile.NetworkProfile.NetworkInterfaceConfigurations.Add(networkConfiguration); if (extensions is not null) { vmssData.VirtualMachineProfile.ExtensionProfile = new VirtualMachineScaleSetExtensionProfile(); foreach (var e in extensions) { vmssData.VirtualMachineProfile.ExtensionProfile.Extensions.Add(e); } } switch (getOsResult.OkV) { case Os.Windows: vmssData.VirtualMachineProfile.OSProfile.AdminPassword = password; break; case Os.Linux: vmssData.VirtualMachineProfile.OSProfile.LinuxConfiguration = new LinuxConfiguration(); vmssData.VirtualMachineProfile.OSProfile.LinuxConfiguration.DisablePasswordAuthentication = true; var i = new SshPublicKeyInfo() { KeyData = sshPublicKey, Path = "/home/onefuzz/.ssh/authorized_keys" }; vmssData.VirtualMachineProfile.OSProfile.LinuxConfiguration.SshPublicKeys.Add(i); break; default: return(OneFuzzResultVoid.Error(ErrorCode.INVALID_CONFIGURATION, $"unhandled OS: {getOsResult.OkV} in image: {image}")); } if (ephemeralOsDisks) { vmssData.VirtualMachineProfile.StorageProfile.OSDisk = new VirtualMachineScaleSetOSDisk(DiskCreateOptionTypes.FromImage); vmssData.VirtualMachineProfile.StorageProfile.OSDisk.DiffDiskSettings = new DiffDiskSettings(); vmssData.VirtualMachineProfile.StorageProfile.OSDisk.DiffDiskSettings.Option = DiffDiskOptions.Local; vmssData.VirtualMachineProfile.StorageProfile.OSDisk.Caching = CachingTypes.ReadOnly; } if (spotInstance.HasValue && spotInstance.Value) { // Setting max price to -1 means it won't be evicted because of // price. // // https://docs.microsoft.com/en-us/azure/ // virtual-machine-scale-sets/use-spot#resource-manager-templates vmssData.VirtualMachineProfile.EvictionPolicy = VirtualMachineEvictionPolicyTypes.Deallocate; vmssData.VirtualMachineProfile.Priority = VirtualMachinePriorityTypes.Spot; vmssData.VirtualMachineProfile.BillingMaxPrice = 1.0; } foreach (var tag in tags) { vmssData.Tags.Add(tag); } if (_serviceConfig.OneFuzzOwner is not null) { vmssData.Tags.Add("OWNER", _serviceConfig.OneFuzzOwner); } try { var rg = _creds.GetResourceGroupResource(); var createUpdate = await rg.GetVirtualMachineScaleSets().CreateOrUpdateAsync(WaitUntil.Started, name.ToString(), vmssData); if (createUpdate.GetRawResponse().IsError) { var msg = $"Failed to create new scaleset due to {createUpdate.GetRawResponse().ReasonPhrase}"; _log.Error(msg); return(OneFuzzResultVoid.Error(ErrorCode.VM_CREATE_FAILED, new[] { msg })); } else { return(OneFuzzResultVoid.Ok); } } catch (Exception ex) { _log.Exception(ex); return(OneFuzzResultVoid.Error(ErrorCode.VM_CREATE_FAILED, new[] { ex.Message })); } }
/// <summary> /// /// </summary> /// <param name="unitOfWork"></param> /// <param name="imageOperations"></param> public ImageApiController(IUnitOfWork unitOfWork, IImageOperations imageOperations) { _unitOfWork = unitOfWork; _imageOperations = imageOperations; }