// MetastoreBackup returns a snapshot of the meta store. func (c *Client) MetastoreBackup() (*meta.Data, error) { req := &Request{ Type: RequestMetastoreBackup, } b, err := c.doRequest(req) if err != nil { return nil, err } // Check the magic. magic := binary.BigEndian.Uint64(b[:8]) if magic != BackupMagicHeader { return nil, errors.New("invalid metadata received") } i := 8 // Size of the meta store bytes. length := int(binary.BigEndian.Uint64(b[i : i+8])) i += 8 metaBytes := b[i : i+length] i += int(length) // Unpack meta data. var data meta.Data if err := data.UnmarshalBinary(metaBytes); err != nil { return nil, fmt.Errorf("unmarshal: %s", err) } return &data, nil }
// unpackMeta reads the metadata from the backup directory and initializes a raft // cluster and replaces the root metadata. func (cmd *Command) unpackMeta() error { // find the meta file metaFiles, err := filepath.Glob(filepath.Join(cmd.backupFilesPath, backup.Metafile+".*")) if err != nil { return err } if len(metaFiles) == 0 { return fmt.Errorf("no metastore backups in %s", cmd.backupFilesPath) } latest := metaFiles[len(metaFiles)-1] fmt.Fprintf(cmd.Stdout, "Using metastore snapshot: %v\n", latest) // Read the metastore backup f, err := os.Open(latest) if err != nil { return err } var buf bytes.Buffer if _, err := io.Copy(&buf, f); err != nil { return fmt.Errorf("copy: %s", err) } b := buf.Bytes() var i int // Make sure the file is actually a meta store backup file magic := binary.BigEndian.Uint64(b[:8]) if magic != snapshotter.BackupMagicHeader { return fmt.Errorf("invalid metadata file") } i += 8 // Size of the meta store bytes length := int(binary.BigEndian.Uint64(b[i : i+8])) i += 8 metaBytes := b[i : i+length] i += int(length) // Size of the node.json bytes length = int(binary.BigEndian.Uint64(b[i : i+8])) i += 8 nodeBytes := b[i:] // Unpack into metadata. var data meta.Data if err := data.UnmarshalBinary(metaBytes); err != nil { return fmt.Errorf("unmarshal: %s", err) } // Copy meta config and remove peers so it starts in single mode. c := cmd.MetaConfig c.Dir = cmd.metadir // Create the meta dir if os.MkdirAll(c.Dir, 0700); err != nil { return err } // Write node.json back to meta dir if err := ioutil.WriteFile(filepath.Join(c.Dir, "node.json"), nodeBytes, 0655); err != nil { return err } client := meta.NewClient(c) client.SetLogger(log.New(ioutil.Discard, "", 0)) if err := client.Open(); err != nil { return err } defer client.Close() // Force set the full metadata. if err := client.SetData(&data); err != nil { return fmt.Errorf("set data: %s", err) } // remove the raft.db file if it exists err = os.Remove(filepath.Join(cmd.metadir, "raft.db")) if err != nil { if os.IsNotExist(err) { return nil } return err } // remove the node.json file if it exists err = os.Remove(filepath.Join(cmd.metadir, "node.json")) if err != nil { if os.IsNotExist(err) { return nil } return err } return nil }