コード例 #1
0
        public static Configuration ParseFromCommandLine(string[] args) 
        {
            Configuration c = new Configuration();

            #region look for F_BACKUP_TYPE
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == F_BACKUP_TYPE)
                {
                    if (i + 1 >= args.Length)
                    {
                        throw new ArgumentException(string.Format("{0:S} flag must be followed by backup type", F_BACKUP_TYPE));
                    }

                    string sBt = args[i + 1];

                    BackupType bt;

                    if (!Enum.TryParse<BackupType>(sBt, out bt))
                    {
                        throw new ArgumentException(string.Format("Backup type can be either {0:S}, {1:S} or {2:S}. {3:S} is not supported.",
                            BackupType.Full, BackupType.Differential, BackupType.Log, sBt));
                    }

                    c.BackupType = bt;

                    break;
                }
            }
            #endregion

            #region look for F_DATA_SOURCE
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == F_DATA_SOURCE)
                {
                    if (i + 1 >= args.Length)
                    {
                        throw new ArgumentException(string.Format("{0:S} flag must be followed data source", F_DATA_SOURCE));
                    }

                    c.DataSource = args[i + 1];

                    break;
                }
            }
            #endregion

            #region look for F_INTEGRATED or F_USERNAME_PASSWORD
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == F_INTEGRATED)
                {
                    c.UserIntegrated = true;
                    break;
                }
                if (args[i] == F_USERNAME_PASSWORD)
                {
                    c.UserIntegrated = false;
                    if (i + 2 >= args.Length)
                    {
                        throw new ArgumentException(string.Format("{0:S} flag must be followed by user name and password", F_USERNAME_PASSWORD));
                    }

                    c.Username = args[i + 1];
                    c.Password = args[i + 2];

                    break;
                }
            }
            #endregion

            #region look for F_STORAGE_ACCOUNT
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == F_STORAGE_ACCOUNT)
                {
                    if (i + 3 >= args.Length)
                    {
                        throw new ArgumentException(string.Format("{0:S} flag must be followed by storage account name, secret and container", F_STORAGE_ACCOUNT));
                    }

                    c.StorageAccount = args[i + 1];
                    c.Secret = args[i + 2];
                    c.Container = args[i + 3];

                    break;
                }
            }
            #endregion

            #region look for F_RETENTION flag
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == F_RETENTION)
                {
                    if (i + 1 >= args.Length)
                    {
                        throw new ArgumentException(string.Format("{0:S} flag must be followed by retention days", F_RETENTION));
                    }

                    int v;
                    if (!int.TryParse(args[i + 1], out v))
                    {
                        throw new ArgumentException(string.Format("{0:S} flag must be followed by a valid number ({1:S} is not a valid number)", F_RETENTION, args[i + 1]));
                    }

                    c.RetentionDays = v;

                    break;
                }
            }
            #endregion

            if (c.BackupType == BackupType.Unknown)
                throw new ArgumentException("Please specify backup type");

            if (string.IsNullOrEmpty(c.DataSource))
                throw new ArgumentException("Please specify the data source (SQL Server to backup)");

            if (c.UserIntegrated == false && string.IsNullOrEmpty(c.Username) && string.IsNullOrEmpty(c.Password))
                throw new ArgumentException("Please specify authentication type (either integrated or mixed)");

            if (string.IsNullOrEmpty(c.StorageAccount) || string.IsNullOrEmpty(c.Secret) || string.IsNullOrEmpty(c.Container))
                throw new ArgumentException("Please specify the Azure parameters (storage account, container and secret)");

            if (c.RetentionDays == int.MinValue)
                throw new ArgumentException("Please specify the retention days (-1 for unlimited)");

            return c;
        }
コード例 #2
0
        static int Process(string[] args)
        {
            Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".exe v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);
            log4net.Config.XmlConfigurator.Configure(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("BackupToUrlWithRotation.log4net.xml"));

            log.Debug("Parsing command line");
            try
            {
                config = Configuration.ParseFromCommandLine(args);
            }
            catch (Exception e)
            {
                log.ErrorFormat("Syntax error: {0:S}", e.Message);
                Configuration.Usage();

                return -1;
            }
            log.Debug("Parsing command line completed");

            log.DebugFormat("config == {0:S}", config.ToString());

            System.Data.SqlClient.SqlConnectionStringBuilder sb = new System.Data.SqlClient.SqlConnectionStringBuilder();
            sb.DataSource = config.DataSource;
            if (config.UserIntegrated)
                sb.IntegratedSecurity = true;
            else
            {
                sb.IntegratedSecurity = false;
                sb.UserID = config.Username;
                sb.Password = config.Password;
            }

            #region Azure connection setup
            Microsoft.WindowsAzure.Storage.Auth.StorageCredentials sc = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(config.StorageAccount, config.Secret);
            CloudStorageAccount csa = new CloudStorageAccount(sc, true);
            var client = csa.CreateCloudBlobClient();
            var container = client.GetContainerReference(config.Container);
            log.DebugFormat("Creating container {0:S} if not existent", config.Container);
            container.CreateIfNotExists();
            #endregion

            dbUtil = new DBUtil(sb.ConnectionString, SQLInfoHandler);
            string tempCred = Guid.NewGuid().ToString();

            log.InfoFormat("Creating temp credential: {0:S}", tempCred);
            dbUtil.CreateCredential(tempCred, config.StorageAccount, config.Secret);

            try
            {
                #region List databases to backup
                // now that we have the container, start with the backups
                log.DebugFormat("Getting database to backup list");
                var lDBs = dbUtil.ListDatabases(config.BackupType == BackupType.Log);
                log.InfoFormat("{0:N0} databases to backup", lDBs.Count);
                #endregion

                #region Backup to URL
                foreach (var db in lDBs)
                {
                    log.InfoFormat("Performing backup of {0:S}", db);

                    DateTime dt = DateTime.Now;

                    string strBackupName = string.Format("{0:S}_{1:S}_{2:S}.{3:S}",
                        dt.ToString(DATE_FORMAT),
                        dt.ToString(TIME_FORMAT),
                        db,
                        config.BackupType.ToString());

                    log.InfoFormat("Backup will be called {0:S}", strBackupName);

                    string backupUrl = string.Format("{0:S}{1:S}/{2:S}",
                        client.StorageUri.PrimaryUri.ToString(),
                        config.Container,
                        strBackupName);
                    log.DebugFormat("Full backup URI {0:S}", backupUrl);

                    //dbUtil.BackupDatabaseToUrl(db, backupUrl, tempCred);
                }
                #endregion
            }
            finally
            {
                // try to drop credential if possibile
                log.InfoFormat("Dropping temp credential: {0:S}", tempCred);
                dbUtil.DropCredential(tempCred);
            }

            #region Old backups deletion
            if (config.RetentionDays != -1)
            {
                foreach (var blob_uri in container.ListBlobs())
                {
                    CloudBlob cblob = new CloudBlob(blob_uri.Uri);
                    var blob = container.GetBlobReference(cblob.Name);

                    // try to parse to our format
                    log.DebugFormat("Parsing {0:S}", blob.Name);

                    DateTime d;
                    if (!DateTime.TryParseExact(blob.Name.Substring(0, 8), DATE_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out d))
                    {
                        log.InfoFormat("Ingoring blob {0:S} because doesn't seem to have a valid date", blob.Name);
                        continue;
                    }

                    DateTime t;

                    if (!DateTime.TryParseExact(blob.Name.Substring(9, 6), TIME_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out t))
                    {
                        log.InfoFormat("Ingoring blob {0:S} because doesn't seem to have a valid time", blob.Name);
                        continue;
                    }

                    log.DebugFormat("{0:S} and {1:S}", d.ToString(), t.ToString());

                    DateTime dfinal = d.AddHours(t.Hour).AddMinutes(t.Minute).AddSeconds(t.Second);
                    log.InfoFormat("Backup {0:S} was taken {1:S}", blob.Name, dfinal.ToString());

                    var delta = DateTime.Now - dfinal;

                    if (true) //(delta.TotalDays > config.RetentionDays)
                    {
                        log.WarnFormat("Backup {0:S} was taken {1:S} days ago. It will be deleted", blob.Name, delta.TotalDays.ToString());
                        try
                        {
                            blob.Delete();
                        }
                        catch (Exception e)
                        {
                            log.ErrorFormat("Failed to delete blob {0:S}: {1:S}", blob.Name, e.Message);
                        }
                        log.DebugFormat("Backup {0:S} deleted", blob.Name);
                    }
                }
            }
            else
            {
                log.WarnFormat("Backup deletion disabled because retention is set to {0:N0}.", config.RetentionDays.ToString());
            }
            #endregion


            log.InfoFormat("Program completed, exiting with 0");

            return 0;
        }