示例#1
0
        public void AddBackupRun(BackupRun br)
        {
            this.Logger.LogInformation("Adding BackupRun with {0} file refs", br.BackupFileRefs == null ? 0 : br.BackupFileRefs.Count);

            this.dbContext.Add <BackupRun>(br);
            this.dbContext.SaveChangesAsync();
        }
示例#2
0
        public void UpdateBackupRun(BackupRun br)
        {
            this.Logger.LogInformation("Updating BackupRun set with BackupRunID: {0}", br.BackupRunID);

            this.dbContext.Update <BackupRun>(br);
            this.dbContext.SaveChangesAsync();
        }
        public void CompleteFileArchive(BackupRunFileRef backupRef, BackupRun br)
        {
            var cacheFileName = GetCacheEntryForFile(backupRef.FullFileName, br);

            if (File.Exists(cacheFileName))
            {
                Logger.LogDebug("Deleting cache file after archive: {0}", cacheFileName);

                File.Delete(cacheFileName);
            }
        }
        public Stream GetCacheStreamForItem(BackupRunFileRef item, BackupRun br)
        {
            var cacheFile = new FileInfo(GetCacheEntryForFile(item.FullFileName, br));

            if (File.Exists(cacheFile.FullName) == false)
            {
                cacheFile.Create();
            }

            return(cacheFile.OpenRead());
        }
示例#5
0
        public bool ArchiveFile(BackupRun backupRun, BackupRunFileRef fileRef, Stream cacheFileStream)
        {
            if (false == isInitialized)
            {
                this.Initialize();
            }

            Logger.LogDebug("Called FileSystemBackup.ArchiveFile");

            //TODO Move direcory check
            //Don't copy directories
            //if (Directory.Exists(cacheFile.FullName))
            //{
            //    Logger.LogInformation(String.Format("Skipping archive for directory reference: {0}", fileRef.FullFileName));

            //    return true;
            //}

            FileInfo archiveFile = new FileInfo(String.Format("{0}{1}{2}{3}{4}",
                                                              this.baseBackupDir,
                                                              Path.DirectorySeparatorChar,
                                                              backupRun.BackupRunID,
                                                              Path.DirectorySeparatorChar,
                                                              fileRef.FullFileName.Substring(3)));

            if (archiveFile.Exists)
            {
                Logger.LogInformation(String.Format("Deleting existing archive entry for file: {0}", fileRef.FullFileName));

                archiveFile.Delete();
            }

            if (archiveFile.Directory.Exists == false)
            {
                Logger.LogInformation(String.Format("Creating parent directory for archive entry: {0}", archiveFile.Directory.FullName));

                archiveFile.Directory.Create();
            }

            byte[] buffer = new byte[1024];
            int    offset = 0;
            int    count;

            while ((count = cacheFileStream.Read(buffer, offset, buffer.Length)) > 0)
            {
                offset += count;
            }

            Logger.LogInformation(String.Format("Completed archive copy for entry: {0} with result: {1}", fileRef.FullFileName, archiveFile.Exists));

            return(true);
        }
示例#6
0
 protected override void ProcessRecord()
 {
     if (ParameterSetName == ParameterSetNames.GetList)
     {
         IEnumerable <BackupRun> backups = GetAllBackupRuns();
         WriteObject(backups, true);
     }
     else
     {
         BackupRunsResource.GetRequest request = Service.BackupRuns.Get(Project, Instance, Id);
         BackupRun result = request.Execute();
         WriteObject(result);
     }
 }
        public void PopulateFilesForBackupRun(BackupRun br)
        {
            List <FileInfo> directoryFiles = new List <FileInfo>();

            Logger.LogInformation("Starting directory scan for backup run");

            foreach (var dirRef in br.BackupDirectories)
            {
                var rootDir = dirRef.DirectoryFullFileName;

                if (String.IsNullOrWhiteSpace(rootDir))
                {
                    throw new Exception("No root directory provided");
                }
                else if (!Directory.Exists(rootDir))
                {
                    throw new Exception(String.Format("Root directory {0} doesn't exist", rootDir));
                }

                PopulateFileList(rootDir, directoryFiles);
            }

            foreach (FileInfo info in directoryFiles)
            {
                //Make sure file wasn't added in an ealier scan for this run
                if (br.BackupFileRefs.Where <BackupRunFileRef>(r => r.FullFileName.ToLower().Equals(info.FullName.ToLower())).ToList().Count == 0)
                {
                    Logger.LogInformation(String.Format("Adding file ref {0} to backup run ID {1}", info.FullName, br.BackupRunID));
                    br.BackupFileRefs.Add(new BackupRunFileRef {
                        FullFileName = info.FullName
                    });
                }
            }

            string backupCacheFullDir = String.Format("{0}{1}", this.BackupCacheDirectory, br.BackupRunID);

            if (Directory.Exists(backupCacheFullDir) == false)
            {
                Logger.LogInformation(String.Format("Creating new backup cache directory at {0}", backupCacheFullDir));

                Directory.CreateDirectory(backupCacheFullDir);
            }
        }
示例#8
0
        private BackupRun CreateBackupRun()
        {
            Logger.LogDebug("CreateBackupRun called");
            var appConfigRoot = this.serviceProvider.GetService <IConfigurationRoot>();
            var config        = appConfigRoot.GetSection("BackupSettings");

            if (config == null)
            {
                throw new Exception("No config section found for backup settings");
            }

            config = config.GetSection("BackupDirectories");

            if (config == null)
            {
                throw new Exception("No config section found for backup directories");
            }

            var br = new BackupRun
            {
                BackupFileRefs    = new List <BackupRunFileRef>(),
                BackupDirectories = new List <BackupDirectoryRef>()
            };


            string[] dirList = this.GetBackupSettingsConfigValue("BackupDirectories").Split(',');

            for (int i = 0; i < dirList.Length; i++)
            {
                br.BackupDirectories.Add(new BackupDirectoryRef {
                    DirectoryFullFileName = dirList[i]
                });
            }

            this.ClientDBHandler.AddBackupRun(br);

            Logger.LogInformation(String.Format("Created new backup run with ID: {0}", br.BackupRunID));

            return(br);
        }
示例#9
0
        /// <summary>
        /// Creates a new backup run on demand. This method is applicable only to Second Generation instances.
        /// Documentation https://developers.google.com/sqladmin/v1beta4/reference/backupRuns/insert
        /// Generation Note: This does not always build corectly.  Google needs to standardise things I need to figuer out which ones are wrong.
        /// </summary>
        /// <param name="service">Authenticated Sqladmin service.</param>
        /// <param name="project">Project ID of the project that contains the instance.</param>
        /// <param name="instance">Cloud SQL instance ID. This does not include the project ID.</param>
        /// <param name="body">A valid Sqladmin v1beta4 body.</param>
        /// <returns>OperationResponse</returns>
        public static Operation Insert(SqladminService service, string project, string instance, BackupRun body)
        {
            try
            {
                // Initial validation.
                if (service == null)
                {
                    throw new ArgumentNullException("service");
                }
                if (body == null)
                {
                    throw new ArgumentNullException("body");
                }
                if (project == null)
                {
                    throw new ArgumentNullException(project);
                }
                if (instance == null)
                {
                    throw new ArgumentNullException(instance);
                }

                // Make the request.
                return(service.BackupRuns.Insert(body, project, instance).Execute());
            }
            catch (Exception ex)
            {
                throw new Exception("Request BackupRuns.Insert failed.", ex);
            }
        }
示例#10
0
        private void Start()
        {
            this.Logger.LogInformation("Initializing BackupClient services...");

            var appConfig = new ConfigurationBuilder()
                            .SetBasePath(System.IO.Directory.GetCurrentDirectory())
                            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();

            this.serviceProvider = new ServiceCollection()
                                   .AddSingleton <ICloudBackupArchiveProvider, FileSystemBackupArchiveProvider>()
                                   .AddSingleton <IClientDBHandler, InMemoryDBHandler>()
                                   .AddSingleton <IConfigurationRoot>(provider => appConfig)
                                   .AddSingleton <IClientFileCacheHandler, LocalClientFileCacheHandler>()
                                   .AddLogging(builder => builder.AddConsole())
                                   .BuildServiceProvider();

            this.Logger.LogInformation("Starting backup run at {0}", DateTime.Now.ToString());

            var appConfigRoot = this.serviceProvider.GetService <IConfigurationRoot>();
            var config        = appConfigRoot.GetSection("BackupSettings");

            if (config == null)
            {
                throw new Exception("No config section found for backup settings");
            }

            this.stopRunTime = DateTime.Now.AddSeconds(this.TotalRunTimeSeconds);

            try
            {
                BackupRun br = null;

                try
                {
                    br = GetOpenBackupRun();

                    if (br == null)
                    {
                        this.Logger.LogInformation("Creating new backup run");
                        br = CreateBackupRun();
                    }

                    this.Logger.LogInformation(String.Format("Processing open backup run with ID: {0}", br.BackupRunID));

                    ArchiveCurrentBackupRun(br);
                }
                catch (Exception ex)
                {
                    if (br != null)
                    {
                        br.BackupRunCompleted  = true;
                        br.BackupRunEnd        = DateTime.Now;
                        br.FailedWithException = true;
                        br.ExceptionMessage    = String.Format("{0}:{1}", ex.Message, ex.StackTrace);

                        try
                        {
                            this.ClientDBHandler.UpdateBackupRun(br);
                        }
                        catch (Exception dbEx)
                        {
                            this.Logger.LogError(dbEx, "Couldn't save backup run exception: {0}", dbEx.Message);
                        }
                    }

                    this.Logger.LogError(ex, "Failure in processing backup run: {0}", ex.Message);
                }
            }
            catch (Exception ex)
            {
                this.Logger.LogError(ex, "Failure in starting DB: {0}", ex.Message);
            }
            finally
            {
                this.ClientDBHandler.Dispose();
            }
        }
示例#11
0
        private BackupRun InitializeBackupRun(BackupRun br)
        {
            Logger.LogDebug("BackupClient.InitializeNewBackupRun called");

            this.ClientFileCacheHandler.PopulateFilesForBackupRun(br);

            long   currentBytes;
            string cacheRef;
            int    fileCount;

            br.BackupRunStart = DateTime.Now;

            currentBytes = 0;

            //File count tracked separately in case the last run is all directories
            fileCount = 0;

            this.Logger.LogInformation("Copying scanned files to backup cache");


            foreach (var fileRef in br.BackupFileRefs)
            {
                if (currentBytes > this.MaxCacheMB * 1000000)
                {
                    Logger.LogInformation("Halting cache file copy due to max copy bytes exceded");
                    break;
                }

                if (fileRef.CopiedToCache == true)
                {
                    Logger.LogDebug(String.Format("Skipping file already copied to backup cache: {0}", fileRef.FullFileName));
                    continue;
                }

                cacheRef = GetCacheEntryForFile(fileRef.FullFileName, br);

                //Verify file wasn't removed from source or already copied to the cache
                if ((Directory.Exists(fileRef.FullFileName) || File.Exists(fileRef.FullFileName)) && File.Exists(cacheRef) == false)
                {
                    if (Directory.Exists(fileRef.FullFileName))
                    {
                        Logger.LogInformation(String.Format("Creating backup cache directory: {0}", cacheRef));

                        Directory.CreateDirectory(cacheRef);
                    }
                    else
                    {
                        if (File.Exists(cacheRef))
                        {
                            Logger.LogInformation(String.Format("Deleting previous version of cache file: {0}", cacheRef));

                            File.Delete(cacheRef);
                        }

                        Logger.LogInformation(String.Format("Copying cache file from source: {0} to target: {1}", fileRef.FullFileName, cacheRef));

                        File.Copy(fileRef.FullFileName, cacheRef);
                        var cacheFile = new FileInfo(cacheRef);
                        currentBytes += cacheFile.Length;

                        Logger.LogDebug(String.Format("Cache copy current bytes count: {0}", currentBytes));
                    }

                    fileRef.CopiedToCache = true;

                    fileCount += 1;

                    Logger.LogDebug("Saving file ref changes");

                    this.ClientDBHandler.UpdateBackupFileRef(fileRef);
                }
            }

            if (fileCount == 0)
            {
                Logger.LogInformation("Backup file count == 0, setting complete flag");

                br.BackupRunCompleted = true;
                br.BackupRunEnd       = DateTime.Now;

                this.ClientDBHandler.UpdateBackupRun(br);
            }

            return(br);
        }
示例#12
0
        private void ArchiveCurrentBackupRun(BackupRun br)
        {
            bool haltTimeNotExceeded;

            do
            {
                InitializeBackupRun(br);

                foreach (var item in br.BackupFileRefs)
                {
                    if (item.CopiedToCache == true && item.CopiedToArchive == false && br.FailedWithException == false)
                    {
                        try
                        {
                            var cacheFileStream = this.ClientFileCacheHandler.GetCacheStreamForItem(item, br);

                            bool success = this.serviceProvider.GetService <ICloudBackupArchiveProvider>().ArchiveFile(br, item, cacheFileStream);

                            cacheFileStream.Close();

                            if (success == false)
                            {
                                throw new Exception(String.Format("Filed to archive file ref: {0}", item.FullFileName));
                            }
                            else
                            {
                                Logger.LogInformation("Arcive copy successful for source file: {0}", item.FullFileName);

                                item.CopiedToArchive = true;

                                this.ClientDBHandler.UpdateBackupFileRef(item);
                            }
                        }
                        catch (Exception ex)
                        {
                            br.FailedWithException = true;
                            br.BackupRunEnd        = DateTime.Now;
                            br.ExceptionMessage    = ex.Message;

                            //  dbContext.Update<BackupRun>(br);

                            this.ClientDBHandler.UpdateBackupRun(br);

                            throw new Exception(String.Format("Backup run with ID {0} failed with exception: {1}", br.BackupRunID, ex.Message));
                        }
                        finally
                        {
                            this.ClientDBHandler.UpdateBackupRun(br);
                        }
                    }
                }

                haltTimeNotExceeded = (DateTime.Now.CompareTo(this.stopRunTime) < 0);

                Logger.LogInformation("Completed cache copy run with BackupRun.Completed = {0} and halt time {1} exceeded",
                                      br.BackupRunCompleted,
                                      (haltTimeNotExceeded ? "was not" : "was"));
            } while (br.BackupRunCompleted == false && haltTimeNotExceeded == true);


            foreach (var backupRef in br.BackupFileRefs)
            {
                this.ClientFileCacheHandler.CompleteFileArchive(backupRef, br);
            }
        }
 private string GetCacheEntryForFile(string fullFileName, BackupRun br) => String.Format("{0}{1}{2}{3}", this.BackupCacheDirectory, br.BackupRunID, Path.DirectorySeparatorChar, fullFileName.Substring(fullFileName.IndexOf(":") + 1));