Add cimfs differ and snapshotter

Details about CimFs project are discussed in #8346

Signed-off-by: Amit Barve <ambarve@microsoft.com>
This commit is contained in:
Amit Barve
2023-09-14 16:18:13 -07:00
parent 643fa70a7d
commit daa1ea522b
104 changed files with 3848 additions and 2996 deletions

View File

@@ -6,11 +6,12 @@ import (
"errors"
"fmt"
"github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
"github.com/Microsoft/hcsshim/internal/hcs"
"github.com/Microsoft/hcsshim/internal/hcserror"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
)
var (
@@ -63,8 +64,8 @@ func (e *HcnError) Error() string {
}
func CheckErrorWithCode(err error, code ErrorCode) bool {
hcnError, ok := err.(*HcnError)
if ok {
var hcnError *HcnError
if errors.As(err, &hcnError) {
return hcnError.code == code
}
return false
@@ -81,7 +82,7 @@ func IsPortAlreadyExistsError(err error) bool {
func new(hr error, title string, rest string) error {
err := &HcnError{}
hcsError := hcserror.New(hr, title, rest)
err.HcsError = hcsError.(*hcserror.HcsError)
err.HcsError = hcsError.(*hcserror.HcsError) //nolint:errorlint
err.code = ErrorCode(hcserror.Win32FromError(hr))
return err
}
@@ -97,6 +98,8 @@ type NetworkNotFoundError struct {
NetworkID string
}
var _ error = NetworkNotFoundError{}
func (e NetworkNotFoundError) Error() string {
if e.NetworkName != "" {
return fmt.Sprintf("Network name %q not found", e.NetworkName)
@@ -110,6 +113,8 @@ type EndpointNotFoundError struct {
EndpointID string
}
var _ error = EndpointNotFoundError{}
func (e EndpointNotFoundError) Error() string {
if e.EndpointName != "" {
return fmt.Sprintf("Endpoint name %q not found", e.EndpointName)
@@ -122,6 +127,8 @@ type NamespaceNotFoundError struct {
NamespaceID string
}
var _ error = NamespaceNotFoundError{}
func (e NamespaceNotFoundError) Error() string {
return fmt.Sprintf("Namespace ID %q not found", e.NamespaceID)
}
@@ -131,6 +138,8 @@ type LoadBalancerNotFoundError struct {
LoadBalancerId string
}
var _ error = LoadBalancerNotFoundError{}
func (e LoadBalancerNotFoundError) Error() string {
return fmt.Sprintf("LoadBalancer %q not found", e.LoadBalancerId)
}
@@ -140,6 +149,8 @@ type RouteNotFoundError struct {
RouteId string
}
var _ error = RouteNotFoundError{}
func (e RouteNotFoundError) Error() string {
return fmt.Sprintf("SDN Route %q not found", e.RouteId)
}
@@ -147,19 +158,31 @@ func (e RouteNotFoundError) Error() string {
// IsNotFoundError returns a boolean indicating whether the error was caused by
// a resource not being found.
func IsNotFoundError(err error) bool {
switch pe := err.(type) {
case NetworkNotFoundError:
// Calling [errors.As] in a loop over `[]error{NetworkNotFoundError{}, ...}` will not work,
// since the loop variable will be an interface type (ie, `error`) and `errors.As(error, *error)` will
// always succeed.
// Unless golang adds loops over (or arrays of) types, we need to manually call `errors.As` for
// each potential error type.
//
// Also, for T = NetworkNotFoundError and co, the error implementation is for T, not *T
if e := (NetworkNotFoundError{}); errors.As(err, &e) {
return true
case EndpointNotFoundError:
return true
case NamespaceNotFoundError:
return true
case LoadBalancerNotFoundError:
return true
case RouteNotFoundError:
return true
case *hcserror.HcsError:
return pe.Err == hcs.ErrElementNotFound
}
if e := (EndpointNotFoundError{}); errors.As(err, &e) {
return true
}
if e := (NamespaceNotFoundError{}); errors.As(err, &e) {
return true
}
if e := (LoadBalancerNotFoundError{}); errors.As(err, &e) {
return true
}
if e := (RouteNotFoundError{}); errors.As(err, &e) {
return true
}
if e := (&hcserror.HcsError{}); errors.As(err, &e) {
return errors.Is(e.Err, hcs.ErrElementNotFound)
}
return false
}

View File

@@ -4,6 +4,7 @@ package hcn
import (
"encoding/json"
"errors"
"os"
"syscall"
@@ -378,7 +379,8 @@ func (namespace *HostComputeNamespace) Sync() error {
shimPath := runhcs.VMPipePath(cfg.HostUniqueID)
if err := runhcs.IssueVMRequest(shimPath, &req); err != nil {
// The shim is likely gone. Simply ignore the sync as if it didn't exist.
if perr, ok := err.(*os.PathError); ok && perr.Err == syscall.ERROR_FILE_NOT_FOUND {
var perr *os.PathError
if errors.As(err, &perr) && errors.Is(perr.Err, syscall.ERROR_FILE_NOT_FOUND) {
// Remove the reg key there is no point to try again
_ = cfg.Remove()
return nil