예제 #1
0
 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());
        }
예제 #3
0
    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);
 }
예제 #8
0
 /// <summary>
 /// 
 /// </summary>
 public HomeController(IImageOperations imageOperations)
 {
     _imageOperations = imageOperations;
 }
예제 #9
0
    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;
 }