def testRunCmd(self, mock_popen):

        commandService = Command()

        # When no error
        mock_popen.return_value.returncode = 0
        mock_popen.return_value.communicate.return_value = ("output", None)
        result = commandService.runCmd("fake cmd")
        self.assertEqual("output", result)

        # With error
        mock_popen.return_value.returncode = 0
        mock_popen.return_value.communicate.return_value = ("output", "Error")
        self.assertEqual("output", result)

        # With bad return code
        mock_popen.return_value.returncode = 1
        mock_popen.return_value.communicate.return_value = ("output", None)
        self.assertRaises(Exception, commandService.runCmd, "fake cmd")
Exemple #2
0
    def initDuplicity(self, backupPath, backend):
        """
        Permit to init Duplicity with the target
        :param backupPath: the path where dump is stored
        :param backend: the full URL of remote target where to store backup
        :type backupPath: str
        :type backend: str
        """

        if backupPath is None or backupPath == "":
            raise KeyError("backupPath must be provided")
        if backend is None or backend == "":
            raise KeyError("backend must be provided")

        logger.debug("backupPath: %s", backupPath)
        logger.debug("backend: %s", backend)

        commandService = Command()

        result = commandService.runCmd("duplicity --no-encryption %s %s" % (backend, backupPath))
        logger.info(result)
Exemple #3
0
    def runDump(self, listDump):
        """
        Permit to perform dump on each services with Docker command
        :param listDump: The list of service where to perform the dump
        :type listDump: list
        """

        if isinstance(listDump, list) is False:
            raise KeyError("listDump must be a list")

        logger.debug("listDump: %s", listDump)

        commandService = Command()

        for dump in listDump:

            try:
                logger.info("Dumping %s/%s in %s" %
                            (dump['service']['stack']['name'],
                             dump['service']['name'], dump['target_dir']))
                environments = ""
                for env in dump['environments']:
                    environments += " -e '%s'" % env.replace(':', '=')

                if 'entrypoint' in dump:
                    entrypoint = "--entrypoint='%s'" % dump['entrypoint']
                else:
                    entrypoint = ''

                # Check if folder to receive dump exist, else create it
                if os.path.isdir(dump['target_dir']) is False:
                    os.makedirs(dump['target_dir'])
                    logger.debug("Create directory '%s'", dump['target_dir'])
                else:
                    logger.debug("Directory '%s' already exist",
                                 dump['target_dir'])

                commandService.runCmd("docker pull %s" % dump['image'])

                for command in dump['commands']:
                    dockerCmd = "docker run --rm %s -v %s:%s %s %s %s" % (
                        entrypoint, dump['target_dir'], dump['target_dir'],
                        environments, dump['image'], command)
                    commandService.runCmd(dockerCmd)
                logger.info("Dump %s/%s is finished" %
                            (dump['service']['stack']['name'],
                             dump['service']['name']))

            except Exception as e:
                logger.error("Error appear when dump '%s/%s', skip : %s" %
                             (dump['service']['stack']['name'],
                              dump['service']['name'], e.message))
                # Don't beack backup if somethink wrong
                pass
Exemple #4
0
    def dumpRancherDatabase(self, backupPath, listDatabaseSettings):
        """
        Permit to dump Rancher database
        :param backupPath: the backup path where store the database dump
        :param listDatabaseSettings: the database parameters to connect on it
        :type backupPath: basestring
        :type listDatabaseSettings: dict
        """

        if backupPath is None or backupPath == "":
            raise KeyError("backupPath must be provided")
        if isinstance(listDatabaseSettings, dict) is False:
            raise KeyError("listDatabaseSettings must be provided")

        if "type" not in listDatabaseSettings:
            raise KeyError("You must provide the database type")
        if "host" not in listDatabaseSettings:
            raise KeyError("You must provide the database host")
        if "port" not in listDatabaseSettings:
            raise KeyError("You must provide the database port")
        if "user" not in listDatabaseSettings:
            raise KeyError("You must provide the database user")
        if "password" not in listDatabaseSettings:
            raise KeyError("You must provide the database password")
        if "name" not in listDatabaseSettings:
            raise KeyError("You must provide the database name")

        commandService = Command()
        target_dir = "%s/database" % (backupPath)
        image = "mysql:latest"
        logger.info("Dumping the Rancher database '%s' in '%s'",
                    listDatabaseSettings['name'], target_dir)

        if os.path.isdir(target_dir) is False:
            os.makedirs(target_dir)
            logger.debug("Create directory '%s'", target_dir)
        else:
            logger.debug("Directory '%s' already exist", target_dir)

        commandService.runCmd("docker pull %s" % image)
        command = "sh -c 'mysqldump -h %s -P %s -u %s %s > %s/%s.dump'" % (
            listDatabaseSettings['host'], listDatabaseSettings['port'],
            listDatabaseSettings['user'], listDatabaseSettings['name'],
            target_dir, listDatabaseSettings['name'])
        dockerCmd = "docker run --rm -v %s:%s -e 'MYSQL_PWD=%s' %s %s" % (
            target_dir, target_dir, listDatabaseSettings['password'], image,
            command)
        commandService.runCmd(dockerCmd)
        logger.info("Dump Rancher database is finished")
Exemple #5
0
    def runDuplicity(self,
                     backupPath,
                     backend,
                     fullBackupFrequency,
                     fullBackupKeep,
                     incrementalBackupChainKeep,
                     volumeSize,
                     options=None):
        """
        Permit to backup the dump on remote target
        :param backupPath: the path where dump is stored
        :param backend: the full URL of remote target where to store backup
        :param fullBackupFrequency: when run full backup
        :param fullBackupKeep: how many full backup to keep
        :param incrementalBackupChainKeep: how many incremental backup chain to keep
        :param volumeSize: how many size for each volume
        :param options: set some duplicity options
        :type backupPath: str
        :type backend: str
        :type fullBackupFrequency: str
        :type incrementalBackupChainKeep: str
        :type volumeSize: str
        :type options: str
        """

        if backupPath is None or backupPath == "":
            raise KeyError("backupPath must be provided")
        if backend is None or backend == "":
            raise KeyError("backend must be provided")
        if fullBackupFrequency is None or fullBackupFrequency == "":
            raise KeyError("fullBackupFrequency  must be provided")
        if isinstance(fullBackupKeep, int) is False:
            raise KeyError("fullBackupKeep must be provided")
        if isinstance(incrementalBackupChainKeep, int) is False:
            raise KeyError("incrementalBackupChainKeep must be provided")
        if isinstance(volumeSize, int) is False:
            raise KeyError("volumeSize must be provided")
        if options is None:
            options = ""
        if isinstance(options, basestring) is False:
            raise KeyError("Options mus be a None or string")

        logger.debug("backupPath: %s", backupPath)
        logger.debug("backend: %s", backend)
        logger.debug("fullBackupFrequency: %s", fullBackupFrequency)
        logger.debug("fullBackupKeep: %s", fullBackupKeep)
        logger.debug("incrementalBackupChainKeep: %s",
                     incrementalBackupChainKeep)
        logger.debug("volumeSize: %s", volumeSize)
        logger.debug("options: %s", options)

        commandService = Command()

        logger.info("Start backup")
        result = commandService.runCmd(
            "duplicity %s --volsize %s --no-encryption --allow-source-mismatch --full-if-older-than %s %s %s"
            % (options, volumeSize, fullBackupFrequency, backupPath, backend))
        logger.info(result)

        logger.info("Clean old full backup is needed")
        result = commandService.runCmd(
            "duplicity remove-all-but-n-full %s --force --allow-source-mismatch --no-encryption %s"
            % (fullBackupKeep, backend))
        logger.info(result)

        logger.info("Clean old incremental backup if needed")
        result = commandService.runCmd(
            "duplicity remove-all-inc-of-but-n-full %s --force --allow-source-mismatch --no-encryption %s"
            % (incrementalBackupChainKeep, backend))
        logger.info(result)

        logger.info("Cleanup backup")
        result = commandService.runCmd(
            "duplicity  cleanup --force --no-encryption %s" % (backend))
        logger.info(result)