diff --git a/graphql/admin/endpoints_ee.go b/graphql/admin/endpoints_ee.go index 803e5f24921..9637ce4b7fc 100644 --- a/graphql/admin/endpoints_ee.go +++ b/graphql/admin/endpoints_ee.go @@ -66,13 +66,16 @@ const adminTypes = ` backupId: String """ - Number of backups within the backup series to be restored. Backups outside this range - will be ignored. If the value is zero or missing, the entire series will be restored. + If backupNum is 0 or missing, the entire series will be restored i.e all the incremental + backups available in the series as well as the full backup will be restored. If backupNum is + non-zero, we restore all the backups in the series that have backupNum smaller or equal to + the backupNum provided here. Backups that have backupNum higher than this will be ignored. + In simple words, all the backups with backupNum of backup <= backupNum will be restored. """ backupNum: Int """ - All the backups with num >= incrementalFrom will be restored. + All the backups with backupNum >= incrementalFrom will be restored. """ incrementalFrom: Int diff --git a/graphql/e2e/multi_tenancy/multi_tenancy_test.go b/graphql/e2e/multi_tenancy/multi_tenancy_test.go index b06dfe22737..b4f22530fa5 100644 --- a/graphql/e2e/multi_tenancy/multi_tenancy_test.go +++ b/graphql/e2e/multi_tenancy/multi_tenancy_test.go @@ -55,8 +55,6 @@ var ( // Whenever schema is updated in a dgraph alpha for one group for any namespace, // that update should also be propagated to alpha nodes in other groups. func TestSchemaSubscribe(t *testing.T) { - // TODO: need to fix the race condition for license propagation, the sleep helps propagate the EE license correctly - time.Sleep(time.Second * 10) header := http.Header{} header.Set(accessJwtHeader, testutil.GrootHttpLogin(groupOneAdminServer).AccessJwt) schema := ` diff --git a/worker/backup_manifest.go b/worker/backup_manifest.go index a846e6720da..3d5130827a9 100644 --- a/worker/backup_manifest.go +++ b/worker/backup_manifest.go @@ -21,6 +21,7 @@ import ( "sort" "strings" + "github.com/golang/glog" "github.com/pkg/errors" "github.com/dgraph-io/dgraph/protos/pb" @@ -56,33 +57,28 @@ func verifyManifests(manifests []*Manifest) error { return nil } -func getManifestsToRestore( - h UriHandler, uri *url.URL, req *pb.RestoreRequest) ([]*Manifest, error) { +func getManifestsToRestore(h UriHandler, uri *url.URL, req *pb.RestoreRequest) ([]*Manifest, error) { manifest, err := GetManifest(h, uri) if err != nil { - return manifest.Manifests, err + return nil, err } - return getFilteredManifests(h, manifest.Manifests, req) -} - -func getFilteredManifests(h UriHandler, manifests []*Manifest, - req *pb.RestoreRequest) ([]*Manifest, error) { + manifests := manifest.Manifests // filter takes a list of manifests and returns the list of manifests // that should be considered during a restore. - filter := func(manifests []*Manifest, backupId string) ([]*Manifest, error) { + filter := func(mfs []*Manifest, backupId string) ([]*Manifest, error) { // Go through the files in reverse order and stop when the latest full backup is found. var out []*Manifest - for i := len(manifests) - 1; i >= 0; i-- { + for i := len(mfs) - 1; i >= 0; i-- { // If backupId is not empty, skip all the manifests that do not match the given - // backupId. If it's empty, do not skip any manifests as the default behavior is + // backupId. If it's empty, do not skip any mfs manifests the default behavior is // to restore the latest series of backups. - if len(backupId) > 0 && manifests[i].BackupId != backupId { + if len(backupId) > 0 && mfs[i].BackupId != backupId { continue } - out = append(out, manifests[i]) - if manifests[i].Type == "full" { + out = append(out, mfs[i]) + if mfs[i].Type == "full" { break } } @@ -100,6 +96,8 @@ func getFilteredManifests(h UriHandler, manifests []*Manifest, for g := range m.Groups { path := filepath.Join(m.Path, backupName(m.ValidReadTs(), g)) if !h.FileExists(path) { + glog.Warningf("backup file [%v] missing for backupId [%v] and backupNum [%v]", + path, m.BackupId, m.BackupNum) missingFiles = true break } @@ -108,7 +106,8 @@ func getFilteredManifests(h UriHandler, manifests []*Manifest, validManifests = append(validManifests, m) } } - manifests, err := filter(validManifests, req.BackupId) + + manifests, err = filter(validManifests, req.BackupId) if err != nil { return nil, err } diff --git a/worker/multi_tenancy_ee.go b/worker/multi_tenancy_ee.go index f7e705008a1..81bc6850d1f 100644 --- a/worker/multi_tenancy_ee.go +++ b/worker/multi_tenancy_ee.go @@ -26,8 +26,7 @@ import ( "github.com/dgraph-io/dgraph/x" ) -func (w *grpcWorker) DeleteNamespace(ctx context.Context, - req *pb.DeleteNsRequest) (*pb.Status, error) { +func (w *grpcWorker) DeleteNamespace(ctx context.Context, req *pb.DeleteNsRequest) (*pb.Status, error) { var emptyRes pb.Status if !groups().ServesGroup(req.GroupId) { return &emptyRes, errors.Errorf("The server doesn't serve group id: %v", req.GroupId) diff --git a/worker/online_restore.go b/worker/online_restore.go index c50dbf56edf..44fbfaa1585 100644 --- a/worker/online_restore.go +++ b/worker/online_restore.go @@ -46,9 +46,7 @@ const ( // verifyRequest verifies that the manifest satisfies the requirements to process the given // restore request. -func verifyRequest(h UriHandler, uri *url.URL, req *pb.RestoreRequest, - currentGroups []uint32) error { - +func verifyRequest(h UriHandler, uri *url.URL, req *pb.RestoreRequest, currentGroups []uint32) error { manifests, err := getManifestsToRestore(h, uri, req) if err != nil { return errors.Wrapf(err, "while retrieving manifests") @@ -287,20 +285,31 @@ func handleRestoreProposal(ctx context.Context, req *pb.RestoreRequest, pidx uin if err != nil { return errors.Wrapf(err, "cannot get backup manifests") } + + // filter manifests that needs to be restored + mfsToRestore := manifests[:0] + for _, m := range manifests { + if (req.BackupNum == 0 || m.BackupNum <= req.BackupNum) && + (req.IncrementalFrom == 0 || m.BackupNum >= req.IncrementalFrom) { + + mfsToRestore = append(mfsToRestore, m) + } + } + manifests = mfsToRestore + if len(manifests) == 0 { return errors.Errorf("no backup manifests found at location %s", req.Location) } lastManifest := manifests[0] restorePreds, ok := lastManifest.Groups[req.GroupId] - if !ok { - return errors.Errorf("backup manifest does not contain information for group ID %d", - req.GroupId) + return errors.Errorf("backup manifest does not contain information for group ID %d", req.GroupId) } + for _, pred := range restorePreds { - // Force the tablet to be moved to this group, even if it's currently being served - // by another group. + // Force the tablet to be moved to this group, even + // if it's currently being served by another group. tablet, err := groups().ForceTablet(pred) if err != nil { return errors.Wrapf(err, "cannot create tablet for restored predicate %s", pred)