예제 #1
0
        internal async Task <string> Clone(SnapSession session)
        {
            try
            {
                PrimaryBackup b = new PrimaryBackup();
                b.BackupName = session.BackupName;
                CloneBody body = new CloneBody();
                CloneConfigurationApplication cloneConfApp = new CloneConfigurationApplication();
                cloneConfApp.type     = "SMCoreContracts.SmSCCloneConfiguration, SMCoreContracts";
                cloneConfApp.MountCmd = new System.Collections.Generic.List <string>();
                cloneConfApp.MountCmd.Add($"mount {session.LeafIP}:%mysql_vol_Clone {session.MountPath}");
                cloneConfApp.PostCloneCreateCmd = new System.Collections.Generic.List <string>();
                cloneConfApp.PostCloneCreateCmd.Add($"{session.MountScript}");
                cloneConfApp.Host = session.CloneHostName;
                CloneConfiguration conf = new CloneConfiguration();
                conf.type   = "SMCoreContracts.SmCloneConfiguration, SMCoreContracts";
                conf.Suffix = string.Empty; // string.Format("_{0}", session.AppName); //set app alias to distiguish clones
                conf.CloneConfigurationApplication = cloneConfApp;
                body.CloneConfiguration            = conf;
                body.Backups = new System.Collections.Generic.List <Backups>();
                Backups back = new Backups();
                back.PrimaryBackup = b;
                body.Backups.Add(back);
                var response = await this.SendRequestAsync <dynamic>(Method.POST, $"api/3.0/plugins/{session.Plugin}/resources/{session.DbKey}/clone", body, false);

                return(response.Response.StatusCode.ToString());
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while cloning {session.DbKey}: {ex}");
                throw;
            }
        }
예제 #2
0
        internal async Task <BackUp> BackUpDetails(SnapSession session)
        {
            try
            {
                ClientResponse <SnapBackupResponse> response = await this.SendRequestAsync <SnapBackupResponse>(Method.GET, $"api/3.0/backups?JobId={session.BackUpJobID}");

                log.Info($"Payload Backup Detail: {response.Payload}");
                BackUp theBackup = null;
                if (response.Payload.Backups != null)
                {
                    //todo: check for the right one
                    foreach (BackUp b in response.Payload.Backups)
                    {
                        theBackup = b;
                        log.Info($"The Backup Detail: {theBackup.BackupId} {theBackup.BackupName}");
                    }
                }
                if (theBackup == null)
                {
                    log.Info($"No backup details for jobid {session.BackUpJobID}");
                }

                return(theBackup);
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while getting backup details for job id {session.BackUpJobID}: {ex}");
                throw;
            }
        }
예제 #3
0
        private void RestoreClone(SnapSession snapSession)
        {
            Task.Run(async() =>
            {
                log.Info($"Trying to restore DB for application  {snapSession.AppName}. SnapSession: {snapSession.toString()}");
                SnapCenter snapClient = await SnapCenter.NewSnapCenterSession(snapSession);
                BackUp b = snapClient.GetCloneSnapshot(snapSession);
                this.log.Info($"GetCloneSnapshot existed and b is not null: {b != null}");
                if (b != null)
                {
                    //restore snapshot
                    snapSession.BackupName = b.BackupName;
                    string answer          = await snapClient.RestoreClone(snapSession);
                    this.log.Info($"Clone restore complete. Response: {answer}");
                }
                else
                {
                    this.log.Info($"No snapshots found proceding to cloning the original.");
                    await snapClient.CloneOriginal(snapSession);

                    string snapshotID = await snapClient.SnapshotClone(snapSession);
                    this.log.Info($"Clone backup complete. ID: {snapshotID}");
                }
            }).GetAwaiter().GetResult();
        }
예제 #4
0
        internal async Task <string> ProtectResource(SnapSession session)
        {
            try
            {
                ProtectionBody body = new ProtectionBody();
                body.ProtectionGroup = new ProtectionGroup();
                body.ProtectionGroup.ProtectionGroupType = "Backup";
                ProtectionPolicy p = new ProtectionPolicy();
                p.Name = session.Policy;
                body.ProtectionGroup.Policies = new System.Collections.Generic.List <ProtectionPolicy>();
                body.ProtectionGroup.Policies.Add(p);
                PluginConfiguration pconf = new PluginConfiguration();
                pconf.type = "SMCoreContracts.SmSCBackupConfiguration, SMCoreContracts";
                pconf.FileSystemConsistentSnapshot = false;
                ProtectionConfiguration conf = new ProtectionConfiguration();
                conf.type = "SMCoreContracts.SmSCBackupConfiguration, SMCoreContracts";
                conf.Name = "rg_internal";
                conf.ConfigurationType             = "ProtectionGroup";
                conf.PluginConfiguration           = pconf;
                body.ProtectionGroup.Configuration = conf;
                var response = await this.SendRequestAsync <dynamic>(Method.POST, $"api/3.0/plugins/{session.Plugin}/resources/{session.DbKey}/protect", body, false);

                this.log.Info($"Protect Resource Response: {response.Response.Content.ToString()}");
                return(response.Response.Content.ToString());
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while protecting resource with key {session.DbKey}: {ex}");
                throw;
            }
        }
예제 #5
0
        internal static async Task <SnapCenter> NewSnapCenterSession(SnapSession session)
        {
            snapUrl = session.Url;
            var  client = new SnapCenter(snapUrl);
            User u      = new User {
                Name = session.Admin, Passphrase = session.Pass, Rolename = "SnapCenterAdmin"
            };
            UserOperationContext c = new UserOperationContext {
                User = u
            };
            AuthRequest body = new AuthRequest {
                UserOperationContext = c
            };

            try
            {
                var authResponse = await client.SendRequestAsync <dynamic>(Method.POST, "api/3.0/auth/login?TokenNeverExpires=true", body);

                client.log.Info($"Payload: {authResponse.Payload}");
                client.log.Info($"User obj in payload: { authResponse.Payload.User}");
                string t = authResponse.Payload.User.Token;
                t            = t.Trim('\r', '\n');
                client.token = t;
                client.log.Info($"Token after trimming: {client.token}");
                return(client);
            }
            catch (Exception ex)
            {
                client.log.Error($"Error getting authentication token: {ex}");
                throw;
            }
        }
예제 #6
0
        internal async Task <string> SnapshotClone(SnapSession session)
        {
            SnapSession cloneSession = session.Clone();

            try
            {
                int  attempts = 0;
                bool stop     = false;
                while (!stop)
                {
                    cloneSession.DbKey = await this.GetDbKey(cloneSession, false);

                    this.log.Info($"Cloning session data: {cloneSession.toString()}");
                    attempts++;
                    this.log.Info($"Tried getting DB Key for {cloneSession.DbName}. Attempt {attempts}");
                    stop = attempts >= CLONE_DELAY_MAX_ATTEMPTS || !string.IsNullOrEmpty(cloneSession.DbKey);
                    if (string.IsNullOrEmpty(cloneSession.DbKey))
                    {
                        if (stop)
                        {
                            string err = $"The number of attempts {attempts} to get DB key exceeded the configurable threshold of {CLONE_DELAY_MAX_ATTEMPTS}. Stopping snapshotting as DB Key is not unavailable";
                            this.log.Info(err);
                            throw new Exception(err);
                        }
                        else
                        {
                            this.log.Info($"DB Key not available yet. Will try again in 5 sec");
                            Thread.Sleep(CLONE_QUERY_INTERVAL);
                        }
                    }
                    else
                    {
                        this.log.Info($"DB Key loaded. Stoping the loop: {stop}");
                    }
                }

                log.Info($"DB Key of the clone received: {cloneSession.DbKey}");
                this.log.Info($"Sending PUT request for the clone");
                await PrepForSnapshot(cloneSession);

                try
                {
                    this.log.Info($"Protecting clone");
                    await this.ProtectResource(cloneSession);
                }
                catch (Exception protectEx)
                {
                    log.Error($"Protect resource failed. Conitnuing with clone snapshot...", protectEx);
                }
                this.log.Info($"Initiating backup");
                cloneSession.BackUpJobID = await this.BackUp(cloneSession);

                return(cloneSession.BackUpJobID);
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while snapshotting the clone {cloneSession.DbName}: {ex}");
                throw;
            }
        }
예제 #7
0
        private BackUp FindSnapshot(SnapSession snapSession)
        {
            BackUp b = null;

            Task.Run(async() =>
            {
                this.log.Info($"Obtaining DB key {snapSession.DbName}.");
                SnapCenter snapClient = await SnapCenter.NewSnapCenterSession(snapSession);
                b = snapClient.GetCloneSnapshot(snapSession);
            }).GetAwaiter().GetResult();
            return(b);
        }
예제 #8
0
        private void CloneOriginal(SnapSession snapSession)
        {
            Task.Run(async() =>
            {
                log.Info($"Initiating DB cloning for  {snapSession.AppName}. SnapSession: {snapSession.toString()}");
                this.log.Info($"Obtaining DB key {snapSession.DbName}.");
                SnapCenter snapClient = await SnapCenter.NewSnapCenterSession(snapSession);
                await snapClient.CloneOriginal(snapSession);

                string snapshotID = await snapClient.SnapshotClone(snapSession);
                this.log.Info($"Clone backup complete. ID: {snapshotID}");
            }).GetAwaiter().GetResult();
        }
예제 #9
0
        internal async Task <string> PrepForSnapshot(SnapSession session)
        {
            try
            {
                SnapShotPutBody body = new SnapShotPutBody();
                body.RunAsNames = session.RunAsName;
                VolumeMapping vm    = new VolumeMapping();
                VolumeName    vname = new VolumeName();
                vname.Name    = session.VolumeName;
                vm.VolumeName = vname;
                FootPrintObject fp = new FootPrintObject();
                fp.SVMName           = session.SvmName;
                fp.VolAndLunsMapping = new System.Collections.Generic.List <VolumeMapping>();
                fp.VolAndLunsMapping.Add(vm);
                body.FootPrint = new System.Collections.Generic.List <FootPrintObject>();
                body.FootPrint.Add(fp);
                PluginParams pluginParams = new PluginParams();
                pluginParams.Data = new System.Collections.Generic.List <PluginData>();
                PluginData port = new PluginData();
                port.Key   = "PORT";
                port.Value = "3306";
                pluginParams.Data.Add(port);
                PluginData ms = new PluginData();
                ms.Key   = "MASTER_SLAVE";
                ms.Value = "N";
                pluginParams.Data.Add(ms);
                PluginData host = new PluginData();
                host.Key   = "HOST";
                host.Value = session.CloneHostName;
                pluginParams.Data.Add(host);
                PluginData uid = new PluginData();
                uid.Key   = "CLONE_UID";
                uid.Value = SnapSession.BuildCloneName(session.DbName, session.AppName);
                pluginParams.Data.Add(uid);
                body.PluginParams = pluginParams;

                ClientResponse <SnapBackupResponse> response = await this.SendRequestAsync <SnapBackupResponse>(Method.PUT, $"api/3.0/plugins/{session.Plugin}/resources/{session.DbKey}", body, false);

                log.Info($"Payload PUT data Detail: {response.Payload}");

                return(response.Response.StatusCode.ToString());
            }
            catch (Exception ex)
            {
                this.log.Error($"Error executing PUT data for snapshot of clone with key {session.DbKey}: {ex}");
                throw;
            }
        }
예제 #10
0
        internal async Task <string> BackUp(SnapSession session)
        {
            try
            {
                BackupBody body = new BackupBody();
                body.name = session.Policy;
                var response = await this.SendRequestAsync <dynamic>(Method.POST, $"api/3.0/plugins/{session.Plugin}/resources/{session.DbKey}/backup", body, false);

                log.Info($"Payload Backup: {response.Payload}");
                string jobUri = string.Empty;
                for (int x = 0; x < response.Response.Headers.Count; x++)
                {
                    Parameter p = response.Response.Headers[x];
                    log.Info($"Backup Header: {p.Name} = {p.Value}");
                    if (p.Name == "JobURI")
                    {
                        jobUri = p.Value.ToString();
                        break;
                    }
                }
                string backUpJobID = string.Empty;
                if (string.IsNullOrEmpty(jobUri) == false)
                {
                    jobUri = jobUri.Trim('\r', '\n');
                    log.Info($"jobUri: {jobUri}");
                    string[] paths = jobUri.Split('/');
                    if (paths.Length > 0)
                    {
                        backUpJobID = paths[paths.Length - 1];
                        log.Info($"backUpJobID: {backUpJobID}");
                    }
                }
                else
                {
                    string errmsg = "Backup Header joburi not found";
                    log.Info(errmsg);
                    throw new Exception(errmsg);
                }
                return(backUpJobID);
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while performing backup: {ex}");
                throw;
            }
        }
예제 #11
0
        internal async Task <string> CreateResource(SnapSession session)
        {
            string answer = string.Empty;

            try
            {
                log.Info($"Token = {this.token}");
                ResourceBody body = new ResourceBody();
                body.ResourceName = session.DbName;
                body.ResourceType = "Database";
                body.HostName     = session.HostName;
                body.RunAsNames   = $"{session.DbName}_{session.Plugin}";
                body.MountPaths   = new System.Collections.Generic.List <MountInfo>();
                MountInfo mi = new MountInfo();
                mi.MountPath = session.MountPath;
                body.MountPaths.Add(mi);
                VolumeMapping vm    = new VolumeMapping();
                VolumeName    vname = new VolumeName();
                vname.Name    = session.VolumeName;
                vm.VolumeName = vname;
                FootPrintObject fp = new FootPrintObject();
                fp.SVMName           = session.SvmName;
                fp.VolAndLunsMapping = new System.Collections.Generic.List <VolumeMapping>();
                fp.VolAndLunsMapping.Add(vm);
                body.FootPrint = new System.Collections.Generic.List <FootPrintObject>();
                body.FootPrint.Add(fp);
                PluginParams pluginParams = new PluginParams();
                pluginParams.Data = new System.Collections.Generic.List <PluginData>();
                PluginData ms = new PluginData();
                ms.Key   = "MASTER_SLAVE";
                ms.Value = "N";
                pluginParams.Data.Add(ms);
                body.PluginParams = pluginParams;

                var response = await this.SendRequestAsync <dynamic>(Method.POST, $"api/3.0/plugins/MySQL/resources", body, false);

                log.Info($"Payload: {response.Payload}");
                string dbKey = string.Empty;
                answer = response.Response.Content.ToString();
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while getting creating resource key: {ex}");
            }
            return(answer);
        }
예제 #12
0
        internal async Task <string> RestoreClone(SnapSession session)
        {
            try
            {
                session.HostName = session.CloneHostName;
                log.Info($"restoring clone with session: {session.toString()}");
                session.DbKey = await this.GetDbKey(session, false);

                log.Info($"DB Key of the clone received: {session.DbKey}");
                // Got Junction Path : This parameter is needed for Restore API Call
                session.JunctionPath = await this.GetJunctionPath(session, false);

                log.Info($"JunctionPath of the clone received: {session.JunctionPath}");



                PrimaryBackup b = new PrimaryBackup();
                b.BackupName = session.BackupName;
                RestoreBody          body         = new RestoreBody();
                RestoreConfiguration cloneConfApp = new RestoreConfiguration();
                cloneConfApp.type = "SMCoreContracts.SmSCRestoreConfiguration, SMCoreContracts";
                //Extra Parameters needed in Restore Body:-
                cloneConfApp.MountCommands = new System.Collections.Generic.List <string>();
                cloneConfApp.MountCommands.Add($"mount {session.LeafIP}:{session.JunctionPath} {session.MountPath} ; sleep 3; /var/lib/start-mysql.sh");

                cloneConfApp.UnMountCommands = new System.Collections.Generic.List <string>();
                cloneConfApp.UnMountCommands.Add($"killall -KILL mysqld ; sleep 3 ; umount {session.MountPath}");

                Backups back = new Backups();
                back.PrimaryBackup     = b;
                body.BackupInfo        = back;
                body.PluginCode        = "SCC";
                body.RestoreLastBackup = 0;
                body.Configuration     = cloneConfApp;

                var response = await this.SendRequestAsync <dynamic>(Method.POST, $"api/3.0/plugins/{session.Plugin}/resources/{session.DbKey}/restore", body, false);

                return(response.Response.StatusCode.ToString());
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while cloning {session.DbKey}: {ex}");
                throw;
            }
        }
예제 #13
0
 internal BackUp GetCloneSnapshot(SnapSession session)
 {
     try
     {
         ClientResponse <SnapBackupResponse> response = this.SendRequest <SnapBackupResponse>(Method.GET, $"api/3.0/backups?Resource={session.DbName}");
         log.Info($"Payload Get List of backups for DB {session.DbName}: {response.Payload.ToString()}");
         if (response.Payload.Backups.Count > 0)
         {
             log.Info($"Snapshots found. Using last...");
             return(response.Payload.Backups[response.Payload.Backups.Count - 1]);
         }
         else
         {
             log.Info($"No backup details for jobid {session.BackUpJobID}");
             return(null);
         }
     }
     catch (Exception ex)
     {
         this.log.Error($"Error while getting backup details for job id {session.BackUpJobID}: {ex}");
         throw;
     }
 }
예제 #14
0
        internal async Task <string> GetDbKey(SnapSession session, bool originalDetails)
        {
            try
            {
                log.Info($"Token = {this.token}");
                var response = await this.SendRequestAsync <dynamic>(Method.GET, $"api/3.0/hosts/{session.HostName}/plugins/MySQL/resources?ResourceType=Database&ResourceName={session.DbName}");

                log.Info($"Payload: {response.Payload}");
                string dbKey = string.Empty;

                if (response.Response.StatusCode.ToString() == "OK")
                {
                    dbKey = response.Payload.Resources[0].OperationResults[0].Target.Key;
                    dbKey = dbKey.Trim('\r', '\n');

                    log.Info($"dbKey after trimming: {dbKey}");


                    if (originalDetails)
                    {   // RunAsName and SvmName are only coming from the original
                        session.RunAsName = response.Payload.Resources[0].OperationResults[0].Target.Auth.RunAsName;
                        session.SvmName   = response.Payload.Resources[0].OperationResults[0].Target.SmAppFileStorageGroups[0].StorageFootPrint.StorageSystemResources[0].Volume.Vserver;
                        // session.junctionPath = response.Payload.Resources[0].OperationResults[0].Target.SmAppFileStorageGroups[0].StorageFootPrint.StorageSystemResources[0].Volume.JunctionPath;
                    }

                    // volume name are unique for each instance
                    session.VolumeName = response.Payload.Resources[0].OperationResults[0].Target.SmAppFileStorageGroups[0].StorageFootPrint.StorageSystemResources[0].Volume.Name;
                }
                return(dbKey);
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while getting DB key: {ex}");
                throw ex;
            }
        }
예제 #15
0
        //Function to Get Clone Junction Path
        internal async Task <string> GetJunctionPath(SnapSession session, bool originalDetails)
        {
            try
            {
                log.Info($"Token = {this.token}");
                var response = await this.SendRequestAsync <dynamic>(Method.GET, $"api/3.0/hosts/{session.HostName}/plugins/MySQL/resources?ResourceType=Database&ResourceName={session.DbName}");

                log.Info($"Payload: {response.Payload}");

                string junctionPath = string.Empty;
                if (response.Response.StatusCode.ToString() == "OK")
                {
                    junctionPath = response.Payload.Resources[0].OperationResults[0].Target.SmAppFileStorageGroups[0].StorageFootPrint.StorageSystemResources[0].Volume.JunctionPath;

                    log.Info($"JunectionPath after trimming: {junctionPath}");
                }
                return(junctionPath);
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while getting Junction Path: {ex}");
                throw ex;
            }
        }
예제 #16
0
        public override void OnPromotingVersion(
            ReadOnlyVersionDataDTO version,
            ApplicationVersionStageDTO proposedStage)
        {
            Task.Run(async() =>
            {
                try
                {
                    this.snapSession = new SnapSession();
                    log.Info($"Authenticating with Apprenda. App = {version.ApplicationAlias}, Token=  {SessionContext.Instance.SessionToken}.");
                    snapSession.AppName = version.ApplicationAlias;
                    var acpClient       = new ACP(SessionContext.Instance.SessionToken);

                    try
                    {
                        log.Info($"Loading Developer properties");

                        var customProperties = acpClient.GetComponentCustomProperties(
                            version.ApplicationAlias, version.Alias, string.Empty).Payload;
                        log.Info($"Loaded Developer custom properties");
                        foreach (CustomProperty cp in customProperties)
                        {
                            log.Info($"Prop Name: {cp.PropertyModel.Name}, Value: {cp.Values.First()}");
                        }
                        var devDbCloneType = customProperties.First(p =>
                                                                    p.PropertyModel.Name == CustomProperties.DBCloneType);
                        log.Info($"Loaded clone type property and it is not null {devDbCloneType != null}");
                        if (devDbCloneType != null)
                        {
                            this.snapSession.CloneType = devDbCloneType.Values.First();
                        }
                        log.Info($"Loaded Developer settings for clone type {this.snapSession.CloneType}");

                        var devDbName = customProperties.First(p =>
                                                               p.PropertyModel.Name == CustomProperties.SnapDBName);
                        log.Info($"Loaded db name property and it is not null {devDbName != null}");
                        if (devDbName != null)
                        {
                            this.snapSession.DbName = devDbName.Values.First();
                        }
                        log.Info($"Loaded Developer settings for DBName {this.snapSession.DbName}");

                        var devPlugin = customProperties.First(p =>
                                                               p.PropertyModel.Name == CustomProperties.SnapPlugin);
                        log.Info($"Loaded Snap Plugin property and it is not null {devPlugin != null}");
                        if (devPlugin != null)
                        {
                            this.snapSession.Plugin = devPlugin.Values.First();
                        }
                        log.Info($"Loaded Developer settings for Snap Plugin {this.snapSession.Plugin}");
                    }
                    catch (Exception ex)
                    {
                        log.Error("Issues loading developer properties. Falling back on SOC defaults", ex);
                    }

                    log.Info($"Loading SOC properties");

                    var socprops = (await acpClient.GetAllCustomPropertiesAsync()).Payload;
                    if (socprops != null)
                    {
                        if (socprops.items != null && socprops.items.Count > 0)
                        {
                            log.Info($"Loaded SOC properties");
                            var snapCloneType = socprops.items.First(p =>
                                                                     p.name == CustomProperties.DBCloneType);

                            if (string.IsNullOrEmpty(this.snapSession.CloneType) && (snapCloneType != null && snapCloneType.valueOptions.defaultValues != null && snapCloneType.valueOptions.defaultValues.Count > 0))
                            {
                                this.snapSession.CloneType = snapCloneType.valueOptions.defaultValues[0];
                            }

                            var snapPluginProp = socprops.items.First(p =>
                                                                      p.name == CustomProperties.SnapPlugin);

                            if (string.IsNullOrEmpty(this.snapSession.Plugin) && snapPluginProp != null && snapPluginProp.valueOptions.defaultValues != null && snapPluginProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.Plugin = snapPluginProp.valueOptions.defaultValues[0];
                            }


                            var snapUrlProp = socprops.items.First(p =>
                                                                   p.name == CustomProperties.SnapCenterUrl);

                            if (snapUrlProp != null && snapUrlProp.valueOptions.defaultValues != null && snapUrlProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.Url = snapUrlProp.valueOptions.defaultValues[0];
                            }


                            var snapAdminProp = socprops.items.First(p =>
                                                                     p.name == CustomProperties.SnapCenterAdmin);
                            if (snapAdminProp != null && snapAdminProp.valueOptions.defaultValues != null && snapAdminProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.Admin = snapAdminProp.valueOptions.defaultValues[0];
                            }

                            var snapPassProp = socprops.items.First(p =>
                                                                    p.name == CustomProperties.SnapCenterPassword);
                            if (snapPassProp != null && snapPassProp.valueOptions.defaultValues != null && snapPassProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.Pass = snapPassProp.valueOptions.defaultValues[0];
                            }

                            var dbNameProp = socprops.items.First(p =>
                                                                  p.name == CustomProperties.SnapDBName);
                            if (string.IsNullOrEmpty(this.snapSession.DbName) && dbNameProp != null && dbNameProp.valueOptions.defaultValues != null && dbNameProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.DbName = dbNameProp.valueOptions.defaultValues[0];
                            }


                            var hostNameProp = socprops.items.First(p =>
                                                                    p.name == CustomProperties.SnapDBHost);

                            if (hostNameProp != null && hostNameProp.valueOptions.defaultValues != null && hostNameProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.HostName = hostNameProp.valueOptions.defaultValues[0];
                            }

                            var cloneHostNameProp = socprops.items.First(p =>
                                                                         p.name == CustomProperties.SnapDBCloneHost);
                            this.log.Info($"Processing clone hostname settings");
                            if (cloneHostNameProp != null && cloneHostNameProp.valueOptions.defaultValues != null && cloneHostNameProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.CloneHostName = cloneHostNameProp.valueOptions.defaultValues[0];
                                this.log.Info($"Going with the default value {this.snapSession.CloneHostName}.");
                            }
                            else if (cloneHostNameProp != null && cloneHostNameProp.valueOptions.possibleValues != null && cloneHostNameProp.valueOptions.possibleValues.Count == 1)
                            {
                                this.log.Info($"Default is not set. Only one possible value found = {cloneHostNameProp.valueOptions.possibleValues[0]}. Use it");
                                this.snapSession.CloneHostName = cloneHostNameProp.valueOptions.possibleValues[0];
                            }
                            else if (cloneHostNameProp != null && cloneHostNameProp.valueOptions.possibleValues != null && cloneHostNameProp.valueOptions.possibleValues.Count > 0)
                            {
                                this.log.Info($"Default is not set and multiple servers are configured. Will figure out which of the configured servers is less busy");
                                string preferred = FindTargetNode(acpClient, cloneHostNameProp.valueOptions.possibleValues);
                                this.log.Info($"The preferred server is {preferred}. Will use it");
                                this.snapSession.CloneHostName = preferred;
                            }
                            else
                            {
                                log.Error($"Error cloning Db {snapSession.DbName} for application {version.ApplicationAlias}: The Clone Host Name property is not configured");
                                return;
                            }
                            this.log.Info($"CloneHostName set to {this.snapSession.CloneHostName}.");

                            var policyProp = socprops.items.First(p =>
                                                                  p.name == CustomProperties.SnapPolicy);

                            if (policyProp != null && policyProp.valueOptions.defaultValues != null && policyProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.Policy = policyProp.valueOptions.defaultValues[0];
                            }

                            var snapScriptProp = socprops.items.First(p =>
                                                                      p.name == CustomProperties.SnapMountScript);

                            if (snapScriptProp != null && snapScriptProp.valueOptions.defaultValues != null && snapScriptProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.MountScript = snapScriptProp.valueOptions.defaultValues[0];
                            }

                            var snapDataLeafProp = socprops.items.First(p =>
                                                                        p.name == CustomProperties.SnapDataLeafIP);

                            if (snapDataLeafProp != null && snapDataLeafProp.valueOptions.defaultValues != null && snapDataLeafProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.LeafIP = snapDataLeafProp.valueOptions.defaultValues[0];
                            }



                            var snapMountPathProp = socprops.items.First(p =>
                                                                         p.name == CustomProperties.SnapMountPath);

                            if (snapMountPathProp != null && snapMountPathProp.valueOptions.defaultValues != null && snapMountPathProp.valueOptions.defaultValues.Count > 0)
                            {
                                this.snapSession.MountPath = snapMountPathProp.valueOptions.defaultValues[0];
                            }
                        }
                    }
                    else
                    {
                        this.log.Info($"Cannot load SOC properties. Will try to use configs");
                        this.snapSession.Plugin        = Settings.Default.SnapPlugin;
                        this.snapSession.Url           = Settings.Default.SnapCenterUrl;
                        this.snapSession.Admin         = Settings.Default.SnapCenterAdmin;
                        this.snapSession.Pass          = Settings.Default.SnapCenterPassword;
                        this.snapSession.DbName        = Settings.Default.SnapDBName;
                        this.snapSession.HostName      = Settings.Default.SnapDBHost;
                        this.snapSession.CloneHostName = Settings.Default.SnapDBCloneHost;
                        this.snapSession.Policy        = Settings.Default.SnapPolicy;
                        this.snapSession.MountPath     = Settings.Default.SnapMountPath;
                        this.snapSession.MountScript   = Settings.Default.SnapMountScript;
                        this.snapSession.LeafIP        = Settings.Default.SnapDataLeafIP;
                    }

                    this.log.Info($"Snap session: {this.snapSession.toString()}");
                    if (this.snapSession.isValid())
                    {
                        //check the type of cloning requested
                        switch (this.snapSession.CloneType)
                        {
                        case DBCloneTypes.CloneOriginal:
                            CloneOriginal(snapSession);
                            break;

                        case DBCloneTypes.RestoreClone:
                            RestoreClone(snapSession);
                            break;

                        default:
                            {
                                BackUp b = FindSnapshot(snapSession);
                                if (b == null)     //if clones do not exist, clone the original
                                {
                                    this.log.Info($"Clone not found. Performing cloning of the original");
                                    CloneOriginal(snapSession);
                                }
                                else
                                {
                                    this.log.Info($"Clone found. Do nothing. Will use existing copy");
                                    //do nothing is the app needs to conect to the existing clone
                                }
                            }
                            break;
                        }
                    }
                    else
                    {
                        this.log.Info($"Snap data incomplete. Aborting...");
                    }
                }
                catch (Exception ex)
                {
                    log.Error($"Error cloning Db {snapSession.DbName} for application {version.ApplicationAlias}: {ex}");
                }
            }).GetAwaiter().GetResult();
        }
예제 #17
0
        internal async Task <string> CloneOriginal(SnapSession snapSession)
        {
            try
            {
                //create resource in SnapCenter, if does not exist
                //string r = await CreateResource(snapSession);
                //log.Info($"Called create resource. Response: {r}.");

                snapSession.DbKey = await GetDbKey(snapSession, true);

                log.Info($"DB Key received {snapSession.DbKey}.");

                try
                {
                    this.log.Info($"Protecting resource");
                    await ProtectResource(snapSession);
                }
                catch (Exception protectEx)
                {
                    log.Error($"Protect resource failed. Contnuing cloning...", protectEx);
                }

                this.log.Info($"Initiating backup");
                snapSession.BackUpJobID = await BackUp(snapSession);

                this.log.Info($"Getting backup details for jobID {snapSession.BackUpJobID}");

                BackUp b        = null;
                int    attempts = 0;
                bool   stop     = false;
                while (!stop)
                {
                    b = await BackUpDetails(snapSession);

                    attempts++;
                    this.log.Info($"Tried getting backup details for jobid {snapSession.BackUpJobID}. Attempt {attempts}");
                    stop = attempts >= BACKUP_DETAIL_MAX_ATTEMPTS || b != null;
                    if (b == null)
                    {
                        if (stop)
                        {
                            string err = $"The number of attempts {attempts} to get back up details exceeded the configurable threshold of {BACKUP_DETAIL_MAX_ATTEMPTS}. Stopping cloning as backup details are unavailable";
                            this.log.Info(err);
                            throw new Exception(err);
                        }
                        else
                        {
                            this.log.Info($"Backup details not available yet. Will try again in 5 sec");
                            Thread.Sleep(BACKUP_QUERY_INTERVAL);
                        }
                    }
                    else
                    {
                        this.log.Info($"Backup details loaded. Stoping the loop: {stop}");
                    }
                }

                snapSession.BackUpID   = b.BackupId;
                snapSession.BackupName = b.BackupName;

                this.log.Info($"Cloning from backup {snapSession.BackUpID}, name = {snapSession.BackupName}");
                string answer = await Clone(snapSession);

                this.log.Info($"DB Cloning complete.");
                return(answer);
            }
            catch (Exception ex)
            {
                this.log.Error($"Error while cloning {snapSession.DbName}: {ex}");
                throw;
            }
        }