Update containerd to 6937c5a3ba
Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
parent
de967051d4
commit
2cc1edcfc3
@ -3,7 +3,7 @@ github.com/blang/semver v3.1.0
|
||||
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
||||
github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
|
||||
github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
|
||||
github.com/containerd/containerd v1.2.0
|
||||
github.com/containerd/containerd 6937c5a3ba8280edff9e9030767e3b0cb742581c
|
||||
github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
|
||||
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
|
||||
github.com/containerd/go-cni 40bcf8ec8acd7372be1d77031d585d5d8e561c90
|
||||
@ -34,12 +34,12 @@ github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f
|
||||
github.com/json-iterator/go 1.1.5
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.0
|
||||
github.com/Microsoft/go-winio v0.4.11
|
||||
github.com/Microsoft/hcsshim v0.7.12
|
||||
github.com/Microsoft/hcsshim v0.8.2
|
||||
github.com/modern-go/concurrent 1.0.3
|
||||
github.com/modern-go/reflect2 1.0.1
|
||||
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||
github.com/opencontainers/image-spec v1.0.1
|
||||
github.com/opencontainers/runc 58592df56734acf62e574865fe40b9e53e967910
|
||||
github.com/opencontainers/runc v1.0.0-rc6
|
||||
github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353
|
||||
github.com/opencontainers/runtime-tools fb101d5d42ab9c040f7d0a004e78336e5d5cb197
|
||||
github.com/opencontainers/selinux b6fa367ed7f534f9ba25391cc2d467085dbb445a
|
||||
@ -50,7 +50,7 @@ github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
|
||||
github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
|
||||
github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
|
||||
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
|
||||
github.com/sirupsen/logrus v1.0.0
|
||||
github.com/sirupsen/logrus v1.0.3
|
||||
github.com/stretchr/testify v1.1.4
|
||||
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
||||
github.com/tchap/go-patricia v2.2.6
|
||||
|
4
vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
generated
vendored
4
vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
generated
vendored
@ -37,8 +37,8 @@ func GetPolicyListByID(policyListID string) (*PolicyList, error) {
|
||||
}
|
||||
|
||||
// AddLoadBalancer policy list for the specified endpoints
|
||||
func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) {
|
||||
return hns.AddLoadBalancer(endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort)
|
||||
func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, isDSR bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) {
|
||||
return hns.AddLoadBalancer(endpoints, isILB, isDSR, sourceVIP, vip, protocol, internalPort, externalPort)
|
||||
}
|
||||
|
||||
// AddRoute adds route policy list for the specified endpoints
|
||||
|
5
vendor/github.com/Microsoft/hcsshim/interface.go
generated
vendored
5
vendor/github.com/Microsoft/hcsshim/interface.go
generated
vendored
@ -17,6 +17,11 @@ type MappedPipe = schema1.MappedPipe
|
||||
type HvRuntime = schema1.HvRuntime
|
||||
type MappedVirtualDisk = schema1.MappedVirtualDisk
|
||||
|
||||
// AssignedDevice represents a device that has been directly assigned to a container
|
||||
//
|
||||
// NOTE: Support added in RS5
|
||||
type AssignedDevice = schema1.AssignedDevice
|
||||
|
||||
// ContainerConfig is used as both the input of CreateContainer
|
||||
// and to convert the parameters to JSON for passing onto the HCS
|
||||
type ContainerConfig = schema1.ContainerConfig
|
||||
|
4
vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go
generated
vendored
4
vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicylist.go
generated
vendored
@ -20,6 +20,7 @@ type ELBPolicy struct {
|
||||
SourceVIP string `json:"SourceVIP,omitempty"`
|
||||
VIPs []string `json:"VIPs,omitempty"`
|
||||
ILB bool `json:"ILB,omitempty"`
|
||||
DSR bool `json:"IsDSR,omitempty"`
|
||||
}
|
||||
|
||||
// LBPolicy is a structure defining schema for LoadBalancing based Policy
|
||||
@ -139,7 +140,7 @@ func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList
|
||||
}
|
||||
|
||||
// AddLoadBalancer policy list for the specified endpoints
|
||||
func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) {
|
||||
func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, isDSR bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) {
|
||||
operation := "AddLoadBalancer"
|
||||
title := "hcsshim::PolicyList::" + operation
|
||||
logrus.Debugf(title+" endpointId=%v, isILB=%v, sourceVIP=%s, vip=%s, protocol=%v, internalPort=%v, externalPort=%v", endpoints, isILB, sourceVIP, vip, protocol, internalPort, externalPort)
|
||||
@ -149,6 +150,7 @@ func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string,
|
||||
elbPolicy := &ELBPolicy{
|
||||
SourceVIP: sourceVIP,
|
||||
ILB: isILB,
|
||||
DSR: isDSR,
|
||||
}
|
||||
|
||||
if len(vip) > 0 {
|
||||
|
4
vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_2.go
generated
vendored
4
vendor/github.com/Microsoft/hcsshim/internal/schema2/memory_2.go
generated
vendored
@ -10,7 +10,6 @@
|
||||
package hcsschema
|
||||
|
||||
type Memory2 struct {
|
||||
|
||||
SizeInMB int32 `json:"SizeInMB,omitempty"`
|
||||
|
||||
AllowOvercommit bool `json:"AllowOvercommit,omitempty"`
|
||||
@ -20,4 +19,7 @@ type Memory2 struct {
|
||||
EnableColdHint bool `json:"EnableColdHint,omitempty"`
|
||||
|
||||
EnableEpf bool `json:"EnableEpf,omitempty"`
|
||||
|
||||
// EnableDeferredCommit is private in the schema. If regenerated need to add back.
|
||||
EnableDeferredCommit bool `json:"EnableDeferredCommit,omitempty"`
|
||||
}
|
||||
|
5
vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_p_mem_controller.go
generated
vendored
5
vendor/github.com/Microsoft/hcsshim/internal/schema2/virtual_p_mem_controller.go
generated
vendored
@ -10,12 +10,11 @@
|
||||
package hcsschema
|
||||
|
||||
type VirtualPMemController struct {
|
||||
|
||||
Devices map[string]VirtualPMemDevice `json:"Devices,omitempty"`
|
||||
|
||||
MaximumCount int32 `json:"MaximumCount,omitempty"`
|
||||
MaximumCount uint32 `json:"MaximumCount,omitempty"`
|
||||
|
||||
MaximumSizeBytes int32 `json:"MaximumSizeBytes,omitempty"`
|
||||
MaximumSizeBytes uint64 `json:"MaximumSizeBytes,omitempty"`
|
||||
|
||||
Backing string `json:"Backing,omitempty"`
|
||||
}
|
||||
|
8
vendor/github.com/containerd/containerd/README.md
generated
vendored
8
vendor/github.com/containerd/containerd/README.md
generated
vendored
@ -224,7 +224,8 @@ This will be the best place to discuss design and implementation.
|
||||
|
||||
For sync communication we have a community slack with a #containerd channel that everyone is welcome to join and chat about development.
|
||||
|
||||
**Slack:** https://join.slack.com/t/dockercommunity/shared_invite/enQtNDM4NjAwNDMyOTUwLWZlMDZmYWRjZjk4Zjc5ZGQ5NWZkOWI1Yjk2NGE3ZWVlYjYxM2VhYjczOWIyZDFhZTE3NTUwZWQzMjhmNGYyZTg
|
||||
**Slack:** Catch us in the #containerd and #containerd-dev channels on dockercommunity.slack.com.
|
||||
[Click here for an invite to docker community slack.](https://join.slack.com/t/dockercommunity/shared_invite/enQtNDY4MDc1Mzc0MzIwLTgxZDBlMmM4ZGEyNDc1N2FkMzlhODJkYmE1YTVkYjM1MDE3ZjAwZjBkOGFlOTJkZjRmZGYzNjYyY2M3ZTUxYzQ)
|
||||
|
||||
### Reporting security issues
|
||||
|
||||
@ -249,3 +250,8 @@ Please find all these core project documents, including the:
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
|
||||
|
||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
||||
|
||||
## Adoption
|
||||
|
||||
Interested to see who is using containerd? Are you using containerd in a project?
|
||||
Please add yourself via pull request to our [ADOPTERS.md](./ADOPTERS.md) file.
|
||||
|
2
vendor/github.com/containerd/containerd/archive/tar.go
generated
vendored
2
vendor/github.com/containerd/containerd/archive/tar.go
generated
vendored
@ -295,7 +295,7 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
|
||||
linkBasename := filepath.Base(hdr.Linkname)
|
||||
srcHdr = aufsHardlinks[linkBasename]
|
||||
if srcHdr == nil {
|
||||
return 0, fmt.Errorf("Invalid aufs hardlink")
|
||||
return 0, fmt.Errorf("invalid aufs hardlink")
|
||||
}
|
||||
p, err := fs.RootPath(aufsTempdir, linkBasename)
|
||||
if err != nil {
|
||||
|
41
vendor/github.com/containerd/containerd/client.go
generated
vendored
41
vendor/github.com/containerd/containerd/client.go
generated
vendored
@ -17,7 +17,9 @@
|
||||
package containerd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"runtime"
|
||||
@ -520,6 +522,45 @@ func (c *Client) ListImages(ctx context.Context, filters ...string) ([]Image, er
|
||||
return images, nil
|
||||
}
|
||||
|
||||
// Restore restores a container from a checkpoint
|
||||
func (c *Client) Restore(ctx context.Context, id string, checkpoint Image, opts ...RestoreOpts) (Container, error) {
|
||||
store := c.ContentStore()
|
||||
index, err := decodeIndex(ctx, store, checkpoint.Target())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, done, err := c.WithLease(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer done(ctx)
|
||||
|
||||
copts := []NewContainerOpts{}
|
||||
for _, o := range opts {
|
||||
copts = append(copts, o(ctx, id, c, checkpoint, index))
|
||||
}
|
||||
|
||||
ctr, err := c.NewContainer(ctx, id, copts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ctr, nil
|
||||
}
|
||||
|
||||
func writeIndex(ctx context.Context, index *ocispec.Index, client *Client, ref string) (d ocispec.Descriptor, err error) {
|
||||
labels := map[string]string{}
|
||||
for i, m := range index.Manifests {
|
||||
labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = m.Digest.String()
|
||||
}
|
||||
data, err := json.Marshal(index)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
return writeContent(ctx, client.ContentStore(), ocispec.MediaTypeImageIndex, ref, bytes.NewReader(data), content.WithLabels(labels))
|
||||
}
|
||||
|
||||
// Subscribe to events that match one or more of the provided filters.
|
||||
//
|
||||
// Callers should listen on both the envelope and errs channels. If the errs
|
||||
|
57
vendor/github.com/containerd/containerd/cmd/containerd/command/main.go
generated
vendored
57
vendor/github.com/containerd/containerd/cmd/containerd/command/main.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
@ -91,6 +92,7 @@ func App() *cli.App {
|
||||
Usage: "containerd state directory",
|
||||
},
|
||||
}
|
||||
app.Flags = append(app.Flags, serviceFlags()...)
|
||||
app.Commands = []cli.Command{
|
||||
configCommand,
|
||||
publishCommand,
|
||||
@ -105,18 +107,34 @@ func App() *cli.App {
|
||||
config = defaultConfig()
|
||||
)
|
||||
|
||||
if err := srvconfig.LoadConfig(context.GlobalString("config"), config); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Apply flags to the config
|
||||
if err := applyFlags(context, config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Make sure top-level directories are created early.
|
||||
if err := server.CreateTopLevelDirectories(config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Stop if we are registering or unregistering against Windows SCM.
|
||||
stop, err := registerUnregisterService(config.Root)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
if stop {
|
||||
return nil
|
||||
}
|
||||
|
||||
done := handleSignals(ctx, signals, serverC)
|
||||
// start the signal handler as soon as we can to make sure that
|
||||
// we don't miss any signals during boot
|
||||
signal.Notify(signals, handledSignals...)
|
||||
|
||||
if err := srvconfig.LoadConfig(context.GlobalString("config"), config); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
// apply flags to the config
|
||||
if err := applyFlags(context, config); err != nil {
|
||||
return err
|
||||
}
|
||||
// cleanup temp mounts
|
||||
if err := mount.SetTempMountLocation(filepath.Join(config.Root, "tmpmounts")); err != nil {
|
||||
return errors.Wrap(err, "creating temp mount location")
|
||||
@ -142,7 +160,14 @@ func App() *cli.App {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Launch as a Windows Service if necessary
|
||||
if err := launchService(server, done); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
serverC <- server
|
||||
|
||||
if config.Debug.Address != "" {
|
||||
var l net.Listener
|
||||
if filepath.IsAbs(config.Debug.Address) {
|
||||
@ -215,6 +240,9 @@ func applyFlags(context *cli.Context, config *srvconfig.Config) error {
|
||||
*v.d = s
|
||||
}
|
||||
}
|
||||
|
||||
applyPlatformFlags(context)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -232,3 +260,18 @@ func setLevel(context *cli.Context, config *srvconfig.Config) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func dumpStacks() {
|
||||
var (
|
||||
buf []byte
|
||||
stackSize int
|
||||
)
|
||||
bufferLen := 16384
|
||||
for stackSize == len(buf) {
|
||||
buf = make([]byte, bufferLen)
|
||||
stackSize = runtime.Stack(buf, true)
|
||||
bufferLen *= 2
|
||||
}
|
||||
buf = buf[:stackSize]
|
||||
logrus.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf)
|
||||
}
|
||||
|
17
vendor/github.com/containerd/containerd/cmd/containerd/command/main_unix.go
generated
vendored
17
vendor/github.com/containerd/containerd/cmd/containerd/command/main_unix.go
generated
vendored
@ -21,11 +21,9 @@ package command
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/services/server"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -66,18 +64,3 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
|
||||
}()
|
||||
return done
|
||||
}
|
||||
|
||||
func dumpStacks() {
|
||||
var (
|
||||
buf []byte
|
||||
stackSize int
|
||||
)
|
||||
bufferLen := 16384
|
||||
for stackSize == len(buf) {
|
||||
buf = make([]byte, bufferLen)
|
||||
stackSize = runtime.Stack(buf, true)
|
||||
bufferLen *= 2
|
||||
}
|
||||
buf = buf[:stackSize]
|
||||
logrus.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf)
|
||||
}
|
||||
|
35
vendor/github.com/containerd/containerd/cmd/containerd/command/main_windows.go
generated
vendored
35
vendor/github.com/containerd/containerd/cmd/containerd/command/main_windows.go
generated
vendored
@ -18,12 +18,15 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"unsafe"
|
||||
|
||||
winio "github.com/Microsoft/go-winio"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/services/server"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
@ -54,5 +57,35 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
|
||||
}
|
||||
}
|
||||
}()
|
||||
setupDumpStacks()
|
||||
return done
|
||||
}
|
||||
|
||||
func setupDumpStacks() {
|
||||
// Windows does not support signals like *nix systems. So instead of
|
||||
// trapping on SIGUSR1 to dump stacks, we wait on a Win32 event to be
|
||||
// signaled. ACL'd to builtin administrators and local system
|
||||
event := "Global\\containerd-daemon-" + fmt.Sprint(os.Getpid())
|
||||
ev, _ := windows.UTF16PtrFromString(event)
|
||||
sd, err := winio.SddlToSecurityDescriptor("D:P(A;;GA;;;BA)(A;;GA;;;SY)")
|
||||
if err != nil {
|
||||
logrus.Errorf("failed to get security descriptor for debug stackdump event %s: %s", event, err.Error())
|
||||
return
|
||||
}
|
||||
var sa windows.SecurityAttributes
|
||||
sa.Length = uint32(unsafe.Sizeof(sa))
|
||||
sa.InheritHandle = 1
|
||||
sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0]))
|
||||
h, err := windows.CreateEvent(&sa, 0, 0, ev)
|
||||
if h == 0 || err != nil {
|
||||
logrus.Errorf("failed to create debug stackdump event %s: %s", event, err.Error())
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
logrus.Debugf("Stackdump - waiting signal at %s", event)
|
||||
for {
|
||||
windows.WaitForSingleObject(h, windows.INFINITE)
|
||||
dumpStacks()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
44
vendor/github.com/containerd/containerd/cmd/containerd/command/service_unsupported.go
generated
vendored
Normal file
44
vendor/github.com/containerd/containerd/cmd/containerd/command/service_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/services/server"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// serviceFlags returns an array of flags for configuring containerd to run
|
||||
// as a service. Only relevant on Windows.
|
||||
func serviceFlags() []cli.Flag {
|
||||
return nil
|
||||
}
|
||||
|
||||
// applyPlatformFlags applys platform-specific flags.
|
||||
func applyPlatformFlags(context *cli.Context) {
|
||||
}
|
||||
|
||||
// registerUnregisterService is only relevant on Windows.
|
||||
func registerUnregisterService(root string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// launchService is only relevant on Windows.
|
||||
func launchService(s *server.Server, done chan struct{}) error {
|
||||
return nil
|
||||
}
|
467
vendor/github.com/containerd/containerd/cmd/containerd/command/service_windows.go
generated
vendored
Normal file
467
vendor/github.com/containerd/containerd/cmd/containerd/command/service_windows.go
generated
vendored
Normal file
@ -0,0 +1,467 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/containerd/containerd/services/server"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc"
|
||||
"golang.org/x/sys/windows/svc/debug"
|
||||
"golang.org/x/sys/windows/svc/eventlog"
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
)
|
||||
|
||||
var (
|
||||
serviceNameFlag string
|
||||
registerServiceFlag bool
|
||||
unregisterServiceFlag bool
|
||||
runServiceFlag bool
|
||||
|
||||
setStdHandle = windows.NewLazySystemDLL("kernel32.dll").NewProc("SetStdHandle")
|
||||
oldStderr windows.Handle
|
||||
panicFile *os.File
|
||||
|
||||
service *handler
|
||||
)
|
||||
|
||||
const (
|
||||
// These should match the values in event_messages.mc.
|
||||
eventInfo = 1
|
||||
eventWarn = 1
|
||||
eventError = 1
|
||||
eventDebug = 2
|
||||
eventPanic = 3
|
||||
eventFatal = 4
|
||||
|
||||
eventExtraOffset = 10 // Add this to any event to get a string that supports extended data
|
||||
)
|
||||
|
||||
// serviceFlags returns an array of flags for configuring containerd to run
|
||||
// as a Windows service under control of SCM.
|
||||
func serviceFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "service-name",
|
||||
Usage: "Set the Windows service name",
|
||||
Value: "containerd",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "register-service",
|
||||
Usage: "Register the service and exit",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "unregister-service",
|
||||
Usage: "Unregister the service and exit",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "run-service",
|
||||
Usage: "",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// applyPlatformFlags applys platform-specific flags.
|
||||
func applyPlatformFlags(context *cli.Context) {
|
||||
|
||||
if s := context.GlobalString("service-name"); s != "" {
|
||||
serviceNameFlag = s
|
||||
}
|
||||
for _, v := range []struct {
|
||||
name string
|
||||
d *bool
|
||||
}{
|
||||
{
|
||||
name: "register-service",
|
||||
d: ®isterServiceFlag,
|
||||
},
|
||||
{
|
||||
name: "unregister-service",
|
||||
d: &unregisterServiceFlag,
|
||||
},
|
||||
{
|
||||
name: "run-service",
|
||||
d: &runServiceFlag,
|
||||
},
|
||||
} {
|
||||
*v.d = context.GlobalBool(v.name)
|
||||
}
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
fromsvc chan error
|
||||
s *server.Server
|
||||
done chan struct{} // Indicates back to app main to quit
|
||||
}
|
||||
|
||||
type etwHook struct {
|
||||
log *eventlog.Log
|
||||
}
|
||||
|
||||
func (h *etwHook) Levels() []logrus.Level {
|
||||
return []logrus.Level{
|
||||
logrus.PanicLevel,
|
||||
logrus.FatalLevel,
|
||||
logrus.ErrorLevel,
|
||||
logrus.WarnLevel,
|
||||
logrus.InfoLevel,
|
||||
logrus.DebugLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *etwHook) Fire(e *logrus.Entry) error {
|
||||
var (
|
||||
etype uint16
|
||||
eid uint32
|
||||
)
|
||||
|
||||
switch e.Level {
|
||||
case logrus.PanicLevel:
|
||||
etype = windows.EVENTLOG_ERROR_TYPE
|
||||
eid = eventPanic
|
||||
case logrus.FatalLevel:
|
||||
etype = windows.EVENTLOG_ERROR_TYPE
|
||||
eid = eventFatal
|
||||
case logrus.ErrorLevel:
|
||||
etype = windows.EVENTLOG_ERROR_TYPE
|
||||
eid = eventError
|
||||
case logrus.WarnLevel:
|
||||
etype = windows.EVENTLOG_WARNING_TYPE
|
||||
eid = eventWarn
|
||||
case logrus.InfoLevel:
|
||||
etype = windows.EVENTLOG_INFORMATION_TYPE
|
||||
eid = eventInfo
|
||||
case logrus.DebugLevel:
|
||||
etype = windows.EVENTLOG_INFORMATION_TYPE
|
||||
eid = eventDebug
|
||||
default:
|
||||
return errors.New("unknown level")
|
||||
}
|
||||
|
||||
// If there is additional data, include it as a second string.
|
||||
exts := ""
|
||||
if len(e.Data) > 0 {
|
||||
fs := bytes.Buffer{}
|
||||
for k, v := range e.Data {
|
||||
fs.WriteString(k)
|
||||
fs.WriteByte('=')
|
||||
fmt.Fprint(&fs, v)
|
||||
fs.WriteByte(' ')
|
||||
}
|
||||
|
||||
exts = fs.String()[:fs.Len()-1]
|
||||
eid += eventExtraOffset
|
||||
}
|
||||
|
||||
if h.log == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s [%s]\n", e.Message, exts)
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
ss [2]*uint16
|
||||
err error
|
||||
)
|
||||
|
||||
ss[0], err = windows.UTF16PtrFromString(e.Message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
count := uint16(1)
|
||||
if exts != "" {
|
||||
ss[1], err = windows.UTF16PtrFromString(exts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
count++
|
||||
}
|
||||
|
||||
return windows.ReportEvent(h.log.Handle, etype, 0, eid, 0, count, 0, &ss[0], nil)
|
||||
}
|
||||
|
||||
func getServicePath() (string, error) {
|
||||
p, err := exec.LookPath(os.Args[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Abs(p)
|
||||
}
|
||||
|
||||
func registerService() error {
|
||||
p, err := getServicePath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer m.Disconnect()
|
||||
|
||||
c := mgr.Config{
|
||||
ServiceType: windows.SERVICE_WIN32_OWN_PROCESS,
|
||||
StartType: mgr.StartAutomatic,
|
||||
ErrorControl: mgr.ErrorNormal,
|
||||
DisplayName: "Containerd",
|
||||
Description: "Container runtime",
|
||||
}
|
||||
|
||||
// Configure the service to launch with the arguments that were just passed.
|
||||
args := []string{"--run-service"}
|
||||
for _, a := range os.Args[1:] {
|
||||
if a != "--register-service" && a != "--unregister-service" {
|
||||
args = append(args, a)
|
||||
}
|
||||
}
|
||||
|
||||
s, err := m.CreateService(serviceNameFlag, p, c, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
// See http://stackoverflow.com/questions/35151052/how-do-i-configure-failure-actions-of-a-windows-service-written-in-go
|
||||
const (
|
||||
scActionNone = 0
|
||||
scActionRestart = 1
|
||||
|
||||
serviceConfigFailureActions = 2
|
||||
)
|
||||
|
||||
type serviceFailureActions struct {
|
||||
ResetPeriod uint32
|
||||
RebootMsg *uint16
|
||||
Command *uint16
|
||||
ActionsCount uint32
|
||||
Actions uintptr
|
||||
}
|
||||
|
||||
type scAction struct {
|
||||
Type uint32
|
||||
Delay uint32
|
||||
}
|
||||
t := []scAction{
|
||||
{Type: scActionRestart, Delay: uint32(60 * time.Second / time.Millisecond)},
|
||||
{Type: scActionRestart, Delay: uint32(60 * time.Second / time.Millisecond)},
|
||||
{Type: scActionNone},
|
||||
}
|
||||
lpInfo := serviceFailureActions{ResetPeriod: uint32(24 * time.Hour / time.Second), ActionsCount: uint32(3), Actions: uintptr(unsafe.Pointer(&t[0]))}
|
||||
err = windows.ChangeServiceConfig2(s.Handle, serviceConfigFailureActions, (*byte)(unsafe.Pointer(&lpInfo)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return eventlog.Install(serviceNameFlag, p, false, eventlog.Info|eventlog.Warning|eventlog.Error)
|
||||
}
|
||||
|
||||
func unregisterService() error {
|
||||
m, err := mgr.Connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer m.Disconnect()
|
||||
|
||||
s, err := m.OpenService(serviceNameFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
eventlog.Remove(serviceNameFlag)
|
||||
err = s.Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// registerUnregisterService is an entrypoint early in the daemon startup
|
||||
// to handle (un-)registering against Windows Service Control Manager (SCM).
|
||||
// It returns an indication to stop on successful SCM operation, and an error.
|
||||
func registerUnregisterService(root string) (bool, error) {
|
||||
|
||||
if unregisterServiceFlag {
|
||||
if registerServiceFlag {
|
||||
return true, errors.New("--register-service and --unregister-service cannot be used together")
|
||||
}
|
||||
return true, unregisterService()
|
||||
}
|
||||
|
||||
if registerServiceFlag {
|
||||
return true, registerService()
|
||||
}
|
||||
|
||||
if runServiceFlag {
|
||||
if err := initPanicFile(filepath.Join(root, "panic.log")); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
interactive, err := svc.IsAnInteractiveSession()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
var log *eventlog.Log
|
||||
if !interactive {
|
||||
log, err = eventlog.Open(serviceNameFlag)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
}
|
||||
|
||||
logrus.AddHook(&etwHook{log})
|
||||
logrus.SetOutput(ioutil.Discard)
|
||||
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// launchService is the entry point for running the daemon under SCM.
|
||||
func launchService(s *server.Server, done chan struct{}) error {
|
||||
|
||||
if !runServiceFlag {
|
||||
return nil
|
||||
}
|
||||
|
||||
h := &handler{
|
||||
fromsvc: make(chan error),
|
||||
s: s,
|
||||
done: done,
|
||||
}
|
||||
|
||||
interactive, err := svc.IsAnInteractiveSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
service = h
|
||||
go func() {
|
||||
if interactive {
|
||||
err = debug.Run(serviceNameFlag, h)
|
||||
} else {
|
||||
err = svc.Run(serviceNameFlag, h)
|
||||
}
|
||||
h.fromsvc <- err
|
||||
}()
|
||||
|
||||
// Wait for the first signal from the service handler.
|
||||
err = <-h.fromsvc
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *handler) Execute(_ []string, r <-chan svc.ChangeRequest, s chan<- svc.Status) (bool, uint32) {
|
||||
s <- svc.Status{State: svc.StartPending, Accepts: 0}
|
||||
// Unblock launchService()
|
||||
h.fromsvc <- nil
|
||||
|
||||
s <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown | svc.Accepted(windows.SERVICE_ACCEPT_PARAMCHANGE)}
|
||||
Loop:
|
||||
for {
|
||||
select {
|
||||
case c := <-r:
|
||||
switch c.Cmd {
|
||||
case svc.Interrogate:
|
||||
s <- c.CurrentStatus
|
||||
case svc.Stop, svc.Shutdown:
|
||||
s <- svc.Status{State: svc.StopPending, Accepts: 0}
|
||||
h.s.Stop()
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removePanicFile()
|
||||
close(h.done)
|
||||
return false, 0
|
||||
}
|
||||
|
||||
func initPanicFile(path string) error {
|
||||
var err error
|
||||
panicFile, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st, err := panicFile.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If there are contents in the file already, move the file out of the way
|
||||
// and replace it.
|
||||
if st.Size() > 0 {
|
||||
panicFile.Close()
|
||||
os.Rename(path, path+".old")
|
||||
panicFile, err = os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update STD_ERROR_HANDLE to point to the panic file so that Go writes to
|
||||
// it when it panics. Remember the old stderr to restore it before removing
|
||||
// the panic file.
|
||||
sh := windows.STD_ERROR_HANDLE
|
||||
h, err := windows.GetStdHandle(uint32(sh))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oldStderr = h
|
||||
|
||||
r, _, err := setStdHandle.Call(uintptr(sh), panicFile.Fd())
|
||||
if r == 0 && err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Reset os.Stderr to the panic file (so fmt.Fprintf(os.Stderr,...) actually gets redirected)
|
||||
os.Stderr = os.NewFile(panicFile.Fd(), "/dev/stderr")
|
||||
|
||||
// Force threads that panic to write to stderr (the panicFile handle now), otherwise it will go into the ether
|
||||
log.SetOutput(os.Stderr)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func removePanicFile() {
|
||||
if st, err := panicFile.Stat(); err == nil {
|
||||
if st.Size() == 0 {
|
||||
sh := windows.STD_ERROR_HANDLE
|
||||
setStdHandle.Call(uintptr(sh), uintptr(oldStderr))
|
||||
panicFile.Close()
|
||||
os.Remove(panicFile.Name())
|
||||
}
|
||||
}
|
||||
}
|
4
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go
generated
vendored
4
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go
generated
vendored
@ -71,10 +71,6 @@ var (
|
||||
Name: "config,c",
|
||||
Usage: "path to the runtime-specific spec config file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "checkpoint",
|
||||
Usage: "provide the checkpoint digest to restore the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cwd",
|
||||
Usage: "specify the working directory of the process",
|
||||
|
156
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/containers.go
generated
vendored
156
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/containers.go
generated
vendored
@ -18,7 +18,6 @@ package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
@ -29,8 +28,10 @@ import (
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands/run"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/typeurl"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
@ -45,13 +46,15 @@ var Command = cli.Command{
|
||||
infoCommand,
|
||||
listCommand,
|
||||
setLabelsCommand,
|
||||
checkpointCommand,
|
||||
restoreCommand,
|
||||
},
|
||||
}
|
||||
|
||||
var createCommand = cli.Command{
|
||||
Name: "create",
|
||||
Usage: "create container",
|
||||
ArgsUsage: "[flags] Image|RootFS CONTAINER",
|
||||
ArgsUsage: "[flags] Image|RootFS CONTAINER [COMMAND] [ARG...]",
|
||||
Flags: append(commands.SnapshotterFlags, commands.ContainerFlags...),
|
||||
Action: func(context *cli.Context) error {
|
||||
var (
|
||||
@ -282,3 +285,152 @@ var infoCommand = cli.Command{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var checkpointCommand = cli.Command{
|
||||
Name: "checkpoint",
|
||||
Usage: "checkpoint a container",
|
||||
ArgsUsage: "CONTAINER REF",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "rw",
|
||||
Usage: "include the rw layer in the checkpoint",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "image",
|
||||
Usage: "include the image in the checkpoint",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "task",
|
||||
Usage: "checkpoint container task",
|
||||
},
|
||||
},
|
||||
Action: func(context *cli.Context) error {
|
||||
id := context.Args().First()
|
||||
if id == "" {
|
||||
return errors.New("container id must be provided")
|
||||
}
|
||||
ref := context.Args().Get(1)
|
||||
if ref == "" {
|
||||
return errors.New("ref must be provided")
|
||||
}
|
||||
client, ctx, cancel, err := commands.NewClient(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cancel()
|
||||
opts := []containerd.CheckpointOpts{
|
||||
containerd.WithCheckpointRuntime,
|
||||
}
|
||||
|
||||
if context.Bool("image") {
|
||||
opts = append(opts, containerd.WithCheckpointImage)
|
||||
}
|
||||
if context.Bool("rw") {
|
||||
opts = append(opts, containerd.WithCheckpointRW)
|
||||
}
|
||||
if context.Bool("task") {
|
||||
opts = append(opts, containerd.WithCheckpointTask)
|
||||
}
|
||||
container, err := client.LoadContainer(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task, err := container.Task(ctx, nil)
|
||||
if err != nil {
|
||||
if !errdefs.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// pause if running
|
||||
if task != nil {
|
||||
if err := task.Pause(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := task.Resume(ctx); err != nil {
|
||||
fmt.Println(errors.Wrap(err, "error resuming task"))
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if _, err := container.Checkpoint(ctx, ref, opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var restoreCommand = cli.Command{
|
||||
Name: "restore",
|
||||
Usage: "restore a container from checkpoint",
|
||||
ArgsUsage: "CONTAINER REF",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "rw",
|
||||
Usage: "restore the rw layer from the checkpoint",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "live",
|
||||
Usage: "restore the runtime and memory data from the checkpoint",
|
||||
},
|
||||
},
|
||||
Action: func(context *cli.Context) error {
|
||||
id := context.Args().First()
|
||||
if id == "" {
|
||||
return errors.New("container id must be provided")
|
||||
}
|
||||
ref := context.Args().Get(1)
|
||||
if ref == "" {
|
||||
return errors.New("ref must be provided")
|
||||
}
|
||||
client, ctx, cancel, err := commands.NewClient(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
checkpoint, err := client.GetImage(ctx, ref)
|
||||
if err != nil {
|
||||
if !errdefs.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
// TODO (ehazlett): consider other options (always/never fetch)
|
||||
ck, err := client.Fetch(ctx, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
checkpoint = containerd.NewImage(client, ck)
|
||||
}
|
||||
|
||||
opts := []containerd.RestoreOpts{
|
||||
containerd.WithRestoreImage,
|
||||
containerd.WithRestoreSpec,
|
||||
containerd.WithRestoreRuntime,
|
||||
}
|
||||
if context.Bool("rw") {
|
||||
opts = append(opts, containerd.WithRestoreRW)
|
||||
}
|
||||
|
||||
ctr, err := client.Restore(ctx, id, checkpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
topts := []containerd.NewTaskOpts{}
|
||||
if context.Bool("live") {
|
||||
topts = append(topts, containerd.WithTaskCheckpoint(checkpoint))
|
||||
}
|
||||
|
||||
task, err := ctr.NewTask(ctx, cio.NewCreator(cio.WithStdio), topts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := task.Start(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
2
vendor/github.com/containerd/containerd/cmd/ctr/commands/resolver.go
generated
vendored
2
vendor/github.com/containerd/containerd/cmd/ctr/commands/resolver.go
generated
vendored
@ -90,7 +90,7 @@ func GetResolver(ctx gocontext.Context, clicontext *cli.Context) (remotes.Resolv
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: clicontext.Bool("insecure"),
|
||||
InsecureSkipVerify: clicontext.Bool("skip-verify"),
|
||||
},
|
||||
ExpectContinueTimeout: 5 * time.Second,
|
||||
}
|
||||
|
8
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go
generated
vendored
8
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go
generated
vendored
@ -106,11 +106,11 @@ var Command = cli.Command{
|
||||
Name: "fifo-dir",
|
||||
Usage: "directory used for storing IO FIFOs",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "isolated",
|
||||
Usage: "run the container with vm isolation",
|
||||
cli.StringFlag{
|
||||
Name: "cgroup",
|
||||
Usage: "cgroup path (To disable use of cgroup, set to \"\" explicitly)",
|
||||
},
|
||||
}, append(commands.SnapshotterFlags, commands.ContainerFlags...)...),
|
||||
}, append(platformRunFlags, append(commands.SnapshotterFlags, commands.ContainerFlags...)...)...),
|
||||
Action: func(context *cli.Context) error {
|
||||
var (
|
||||
err error
|
||||
|
14
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go
generated
vendored
14
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go
generated
vendored
@ -32,6 +32,8 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var platformRunFlags []cli.Flag
|
||||
|
||||
// NewContainer creates a new container
|
||||
func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli.Context) (containerd.Container, error) {
|
||||
var (
|
||||
@ -44,14 +46,6 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
||||
id = context.Args().Get(1)
|
||||
}
|
||||
|
||||
if raw := context.String("checkpoint"); raw != "" {
|
||||
im, err := client.GetImage(ctx, raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client.NewContainer(ctx, id, containerd.WithCheckpoint(im, id), containerd.WithRuntime(context.String("runtime"), nil))
|
||||
}
|
||||
|
||||
var (
|
||||
opts []oci.SpecOpts
|
||||
cOpts []containerd.NewContainerOpts
|
||||
@ -141,6 +135,10 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
||||
if context.IsSet("allow-new-privs") {
|
||||
opts = append(opts, oci.WithNewPrivileges)
|
||||
}
|
||||
if context.IsSet("cgroup") {
|
||||
// NOTE: can be set to "" explicitly for disabling cgroup.
|
||||
opts = append(opts, oci.WithCgroup(context.String("cgroup")))
|
||||
}
|
||||
}
|
||||
|
||||
cOpts = append(cOpts, containerd.WithRuntime(context.String("runtime"), nil))
|
||||
|
17
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_windows.go
generated
vendored
17
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_windows.go
generated
vendored
@ -23,11 +23,19 @@ import (
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
"github.com/containerd/containerd/oci"
|
||||
"github.com/containerd/containerd/runtime/v2/runhcs/options"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var platformRunFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "isolated",
|
||||
Usage: "run the container with vm isolation",
|
||||
},
|
||||
}
|
||||
|
||||
// NewContainer creates a new container
|
||||
func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli.Context) (containerd.Container, error) {
|
||||
var (
|
||||
@ -100,7 +108,14 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
||||
}
|
||||
|
||||
cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("label"))))
|
||||
cOpts = append(cOpts, containerd.WithRuntime(context.String("runtime"), nil))
|
||||
runtime := context.String("runtime")
|
||||
var runtimeOpts interface{}
|
||||
if runtime == "io.containerd.runhcs.v1" {
|
||||
runtimeOpts = &options.Options{
|
||||
Debug: context.GlobalBool("debug"),
|
||||
}
|
||||
}
|
||||
cOpts = append(cOpts, containerd.WithRuntime(runtime, runtimeOpts))
|
||||
|
||||
var s specs.Spec
|
||||
spec = containerd.WithSpec(&s, opts...)
|
||||
|
12
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/checkpoint.go
generated
vendored
12
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/checkpoint.go
generated
vendored
@ -18,7 +18,6 @@ package tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
@ -37,11 +36,6 @@ var checkpointCommand = cli.Command{
|
||||
Name: "exit",
|
||||
Usage: "stop the container after the checkpoint",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "runtime",
|
||||
Usage: "runtime name",
|
||||
Value: fmt.Sprintf("io.containerd.runtime.v1.%s", runtime.GOOS),
|
||||
},
|
||||
},
|
||||
Action: func(context *cli.Context) error {
|
||||
id := context.Args().First()
|
||||
@ -61,9 +55,13 @@ var checkpointCommand = cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := container.Info(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var opts []containerd.CheckpointTaskOpts
|
||||
if context.Bool("exit") {
|
||||
opts = append(opts, withExit(context.String("runtime")))
|
||||
opts = append(opts, withExit(info.Runtime.Name))
|
||||
}
|
||||
checkpoint, err := task.Checkpoint(ctx, opts...)
|
||||
if err != nil {
|
||||
|
24
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/delete.go
generated
vendored
24
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/delete.go
generated
vendored
@ -32,8 +32,16 @@ var deleteCommand = cli.Command{
|
||||
Name: "force, f",
|
||||
Usage: "force delete task process",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "exec-id",
|
||||
Usage: "process ID to kill",
|
||||
},
|
||||
},
|
||||
Action: func(context *cli.Context) error {
|
||||
var (
|
||||
execID = context.String("exec-id")
|
||||
force = context.Bool("force")
|
||||
)
|
||||
client, ctx, cancel, err := commands.NewClient(context)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -48,9 +56,22 @@ var deleteCommand = cli.Command{
|
||||
return err
|
||||
}
|
||||
var opts []containerd.ProcessDeleteOpts
|
||||
if context.Bool("force") {
|
||||
if force {
|
||||
opts = append(opts, containerd.WithProcessKill)
|
||||
}
|
||||
if execID != "" {
|
||||
p, err := task.LoadProcess(ctx, execID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
status, err := p.Delete(ctx, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ec := status.ExitCode(); ec != 0 {
|
||||
return cli.NewExitError("", int(ec))
|
||||
}
|
||||
} else {
|
||||
status, err := task.Delete(ctx, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -58,6 +79,7 @@ var deleteCommand = cli.Command{
|
||||
if ec := status.ExitCode(); ec != 0 {
|
||||
return cli.NewExitError("", int(ec))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
13
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/exec.go
generated
vendored
13
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/exec.go
generated
vendored
@ -40,6 +40,10 @@ var execCommand = cli.Command{
|
||||
Name: "tty,t",
|
||||
Usage: "allocate a TTY for the container",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "detach,d",
|
||||
Usage: "detach from the task after it has started execution",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "exec-id",
|
||||
Usage: "exec specific id for the process",
|
||||
@ -54,6 +58,7 @@ var execCommand = cli.Command{
|
||||
id = context.Args().First()
|
||||
args = context.Args().Tail()
|
||||
tty = context.Bool("tty")
|
||||
detach = context.Bool("detach")
|
||||
)
|
||||
if id == "" {
|
||||
return errors.New("container id must be provided")
|
||||
@ -89,7 +94,10 @@ var execCommand = cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// if detach, we should not call this defer
|
||||
if !detach {
|
||||
defer process.Delete(ctx)
|
||||
}
|
||||
|
||||
statusC, err := process.Wait(ctx)
|
||||
if err != nil {
|
||||
@ -104,6 +112,7 @@ var execCommand = cli.Command{
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !detach {
|
||||
if tty {
|
||||
if err := HandleConsoleResize(ctx, process, con); err != nil {
|
||||
logrus.WithError(err).Error("console resize")
|
||||
@ -112,10 +121,14 @@ var execCommand = cli.Command{
|
||||
sigc := commands.ForwardAllSignals(ctx, process)
|
||||
defer commands.StopCatch(sigc)
|
||||
}
|
||||
}
|
||||
|
||||
if err := process.Start(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if detach {
|
||||
return nil
|
||||
}
|
||||
status := <-statusC
|
||||
code, _, err := status.Result()
|
||||
if err != nil {
|
||||
|
76
vendor/github.com/containerd/containerd/container.go
generated
vendored
76
vendor/github.com/containerd/containerd/container.go
generated
vendored
@ -28,12 +28,22 @@ import (
|
||||
"github.com/containerd/containerd/cio"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/oci"
|
||||
"github.com/containerd/containerd/runtime/v2/runc/options"
|
||||
"github.com/containerd/typeurl"
|
||||
prototypes "github.com/gogo/protobuf/types"
|
||||
ver "github.com/opencontainers/image-spec/specs-go"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
checkpointImageNameLabel = "org.opencontainers.image.ref.name"
|
||||
checkpointRuntimeNameLabel = "io.containerd.checkpoint.runtime"
|
||||
checkpointSnapshotterNameLabel = "io.containerd.checkpoint.snapshotter"
|
||||
)
|
||||
|
||||
// Container is a metadata object for container resources and task creation
|
||||
type Container interface {
|
||||
// ID identifies the container
|
||||
@ -64,6 +74,8 @@ type Container interface {
|
||||
Extensions(context.Context) (map[string]prototypes.Any, error)
|
||||
// Update a container
|
||||
Update(context.Context, ...UpdateContainerOpts) error
|
||||
// Checkpoint creates a checkpoint image of the current container
|
||||
Checkpoint(context.Context, string, ...CheckpointOpts) (Image, error)
|
||||
}
|
||||
|
||||
func containerFromRecord(client *Client, c containers.Container) *container {
|
||||
@ -272,6 +284,70 @@ func (c *container) Update(ctx context.Context, opts ...UpdateContainerOpts) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *container) Checkpoint(ctx context.Context, ref string, opts ...CheckpointOpts) (Image, error) {
|
||||
index := &ocispec.Index{
|
||||
Versioned: ver.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
Annotations: make(map[string]string),
|
||||
}
|
||||
copts := &options.CheckpointOptions{
|
||||
Exit: false,
|
||||
OpenTcp: false,
|
||||
ExternalUnixSockets: false,
|
||||
Terminal: false,
|
||||
FileLocks: true,
|
||||
EmptyNamespaces: nil,
|
||||
}
|
||||
info, err := c.Info(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img, err := c.Image(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, done, err := c.client.WithLease(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer done(ctx)
|
||||
|
||||
// add image name to manifest
|
||||
index.Annotations[checkpointImageNameLabel] = img.Name()
|
||||
// add runtime info to index
|
||||
index.Annotations[checkpointRuntimeNameLabel] = info.Runtime.Name
|
||||
// add snapshotter info to index
|
||||
index.Annotations[checkpointSnapshotterNameLabel] = info.Snapshotter
|
||||
|
||||
// process remaining opts
|
||||
for _, o := range opts {
|
||||
if err := o(ctx, c.client, &info, index, copts); err != nil {
|
||||
err = errdefs.FromGRPC(err)
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
desc, err := writeIndex(ctx, index, c.client, c.ID()+"index")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i := images.Image{
|
||||
Name: ref,
|
||||
Target: desc,
|
||||
}
|
||||
checkpoint, err := c.client.ImageService().Create(ctx, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewImage(c.client, checkpoint), nil
|
||||
}
|
||||
|
||||
func (c *container) loadTask(ctx context.Context, ioAttach cio.Attach) (Task, error) {
|
||||
response, err := c.client.TaskService().Get(ctx, &tasks.GetRequest{
|
||||
ContainerID: c.id,
|
||||
|
155
vendor/github.com/containerd/containerd/container_checkpoint_opts.go
generated
vendored
Normal file
155
vendor/github.com/containerd/containerd/container_checkpoint_opts.go
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package containerd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
tasks "github.com/containerd/containerd/api/services/tasks/v1"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/diff"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/rootfs"
|
||||
"github.com/containerd/containerd/runtime/v2/runc/options"
|
||||
"github.com/containerd/typeurl"
|
||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrCheckpointRWUnsupported is returned if the container runtime does not support checkpoint
|
||||
ErrCheckpointRWUnsupported = errors.New("rw checkpoint is only supported on v2 runtimes")
|
||||
// ErrMediaTypeNotFound returns an error when a media type in the manifest is unknown
|
||||
ErrMediaTypeNotFound = errors.New("media type not found")
|
||||
)
|
||||
|
||||
// CheckpointOpts are options to manage the checkpoint operation
|
||||
type CheckpointOpts func(context.Context, *Client, *containers.Container, *imagespec.Index, *options.CheckpointOptions) error
|
||||
|
||||
// WithCheckpointImage includes the container image in the checkpoint
|
||||
func WithCheckpointImage(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
|
||||
ir, err := client.ImageService().Get(ctx, c.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
index.Manifests = append(index.Manifests, ir.Target)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithCheckpointTask includes the running task
|
||||
func WithCheckpointTask(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
|
||||
any, err := typeurl.MarshalAny(copts)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
task, err := client.TaskService().Checkpoint(ctx, &tasks.CheckpointTaskRequest{
|
||||
ContainerID: c.ID,
|
||||
Options: any,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, d := range task.Descriptors {
|
||||
platformSpec := platforms.DefaultSpec()
|
||||
index.Manifests = append(index.Manifests, imagespec.Descriptor{
|
||||
MediaType: d.MediaType,
|
||||
Size: d.Size_,
|
||||
Digest: d.Digest,
|
||||
Platform: &platformSpec,
|
||||
})
|
||||
}
|
||||
// save copts
|
||||
data, err := any.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := bytes.NewReader(data)
|
||||
desc, err := writeContent(ctx, client.ContentStore(), images.MediaTypeContainerd1CheckpointOptions, c.ID+"-checkpoint-options", r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
desc.Platform = &imagespec.Platform{
|
||||
OS: runtime.GOOS,
|
||||
Architecture: runtime.GOARCH,
|
||||
}
|
||||
index.Manifests = append(index.Manifests, desc)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithCheckpointRuntime includes the container runtime info
|
||||
func WithCheckpointRuntime(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
|
||||
if c.Runtime.Options != nil {
|
||||
data, err := c.Runtime.Options.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := bytes.NewReader(data)
|
||||
desc, err := writeContent(ctx, client.ContentStore(), images.MediaTypeContainerd1CheckpointRuntimeOptions, c.ID+"-runtime-options", r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
desc.Platform = &imagespec.Platform{
|
||||
OS: runtime.GOOS,
|
||||
Architecture: runtime.GOARCH,
|
||||
}
|
||||
index.Manifests = append(index.Manifests, desc)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithCheckpointRW includes the rw in the checkpoint
|
||||
func WithCheckpointRW(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
|
||||
diffOpts := []diff.Opt{
|
||||
diff.WithReference(fmt.Sprintf("checkpoint-rw-%s", c.SnapshotKey)),
|
||||
}
|
||||
rw, err := rootfs.CreateDiff(ctx,
|
||||
c.SnapshotKey,
|
||||
client.SnapshotService(c.Snapshotter),
|
||||
client.DiffService(),
|
||||
diffOpts...,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
rw.Platform = &imagespec.Platform{
|
||||
OS: runtime.GOOS,
|
||||
Architecture: runtime.GOARCH,
|
||||
}
|
||||
index.Manifests = append(index.Manifests, rw)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithCheckpointTaskExit causes the task to exit after checkpoint
|
||||
func WithCheckpointTaskExit(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error {
|
||||
copts.Exit = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetIndexByMediaType returns the index in a manifest for the specified media type
|
||||
func GetIndexByMediaType(index *imagespec.Index, mt string) (*imagespec.Descriptor, error) {
|
||||
for _, d := range index.Manifests {
|
||||
if d.MediaType == mt {
|
||||
return &d, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrMediaTypeNotFound
|
||||
}
|
69
vendor/github.com/containerd/containerd/container_opts_unix.go
generated
vendored
69
vendor/github.com/containerd/containerd/container_opts_unix.go
generated
vendored
@ -26,81 +26,12 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
protobuf "github.com/gogo/protobuf/types"
|
||||
"github.com/opencontainers/image-spec/identity"
|
||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// WithCheckpoint allows a container to be created from the checkpointed information
|
||||
// provided by the descriptor. The image, snapshot, and runtime specifications are
|
||||
// restored on the container
|
||||
func WithCheckpoint(im Image, snapshotKey string) NewContainerOpts {
|
||||
// set image and rw, and spec
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
var (
|
||||
desc = im.Target()
|
||||
store = client.ContentStore()
|
||||
)
|
||||
index, err := decodeIndex(ctx, store, desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rw *v1.Descriptor
|
||||
for _, m := range index.Manifests {
|
||||
switch m.MediaType {
|
||||
case v1.MediaTypeImageLayer:
|
||||
fk := m
|
||||
rw = &fk
|
||||
case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList:
|
||||
config, err := images.Config(ctx, store, m, platforms.Default())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to resolve image config")
|
||||
}
|
||||
diffIDs, err := images.RootFS(ctx, store, config)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to get rootfs")
|
||||
}
|
||||
setSnapshotterIfEmpty(c)
|
||||
if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, snapshotKey, identity.ChainID(diffIDs).String()); err != nil {
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
c.Image = index.Annotations["image.name"]
|
||||
case images.MediaTypeContainerd1CheckpointConfig:
|
||||
data, err := content.ReadBlob(ctx, store, m)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to read checkpoint config")
|
||||
}
|
||||
var any protobuf.Any
|
||||
if err := proto.Unmarshal(data, &any); err != nil {
|
||||
return err
|
||||
}
|
||||
c.Spec = &any
|
||||
}
|
||||
}
|
||||
if rw != nil {
|
||||
// apply the rw snapshot to the new rw layer
|
||||
mounts, err := client.SnapshotService(c.Snapshotter).Mounts(ctx, snapshotKey)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to get mounts for %s", snapshotKey)
|
||||
}
|
||||
if _, err := client.DiffService().Apply(ctx, *rw, mounts); err != nil {
|
||||
return errors.Wrap(err, "unable to apply rw diff")
|
||||
}
|
||||
}
|
||||
c.SnapshotKey = snapshotKey
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRemappedSnapshot creates a new snapshot and remaps the uid/gid for the
|
||||
// filesystem to be used by a container with user namespaces
|
||||
func WithRemappedSnapshot(id string, i Image, uid, gid uint32) NewContainerOpts {
|
||||
|
150
vendor/github.com/containerd/containerd/container_restore_opts.go
generated
vendored
Normal file
150
vendor/github.com/containerd/containerd/container_restore_opts.go
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package containerd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
"github.com/opencontainers/image-spec/identity"
|
||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrImageNameNotFoundInIndex is returned when the image name is not found in the index
|
||||
ErrImageNameNotFoundInIndex = errors.New("image name not found in index")
|
||||
// ErrRuntimeNameNotFoundInIndex is returned when the runtime is not found in the index
|
||||
ErrRuntimeNameNotFoundInIndex = errors.New("runtime not found in index")
|
||||
// ErrSnapshotterNameNotFoundInIndex is returned when the snapshotter is not found in the index
|
||||
ErrSnapshotterNameNotFoundInIndex = errors.New("snapshotter not found in index")
|
||||
)
|
||||
|
||||
// RestoreOpts are options to manage the restore operation
|
||||
type RestoreOpts func(context.Context, string, *Client, Image, *imagespec.Index) NewContainerOpts
|
||||
|
||||
// WithRestoreImage restores the image for the container
|
||||
func WithRestoreImage(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts {
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
name, ok := index.Annotations[checkpointImageNameLabel]
|
||||
if !ok || name == "" {
|
||||
return ErrRuntimeNameNotFoundInIndex
|
||||
}
|
||||
snapshotter, ok := index.Annotations[checkpointSnapshotterNameLabel]
|
||||
if !ok || name == "" {
|
||||
return ErrSnapshotterNameNotFoundInIndex
|
||||
}
|
||||
i, err := client.GetImage(ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
parent := identity.ChainID(diffIDs).String()
|
||||
if _, err := client.SnapshotService(snapshotter).Prepare(ctx, id, parent); err != nil {
|
||||
return err
|
||||
}
|
||||
c.Image = i.Name()
|
||||
c.SnapshotKey = id
|
||||
c.Snapshotter = snapshotter
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRestoreRuntime restores the runtime for the container
|
||||
func WithRestoreRuntime(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts {
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
name, ok := index.Annotations[checkpointRuntimeNameLabel]
|
||||
if !ok {
|
||||
return ErrRuntimeNameNotFoundInIndex
|
||||
}
|
||||
|
||||
// restore options if present
|
||||
m, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointRuntimeOptions)
|
||||
if err != nil {
|
||||
if err != ErrMediaTypeNotFound {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var options *ptypes.Any
|
||||
if m != nil {
|
||||
store := client.ContentStore()
|
||||
data, err := content.ReadBlob(ctx, store, *m)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to read checkpoint runtime")
|
||||
}
|
||||
if err := proto.Unmarshal(data, options); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
c.Runtime = containers.RuntimeInfo{
|
||||
Name: name,
|
||||
Options: options,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRestoreSpec restores the spec from the checkpoint for the container
|
||||
func WithRestoreSpec(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts {
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
m, err := GetIndexByMediaType(index, images.MediaTypeContainerd1CheckpointConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
store := client.ContentStore()
|
||||
data, err := content.ReadBlob(ctx, store, *m)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to read checkpoint config")
|
||||
}
|
||||
var any ptypes.Any
|
||||
if err := proto.Unmarshal(data, &any); err != nil {
|
||||
return err
|
||||
}
|
||||
c.Spec = &any
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRestoreRW restores the rw layer from the checkpoint for the container
|
||||
func WithRestoreRW(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts {
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
// apply rw layer
|
||||
rw, err := GetIndexByMediaType(index, imagespec.MediaTypeImageLayerGzip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mounts, err := client.SnapshotService(c.Snapshotter).Mounts(ctx, c.SnapshotKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := client.DiffService().Apply(ctx, *rw, mounts); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
2
vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go
generated
vendored
2
vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go
generated
vendored
@ -90,6 +90,8 @@ func WithGPUs(opts ...Opts) oci.SpecOpts {
|
||||
"oci-hook",
|
||||
"--",
|
||||
nvidiaPath,
|
||||
// ensures the required kernel modules are properly loaded
|
||||
"--load-kmods",
|
||||
}, c.args()...),
|
||||
Env: os.Environ(),
|
||||
})
|
||||
|
4
vendor/github.com/containerd/containerd/contrib/seccomp/seccomp.go
generated
vendored
4
vendor/github.com/containerd/containerd/contrib/seccomp/seccomp.go
generated
vendored
@ -37,10 +37,10 @@ func WithProfile(profile string) oci.SpecOpts {
|
||||
s.Linux.Seccomp = &specs.LinuxSeccomp{}
|
||||
f, err := ioutil.ReadFile(profile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot load seccomp profile %q: %v", profile, err)
|
||||
return fmt.Errorf("cannot load seccomp profile %q: %v", profile, err)
|
||||
}
|
||||
if err := json.Unmarshal(f, s.Linux.Seccomp); err != nil {
|
||||
return fmt.Errorf("Decoding seccomp profile failed %q: %v", profile, err)
|
||||
return fmt.Errorf("decoding seccomp profile failed %q: %v", profile, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
2
vendor/github.com/containerd/containerd/errdefs/grpc.go
generated
vendored
2
vendor/github.com/containerd/containerd/errdefs/grpc.go
generated
vendored
@ -95,7 +95,7 @@ func FromGRPC(err error) error {
|
||||
|
||||
msg := rebaseMessage(cls, err)
|
||||
if msg != "" {
|
||||
err = errors.Wrapf(cls, msg)
|
||||
err = errors.Wrap(cls, msg)
|
||||
} else {
|
||||
err = errors.WithStack(cls)
|
||||
}
|
||||
|
8
vendor/github.com/containerd/containerd/events/exchange/exchange.go
generated
vendored
8
vendor/github.com/containerd/containerd/events/exchange/exchange.go
generated
vendored
@ -138,10 +138,10 @@ func (e *Exchange) Subscribe(ctx context.Context, fs ...string) (ch <-chan *even
|
||||
)
|
||||
|
||||
closeAll := func() {
|
||||
defer close(errq)
|
||||
defer e.broadcaster.Remove(dst)
|
||||
defer queue.Close()
|
||||
defer channel.Close()
|
||||
channel.Close()
|
||||
queue.Close()
|
||||
e.broadcaster.Remove(dst)
|
||||
close(errq)
|
||||
}
|
||||
|
||||
ch = evch
|
||||
|
2
vendor/github.com/containerd/containerd/filters/parser.go
generated
vendored
2
vendor/github.com/containerd/containerd/filters/parser.go
generated
vendored
@ -71,7 +71,7 @@ func ParseAll(ss ...string) (Filter, error) {
|
||||
for _, s := range ss {
|
||||
f, err := Parse(s)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error())
|
||||
return nil, errors.Wrap(errdefs.ErrInvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
fs = append(fs, f)
|
||||
|
3
vendor/github.com/containerd/containerd/images/mediatypes.go
generated
vendored
3
vendor/github.com/containerd/containerd/images/mediatypes.go
generated
vendored
@ -34,6 +34,9 @@ const (
|
||||
MediaTypeContainerd1Resource = "application/vnd.containerd.container.resource.tar"
|
||||
MediaTypeContainerd1RW = "application/vnd.containerd.container.rw.tar"
|
||||
MediaTypeContainerd1CheckpointConfig = "application/vnd.containerd.container.checkpoint.config.v1+proto"
|
||||
MediaTypeContainerd1CheckpointOptions = "application/vnd.containerd.container.checkpoint.options.v1+proto"
|
||||
MediaTypeContainerd1CheckpointRuntimeName = "application/vnd.containerd.container.checkpoint.runtime.name"
|
||||
MediaTypeContainerd1CheckpointRuntimeOptions = "application/vnd.containerd.container.checkpoint.runtime.options+proto"
|
||||
// Legacy Docker schema1 manifest
|
||||
MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
|
||||
)
|
||||
|
2
vendor/github.com/containerd/containerd/metadata/containers.go
generated
vendored
2
vendor/github.com/containerd/containerd/metadata/containers.go
generated
vendored
@ -72,7 +72,7 @@ func (s *containerStore) List(ctx context.Context, fs ...string) ([]containers.C
|
||||
|
||||
filter, err := filters.ParseAll(fs...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error())
|
||||
return nil, errors.Wrap(errdefs.ErrInvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
bkt := getContainersBucket(s.tx, namespace)
|
||||
|
2
vendor/github.com/containerd/containerd/metadata/images.go
generated
vendored
2
vendor/github.com/containerd/containerd/metadata/images.go
generated
vendored
@ -84,7 +84,7 @@ func (s *imageStore) List(ctx context.Context, fs ...string) ([]images.Image, er
|
||||
|
||||
filter, err := filters.ParseAll(fs...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error())
|
||||
return nil, errors.Wrap(errdefs.ErrInvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
var m []images.Image
|
||||
|
2
vendor/github.com/containerd/containerd/metadata/leases.go
generated
vendored
2
vendor/github.com/containerd/containerd/metadata/leases.go
generated
vendored
@ -122,7 +122,7 @@ func (lm *LeaseManager) List(ctx context.Context, fs ...string) ([]leases.Lease,
|
||||
|
||||
filter, err := filters.ParseAll(fs...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error())
|
||||
return nil, errors.Wrap(errdefs.ErrInvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
var ll []leases.Lease
|
||||
|
8
vendor/github.com/containerd/containerd/mount/mountinfo_linux.go
generated
vendored
8
vendor/github.com/containerd/containerd/mount/mountinfo_linux.go
generated
vendored
@ -68,7 +68,7 @@ func parseInfoFile(r io.Reader) ([]Info, error) {
|
||||
numFields := len(fields)
|
||||
if numFields < 10 {
|
||||
// should be at least 10 fields
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: not enough fields (%d)", text, numFields)
|
||||
return nil, fmt.Errorf("parsing '%s' failed: not enough fields (%d)", text, numFields)
|
||||
}
|
||||
p := Info{}
|
||||
// ignore any numbers parsing errors, as there should not be any
|
||||
@ -76,7 +76,7 @@ func parseInfoFile(r io.Reader) ([]Info, error) {
|
||||
p.Parent, _ = strconv.Atoi(fields[1])
|
||||
mm := strings.Split(fields[2], ":")
|
||||
if len(mm) != 2 {
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: unexpected minor:major pair %s", text, mm)
|
||||
return nil, fmt.Errorf("parsing '%s' failed: unexpected minor:major pair %s", text, mm)
|
||||
}
|
||||
p.Major, _ = strconv.Atoi(mm[0])
|
||||
p.Minor, _ = strconv.Atoi(mm[1])
|
||||
@ -101,11 +101,11 @@ func parseInfoFile(r io.Reader) ([]Info, error) {
|
||||
}
|
||||
}
|
||||
if i == numFields {
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: missing separator ('-')", text)
|
||||
return nil, fmt.Errorf("parsing '%s' failed: missing separator ('-')", text)
|
||||
}
|
||||
// There should be 3 fields after the separator...
|
||||
if i+4 > numFields {
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: not enough fields after a separator", text)
|
||||
return nil, fmt.Errorf("parsing '%s' failed: not enough fields after a separator", text)
|
||||
}
|
||||
// ... but in Linux <= 3.9 mounting a cifs with spaces in a share name
|
||||
// (like "//serv/My Documents") _may_ end up having a space in the last field
|
||||
|
2
vendor/github.com/containerd/containerd/oci/spec.go
generated
vendored
2
vendor/github.com/containerd/containerd/oci/spec.go
generated
vendored
@ -209,6 +209,7 @@ func populateDefaultUnixSpec(ctx context.Context, s *Spec, id string) error {
|
||||
Linux: &specs.Linux{
|
||||
MaskedPaths: []string{
|
||||
"/proc/acpi",
|
||||
"/proc/asound",
|
||||
"/proc/kcore",
|
||||
"/proc/keys",
|
||||
"/proc/latency_stats",
|
||||
@ -219,7 +220,6 @@ func populateDefaultUnixSpec(ctx context.Context, s *Spec, id string) error {
|
||||
"/proc/scsi",
|
||||
},
|
||||
ReadonlyPaths: []string{
|
||||
"/proc/asound",
|
||||
"/proc/bus",
|
||||
"/proc/fs",
|
||||
"/proc/irq",
|
||||
|
2
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
2
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
@ -81,7 +81,7 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R
|
||||
// TODO(dmcg): Store challenge, not token
|
||||
// Move token fetching to authorize
|
||||
return a.setTokenAuth(ctx, host, c.parameters)
|
||||
} else if c.scheme == basicAuth {
|
||||
} else if c.scheme == basicAuth && a.credentials != nil {
|
||||
// TODO: Resolve credentials on authorize
|
||||
username, secret, err := a.credentials(host)
|
||||
if err != nil {
|
||||
|
29
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
29
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
@ -29,6 +29,7 @@ import (
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/reference"
|
||||
"github.com/containerd/containerd/remotes"
|
||||
"github.com/containerd/containerd/version"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
@ -75,13 +76,16 @@ type ResolverOptions struct {
|
||||
|
||||
// Credentials provides username and secret given a host.
|
||||
// If username is empty but a secret is given, that secret
|
||||
// is interpretted as a long lived token.
|
||||
// is interpreted as a long lived token.
|
||||
// Deprecated: use Authorizer
|
||||
Credentials func(string) (string, string, error)
|
||||
|
||||
// Host provides the hostname given a namespace.
|
||||
Host func(string) (string, error)
|
||||
|
||||
// Headers are the HTTP request header fields sent by the resolver
|
||||
Headers http.Header
|
||||
|
||||
// PlainHTTP specifies to use plain http and not https
|
||||
PlainHTTP bool
|
||||
|
||||
@ -105,6 +109,7 @@ func DefaultHost(ns string) (string, error) {
|
||||
type dockerResolver struct {
|
||||
auth Authorizer
|
||||
host func(string) (string, error)
|
||||
headers http.Header
|
||||
plainHTTP bool
|
||||
client *http.Client
|
||||
tracker StatusTracker
|
||||
@ -118,12 +123,27 @@ func NewResolver(options ResolverOptions) remotes.Resolver {
|
||||
if options.Host == nil {
|
||||
options.Host = DefaultHost
|
||||
}
|
||||
if options.Headers == nil {
|
||||
options.Headers = make(http.Header)
|
||||
}
|
||||
if _, ok := options.Headers["Accept"]; !ok {
|
||||
// set headers for all the types we support for resolution.
|
||||
options.Headers.Set("Accept", strings.Join([]string{
|
||||
images.MediaTypeDockerSchema2Manifest,
|
||||
images.MediaTypeDockerSchema2ManifestList,
|
||||
ocispec.MediaTypeImageManifest,
|
||||
ocispec.MediaTypeImageIndex, "*"}, ", "))
|
||||
}
|
||||
if _, ok := options.Headers["User-Agent"]; !ok {
|
||||
options.Headers.Set("User-Agent", "containerd/"+version.Version)
|
||||
}
|
||||
if options.Authorizer == nil {
|
||||
options.Authorizer = NewAuthorizer(options.Client, options.Credentials)
|
||||
}
|
||||
return &dockerResolver{
|
||||
auth: options.Authorizer,
|
||||
host: options.Host,
|
||||
headers: options.Headers,
|
||||
plainHTTP: options.PlainHTTP,
|
||||
client: options.Client,
|
||||
tracker: options.Tracker,
|
||||
@ -182,12 +202,7 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp
|
||||
return "", ocispec.Descriptor{}, err
|
||||
}
|
||||
|
||||
// set headers for all the types we support for resolution.
|
||||
req.Header.Set("Accept", strings.Join([]string{
|
||||
images.MediaTypeDockerSchema2Manifest,
|
||||
images.MediaTypeDockerSchema2ManifestList,
|
||||
ocispec.MediaTypeImageManifest,
|
||||
ocispec.MediaTypeImageIndex, "*"}, ", "))
|
||||
req.Header = r.headers
|
||||
|
||||
log.G(ctx).Debug("resolving")
|
||||
resp, err := fetcher.doRequestWithRetries(ctx, req, nil)
|
||||
|
5
vendor/github.com/containerd/containerd/runtime/proc/proc.go
generated
vendored
5
vendor/github.com/containerd/containerd/runtime/proc/proc.go
generated
vendored
@ -40,7 +40,6 @@ func (s Stdio) IsNull() bool {
|
||||
|
||||
// Process on a system
|
||||
type Process interface {
|
||||
State
|
||||
// ID returns the id for the process
|
||||
ID() string
|
||||
// Pid returns the pid for the process
|
||||
@ -57,10 +56,6 @@ type Process interface {
|
||||
Status(context.Context) (string, error)
|
||||
// Wait blocks until the process has exited
|
||||
Wait()
|
||||
}
|
||||
|
||||
// State of a process
|
||||
type State interface {
|
||||
// Resize resizes the process console
|
||||
Resize(ws console.WinSize) error
|
||||
// Start execution of the process
|
||||
|
4
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go
generated
vendored
4
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go
generated
vendored
@ -69,3 +69,7 @@ func (s *deletedState) SetExited(status int) {
|
||||
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
return nil, errors.Errorf("cannot exec in a deleted state")
|
||||
}
|
||||
|
||||
func (s *deletedState) Pid() int {
|
||||
return -1
|
||||
}
|
||||
|
43
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go
generated
vendored
43
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go
generated
vendored
@ -41,7 +41,7 @@ import (
|
||||
type execProcess struct {
|
||||
wg sync.WaitGroup
|
||||
|
||||
proc.State
|
||||
execState execState
|
||||
|
||||
mu sync.Mutex
|
||||
id string
|
||||
@ -69,8 +69,10 @@ func (e *execProcess) ID() string {
|
||||
}
|
||||
|
||||
func (e *execProcess) Pid() int {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
return e.execState.Pid()
|
||||
}
|
||||
|
||||
func (e *execProcess) pidv() int {
|
||||
return e.pid
|
||||
}
|
||||
|
||||
@ -86,6 +88,13 @@ func (e *execProcess) ExitedAt() time.Time {
|
||||
return e.exited
|
||||
}
|
||||
|
||||
func (e *execProcess) SetExited(status int) {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
|
||||
e.execState.SetExited(status)
|
||||
}
|
||||
|
||||
func (e *execProcess) setExited(status int) {
|
||||
e.status = status
|
||||
e.exited = time.Now()
|
||||
@ -93,6 +102,13 @@ func (e *execProcess) setExited(status int) {
|
||||
close(e.waitBlock)
|
||||
}
|
||||
|
||||
func (e *execProcess) Delete(ctx context.Context) error {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
|
||||
return e.execState.Delete(ctx)
|
||||
}
|
||||
|
||||
func (e *execProcess) delete(ctx context.Context) error {
|
||||
e.wg.Wait()
|
||||
if e.io != nil {
|
||||
@ -107,6 +123,13 @@ func (e *execProcess) delete(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *execProcess) Resize(ws console.WinSize) error {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
|
||||
return e.execState.Resize(ws)
|
||||
}
|
||||
|
||||
func (e *execProcess) resize(ws console.WinSize) error {
|
||||
if e.console == nil {
|
||||
return nil
|
||||
@ -114,6 +137,13 @@ func (e *execProcess) resize(ws console.WinSize) error {
|
||||
return e.console.Resize(ws)
|
||||
}
|
||||
|
||||
func (e *execProcess) Kill(ctx context.Context, sig uint32, _ bool) error {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
|
||||
return e.execState.Kill(ctx, sig, false)
|
||||
}
|
||||
|
||||
func (e *execProcess) kill(ctx context.Context, sig uint32, _ bool) error {
|
||||
pid := e.pid
|
||||
if pid != 0 {
|
||||
@ -132,6 +162,13 @@ func (e *execProcess) Stdio() proc.Stdio {
|
||||
return e.stdio
|
||||
}
|
||||
|
||||
func (e *execProcess) Start(ctx context.Context) error {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
|
||||
return e.execState.Start(ctx)
|
||||
}
|
||||
|
||||
func (e *execProcess) start(ctx context.Context) (err error) {
|
||||
var (
|
||||
socket *runc.Socket
|
||||
|
76
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go
generated
vendored
76
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go
generated
vendored
@ -25,6 +25,15 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type execState interface {
|
||||
Resize(console.WinSize) error
|
||||
Start(context.Context) error
|
||||
Delete(context.Context) error
|
||||
Kill(context.Context, uint32, bool) error
|
||||
SetExited(int)
|
||||
Pid() int
|
||||
}
|
||||
|
||||
type execCreatedState struct {
|
||||
p *execProcess
|
||||
}
|
||||
@ -32,11 +41,11 @@ type execCreatedState struct {
|
||||
func (s *execCreatedState) transition(name string) error {
|
||||
switch name {
|
||||
case "running":
|
||||
s.p.State = &execRunningState{p: s.p}
|
||||
s.p.execState = &execRunningState{p: s.p}
|
||||
case "stopped":
|
||||
s.p.State = &execStoppedState{p: s.p}
|
||||
s.p.execState = &execStoppedState{p: s.p}
|
||||
case "deleted":
|
||||
s.p.State = &deletedState{}
|
||||
s.p.execState = &deletedState{}
|
||||
default:
|
||||
return errors.Errorf("invalid state transition %q to %q", stateName(s), name)
|
||||
}
|
||||
@ -44,15 +53,10 @@ func (s *execCreatedState) transition(name string) error {
|
||||
}
|
||||
|
||||
func (s *execCreatedState) Resize(ws console.WinSize) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.resize(ws)
|
||||
}
|
||||
|
||||
func (s *execCreatedState) Start(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
if err := s.p.start(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -63,22 +67,15 @@ func (s *execCreatedState) Delete(ctx context.Context) error {
|
||||
if err := s.p.delete(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.transition("deleted")
|
||||
}
|
||||
|
||||
func (s *execCreatedState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.kill(ctx, sig, all)
|
||||
}
|
||||
|
||||
func (s *execCreatedState) SetExited(status int) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
s.p.setExited(status)
|
||||
|
||||
if err := s.transition("stopped"); err != nil {
|
||||
@ -86,6 +83,12 @@ func (s *execCreatedState) SetExited(status int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *execCreatedState) Pid() int {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
return s.p.pidv()
|
||||
}
|
||||
|
||||
type execRunningState struct {
|
||||
p *execProcess
|
||||
}
|
||||
@ -93,7 +96,7 @@ type execRunningState struct {
|
||||
func (s *execRunningState) transition(name string) error {
|
||||
switch name {
|
||||
case "stopped":
|
||||
s.p.State = &execStoppedState{p: s.p}
|
||||
s.p.execState = &execStoppedState{p: s.p}
|
||||
default:
|
||||
return errors.Errorf("invalid state transition %q to %q", stateName(s), name)
|
||||
}
|
||||
@ -101,37 +104,22 @@ func (s *execRunningState) transition(name string) error {
|
||||
}
|
||||
|
||||
func (s *execRunningState) Resize(ws console.WinSize) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.resize(ws)
|
||||
}
|
||||
|
||||
func (s *execRunningState) Start(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot start a running process")
|
||||
}
|
||||
|
||||
func (s *execRunningState) Delete(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot delete a running process")
|
||||
}
|
||||
|
||||
func (s *execRunningState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.kill(ctx, sig, all)
|
||||
}
|
||||
|
||||
func (s *execRunningState) SetExited(status int) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
s.p.setExited(status)
|
||||
|
||||
if err := s.transition("stopped"); err != nil {
|
||||
@ -139,6 +127,12 @@ func (s *execRunningState) SetExited(status int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *execRunningState) Pid() int {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
return s.p.pidv()
|
||||
}
|
||||
|
||||
type execStoppedState struct {
|
||||
p *execProcess
|
||||
}
|
||||
@ -146,7 +140,7 @@ type execStoppedState struct {
|
||||
func (s *execStoppedState) transition(name string) error {
|
||||
switch name {
|
||||
case "deleted":
|
||||
s.p.State = &deletedState{}
|
||||
s.p.execState = &deletedState{}
|
||||
default:
|
||||
return errors.Errorf("invalid state transition %q to %q", stateName(s), name)
|
||||
}
|
||||
@ -154,16 +148,10 @@ func (s *execStoppedState) transition(name string) error {
|
||||
}
|
||||
|
||||
func (s *execStoppedState) Resize(ws console.WinSize) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot resize a stopped container")
|
||||
}
|
||||
|
||||
func (s *execStoppedState) Start(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot start a stopped process")
|
||||
}
|
||||
|
||||
@ -171,18 +159,18 @@ func (s *execStoppedState) Delete(ctx context.Context) error {
|
||||
if err := s.p.delete(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.transition("deleted")
|
||||
}
|
||||
|
||||
func (s *execStoppedState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.kill(ctx, sig, all)
|
||||
}
|
||||
|
||||
func (s *execStoppedState) SetExited(status int) {
|
||||
// no op
|
||||
}
|
||||
|
||||
func (s *execStoppedState) Pid() int {
|
||||
return s.p.pidv()
|
||||
}
|
||||
|
125
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go
generated
vendored
125
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go
generated
vendored
@ -47,7 +47,7 @@ const InitPidFile = "init.pid"
|
||||
// Init represents an initial process for a container
|
||||
type Init struct {
|
||||
wg sync.WaitGroup
|
||||
initState
|
||||
initState initState
|
||||
|
||||
// mu is used to ensure that `Start()` and `Exited()` calls return in
|
||||
// the right order when invoked in separate go routines.
|
||||
@ -212,6 +212,7 @@ func (p *Init) Pid() int {
|
||||
func (p *Init) ExitStatus() int {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.status
|
||||
}
|
||||
|
||||
@ -219,6 +220,7 @@ func (p *Init) ExitStatus() int {
|
||||
func (p *Init) ExitedAt() time.Time {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.exited
|
||||
}
|
||||
|
||||
@ -226,6 +228,7 @@ func (p *Init) ExitedAt() time.Time {
|
||||
func (p *Init) Status(ctx context.Context) (string, error) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
c, err := p.runtime.State(ctx, p.id)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "does not exist") {
|
||||
@ -236,11 +239,27 @@ func (p *Init) Status(ctx context.Context) (string, error) {
|
||||
return c.Status, nil
|
||||
}
|
||||
|
||||
func (p *Init) start(context context.Context) error {
|
||||
err := p.runtime.Start(context, p.id)
|
||||
// Start the init process
|
||||
func (p *Init) Start(ctx context.Context) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.initState.Start(ctx)
|
||||
}
|
||||
|
||||
func (p *Init) start(ctx context.Context) error {
|
||||
err := p.runtime.Start(ctx, p.id)
|
||||
return p.runtimeError(err, "OCI runtime start failed")
|
||||
}
|
||||
|
||||
// SetExited of the init process with the next status
|
||||
func (p *Init) SetExited(status int) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
p.initState.SetExited(status)
|
||||
}
|
||||
|
||||
func (p *Init) setExited(status int) {
|
||||
p.exited = time.Now()
|
||||
p.status = status
|
||||
@ -248,9 +267,17 @@ func (p *Init) setExited(status int) {
|
||||
close(p.waitBlock)
|
||||
}
|
||||
|
||||
func (p *Init) delete(context context.Context) error {
|
||||
// Delete the init process
|
||||
func (p *Init) Delete(ctx context.Context) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.initState.Delete(ctx)
|
||||
}
|
||||
|
||||
func (p *Init) delete(ctx context.Context) error {
|
||||
p.wg.Wait()
|
||||
err := p.runtime.Delete(context, p.id, nil)
|
||||
err := p.runtime.Delete(ctx, p.id, nil)
|
||||
// ignore errors if a runtime has already deleted the process
|
||||
// but we still hold metadata and pipes
|
||||
//
|
||||
@ -270,7 +297,7 @@ func (p *Init) delete(context context.Context) error {
|
||||
p.io.Close()
|
||||
}
|
||||
if err2 := mount.UnmountAll(p.Rootfs, 0); err2 != nil {
|
||||
log.G(context).WithError(err2).Warn("failed to cleanup rootfs mount")
|
||||
log.G(ctx).WithError(err2).Warn("failed to cleanup rootfs mount")
|
||||
if err == nil {
|
||||
err = errors.Wrap(err2, "failed rootfs umount")
|
||||
}
|
||||
@ -278,6 +305,17 @@ func (p *Init) delete(context context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Resize the init processes console
|
||||
func (p *Init) Resize(ws console.WinSize) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
if p.console == nil {
|
||||
return nil
|
||||
}
|
||||
return p.console.Resize(ws)
|
||||
}
|
||||
|
||||
func (p *Init) resize(ws console.WinSize) error {
|
||||
if p.console == nil {
|
||||
return nil
|
||||
@ -285,26 +323,43 @@ func (p *Init) resize(ws console.WinSize) error {
|
||||
return p.console.Resize(ws)
|
||||
}
|
||||
|
||||
func (p *Init) pause(context context.Context) error {
|
||||
err := p.runtime.Pause(context, p.id)
|
||||
return p.runtimeError(err, "OCI runtime pause failed")
|
||||
// Pause the init process and all its child processes
|
||||
func (p *Init) Pause(ctx context.Context) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.initState.Pause(ctx)
|
||||
}
|
||||
|
||||
func (p *Init) resume(context context.Context) error {
|
||||
err := p.runtime.Resume(context, p.id)
|
||||
return p.runtimeError(err, "OCI runtime resume failed")
|
||||
// Resume the init process and all its child processes
|
||||
func (p *Init) Resume(ctx context.Context) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.initState.Resume(ctx)
|
||||
}
|
||||
|
||||
func (p *Init) kill(context context.Context, signal uint32, all bool) error {
|
||||
err := p.runtime.Kill(context, p.id, int(signal), &runc.KillOpts{
|
||||
// Kill the init process
|
||||
func (p *Init) Kill(ctx context.Context, signal uint32, all bool) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.initState.Kill(ctx, signal, all)
|
||||
}
|
||||
|
||||
func (p *Init) kill(ctx context.Context, signal uint32, all bool) error {
|
||||
err := p.runtime.Kill(ctx, p.id, int(signal), &runc.KillOpts{
|
||||
All: all,
|
||||
})
|
||||
return checkKillError(err)
|
||||
}
|
||||
|
||||
// KillAll processes belonging to the init process
|
||||
func (p *Init) KillAll(context context.Context) error {
|
||||
err := p.runtime.Kill(context, p.id, int(syscall.SIGKILL), &runc.KillOpts{
|
||||
func (p *Init) KillAll(ctx context.Context) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
err := p.runtime.Kill(ctx, p.id, int(syscall.SIGKILL), &runc.KillOpts{
|
||||
All: true,
|
||||
})
|
||||
return p.runtimeError(err, "OCI runtime killall failed")
|
||||
@ -320,8 +375,16 @@ func (p *Init) Runtime() *runc.Runc {
|
||||
return p.runtime
|
||||
}
|
||||
|
||||
// Exec returns a new child process
|
||||
func (p *Init) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.initState.Exec(ctx, path, r)
|
||||
}
|
||||
|
||||
// exec returns a new exec'd process
|
||||
func (p *Init) exec(context context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
func (p *Init) exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
// process exec request
|
||||
var spec specs.Process
|
||||
if err := json.Unmarshal(r.Spec.Value, &spec); err != nil {
|
||||
@ -342,18 +405,26 @@ func (p *Init) exec(context context.Context, path string, r *ExecConfig) (proc.P
|
||||
},
|
||||
waitBlock: make(chan struct{}),
|
||||
}
|
||||
e.State = &execCreatedState{p: e}
|
||||
e.execState = &execCreatedState{p: e}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func (p *Init) checkpoint(context context.Context, r *CheckpointConfig) error {
|
||||
// Checkpoint the init process
|
||||
func (p *Init) Checkpoint(ctx context.Context, r *CheckpointConfig) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.initState.Checkpoint(ctx, r)
|
||||
}
|
||||
|
||||
func (p *Init) checkpoint(ctx context.Context, r *CheckpointConfig) error {
|
||||
var actions []runc.CheckpointAction
|
||||
if !r.Exit {
|
||||
actions = append(actions, runc.LeaveRunning)
|
||||
}
|
||||
work := filepath.Join(p.WorkDir, "criu-work")
|
||||
defer os.RemoveAll(work)
|
||||
if err := p.runtime.Checkpoint(context, p.id, &runc.CheckpointOpts{
|
||||
if err := p.runtime.Checkpoint(ctx, p.id, &runc.CheckpointOpts{
|
||||
WorkDir: work,
|
||||
ImagePath: r.Path,
|
||||
AllowOpenTCP: r.AllowOpenTCP,
|
||||
@ -364,19 +435,27 @@ func (p *Init) checkpoint(context context.Context, r *CheckpointConfig) error {
|
||||
}, actions...); err != nil {
|
||||
dumpLog := filepath.Join(p.Bundle, "criu-dump.log")
|
||||
if cerr := copyFile(dumpLog, filepath.Join(work, "dump.log")); cerr != nil {
|
||||
log.G(context).Error(err)
|
||||
log.G(ctx).Error(err)
|
||||
}
|
||||
return fmt.Errorf("%s path= %s", criuError(err), dumpLog)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Init) update(context context.Context, r *google_protobuf.Any) error {
|
||||
// Update the processes resource configuration
|
||||
func (p *Init) Update(ctx context.Context, r *google_protobuf.Any) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
return p.initState.Update(ctx, r)
|
||||
}
|
||||
|
||||
func (p *Init) update(ctx context.Context, r *google_protobuf.Any) error {
|
||||
var resources specs.LinuxResources
|
||||
if err := json.Unmarshal(r.Value, &resources); err != nil {
|
||||
return err
|
||||
}
|
||||
return p.runtime.Update(context, p.id, &resources)
|
||||
return p.runtime.Update(ctx, p.id, &resources)
|
||||
}
|
||||
|
||||
// Stdio of the process
|
||||
|
183
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go
generated
vendored
183
vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go
generated
vendored
@ -24,22 +24,25 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/runtime/proc"
|
||||
"github.com/containerd/fifo"
|
||||
runc "github.com/containerd/go-runc"
|
||||
google_protobuf "github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type initState interface {
|
||||
proc.State
|
||||
|
||||
Resize(console.WinSize) error
|
||||
Start(context.Context) error
|
||||
Delete(context.Context) error
|
||||
Pause(context.Context) error
|
||||
Resume(context.Context) error
|
||||
Update(context.Context, *google_protobuf.Any) error
|
||||
Checkpoint(context.Context, *CheckpointConfig) error
|
||||
Exec(context.Context, string, *ExecConfig) (proc.Process, error)
|
||||
Kill(context.Context, uint32, bool) error
|
||||
SetExited(int)
|
||||
}
|
||||
|
||||
type createdState struct {
|
||||
@ -61,43 +64,26 @@ func (s *createdState) transition(name string) error {
|
||||
}
|
||||
|
||||
func (s *createdState) Pause(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot pause task in created state")
|
||||
}
|
||||
|
||||
func (s *createdState) Resume(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot resume task in created state")
|
||||
}
|
||||
|
||||
func (s *createdState) Update(context context.Context, r *google_protobuf.Any) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.update(context, r)
|
||||
func (s *createdState) Update(ctx context.Context, r *google_protobuf.Any) error {
|
||||
return s.p.update(ctx, r)
|
||||
}
|
||||
|
||||
func (s *createdState) Checkpoint(context context.Context, r *CheckpointConfig) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
func (s *createdState) Checkpoint(ctx context.Context, r *CheckpointConfig) error {
|
||||
return errors.Errorf("cannot checkpoint a task in created state")
|
||||
}
|
||||
|
||||
func (s *createdState) Resize(ws console.WinSize) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.resize(ws)
|
||||
}
|
||||
|
||||
func (s *createdState) Start(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
if err := s.p.start(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -105,8 +91,6 @@ func (s *createdState) Start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *createdState) Delete(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
if err := s.p.delete(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -114,16 +98,10 @@ func (s *createdState) Delete(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *createdState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.kill(ctx, sig, all)
|
||||
}
|
||||
|
||||
func (s *createdState) SetExited(status int) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
s.p.setExited(status)
|
||||
|
||||
if err := s.transition("stopped"); err != nil {
|
||||
@ -132,8 +110,6 @@ func (s *createdState) SetExited(status int) {
|
||||
}
|
||||
|
||||
func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
return s.p.exec(ctx, path, r)
|
||||
}
|
||||
|
||||
@ -157,43 +133,26 @@ func (s *createdCheckpointState) transition(name string) error {
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Pause(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot pause task in created state")
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Resume(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot resume task in created state")
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Update(context context.Context, r *google_protobuf.Any) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.update(context, r)
|
||||
func (s *createdCheckpointState) Update(ctx context.Context, r *google_protobuf.Any) error {
|
||||
return s.p.update(ctx, r)
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Checkpoint(context context.Context, r *CheckpointConfig) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
func (s *createdCheckpointState) Checkpoint(ctx context.Context, r *CheckpointConfig) error {
|
||||
return errors.Errorf("cannot checkpoint a task in created state")
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Resize(ws console.WinSize) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.resize(ws)
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Start(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
p := s.p
|
||||
sio := p.stdio
|
||||
|
||||
@ -247,8 +206,6 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Delete(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
if err := s.p.delete(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -256,16 +213,10 @@ func (s *createdCheckpointState) Delete(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.kill(ctx, sig, all)
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) SetExited(status int) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
s.p.setExited(status)
|
||||
|
||||
if err := s.transition("stopped"); err != nil {
|
||||
@ -274,9 +225,6 @@ func (s *createdCheckpointState) SetExited(status int) {
|
||||
}
|
||||
|
||||
func (s *createdCheckpointState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return nil, errors.Errorf("cannot exec in a created state")
|
||||
}
|
||||
|
||||
@ -297,67 +245,42 @@ func (s *runningState) transition(name string) error {
|
||||
}
|
||||
|
||||
func (s *runningState) Pause(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
if err := s.p.pause(ctx); err != nil {
|
||||
return err
|
||||
if err := s.p.runtime.Pause(ctx, s.p.id); err != nil {
|
||||
return s.p.runtimeError(err, "OCI runtime pause failed")
|
||||
}
|
||||
|
||||
return s.transition("paused")
|
||||
}
|
||||
|
||||
func (s *runningState) Resume(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot resume a running process")
|
||||
}
|
||||
|
||||
func (s *runningState) Update(context context.Context, r *google_protobuf.Any) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.update(context, r)
|
||||
func (s *runningState) Update(ctx context.Context, r *google_protobuf.Any) error {
|
||||
return s.p.update(ctx, r)
|
||||
}
|
||||
|
||||
func (s *runningState) Checkpoint(ctx context.Context, r *CheckpointConfig) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.checkpoint(ctx, r)
|
||||
}
|
||||
|
||||
func (s *runningState) Resize(ws console.WinSize) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.resize(ws)
|
||||
}
|
||||
|
||||
func (s *runningState) Start(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot start a running process")
|
||||
}
|
||||
|
||||
func (s *runningState) Delete(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot delete a running process")
|
||||
}
|
||||
|
||||
func (s *runningState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.kill(ctx, sig, all)
|
||||
}
|
||||
|
||||
func (s *runningState) SetExited(status int) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
s.p.setExited(status)
|
||||
|
||||
if err := s.transition("stopped"); err != nil {
|
||||
@ -366,8 +289,6 @@ func (s *runningState) SetExited(status int) {
|
||||
}
|
||||
|
||||
func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
return s.p.exec(ctx, path, r)
|
||||
}
|
||||
|
||||
@ -388,79 +309,54 @@ func (s *pausedState) transition(name string) error {
|
||||
}
|
||||
|
||||
func (s *pausedState) Pause(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot pause a paused container")
|
||||
}
|
||||
|
||||
func (s *pausedState) Resume(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
if err := s.p.resume(ctx); err != nil {
|
||||
return err
|
||||
if err := s.p.runtime.Resume(ctx, s.p.id); err != nil {
|
||||
return s.p.runtimeError(err, "OCI runtime resume failed")
|
||||
}
|
||||
|
||||
return s.transition("running")
|
||||
}
|
||||
|
||||
func (s *pausedState) Update(context context.Context, r *google_protobuf.Any) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.update(context, r)
|
||||
func (s *pausedState) Update(ctx context.Context, r *google_protobuf.Any) error {
|
||||
return s.p.update(ctx, r)
|
||||
}
|
||||
|
||||
func (s *pausedState) Checkpoint(ctx context.Context, r *CheckpointConfig) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.checkpoint(ctx, r)
|
||||
}
|
||||
|
||||
func (s *pausedState) Resize(ws console.WinSize) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.resize(ws)
|
||||
}
|
||||
|
||||
func (s *pausedState) Start(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot start a paused process")
|
||||
}
|
||||
|
||||
func (s *pausedState) Delete(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot delete a paused process")
|
||||
}
|
||||
|
||||
func (s *pausedState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return s.p.kill(ctx, sig, all)
|
||||
}
|
||||
|
||||
func (s *pausedState) SetExited(status int) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
s.p.setExited(status)
|
||||
|
||||
if err := s.p.runtime.Resume(context.Background(), s.p.id); err != nil {
|
||||
logrus.WithError(err).Error("resuming exited container from paused state")
|
||||
}
|
||||
|
||||
if err := s.transition("stopped"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *pausedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return nil, errors.Errorf("cannot exec in a paused state")
|
||||
}
|
||||
|
||||
@ -479,50 +375,30 @@ func (s *stoppedState) transition(name string) error {
|
||||
}
|
||||
|
||||
func (s *stoppedState) Pause(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot pause a stopped container")
|
||||
}
|
||||
|
||||
func (s *stoppedState) Resume(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot resume a stopped container")
|
||||
}
|
||||
|
||||
func (s *stoppedState) Update(context context.Context, r *google_protobuf.Any) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
func (s *stoppedState) Update(ctx context.Context, r *google_protobuf.Any) error {
|
||||
return errors.Errorf("cannot update a stopped container")
|
||||
}
|
||||
|
||||
func (s *stoppedState) Checkpoint(ctx context.Context, r *CheckpointConfig) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot checkpoint a stopped container")
|
||||
}
|
||||
|
||||
func (s *stoppedState) Resize(ws console.WinSize) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot resize a stopped container")
|
||||
}
|
||||
|
||||
func (s *stoppedState) Start(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return errors.Errorf("cannot start a stopped process")
|
||||
}
|
||||
|
||||
func (s *stoppedState) Delete(ctx context.Context) error {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
if err := s.p.delete(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -530,7 +406,7 @@ func (s *stoppedState) Delete(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *stoppedState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
return errdefs.ToGRPCf(errdefs.ErrNotFound, "process %s not found", s.p.id)
|
||||
return s.p.kill(ctx, sig, all)
|
||||
}
|
||||
|
||||
func (s *stoppedState) SetExited(status int) {
|
||||
@ -538,8 +414,5 @@ func (s *stoppedState) SetExited(status int) {
|
||||
}
|
||||
|
||||
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
s.p.mu.Lock()
|
||||
defer s.p.mu.Unlock()
|
||||
|
||||
return nil, errors.Errorf("cannot exec in a stopped state")
|
||||
}
|
||||
|
26
vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go
generated
vendored
26
vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go
generated
vendored
@ -21,6 +21,7 @@ package linux
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -40,6 +41,7 @@ import (
|
||||
"github.com/containerd/containerd/plugin"
|
||||
"github.com/containerd/containerd/runtime"
|
||||
"github.com/containerd/containerd/runtime/linux/runctypes"
|
||||
"github.com/containerd/containerd/runtime/v1"
|
||||
"github.com/containerd/containerd/runtime/v1/linux/proc"
|
||||
shim "github.com/containerd/containerd/runtime/v1/shim/v1"
|
||||
runc "github.com/containerd/go-runc"
|
||||
@ -341,6 +343,30 @@ func (r *Runtime) loadTasks(ctx context.Context, ns string) ([]*Task, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
logDirPath := filepath.Join(r.root, ns, id)
|
||||
|
||||
shimStdoutLog, err := v1.OpenShimStdoutLog(ctx, logDirPath)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).WithFields(logrus.Fields{
|
||||
"id": id,
|
||||
"namespace": ns,
|
||||
"logDirPath": logDirPath,
|
||||
}).Error("opening shim stdout log pipe")
|
||||
continue
|
||||
}
|
||||
go io.Copy(os.Stdout, shimStdoutLog)
|
||||
|
||||
shimStderrLog, err := v1.OpenShimStderrLog(ctx, logDirPath)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).WithFields(logrus.Fields{
|
||||
"id": id,
|
||||
"namespace": ns,
|
||||
"logDirPath": logDirPath,
|
||||
}).Error("opening shim stderr log pipe")
|
||||
continue
|
||||
}
|
||||
go io.Copy(os.Stderr, shimStderrLog)
|
||||
|
||||
t, err := newTask(id, ns, pid, s, r.events, r.tasks, bundle)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Error("loading task type")
|
||||
|
38
vendor/github.com/containerd/containerd/runtime/v1/shim.go
generated
vendored
Normal file
38
vendor/github.com/containerd/containerd/runtime/v1/shim.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/fifo"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// OpenShimStdoutLog opens the shim log for reading
|
||||
func OpenShimStdoutLog(ctx context.Context, logDirPath string) (io.ReadWriteCloser, error) {
|
||||
return fifo.OpenFifo(ctx, filepath.Join(logDirPath, "shim.stdout.log"), unix.O_RDWR|unix.O_CREAT|unix.O_NONBLOCK, 0700)
|
||||
}
|
||||
|
||||
// OpenShimStderrLog opens the shim log
|
||||
func OpenShimStderrLog(ctx context.Context, logDirPath string) (io.ReadWriteCloser, error) {
|
||||
return fifo.OpenFifo(ctx, filepath.Join(logDirPath, "shim.stderr.log"), unix.O_RDWR|unix.O_CREAT|unix.O_NONBLOCK, 0700)
|
||||
}
|
34
vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go
generated
vendored
34
vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go
generated
vendored
@ -37,6 +37,7 @@ import (
|
||||
|
||||
"github.com/containerd/containerd/events"
|
||||
"github.com/containerd/containerd/log"
|
||||
v1 "github.com/containerd/containerd/runtime/v1"
|
||||
"github.com/containerd/containerd/runtime/v1/shim"
|
||||
shimapi "github.com/containerd/containerd/runtime/v1/shim/v1"
|
||||
"github.com/containerd/containerd/sys"
|
||||
@ -62,7 +63,24 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
cmd, err := newCommand(binary, daemonAddress, debug, config, f)
|
||||
var stdoutLog io.ReadWriteCloser
|
||||
var stderrLog io.ReadWriteCloser
|
||||
if debug {
|
||||
stdoutLog, err = v1.OpenShimStdoutLog(ctx, config.WorkDir)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "failed to create stdout log")
|
||||
}
|
||||
|
||||
stderrLog, err = v1.OpenShimStderrLog(ctx, config.WorkDir)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "failed to create stderr log")
|
||||
}
|
||||
|
||||
go io.Copy(os.Stdout, stdoutLog)
|
||||
go io.Copy(os.Stderr, stderrLog)
|
||||
}
|
||||
|
||||
cmd, err := newCommand(binary, daemonAddress, debug, config, f, stdoutLog, stderrLog)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -77,6 +95,12 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
|
||||
go func() {
|
||||
cmd.Wait()
|
||||
exitHandler()
|
||||
if stdoutLog != nil {
|
||||
stderrLog.Close()
|
||||
}
|
||||
if stdoutLog != nil {
|
||||
stderrLog.Close()
|
||||
}
|
||||
}()
|
||||
log.G(ctx).WithFields(logrus.Fields{
|
||||
"pid": cmd.Process.Pid,
|
||||
@ -104,7 +128,7 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
|
||||
}
|
||||
}
|
||||
|
||||
func newCommand(binary, daemonAddress string, debug bool, config shim.Config, socket *os.File) (*exec.Cmd, error) {
|
||||
func newCommand(binary, daemonAddress string, debug bool, config shim.Config, socket *os.File, stdout, stderr io.Writer) (*exec.Cmd, error) {
|
||||
selfExe, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -137,10 +161,8 @@ func newCommand(binary, daemonAddress string, debug bool, config shim.Config, so
|
||||
cmd.SysProcAttr = getSysProcAttr()
|
||||
cmd.ExtraFiles = append(cmd.ExtraFiles, socket)
|
||||
cmd.Env = append(os.Environ(), "GOMAXPROCS=2")
|
||||
if debug {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
|
3
vendor/github.com/containerd/containerd/runtime/v1/shim/reaper.go
generated
vendored
3
vendor/github.com/containerd/containerd/runtime/v1/shim/reaper.go
generated
vendored
@ -31,7 +31,7 @@ import (
|
||||
// ErrNoSuchProcess is returned when the process no longer exists
|
||||
var ErrNoSuchProcess = errors.New("no such process")
|
||||
|
||||
const bufferSize = 32
|
||||
const bufferSize = 2048
|
||||
|
||||
// Reap should be called when the process receives an SIGCHLD. Reap will reap
|
||||
// all exited processes and close their wait channels
|
||||
@ -47,7 +47,6 @@ func Reap() error {
|
||||
Status: e.Status,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Default.Unlock()
|
||||
return err
|
||||
|
156
vendor/github.com/containerd/containerd/runtime/v1/shim/service.go
generated
vendored
156
vendor/github.com/containerd/containerd/runtime/v1/shim/service.go
generated
vendored
@ -114,9 +114,6 @@ type Service struct {
|
||||
|
||||
// Create a new initial process and container with the underlying OCI runtime
|
||||
func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *shimapi.CreateTaskResponse, err error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
var mounts []proc.Mount
|
||||
for _, m := range r.Rootfs {
|
||||
mounts = append(mounts, proc.Mount{
|
||||
@ -158,6 +155,10 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *
|
||||
return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m)
|
||||
}
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
process, err := newInit(
|
||||
ctx,
|
||||
s.config.Path,
|
||||
@ -187,11 +188,9 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *
|
||||
|
||||
// Start a process
|
||||
func (s *Service) Start(ctx context.Context, r *shimapi.StartRequest) (*shimapi.StartResponse, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
p := s.processes[r.ID]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrNotFound, "process %s", r.ID)
|
||||
p, err := s.getExecProcess(r.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.Start(ctx); err != nil {
|
||||
return nil, err
|
||||
@ -204,16 +203,16 @@ func (s *Service) Start(ctx context.Context, r *shimapi.StartRequest) (*shimapi.
|
||||
|
||||
// Delete the initial process and container
|
||||
func (s *Service) Delete(ctx context.Context, r *ptypes.Empty) (*shimapi.DeleteResponse, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
p := s.processes[s.id]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
p, err := s.getInitProcess()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.Delete(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.mu.Lock()
|
||||
delete(s.processes, s.id)
|
||||
s.mu.Unlock()
|
||||
s.platform.Close()
|
||||
return &shimapi.DeleteResponse{
|
||||
ExitStatus: uint32(p.ExitStatus()),
|
||||
@ -227,11 +226,9 @@ func (s *Service) DeleteProcess(ctx context.Context, r *shimapi.DeleteProcessReq
|
||||
if r.ID == s.id {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "cannot delete init process with DeleteProcess")
|
||||
}
|
||||
s.mu.Lock()
|
||||
p := s.processes[r.ID]
|
||||
s.mu.Unlock()
|
||||
if p == nil {
|
||||
return nil, errors.Wrapf(errdefs.ErrNotFound, "process %s", r.ID)
|
||||
p, err := s.getExecProcess(r.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.Delete(ctx); err != nil {
|
||||
return nil, err
|
||||
@ -249,13 +246,14 @@ func (s *Service) DeleteProcess(ctx context.Context, r *shimapi.DeleteProcessReq
|
||||
// Exec an additional process inside the container
|
||||
func (s *Service) Exec(ctx context.Context, r *shimapi.ExecProcessRequest) (*ptypes.Empty, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if p := s.processes[r.ID]; p != nil {
|
||||
s.mu.Unlock()
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrAlreadyExists, "id %s", r.ID)
|
||||
}
|
||||
|
||||
p := s.processes[s.id]
|
||||
s.mu.Unlock()
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
}
|
||||
@ -271,14 +269,14 @@ func (s *Service) Exec(ctx context.Context, r *shimapi.ExecProcessRequest) (*pty
|
||||
if err != nil {
|
||||
return nil, errdefs.ToGRPC(err)
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.processes[r.ID] = process
|
||||
s.mu.Unlock()
|
||||
return empty, nil
|
||||
}
|
||||
|
||||
// ResizePty of a process
|
||||
func (s *Service) ResizePty(ctx context.Context, r *shimapi.ResizePtyRequest) (*ptypes.Empty, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if r.ID == "" {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrInvalidArgument, "id not provided")
|
||||
}
|
||||
@ -286,7 +284,9 @@ func (s *Service) ResizePty(ctx context.Context, r *shimapi.ResizePtyRequest) (*
|
||||
Width: uint16(r.Width),
|
||||
Height: uint16(r.Height),
|
||||
}
|
||||
s.mu.Lock()
|
||||
p := s.processes[r.ID]
|
||||
s.mu.Unlock()
|
||||
if p == nil {
|
||||
return nil, errors.Errorf("process does not exist %s", r.ID)
|
||||
}
|
||||
@ -298,11 +298,9 @@ func (s *Service) ResizePty(ctx context.Context, r *shimapi.ResizePtyRequest) (*
|
||||
|
||||
// State returns runtime state information for a process
|
||||
func (s *Service) State(ctx context.Context, r *shimapi.StateRequest) (*shimapi.StateResponse, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
p := s.processes[r.ID]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrNotFound, "process id %s", r.ID)
|
||||
p, err := s.getExecProcess(r.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st, err := p.Status(ctx)
|
||||
if err != nil {
|
||||
@ -338,11 +336,9 @@ func (s *Service) State(ctx context.Context, r *shimapi.StateRequest) (*shimapi.
|
||||
|
||||
// Pause the container
|
||||
func (s *Service) Pause(ctx context.Context, r *ptypes.Empty) (*ptypes.Empty, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
p := s.processes[s.id]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
p, err := s.getInitProcess()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.(*proc.Init).Pause(ctx); err != nil {
|
||||
return nil, err
|
||||
@ -352,11 +348,9 @@ func (s *Service) Pause(ctx context.Context, r *ptypes.Empty) (*ptypes.Empty, er
|
||||
|
||||
// Resume the container
|
||||
func (s *Service) Resume(ctx context.Context, r *ptypes.Empty) (*ptypes.Empty, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
p := s.processes[s.id]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
p, err := s.getInitProcess()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.(*proc.Init).Resume(ctx); err != nil {
|
||||
return nil, err
|
||||
@ -366,12 +360,10 @@ func (s *Service) Resume(ctx context.Context, r *ptypes.Empty) (*ptypes.Empty, e
|
||||
|
||||
// Kill a process with the provided signal
|
||||
func (s *Service) Kill(ctx context.Context, r *shimapi.KillRequest) (*ptypes.Empty, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if r.ID == "" {
|
||||
p := s.processes[s.id]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
p, err := s.getInitProcess()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.Kill(ctx, r.Signal, r.All); err != nil {
|
||||
return nil, errdefs.ToGRPC(err)
|
||||
@ -379,9 +371,9 @@ func (s *Service) Kill(ctx context.Context, r *shimapi.KillRequest) (*ptypes.Emp
|
||||
return empty, nil
|
||||
}
|
||||
|
||||
p := s.processes[r.ID]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrNotFound, "process id %s not found", r.ID)
|
||||
p, err := s.getExecProcess(r.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.Kill(ctx, r.Signal, r.All); err != nil {
|
||||
return nil, errdefs.ToGRPC(err)
|
||||
@ -422,11 +414,9 @@ func (s *Service) ListPids(ctx context.Context, r *shimapi.ListPidsRequest) (*sh
|
||||
|
||||
// CloseIO of a process
|
||||
func (s *Service) CloseIO(ctx context.Context, r *shimapi.CloseIORequest) (*ptypes.Empty, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
p := s.processes[r.ID]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrNotFound, "process does not exist %s", r.ID)
|
||||
p, err := s.getExecProcess(r.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if stdin := p.Stdin(); stdin != nil {
|
||||
if err := stdin.Close(); err != nil {
|
||||
@ -438,11 +428,9 @@ func (s *Service) CloseIO(ctx context.Context, r *shimapi.CloseIORequest) (*ptyp
|
||||
|
||||
// Checkpoint the container
|
||||
func (s *Service) Checkpoint(ctx context.Context, r *shimapi.CheckpointTaskRequest) (*ptypes.Empty, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
p := s.processes[s.id]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
p, err := s.getInitProcess()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var options runctypes.CheckpointOptions
|
||||
if r.Options != nil {
|
||||
@ -475,11 +463,9 @@ func (s *Service) ShimInfo(ctx context.Context, r *ptypes.Empty) (*shimapi.ShimI
|
||||
|
||||
// Update a running container
|
||||
func (s *Service) Update(ctx context.Context, r *shimapi.UpdateTaskRequest) (*ptypes.Empty, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
p := s.processes[s.id]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
p, err := s.getInitProcess()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := p.(*proc.Init).Update(ctx, r.Resources); err != nil {
|
||||
return nil, errdefs.ToGRPC(err)
|
||||
@ -489,11 +475,9 @@ func (s *Service) Update(ctx context.Context, r *shimapi.UpdateTaskRequest) (*pt
|
||||
|
||||
// Wait for a process to exit
|
||||
func (s *Service) Wait(ctx context.Context, r *shimapi.WaitRequest) (*shimapi.WaitResponse, error) {
|
||||
s.mu.Lock()
|
||||
p := s.processes[r.ID]
|
||||
s.mu.Unlock()
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
p, err := s.getExecProcess(r.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Wait()
|
||||
|
||||
@ -509,16 +493,24 @@ func (s *Service) processExits() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) checkProcesses(e runc.Exit) {
|
||||
func (s *Service) allProcesses() []rproc.Process {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
res := make([]rproc.Process, 0, len(s.processes))
|
||||
for _, p := range s.processes {
|
||||
res = append(res, p)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *Service) checkProcesses(e runc.Exit) {
|
||||
shouldKillAll, err := shouldKillAllOnExit(s.bundle)
|
||||
if err != nil {
|
||||
log.G(s.context).WithError(err).Error("failed to check shouldKillAll")
|
||||
}
|
||||
|
||||
for _, p := range s.processes {
|
||||
for _, p := range s.allProcesses() {
|
||||
if p.Pid() == e.Pid {
|
||||
|
||||
if shouldKillAll {
|
||||
@ -563,11 +555,9 @@ func shouldKillAllOnExit(bundlePath string) (bool, error) {
|
||||
}
|
||||
|
||||
func (s *Service) getContainerPids(ctx context.Context, id string) ([]uint32, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
p := s.processes[s.id]
|
||||
if p == nil {
|
||||
return nil, errors.Wrapf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
p, err := s.getInitProcess()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ps, err := p.(*proc.Init).Runtime().Ps(ctx, id)
|
||||
@ -589,6 +579,30 @@ func (s *Service) forward(publisher events.Publisher) {
|
||||
}
|
||||
}
|
||||
|
||||
// getInitProcess returns initial process
|
||||
func (s *Service) getInitProcess() (rproc.Process, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
p := s.processes[s.id]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// getExecProcess returns exec process
|
||||
func (s *Service) getExecProcess(id string) (rproc.Process, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
p := s.processes[id]
|
||||
if p == nil {
|
||||
return nil, errdefs.ToGRPCf(errdefs.ErrNotFound, "process %s does not exist", id)
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func getTopic(ctx context.Context, e interface{}) string {
|
||||
switch e.(type) {
|
||||
case *eventstypes.TaskCreate:
|
||||
|
8
vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go
generated
vendored
8
vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go
generated
vendored
@ -49,9 +49,11 @@ func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console
|
||||
cwg.Add(1)
|
||||
go func() {
|
||||
cwg.Done()
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
io.CopyBuffer(epollConsole, in, *p)
|
||||
bp := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(bp)
|
||||
io.CopyBuffer(epollConsole, in, *bp)
|
||||
// we need to shutdown epollConsole when pipe broken
|
||||
epollConsole.Shutdown(p.epoller.CloseConsole)
|
||||
}()
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
// +build windows,windows_v2
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
@ -16,20 +14,4 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/plugin"
|
||||
"github.com/containerd/containerd/runtime"
|
||||
)
|
||||
|
||||
var tasksServiceRequires = []plugin.Type{
|
||||
plugin.RuntimePluginV2,
|
||||
plugin.MetadataPlugin,
|
||||
plugin.TaskMonitorPlugin,
|
||||
}
|
||||
|
||||
// loadV1Runtimes on Windows V2 returns an empty map. There are no v1 runtimes
|
||||
func loadV1Runtimes(ic *plugin.InitContext) (map[string]runtime.PlatformRuntime, error) {
|
||||
return make(map[string]runtime.PlatformRuntime), nil
|
||||
}
|
||||
package options
|
418
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.pb.go
generated
vendored
Normal file
418
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.pb.go
generated
vendored
Normal file
@ -0,0 +1,418 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto
|
||||
|
||||
/*
|
||||
Package options is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Options
|
||||
*/
|
||||
package options
|
||||
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Options_DebugType int32
|
||||
|
||||
const (
|
||||
Options_NPIPE Options_DebugType = 0
|
||||
Options_FILE Options_DebugType = 1
|
||||
)
|
||||
|
||||
var Options_DebugType_name = map[int32]string{
|
||||
0: "NPIPE",
|
||||
1: "FILE",
|
||||
}
|
||||
var Options_DebugType_value = map[string]int32{
|
||||
"NPIPE": 0,
|
||||
"FILE": 1,
|
||||
}
|
||||
|
||||
func (x Options_DebugType) String() string {
|
||||
return proto.EnumName(Options_DebugType_name, int32(x))
|
||||
}
|
||||
func (Options_DebugType) EnumDescriptor() ([]byte, []int) { return fileDescriptorRunhcs, []int{0, 0} }
|
||||
|
||||
type Options struct {
|
||||
// enable debug tracing
|
||||
Debug bool `protobuf:"varint,1,opt,name=debug,proto3" json:"debug,omitempty"`
|
||||
// debug tracing output type
|
||||
DebugType Options_DebugType `protobuf:"varint,2,opt,name=debug_type,json=debugType,proto3,enum=containerd.runhcs.v1.Options_DebugType" json:"debug_type,omitempty"`
|
||||
// registry key root for storage of the runhcs container state
|
||||
RegistryRoot string `protobuf:"bytes,3,opt,name=registry_root,json=registryRoot,proto3" json:"registry_root,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Options) Reset() { *m = Options{} }
|
||||
func (*Options) ProtoMessage() {}
|
||||
func (*Options) Descriptor() ([]byte, []int) { return fileDescriptorRunhcs, []int{0} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Options)(nil), "containerd.runhcs.v1.Options")
|
||||
proto.RegisterEnum("containerd.runhcs.v1.Options_DebugType", Options_DebugType_name, Options_DebugType_value)
|
||||
}
|
||||
func (m *Options) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Options) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Debug {
|
||||
dAtA[i] = 0x8
|
||||
i++
|
||||
if m.Debug {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i++
|
||||
}
|
||||
if m.DebugType != 0 {
|
||||
dAtA[i] = 0x10
|
||||
i++
|
||||
i = encodeVarintRunhcs(dAtA, i, uint64(m.DebugType))
|
||||
}
|
||||
if len(m.RegistryRoot) > 0 {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintRunhcs(dAtA, i, uint64(len(m.RegistryRoot)))
|
||||
i += copy(dAtA[i:], m.RegistryRoot)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeVarintRunhcs(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *Options) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Debug {
|
||||
n += 2
|
||||
}
|
||||
if m.DebugType != 0 {
|
||||
n += 1 + sovRunhcs(uint64(m.DebugType))
|
||||
}
|
||||
l = len(m.RegistryRoot)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRunhcs(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovRunhcs(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozRunhcs(x uint64) (n int) {
|
||||
return sovRunhcs(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (this *Options) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := strings.Join([]string{`&Options{`,
|
||||
`Debug:` + fmt.Sprintf("%v", this.Debug) + `,`,
|
||||
`DebugType:` + fmt.Sprintf("%v", this.DebugType) + `,`,
|
||||
`RegistryRoot:` + fmt.Sprintf("%v", this.RegistryRoot) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func valueToStringRunhcs(v interface{}) string {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.IsNil() {
|
||||
return "nil"
|
||||
}
|
||||
pv := reflect.Indirect(rv).Interface()
|
||||
return fmt.Sprintf("*%v", pv)
|
||||
}
|
||||
func (m *Options) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRunhcs
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Options: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Options: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Debug", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRunhcs
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Debug = bool(v != 0)
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field DebugType", wireType)
|
||||
}
|
||||
m.DebugType = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRunhcs
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.DebugType |= (Options_DebugType(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field RegistryRoot", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRunhcs
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthRunhcs
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.RegistryRoot = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipRunhcs(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthRunhcs
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipRunhcs(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowRunhcs
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowRunhcs
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowRunhcs
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthRunhcs
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowRunhcs
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipRunhcs(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthRunhcs = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowRunhcs = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto", fileDescriptorRunhcs)
|
||||
}
|
||||
|
||||
var fileDescriptorRunhcs = []byte{
|
||||
// 265 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x72, 0x4f, 0xcf, 0x2c, 0xc9,
|
||||
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d,
|
||||
0x4a, 0x41, 0x66, 0x16, 0x95, 0xe6, 0x95, 0x64, 0xe6, 0xa6, 0xea, 0x97, 0x19, 0x81, 0x98, 0x19,
|
||||
0xc9, 0xc5, 0xfa, 0xf9, 0x05, 0x25, 0x99, 0xf9, 0x79, 0xc5, 0x50, 0xae, 0x5e, 0x41, 0x51, 0x7e,
|
||||
0x49, 0xbe, 0x90, 0x08, 0x42, 0x8b, 0x1e, 0x54, 0xa2, 0xcc, 0x50, 0x4a, 0x24, 0x3d, 0x3f, 0x3d,
|
||||
0x1f, 0xac, 0x40, 0x1f, 0xc4, 0x82, 0xa8, 0x55, 0x5a, 0xc7, 0xc8, 0xc5, 0xee, 0x0f, 0x31, 0x44,
|
||||
0x48, 0x84, 0x8b, 0x35, 0x25, 0x35, 0xa9, 0x34, 0x5d, 0x82, 0x51, 0x81, 0x51, 0x83, 0x23, 0x08,
|
||||
0xc2, 0x11, 0x72, 0xe3, 0xe2, 0x02, 0x33, 0xe2, 0x4b, 0x2a, 0x0b, 0x52, 0x25, 0x98, 0x14, 0x18,
|
||||
0x35, 0xf8, 0x8c, 0xd4, 0xf5, 0xb0, 0x59, 0xa1, 0x07, 0x35, 0x48, 0xcf, 0x05, 0xa4, 0x3e, 0xa4,
|
||||
0xb2, 0x20, 0x35, 0x88, 0x33, 0x05, 0xc6, 0x14, 0x52, 0xe6, 0xe2, 0x2d, 0x4a, 0x4d, 0xcf, 0x2c,
|
||||
0x2e, 0x29, 0xaa, 0x8c, 0x2f, 0xca, 0xcf, 0x2f, 0x91, 0x60, 0x56, 0x60, 0xd4, 0xe0, 0x0c, 0xe2,
|
||||
0x81, 0x09, 0x06, 0xe5, 0xe7, 0x97, 0x28, 0x29, 0x70, 0x71, 0xc2, 0x35, 0x0b, 0x71, 0x72, 0xb1,
|
||||
0xfa, 0x05, 0x78, 0x06, 0xb8, 0x0a, 0x30, 0x08, 0x71, 0x70, 0xb1, 0xb8, 0x79, 0xfa, 0xb8, 0x0a,
|
||||
0x30, 0x3a, 0xc5, 0x9c, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, 0x23, 0x39, 0xc6,
|
||||
0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x31, 0xca, 0x89, 0xfc,
|
||||
0xf0, 0xb3, 0x86, 0xd2, 0x11, 0x0c, 0x49, 0x6c, 0xe0, 0x70, 0x31, 0x06, 0x04, 0x00, 0x00, 0xff,
|
||||
0xff, 0x91, 0x7a, 0xda, 0xa5, 0x8e, 0x01, 0x00, 0x00,
|
||||
}
|
20
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto
generated
vendored
Normal file
20
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.runhcs.v1;
|
||||
|
||||
import weak "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/runtime/v2/runhcs/options;options";
|
||||
|
||||
message Options {
|
||||
// enable debug tracing
|
||||
bool debug = 1;
|
||||
enum DebugType {
|
||||
NPIPE = 0;
|
||||
FILE = 1;
|
||||
}
|
||||
// debug tracing output type
|
||||
DebugType debug_type = 2;
|
||||
// registry key root for storage of the runhcs container state
|
||||
string registry_root = 3;
|
||||
}
|
3
vendor/github.com/containerd/containerd/runtime/v2/shim/reaper_unix.go
generated
vendored
3
vendor/github.com/containerd/containerd/runtime/v2/shim/reaper_unix.go
generated
vendored
@ -31,7 +31,7 @@ import (
|
||||
// ErrNoSuchProcess is returned when the process no longer exists
|
||||
var ErrNoSuchProcess = errors.New("no such process")
|
||||
|
||||
const bufferSize = 32
|
||||
const bufferSize = 2048
|
||||
|
||||
// Reap should be called when the process receives an SIGCHLD. Reap will reap
|
||||
// all exited processes and close their wait channels
|
||||
@ -47,7 +47,6 @@ func Reap() error {
|
||||
Status: e.Status,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Default.Unlock()
|
||||
return err
|
||||
|
2
vendor/github.com/containerd/containerd/runtime/v2/shim/shim_unix.go
generated
vendored
2
vendor/github.com/containerd/containerd/runtime/v2/shim/shim_unix.go
generated
vendored
@ -87,7 +87,7 @@ func handleSignals(logger *logrus.Entry, signals chan os.Signal) error {
|
||||
}
|
||||
|
||||
func openLog(ctx context.Context, _ string) (io.Writer, error) {
|
||||
return fifo.OpenFifo(context.Background(), "log", unix.O_WRONLY, 0700)
|
||||
return fifo.OpenFifo(ctx, "log", unix.O_WRONLY, 0700)
|
||||
}
|
||||
|
||||
func (l *remoteEventsPublisher) Publish(ctx context.Context, topic string, event events.Event) error {
|
||||
|
7
vendor/github.com/containerd/containerd/runtime/v2/shim/shim_windows.go
generated
vendored
7
vendor/github.com/containerd/containerd/runtime/v2/shim/shim_windows.go
generated
vendored
@ -27,7 +27,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
winio "github.com/Microsoft/go-winio"
|
||||
@ -40,10 +39,6 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
errorConnectionAborted syscall.Errno = 1236
|
||||
)
|
||||
|
||||
// setupSignals creates a new signal handler for all signals
|
||||
func setupSignals() (chan os.Signal, error) {
|
||||
signals := make(chan os.Signal, 32)
|
||||
@ -209,7 +204,7 @@ func (dswl *deferredShimWriteLogger) beginAccept() {
|
||||
dswl.mu.Unlock()
|
||||
|
||||
c, err := dswl.l.Accept()
|
||||
if err == errorConnectionAborted {
|
||||
if err == winio.ErrPipeListenerClosed {
|
||||
dswl.mu.Lock()
|
||||
dswl.aborted = true
|
||||
dswl.l.Close()
|
||||
|
14
vendor/github.com/containerd/containerd/runtime/v2/shim/util.go
generated
vendored
14
vendor/github.com/containerd/containerd/runtime/v2/shim/util.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
@ -32,6 +33,8 @@ import (
|
||||
|
||||
const shimBinaryFormat = "containerd-shim-%s-%s"
|
||||
|
||||
var runtimePaths sync.Map
|
||||
|
||||
// Command returns the shim command with the provided args and configuration
|
||||
func Command(ctx context.Context, runtime, containerdAddress, path string, cmdArgs ...string) (*exec.Cmd, error) {
|
||||
ns, err := namespaces.NamespaceRequired(ctx)
|
||||
@ -52,7 +55,12 @@ func Command(ctx context.Context, runtime, containerdAddress, path string, cmdAr
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("invalid runtime name %s, correct runtime name should format like io.containerd.runc.v1", runtime)
|
||||
}
|
||||
|
||||
var cmdPath string
|
||||
cmdPathI, cmdPathFound := runtimePaths.Load(name)
|
||||
if cmdPathFound {
|
||||
cmdPath = cmdPathI.(string)
|
||||
} else {
|
||||
var lerr error
|
||||
if cmdPath, lerr = exec.LookPath(name); lerr != nil {
|
||||
if eerr, ok := lerr.(*exec.Error); ok {
|
||||
@ -65,6 +73,12 @@ func Command(ctx context.Context, runtime, containerdAddress, path string, cmdAr
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cmdPathI, cmdPathFound = runtimePaths.LoadOrStore(name, cmdPath); cmdPathFound {
|
||||
// We didn't store cmdPath we loaded an already cached value. Use it.
|
||||
cmdPath = cmdPathI.(string)
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command(cmdPath, args...)
|
||||
cmd.Dir = path
|
||||
cmd.Env = append(os.Environ(), "GOMAXPROCS=2")
|
||||
|
23
vendor/github.com/containerd/containerd/services/server/server.go
generated
vendored
23
vendor/github.com/containerd/containerd/services/server/server.go
generated
vendored
@ -50,23 +50,28 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// New creates and initializes a new containerd server
|
||||
func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
|
||||
// CreateTopLevelDirectories creates the top-level root and state directories.
|
||||
func CreateTopLevelDirectories(config *srvconfig.Config) error {
|
||||
switch {
|
||||
case config.Root == "":
|
||||
return nil, errors.New("root must be specified")
|
||||
return errors.New("root must be specified")
|
||||
case config.State == "":
|
||||
return nil, errors.New("state must be specified")
|
||||
return errors.New("state must be specified")
|
||||
case config.Root == config.State:
|
||||
return nil, errors.New("root and state must be different paths")
|
||||
return errors.New("root and state must be different paths")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(config.Root, 0711); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(config.State, 0711); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// New creates and initializes a new containerd server
|
||||
func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
|
||||
if err := apply(ctx, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -125,7 +130,7 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
|
||||
instance, err := result.Instance()
|
||||
if err != nil {
|
||||
if plugin.IsSkipPlugin(err) {
|
||||
log.G(ctx).WithField("type", p.Type).Infof("skip loading plugin %q...", id)
|
||||
log.G(ctx).WithError(err).WithField("type", p.Type).Infof("skip loading plugin %q...", id)
|
||||
} else {
|
||||
log.G(ctx).WithError(err).Warnf("failed to load plugin %s", id)
|
||||
}
|
||||
@ -251,8 +256,10 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis
|
||||
for name, sn := range snapshottersRaw {
|
||||
sn, err := sn.Instance()
|
||||
if err != nil {
|
||||
if !plugin.IsSkipPlugin(err) {
|
||||
log.G(ic.Context).WithError(err).
|
||||
Warnf("could not use snapshotter %v in metadata plugin", name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
snapshotters[name] = sn.(snapshots.Snapshotter)
|
||||
|
9
vendor/github.com/containerd/containerd/services/tasks/local.go
generated
vendored
9
vendor/github.com/containerd/containerd/services/tasks/local.go
generated
vendored
@ -173,11 +173,14 @@ func (l *local) Create(ctx context.Context, r *api.CreateTaskRequest, _ ...grpc.
|
||||
Options: m.Options,
|
||||
})
|
||||
}
|
||||
runtime, err := l.getRuntime(container.Runtime.Name)
|
||||
rtime, err := l.getRuntime(container.Runtime.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c, err := runtime.Create(ctx, r.ContainerID, opts)
|
||||
if _, err := rtime.Get(ctx, r.ContainerID); err != runtime.ErrTaskNotExists {
|
||||
return nil, errdefs.ToGRPC(fmt.Errorf("task %s already exists", r.ContainerID))
|
||||
}
|
||||
c, err := rtime.Create(ctx, r.ContainerID, opts)
|
||||
if err != nil {
|
||||
return nil, errdefs.ToGRPC(err)
|
||||
}
|
||||
@ -460,7 +463,7 @@ func (l *local) CloseIO(ctx context.Context, r *api.CloseIORequest, _ ...grpc.Ca
|
||||
}
|
||||
if r.Stdin {
|
||||
if err := p.CloseIO(ctx); err != nil {
|
||||
return nil, err
|
||||
return nil, errdefs.ToGRPC(err)
|
||||
}
|
||||
}
|
||||
return empty, nil
|
||||
|
2
vendor/github.com/containerd/containerd/services/tasks/local_unix.go
generated
vendored
2
vendor/github.com/containerd/containerd/services/tasks/local_unix.go
generated
vendored
@ -1,5 +1,3 @@
|
||||
// +build !windows_v2
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
|
10
vendor/github.com/containerd/containerd/vendor.conf
generated
vendored
10
vendor/github.com/containerd/containerd/vendor.conf
generated
vendored
@ -20,8 +20,8 @@ github.com/gogo/protobuf v1.0.0
|
||||
github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
|
||||
github.com/golang/protobuf v1.1.0
|
||||
github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
|
||||
github.com/opencontainers/runc 58592df56734acf62e574865fe40b9e53e967910
|
||||
github.com/sirupsen/logrus v1.0.0
|
||||
github.com/opencontainers/runc v1.0.0-rc6
|
||||
github.com/sirupsen/logrus v1.0.3
|
||||
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
||||
golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
|
||||
google.golang.org/grpc v1.12.0
|
||||
@ -33,7 +33,7 @@ golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
|
||||
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
||||
github.com/Microsoft/go-winio v0.4.11
|
||||
github.com/Microsoft/hcsshim v0.7.12
|
||||
github.com/Microsoft/hcsshim v0.8.2
|
||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||
github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
|
||||
@ -81,9 +81,9 @@ k8s.io/kubernetes v1.12.0
|
||||
k8s.io/utils cd34563cd63c2bd7c6fe88a73c4dcf34ed8a67cb
|
||||
|
||||
# zfs dependencies
|
||||
github.com/containerd/zfs 9a0b8b8b5982014b729cd34eb7cd7a11062aa6ec
|
||||
github.com/containerd/zfs 9f6ef3b1fe5144bd91fe5855b4eba81bc0d17d03
|
||||
github.com/mistifyio/go-zfs 166add352731e515512690329794ee593f1aaff2
|
||||
github.com/pborman/uuid c65b2f87fee37d1c7854c9164a450713c28d50cd
|
||||
|
||||
# aufs dependencies
|
||||
github.com/containerd/aufs ffa39970e26ad01d81f540b21e65f9c1841a5f92
|
||||
github.com/containerd/aufs da3cf16bfbe68ba8f114f1536a05c01528a25434
|
||||
|
5
vendor/github.com/opencontainers/runc/README.md
generated
vendored
5
vendor/github.com/opencontainers/runc/README.md
generated
vendored
@ -68,6 +68,7 @@ make BUILDTAGS='seccomp apparmor'
|
||||
| selinux | selinux process and mount labeling | <none> |
|
||||
| apparmor | apparmor profile support | <none> |
|
||||
| ambient | ambient capability support | kernel 4.3 |
|
||||
| nokmem | disable kernel memory account | <none> |
|
||||
|
||||
|
||||
### Running the test suite
|
||||
@ -263,3 +264,7 @@ PIDFile=/run/mycontainerid.pid
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
The code and docs are released under the [Apache 2.0 license](LICENSE).
|
||||
|
8
vendor/github.com/opencontainers/runc/libcontainer/README.md
generated
vendored
8
vendor/github.com/opencontainers/runc/libcontainer/README.md
generated
vendored
@ -148,6 +148,7 @@ config := &configs.Config{
|
||||
{Type: configs.NEWPID},
|
||||
{Type: configs.NEWUSER},
|
||||
{Type: configs.NEWNET},
|
||||
{Type: configs.NEWCGROUP},
|
||||
}),
|
||||
Cgroups: &configs.Cgroup{
|
||||
Name: "test-container",
|
||||
@ -323,6 +324,7 @@ generated when building libcontainer with docker.
|
||||
|
||||
## Copyright and license
|
||||
|
||||
Code and documentation copyright 2014 Docker, inc. Code released under the Apache 2.0 license.
|
||||
Docs released under Creative commons.
|
||||
|
||||
Code and documentation copyright 2014 Docker, inc.
|
||||
The code and documentation are released under the [Apache 2.0 license](../LICENSE).
|
||||
The documentation is also released under Creative Commons Attribution 4.0 International License.
|
||||
You may obtain a copy of the license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.
|
||||
|
13
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
13
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
@ -272,26 +272,23 @@ func (hooks Hooks) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
// HookState is the payload provided to a hook on execution.
|
||||
type HookState specs.State
|
||||
|
||||
type Hook interface {
|
||||
// Run executes the hook with the provided state.
|
||||
Run(HookState) error
|
||||
Run(*specs.State) error
|
||||
}
|
||||
|
||||
// NewFunctionHook will call the provided function when the hook is run.
|
||||
func NewFunctionHook(f func(HookState) error) FuncHook {
|
||||
func NewFunctionHook(f func(*specs.State) error) FuncHook {
|
||||
return FuncHook{
|
||||
run: f,
|
||||
}
|
||||
}
|
||||
|
||||
type FuncHook struct {
|
||||
run func(HookState) error
|
||||
run func(*specs.State) error
|
||||
}
|
||||
|
||||
func (f FuncHook) Run(s HookState) error {
|
||||
func (f FuncHook) Run(s *specs.State) error {
|
||||
return f.run(s)
|
||||
}
|
||||
|
||||
@ -314,7 +311,7 @@ type CommandHook struct {
|
||||
Command
|
||||
}
|
||||
|
||||
func (c Command) Run(s HookState) error {
|
||||
func (c Command) Run(s *specs.State) error {
|
||||
b, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
return err
|
||||
|
4
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_linux.go
generated
vendored
4
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_linux.go
generated
vendored
@ -13,6 +13,7 @@ const (
|
||||
NEWUTS NamespaceType = "NEWUTS"
|
||||
NEWIPC NamespaceType = "NEWIPC"
|
||||
NEWUSER NamespaceType = "NEWUSER"
|
||||
NEWCGROUP NamespaceType = "NEWCGROUP"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -35,6 +36,8 @@ func NsName(ns NamespaceType) string {
|
||||
return "user"
|
||||
case NEWUTS:
|
||||
return "uts"
|
||||
case NEWCGROUP:
|
||||
return "cgroup"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@ -68,6 +71,7 @@ func NamespaceTypes() []NamespaceType {
|
||||
NEWNET,
|
||||
NEWPID,
|
||||
NEWNS,
|
||||
NEWCGROUP,
|
||||
}
|
||||
}
|
||||
|
||||
|
1
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
generated
vendored
1
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
generated
vendored
@ -15,6 +15,7 @@ var namespaceInfo = map[NamespaceType]int{
|
||||
NEWIPC: unix.CLONE_NEWIPC,
|
||||
NEWUTS: unix.CLONE_NEWUTS,
|
||||
NEWPID: unix.CLONE_NEWPID,
|
||||
NEWCGROUP: unix.CLONE_NEWCGROUP,
|
||||
}
|
||||
|
||||
// CloneFlags parses the container's Namespaces options to set the correct
|
||||
|
63
vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
generated
vendored
63
vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
generated
vendored
@ -42,6 +42,12 @@ enum sync_t {
|
||||
SYNC_ERR = 0xFF, /* Fatal error, no turning back. The error code follows. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Synchronisation value for cgroup namespace setup.
|
||||
* The same constant is defined in process_linux.go as "createCgroupns".
|
||||
*/
|
||||
#define CREATECGROUPNS 0x80
|
||||
|
||||
/* longjmp() arguments. */
|
||||
#define JUMP_PARENT 0x00
|
||||
#define JUMP_CHILD 0xA0
|
||||
@ -640,7 +646,6 @@ void nsexec(void)
|
||||
case JUMP_PARENT:{
|
||||
int len;
|
||||
pid_t child, first_child = -1;
|
||||
char buf[JSON_MAX];
|
||||
bool ready = false;
|
||||
|
||||
/* For debugging. */
|
||||
@ -716,6 +721,18 @@ void nsexec(void)
|
||||
kill(child, SIGKILL);
|
||||
bail("failed to sync with child: write(SYNC_RECVPID_ACK)");
|
||||
}
|
||||
|
||||
/* Send the init_func pid back to our parent.
|
||||
*
|
||||
* Send the init_func pid and the pid of the first child back to our parent.
|
||||
* We need to send both back because we can't reap the first child we created (CLONE_PARENT).
|
||||
* It becomes the responsibility of our parent to reap the first child.
|
||||
*/
|
||||
len = dprintf(pipenum, "{\"pid\": %d, \"pid_first\": %d}\n", child, first_child);
|
||||
if (len < 0) {
|
||||
kill(child, SIGKILL);
|
||||
bail("unable to generate JSON for child pid");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SYNC_CHILD_READY:
|
||||
@ -759,23 +776,6 @@ void nsexec(void)
|
||||
bail("unexpected sync value: %u", s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the init_func pid and the pid of the first child back to our parent.
|
||||
*
|
||||
* We need to send both back because we can't reap the first child we created (CLONE_PARENT).
|
||||
* It becomes the responsibility of our parent to reap the first child.
|
||||
*/
|
||||
len = snprintf(buf, JSON_MAX, "{\"pid\": %d, \"pid_first\": %d}\n", child, first_child);
|
||||
if (len < 0) {
|
||||
kill(child, SIGKILL);
|
||||
bail("unable to generate JSON for child pid");
|
||||
}
|
||||
if (write(pipenum, buf, len) != len) {
|
||||
kill(child, SIGKILL);
|
||||
bail("unable to send child pid to bootstrapper");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -862,14 +862,17 @@ void nsexec(void)
|
||||
if (setresuid(0, 0, 0) < 0)
|
||||
bail("failed to become root in user namespace");
|
||||
}
|
||||
|
||||
/*
|
||||
* Unshare all of the namespaces. Note that we don't merge this
|
||||
* with clone() because there were some old kernel versions where
|
||||
* clone(CLONE_PARENT | CLONE_NEWPID) was broken, so we'll just do
|
||||
* it the long way.
|
||||
* Unshare all of the namespaces. Now, it should be noted that this
|
||||
* ordering might break in the future (especially with rootless
|
||||
* containers). But for now, it's not possible to split this into
|
||||
* CLONE_NEWUSER + [the rest] because of some RHEL SELinux issues.
|
||||
*
|
||||
* Note that we don't merge this with clone() because there were
|
||||
* some old kernel versions where clone(CLONE_PARENT | CLONE_NEWPID)
|
||||
* was broken, so we'll just do it the long way anyway.
|
||||
*/
|
||||
if (unshare(config.cloneflags) < 0)
|
||||
if (unshare(config.cloneflags & ~CLONE_NEWCGROUP) < 0)
|
||||
bail("failed to unshare namespaces");
|
||||
|
||||
/*
|
||||
@ -958,6 +961,18 @@ void nsexec(void)
|
||||
bail("setgroups failed");
|
||||
}
|
||||
|
||||
/* ... wait until our topmost parent has finished cgroup setup in p.manager.Apply() ... */
|
||||
if (config.cloneflags & CLONE_NEWCGROUP) {
|
||||
uint8_t value;
|
||||
if (read(pipenum, &value, sizeof(value)) != sizeof(value))
|
||||
bail("read synchronisation value failed");
|
||||
if (value == CREATECGROUPNS) {
|
||||
if (unshare(CLONE_NEWCGROUP) < 0)
|
||||
bail("failed to unshare cgroup namespace");
|
||||
} else
|
||||
bail("received unknown synchronisation value");
|
||||
}
|
||||
|
||||
s = SYNC_CHILD_READY;
|
||||
if (write(syncfd, &s, sizeof(s)) != sizeof(s))
|
||||
bail("failed to sync with patent: write(SYNC_CHILD_READY)");
|
||||
|
32
vendor/github.com/sirupsen/logrus/README.md
generated
vendored
32
vendor/github.com/sirupsen/logrus/README.md
generated
vendored
@ -1,22 +1,24 @@
|
||||
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [](https://travis-ci.org/sirupsen/logrus) [](https://godoc.org/github.com/sirupsen/logrus)
|
||||
|
||||
Logrus is a structured logger for Go (golang), completely API compatible with
|
||||
the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
|
||||
yet stable (pre 1.0). Logrus itself is completely stable and has been used in
|
||||
many large deployments. The core API is unlikely to change much but please
|
||||
version control your Logrus to make sure you aren't fetching latest `master` on
|
||||
every build.**
|
||||
the standard library logger.
|
||||
|
||||
**Seeing weird case-sensitive problems?** Unfortunately, the author failed to
|
||||
realize the consequences of renaming to lower-case. Due to the Go package
|
||||
environment, this caused issues. Regretfully, there's no turning back now.
|
||||
**Seeing weird case-sensitive problems?** It's in the past been possible to
|
||||
import Logrus as both upper- and lower-case. Due to the Go package environment,
|
||||
this caused issues in the community and we needed a standard. Some environments
|
||||
experienced problems with the upper-case variant, so the lower-case was decided.
|
||||
Everything using `logrus` will need to use the lower-case:
|
||||
`github.com/sirupsen/logrus`. Any package that isn't, should be changed.
|
||||
|
||||
I am terribly sorry for this inconvenience. Logrus strives hard for backwards
|
||||
compatibility, and the author failed to realize the cascading consequences of
|
||||
such a name-change. To fix Glide, see [these
|
||||
To fix Glide, see [these
|
||||
comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437).
|
||||
For an in-depth explanation of the casing issue, see [this
|
||||
comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276).
|
||||
|
||||
**Are you interested in assisting in maintaining Logrus?** Currently I have a
|
||||
lot of obligations, and I am unable to provide Logrus with the maintainership it
|
||||
needs. If you'd like to help, please reach out to me at `simon at author's
|
||||
username dot com`.
|
||||
|
||||
Nicely color-coded in development (when a TTY is attached, otherwise just
|
||||
plain text):
|
||||
@ -266,6 +268,7 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
|
||||
| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
|
||||
| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
|
||||
| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
|
||||
| [Mattermost](https://github.com/shuLhan/mattermost-integration/tree/master/hooks/logrus) | Hook for logging to [Mattermost](https://mattermost.com/) |
|
||||
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
|
||||
| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) |
|
||||
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
|
||||
@ -280,7 +283,7 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
|
||||
| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
|
||||
| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) |
|
||||
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
|
||||
| [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
|
||||
| [Syslog](https://github.com/sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
|
||||
| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. |
|
||||
| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) |
|
||||
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
|
||||
@ -369,6 +372,7 @@ The built-in logging formatters are:
|
||||
|
||||
Third party logging formatters:
|
||||
|
||||
* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can by parsed by Kubernetes and Google Container Engine.
|
||||
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
|
||||
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
|
||||
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
|
||||
@ -449,13 +453,13 @@ Logrus has a built in facility for asserting the presence of log messages. This
|
||||
```go
|
||||
import(
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus/hooks/null"
|
||||
"github.com/sirupsen/logrus/hooks/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSomething(t*testing.T){
|
||||
logger, hook := null.NewNullLogger()
|
||||
logger, hook := test.NewNullLogger()
|
||||
logger.Error("Helloerror")
|
||||
|
||||
assert.Equal(t, 1, len(hook.Entries))
|
||||
|
1
vendor/github.com/sirupsen/logrus/entry.go
generated
vendored
1
vendor/github.com/sirupsen/logrus/entry.go
generated
vendored
@ -35,6 +35,7 @@ type Entry struct {
|
||||
Time time.Time
|
||||
|
||||
// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
|
||||
// This field will be set on entry firing and the value will be equal to the one in Logger struct field.
|
||||
Level Level
|
||||
|
||||
// Message passed to Debug, Info, Warn, Error, Fatal or Panic
|
||||
|
2
vendor/github.com/sirupsen/logrus/exported.go
generated
vendored
2
vendor/github.com/sirupsen/logrus/exported.go
generated
vendored
@ -31,7 +31,7 @@ func SetFormatter(formatter Formatter) {
|
||||
func SetLevel(level Level) {
|
||||
std.mu.Lock()
|
||||
defer std.mu.Unlock()
|
||||
std.setLevel(level)
|
||||
std.SetLevel(level)
|
||||
}
|
||||
|
||||
// GetLevel returns the standard logger level.
|
||||
|
2
vendor/github.com/sirupsen/logrus/formatter.go
generated
vendored
2
vendor/github.com/sirupsen/logrus/formatter.go
generated
vendored
@ -2,7 +2,7 @@ package logrus
|
||||
|
||||
import "time"
|
||||
|
||||
const DefaultTimestampFormat = time.RFC3339
|
||||
const defaultTimestampFormat = time.RFC3339
|
||||
|
||||
// The Formatter interface is used to implement a custom Formatter. It takes an
|
||||
// `Entry`. It exposes all the fields, including the default ones:
|
||||
|
9
vendor/github.com/sirupsen/logrus/json_formatter.go
generated
vendored
9
vendor/github.com/sirupsen/logrus/json_formatter.go
generated
vendored
@ -6,8 +6,11 @@ import (
|
||||
)
|
||||
|
||||
type fieldKey string
|
||||
|
||||
// FieldMap allows customization of the key names for default fields.
|
||||
type FieldMap map[fieldKey]string
|
||||
|
||||
// Default key names for the default fields
|
||||
const (
|
||||
FieldKeyMsg = "msg"
|
||||
FieldKeyLevel = "level"
|
||||
@ -22,6 +25,7 @@ func (f FieldMap) resolve(key fieldKey) string {
|
||||
return string(key)
|
||||
}
|
||||
|
||||
// JSONFormatter formats logs into parsable json
|
||||
type JSONFormatter struct {
|
||||
// TimestampFormat sets the format used for marshaling timestamps.
|
||||
TimestampFormat string
|
||||
@ -29,7 +33,7 @@ type JSONFormatter struct {
|
||||
// DisableTimestamp allows disabling automatic timestamps in output
|
||||
DisableTimestamp bool
|
||||
|
||||
// FieldMap allows users to customize the names of keys for various fields.
|
||||
// FieldMap allows users to customize the names of keys for default fields.
|
||||
// As an example:
|
||||
// formatter := &JSONFormatter{
|
||||
// FieldMap: FieldMap{
|
||||
@ -41,6 +45,7 @@ type JSONFormatter struct {
|
||||
FieldMap FieldMap
|
||||
}
|
||||
|
||||
// Format renders a single log entry
|
||||
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
||||
data := make(Fields, len(entry.Data)+3)
|
||||
for k, v := range entry.Data {
|
||||
@ -57,7 +62,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
||||
|
||||
timestampFormat := f.TimestampFormat
|
||||
if timestampFormat == "" {
|
||||
timestampFormat = DefaultTimestampFormat
|
||||
timestampFormat = defaultTimestampFormat
|
||||
}
|
||||
|
||||
if !f.DisableTimestamp {
|
||||
|
4
vendor/github.com/sirupsen/logrus/logger.go
generated
vendored
4
vendor/github.com/sirupsen/logrus/logger.go
generated
vendored
@ -25,7 +25,7 @@ type Logger struct {
|
||||
Formatter Formatter
|
||||
// The logging level the logger should log at. This is typically (and defaults
|
||||
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
|
||||
// logged. `logrus.Debug` is useful in
|
||||
// logged.
|
||||
Level Level
|
||||
// Used to sync writing to the log. Locking is enabled by Default
|
||||
mu MutexWrap
|
||||
@ -312,6 +312,6 @@ func (logger *Logger) level() Level {
|
||||
return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
|
||||
}
|
||||
|
||||
func (logger *Logger) setLevel(level Level) {
|
||||
func (logger *Logger) SetLevel(level Level) {
|
||||
atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
|
||||
}
|
||||
|
10
vendor/github.com/sirupsen/logrus/terminal_appengine.go
generated
vendored
10
vendor/github.com/sirupsen/logrus/terminal_appengine.go
generated
vendored
@ -1,10 +0,0 @@
|
||||
// +build appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import "io"
|
||||
|
||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
||||
func IsTerminal(f io.Writer) bool {
|
||||
return true
|
||||
}
|
6
vendor/github.com/sirupsen/logrus/terminal_bsd.go
generated
vendored
6
vendor/github.com/sirupsen/logrus/terminal_bsd.go
generated
vendored
@ -3,8 +3,8 @@
|
||||
|
||||
package logrus
|
||||
|
||||
import "syscall"
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
const ioctlReadTermios = syscall.TIOCGETA
|
||||
const ioctlReadTermios = unix.TIOCGETA
|
||||
|
||||
type Termios syscall.Termios
|
||||
type Termios unix.Termios
|
||||
|
6
vendor/github.com/sirupsen/logrus/terminal_linux.go
generated
vendored
6
vendor/github.com/sirupsen/logrus/terminal_linux.go
generated
vendored
@ -7,8 +7,8 @@
|
||||
|
||||
package logrus
|
||||
|
||||
import "syscall"
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
const ioctlReadTermios = syscall.TCGETS
|
||||
const ioctlReadTermios = unix.TCGETS
|
||||
|
||||
type Termios syscall.Termios
|
||||
type Termios unix.Termios
|
||||
|
28
vendor/github.com/sirupsen/logrus/terminal_notwindows.go
generated
vendored
28
vendor/github.com/sirupsen/logrus/terminal_notwindows.go
generated
vendored
@ -1,28 +0,0 @@
|
||||
// Based on ssh/terminal:
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
||||
func IsTerminal(f io.Writer) bool {
|
||||
var termios Termios
|
||||
switch v := f.(type) {
|
||||
case *os.File:
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(v.Fd()), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
||||
return err == 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
21
vendor/github.com/sirupsen/logrus/terminal_solaris.go
generated
vendored
21
vendor/github.com/sirupsen/logrus/terminal_solaris.go
generated
vendored
@ -1,21 +0,0 @@
|
||||
// +build solaris,!appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||
func IsTerminal(f io.Writer) bool {
|
||||
switch v := f.(type) {
|
||||
case *os.File:
|
||||
_, err := unix.IoctlGetTermios(int(v.Fd()), unix.TCGETA)
|
||||
return err == nil
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
82
vendor/github.com/sirupsen/logrus/terminal_windows.go
generated
vendored
82
vendor/github.com/sirupsen/logrus/terminal_windows.go
generated
vendored
@ -1,82 +0,0 @@
|
||||
// Based on ssh/terminal:
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows,!appengine
|
||||
|
||||
package logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
var (
|
||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
|
||||
)
|
||||
|
||||
const (
|
||||
enableProcessedOutput = 0x0001
|
||||
enableWrapAtEolOutput = 0x0002
|
||||
enableVirtualTerminalProcessing = 0x0004
|
||||
)
|
||||
|
||||
func getVersion() (float64, error) {
|
||||
stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{}
|
||||
cmd := exec.Command("cmd", "ver")
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
// The output should be like "Microsoft Windows [Version XX.X.XXXXXX]"
|
||||
version := strings.Replace(stdout.String(), "\n", "", -1)
|
||||
version = strings.Replace(version, "\r\n", "", -1)
|
||||
|
||||
x1 := strings.Index(version, "[Version")
|
||||
|
||||
if x1 == -1 || strings.Index(version, "]") == -1 {
|
||||
return -1, errors.New("Can't determine Windows version")
|
||||
}
|
||||
|
||||
return strconv.ParseFloat(version[x1+9:x1+13], 64)
|
||||
}
|
||||
|
||||
func init() {
|
||||
ver, err := getVersion()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Activate Virtual Processing for Windows CMD
|
||||
// Info: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
|
||||
if ver >= 10 {
|
||||
handle := syscall.Handle(os.Stderr.Fd())
|
||||
procSetConsoleMode.Call(uintptr(handle), enableProcessedOutput|enableWrapAtEolOutput|enableVirtualTerminalProcessing)
|
||||
}
|
||||
}
|
||||
|
||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
||||
func IsTerminal(f io.Writer) bool {
|
||||
switch v := f.(type) {
|
||||
case *os.File:
|
||||
var st uint32
|
||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(v.Fd()), uintptr(unsafe.Pointer(&st)), 0)
|
||||
return r != 0 && e == 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
56
vendor/github.com/sirupsen/logrus/text_formatter.go
generated
vendored
56
vendor/github.com/sirupsen/logrus/text_formatter.go
generated
vendored
@ -3,10 +3,14 @@ package logrus
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -14,7 +18,7 @@ const (
|
||||
red = 31
|
||||
green = 32
|
||||
yellow = 33
|
||||
blue = 34
|
||||
blue = 36
|
||||
gray = 37
|
||||
)
|
||||
|
||||
@ -26,6 +30,7 @@ func init() {
|
||||
baseTimestamp = time.Now()
|
||||
}
|
||||
|
||||
// TextFormatter formats logs into text
|
||||
type TextFormatter struct {
|
||||
// Set to true to bypass checking for a TTY before outputting colors.
|
||||
ForceColors bool
|
||||
@ -52,10 +57,6 @@ type TextFormatter struct {
|
||||
// QuoteEmptyFields will wrap empty fields in quotes if true
|
||||
QuoteEmptyFields bool
|
||||
|
||||
// QuoteCharacter can be set to the override the default quoting character "
|
||||
// with something else. For example: ', or `.
|
||||
QuoteCharacter string
|
||||
|
||||
// Whether the logger's out is to a terminal
|
||||
isTerminal bool
|
||||
|
||||
@ -63,14 +64,21 @@ type TextFormatter struct {
|
||||
}
|
||||
|
||||
func (f *TextFormatter) init(entry *Entry) {
|
||||
if len(f.QuoteCharacter) == 0 {
|
||||
f.QuoteCharacter = "\""
|
||||
}
|
||||
if entry.Logger != nil {
|
||||
f.isTerminal = IsTerminal(entry.Logger.Out)
|
||||
f.isTerminal = f.checkIfTerminal(entry.Logger.Out)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *TextFormatter) checkIfTerminal(w io.Writer) bool {
|
||||
switch v := w.(type) {
|
||||
case *os.File:
|
||||
return terminal.IsTerminal(int(v.Fd()))
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Format renders a single log entry
|
||||
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
||||
var b *bytes.Buffer
|
||||
keys := make([]string, 0, len(entry.Data))
|
||||
@ -95,7 +103,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
||||
|
||||
timestampFormat := f.TimestampFormat
|
||||
if timestampFormat == "" {
|
||||
timestampFormat = DefaultTimestampFormat
|
||||
timestampFormat = defaultTimestampFormat
|
||||
}
|
||||
if isColored {
|
||||
f.printColored(b, entry, keys, timestampFormat)
|
||||
@ -153,7 +161,7 @@ func (f *TextFormatter) needsQuoting(text string) bool {
|
||||
if !((ch >= 'a' && ch <= 'z') ||
|
||||
(ch >= 'A' && ch <= 'Z') ||
|
||||
(ch >= '0' && ch <= '9') ||
|
||||
ch == '-' || ch == '.') {
|
||||
ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -161,29 +169,23 @@ func (f *TextFormatter) needsQuoting(text string) bool {
|
||||
}
|
||||
|
||||
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
|
||||
|
||||
if b.Len() > 0 {
|
||||
b.WriteByte(' ')
|
||||
}
|
||||
b.WriteString(key)
|
||||
b.WriteByte('=')
|
||||
f.appendValue(b, value)
|
||||
b.WriteByte(' ')
|
||||
}
|
||||
|
||||
func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
if !f.needsQuoting(value) {
|
||||
b.WriteString(value)
|
||||
} else {
|
||||
fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, value, f.QuoteCharacter)
|
||||
stringVal, ok := value.(string)
|
||||
if !ok {
|
||||
stringVal = fmt.Sprint(value)
|
||||
}
|
||||
case error:
|
||||
errmsg := value.Error()
|
||||
if !f.needsQuoting(errmsg) {
|
||||
b.WriteString(errmsg)
|
||||
|
||||
if !f.needsQuoting(stringVal) {
|
||||
b.WriteString(stringVal)
|
||||
} else {
|
||||
fmt.Fprintf(b, "%s%v%s", f.QuoteCharacter, errmsg, f.QuoteCharacter)
|
||||
}
|
||||
default:
|
||||
fmt.Fprint(b, value)
|
||||
b.WriteString(fmt.Sprintf("%q", stringVal))
|
||||
}
|
||||
}
|
||||
|
198
vendor/golang.org/x/sys/windows/registry/key.go
generated
vendored
Normal file
198
vendor/golang.org/x/sys/windows/registry/key.go
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
// Package registry provides access to the Windows registry.
|
||||
//
|
||||
// Here is a simple example, opening a registry key and reading a string value from it.
|
||||
//
|
||||
// k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
// defer k.Close()
|
||||
//
|
||||
// s, _, err := k.GetStringValue("SystemRoot")
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
// fmt.Printf("Windows system root is %q\n", s)
|
||||
//
|
||||
package registry
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// Registry key security and access rights.
|
||||
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724878.aspx
|
||||
// for details.
|
||||
ALL_ACCESS = 0xf003f
|
||||
CREATE_LINK = 0x00020
|
||||
CREATE_SUB_KEY = 0x00004
|
||||
ENUMERATE_SUB_KEYS = 0x00008
|
||||
EXECUTE = 0x20019
|
||||
NOTIFY = 0x00010
|
||||
QUERY_VALUE = 0x00001
|
||||
READ = 0x20019
|
||||
SET_VALUE = 0x00002
|
||||
WOW64_32KEY = 0x00200
|
||||
WOW64_64KEY = 0x00100
|
||||
WRITE = 0x20006
|
||||
)
|
||||
|
||||
// Key is a handle to an open Windows registry key.
|
||||
// Keys can be obtained by calling OpenKey; there are
|
||||
// also some predefined root keys such as CURRENT_USER.
|
||||
// Keys can be used directly in the Windows API.
|
||||
type Key syscall.Handle
|
||||
|
||||
const (
|
||||
// Windows defines some predefined root keys that are always open.
|
||||
// An application can use these keys as entry points to the registry.
|
||||
// Normally these keys are used in OpenKey to open new keys,
|
||||
// but they can also be used anywhere a Key is required.
|
||||
CLASSES_ROOT = Key(syscall.HKEY_CLASSES_ROOT)
|
||||
CURRENT_USER = Key(syscall.HKEY_CURRENT_USER)
|
||||
LOCAL_MACHINE = Key(syscall.HKEY_LOCAL_MACHINE)
|
||||
USERS = Key(syscall.HKEY_USERS)
|
||||
CURRENT_CONFIG = Key(syscall.HKEY_CURRENT_CONFIG)
|
||||
PERFORMANCE_DATA = Key(syscall.HKEY_PERFORMANCE_DATA)
|
||||
)
|
||||
|
||||
// Close closes open key k.
|
||||
func (k Key) Close() error {
|
||||
return syscall.RegCloseKey(syscall.Handle(k))
|
||||
}
|
||||
|
||||
// OpenKey opens a new key with path name relative to key k.
|
||||
// It accepts any open key, including CURRENT_USER and others,
|
||||
// and returns the new key and an error.
|
||||
// The access parameter specifies desired access rights to the
|
||||
// key to be opened.
|
||||
func OpenKey(k Key, path string, access uint32) (Key, error) {
|
||||
p, err := syscall.UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var subkey syscall.Handle
|
||||
err = syscall.RegOpenKeyEx(syscall.Handle(k), p, 0, access, &subkey)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return Key(subkey), nil
|
||||
}
|
||||
|
||||
// OpenRemoteKey opens a predefined registry key on another
|
||||
// computer pcname. The key to be opened is specified by k, but
|
||||
// can only be one of LOCAL_MACHINE, PERFORMANCE_DATA or USERS.
|
||||
// If pcname is "", OpenRemoteKey returns local computer key.
|
||||
func OpenRemoteKey(pcname string, k Key) (Key, error) {
|
||||
var err error
|
||||
var p *uint16
|
||||
if pcname != "" {
|
||||
p, err = syscall.UTF16PtrFromString(`\\` + pcname)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
var remoteKey syscall.Handle
|
||||
err = regConnectRegistry(p, syscall.Handle(k), &remoteKey)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return Key(remoteKey), nil
|
||||
}
|
||||
|
||||
// ReadSubKeyNames returns the names of subkeys of key k.
|
||||
// The parameter n controls the number of returned names,
|
||||
// analogous to the way os.File.Readdirnames works.
|
||||
func (k Key) ReadSubKeyNames(n int) ([]string, error) {
|
||||
names := make([]string, 0)
|
||||
// Registry key size limit is 255 bytes and described there:
|
||||
// https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx
|
||||
buf := make([]uint16, 256) //plus extra room for terminating zero byte
|
||||
loopItems:
|
||||
for i := uint32(0); ; i++ {
|
||||
if n > 0 {
|
||||
if len(names) == n {
|
||||
return names, nil
|
||||
}
|
||||
}
|
||||
l := uint32(len(buf))
|
||||
for {
|
||||
err := syscall.RegEnumKeyEx(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if err == syscall.ERROR_MORE_DATA {
|
||||
// Double buffer size and try again.
|
||||
l = uint32(2 * len(buf))
|
||||
buf = make([]uint16, l)
|
||||
continue
|
||||
}
|
||||
if err == _ERROR_NO_MORE_ITEMS {
|
||||
break loopItems
|
||||
}
|
||||
return names, err
|
||||
}
|
||||
names = append(names, syscall.UTF16ToString(buf[:l]))
|
||||
}
|
||||
if n > len(names) {
|
||||
return names, io.EOF
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// CreateKey creates a key named path under open key k.
|
||||
// CreateKey returns the new key and a boolean flag that reports
|
||||
// whether the key already existed.
|
||||
// The access parameter specifies the access rights for the key
|
||||
// to be created.
|
||||
func CreateKey(k Key, path string, access uint32) (newk Key, openedExisting bool, err error) {
|
||||
var h syscall.Handle
|
||||
var d uint32
|
||||
err = regCreateKeyEx(syscall.Handle(k), syscall.StringToUTF16Ptr(path),
|
||||
0, nil, _REG_OPTION_NON_VOLATILE, access, nil, &h, &d)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
return Key(h), d == _REG_OPENED_EXISTING_KEY, nil
|
||||
}
|
||||
|
||||
// DeleteKey deletes the subkey path of key k and its values.
|
||||
func DeleteKey(k Key, path string) error {
|
||||
return regDeleteKey(syscall.Handle(k), syscall.StringToUTF16Ptr(path))
|
||||
}
|
||||
|
||||
// A KeyInfo describes the statistics of a key. It is returned by Stat.
|
||||
type KeyInfo struct {
|
||||
SubKeyCount uint32
|
||||
MaxSubKeyLen uint32 // size of the key's subkey with the longest name, in Unicode characters, not including the terminating zero byte
|
||||
ValueCount uint32
|
||||
MaxValueNameLen uint32 // size of the key's longest value name, in Unicode characters, not including the terminating zero byte
|
||||
MaxValueLen uint32 // longest data component among the key's values, in bytes
|
||||
lastWriteTime syscall.Filetime
|
||||
}
|
||||
|
||||
// ModTime returns the key's last write time.
|
||||
func (ki *KeyInfo) ModTime() time.Time {
|
||||
return time.Unix(0, ki.lastWriteTime.Nanoseconds())
|
||||
}
|
||||
|
||||
// Stat retrieves information about the open key k.
|
||||
func (k Key) Stat() (*KeyInfo, error) {
|
||||
var ki KeyInfo
|
||||
err := syscall.RegQueryInfoKey(syscall.Handle(k), nil, nil, nil,
|
||||
&ki.SubKeyCount, &ki.MaxSubKeyLen, nil, &ki.ValueCount,
|
||||
&ki.MaxValueNameLen, &ki.MaxValueLen, nil, &ki.lastWriteTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ki, nil
|
||||
}
|
7
vendor/golang.org/x/sys/windows/registry/mksyscall.go
generated
vendored
Normal file
7
vendor/golang.org/x/sys/windows/registry/mksyscall.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package registry
|
||||
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
|
32
vendor/golang.org/x/sys/windows/registry/syscall.go
generated
vendored
Normal file
32
vendor/golang.org/x/sys/windows/registry/syscall.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package registry
|
||||
|
||||
import "syscall"
|
||||
|
||||
const (
|
||||
_REG_OPTION_NON_VOLATILE = 0
|
||||
|
||||
_REG_CREATED_NEW_KEY = 1
|
||||
_REG_OPENED_EXISTING_KEY = 2
|
||||
|
||||
_ERROR_NO_MORE_ITEMS syscall.Errno = 259
|
||||
)
|
||||
|
||||
func LoadRegLoadMUIString() error {
|
||||
return procRegLoadMUIStringW.Find()
|
||||
}
|
||||
|
||||
//sys regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) = advapi32.RegCreateKeyExW
|
||||
//sys regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) = advapi32.RegDeleteKeyW
|
||||
//sys regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) = advapi32.RegSetValueExW
|
||||
//sys regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegEnumValueW
|
||||
//sys regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) = advapi32.RegDeleteValueW
|
||||
//sys regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) = advapi32.RegLoadMUIStringW
|
||||
//sys regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) = advapi32.RegConnectRegistryW
|
||||
|
||||
//sys expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) = kernel32.ExpandEnvironmentStringsW
|
384
vendor/golang.org/x/sys/windows/registry/value.go
generated
vendored
Normal file
384
vendor/golang.org/x/sys/windows/registry/value.go
generated
vendored
Normal file
@ -0,0 +1,384 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package registry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Registry value types.
|
||||
NONE = 0
|
||||
SZ = 1
|
||||
EXPAND_SZ = 2
|
||||
BINARY = 3
|
||||
DWORD = 4
|
||||
DWORD_BIG_ENDIAN = 5
|
||||
LINK = 6
|
||||
MULTI_SZ = 7
|
||||
RESOURCE_LIST = 8
|
||||
FULL_RESOURCE_DESCRIPTOR = 9
|
||||
RESOURCE_REQUIREMENTS_LIST = 10
|
||||
QWORD = 11
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrShortBuffer is returned when the buffer was too short for the operation.
|
||||
ErrShortBuffer = syscall.ERROR_MORE_DATA
|
||||
|
||||
// ErrNotExist is returned when a registry key or value does not exist.
|
||||
ErrNotExist = syscall.ERROR_FILE_NOT_FOUND
|
||||
|
||||
// ErrUnexpectedType is returned by Get*Value when the value's type was unexpected.
|
||||
ErrUnexpectedType = errors.New("unexpected key value type")
|
||||
)
|
||||
|
||||
// GetValue retrieves the type and data for the specified value associated
|
||||
// with an open key k. It fills up buffer buf and returns the retrieved
|
||||
// byte count n. If buf is too small to fit the stored value it returns
|
||||
// ErrShortBuffer error along with the required buffer size n.
|
||||
// If no buffer is provided, it returns true and actual buffer size n.
|
||||
// If no buffer is provided, GetValue returns the value's type only.
|
||||
// If the value does not exist, the error returned is ErrNotExist.
|
||||
//
|
||||
// GetValue is a low level function. If value's type is known, use the appropriate
|
||||
// Get*Value function instead.
|
||||
func (k Key) GetValue(name string, buf []byte) (n int, valtype uint32, err error) {
|
||||
pname, err := syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
var pbuf *byte
|
||||
if len(buf) > 0 {
|
||||
pbuf = (*byte)(unsafe.Pointer(&buf[0]))
|
||||
}
|
||||
l := uint32(len(buf))
|
||||
err = syscall.RegQueryValueEx(syscall.Handle(k), pname, nil, &valtype, pbuf, &l)
|
||||
if err != nil {
|
||||
return int(l), valtype, err
|
||||
}
|
||||
return int(l), valtype, nil
|
||||
}
|
||||
|
||||
func (k Key) getValue(name string, buf []byte) (date []byte, valtype uint32, err error) {
|
||||
p, err := syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
var t uint32
|
||||
n := uint32(len(buf))
|
||||
for {
|
||||
err = syscall.RegQueryValueEx(syscall.Handle(k), p, nil, &t, (*byte)(unsafe.Pointer(&buf[0])), &n)
|
||||
if err == nil {
|
||||
return buf[:n], t, nil
|
||||
}
|
||||
if err != syscall.ERROR_MORE_DATA {
|
||||
return nil, 0, err
|
||||
}
|
||||
if n <= uint32(len(buf)) {
|
||||
return nil, 0, err
|
||||
}
|
||||
buf = make([]byte, n)
|
||||
}
|
||||
}
|
||||
|
||||
// GetStringValue retrieves the string value for the specified
|
||||
// value name associated with an open key k. It also returns the value's type.
|
||||
// If value does not exist, GetStringValue returns ErrNotExist.
|
||||
// If value is not SZ or EXPAND_SZ, it will return the correct value
|
||||
// type and ErrUnexpectedType.
|
||||
func (k Key) GetStringValue(name string) (val string, valtype uint32, err error) {
|
||||
data, typ, err2 := k.getValue(name, make([]byte, 64))
|
||||
if err2 != nil {
|
||||
return "", typ, err2
|
||||
}
|
||||
switch typ {
|
||||
case SZ, EXPAND_SZ:
|
||||
default:
|
||||
return "", typ, ErrUnexpectedType
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return "", typ, nil
|
||||
}
|
||||
u := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:]
|
||||
return syscall.UTF16ToString(u), typ, nil
|
||||
}
|
||||
|
||||
// GetMUIStringValue retrieves the localized string value for
|
||||
// the specified value name associated with an open key k.
|
||||
// If the value name doesn't exist or the localized string value
|
||||
// can't be resolved, GetMUIStringValue returns ErrNotExist.
|
||||
// GetMUIStringValue panics if the system doesn't support
|
||||
// regLoadMUIString; use LoadRegLoadMUIString to check if
|
||||
// regLoadMUIString is supported before calling this function.
|
||||
func (k Key) GetMUIStringValue(name string) (string, error) {
|
||||
pname, err := syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
buf := make([]uint16, 1024)
|
||||
var buflen uint32
|
||||
var pdir *uint16
|
||||
|
||||
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||
if err == syscall.ERROR_FILE_NOT_FOUND { // Try fallback path
|
||||
|
||||
// Try to resolve the string value using the system directory as
|
||||
// a DLL search path; this assumes the string value is of the form
|
||||
// @[path]\dllname,-strID but with no path given, e.g. @tzres.dll,-320.
|
||||
|
||||
// This approach works with tzres.dll but may have to be revised
|
||||
// in the future to allow callers to provide custom search paths.
|
||||
|
||||
var s string
|
||||
s, err = ExpandString("%SystemRoot%\\system32\\")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
pdir, err = syscall.UTF16PtrFromString(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||
}
|
||||
|
||||
for err == syscall.ERROR_MORE_DATA { // Grow buffer if needed
|
||||
if buflen <= uint32(len(buf)) {
|
||||
break // Buffer not growing, assume race; break
|
||||
}
|
||||
buf = make([]uint16, buflen)
|
||||
err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return syscall.UTF16ToString(buf), nil
|
||||
}
|
||||
|
||||
// ExpandString expands environment-variable strings and replaces
|
||||
// them with the values defined for the current user.
|
||||
// Use ExpandString to expand EXPAND_SZ strings.
|
||||
func ExpandString(value string) (string, error) {
|
||||
if value == "" {
|
||||
return "", nil
|
||||
}
|
||||
p, err := syscall.UTF16PtrFromString(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
r := make([]uint16, 100)
|
||||
for {
|
||||
n, err := expandEnvironmentStrings(p, &r[0], uint32(len(r)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if n <= uint32(len(r)) {
|
||||
u := (*[1 << 29]uint16)(unsafe.Pointer(&r[0]))[:]
|
||||
return syscall.UTF16ToString(u), nil
|
||||
}
|
||||
r = make([]uint16, n)
|
||||
}
|
||||
}
|
||||
|
||||
// GetStringsValue retrieves the []string value for the specified
|
||||
// value name associated with an open key k. It also returns the value's type.
|
||||
// If value does not exist, GetStringsValue returns ErrNotExist.
|
||||
// If value is not MULTI_SZ, it will return the correct value
|
||||
// type and ErrUnexpectedType.
|
||||
func (k Key) GetStringsValue(name string) (val []string, valtype uint32, err error) {
|
||||
data, typ, err2 := k.getValue(name, make([]byte, 64))
|
||||
if err2 != nil {
|
||||
return nil, typ, err2
|
||||
}
|
||||
if typ != MULTI_SZ {
|
||||
return nil, typ, ErrUnexpectedType
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return nil, typ, nil
|
||||
}
|
||||
p := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:len(data)/2]
|
||||
if len(p) == 0 {
|
||||
return nil, typ, nil
|
||||
}
|
||||
if p[len(p)-1] == 0 {
|
||||
p = p[:len(p)-1] // remove terminating null
|
||||
}
|
||||
val = make([]string, 0, 5)
|
||||
from := 0
|
||||
for i, c := range p {
|
||||
if c == 0 {
|
||||
val = append(val, string(utf16.Decode(p[from:i])))
|
||||
from = i + 1
|
||||
}
|
||||
}
|
||||
return val, typ, nil
|
||||
}
|
||||
|
||||
// GetIntegerValue retrieves the integer value for the specified
|
||||
// value name associated with an open key k. It also returns the value's type.
|
||||
// If value does not exist, GetIntegerValue returns ErrNotExist.
|
||||
// If value is not DWORD or QWORD, it will return the correct value
|
||||
// type and ErrUnexpectedType.
|
||||
func (k Key) GetIntegerValue(name string) (val uint64, valtype uint32, err error) {
|
||||
data, typ, err2 := k.getValue(name, make([]byte, 8))
|
||||
if err2 != nil {
|
||||
return 0, typ, err2
|
||||
}
|
||||
switch typ {
|
||||
case DWORD:
|
||||
if len(data) != 4 {
|
||||
return 0, typ, errors.New("DWORD value is not 4 bytes long")
|
||||
}
|
||||
return uint64(*(*uint32)(unsafe.Pointer(&data[0]))), DWORD, nil
|
||||
case QWORD:
|
||||
if len(data) != 8 {
|
||||
return 0, typ, errors.New("QWORD value is not 8 bytes long")
|
||||
}
|
||||
return uint64(*(*uint64)(unsafe.Pointer(&data[0]))), QWORD, nil
|
||||
default:
|
||||
return 0, typ, ErrUnexpectedType
|
||||
}
|
||||
}
|
||||
|
||||
// GetBinaryValue retrieves the binary value for the specified
|
||||
// value name associated with an open key k. It also returns the value's type.
|
||||
// If value does not exist, GetBinaryValue returns ErrNotExist.
|
||||
// If value is not BINARY, it will return the correct value
|
||||
// type and ErrUnexpectedType.
|
||||
func (k Key) GetBinaryValue(name string) (val []byte, valtype uint32, err error) {
|
||||
data, typ, err2 := k.getValue(name, make([]byte, 64))
|
||||
if err2 != nil {
|
||||
return nil, typ, err2
|
||||
}
|
||||
if typ != BINARY {
|
||||
return nil, typ, ErrUnexpectedType
|
||||
}
|
||||
return data, typ, nil
|
||||
}
|
||||
|
||||
func (k Key) setValue(name string, valtype uint32, data []byte) error {
|
||||
p, err := syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return regSetValueEx(syscall.Handle(k), p, 0, valtype, nil, 0)
|
||||
}
|
||||
return regSetValueEx(syscall.Handle(k), p, 0, valtype, &data[0], uint32(len(data)))
|
||||
}
|
||||
|
||||
// SetDWordValue sets the data and type of a name value
|
||||
// under key k to value and DWORD.
|
||||
func (k Key) SetDWordValue(name string, value uint32) error {
|
||||
return k.setValue(name, DWORD, (*[4]byte)(unsafe.Pointer(&value))[:])
|
||||
}
|
||||
|
||||
// SetQWordValue sets the data and type of a name value
|
||||
// under key k to value and QWORD.
|
||||
func (k Key) SetQWordValue(name string, value uint64) error {
|
||||
return k.setValue(name, QWORD, (*[8]byte)(unsafe.Pointer(&value))[:])
|
||||
}
|
||||
|
||||
func (k Key) setStringValue(name string, valtype uint32, value string) error {
|
||||
v, err := syscall.UTF16FromString(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||
return k.setValue(name, valtype, buf)
|
||||
}
|
||||
|
||||
// SetStringValue sets the data and type of a name value
|
||||
// under key k to value and SZ. The value must not contain a zero byte.
|
||||
func (k Key) SetStringValue(name, value string) error {
|
||||
return k.setStringValue(name, SZ, value)
|
||||
}
|
||||
|
||||
// SetExpandStringValue sets the data and type of a name value
|
||||
// under key k to value and EXPAND_SZ. The value must not contain a zero byte.
|
||||
func (k Key) SetExpandStringValue(name, value string) error {
|
||||
return k.setStringValue(name, EXPAND_SZ, value)
|
||||
}
|
||||
|
||||
// SetStringsValue sets the data and type of a name value
|
||||
// under key k to value and MULTI_SZ. The value strings
|
||||
// must not contain a zero byte.
|
||||
func (k Key) SetStringsValue(name string, value []string) error {
|
||||
ss := ""
|
||||
for _, s := range value {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == 0 {
|
||||
return errors.New("string cannot have 0 inside")
|
||||
}
|
||||
}
|
||||
ss += s + "\x00"
|
||||
}
|
||||
v := utf16.Encode([]rune(ss + "\x00"))
|
||||
buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
|
||||
return k.setValue(name, MULTI_SZ, buf)
|
||||
}
|
||||
|
||||
// SetBinaryValue sets the data and type of a name value
|
||||
// under key k to value and BINARY.
|
||||
func (k Key) SetBinaryValue(name string, value []byte) error {
|
||||
return k.setValue(name, BINARY, value)
|
||||
}
|
||||
|
||||
// DeleteValue removes a named value from the key k.
|
||||
func (k Key) DeleteValue(name string) error {
|
||||
return regDeleteValue(syscall.Handle(k), syscall.StringToUTF16Ptr(name))
|
||||
}
|
||||
|
||||
// ReadValueNames returns the value names of key k.
|
||||
// The parameter n controls the number of returned names,
|
||||
// analogous to the way os.File.Readdirnames works.
|
||||
func (k Key) ReadValueNames(n int) ([]string, error) {
|
||||
ki, err := k.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
names := make([]string, 0, ki.ValueCount)
|
||||
buf := make([]uint16, ki.MaxValueNameLen+1) // extra room for terminating null character
|
||||
loopItems:
|
||||
for i := uint32(0); ; i++ {
|
||||
if n > 0 {
|
||||
if len(names) == n {
|
||||
return names, nil
|
||||
}
|
||||
}
|
||||
l := uint32(len(buf))
|
||||
for {
|
||||
err := regEnumValue(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if err == syscall.ERROR_MORE_DATA {
|
||||
// Double buffer size and try again.
|
||||
l = uint32(2 * len(buf))
|
||||
buf = make([]uint16, l)
|
||||
continue
|
||||
}
|
||||
if err == _ERROR_NO_MORE_ITEMS {
|
||||
break loopItems
|
||||
}
|
||||
return names, err
|
||||
}
|
||||
names = append(names, syscall.UTF16ToString(buf[:l]))
|
||||
}
|
||||
if n > len(names) {
|
||||
return names, io.EOF
|
||||
}
|
||||
return names, nil
|
||||
}
|
120
vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go
generated
vendored
Normal file
120
vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
|
||||
package registry
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
// Do the interface allocations only once for common
|
||||
// Errno values.
|
||||
const (
|
||||
errnoERROR_IO_PENDING = 997
|
||||
)
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return nil
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
var (
|
||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
|
||||
procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW")
|
||||
procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW")
|
||||
procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW")
|
||||
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
||||
procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW")
|
||||
procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW")
|
||||
procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW")
|
||||
procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
|
||||
)
|
||||
|
||||
func regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) {
|
||||
r0, _, _ := syscall.Syscall9(procRegCreateKeyExW.Addr(), 9, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desired), uintptr(unsafe.Pointer(sa)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition)))
|
||||
if r0 != 0 {
|
||||
regerrno = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) {
|
||||
r0, _, _ := syscall.Syscall(procRegDeleteKeyW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(subkey)), 0)
|
||||
if r0 != 0 {
|
||||
regerrno = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) {
|
||||
r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize))
|
||||
if r0 != 0 {
|
||||
regerrno = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) {
|
||||
r0, _, _ := syscall.Syscall9(procRegEnumValueW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen)), 0)
|
||||
if r0 != 0 {
|
||||
regerrno = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) {
|
||||
r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0)
|
||||
if r0 != 0 {
|
||||
regerrno = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) {
|
||||
r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0)
|
||||
if r0 != 0 {
|
||||
regerrno = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) {
|
||||
r0, _, _ := syscall.Syscall(procRegConnectRegistryW.Addr(), 3, uintptr(unsafe.Pointer(machinename)), uintptr(key), uintptr(unsafe.Pointer(result)))
|
||||
if r0 != 0 {
|
||||
regerrno = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) {
|
||||
r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size))
|
||||
n = uint32(r0)
|
||||
if n == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
56
vendor/golang.org/x/sys/windows/svc/debug/log.go
generated
vendored
Normal file
56
vendor/golang.org/x/sys/windows/svc/debug/log.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package debug
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Log interface allows different log implementations to be used.
|
||||
type Log interface {
|
||||
Close() error
|
||||
Info(eid uint32, msg string) error
|
||||
Warning(eid uint32, msg string) error
|
||||
Error(eid uint32, msg string) error
|
||||
}
|
||||
|
||||
// ConsoleLog provides access to the console.
|
||||
type ConsoleLog struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// New creates new ConsoleLog.
|
||||
func New(source string) *ConsoleLog {
|
||||
return &ConsoleLog{Name: source}
|
||||
}
|
||||
|
||||
// Close closes console log l.
|
||||
func (l *ConsoleLog) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *ConsoleLog) report(kind string, eid uint32, msg string) error {
|
||||
s := l.Name + "." + kind + "(" + strconv.Itoa(int(eid)) + "): " + msg + "\n"
|
||||
_, err := os.Stdout.Write([]byte(s))
|
||||
return err
|
||||
}
|
||||
|
||||
// Info writes an information event msg with event id eid to the console l.
|
||||
func (l *ConsoleLog) Info(eid uint32, msg string) error {
|
||||
return l.report("info", eid, msg)
|
||||
}
|
||||
|
||||
// Warning writes an warning event msg with event id eid to the console l.
|
||||
func (l *ConsoleLog) Warning(eid uint32, msg string) error {
|
||||
return l.report("warn", eid, msg)
|
||||
}
|
||||
|
||||
// Error writes an error event msg with event id eid to the console l.
|
||||
func (l *ConsoleLog) Error(eid uint32, msg string) error {
|
||||
return l.report("error", eid, msg)
|
||||
}
|
45
vendor/golang.org/x/sys/windows/svc/debug/service.go
generated
vendored
Normal file
45
vendor/golang.org/x/sys/windows/svc/debug/service.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
// Package debug provides facilities to execute svc.Handler on console.
|
||||
//
|
||||
package debug
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows/svc"
|
||||
)
|
||||
|
||||
// Run executes service name by calling appropriate handler function.
|
||||
// The process is running on console, unlike real service. Use Ctrl+C to
|
||||
// send "Stop" command to your service.
|
||||
func Run(name string, handler svc.Handler) error {
|
||||
cmds := make(chan svc.ChangeRequest)
|
||||
changes := make(chan svc.Status)
|
||||
|
||||
sig := make(chan os.Signal)
|
||||
signal.Notify(sig)
|
||||
|
||||
go func() {
|
||||
status := svc.Status{State: svc.Stopped}
|
||||
for {
|
||||
select {
|
||||
case <-sig:
|
||||
cmds <- svc.ChangeRequest{Cmd: svc.Stop, CurrentStatus: status}
|
||||
case status = <-changes:
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
_, errno := handler.Execute([]string{name}, cmds, changes)
|
||||
if errno != 0 {
|
||||
return syscall.Errno(errno)
|
||||
}
|
||||
return nil
|
||||
}
|
80
vendor/golang.org/x/sys/windows/svc/eventlog/install.go
generated
vendored
Normal file
80
vendor/golang.org/x/sys/windows/svc/eventlog/install.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package eventlog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
const (
|
||||
// Log levels.
|
||||
Info = windows.EVENTLOG_INFORMATION_TYPE
|
||||
Warning = windows.EVENTLOG_WARNING_TYPE
|
||||
Error = windows.EVENTLOG_ERROR_TYPE
|
||||
)
|
||||
|
||||
const addKeyName = `SYSTEM\CurrentControlSet\Services\EventLog\Application`
|
||||
|
||||
// Install modifies PC registry to allow logging with an event source src.
|
||||
// It adds all required keys and values to the event log registry key.
|
||||
// Install uses msgFile as the event message file. If useExpandKey is true,
|
||||
// the event message file is installed as REG_EXPAND_SZ value,
|
||||
// otherwise as REG_SZ. Use bitwise of log.Error, log.Warning and
|
||||
// log.Info to specify events supported by the new event source.
|
||||
func Install(src, msgFile string, useExpandKey bool, eventsSupported uint32) error {
|
||||
appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.CREATE_SUB_KEY)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer appkey.Close()
|
||||
|
||||
sk, alreadyExist, err := registry.CreateKey(appkey, src, registry.SET_VALUE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer sk.Close()
|
||||
if alreadyExist {
|
||||
return errors.New(addKeyName + `\` + src + " registry key already exists")
|
||||
}
|
||||
|
||||
err = sk.SetDWordValue("CustomSource", 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if useExpandKey {
|
||||
err = sk.SetExpandStringValue("EventMessageFile", msgFile)
|
||||
} else {
|
||||
err = sk.SetStringValue("EventMessageFile", msgFile)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = sk.SetDWordValue("TypesSupported", eventsSupported)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InstallAsEventCreate is the same as Install, but uses
|
||||
// %SystemRoot%\System32\EventCreate.exe as the event message file.
|
||||
func InstallAsEventCreate(src string, eventsSupported uint32) error {
|
||||
return Install(src, "%SystemRoot%\\System32\\EventCreate.exe", true, eventsSupported)
|
||||
}
|
||||
|
||||
// Remove deletes all registry elements installed by the correspondent Install.
|
||||
func Remove(src string) error {
|
||||
appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.SET_VALUE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer appkey.Close()
|
||||
return registry.DeleteKey(appkey, src)
|
||||
}
|
70
vendor/golang.org/x/sys/windows/svc/eventlog/log.go
generated
vendored
Normal file
70
vendor/golang.org/x/sys/windows/svc/eventlog/log.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
// Package eventlog implements access to Windows event log.
|
||||
//
|
||||
package eventlog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// Log provides access to the system log.
|
||||
type Log struct {
|
||||
Handle windows.Handle
|
||||
}
|
||||
|
||||
// Open retrieves a handle to the specified event log.
|
||||
func Open(source string) (*Log, error) {
|
||||
return OpenRemote("", source)
|
||||
}
|
||||
|
||||
// OpenRemote does the same as Open, but on different computer host.
|
||||
func OpenRemote(host, source string) (*Log, error) {
|
||||
if source == "" {
|
||||
return nil, errors.New("Specify event log source")
|
||||
}
|
||||
var s *uint16
|
||||
if host != "" {
|
||||
s = syscall.StringToUTF16Ptr(host)
|
||||
}
|
||||
h, err := windows.RegisterEventSource(s, syscall.StringToUTF16Ptr(source))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Log{Handle: h}, nil
|
||||
}
|
||||
|
||||
// Close closes event log l.
|
||||
func (l *Log) Close() error {
|
||||
return windows.DeregisterEventSource(l.Handle)
|
||||
}
|
||||
|
||||
func (l *Log) report(etype uint16, eid uint32, msg string) error {
|
||||
ss := []*uint16{syscall.StringToUTF16Ptr(msg)}
|
||||
return windows.ReportEvent(l.Handle, etype, 0, eid, 0, 1, 0, &ss[0], nil)
|
||||
}
|
||||
|
||||
// Info writes an information event msg with event id eid to the end of event log l.
|
||||
// When EventCreate.exe is used, eid must be between 1 and 1000.
|
||||
func (l *Log) Info(eid uint32, msg string) error {
|
||||
return l.report(windows.EVENTLOG_INFORMATION_TYPE, eid, msg)
|
||||
}
|
||||
|
||||
// Warning writes an warning event msg with event id eid to the end of event log l.
|
||||
// When EventCreate.exe is used, eid must be between 1 and 1000.
|
||||
func (l *Log) Warning(eid uint32, msg string) error {
|
||||
return l.report(windows.EVENTLOG_WARNING_TYPE, eid, msg)
|
||||
}
|
||||
|
||||
// Error writes an error event msg with event id eid to the end of event log l.
|
||||
// When EventCreate.exe is used, eid must be between 1 and 1000.
|
||||
func (l *Log) Error(eid uint32, msg string) error {
|
||||
return l.report(windows.EVENTLOG_ERROR_TYPE, eid, msg)
|
||||
}
|
145
vendor/golang.org/x/sys/windows/svc/mgr/config.go
generated
vendored
Normal file
145
vendor/golang.org/x/sys/windows/svc/mgr/config.go
generated
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package mgr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
// Service start types.
|
||||
StartManual = windows.SERVICE_DEMAND_START // the service must be started manually
|
||||
StartAutomatic = windows.SERVICE_AUTO_START // the service will start by itself whenever the computer reboots
|
||||
StartDisabled = windows.SERVICE_DISABLED // the service cannot be started
|
||||
|
||||
// The severity of the error, and action taken,
|
||||
// if this service fails to start.
|
||||
ErrorCritical = windows.SERVICE_ERROR_CRITICAL
|
||||
ErrorIgnore = windows.SERVICE_ERROR_IGNORE
|
||||
ErrorNormal = windows.SERVICE_ERROR_NORMAL
|
||||
ErrorSevere = windows.SERVICE_ERROR_SEVERE
|
||||
)
|
||||
|
||||
// TODO(brainman): Password is not returned by windows.QueryServiceConfig, not sure how to get it.
|
||||
|
||||
type Config struct {
|
||||
ServiceType uint32
|
||||
StartType uint32
|
||||
ErrorControl uint32
|
||||
BinaryPathName string // fully qualified path to the service binary file, can also include arguments for an auto-start service
|
||||
LoadOrderGroup string
|
||||
TagId uint32
|
||||
Dependencies []string
|
||||
ServiceStartName string // name of the account under which the service should run
|
||||
DisplayName string
|
||||
Password string
|
||||
Description string
|
||||
}
|
||||
|
||||
func toString(p *uint16) string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
return syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(p))[:])
|
||||
}
|
||||
|
||||
func toStringSlice(ps *uint16) []string {
|
||||
if ps == nil {
|
||||
return nil
|
||||
}
|
||||
r := make([]string, 0)
|
||||
for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(ps)); true; i++ {
|
||||
if p[i] == 0 {
|
||||
// empty string marks the end
|
||||
if i <= from {
|
||||
break
|
||||
}
|
||||
r = append(r, string(utf16.Decode(p[from:i])))
|
||||
from = i + 1
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Config retrieves service s configuration paramteres.
|
||||
func (s *Service) Config() (Config, error) {
|
||||
var p *windows.QUERY_SERVICE_CONFIG
|
||||
n := uint32(1024)
|
||||
for {
|
||||
b := make([]byte, n)
|
||||
p = (*windows.QUERY_SERVICE_CONFIG)(unsafe.Pointer(&b[0]))
|
||||
err := windows.QueryServiceConfig(s.Handle, p, n, &n)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER {
|
||||
return Config{}, err
|
||||
}
|
||||
if n <= uint32(len(b)) {
|
||||
return Config{}, err
|
||||
}
|
||||
}
|
||||
|
||||
b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_DESCRIPTION)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
p2 := (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0]))
|
||||
|
||||
return Config{
|
||||
ServiceType: p.ServiceType,
|
||||
StartType: p.StartType,
|
||||
ErrorControl: p.ErrorControl,
|
||||
BinaryPathName: toString(p.BinaryPathName),
|
||||
LoadOrderGroup: toString(p.LoadOrderGroup),
|
||||
TagId: p.TagId,
|
||||
Dependencies: toStringSlice(p.Dependencies),
|
||||
ServiceStartName: toString(p.ServiceStartName),
|
||||
DisplayName: toString(p.DisplayName),
|
||||
Description: toString(p2.Description),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func updateDescription(handle windows.Handle, desc string) error {
|
||||
d := windows.SERVICE_DESCRIPTION{Description: toPtr(desc)}
|
||||
return windows.ChangeServiceConfig2(handle,
|
||||
windows.SERVICE_CONFIG_DESCRIPTION, (*byte)(unsafe.Pointer(&d)))
|
||||
}
|
||||
|
||||
// UpdateConfig updates service s configuration parameters.
|
||||
func (s *Service) UpdateConfig(c Config) error {
|
||||
err := windows.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType,
|
||||
c.ErrorControl, toPtr(c.BinaryPathName), toPtr(c.LoadOrderGroup),
|
||||
nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName),
|
||||
toPtr(c.Password), toPtr(c.DisplayName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return updateDescription(s.Handle, c.Description)
|
||||
}
|
||||
|
||||
// queryServiceConfig2 calls Windows QueryServiceConfig2 with infoLevel parameter and returns retrieved service configuration information.
|
||||
func (s *Service) queryServiceConfig2(infoLevel uint32) ([]byte, error) {
|
||||
n := uint32(1024)
|
||||
for {
|
||||
b := make([]byte, n)
|
||||
err := windows.QueryServiceConfig2(s.Handle, infoLevel, &b[0], n, &n)
|
||||
if err == nil {
|
||||
return b, nil
|
||||
}
|
||||
if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER {
|
||||
return nil, err
|
||||
}
|
||||
if n <= uint32(len(b)) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
162
vendor/golang.org/x/sys/windows/svc/mgr/mgr.go
generated
vendored
Normal file
162
vendor/golang.org/x/sys/windows/svc/mgr/mgr.go
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
// Package mgr can be used to manage Windows service programs.
|
||||
// It can be used to install and remove them. It can also start,
|
||||
// stop and pause them. The package can query / change current
|
||||
// service state and config parameters.
|
||||
//
|
||||
package mgr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// Mgr is used to manage Windows service.
|
||||
type Mgr struct {
|
||||
Handle windows.Handle
|
||||
}
|
||||
|
||||
// Connect establishes a connection to the service control manager.
|
||||
func Connect() (*Mgr, error) {
|
||||
return ConnectRemote("")
|
||||
}
|
||||
|
||||
// ConnectRemote establishes a connection to the
|
||||
// service control manager on computer named host.
|
||||
func ConnectRemote(host string) (*Mgr, error) {
|
||||
var s *uint16
|
||||
if host != "" {
|
||||
s = syscall.StringToUTF16Ptr(host)
|
||||
}
|
||||
h, err := windows.OpenSCManager(s, nil, windows.SC_MANAGER_ALL_ACCESS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Mgr{Handle: h}, nil
|
||||
}
|
||||
|
||||
// Disconnect closes connection to the service control manager m.
|
||||
func (m *Mgr) Disconnect() error {
|
||||
return windows.CloseServiceHandle(m.Handle)
|
||||
}
|
||||
|
||||
func toPtr(s string) *uint16 {
|
||||
if len(s) == 0 {
|
||||
return nil
|
||||
}
|
||||
return syscall.StringToUTF16Ptr(s)
|
||||
}
|
||||
|
||||
// toStringBlock terminates strings in ss with 0, and then
|
||||
// concatenates them together. It also adds extra 0 at the end.
|
||||
func toStringBlock(ss []string) *uint16 {
|
||||
if len(ss) == 0 {
|
||||
return nil
|
||||
}
|
||||
t := ""
|
||||
for _, s := range ss {
|
||||
if s != "" {
|
||||
t += s + "\x00"
|
||||
}
|
||||
}
|
||||
if t == "" {
|
||||
return nil
|
||||
}
|
||||
t += "\x00"
|
||||
return &utf16.Encode([]rune(t))[0]
|
||||
}
|
||||
|
||||
// CreateService installs new service name on the system.
|
||||
// The service will be executed by running exepath binary.
|
||||
// Use config c to specify service parameters.
|
||||
// Any args will be passed as command-line arguments when
|
||||
// the service is started; these arguments are distinct from
|
||||
// the arguments passed to Service.Start or via the "Start
|
||||
// parameters" field in the service's Properties dialog box.
|
||||
func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Service, error) {
|
||||
if c.StartType == 0 {
|
||||
c.StartType = StartManual
|
||||
}
|
||||
if c.ErrorControl == 0 {
|
||||
c.ErrorControl = ErrorNormal
|
||||
}
|
||||
if c.ServiceType == 0 {
|
||||
c.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS
|
||||
}
|
||||
s := syscall.EscapeArg(exepath)
|
||||
for _, v := range args {
|
||||
s += " " + syscall.EscapeArg(v)
|
||||
}
|
||||
h, err := windows.CreateService(m.Handle, toPtr(name), toPtr(c.DisplayName),
|
||||
windows.SERVICE_ALL_ACCESS, c.ServiceType,
|
||||
c.StartType, c.ErrorControl, toPtr(s), toPtr(c.LoadOrderGroup),
|
||||
nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName), toPtr(c.Password))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c.Description != "" {
|
||||
err = updateDescription(h, c.Description)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &Service{Name: name, Handle: h}, nil
|
||||
}
|
||||
|
||||
// OpenService retrieves access to service name, so it can
|
||||
// be interrogated and controlled.
|
||||
func (m *Mgr) OpenService(name string) (*Service, error) {
|
||||
h, err := windows.OpenService(m.Handle, syscall.StringToUTF16Ptr(name), windows.SERVICE_ALL_ACCESS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Service{Name: name, Handle: h}, nil
|
||||
}
|
||||
|
||||
// ListServices enumerates services in the specified
|
||||
// service control manager database m.
|
||||
// If the caller does not have the SERVICE_QUERY_STATUS
|
||||
// access right to a service, the service is silently
|
||||
// omitted from the list of services returned.
|
||||
func (m *Mgr) ListServices() ([]string, error) {
|
||||
var err error
|
||||
var bytesNeeded, servicesReturned uint32
|
||||
var buf []byte
|
||||
for {
|
||||
var p *byte
|
||||
if len(buf) > 0 {
|
||||
p = &buf[0]
|
||||
}
|
||||
err = windows.EnumServicesStatusEx(m.Handle, windows.SC_ENUM_PROCESS_INFO,
|
||||
windows.SERVICE_WIN32, windows.SERVICE_STATE_ALL,
|
||||
p, uint32(len(buf)), &bytesNeeded, &servicesReturned, nil, nil)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if err != syscall.ERROR_MORE_DATA {
|
||||
return nil, err
|
||||
}
|
||||
if bytesNeeded <= uint32(len(buf)) {
|
||||
return nil, err
|
||||
}
|
||||
buf = make([]byte, bytesNeeded)
|
||||
}
|
||||
if servicesReturned == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
services := (*[1 << 20]windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0]))[:servicesReturned]
|
||||
var names []string
|
||||
for _, s := range services {
|
||||
name := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(s.ServiceName))[:])
|
||||
names = append(names, name)
|
||||
}
|
||||
return names, nil
|
||||
}
|
96
vendor/golang.org/x/sys/windows/svc/mgr/recovery.go
generated
vendored
Normal file
96
vendor/golang.org/x/sys/windows/svc/mgr/recovery.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package mgr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
// Possible recovery actions that the service control manager can perform.
|
||||
NoAction = windows.SC_ACTION_NONE // no action
|
||||
ComputerReboot = windows.SC_ACTION_REBOOT // reboot the computer
|
||||
ServiceRestart = windows.SC_ACTION_RESTART // restart the service
|
||||
RunCommand = windows.SC_ACTION_RUN_COMMAND // run a command
|
||||
)
|
||||
|
||||
// RecoveryAction represents an action that the service control manager can perform when service fails.
|
||||
// A service is considered failed when it terminates without reporting a status of SERVICE_STOPPED to the service controller.
|
||||
type RecoveryAction struct {
|
||||
Type int // one of NoAction, ComputerReboot, ServiceRestart or RunCommand
|
||||
Delay time.Duration // the time to wait before performing the specified action
|
||||
}
|
||||
|
||||
// SetRecoveryActions sets actions that service controller performs when service fails and
|
||||
// the time after which to reset the service failure count to zero if there are no failures, in seconds.
|
||||
// Specify INFINITE to indicate that service failure count should never be reset.
|
||||
func (s *Service) SetRecoveryActions(recoveryActions []RecoveryAction, resetPeriod uint32) error {
|
||||
if recoveryActions == nil {
|
||||
return errors.New("recoveryActions cannot be nil")
|
||||
}
|
||||
actions := []windows.SC_ACTION{}
|
||||
for _, a := range recoveryActions {
|
||||
action := windows.SC_ACTION{
|
||||
Type: uint32(a.Type),
|
||||
Delay: uint32(a.Delay.Nanoseconds() / 1000000),
|
||||
}
|
||||
actions = append(actions, action)
|
||||
}
|
||||
rActions := windows.SERVICE_FAILURE_ACTIONS{
|
||||
ActionsCount: uint32(len(actions)),
|
||||
Actions: &actions[0],
|
||||
ResetPeriod: resetPeriod,
|
||||
}
|
||||
return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
|
||||
}
|
||||
|
||||
// RecoveryActions returns actions that service controller performs when service fails.
|
||||
// The service control manager counts the number of times service s has failed since the system booted.
|
||||
// The count is reset to 0 if the service has not failed for ResetPeriod seconds.
|
||||
// When the service fails for the Nth time, the service controller performs the action specified in element [N-1] of returned slice.
|
||||
// If N is greater than slice length, the service controller repeats the last action in the slice.
|
||||
func (s *Service) RecoveryActions() ([]RecoveryAction, error) {
|
||||
b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
|
||||
if p.Actions == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var recoveryActions []RecoveryAction
|
||||
actions := (*[1024]windows.SC_ACTION)(unsafe.Pointer(p.Actions))[:p.ActionsCount]
|
||||
for _, action := range actions {
|
||||
recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond})
|
||||
}
|
||||
return recoveryActions, nil
|
||||
}
|
||||
|
||||
// ResetRecoveryActions deletes both reset period and array of failure actions.
|
||||
func (s *Service) ResetRecoveryActions() error {
|
||||
actions := make([]windows.SC_ACTION, 1)
|
||||
rActions := windows.SERVICE_FAILURE_ACTIONS{
|
||||
Actions: &actions[0],
|
||||
}
|
||||
return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
|
||||
}
|
||||
|
||||
// ResetPeriod is the time after which to reset the service failure
|
||||
// count to zero if there are no failures, in seconds.
|
||||
func (s *Service) ResetPeriod() (uint32, error) {
|
||||
b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
|
||||
return p.ResetPeriod, nil
|
||||
}
|
72
vendor/golang.org/x/sys/windows/svc/mgr/service.go
generated
vendored
Normal file
72
vendor/golang.org/x/sys/windows/svc/mgr/service.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package mgr
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc"
|
||||
)
|
||||
|
||||
// TODO(brainman): Use EnumDependentServices to enumerate dependent services.
|
||||
|
||||
// Service is used to access Windows service.
|
||||
type Service struct {
|
||||
Name string
|
||||
Handle windows.Handle
|
||||
}
|
||||
|
||||
// Delete marks service s for deletion from the service control manager database.
|
||||
func (s *Service) Delete() error {
|
||||
return windows.DeleteService(s.Handle)
|
||||
}
|
||||
|
||||
// Close relinquish access to the service s.
|
||||
func (s *Service) Close() error {
|
||||
return windows.CloseServiceHandle(s.Handle)
|
||||
}
|
||||
|
||||
// Start starts service s.
|
||||
// args will be passed to svc.Handler.Execute.
|
||||
func (s *Service) Start(args ...string) error {
|
||||
var p **uint16
|
||||
if len(args) > 0 {
|
||||
vs := make([]*uint16, len(args))
|
||||
for i := range vs {
|
||||
vs[i] = syscall.StringToUTF16Ptr(args[i])
|
||||
}
|
||||
p = &vs[0]
|
||||
}
|
||||
return windows.StartService(s.Handle, uint32(len(args)), p)
|
||||
}
|
||||
|
||||
// Control sends state change request c to the servce s.
|
||||
func (s *Service) Control(c svc.Cmd) (svc.Status, error) {
|
||||
var t windows.SERVICE_STATUS
|
||||
err := windows.ControlService(s.Handle, uint32(c), &t)
|
||||
if err != nil {
|
||||
return svc.Status{}, err
|
||||
}
|
||||
return svc.Status{
|
||||
State: svc.State(t.CurrentState),
|
||||
Accepts: svc.Accepted(t.ControlsAccepted),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Query returns current status of service s.
|
||||
func (s *Service) Query() (svc.Status, error) {
|
||||
var t windows.SERVICE_STATUS
|
||||
err := windows.QueryServiceStatus(s.Handle, &t)
|
||||
if err != nil {
|
||||
return svc.Status{}, err
|
||||
}
|
||||
return svc.Status{
|
||||
State: svc.State(t.CurrentState),
|
||||
Accepts: svc.Accepted(t.ControlsAccepted),
|
||||
}, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user