github.com/whamcloud/lemur@v0.0.0-20190827193804-4655df8a52af/cmd/lhsmd/agent/snapshot.go (about) 1 // Copyright (c) 2018 DDN. All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package agent 6 7 import ( 8 "fmt" 9 "os" 10 "path" 11 "time" 12 13 "github.com/pkg/errors" 14 15 "github.com/intel-hpdd/go-lustre" 16 "github.com/intel-hpdd/go-lustre/fs" 17 "github.com/intel-hpdd/go-lustre/hsm" 18 "github.com/intel-hpdd/go-lustre/llapi" 19 "github.com/intel-hpdd/go-lustre/status" 20 "github.com/intel-hpdd/lemur/cmd/lhsmd/agent/fileid" 21 "github.com/intel-hpdd/logging/alert" 22 "github.com/intel-hpdd/logging/debug" 23 ) 24 25 func createSnapDir(p string) (string, error) { 26 fi, err := os.Lstat(p) 27 if err != nil { 28 return "", errors.Wrap(err, "lstat failed") 29 } 30 snapDir := path.Join(p, ".hsmsnap") 31 err = os.MkdirAll(snapDir, fi.Mode()) 32 if err != nil { 33 return "", errors.Wrap(err, "mkdir all failed") 34 } 35 return snapDir, nil 36 } 37 38 func createStubFile(f string, fi os.FileInfo, archive uint, layout *llapi.DataLayout) error { 39 _, err := hsm.Import(f, archive, fi, layout) 40 if err != nil { 41 os.Remove(f) 42 return errors.Wrapf(err, "%s: import failed", f) 43 } 44 return nil 45 } 46 47 func snapName(fi os.FileInfo) string { 48 return fmt.Sprintf("%s^%s", fi.Name(), fi.ModTime().Format(time.RFC3339)) 49 } 50 51 func createSnapshots(mnt fs.RootDir, archive uint, fileID []byte, names []string) error { 52 var firstPath string 53 first := true 54 for _, p := range names { 55 absPath := mnt.Join(p) 56 snapDir, err := createSnapDir(path.Dir(absPath)) 57 if err != nil { 58 return errors.Wrap(err, "create snapdir failed") 59 } 60 fi, err := os.Lstat(absPath) 61 if err != nil { 62 return errors.Wrap(err, "lstat failed") 63 } 64 f := path.Join(snapDir, snapName(fi)) 65 if first { 66 var layout *llapi.DataLayout 67 layout, err = llapi.FileDataLayout(absPath) 68 if err != nil { 69 alert.Warnf("%s: unable to get layout: %v", f, err) 70 return errors.Wrap(err, "get layout") 71 } 72 debug.Printf("%s: layout: %#v", absPath, layout) 73 err = createStubFile(f, fi, archive, layout) 74 if err != nil { 75 return errors.Wrap(err, "create stub file") 76 } 77 err = fileid.UUID.Set(f, fileID) 78 if err != nil { 79 return errors.Wrapf(err, "%s: set fileid", f) 80 } 81 firstPath = f 82 first = false 83 } else { 84 err = os.Link(firstPath, f) 85 if err != nil { 86 return errors.Wrapf(err, "%s: link to %s failed", f, firstPath) 87 } 88 } 89 90 } 91 return nil 92 } 93 94 func createSnapshot(mnt fs.RootDir, archive uint, fid *lustre.Fid, fileID []byte) error { 95 names, err := status.FidPathnames(mnt, fid) 96 if err != nil { 97 return errors.Wrapf(err, "%s: fidpathname failed", fid) 98 } 99 100 return createSnapshots(mnt, archive, fileID, names) 101 }