Пример #1
0
        public override object Execute()
        {
            const bool aftsDeleteSourceAfterTransfer = true;
            const bool aftsOverwriteDestinationBlob  = true;

            //*** leave if Azure containers are not yet synchronized
            if (!ContainersSynchronized)
            {
                return(0);
            }

            if (AllQueuesBlocked)
            {
                return(0);
            }

            var cdb = new CmpDb(CmpDbConnectionString);

            List <Models.VmDeploymentRequest> vmReqList = null;

            try
            {
                vmReqList = cdb.FetchVmDepRequests(
                    Constants.StatusEnum.Converted.ToString(), true);
            }
            catch (Exception ex)
            {
                throw new Exception("Exception in ProcessorVm.ProcessConvertedSubmissions() : " +
                                    CmpCommon.Utilities.UnwindExceptionMessages(ex));
            }

            foreach (var vmReq in vmReqList)
            {
                try
                {
                    if (vmReq.RequestType.Equals(Constants.RequestTypeEnum.NewVM.ToString()))
                    {
                        continue;
                    }

                    //*** Temporary ***
                    vmReq.Config = vmReq.Config.Replace("<IsOS>True</IsOS>", "<IsOS>true</IsOS>");
                    vmReq.Config = vmReq.Config.Replace("<IsOS>False</IsOS>", "<IsOS>false</IsOS>");

                    if (!vmReq.Config.Contains("<IsOS>true</IsOS>"))
                    {
                        throw new Exception("Migration request does not contain a disk spec for an OS disk.");
                    }

                    //*** Get the target service provider account resource group ***
                    vmReq.ServiceProviderResourceGroup = GetTargetServiceProviderAccountResourceGroup(vmReq);

                    //*** Temporary ***
                    //vmReq.ServiceProviderResourceGroup = "DEV02";

                    //*** Get the list of service provider accounts associated with the resource group
                    var servProvAcctList = ServProvAccount.GetAzureServiceAccountList(
                        vmReq.ServiceProviderResourceGroup, CmpDbConnectionString);

                    var vmc = VmConfig.Deserialize(vmReq.Config);

                    if (null == vmc)
                    {
                        vmc = new VmConfig();
                    }

                    //*** Service Name ***

                    if (null == vmc.HostedServiceConfig)
                    {
                        vmc.HostedServiceConfig = new HostedService();
                    }

                    //*** TODO *** Handle a non CMDB case here

                    vmReq.TargetServicename             = GetSafeHostServiceName(vmReq.ParentAppID);
                    vmc.HostedServiceConfig.ServiceName = vmReq.TargetServicename;
                    vmc.HostedServiceConfig.Label       = Util.ToB64(vmc.HostedServiceConfig.ServiceName);
                    vmc.HostedServiceConfig.Description = vmc.CmdbConfig.ApplicationName;
                    //vmc.HostedServiceConfig.AffinityGroup = Constants.AUTOAFFINITYGROUP;
                    vmc.HostedServiceConfig.ExtendedProperties = null;

                    //*** Role Size ***

                    if (null == vmc.AzureVmConfig)
                    {
                        vmc.AzureVmConfig = new AzureVmDeployment();
                    }

                    if (null == vmc.AzureVmConfig.RoleList)
                    {
                        vmc.AzureVmConfig.RoleList = new List <Role>();
                    }

                    if (0 == vmc.AzureVmConfig.RoleList.Count)
                    {
                        vmc.AzureVmConfig.RoleList.Add(new CmpInterfaceModel.Models.PersistentVMRole());
                    }


                    //*** TODO *** Handle a non CMDB case here

                    ((PersistentVMRole)vmc.AzureVmConfig.RoleList[0]).RoleSize = vmc.CmdbConfig.AzureComputeSku;

                    vmReq.Config = vmc.Serialize();

                    //string storageAccountKey = "";

                    Models.ServiceProviderAccount servProdAccount;

                    var resp = GetHostService(vmReq, servProvAcctList, out servProdAccount);

                    if (resp.HadError)
                    {
                        if (resp.Retry)
                        {
                            continue;
                        }

                        throw new Exception("Unable to find/create a host service : " + resp.Body);
                    }

                    var cc = new AzureSubscription();
                    //cc.LoadStorageAccounts(servProdAccount.AccountID, servProdAccount.CertificateThumbprint);

                    //*****************

                    var vmCfg = CmpInterfaceModel.Models.VmConfig.Deserialize(vmReq.Config);

                    if (null == vmCfg.Placement)
                    {
                        throw new Exception("Placement element not found in vmReq.Config");
                    }

                    //servProdAccount.AzStorageContainerUrl = vmCfg.Placement.StorageContainerUrl;

                    //*****************

                    //var storageAcct = cc.GetStorageAccount(servProdAccount.AccountID, servProdAccount.CertificateThumbprint,
                    //    servProdAccount.AzStorageContainerUrl);

                    //********************************
                    //********************************

                    var diskCount = 1;
                    if (null != vmCfg.DiskSpecList)
                    {
                        diskCount += vmCfg.DiskSpecList.Count;
                    }

                    var connection =
                        ServProvAccount.GetAzureServiceAccountConnection(
                            servProdAccount.AccountID, servProdAccount.CertificateThumbprint,
                            servProdAccount.AzureADTenantId, servProdAccount.AzureADClientId, servProdAccount.AzureADClientKey);

                    var so = new AzureAdminClientLib.StorageOps(connection);

                    var container = so.GetLeastUsedContainer(DefaultVhdContainerName,
                                                             null, vmCfg.HostedServiceConfig.Location, BlobsPerContainerLimit,
                                                             VmsPerVnetLimit, diskCount, EnforceAppAgAffinity);

                    if (null == container)
                    {
                        throw new Exception("No suitable containers found in subscription. Suitable containers must be named '" +
                                            DefaultVhdContainerName + "' and must be in an AG with an InUse VNet");
                    }

                    var storageAcct = container.StorageAccount;

                    if (null == storageAcct)
                    {
                        throw new Exception(string.Format("No storage account associated with storage container '{0}' in subscription '{1}' in ServiceProviderResourceGroup '{2}'",
                                                          container.Url, servProdAccount.Name, vmReq.ServiceProviderResourceGroup));
                    }

                    //*** Populate placement ***

                    vmCfg.Placement.StorageContainerUrl = container.Url;
                    vmCfg.Placement.AffinityGroup       = container.StorageAccount.AffinityGroup;
                    vmCfg.Placement.Location            = container.StorageAccount.Location;
                    vmCfg.Placement.VNet      = container.StorageAccount.VirtualNetworksAvailable[0].Name;
                    vmCfg.Placement.Subnet    = servProdAccount.AzSubnet;
                    vmCfg.Placement.DiskCount = diskCount;

                    vmReq.Config = vmCfg.Serialize();


                    var cmp = new CmpService(EventLog, CmpDbConnectionString, AftsDbConnectionString);
                    cmp.InsertAftsRequest(vmReq, container.Url, storageAcct.PrimaryAccessKey,
                                          aftsDeleteSourceAfterTransfer, aftsOverwriteDestinationBlob);

                    vmReq.CurrentStateStartTime    = DateTime.UtcNow;
                    vmReq.ExceptionMessage         = "";
                    vmReq.ExceptionTypeCode        = "";
                    vmReq.StatusCode               = Constants.StatusEnum.ReadyForTransfer.ToString();
                    vmReq.StatusMessage            = "Ready for transfer to Azure storage";
                    vmReq.ServiceProviderAccountID = servProdAccount.ID;

                    so.ReserveContainerSpace(container.Url, diskCount, vmReq.ID, vmReq);

                    cdb.SetVmDepRequestStatus(vmReq, null);
                }
                catch (Exception ex)
                {
                    vmReq.StatusCode       = Constants.StatusEnum.Exception.ToString();
                    vmReq.ExceptionMessage = "Exception in ProcessorVm.ProcessConvertedSubmissions() : " +
                                             Utilities.UnwindExceptionMessages(ex);
                    vmReq.StatusMessage = vmReq.ExceptionMessage;
                    Utilities.SetVmReqExceptionType(vmReq,
                                                    Constants.RequestExceptionTypeCodeEnum.Admin);
                    cdb.SetVmDepRequestStatus(vmReq, null);
                }
            }

            return(0);
        }
Пример #2
0
        public override object Execute()
        {
            if (AllQueuesBlocked)
            {
                return(0);
            }

            //*** leave if Azure containers are not yet synchronized
            if (!ContainersSynchronized)
            {
                return(0);
            }

            var haltSequence = false;
            var appIdList    = new HashSet <string>();

            var cdb = new CmpDb(CmpDbConnectionString);
            List <Models.VmDeploymentRequest> vmReqList = null;

            try
            {
                vmReqList = cdb.FetchVmDepRequests(
                    Constants.StatusEnum.QcVmRequestPassed.ToString(), true);
            }
            catch (Exception ex)
            {
                throw new Exception("Exception in ProcessQcVmRequestPassed() " +
                                    CmpCommon.Utilities.UnwindExceptionMessages(ex));
            }

            foreach (var vmReq in vmReqList)
            {
                try
                {
                    var vmCfg = CmpInterfaceModel.Models.VmConfig.Deserialize(vmReq.Config);

                    //*** Which Azure API are we looking at here? ***
                    if (null == vmCfg.AzureApiConfig)
                    {
                        vmCfg.AzureApiConfig = null == vmCfg.AzureArmConfig
                            ? new AzureApiSpec()
                        {
                            Platform = Constants.AzureApiType.RDFE.ToString()
                        }
                    }
                    : new AzureApiSpec()
                    {
                        Platform = Constants.AzureApiType.ARM.ToString()
                    };

                    //*** Don't try ops on the same service twice in the same run ***
                    if (vmCfg.AzureApiConfig.Platform.Equals(Constants.AzureApiType.RDFE.ToString()))
                    {
                        if (appIdList.Contains(vmReq.ParentAppID))
                        {
                            continue;
                        }

                        appIdList.Add(vmReq.ParentAppID);
                    }

                    //*** Get the target service provider account resource group ***
                    vmReq.ServiceProviderResourceGroup = GetTargetServiceProviderAccountResourceGroup(vmReq);

                    //*** Get the list of service provider accounts associated with the resource group
                    var servProvAcctList = ServProvAccount.GetAzureServiceAccountList(
                        vmReq.ServiceProviderResourceGroup, CmpDbConnectionString);

                    //*** Were any SPs found? ***
                    if (0 == servProvAcctList.Count)
                    {
                        throw new Exception(string.Format("No Service provider Account found with group name '{0}'",
                                                          vmReq.ServiceProviderResourceGroup));
                    }

                    //*** Get the target service provider account ID ***
                    //vmReq.ServiceProviderAccountID = GetTargetServiceProviderAccountID(vmReq);

                    //*** Get account info ***
                    //if (null == vmReq.ServiceProviderAccountID)
                    //    throw new Exception("ServiceProviderAccountID == NULL");

                    //AzureAdminClientLib.Connection connection =
                    //    ServProvAccount.GetAzureServiceAccountConnection((int)vmReq.ServiceProviderAccountID, _CmpDbConnectionString);

                    var hsBody = BuildAzureHsRequestBody(vmReq.Config);

                    if (null == hsBody)
                    {
                        vmReq.StatusCode       = Constants.StatusEnum.ReadyForUploadingServiceCert.ToString();
                        vmReq.ExceptionMessage = "No Service Specified";
                        vmReq.ServiceProviderStatusCheckTag = "";
                    }
                    else
                    {
                        AzureAdminClientLib.HttpResponse resp            = null;
                        Models.ServiceProviderAccount    servProdAccount = null;
                        AzureAdminClientLib.Connection   connection      = null;
                        string useThisServiceName       = null;
                        string useThisAffinityGroupName = null;

                        //*** Count disks ***

                        var diskCount = 1;

                        if (null != vmCfg.DiskSpecList)
                        {
                            diskCount += vmCfg.DiskSpecList.Count;
                        }

                        //*** Do we need to create the hosted service? ***

                        var serviceName = Utilities.GetXmlInnerText(hsBody, "ServiceName");

                        if (null == serviceName)
                        {
                            throw new Exception("ServiceName = NULL");
                        }

                        if (0 == serviceName.Length)
                        {
                            throw new Exception("ServiceName.Length = 0");
                        }

                        var avail = HostedServiceOps.ServiceAvailabilityEnum.Unknown;

                        //* Pivot on API here. If RDFE, look for the host service. If ARM, create the
                        //* service (or find if alreday exists) and say we already own it.

                        if (vmCfg.AzureApiConfig.Platform.Equals(Constants.AzureApiType.RDFE.ToString()))
                        {
                            avail = CheckServiceNameAvailability(servProvAcctList,
                                                                 serviceName, null, vmCfg.HostedServiceConfig.Location,
                                                                 diskCount, out servProdAccount, out useThisServiceName,
                                                                 out useThisAffinityGroupName);
                        }
                        else
                        {
                            //*** TODO * Use placement, just take the first one for now
                            servProdAccount = servProvAcctList[0];
                            vmReq.ServiceProviderAccountID = servProdAccount.ID;

                            connection = ServProvAccount.GetAzureServiceAccountConnection(
                                servProdAccount.AccountID, servProdAccount.CertificateThumbprint,
                                servProdAccount.AzureADTenantId, servProdAccount.AzureADClientId, servProdAccount.AzureADClientKey);

                            var hso = new AzureAdminClientLib.HostedServiceOps(connection);
                            resp = hso.CreateResourceGroup(serviceName,
                                                           vmCfg.AzureArmConfig.properties.template.variables.location, false);

                            avail = HostedServiceOps.ServiceAvailabilityEnum.AlredayOwnIt;
                            useThisServiceName       = serviceName;
                            useThisAffinityGroupName = null;
                        }

                        vmReq.TargetServicename = useThisServiceName;
                        vmReq.Config            = vmReq.Config.Replace("<ServiceName>" + serviceName + "</ServiceName>",
                                                                       "<ServiceName>" + useThisServiceName + "</ServiceName>");

                        switch (avail)
                        {
                        case AzureAdminClientLib.HostedServiceOps.ServiceAvailabilityEnum.Unavailable:
                            resp = new AzureAdminClientLib.HttpResponse {
                                HadError = true, Body = "Service Name Not Available", HTTP = ""
                            };
                            break;

                        case AzureAdminClientLib.HostedServiceOps.ServiceAvailabilityEnum.AlredayOwnIt:

                            //*** Iffn it's ARM, we don't be needn to set placement
                            if (vmCfg.AzureApiConfig.Platform.Equals(Constants.AzureApiType.ARM.ToString()))
                            {
                                break;
                            }

                            connection = ServProvAccount.GetAzureServiceAccountConnection(
                                servProdAccount.AccountID, servProdAccount.CertificateThumbprint,
                                servProdAccount.AzureADTenantId, servProdAccount.AzureADClientId, servProdAccount.AzureADClientKey);

                            resp = SetPlacement(vmReq, useThisAffinityGroupName, connection, servProdAccount);

                            if (resp.HadError)
                            {
                                if (resp.Retry)
                                {
                                    Thread.Sleep(PlacementBusyDwelltime);
                                    continue;
                                }

                                throw new Exception("Unable to find/create placement : " + resp.Body);
                            }

                            resp = new AzureAdminClientLib.HttpResponse
                            {
                                HadError = false, Body = "Already Own Service Name", StatusCheckUrl = ""
                            };

                            break;

                        case AzureAdminClientLib.HostedServiceOps.ServiceAvailabilityEnum.Available:

                            // Go through each of the service provider accounts (a.k.a. subscriptions) and
                            // populate the Azure properties. Currently this is just the core counts.
                            // This needs to be done before calling the Min() function, otherwise all the values
                            // will be zero and the comparison won't be of much value.

                            if (null == servProdAccount)
                            {
                                foreach (var oneProviderAccount in servProvAcctList)
                                {
                                    oneProviderAccount.LoadAzureProperties();
                                }

                                // Get the provider account with the maximum percentage of available cores
                                servProdAccount = servProvAcctList.Max();
                            }

                            connection = ServProvAccount.GetAzureServiceAccountConnection(
                                servProdAccount.AccountID, servProdAccount.CertificateThumbprint,
                                servProdAccount.AzureADTenantId, servProdAccount.AzureADClientId, servProdAccount.AzureADClientKey);

                            var hso = new AzureAdminClientLib.HostedServiceOps(connection);

                            resp = SetPlacement(vmReq, null, connection, servProdAccount);

                            if (resp.HadError)
                            {
                                if (resp.Retry)
                                {
                                    Thread.Sleep(PlacementBusyDwelltime);
                                    continue;
                                }

                                throw new Exception("Unable to find/create placement : " + resp.Body);
                            }

                            hsBody = BuildAzureHsRequestBody(vmReq.Config);
                            resp   = hso.CreateHostedService(hsBody);
                            break;
                        }

                        if (resp.HadError)
                        {
                            if (resp.HTTP.Contains("409"))
                            {
                                vmReq.StatusCode       = Constants.StatusEnum.ReadyForUploadingServiceCert.ToString();
                                vmReq.ExceptionMessage = "";
                                vmReq.StatusMessage    = "Service already exists";
                            }
                            else
                            {
                                haltSequence                = true;
                                vmReq.ExceptionMessage      = resp.Body;
                                vmReq.CurrentStateStartTime = DateTime.UtcNow;

                                if (avail == HostedServiceOps.ServiceAvailabilityEnum.Unavailable)
                                {
                                    vmReq.StatusMessage = "Rejected";
                                    vmReq.StatusCode    = Constants.StatusEnum.Rejected.ToString();
                                    Utilities.SetVmReqExceptionType(vmReq,
                                                                    CmpInterfaceModel.Constants.RequestExceptionTypeCodeEnum.Customer);
                                }
                                else
                                {
                                    vmReq.StatusMessage = "Exception";
                                    vmReq.StatusCode    = Constants.StatusEnum.Exception.ToString();
                                    Utilities.SetVmReqExceptionType(vmReq,
                                                                    CmpInterfaceModel.Constants.RequestExceptionTypeCodeEnum.Admin);
                                }
                            }
                        }
                        else
                        {
                            vmReq.StatusCode       = Constants.StatusEnum.ReadyForUploadingServiceCert.ToString();
                            vmReq.ExceptionMessage = "";
                            vmReq.StatusMessage    = resp.Body;
                            vmReq.ServiceProviderStatusCheckTag = resp.StatusCheckUrl;
                            System.Threading.Thread.Sleep(HostedServiceCreationDwellTime);
                        }
                    }

                    if (!haltSequence)
                    {
                        vmReq.CurrentStateStartTime = DateTime.UtcNow;
                    }

                    cdb.SetVmDepRequestStatus(vmReq, null);

                    Thread.Sleep(PlacementDwelltime);
                }
                catch (Exception ex)
                {
                    if (null != vmReq)
                    {
                        if (ex.Message.Contains("(503)"))
                        {
                            continue;
                        }
                        else
                        {
                            vmReq.StatusCode       = Constants.StatusEnum.Exception.ToString();
                            vmReq.ExceptionMessage = "Exception in ProcessQcVmRequestPassed() : " +
                                                     Utilities.UnwindExceptionMessages(ex);
                            vmReq.StatusMessage         = "Exception";
                            vmReq.CurrentStateStartTime = DateTime.UtcNow;
                            Utilities.SetVmReqExceptionType(vmReq,
                                                            CmpInterfaceModel.Constants.RequestExceptionTypeCodeEnum.Admin);
                            cdb.SetVmDepRequestStatus(vmReq, null);
                            Thread.Sleep(PlacementBusyDwelltime);
                        }
                    }
                }
            }

            return(0);
        }