/// <summary>
        /// Queries by friendly name.
        /// </summary>
        private void GetByFriendlyName()
        {
            bool found = false;

            ProtectableItemListResponse protectableItemListResponse = RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(
                Utilities.GetValueFromArmId(this.ProtectionContainer.ID, ARMResourceTypeConstants.ReplicationFabrics),
                this.ProtectionContainer.Name);
            ProtectableItem protectableItem =
                protectableItemListResponse.ProtectableItems.SingleOrDefault(t =>
                                                                             string.Compare(t.Properties.FriendlyName, this.FriendlyName, StringComparison.OrdinalIgnoreCase) == 0);

            if (protectableItem != null)
            {
                ProtectableItemResponse protectableItemResponse = RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(
                    Utilities.GetValueFromArmId(this.ProtectionContainer.ID, ARMResourceTypeConstants.ReplicationFabrics),
                    this.ProtectionContainer.Name,
                    protectableItem.Name);
                WriteProtectableItem(protectableItemResponse.ProtectableItem);

                found = true;
            }

            if (!found)
            {
                throw new InvalidOperationException(
                          string.Format(
                              Properties.Resources.ProtectionEntityNotFound,
                              this.FriendlyName,
                              this.ProtectionContainer.FriendlyName));
            }
        }
        /// <summary>
        /// Start PE Commit.
        /// </summary>
        private void SetPECommit()
        {
            // fetch the latest PE object
            ProtectableItemResponse protectableItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(this.fabricName,
                                                                           this.ProtectionEntity.ProtectionContainerId, this.ProtectionEntity.Name);

            ReplicationProtectedItemResponse replicationProtectedItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(this.fabricName,
                                                                                    this.ProtectionEntity.ProtectionContainerId, Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems));

            PolicyResponse policyResponse = RecoveryServicesClient.GetAzureSiteRecoveryPolicy(Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Properties.PolicyID, ARMResourceTypeConstants.ReplicationPolicies));

            this.ProtectionEntity = new ASRProtectionEntity(protectableItemResponse.ProtectableItem, replicationProtectedItemResponse.ReplicationProtectedItem);

            LongRunningOperationResponse response = RecoveryServicesClient.StartAzureSiteRecoveryCommitFailover(
                this.fabricName,
                this.protectionContainerName,
                Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Id, ARMResourceTypeConstants.ReplicationProtectedItems));

            JobResponse jobResponse =
                RecoveryServicesClient
                .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

            WriteObject(new ASRJob(jobResponse.Job));
        }
예제 #3
0
        /// <summary>
        /// Queries by Protectable Item
        /// </summary>
        private void GetByProtectableItem()
        {
            bool found = false;

            ProtectableItemResponse protectableItemResponse = RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(
                Utilities.GetValueFromArmId(this.ProtectableItem.ID, ARMResourceTypeConstants.ReplicationFabrics),
                Utilities.GetValueFromArmId(this.ProtectableItem.ID, ARMResourceTypeConstants.ReplicationProtectionContainers),
                this.ProtectableItem.Name);

            if (protectableItemResponse.ProtectableItem != null)
            {
                ReplicationProtectedItemResponse replicationProtectedItemResponse = RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(
                    Utilities.GetValueFromArmId(this.ProtectableItem.ID, ARMResourceTypeConstants.ReplicationFabrics),
                    Utilities.GetValueFromArmId(this.ProtectableItem.ID, ARMResourceTypeConstants.ReplicationProtectionContainers),
                    Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems));

                WriteReplicationProtectedItem(replicationProtectedItemResponse.ReplicationProtectedItem);

                found = true;
            }

            if (!found)
            {
                throw new InvalidOperationException(
                          string.Format(
                              Properties.Resources.ProtectionEntityNotFound,
                              this.FriendlyName,
                              this.ProtectionContainer.FriendlyName));
            }
        }
예제 #4
0
        /// <summary>
        /// Starts PE Unplanned failover.
        /// </summary>
        private void StartPEUnplannedFailover()
        {
            var unplannedFailoverInputProperties = new UnplannedFailoverInputProperties()
            {
                FailoverDirection       = this.Direction,
                SourceSiteOperations    = this.PerformSourceSideActions ? "Required" : "NotRequired", //Required|NotRequired
                ProviderSpecificDetails = new ProviderSpecificFailoverInput()
            };

            var input = new UnplannedFailoverInput()
            {
                Properties = unplannedFailoverInputProperties
            };

            // fetch the latest PE object
            ProtectableItemResponse protectableItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(this.fabricName,
                                                                           this.ProtectionEntity.ProtectionContainerId, this.ProtectionEntity.Name);

            ReplicationProtectedItemResponse replicationProtectedItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(this.fabricName,
                                                                                    this.ProtectionEntity.ProtectionContainerId, Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems));

            PolicyResponse policyResponse = RecoveryServicesClient.GetAzureSiteRecoveryPolicy(Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Properties.PolicyID, ARMResourceTypeConstants.ReplicationPolicies));

            this.ProtectionEntity = new ASRProtectionEntity(protectableItemResponse.ProtectableItem, replicationProtectedItemResponse.ReplicationProtectedItem);

            if (0 == string.Compare(
                    this.ProtectionEntity.ReplicationProvider,
                    Constants.HyperVReplicaAzure,
                    StringComparison.OrdinalIgnoreCase))
            {
                if (this.Direction == Constants.PrimaryToRecovery)
                {
                    var failoverInput = new HyperVReplicaAzureFailoverProviderInput()
                    {
                        PrimaryKekCertificatePfx   = primaryKekCertpfx,
                        SecondaryKekCertificatePfx = secondaryKekCertpfx,
                        VaultLocation = this.GetCurrentVaultLocation()
                    };
                    input.Properties.ProviderSpecificDetails = failoverInput;
                }
            }

            LongRunningOperationResponse response =
                RecoveryServicesClient.StartAzureSiteRecoveryUnplannedFailover(
                    this.fabricName,
                    this.protectionContainerName,
                    Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Id, ARMResourceTypeConstants.ReplicationProtectedItems),
                    input);

            JobResponse jobResponse =
                RecoveryServicesClient
                .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

            WriteObject(new ASRJob(jobResponse.Job));
        }
        /// <summary>
        /// Creates Replication Plan Legacy.
        /// </summary>
        private void CreateRecoveryPlanLegacy()
        {
            CreateRecoveryPlanInputProperties createRecoveryPlanInputProperties = new CreateRecoveryPlanInputProperties()
            {
                FailoverDeploymentModel = failoverDeploymentModel,
                Groups           = new List <RecoveryPlanGroup>(),
                PrimaryFabricId  = this.primaryserver,
                RecoveryFabricId = this.recoveryserver
            };

            RecoveryPlanGroup recoveryPlanGroup = new RecoveryPlanGroup()
            {
                GroupType = Constants.Boot,
                ReplicationProtectedItems = new List <RecoveryPlanProtectedItem>(),
                StartGroupActions         = new List <RecoveryPlanAction>(),
                EndGroupActions           = new List <RecoveryPlanAction>()
            };

            foreach (ASRProtectionEntity pe in ProtectionEntityList)
            {
                string fabricName = Utilities.GetValueFromArmId(pe.ID, ARMResourceTypeConstants.ReplicationFabrics);
                // fetch the latest PE object
                ProtectableItemResponse protectableItemResponse =
                    RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(fabricName,
                                                                               pe.ProtectionContainerId, pe.Name);

                ReplicationProtectedItemResponse replicationProtectedItemResponse =
                    RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(fabricName,
                                                                                        pe.ProtectionContainerId, Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems));

                string VmId = null;

                if (replicationProtectedItemResponse.ReplicationProtectedItem.Properties.ProviderSpecificDetails.GetType() == typeof(HyperVReplicaAzureReplicationDetails))
                {
                    VmId = ((HyperVReplicaAzureReplicationDetails)replicationProtectedItemResponse.ReplicationProtectedItem.Properties.ProviderSpecificDetails).VmId;
                }
                else if (replicationProtectedItemResponse.ReplicationProtectedItem.Properties.ProviderSpecificDetails.GetType() == typeof(HyperVReplica2012ReplicationDetails))
                {
                    VmId = ((HyperVReplica2012ReplicationDetails)replicationProtectedItemResponse.ReplicationProtectedItem.Properties.ProviderSpecificDetails).VmId;
                }

                RecoveryPlanProtectedItem recoveryPlanProtectedItem = new RecoveryPlanProtectedItem();
                recoveryPlanProtectedItem.Id = replicationProtectedItemResponse.ReplicationProtectedItem.Id;
                recoveryPlanProtectedItem.VirtualMachineId = VmId;
                recoveryPlanGroup.ReplicationProtectedItems.Add(recoveryPlanProtectedItem);
            }

            createRecoveryPlanInputProperties.Groups.Add(recoveryPlanGroup);

            CreateRecoveryPlanInput createRecoveryPlanInput = new CreateRecoveryPlanInput()
            {
                Properties = createRecoveryPlanInputProperties
            };

            CreateRecoveryPlan(this.Name, createRecoveryPlanInput);
        }
예제 #6
0
        /// <summary>
        /// ProcessRecord of the command.
        /// </summary>
        public override void ExecuteSiteRecoveryCmdlet()
        {
            base.ExecuteSiteRecoveryCmdlet();

            ProtectableItemResponse protectableItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(Utilities.GetValueFromArmId(this.VirtualMachine.ID, ARMResourceTypeConstants.ReplicationFabrics),
                                                                           this.VirtualMachine.ProtectionContainerId, this.VirtualMachine.Name);

            if (protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId == null)
            {
                this.WriteWarning(Properties.Resources.ProtectionIsNotEnabledForVM.ToString());
                return;
            }

            ReplicationProtectedItemResponse replicationProtectedItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(Utilities.GetValueFromArmId(this.VirtualMachine.ID, ARMResourceTypeConstants.ReplicationFabrics),
                                                                                    this.VirtualMachine.ProtectionContainerId, Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems));

            // Check for Replication Provider type HyperVReplicaAzure
            if (0 != string.Compare(
                    replicationProtectedItemResponse.ReplicationProtectedItem.Properties.ProviderSpecificDetails.InstanceType,
                    Constants.HyperVReplicaAzure,
                    StringComparison.OrdinalIgnoreCase))
            {
                this.WriteWarning(Properties.Resources.UnsupportedReplicationProvidedForUpdateVmProperties.ToString());
                return;
            }

            // Check for at least one option
            if (string.IsNullOrEmpty(this.Name) &&
                string.IsNullOrEmpty(this.Size) &&
                string.IsNullOrEmpty(this.PrimaryNic) &&
                string.IsNullOrEmpty(this.RecoveryNetworkId))
            {
                this.WriteWarning(Properties.Resources.ArgumentsMissingForUpdateVmProperties.ToString());
                return;
            }

            // Both primary & recovery inputs should be present
            if (string.IsNullOrEmpty(this.PrimaryNic) ^
                string.IsNullOrEmpty(this.RecoveryNetworkId))
            {
                this.WriteWarning(Properties.Resources.NetworkArgumentsMissingForUpdateVmProperties.ToString());
                return;
            }

            List <VMNicInputDetails> vMNicInputDetailsList = new List <VMNicInputDetails>();
            VMNicDetails             vMNicDetailsToBeUpdated;

            if (!string.IsNullOrEmpty(this.PrimaryNic))
            {
                HyperVReplicaAzureReplicationDetails providerSpecificDetails =
                    (HyperVReplicaAzureReplicationDetails)replicationProtectedItemResponse.ReplicationProtectedItem.Properties.ProviderSpecificDetails;

                if (providerSpecificDetails.VMNics != null)
                {
                    vMNicDetailsToBeUpdated = providerSpecificDetails.VMNics.SingleOrDefault(n => string.Compare(n.NicId, this.PrimaryNic, StringComparison.OrdinalIgnoreCase) == 0);
                    if (vMNicDetailsToBeUpdated != null)
                    {
                        VMNicInputDetails vMNicInputDetails = new VMNicInputDetails();

                        vMNicInputDetails.NicId = this.PrimaryNic;
                        vMNicInputDetails.RecoveryVMSubnetName      = this.RecoveryNicSubnetName;
                        vMNicInputDetails.ReplicaNicStaticIPAddress = this.RecoveryNicStaticIPAddress;
                        vMNicInputDetails.SelectionType             = string.IsNullOrEmpty(this.NicSelectionType) ? Constants.SelectedByUser : this.NicSelectionType;
                        vMNicInputDetailsList.Add(vMNicInputDetails);

                        IEnumerable <VMNicDetails> vMNicDetailsListRemaining = providerSpecificDetails.VMNics.Where(n => string.Compare(n.NicId, this.PrimaryNic, StringComparison.OrdinalIgnoreCase) != 0);
                        foreach (VMNicDetails nDetails in vMNicDetailsListRemaining)
                        {
                            vMNicInputDetails = new VMNicInputDetails();

                            vMNicInputDetails.NicId = nDetails.NicId;
                            vMNicInputDetails.RecoveryVMSubnetName      = nDetails.RecoveryVMSubnetName;
                            vMNicInputDetails.ReplicaNicStaticIPAddress = nDetails.ReplicaNicStaticIPAddress;
                            vMNicInputDetails.SelectionType             = nDetails.SelectionType;
                            vMNicInputDetailsList.Add(vMNicInputDetails);
                        }
                    }
                    else
                    {
                        throw new PSInvalidOperationException(Properties.Resources.NicNotFoundInVMForUpdateVmProperties);
                    }
                }
            }

            UpdateReplicationProtectedItemInputProperties updateReplicationProtectedItemInputProperties = new UpdateReplicationProtectedItemInputProperties()
            {
                RecoveryAzureVMName            = this.Name,
                RecoveryAzureVMSize            = this.Size,
                SelectedRecoveryAzureNetworkId = this.RecoveryNetworkId,
                VmNics = vMNicInputDetailsList
            };

            UpdateReplicationProtectedItemInput input = new UpdateReplicationProtectedItemInput()
            {
                Properties = updateReplicationProtectedItemInputProperties
            };

            LongRunningOperationResponse response = RecoveryServicesClient.UpdateVmProperties(
                Utilities.GetValueFromArmId(this.VirtualMachine.ID, ARMResourceTypeConstants.ReplicationFabrics),
                Utilities.GetValueFromArmId(this.VirtualMachine.ID, ARMResourceTypeConstants.ReplicationProtectionContainers),
                replicationProtectedItemResponse.ReplicationProtectedItem.Name,
                input);

            JobResponse jobResponse =
                RecoveryServicesClient
                .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

            WriteObject(new ASRJob(jobResponse.Job));
        }
        /// <summary>
        /// ProcessRecord of the command.
        /// </summary>
        public override void ExecuteSiteRecoveryCmdlet()
        {
            base.ExecuteSiteRecoveryCmdlet();

            this.targetNameOrId = this.ProtectionEntity.FriendlyName;
            this.ConfirmAction(
                this.Force.IsPresent || 0 != string.CompareOrdinal(this.Protection, Constants.DisableProtection),
                string.Format(Properties.Resources.DisableProtectionWarning, this.targetNameOrId),
                string.Format(Properties.Resources.DisableProtectionWhatIfMessage, this.Protection),
                this.targetNameOrId,
                () =>
            {
                if (this.Protection == Constants.EnableProtection)
                {
                    if (string.Compare(this.ParameterSetName, ASRParameterSets.DisableDR, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        throw new PSArgumentException(Properties.Resources.PassingPolicyMandatoryForEnablingDR);
                    }

                    EnableProtectionProviderSpecificInput enableProtectionProviderSpecificInput = new EnableProtectionProviderSpecificInput();

                    EnableProtectionInputProperties inputProperties = new EnableProtectionInputProperties()
                    {
                        PolicyId                = this.Policy.ID,
                        ProtectableItemId       = this.ProtectionEntity.ID,
                        ProviderSpecificDetails = enableProtectionProviderSpecificInput
                    };

                    EnableProtectionInput input = new EnableProtectionInput()
                    {
                        Properties = inputProperties
                    };

                    // Process if block only if policy is not null, policy is created for E2A or B2A and parameter set is for enable DR of E2A or B2A
                    if (this.Policy != null &&
                        0 == string.Compare(this.Policy.ReplicationProvider, Constants.HyperVReplicaAzure, StringComparison.OrdinalIgnoreCase) &&
                        (0 == string.Compare(this.ParameterSetName, ASRParameterSets.EnterpriseToAzure, StringComparison.OrdinalIgnoreCase) ||
                         0 == string.Compare(this.ParameterSetName, ASRParameterSets.HyperVSiteToAzure, StringComparison.OrdinalIgnoreCase)))
                    {
                        HyperVReplicaAzureEnableProtectionInput providerSettings = new HyperVReplicaAzureEnableProtectionInput();
                        providerSettings.HvHostVmId = this.ProtectionEntity.FabricObjectId;
                        providerSettings.VmName     = this.ProtectionEntity.FriendlyName;

                        // Id disk details are missing in input PE object, get the latest PE.
                        if (string.IsNullOrEmpty(this.ProtectionEntity.OS))
                        {
                            // Just checked for OS to see whether the disk details got filled up or not
                            ProtectableItemResponse protectableItemResponse =
                                RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(
                                    Utilities.GetValueFromArmId(this.ProtectionEntity.ID, ARMResourceTypeConstants.ReplicationFabrics),
                                    this.ProtectionEntity.ProtectionContainerId,
                                    this.ProtectionEntity.Name);

                            this.ProtectionEntity = new ASRProtectionEntity(protectableItemResponse.ProtectableItem);
                        }

                        if (string.IsNullOrWhiteSpace(this.OS))
                        {
                            providerSettings.OSType = ((string.Compare(this.ProtectionEntity.OS, Constants.OSWindows) == 0) || (string.Compare(this.ProtectionEntity.OS, Constants.OSLinux) == 0)) ? this.ProtectionEntity.OS : Constants.OSWindows;
                        }
                        else
                        {
                            providerSettings.OSType = this.OS;
                        }

                        if (string.IsNullOrWhiteSpace(this.OSDiskName))
                        {
                            providerSettings.VhdId = this.ProtectionEntity.OSDiskId;
                        }
                        else
                        {
                            foreach (var disk in this.ProtectionEntity.Disks)
                            {
                                if (0 == string.Compare(disk.Name, this.OSDiskName, true))
                                {
                                    providerSettings.VhdId = disk.Id;
                                    break;
                                }
                            }
                        }

                        if (RecoveryAzureStorageAccountId != null)
                        {
                            providerSettings.TargetStorageAccountId = RecoveryAzureStorageAccountId;
                        }

                        input.Properties.ProviderSpecificDetails = providerSettings;
                    }
                    else if (this.Policy != null &&
                             0 == string.Compare(this.Policy.ReplicationProvider, Constants.HyperVReplicaAzure, StringComparison.OrdinalIgnoreCase) &&
                             0 == string.Compare(this.ParameterSetName, ASRParameterSets.EnterpriseToEnterprise, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new PSArgumentException(Properties.Resources.PassingStorageMandatoryForEnablingDRInAzureScenarios);
                    }

                    this.response =
                        RecoveryServicesClient.EnableProtection(
                            Utilities.GetValueFromArmId(this.ProtectionEntity.ID, ARMResourceTypeConstants.ReplicationFabrics),
                            Utilities.GetValueFromArmId(this.ProtectionEntity.ID, ARMResourceTypeConstants.ReplicationProtectionContainers),
                            this.ProtectionEntity.Name,
                            input);
                }
                else
                {
                    // fetch the latest PE object
                    ProtectableItemResponse protectableItemResponse =
                        RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(Utilities.GetValueFromArmId(this.ProtectionEntity.ID, ARMResourceTypeConstants.ReplicationFabrics),
                                                                                   this.ProtectionEntity.ProtectionContainerId, this.ProtectionEntity.Name);
                    ProtectableItem protectableItem = protectableItemResponse.ProtectableItem;

                    if (!this.Force.IsPresent)
                    {
                        DisableProtectionInput input = new DisableProtectionInput();
                        input.Properties             = new DisableProtectionInputProperties()
                        {
                            ProviderSettings = new DisableProtectionProviderSpecificInput()
                        };

                        this.response =
                            RecoveryServicesClient.DisableProtection(
                                Utilities.GetValueFromArmId(this.ProtectionEntity.ID, ARMResourceTypeConstants.ReplicationFabrics),
                                Utilities.GetValueFromArmId(this.ProtectionEntity.ID, ARMResourceTypeConstants.ReplicationProtectionContainers),
                                Utilities.GetValueFromArmId(protectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems),
                                input);
                    }
                    else
                    {
                        this.response =
                            RecoveryServicesClient.PurgeProtection(
                                Utilities.GetValueFromArmId(this.ProtectionEntity.ID, ARMResourceTypeConstants.ReplicationFabrics),
                                Utilities.GetValueFromArmId(this.ProtectionEntity.ID, ARMResourceTypeConstants.ReplicationProtectionContainers),
                                Utilities.GetValueFromArmId(protectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems)
                                );
                    }
                }

                jobResponse =
                    RecoveryServicesClient
                    .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

                WriteObject(new ASRJob(jobResponse.Job));

                if (this.WaitForCompletion.IsPresent)
                {
                    this.WaitForJobCompletion(this.jobResponse.Job.Name);

                    jobResponse =
                        RecoveryServicesClient
                        .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

                    WriteObject(new ASRJob(jobResponse.Job));
                }
            });
        }
예제 #8
0
        /// <summary>
        /// ProcessRecord of the command.
        /// </summary>
        public override void ExecuteSiteRecoveryCmdlet()
        {
            base.ExecuteSiteRecoveryCmdlet();

            ASRRecoveryPlanGroup tempGroup;

            switch (this.ParameterSetName)
            {
            case ASRParameterSets.AppendGroup:
                RecoveryPlanGroup recoveryPlanGroup = new RecoveryPlanGroup()
                {
                    GroupType = Constants.Boot,
                    ReplicationProtectedItems = new List <RecoveryPlanProtectedItem>(),
                    StartGroupActions         = new List <RecoveryPlanAction>(),
                    EndGroupActions           = new List <RecoveryPlanAction>()
                };

                this.RecoveryPlan.Groups.Add(new ASRRecoveryPlanGroup("Group " + (RecoveryPlan.Groups.Count - 1).ToString(), recoveryPlanGroup));
                break;

            case ASRParameterSets.RemoveGroup:
                tempGroup = this.RecoveryPlan.Groups.FirstOrDefault(g => String.Compare(g.Name, RemoveGroup.Name, StringComparison.OrdinalIgnoreCase) == 0);

                if (tempGroup != null)
                {
                    this.RecoveryPlan.Groups.Remove(tempGroup);
                    this.RecoveryPlan = this.RecoveryPlan.RefreshASRRecoveryPlanGroupNames();
                }
                else
                {
                    throw new PSArgumentException(string.Format(Properties.Resources.GroupNotFoundInRecoveryPlan, this.RemoveGroup.Name, this.RecoveryPlan.FriendlyName));
                }

                break;

            case ASRParameterSets.AddProtectedEntities:
                foreach (ASRProtectionEntity pe in AddProtectedEntities)
                {
                    string fabricName = Utilities.GetValueFromArmId(pe.ID, ARMResourceTypeConstants.ReplicationFabrics);
                    // fetch the latest PE object
                    ProtectableItemResponse protectableItemResponse =
                        RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(fabricName,
                                                                                   pe.ProtectionContainerId, pe.Name);

                    ReplicationProtectedItemResponse replicationProtectedItemResponse =
                        RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(fabricName,
                                                                                            pe.ProtectionContainerId, Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId,
                                                                                                                                                  ARMResourceTypeConstants.ReplicationProtectedItems));

                    tempGroup = this.RecoveryPlan.Groups.FirstOrDefault(g => String.Compare(g.Name, Group.Name, StringComparison.OrdinalIgnoreCase) == 0);

                    if (tempGroup != null)
                    {
                        foreach (ASRRecoveryPlanGroup gp in this.RecoveryPlan.Groups)
                        {
                            if (gp.ReplicationProtectedItems == null)
                            {
                                continue;
                            }

                            if (gp.ReplicationProtectedItems.Any(pi => String.Compare(pi.Id, replicationProtectedItemResponse.ReplicationProtectedItem.Id, StringComparison.OrdinalIgnoreCase) == 0))
                            {
                                throw new PSArgumentException(string.Format(Properties.Resources.VMAlreadyPartOfGroup, pe.FriendlyName, gp.Name, this.RecoveryPlan.FriendlyName));
                            }
                        }

                        this.RecoveryPlan.Groups[RecoveryPlan.Groups.IndexOf(tempGroup)].ReplicationProtectedItems.Add(replicationProtectedItemResponse.ReplicationProtectedItem);
                    }
                    else
                    {
                        throw new PSArgumentException(string.Format(Properties.Resources.GroupNotFoundInRecoveryPlan, this.Group.Name, this.RecoveryPlan.FriendlyName));
                    }
                }
                break;

            case ASRParameterSets.RemoveProtectedEntities:
                foreach (ASRProtectionEntity pe in RemoveProtectedEntities)
                {
                    string fabricName = Utilities.GetValueFromArmId(pe.ID, ARMResourceTypeConstants.ReplicationFabrics);
                    // fetch the latest PE object
                    ProtectableItemResponse protectableItemResponse =
                        RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(fabricName,
                                                                                   pe.ProtectionContainerId, pe.Name);

                    tempGroup = this.RecoveryPlan.Groups.FirstOrDefault(g => String.Compare(g.Name, Group.Name, StringComparison.OrdinalIgnoreCase) == 0);

                    if (tempGroup != null)
                    {
                        var ReplicationProtectedItem =
                            this.RecoveryPlan.Groups[RecoveryPlan.Groups.IndexOf(tempGroup)].
                            ReplicationProtectedItems.
                            FirstOrDefault(pi => String.Compare(pi.Id,
                                                                protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId,
                                                                StringComparison.OrdinalIgnoreCase) == 0);

                        if (ReplicationProtectedItem != null)
                        {
                            this.RecoveryPlan.Groups[RecoveryPlan.Groups.IndexOf(tempGroup)].ReplicationProtectedItems.Remove(ReplicationProtectedItem);
                        }
                        else
                        {
                            throw new PSArgumentException(string.Format(Properties.Resources.VMNotFoundInGroup, pe.FriendlyName, this.Group.Name, this.RecoveryPlan.FriendlyName));
                        }
                    }
                    else
                    {
                        throw new PSArgumentException(string.Format(Properties.Resources.GroupNotFoundInRecoveryPlan, this.Group.Name, this.RecoveryPlan.FriendlyName));
                    }
                }
                break;
            }
            ;

            this.WriteObject(this.RecoveryPlan);
        }
예제 #9
0
        /// <summary>
        /// Starts PE Test failover.
        /// </summary>
        private void StartPETestFailover()
        {
            var testFailoverInputProperties = new TestFailoverInputProperties()
            {
                FailoverDirection       = this.Direction,
                NetworkId               = this.networkId,
                NetworkType             = this.networkType,
                ProviderSpecificDetails = new ProviderSpecificFailoverInput()
            };

            var input = new TestFailoverInput()
            {
                Properties = testFailoverInputProperties
            };

            // fetch the latest PE object
            ProtectableItemResponse protectableItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(this.fabricName,
                                                                           this.ProtectionEntity.ProtectionContainerId, this.ProtectionEntity.Name);

            ReplicationProtectedItemResponse replicationProtectedItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(this.fabricName,
                                                                                    this.ProtectionEntity.ProtectionContainerId, Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems));

            PolicyResponse policyResponse = RecoveryServicesClient.GetAzureSiteRecoveryPolicy(Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Properties.PolicyID, ARMResourceTypeConstants.ReplicationPolicies));

            this.ProtectionEntity = new ASRProtectionEntity(protectableItemResponse.ProtectableItem, replicationProtectedItemResponse.ReplicationProtectedItem);

            if (0 == string.Compare(
                    this.ProtectionEntity.ReplicationProvider,
                    Constants.HyperVReplicaAzure,
                    StringComparison.OrdinalIgnoreCase))
            {
                if (this.Direction == Constants.PrimaryToRecovery)
                {
                    var failoverInput = new HyperVReplicaAzureFailoverProviderInput()
                    {
                        PrimaryKekCertificatePfx   = primaryKekCertpfx,
                        SecondaryKekCertificatePfx = secondaryKekCertpfx,
                        VaultLocation = this.GetCurrentVaultLocation()
                    };

                    input.Properties.ProviderSpecificDetails = failoverInput;
                }
                else
                {
                    new ArgumentException(Properties.Resources.UnsupportedDirectionForTFO);// Throw Unsupported Direction Exception
                }
            }

            LongRunningOperationResponse response =
                RecoveryServicesClient.StartAzureSiteRecoveryTestFailover(
                    this.fabricName,
                    this.protectionContainerName,
                    Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Id, ARMResourceTypeConstants.ReplicationProtectedItems),
                    input);

            JobResponse jobResponse =
                RecoveryServicesClient
                .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

            WriteObject(new ASRJob(jobResponse.Job));
        }
예제 #10
0
        /// <summary>
        /// Starts PE Planned failover.
        /// </summary>
        private void StartPEPlannedFailover()
        {
            var plannedFailoverInputProperties = new PlannedFailoverInputProperties()
            {
                FailoverDirection       = this.Direction,
                ProviderSpecificDetails = new ProviderSpecificFailoverInput()
            };

            var input = new PlannedFailoverInput()
            {
                Properties = plannedFailoverInputProperties
            };

            // fetch the latest PE object
            ProtectableItemResponse protectableItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(this.fabricName,
                                                                           this.ProtectionEntity.ProtectionContainerId, this.ProtectionEntity.Name);

            ReplicationProtectedItemResponse replicationProtectedItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(this.fabricName,
                                                                                    this.ProtectionEntity.ProtectionContainerId, Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems));

            PolicyResponse policyResponse = RecoveryServicesClient.GetAzureSiteRecoveryPolicy(Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Properties.PolicyID, ARMResourceTypeConstants.ReplicationPolicies));

            this.ProtectionEntity = new ASRProtectionEntity(protectableItemResponse.ProtectableItem, replicationProtectedItemResponse.ReplicationProtectedItem);


            if (0 == string.Compare(
                    this.ProtectionEntity.ReplicationProvider,
                    Constants.HyperVReplicaAzure,
                    StringComparison.OrdinalIgnoreCase))
            {
                if (this.Direction == Constants.PrimaryToRecovery)
                {
                    var failoverInput = new HyperVReplicaAzureFailoverProviderInput()
                    {
                        PrimaryKekCertificatePfx   = primaryKekCertpfx,
                        SecondaryKekCertificatePfx = secondaryKekCertpfx,
                        VaultLocation = this.GetCurrentVaultLocation()
                    };
                    input.Properties.ProviderSpecificDetails = failoverInput;
                }
                else
                {
                    var failbackInput = new HyperVReplicaAzureFailbackProviderInput()
                    {
                        DataSyncOption           = this.Optimize == Constants.ForDownTime ? Constants.ForDownTime : Constants.ForSynchronization,
                        RecoveryVmCreationOption = String.Compare(this.CreateVmIfNotFound, Constants.Yes, StringComparison.OrdinalIgnoreCase) == 0 ? Constants.CreateVmIfNotFound : Constants.NoAction
                    };

                    if (String.Compare(this.CreateVmIfNotFound, Constants.Yes, StringComparison.OrdinalIgnoreCase) == 0 &&
                        string.Compare(RecoveryServicesClient.GetAzureSiteRecoveryFabric(this.fabricName).Fabric.Properties.CustomDetails.InstanceType, Constants.HyperVSite) == 0)
                    {
                        if (this.Server == null || string.Compare(this.Server.FabricType, Constants.HyperVSite) != 0)
                        {
                            throw new InvalidOperationException(
                                      Properties.Resources.ImproperServerObjectPassedForHyperVFailback);
                        }
                        else
                        {
                            failbackInput.ProviderIdForAlternateRecovery = this.Server.ID;
                        }
                    }

                    input.Properties.ProviderSpecificDetails = failbackInput;
                }
            }

            LongRunningOperationResponse response =
                RecoveryServicesClient.StartAzureSiteRecoveryPlannedFailover(
                    this.fabricName,
                    this.protectionContainerName,
                    Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Id, ARMResourceTypeConstants.ReplicationProtectedItems),
                    input);

            JobResponse jobResponse =
                RecoveryServicesClient
                .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

            WriteObject(new ASRJob(jobResponse.Job));
        }
        /// <summary>
        /// ProcessRecord of the command.
        /// </summary>
        public override void ExecuteSiteRecoveryCmdlet()
        {
            base.ExecuteSiteRecoveryCmdlet();

            var policy = RecoveryServicesClient.GetAzureSiteRecoveryPolicy(
                Utilities.GetValueFromArmId(this.ProtectionContainerMapping.PolicyId, ARMResourceTypeConstants.Policies)).Policy;
            var policyInstanceType = policy.Properties.ProviderSpecificDetails.InstanceType;

            switch (this.ParameterSetName)
            {
            case ASRParameterSets.EnterpriseToEnterprise:
                if (policyInstanceType != Constants.HyperVReplica2012 &&
                    policyInstanceType != Constants.HyperVReplica2012R2)
                {
                    throw new PSArgumentException(
                              string.Format(
                                  Properties.Resources.ContainerMappingParameterSetMismatch,
                                  this.ProtectionContainerMapping.Name,
                                  policyInstanceType));
                }
                break;

            case ASRParameterSets.EnterpriseToAzure:
            case ASRParameterSets.HyperVSiteToAzure:
                if (policyInstanceType != Constants.HyperVReplicaAzure)
                {
                    throw new PSArgumentException(
                              string.Format(
                                  Properties.Resources.ContainerMappingParameterSetMismatch,
                                  this.ProtectionContainerMapping.Name,
                                  policyInstanceType));
                }
                break;

            default:
                break;
            }

            EnableProtectionProviderSpecificInput enableProtectionProviderSpecificInput = new EnableProtectionProviderSpecificInput();
            EnableProtectionInputProperties       inputProperties = new EnableProtectionInputProperties()
            {
                PolicyId                = this.ProtectionContainerMapping.PolicyId,
                ProtectableItemId       = this.ProtectableItem.ID,
                ProviderSpecificDetails = enableProtectionProviderSpecificInput
            };

            EnableProtectionInput input = new EnableProtectionInput()
            {
                Properties = inputProperties
            };

            // E2A and B2A.
            if (0 == string.Compare(this.ParameterSetName, ASRParameterSets.EnterpriseToAzure, StringComparison.OrdinalIgnoreCase) ||
                0 == string.Compare(this.ParameterSetName, ASRParameterSets.HyperVSiteToAzure, StringComparison.OrdinalIgnoreCase))
            {
                HyperVReplicaAzureEnableProtectionInput providerSettings = new HyperVReplicaAzureEnableProtectionInput();
                providerSettings.HvHostVmId = this.ProtectableItem.FabricObjectId;
                providerSettings.VmName     = this.ProtectableItem.FriendlyName;

                // Id disk details are missing in input PE object, get the latest PE.
                if (string.IsNullOrEmpty(this.ProtectableItem.OS))
                {
                    // Just checked for OS to see whether the disk details got filled up or not
                    ProtectableItemResponse protectableItemResponse =
                        RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(
                            Utilities.GetValueFromArmId(this.ProtectableItem.ID, ARMResourceTypeConstants.ReplicationFabrics),
                            this.ProtectableItem.ProtectionContainerId,
                            this.ProtectableItem.Name);

                    this.ProtectableItem = new ASRProtectableItem(protectableItemResponse.ProtectableItem);
                }

                if (string.IsNullOrWhiteSpace(this.OS))
                {
                    providerSettings.OSType = ((string.Compare(this.ProtectableItem.OS, Constants.OSWindows, StringComparison.OrdinalIgnoreCase) == 0) ||
                                               (string.Compare(this.ProtectableItem.OS, Constants.OSLinux) == 0)) ? this.ProtectableItem.OS : Constants.OSWindows;
                }
                else
                {
                    providerSettings.OSType = this.OS;
                }

                if (string.IsNullOrWhiteSpace(this.OSDiskName))
                {
                    providerSettings.VhdId = this.ProtectableItem.OSDiskId;
                }
                else
                {
                    foreach (var disk in this.ProtectableItem.Disks)
                    {
                        if (0 == string.Compare(disk.Name, this.OSDiskName, true))
                        {
                            providerSettings.VhdId = disk.Id;
                            break;
                        }
                    }
                }

                if (RecoveryAzureStorageAccountId != null)
                {
                    providerSettings.TargetStorageAccountId = RecoveryAzureStorageAccountId;
                }

                input.Properties.ProviderSpecificDetails = providerSettings;
            }

            this.response =
                RecoveryServicesClient.EnableProtection(
                    Utilities.GetValueFromArmId(this.ProtectableItem.ID, ARMResourceTypeConstants.ReplicationFabrics),
                    Utilities.GetValueFromArmId(this.ProtectableItem.ID, ARMResourceTypeConstants.ReplicationProtectionContainers),
                    Name,
                    input);

            jobResponse =
                RecoveryServicesClient
                .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

            WriteObject(new ASRJob(jobResponse.Job));

            if (this.WaitForCompletion.IsPresent)
            {
                this.WaitForJobCompletion(this.jobResponse.Job.Name);

                jobResponse =
                    RecoveryServicesClient
                    .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

                WriteObject(new ASRJob(jobResponse.Job));
            }
        }
예제 #12
0
        /// <summary>
        /// PE Reprotect.
        /// </summary>
        private void SetPEReprotect()
        {
            ReverseReplicationInputProperties plannedFailoverInputProperties = new ReverseReplicationInputProperties()
            {
                FailoverDirection       = this.Direction,
                ProviderSpecificDetails = new ReverseReplicationProviderSpecificInput()
            };

            ReverseReplicationInput input = new ReverseReplicationInput()
            {
                Properties = plannedFailoverInputProperties
            };

            // fetch the latest PE object
            ProtectableItemResponse protectableItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(this.fabricName,
                                                                           this.ProtectionEntity.ProtectionContainerId, this.ProtectionEntity.Name);

            ReplicationProtectedItemResponse replicationProtectedItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(this.fabricName,
                                                                                    this.ProtectionEntity.ProtectionContainerId, Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems));

            PolicyResponse policyResponse = RecoveryServicesClient.GetAzureSiteRecoveryPolicy(Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Properties.PolicyID, ARMResourceTypeConstants.ReplicationPolicies));

            this.ProtectionEntity = new ASRProtectionEntity(protectableItemResponse.ProtectableItem, replicationProtectedItemResponse.ReplicationProtectedItem);

            if (0 == string.Compare(
                    this.ProtectionEntity.ReplicationProvider,
                    Constants.HyperVReplicaAzure,
                    StringComparison.OrdinalIgnoreCase))
            {
                if (this.Direction == Constants.PrimaryToRecovery)
                {
                    HyperVReplicaAzureReprotectInput reprotectInput = new HyperVReplicaAzureReprotectInput()
                    {
                        HvHostVmId = this.ProtectionEntity.FabricObjectId,
                        VmName     = this.ProtectionEntity.FriendlyName,
                        OSType     = ((string.Compare(this.ProtectionEntity.OS, "Windows") == 0) || (string.Compare(this.ProtectionEntity.OS, "Linux") == 0)) ? this.ProtectionEntity.OS : "Windows",
                        VHDId      = this.ProtectionEntity.OSDiskId
                    };

                    HyperVReplicaAzureReplicationDetails providerSpecificDetails =
                        (HyperVReplicaAzureReplicationDetails)replicationProtectedItemResponse.ReplicationProtectedItem.Properties.ProviderSpecificDetails;

                    reprotectInput.StorageAccountId = providerSpecificDetails.RecoveryAzureStorageAccount;

                    input.Properties.ProviderSpecificDetails = reprotectInput;
                }
            }

            LongRunningOperationResponse response =
                RecoveryServicesClient.StartAzureSiteRecoveryReprotection(
                    this.fabricName,
                    this.protectionContainerName,
                    Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Id, ARMResourceTypeConstants.ReplicationProtectedItems),
                    input);

            JobResponse jobResponse =
                RecoveryServicesClient
                .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

            WriteObject(new ASRJob(jobResponse.Job));
        }
예제 #13
0
        /// <summary>
        /// Starts PE Planned failover.
        /// </summary>
        private void StartPEPlannedFailover()
        {
            PlannedFailoverInputProperties plannedFailoverInputProperties = new PlannedFailoverInputProperties()
            {
                FailoverDirection       = this.Direction,
                ProviderSpecificDetails = new ProviderSpecificFailoverInput()
            };

            PlannedFailoverInput input = new PlannedFailoverInput()
            {
                Properties = plannedFailoverInputProperties
            };

            // fetch the latest PE object
            ProtectableItemResponse protectableItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryProtectableItem(this.fabricName,
                                                                           this.ProtectionEntity.ProtectionContainerId, this.ProtectionEntity.Name);

            ReplicationProtectedItemResponse replicationProtectedItemResponse =
                RecoveryServicesClient.GetAzureSiteRecoveryReplicationProtectedItem(this.fabricName,
                                                                                    this.ProtectionEntity.ProtectionContainerId, Utilities.GetValueFromArmId(protectableItemResponse.ProtectableItem.Properties.ReplicationProtectedItemId, ARMResourceTypeConstants.ReplicationProtectedItems));

            PolicyResponse policyResponse = RecoveryServicesClient.GetAzureSiteRecoveryPolicy(Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Properties.PolicyID, ARMResourceTypeConstants.ReplicationPolicies));

            this.ProtectionEntity = new ASRProtectionEntity(protectableItemResponse.ProtectableItem, replicationProtectedItemResponse.ReplicationProtectedItem);


            if (0 == string.Compare(
                    this.ProtectionEntity.ReplicationProvider,
                    Constants.HyperVReplicaAzure,
                    StringComparison.OrdinalIgnoreCase))
            {
                if (this.Direction == Constants.PrimaryToRecovery)
                {
                    HyperVReplicaAzureFailoverProviderInput failoverInput = new HyperVReplicaAzureFailoverProviderInput()
                    {
                        PrimaryKekCertificatePfx   = null,
                        SecondaryKekCertificatePfx = null,
                        VaultLocation = this.GetCurrentValutLocation()
                    };
                    input.Properties.ProviderSpecificDetails = failoverInput;
                }
                else
                {
                    HyperVReplicaAzureFailbackProviderInput failbackInput = new HyperVReplicaAzureFailbackProviderInput()
                    {
                        DataSyncOption = this.Optimize == Constants.ForDowntime ? Constants.ForDowntime : Constants.ForSynchronization,
                        //ProviderIdForAlternateRecovery = "",
                        RecoveryVmCreationOption = "CreateVmIfNotFound" //CreateVmIfNotFound | NoAction
                    };
                    input.Properties.ProviderSpecificDetails = failbackInput;
                }
            }

            LongRunningOperationResponse response =
                RecoveryServicesClient.StartAzureSiteRecoveryPlannedFailover(
                    this.fabricName,
                    this.protectionContainerName,
                    Utilities.GetValueFromArmId(replicationProtectedItemResponse.ReplicationProtectedItem.Id, ARMResourceTypeConstants.ReplicationProtectedItems),
                    input);

            JobResponse jobResponse =
                RecoveryServicesClient
                .GetAzureSiteRecoveryJobDetails(PSRecoveryServicesClient.GetJobIdFromReponseLocation(response.Location));

            WriteObject(new ASRJob(jobResponse.Job));
        }