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; } }
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; } }
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(); }
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; } }
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; } }
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; } }
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); }
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(); }
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; } }
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; } }
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); }
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; } }
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; } }
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; } }
//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; } }
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(); }
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; } }