예제 #1
0
        public void Restore(BitnamiRedmineStack stack, DatabaseConfiguration configuration, string path)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            try
            {
                if (!File.Exists(path))
                {
                    throw new FileNotFoundException("インポートする sql ファイルが存在しません。", path);
                }

                var connectionString = CreateConnectionString(configuration);

                this._LogService.Info("Create MySqlConnection");
                using (var con = new MySqlConnection(connectionString))
                {
                    var text   = File.ReadAllText(path);
                    var script = new MySqlScript(con, text);

                    this._LogService.Info("Execute MySqlScript");
                    var result = script.Execute();

                    this._LogService.Info($"MySqlScript,Execute returns {result}");
                }
            }
            catch (Exception e)
            {
                this._LogService.Error(e.Message);
                throw;
            }
        }
        public IEnumerable <BitnamiRedmineStack> GetBitnamiRedmineStacks()
        {
            var stacks = new List <BitnamiRedmineStack>();

            try
            {
                var registryKeys = new[]
                {
                    @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
                    @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
                };

                foreach (var registryKey in registryKeys)
                {
                    using (var key = Registry.LocalMachine.OpenSubKey(registryKey))
                    {
                        if (key == null)
                        {
                            continue;
                        }

                        foreach (var subkeyName in key.GetSubKeyNames())
                        {
                            using (var subkey = key.OpenSubKey(subkeyName))
                            {
                                var value = subkey?.GetValue("DisplayName") as string;
                                if (value == null)
                                {
                                    continue;
                                }

                                if (!value.Equals("Bitnami Redmine Stack", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    continue;
                                }

                                var installLocation = subkey.GetValue("InstallLocation") as string;

                                // Include '"' from 4.0.0
                                installLocation = installLocation?.Trim('"');

                                var displayVersion = subkey.GetValue("DisplayVersion") as string;

                                var stack = new BitnamiRedmineStack(installLocation, displayVersion);
                                stacks.Add(stack);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                this._LogService.Error(e.Message);
                throw;
            }

            return(stacks);
        }
예제 #3
0
        public IEnumerable <ServiceStatus> GetServiceDisplayNames(BitnamiRedmineStack stack, ServiceConfiguration configuration)
        {
            var statusList = new List <ServiceStatus>();

            try
            {
                var services = new[]
                {
                    new { Path = Path.Combine(stack.InstallLocation, ApachePath), Condition = configuration.Apache },
                    new { Path = Path.Combine(stack.InstallLocation, MySqlPath), Condition = configuration.MySql },
                    new { Path = Path.Combine(stack.InstallLocation, RedminePath), Condition = configuration.Redmine },
                    new { Path = Path.Combine(stack.InstallLocation, SubversionPath), Condition = configuration.Subversion }
                };

                const string registryKey = @"SYSTEM\CurrentControlSet\services";
                using (var key = Registry.LocalMachine.OpenSubKey(registryKey))
                {
                    if (key == null)
                    {
                        throw new KeyNotFoundException($"サブキー 'HKEY_LOCAL_MACHINE\\{registryKey}' が存在しません。");
                    }

                    var subKeyNames = key.GetSubKeyNames();
                    foreach (var subkeyName in subKeyNames)
                    {
                        using (var subkey = key.OpenSubKey(subkeyName))
                        {
                            var imagePath = subkey?.GetValue("ImagePath") as string;
                            if (string.IsNullOrWhiteSpace(imagePath))
                            {
                                continue;
                            }

                            var displayName = subkey.GetValue("DisplayName") as string;
                            if (string.IsNullOrWhiteSpace(displayName))
                            {
                                continue;
                            }

                            // 時々、8.3 形式の短いパスがある
                            // さらに、引数を含むパスがいるため、分解してから長い形式のパスに変換する
                            // が、長い形式のパスを System.IO.Path.GetFullPath で
                            // 変関すると例外を投げるので、Win32 API の GetLongPathName を使う
                            try
                            {
                                var splitArgs = InteropHelper.SplitArgs(imagePath);
                                if (splitArgs == null || splitArgs.Length == 0)
                                {
                                    continue;
                                }

                                imagePath = InteropHelper.GetLongPathName(splitArgs[0]);
                            }
                            catch
                            { }

                            if (imagePath == null)
                            {
                                continue;
                            }

                            foreach (var service in services)
                            {
                                if (!service.Condition)
                                {
                                    continue;
                                }

                                if (imagePath.Contains(service.Path))
                                {
                                    var startupType = GetStartupType(subkey);
                                    var status      = new ServiceStatus(this, subkeyName, startupType);
                                    statusList.Add(status);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                this._LogService.Error(e.Message);
                throw;
            }

            return(statusList);
        }
예제 #4
0
        public void Restore(BitnamiRedmineStack stack, BackupConfiguration configuration, string path, IProgress <ProgressReportsModel> progress = null)
        {
            if (!Directory.Exists(path))
            {
                throw new DirectoryNotFoundException($"{path} は存在しません。");
            }

            var databaseName     = Resources.Word_Database;
            var pluginName       = Resources.Word_Plugin;
            var themeName        = Resources.Word_Theme;
            var attachedFileName = Resources.Word_AttachedFile;

            var report = new ProgressReportsModel(this._DispatcherService, new[]
            {
                new ProgressItemModel {
                    Key = databaseName, Progress = ProgressState.NotStart
                },
                new ProgressItemModel {
                    Key = pluginName, Progress = ProgressState.NotStart
                },
                new ProgressItemModel {
                    Key = themeName, Progress = ProgressState.NotStart
                },
                new ProgressItemModel {
                    Key = attachedFileName, Progress = ProgressState.NotStart
                },
            });

            // データベースの復元
            if (configuration.Database)
            {
                report.UpdateProgress(databaseName, ProgressState.InProgress);
                progress?.Report(report);

                var databaseConfigurations = this._DatabaseConfigurationService.GetDatabaseConfiguration(stack).ToArray();
                foreach (var databaseConfiguration in databaseConfigurations)
                {
                    var sqlFileName = $"{databaseConfiguration.Mode}.sql";
                    var sqlFilePath = Path.Combine(path, sqlFileName);
                    if (!File.Exists(sqlFilePath))
                    {
                        continue;
                    }

                    this._DatabaseService.Restore(stack, databaseConfiguration, sqlFilePath);
                }

                report.UpdateProgress(databaseName, ProgressState.Complete);
                progress?.Report(report);
                report.AddErrorMessage(databaseName, Resources.Msg_RestoreComplete);
            }
            else
            {
                report.UpdateProgress(databaseName, ProgressState.NotRequire);
                report.AddErrorMessage(databaseName, Resources.Msg_RestoreSkip);

                this._LogService.Info("Database is skipped");
            }

            // プラグイン、テーマ、添付ファイルの復元
            var rules = new[]
            {
                new
                {
                    Condition   = configuration.Plugins,
                    Target      = BackupConfiguration.PluginsPath,
                    Source      = PluginsDirectoryName,
                    CheckAction = new Action <ProgressState>(state =>
                    {
                        report.UpdateProgress(pluginName, state);
                        progress?.Report(report);

                        switch (state)
                        {
                        case ProgressState.Complete:
                            report.AddErrorMessage(databaseName, Resources.Msg_RestoreComplete);
                            break;

                        case ProgressState.NotRequire:
                            report.AddErrorMessage(databaseName, Resources.Msg_RestoreSkip);
                            break;

                        case ProgressState.Failed:
                            report.AddErrorMessage(databaseName, Resources.Msg_RestoreFailed);
                            break;
                        }
                    })
                },
                new
                {
                    Condition   = configuration.Themes,
                    Target      = BackupConfiguration.ThemesePath,
                    Source      = ThemeseDirectoryName,
                    CheckAction = new Action <ProgressState>(state =>
                    {
                        report.UpdateProgress(themeName, state);
                        progress?.Report(report);

                        switch (state)
                        {
                        case ProgressState.Complete:
                            report.AddErrorMessage(databaseName, Resources.Msg_RestoreComplete);
                            break;

                        case ProgressState.NotRequire:
                            report.AddErrorMessage(databaseName, Resources.Msg_RestoreSkip);
                            break;

                        case ProgressState.Failed:
                            report.AddErrorMessage(databaseName, Resources.Msg_RestoreFailed);
                            break;
                        }
                    })
                },
                new
                {
                    Condition   = configuration.Files,
                    Target      = BackupConfiguration.FilesPath,
                    Source      = FilesDirectoryName,
                    CheckAction = new Action <ProgressState>(state =>
                    {
                        report.UpdateProgress(attachedFileName, state);
                        progress?.Report(report);

                        switch (state)
                        {
                        case ProgressState.Complete:
                            report.AddErrorMessage(databaseName, Resources.Msg_RestoreComplete);
                            break;

                        case ProgressState.NotRequire:
                            report.AddErrorMessage(databaseName, Resources.Msg_RestoreSkip);
                            break;

                        case ProgressState.Failed:
                            report.AddErrorMessage(databaseName, Resources.Msg_RestoreFailed);
                            break;
                        }
                    })
                }
            };

            foreach (var rule in rules)
            {
                if (!rule.Condition)
                {
                    rule.CheckAction(ProgressState.NotRequire);
                    continue;
                }

                var sourceDir = Path.Combine(path, rule.Source);
                var targetDir = Path.Combine(stack.InstallLocation, rule.Target);
                var condition = Directory.Exists(sourceDir);
                if (!condition)
                {
                    rule.CheckAction(ProgressState.Failed);
                    continue;
                }

                rule.CheckAction(ProgressState.InProgress);

                this.CopyDirectory(sourceDir, targetDir);

                rule.CheckAction(ProgressState.Complete);
            }
        }
예제 #5
0
        public BackupConfiguration CheckRestoreFolder(BitnamiRedmineStack stack, string path)
        {
            var configuration = new BackupConfiguration();

            // データベース
            var databaseConfigurations = this._DatabaseConfigurationService.GetDatabaseConfiguration(stack).ToArray();

            foreach (var databaseConfiguration in databaseConfigurations)
            {
                var sqlFileName = string.Format("{0}.sql", databaseConfiguration.Mode);
                var sqlFilePath = Path.Combine(path, sqlFileName);
                if (!File.Exists(sqlFilePath))
                {
                    continue;
                }

                configuration.Database = true;
                break;
            }

            // プラグイン、テーマ、添付ファイル
            var rules = new[]
            {
                new
                {
                    Target      = BackupConfiguration.PluginsPath,
                    Source      = PluginsDirectoryName,
                    CheckAction = new Action(() =>
                    {
                        configuration.Plugins = true;
                    })
                },
                new
                {
                    Target      = BackupConfiguration.ThemesePath,
                    Source      = ThemeseDirectoryName,
                    CheckAction = new Action(() =>
                    {
                        configuration.Themes = true;
                    })
                },
                new
                {
                    Target      = BackupConfiguration.FilesPath,
                    Source      = FilesDirectoryName,
                    CheckAction = new Action(() =>
                    {
                        configuration.Files = true;
                    })
                }
            };

            foreach (var rule in rules)
            {
                var sourceDir = Path.Combine(path, rule.Source);
                var condition = Directory.Exists(sourceDir);
                if (!condition)
                {
                    continue;
                }

                rule.CheckAction();
            }

            return(configuration);
        }
예제 #6
0
        public void Backup(BitnamiRedmineStack stack, DatabaseConfiguration configuration, string path)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            try
            {
                var apppath = CreateMySqlDumpLocation(stack);
                if (!File.Exists(apppath))
                {
                    throw new FileNotFoundException("mysqldump.exe が存在しません。", apppath);
                }

                // サポートしている文字コードは
                // mysql> show character set; を実行
                Encoding encoding;
                switch (configuration.Encoding)
                {
                case "utf8":
                    encoding = Encoding.UTF8;
                    break;

                default:
                    throw new NotSupportedException($"{configuration.Encoding} はサポートしていません。");
                }

                const string format =
                    "--default-character-set={0} --user={1} --password={2} --port={3} --databases {4}";
                var arguments = string.Format(
                    format,
                    configuration.Encoding,
                    configuration.Username,
                    configuration.Password,
                    configuration.Port,
                    configuration.Name);

                var psInfo = new ProcessStartInfo();
                psInfo.FileName               = apppath;
                psInfo.Arguments              = arguments;
                psInfo.CreateNoWindow         = true;
                psInfo.UseShellExecute        = false;
                psInfo.RedirectStandardOutput = true;
                psInfo.StandardOutputEncoding = encoding;

                this._LogService.Info("Create mysqldump.exe process");
                using (var process = Process.Start(psInfo))
                {
                    var contents = process.StandardOutput.ReadToEnd();

                    this._LogService.Info("Start mysqldump.exe");
                    process.WaitForExit();

                    this._LogService.Info("End mysqldump.exe");
                    File.WriteAllText(path, contents, encoding);
                }
            }
            catch (Exception e)
            {
                this._LogService.Error(e.Message);
                throw;
            }
        }
예제 #7
0
 private static string CreateMySqlLocation(BitnamiRedmineStack stack)
 {
     return(Path.Combine(stack.InstallLocation, MySqlPath));
 }
        public IEnumerable <DatabaseConfiguration> GetDatabaseConfiguration(BitnamiRedmineStack info)
        {
            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }

            try
            {
                const string databaseYmlPath = @"apps\redmine\htdocs\config\database.yml";
                var          path            = Path.Combine(info.InstallLocation, databaseYmlPath);
                if (!File.Exists(path))
                {
                    throw new FileNotFoundException("database.yml が存在しません。", path);
                }

                object[] deserialized;

                var serializer = new YamlSerializer();
                using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    deserialized = serializer.Deserialize(fs);
                }

                var configurations = new List <DatabaseConfiguration>();
                foreach (var obj in deserialized)
                {
                    var dictionary = obj as Dictionary <object, object>;
                    if (dictionary == null)
                    {
                        continue;
                    }

                    // ポート番号は 1 つしか存在しない
                    var port = 0;
                    foreach (var values in (from kvp in dictionary
                                            let mode = kvp.Key as string
                                                       where mode != null
                                                       select kvp.Value).OfType <Dictionary <object, object> >().Where(values => values.ContainsKey("port")))
                    {
                        port = (int)values["port"];
                    }

                    configurations.AddRange(from kvp in dictionary let mode = kvp.Key as string
                                                                              where mode != null let values = kvp.Value as Dictionary <object, object>
                                                                                                              where values != null
                                                                                                              let database = values["database"] as string
                                                                                                                             let username = values["username"] as string
                                                                                                                                            let password = values["password"] as string
                                                                                                                                                           let encoding                       = values["encoding"] as string
                                                                                                                                                                                     let host = values["host"] as string
                                                                                                                                                                                                select new DatabaseConfiguration(mode, database, host, username, password, encoding, port));
                }

                return(configurations);
            }
            catch (Exception e)
            {
                this._LogService.Error(e.Message);
                throw;
            }
        }