mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 12:43:23 +00:00
This tag of hcsshim brings in a couple welcome features/improvements. One being exposing a way to query for hns endpoint statistics (Packets received/sent etc.). This tag also contains some optimizations for querying whether a certain HCN feature is supported, which is a common workflow in kube-proxy on Windows. The first result from querying HCN is now cached so further calls can skip the hcn query as well as the version range parsing that was performed. This also gets rid of some redundant logs that used to hit everytime the version range parsing occurred. The Go-winio dep bump, and all of the ctrd deps are transitive only. Nothing new is needed/intended to be used. Signed-off-by: Daniel Canter <dcanter@microsoft.com>
183 lines
3.9 KiB
Go
183 lines
3.9 KiB
Go
package wclayer
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"syscall"
|
|
|
|
"github.com/Microsoft/go-winio"
|
|
"github.com/Microsoft/hcsshim/internal/hcserror"
|
|
"github.com/Microsoft/hcsshim/internal/oc"
|
|
"github.com/Microsoft/hcsshim/internal/safefile"
|
|
"github.com/Microsoft/hcsshim/internal/winapi"
|
|
"go.opencensus.io/trace"
|
|
)
|
|
|
|
type baseLayerWriter struct {
|
|
ctx context.Context
|
|
s *trace.Span
|
|
|
|
root *os.File
|
|
f *os.File
|
|
bw *winio.BackupFileWriter
|
|
err error
|
|
hasUtilityVM bool
|
|
dirInfo []dirInfo
|
|
}
|
|
|
|
type dirInfo struct {
|
|
path string
|
|
fileInfo winio.FileBasicInfo
|
|
}
|
|
|
|
// reapplyDirectoryTimes reapplies directory modification, creation, etc. times
|
|
// after processing of the directory tree has completed. The times are expected
|
|
// to be ordered such that parent directories come before child directories.
|
|
func reapplyDirectoryTimes(root *os.File, dis []dirInfo) error {
|
|
for i := range dis {
|
|
di := &dis[len(dis)-i-1] // reverse order: process child directories first
|
|
f, err := safefile.OpenRelative(di.path, root, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, winapi.FILE_OPEN, winapi.FILE_DIRECTORY_FILE|syscall.FILE_FLAG_OPEN_REPARSE_POINT)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = winio.SetFileBasicInfo(f, &di.fileInfo)
|
|
f.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *baseLayerWriter) closeCurrentFile() error {
|
|
if w.f != nil {
|
|
err := w.bw.Close()
|
|
err2 := w.f.Close()
|
|
w.f = nil
|
|
w.bw = nil
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err2 != nil {
|
|
return err2
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err error) {
|
|
defer func() {
|
|
if err != nil {
|
|
w.err = err
|
|
}
|
|
}()
|
|
|
|
err = w.closeCurrentFile()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if filepath.ToSlash(name) == `UtilityVM/Files` {
|
|
w.hasUtilityVM = true
|
|
}
|
|
|
|
var f *os.File
|
|
defer func() {
|
|
if f != nil {
|
|
f.Close()
|
|
}
|
|
}()
|
|
|
|
extraFlags := uint32(0)
|
|
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
|
extraFlags |= winapi.FILE_DIRECTORY_FILE
|
|
w.dirInfo = append(w.dirInfo, dirInfo{name, *fileInfo})
|
|
}
|
|
|
|
mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY)
|
|
f, err = safefile.OpenRelative(name, w.root, mode, syscall.FILE_SHARE_READ, winapi.FILE_CREATE, extraFlags)
|
|
if err != nil {
|
|
return hcserror.New(err, "Failed to safefile.OpenRelative", name)
|
|
}
|
|
|
|
err = winio.SetFileBasicInfo(f, fileInfo)
|
|
if err != nil {
|
|
return hcserror.New(err, "Failed to SetFileBasicInfo", name)
|
|
}
|
|
|
|
w.f = f
|
|
w.bw = winio.NewBackupFileWriter(f, true)
|
|
f = nil
|
|
return nil
|
|
}
|
|
|
|
func (w *baseLayerWriter) AddLink(name string, target string) (err error) {
|
|
defer func() {
|
|
if err != nil {
|
|
w.err = err
|
|
}
|
|
}()
|
|
|
|
err = w.closeCurrentFile()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return safefile.LinkRelative(target, w.root, name, w.root)
|
|
}
|
|
|
|
func (w *baseLayerWriter) Remove(name string) error {
|
|
return errors.New("base layer cannot have tombstones")
|
|
}
|
|
|
|
func (w *baseLayerWriter) Write(b []byte) (int, error) {
|
|
n, err := w.bw.Write(b)
|
|
if err != nil {
|
|
w.err = err
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
func (w *baseLayerWriter) Close() (err error) {
|
|
defer w.s.End()
|
|
defer func() { oc.SetSpanStatus(w.s, err) }()
|
|
defer func() {
|
|
w.root.Close()
|
|
w.root = nil
|
|
}()
|
|
|
|
err = w.closeCurrentFile()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if w.err == nil {
|
|
// Restore the file times of all the directories, since they may have
|
|
// been modified by creating child directories.
|
|
err = reapplyDirectoryTimes(w.root, w.dirInfo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = ProcessBaseLayer(w.ctx, w.root.Name())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if w.hasUtilityVM {
|
|
err := safefile.EnsureNotReparsePointRelative("UtilityVM", w.root)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = ProcessUtilityVMImage(w.ctx, filepath.Join(w.root.Name(), "UtilityVM"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return w.err
|
|
}
|