예제 #1
0
func nestedBsonMapGet(m bson.M, arg string, moreArgs ...string) (interface{}, error) {
	strata.Log("Call to nestedBsonMapGet()")
	value, found := m[arg]
	if !found {
		return nil, errors.New("Key not found")
	}
	if len(moreArgs) == 0 {
		return value, nil
	}
	nextNest, ok := value.(bson.M)
	if !ok {
		return nil, errors.New("Nested value is not a bson map")
	}
	return nestedBsonMapGet(nextNest, moreArgs[0], moreArgs[1:]...)
}
예제 #2
0
// PrepareToRestoreSnapshot checks that the necessary directories exist and are not being used
func (r *LocalReplica) PrepareToRestoreSnapshot(replicaID string, targetPath string, s *strata.Snapshot) (string, error) {
	if targetPath == "" {
		targetPath = s.Metadata.Path
	}
	dbpath := targetPath + "/db/"
	syscall.Umask(0)
	if err := os.MkdirAll(dbpath, 0777); err != nil {
		return dbpath, err
	}

	// Check that database is not in use
	strata.Log("Checking that database is not in use")
	lockfile, err := GetDBLock(targetPath)
	if lockfile != nil {
		defer lockfile.Close()
	}
	if err != nil && !os.IsNotExist(err) {
		return dbpath, err
	}

	return dbpath, nil
}
예제 #3
0
// CreateSnapshot is called to trigger snapshot creation on the target source.
// It should run on the host that corresponds to replicaID unless you know what you're doing.
// CreateSnapshot replaces DBPATH/backup/latest with the snapshot that it creates. No other snapshots are kept locally.
// TODO(agf): Have a way to pass in tags
func (r *LocalReplica) CreateSnapshot(replicaID, snapshotID string) (*strata.Snapshot, error) {
	strata.Log("Getting session for CreateSnapshot()")
	session, err := r.sessionGetter.get(r.port, r.username, r.password)
	if err != nil {
		return nil, err
	}
	defer session.Close()
	session.SetMode(mgo.Eventual, false)

	result := bson.M{}

	strata.Log("Getting dbpath")
	// determine dbpath
	cmd := bson.D{{"getCmdLineOpts", 1}}
	if err := session.DB("admin").Run(cmd, &result); err != nil {
		return nil, err
	}
	dbpathInterface, err := nestedBsonMapGet(result, "parsed", "storage", "dbPath")
	if err != nil {
		return nil, err
	}
	dbpath, ok := dbpathInterface.(string)
	if !ok {
		return nil, errors.New("Nested bson map do not end in a string")
	}
	if !strings.HasPrefix(dbpath, "/") {
		return nil, fmt.Errorf(
			"Found relative database path %s. Database path must be absolute.", dbpath)
	}
	strata.Log("Got dbpath: " + dbpath)

	strata.Log("Preparing backup directory")
	// The backup's parent directory should exist
	syscall.Umask(0)
	if err := os.MkdirAll(getParentOfBackupPath(dbpath, replicaID), 0777); err != nil {
		return nil, err
	}
	// The actual backup directory shouldn't exist yet
	backupPath := getBackupPath(dbpath, replicaID)
	if err := os.RemoveAll(backupPath); err != nil {
		return nil, err
	}

	strata.Log("Getting new snapshot metadata")
	metadata := strata.SnapshotMetadata{
		ID:        snapshotID,
		ReplicaID: replicaID,
		Time:      time.Now(),
		Path:      dbpath}

	cmd = bson.D{{"setParameter", 1}, {"rocksdbBackup", backupPath}}
	strata.Log("Performing command for local backup")
	if err := session.DB("admin").Run(cmd, &result); err != nil {
		strata.Log("Error performing local backup....")
		return nil, err
	}

	strata.Log("Building metadata.Files")
	// Build metadata.Files
	files, err := ioutil.ReadDir(backupPath)
	if err != nil {
		return nil, err
	}
	for _, file := range files {
		fullpath := backupPath + "/" + file.Name()
		csum, err := partialChecksum(fullpath)
		if err != nil {
			return nil, err
		}
		metadata.Files = append(
			metadata.Files,
			strata.File{
				Name:     file.Name(),
				Size:     file.Size(),
				Checksum: csum})
	}
	strata.Log("Finished building metadata.Files.")

	return r.GetSnapshot(metadata)
}