github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/ee/backup/run.go (about) 1 // +build !oss 2 3 /* 4 * Copyright 2018 Dgraph Labs, Inc. and Contributors 5 * 6 * Licensed under the Dgraph Community License (the "License"); you 7 * may not use this file except in compliance with the License. You 8 * may obtain a copy of the License at 9 * 10 * https://github.com/dgraph-io/dgraph/blob/master/licenses/DCL.txt 11 */ 12 13 package backup 14 15 import ( 16 "context" 17 "fmt" 18 "os" 19 "time" 20 21 "github.com/dgraph-io/dgraph/protos/pb" 22 "github.com/dgraph-io/dgraph/x" 23 "github.com/pkg/errors" 24 "github.com/spf13/cobra" 25 "google.golang.org/grpc" 26 ) 27 28 // Restore is the sub-command used to restore a backup. 29 var Restore x.SubCommand 30 31 // LsBackup is the sub-command used to list the backups in a folder. 32 var LsBackup x.SubCommand 33 34 var opt struct { 35 backupId, location, pdir, zero string 36 } 37 38 func init() { 39 initRestore() 40 initBackupLs() 41 } 42 43 func initRestore() { 44 Restore.Cmd = &cobra.Command{ 45 Use: "restore", 46 Short: "Run Dgraph (EE) Restore backup", 47 Long: ` 48 Restore loads objects created with the backup feature in Dgraph Enterprise Edition (EE). 49 50 Backups are originated from HTTP at /admin/backup, then can be restored using CLI restore 51 command. Restore is intended to be used with new Dgraph clusters in offline state. 52 53 The --location flag indicates a source URI with Dgraph backup objects. This URI supports all 54 the schemes used for backup. 55 56 Source URI formats: 57 [scheme]://[host]/[path]?[args] 58 [scheme]:///[path]?[args] 59 /[path]?[args] (only for local or NFS) 60 61 Source URI parts: 62 scheme - service handler, one of: "s3", "minio", "file" 63 host - remote address. ex: "dgraph.s3.amazonaws.com" 64 path - directory, bucket or container at target. ex: "/dgraph/backups/" 65 args - specific arguments that are ok to appear in logs. 66 67 The --posting flag sets the posting list parent dir to store the loaded backup files. 68 69 Using the --zero flag will use a Dgraph Zero address to update the start timestamp using 70 the restored version. Otherwise, the timestamp must be manually updated through Zero's HTTP 71 'assign' command. 72 73 Dgraph backup creates a unique backup object for each node group, and restore will create 74 a posting directory 'p' matching the backup group ID. Such that a backup file 75 named '.../r32-g2.backup' will be loaded to posting dir 'p2'. 76 77 Usage examples: 78 79 # Restore from local dir or NFS mount: 80 $ dgraph restore -p . -l /var/backups/dgraph 81 82 # Restore from S3: 83 $ dgraph restore -p /var/db/dgraph -l s3://s3.us-west-2.amazonaws.com/srfrog/dgraph 84 85 # Restore from dir and update Ts: 86 $ dgraph restore -p . -l /var/backups/dgraph -z localhost:5080 87 88 `, 89 Args: cobra.NoArgs, 90 Run: func(cmd *cobra.Command, args []string) { 91 defer x.StartProfile(Restore.Conf).Stop() 92 if err := runRestoreCmd(); err != nil { 93 fmt.Fprintln(os.Stderr, err) 94 os.Exit(1) 95 } 96 }, 97 } 98 99 flag := Restore.Cmd.Flags() 100 flag.StringVarP(&opt.location, "location", "l", "", 101 "Sets the source location URI (required).") 102 flag.StringVarP(&opt.pdir, "postings", "p", "", 103 "Directory where posting lists are stored (required).") 104 flag.StringVarP(&opt.zero, "zero", "z", "", "gRPC address for Dgraph zero. ex: localhost:5080") 105 flag.StringVarP(&opt.backupId, "backup_id", "", "", "The ID of the backup series to "+ 106 "restore. If empty, it will restore the latest series.") 107 _ = Restore.Cmd.MarkFlagRequired("postings") 108 _ = Restore.Cmd.MarkFlagRequired("location") 109 } 110 111 func initBackupLs() { 112 LsBackup.Cmd = &cobra.Command{ 113 Use: "lsbackup", 114 Short: "List info on backups in given location", 115 Long: ` 116 lsbackup looks at a location where backups are stored and prints information about them. 117 118 Backups are originated from HTTP at /admin/backup, then can be restored using CLI restore 119 command. Restore is intended to be used with new Dgraph clusters in offline state. 120 121 The --location flag indicates a source URI with Dgraph backup objects. This URI supports all 122 the schemes used for backup. 123 124 Source URI formats: 125 [scheme]://[host]/[path]?[args] 126 [scheme]:///[path]?[args] 127 /[path]?[args] (only for local or NFS) 128 129 Source URI parts: 130 scheme - service handler, one of: "s3", "minio", "file" 131 host - remote address. ex: "dgraph.s3.amazonaws.com" 132 path - directory, bucket or container at target. ex: "/dgraph/backups/" 133 args - specific arguments that are ok to appear in logs. 134 135 Dgraph backup creates a unique backup object for each node group, and restore will create 136 a posting directory 'p' matching the backup group ID. Such that a backup file 137 named '.../r32-g2.backup' will be loaded to posting dir 'p2'. 138 139 Usage examples: 140 141 # Run using location in S3: 142 $ dgraph lsbackup -l s3://s3.us-west-2.amazonaws.com/srfrog/dgraph 143 `, 144 Args: cobra.NoArgs, 145 Run: func(cmd *cobra.Command, args []string) { 146 defer x.StartProfile(Restore.Conf).Stop() 147 if err := runLsbackupCmd(); err != nil { 148 fmt.Fprintln(os.Stderr, err) 149 os.Exit(1) 150 } 151 }, 152 } 153 154 flag := LsBackup.Cmd.Flags() 155 flag.StringVarP(&opt.location, "location", "l", "", 156 "Sets the source location URI (required).") 157 _ = LsBackup.Cmd.MarkFlagRequired("location") 158 } 159 160 func runRestoreCmd() error { 161 var ( 162 start time.Time 163 zc pb.ZeroClient 164 ) 165 166 fmt.Println("Restoring backups from:", opt.location) 167 fmt.Println("Writing postings to:", opt.pdir) 168 169 // TODO: Remove this dependency on Zero. It complicates restore for the end 170 // user. 171 if opt.zero != "" { 172 fmt.Println("Updating Zero timestamp at:", opt.zero) 173 174 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 175 defer cancel() 176 177 zero, err := grpc.DialContext(ctx, opt.zero, 178 grpc.WithBlock(), 179 grpc.WithInsecure()) 180 if err != nil { 181 return errors.Wrapf(err, "Unable to connect to %s", opt.zero) 182 } 183 zc = pb.NewZeroClient(zero) 184 } 185 186 start = time.Now() 187 version, err := RunRestore(opt.pdir, opt.location, opt.backupId) 188 if err != nil { 189 return err 190 } 191 if version == 0 { 192 return errors.Errorf("Failed to obtain a restore version") 193 } 194 fmt.Printf("Restore version: %d\n", version) 195 196 if zc != nil { 197 ctx, cancel := context.WithTimeout(context.Background(), time.Minute) 198 defer cancel() 199 200 _, err = zc.Timestamps(ctx, &pb.Num{Val: version}) 201 if err != nil { 202 fmt.Printf("Failed to assign timestamp %d in Zero: %v", version, err) 203 } 204 } 205 206 fmt.Printf("Restore: Time elapsed: %s\n", time.Since(start).Round(time.Second)) 207 return nil 208 } 209 210 func runLsbackupCmd() error { 211 fmt.Println("Listing backups from:", opt.location) 212 manifests, err := ListManifests(opt.location) 213 if err != nil { 214 return errors.Wrapf(err, "while listing manifests") 215 } 216 217 fmt.Printf("Name\tSince\tGroups\n") 218 for path, manifest := range manifests { 219 fmt.Printf("%v\t%v\t%v\n", path, manifest.Since, manifest.Groups) 220 } 221 222 return nil 223 }