mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 17:26:28 +00:00
commit
e921db1292
@ -26,6 +26,10 @@ const (
|
||||
hyperkitNetworkingDefault = hyperkitNetworkingDockerForMac
|
||||
)
|
||||
|
||||
func init() {
|
||||
hyperkit.SetLogger(log.StandardLogger())
|
||||
}
|
||||
|
||||
// Process the run arguments and execute run
|
||||
func runHyperKit(args []string) {
|
||||
flags := flag.NewFlagSet("hyperkit", flag.ExitOnError)
|
||||
@ -206,12 +210,15 @@ func runHyperKit(args []string) {
|
||||
id = strconv.Itoa(i)
|
||||
}
|
||||
if d.Size != 0 && d.Path == "" {
|
||||
d.Path = filepath.Join(*state, "disk"+id+".img")
|
||||
d.Path = filepath.Join(*state, "disk"+id+".raw")
|
||||
}
|
||||
if d.Path == "" {
|
||||
log.Fatalf("disk specified with no size or name")
|
||||
}
|
||||
hd := hyperkit.DiskConfig{Path: d.Path, Size: d.Size}
|
||||
hd, err := hyperkit.NewDisk(d.Path, d.Size)
|
||||
if err != nil {
|
||||
log.Fatalf("NewDisk failed: %v", err)
|
||||
}
|
||||
h.Disks = append(h.Disks, hd)
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ github.com/gorilla/mux 4c1c3952b7d9d0a061a3fa7b36fd373ba0398ebc
|
||||
github.com/jmespath/go-jmespath bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d
|
||||
github.com/mitchellh/go-ps 4fdf99ab29366514c69ccccddab5dc58b8d84062
|
||||
github.com/moby/datakit 97b3d230535397a813323902c23751e176481a86
|
||||
github.com/moby/hyperkit a12cd7250bcd8d689078e3e42ae4a7cf6a0cbaf3
|
||||
github.com/moby/hyperkit a285521725f44f3d10ca1042c2c07d3a6e24bed8
|
||||
# When updating also:
|
||||
# curl -fsSL -o src/cmd/linuxkit/build.go https://raw.githubusercontent.com/moby/tool/«hash»/cmd/moby/build.go
|
||||
github.com/moby/tool caca03c097eafd7aa1e011de59ded3604e1b318f
|
||||
|
60
src/cmd/linuxkit/vendor/github.com/docker/docker/hack/README.md
generated
vendored
60
src/cmd/linuxkit/vendor/github.com/docker/docker/hack/README.md
generated
vendored
@ -1,60 +0,0 @@
|
||||
## About
|
||||
|
||||
This directory contains a collection of scripts used to build and manage this
|
||||
repository. If there are any issues regarding the intention of a particular
|
||||
script (or even part of a certain script), please reach out to us.
|
||||
It may help us either refine our current scripts, or add on new ones
|
||||
that are appropriate for a given use case.
|
||||
|
||||
## DinD (dind.sh)
|
||||
|
||||
DinD is a wrapper script which allows Docker to be run inside a Docker
|
||||
container. DinD requires the container to
|
||||
be run with privileged mode enabled.
|
||||
|
||||
## Generate Authors (generate-authors.sh)
|
||||
|
||||
Generates AUTHORS; a file with all the names and corresponding emails of
|
||||
individual contributors. AUTHORS can be found in the home directory of
|
||||
this repository.
|
||||
|
||||
## Make
|
||||
|
||||
There are two make files, each with different extensions. Neither are supposed
|
||||
to be called directly; only invoke `make`. Both scripts run inside a Docker
|
||||
container.
|
||||
|
||||
### make.ps1
|
||||
|
||||
- The Windows native build script that uses PowerShell semantics; it is limited
|
||||
unlike `hack\make.sh` since it does not provide support for the full set of
|
||||
operations provided by the Linux counterpart, `make.sh`. However, `make.ps1`
|
||||
does provide support for local Windows development and Windows to Windows CI.
|
||||
More information is found within `make.ps1` by the author, @jhowardmsft
|
||||
|
||||
### make.sh
|
||||
|
||||
- Referenced via `make test` when running tests on a local machine,
|
||||
or directly referenced when running tests inside a Docker development container.
|
||||
- When running on a local machine, `make test` to run all tests found in
|
||||
`test`, `test-unit`, `test-integration`, and `test-docker-py` on
|
||||
your local machine. The default timeout is set in `make.sh` to 60 minutes
|
||||
(`${TIMEOUT:=60m}`), since it currently takes up to an hour to run
|
||||
all of the tests.
|
||||
- When running inside a Docker development container, `hack/make.sh` does
|
||||
not have a single target that runs all the tests. You need to provide a
|
||||
single command line with multiple targets that performs the same thing.
|
||||
An example referenced from [Run targets inside a development container](https://docs.docker.com/opensource/project/test-and-docs/#run-targets-inside-a-development-container): `root@5f8630b873fe:/go/src/github.com/moby/moby# hack/make.sh dynbinary binary cross test-unit test-integration test-docker-py`
|
||||
- For more information related to testing outside the scope of this README,
|
||||
refer to
|
||||
[Run tests and test documentation](https://docs.docker.com/opensource/project/test-and-docs/)
|
||||
|
||||
## Release (release.sh)
|
||||
|
||||
Releases any bundles built by `make` on a public AWS S3 bucket.
|
||||
For information regarding configuration, please view `release.sh`.
|
||||
|
||||
## Vendor (vendor.sh)
|
||||
|
||||
A shell script that is a wrapper around Vndr. For information on how to use
|
||||
this, please refer to [vndr's README](https://github.com/LK4D4/vndr/blob/master/README.md)
|
69
src/cmd/linuxkit/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md
generated
vendored
69
src/cmd/linuxkit/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md
generated
vendored
@ -1,69 +0,0 @@
|
||||
# Integration Testing on Swarm
|
||||
|
||||
IT on Swarm allows you to execute integration test in parallel across a Docker Swarm cluster
|
||||
|
||||
## Architecture
|
||||
|
||||
### Master service
|
||||
|
||||
- Works as a funker caller
|
||||
- Calls a worker funker (`-worker-service`) with a chunk of `-check.f` filter strings (passed as a file via `-input` flag, typically `/mnt/input`)
|
||||
|
||||
### Worker service
|
||||
|
||||
- Works as a funker callee
|
||||
- Executes an equivalent of `TESTFLAGS=-check.f TestFoo|TestBar|TestBaz ... make test-integration-cli` using the bind-mounted API socket (`docker.sock`)
|
||||
|
||||
### Client
|
||||
|
||||
- Controls master and workers via `docker stack`
|
||||
- No need to have a local daemon
|
||||
|
||||
Typically, the master and workers are supposed to be running on a cloud environment,
|
||||
while the client is supposed to be running on a laptop, e.g. Docker for Mac/Windows.
|
||||
|
||||
## Requirement
|
||||
|
||||
- Docker daemon 1.13 or later
|
||||
- Private registry for distributed execution with multiple nodes
|
||||
|
||||
## Usage
|
||||
|
||||
### Step 1: Prepare images
|
||||
|
||||
$ make build-integration-cli-on-swarm
|
||||
|
||||
Following environment variables are known to work in this step:
|
||||
|
||||
- `BUILDFLAGS`
|
||||
- `DOCKER_INCREMENTAL_BINARY`
|
||||
|
||||
Note: during the transition into Moby Project, you might need to create a symbolic link `$GOPATH/src/github.com/docker/docker` to `$GOPATH/src/github.com/moby/moby`.
|
||||
|
||||
### Step 2: Execute tests
|
||||
|
||||
$ ./hack/integration-cli-on-swarm/integration-cli-on-swarm -replicas 40 -push-worker-image YOUR_REGISTRY.EXAMPLE.COM/integration-cli-worker:latest
|
||||
|
||||
Following environment variables are known to work in this step:
|
||||
|
||||
- `DOCKER_GRAPHDRIVER`
|
||||
- `DOCKER_EXPERIMENTAL`
|
||||
|
||||
#### Flags
|
||||
|
||||
Basic flags:
|
||||
|
||||
- `-replicas N`: the number of worker service replicas. i.e. degree of parallelism.
|
||||
- `-chunks N`: the number of chunks. By default, `chunks` == `replicas`.
|
||||
- `-push-worker-image REGISTRY/IMAGE:TAG`: push the worker image to the registry. Note that if you have only single node and hence you do not need a private registry, you do not need to specify `-push-worker-image`.
|
||||
|
||||
Experimental flags for mitigating makespan nonuniformity:
|
||||
|
||||
- `-shuffle`: Shuffle the test filter strings
|
||||
|
||||
Flags for debugging IT on Swarm itself:
|
||||
|
||||
- `-rand-seed N`: the random seed. This flag is useful for deterministic replaying. By default(0), the timestamp is used.
|
||||
- `-filters-file FILE`: the file contains `-check.f` strings. By default, the file is automatically generated.
|
||||
- `-dry-run`: skip the actual workload
|
||||
- `keep-executor`: do not auto-remove executor containers, which is used for running privileged programs on Swarm
|
@ -1,2 +0,0 @@
|
||||
# dependencies specific to worker (i.e. github.com/docker/docker/...) are not vendored here
|
||||
github.com/bfirsh/funker-go eaa0a2e06f30e72c9a0b7f858951e581e26ef773
|
10
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/README.md
generated
vendored
10
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/README.md
generated
vendored
@ -1,8 +1,8 @@
|
||||
## [HyperKit](http://github.com/docker/hyperkit)
|
||||
## [HyperKit](http://github.com/moby/hyperkit)
|
||||
|
||||

|
||||

|
||||
|
||||
*HyperKit* is a toolkit for embedding hypervisor capabilities in your application. It includes a complete hypervisor, based on [xhyve](https://github.com/mist64/xhyve)/[bhyve](http://bhyve.org), which is optimized for lightweight virtual machines and container deployment. It is designed to be interfaced with higher-level components such as the [VPNKit](https://github.com/docker/vpnkit) and [DataKit](https://github.com/docker/datakit).
|
||||
*HyperKit* is a toolkit for embedding hypervisor capabilities in your application. It includes a complete hypervisor, based on [xhyve](https://github.com/mist64/xhyve)/[bhyve](http://bhyve.org), which is optimized for lightweight virtual machines and container deployment. It is designed to be interfaced with higher-level components such as the [VPNKit](https://github.com/moby/vpnkit) and [DataKit](https://github.com/moby/datakit).
|
||||
|
||||
HyperKit currently only supports Mac OS X using the [Hypervisor.framework](https://developer.apple.com/library/mac/documentation/DriversKernelHardware/Reference/Hypervisor/index.html). It is a core component of Docker For Mac.
|
||||
|
||||
@ -24,7 +24,7 @@ If you are using Hyperkit directly then please report issues against this reposi
|
||||
|
||||
## Building
|
||||
|
||||
$ git clone https://github.com/docker/hyperkit
|
||||
$ git clone https://github.com/moby/hyperkit
|
||||
$ cd hyperkit
|
||||
$ make
|
||||
|
||||
@ -38,7 +38,7 @@ via `brew` and using `opam` to install the appropriate libraries:
|
||||
$ brew install opam libev
|
||||
$ opam init
|
||||
$ eval `opam config env`
|
||||
$ opam install uri qcow.0.10.3 conduit.1.0.0 lwt.3.1.0 qcow-tool mirage-block-unix.2.7.0 conf-libev logs fmt mirage-unix prometheus-app
|
||||
$ opam install uri qcow.0.10.3 conduit.1.0.0 lwt.3.1.0 qcow-tool mirage-block-unix.2.9.0 conf-libev logs fmt mirage-unix prometheus-app
|
||||
|
||||
Notes:
|
||||
|
||||
|
433
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/disk.go
generated
vendored
Normal file
433
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/disk.go
generated
vendored
Normal file
@ -0,0 +1,433 @@
|
||||
package hyperkit
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
mib = int64(1024 * 1024)
|
||||
)
|
||||
|
||||
/*-------.
|
||||
| Disk. |
|
||||
`-------*/
|
||||
|
||||
// Disk in an interface for qcow2 and raw disk images.
|
||||
type Disk interface {
|
||||
// GetPath returns the location of the disk image file.
|
||||
GetPath() string
|
||||
// SetPath changes the location of the disk image file.
|
||||
SetPath(p string)
|
||||
// GetSize returns the desired disk size.
|
||||
GetSize() int
|
||||
// GetCurrentSize returns the current disk size in MiB.
|
||||
GetCurrentSize() (int, error)
|
||||
// String returns the path.
|
||||
String() string
|
||||
|
||||
// Exists iff the disk image file can be stat'd without error.
|
||||
Exists() bool
|
||||
// Ensure creates the disk image if needed, and resizes it if needed.
|
||||
Ensure() error
|
||||
// Stop can be called when hyperkit has quit. It performs sanity checks, compaction, etc.
|
||||
Stop() error
|
||||
|
||||
// AsArgument returns the command-line option to pass after `-s <slot>:0,` to hyperkit for this disk.
|
||||
AsArgument() string
|
||||
|
||||
create() error
|
||||
resize() error
|
||||
}
|
||||
|
||||
// DiskFormat describes the physical format of the disk data
|
||||
type DiskFormat int
|
||||
|
||||
const (
|
||||
// DiskFormatQcow means the disk is a qcow2.
|
||||
DiskFormatQcow DiskFormat = iota
|
||||
|
||||
// DiskFormatRaw means the disk is a raw file.
|
||||
DiskFormatRaw
|
||||
)
|
||||
|
||||
// GetDiskFormat computes the format based on the path's extensions.
|
||||
func GetDiskFormat(path string) DiskFormat {
|
||||
switch ext := filepath.Ext(path); ext {
|
||||
case ".qcow2":
|
||||
return DiskFormatQcow
|
||||
case ".raw", ".img":
|
||||
return DiskFormatRaw
|
||||
default:
|
||||
log.Debugf("Unknown disk extension %q, will use raw format", path)
|
||||
return DiskFormatRaw
|
||||
}
|
||||
}
|
||||
|
||||
// NewDisk creates a qcow/raw disk configuration based on the spec.
|
||||
func NewDisk(spec string, size int) (Disk, error) {
|
||||
u, err := url.Parse(spec)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid disk path %q: %v", spec, err)
|
||||
}
|
||||
switch path := u.Path; GetDiskFormat(path) {
|
||||
case DiskFormatRaw:
|
||||
return &RawDisk{
|
||||
Path: path,
|
||||
Size: size,
|
||||
Trim: true,
|
||||
}, nil
|
||||
case DiskFormatQcow:
|
||||
return &QcowDisk{
|
||||
Path: path,
|
||||
Size: size,
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("impossible")
|
||||
}
|
||||
|
||||
// exists iff the image file can be stat'd without error.
|
||||
func exists(d Disk) bool {
|
||||
_, err := os.Stat(d.GetPath())
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
log.Debugf("cannot stat %q: %v", d, err)
|
||||
}
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// ensure creates the disk image if needed, and resizes it if needed.
|
||||
func ensure(d Disk) error {
|
||||
current, err := d.GetCurrentSize()
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
return d.create()
|
||||
}
|
||||
if current < d.GetSize() {
|
||||
return d.resize()
|
||||
}
|
||||
if d.GetSize() < current {
|
||||
log.Errorf("Cannot safely shrink %q from %dMiB to %dMiB", d, current, d.GetSize())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// diskDriver to use.
|
||||
//
|
||||
// Dave Scott writes:
|
||||
//
|
||||
// > Regarding TRIM and raw disks
|
||||
// > (https://github.com/docker/pinata/pull/8235/commits/0e2c7c2e21114b4ed61589bd42b720f7d88c0d8e):
|
||||
// > it works like this: the `ahci-hd` virtual hardware in hyperkit
|
||||
// > exposes the `ATA_SUPPORT_DSM_TRIM` capability
|
||||
// > (https://github.com/moby/hyperkit/blob/81fa6279fcb17e8435f3cec0978e9aa3af02e63b/src/lib/pci_ahci.c#L996)
|
||||
// > if the `fcntl(F_PUNCHHOLE)`
|
||||
// > (https://github.com/moby/hyperkit/blob/81fa6279fcb17e8435f3cec0978e9aa3af02e63b/src/lib/block_if.c#L276)
|
||||
// > API works on the raw file (it's dynamically detected so on HFS+ it's
|
||||
// > disabled and on APFS it's enabled) -> TRIM on raw doesn't need any
|
||||
// > special flags set in the Go code; the special flags are only for the
|
||||
// > TRIM on qcow implementation. When images are deleted in the VM the
|
||||
// > `trim-after-delete`
|
||||
// > (https://github.com/linuxkit/linuxkit/tree/master/pkg/trim-after-delete)
|
||||
// > daemon calls `fstrim /var/lib/docker` which causes Linux to emit the
|
||||
// > TRIM commands to hyperkit, which calls `fcntl`, which tells macOS to
|
||||
// > free the space in the file, visible in `ls -sl`.
|
||||
// >
|
||||
// > Unfortunately the `virtio-blk` protocol doesn't support `TRIM`
|
||||
// > requests at all so we have to use `ahci-hd` (if you try to run
|
||||
// > `fstrim /var/lib/docker` with `virtio-blk` it'll give an `ioctl`
|
||||
// > error).
|
||||
func diskDriver(trim bool) string {
|
||||
if trim {
|
||||
return "ahci-hd"
|
||||
}
|
||||
return "virtio-blk"
|
||||
}
|
||||
|
||||
/*----------.
|
||||
| RawDisk. |
|
||||
`----------*/
|
||||
|
||||
// RawDisk describes a raw disk image file.
|
||||
type RawDisk struct {
|
||||
// Path specifies where the image file will be.
|
||||
Path string `json:"path"`
|
||||
// Size specifies the size of the disk.
|
||||
Size int `json:"size"`
|
||||
// Format is passed as-is to the driver.
|
||||
Format string `json:"format"`
|
||||
// Trim specifies whether we should trim the image file.
|
||||
Trim bool `json:"trim"`
|
||||
}
|
||||
|
||||
// GetPath returns the location of the disk image file.
|
||||
func (d *RawDisk) GetPath() string {
|
||||
return d.Path
|
||||
}
|
||||
|
||||
// SetPath changes the location of the disk image file.
|
||||
func (d *RawDisk) SetPath(p string) {
|
||||
d.Path = p
|
||||
}
|
||||
|
||||
// GetSize returns the desired disk size.
|
||||
func (d *RawDisk) GetSize() int {
|
||||
return d.Size
|
||||
}
|
||||
|
||||
// String returns the path.
|
||||
func (d *RawDisk) String() string {
|
||||
return d.Path
|
||||
}
|
||||
|
||||
// Exists iff the image file can be stat's without error.
|
||||
func (d *RawDisk) Exists() bool {
|
||||
return exists(d)
|
||||
}
|
||||
|
||||
// Ensure creates the disk image if needed, and resizes it if needed.
|
||||
func (d *RawDisk) Ensure() error {
|
||||
return ensure(d)
|
||||
}
|
||||
|
||||
// Create a disk.
|
||||
func (d *RawDisk) create() error {
|
||||
log.Infof("Create %q", d)
|
||||
f, err := os.Create(d.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return d.resize()
|
||||
}
|
||||
|
||||
// GetCurrentSize returns the current disk size in MiB.
|
||||
func (d *RawDisk) GetCurrentSize() (int, error) {
|
||||
fileinfo, err := os.Stat(d.Path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(fileinfo.Size() / mib), nil
|
||||
}
|
||||
|
||||
// Resize the virtual size of the disk
|
||||
func (d *RawDisk) resize() error {
|
||||
s, err := d.GetCurrentSize()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot resize %q: %v", d, err)
|
||||
}
|
||||
log.Infof("Resize %q from %vMiB to %vMiB", d, s, d.GetSize())
|
||||
// APFS exhibits a weird behavior wrt sparse files: we cannot
|
||||
// create (or grow) them "too fast": there's a limit,
|
||||
// apparently related to the available disk space. However,
|
||||
// if the additional space is small enough, we can procede way
|
||||
// beyond the available disk space. So grow incrementally,
|
||||
// by steps of 1GB.
|
||||
for s < d.Size {
|
||||
s += 1000
|
||||
if d.Size < s {
|
||||
s = d.Size
|
||||
}
|
||||
if err := os.Truncate(d.Path, int64(s)*mib); err != nil {
|
||||
return fmt.Errorf("Cannot resize %q to %vMiB: %v", d, s, err)
|
||||
}
|
||||
}
|
||||
log.Infof("Resized %q to %vMiB", d, d.GetSize())
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop cleans up this disk when we are quitting.
|
||||
func (d *RawDisk) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AsArgument returns the command-line option to pass after `-s <slot>:0,` to hyperkit for this disk.
|
||||
func (d *RawDisk) AsArgument() string {
|
||||
res := fmt.Sprintf("%s,%s", diskDriver(d.Trim), d.Path)
|
||||
if d.Format != "" {
|
||||
res += ",format=" + d.Format
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
/*-----------.
|
||||
| QcowDisk. |
|
||||
`-----------*/
|
||||
|
||||
// QcowDisk describes a qcow2 disk image file.
|
||||
type QcowDisk struct {
|
||||
// Path specifies where the image file will be.
|
||||
Path string `json:"path"`
|
||||
// Size specifies the size of the disk.
|
||||
Size int `json:"size"`
|
||||
// Format is passed as-is to the driver.
|
||||
Format string `json:"format"`
|
||||
// Trim specifies whether we should trim the image file.
|
||||
Trim bool `json:"trim"`
|
||||
// QcowToolPath is the path to the binary to use to manage this image.
|
||||
// Defaults to "qcow-tool" when empty.
|
||||
QcowToolPath string
|
||||
OnFlush string
|
||||
CompactAfter int
|
||||
KeepErased int
|
||||
RuntimeAsserts bool
|
||||
Stats string
|
||||
}
|
||||
|
||||
// GetPath returns the location of the disk image file.
|
||||
func (d *QcowDisk) GetPath() string {
|
||||
return d.Path
|
||||
}
|
||||
|
||||
// SetPath changes the location of the disk image file.
|
||||
func (d *QcowDisk) SetPath(p string) {
|
||||
d.Path = p
|
||||
}
|
||||
|
||||
// GetSize returns the desired disk size.
|
||||
func (d *QcowDisk) GetSize() int {
|
||||
return d.Size
|
||||
}
|
||||
|
||||
// String returns the path.
|
||||
func (d *QcowDisk) String() string {
|
||||
return d.Path
|
||||
}
|
||||
|
||||
// QcowTool prepares a call to qcow-tool on this image.
|
||||
func (d *QcowDisk) QcowTool(verb string, args ...string) *exec.Cmd {
|
||||
if d.QcowToolPath == "" {
|
||||
d.QcowToolPath = "qcow-tool"
|
||||
}
|
||||
return exec.Command(d.QcowToolPath, append([]string{verb, d.Path}, args...)...)
|
||||
}
|
||||
|
||||
func run(cmd *exec.Cmd) (string, error) {
|
||||
buf, err := cmd.CombinedOutput()
|
||||
out := string(buf)
|
||||
log.Debugf("ran %v: out=%q, err=%v", cmd.Args, out, err)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Exists iff the image file can be stat'd without error.
|
||||
func (d *QcowDisk) Exists() bool {
|
||||
return exists(d)
|
||||
}
|
||||
|
||||
// Ensure creates the disk image if needed, and resizes it if needed.
|
||||
func (d *QcowDisk) Ensure() error {
|
||||
if d.Trim {
|
||||
log.Infof("%v: TRIM is enabled; recycling thread will keep %v sectors free and will compact after %v more sectors are free",
|
||||
d, d.KeepErased, d.CompactAfter)
|
||||
}
|
||||
if d.RuntimeAsserts {
|
||||
log.Warnf("%v: Expensive runtime checks are enabled", d)
|
||||
}
|
||||
return ensure(d)
|
||||
}
|
||||
|
||||
// Create a disk with the given size in MiB
|
||||
func (d *QcowDisk) create() error {
|
||||
log.Infof("Create %q", d)
|
||||
_, err := run(d.QcowTool("create", "--size", fmt.Sprintf("%dMiB", d.Size)))
|
||||
return err
|
||||
}
|
||||
|
||||
// GetCurrentSize returns the current disk size in MiB.
|
||||
func (d *QcowDisk) GetCurrentSize() (int, error) {
|
||||
if _, err := os.Stat(d.Path); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
out, err := run(d.QcowTool("info", "--filter", ".size"))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size, err := strconv.ParseInt(strings.TrimSpace(string(out)), 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(size / mib), nil
|
||||
}
|
||||
|
||||
func (d *QcowDisk) sizeString() string {
|
||||
s, err := d.GetCurrentSize()
|
||||
if err != nil {
|
||||
return fmt.Sprintf("cannot get size: %v", err)
|
||||
}
|
||||
return fmt.Sprintf("%vMiB", s)
|
||||
}
|
||||
|
||||
// Resize the virtual size of the disk
|
||||
func (d *QcowDisk) resize() error {
|
||||
log.Infof("Resize %q from %v to %dMiB", d, d.sizeString(), d.GetSize())
|
||||
_, err := run(d.QcowTool("resize", "--size", fmt.Sprintf("%dMiB", d.Size)))
|
||||
return err
|
||||
}
|
||||
|
||||
// compact the disk to shrink the physical size.
|
||||
func (d *QcowDisk) compact() error {
|
||||
log.Infof("Compact: %q... (%v)", d, d.sizeString())
|
||||
cmd := d.QcowTool("compact")
|
||||
if _, err := run(cmd); err != nil {
|
||||
if err.(*exec.ExitError) != nil {
|
||||
return errors.New("Failed to compact qcow2")
|
||||
}
|
||||
return err
|
||||
}
|
||||
log.Infof("Compact: %q: done (%v)", d, d.sizeString())
|
||||
return nil
|
||||
}
|
||||
|
||||
// check the disk is well-formed.
|
||||
func (d *QcowDisk) check() error {
|
||||
cmd := d.QcowTool("check")
|
||||
if _, err := run(cmd); err != nil {
|
||||
if err.(*exec.ExitError) != nil {
|
||||
return errors.New("qcow2 failed integrity check: it may be corrupt")
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop cleans up this disk when we are quitting.
|
||||
func (d *QcowDisk) Stop() error {
|
||||
if !d.Trim && d.CompactAfter == 0 {
|
||||
log.Infof("TRIM is enabled but auto-compaction disabled: compacting %q now", d)
|
||||
if err := d.compact(); err != nil {
|
||||
return fmt.Errorf("Failed to compact %q: %v", d, err)
|
||||
}
|
||||
if err := d.check(); err != nil {
|
||||
return fmt.Errorf("Post-compact disk integrity check of %q failed: %v", d, err)
|
||||
}
|
||||
log.Infof("Post-compact disk integrity check of %q successful", d)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AsArgument returns the command-line option to pass after `-s <slot>:0,` to hyperkit for this disk.
|
||||
func (d *QcowDisk) AsArgument() string {
|
||||
res := fmt.Sprintf("%s,file://%s?sync=%s&buffered=1", diskDriver(d.Trim), d.Path, d.OnFlush)
|
||||
{
|
||||
format := d.Format
|
||||
if format == "" {
|
||||
format = "qcow"
|
||||
}
|
||||
res += fmt.Sprintf(",format=%v", format)
|
||||
}
|
||||
if d.Stats != "" {
|
||||
res += ",qcow-stats-config=" + d.Stats
|
||||
}
|
||||
res += fmt.Sprintf(",qcow-config=discard=%t;compact_after_unmaps=%d;keep_erased=%d;runtime_asserts=%t",
|
||||
d.Trim, d.CompactAfter, d.KeepErased, d.RuntimeAsserts)
|
||||
return res
|
||||
}
|
272
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/hyperkit.go
generated
vendored
272
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/hyperkit.go
generated
vendored
@ -27,12 +27,10 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -70,18 +68,13 @@ type Socket9P struct {
|
||||
Tag string `json:"tag"`
|
||||
}
|
||||
|
||||
// DiskConfig contains the path to a disk image and an optional size if the image needs to be created.
|
||||
type DiskConfig struct {
|
||||
Path string `json:"path"`
|
||||
Size int `json:"size"`
|
||||
Format string `json:"format"`
|
||||
Driver string `json:"driver"`
|
||||
}
|
||||
|
||||
// HyperKit contains the configuration of the hyperkit VM
|
||||
type HyperKit struct {
|
||||
// HyperKit is the path to the hyperkit binary
|
||||
// HyperKit is the path to the hyperkit binary.
|
||||
HyperKit string `json:"hyperkit"`
|
||||
// Argv0 is the name to declare as argv[0]. If left empty, argv[0] is left untouched.
|
||||
Argv0 string `json:"argv0"`
|
||||
|
||||
// StateDir is the directory where runtime state is kept. If left empty, no state will be kept.
|
||||
StateDir string `json:"state_dir"`
|
||||
// VPNKitSock is the location of the VPNKit socket used for networking.
|
||||
@ -93,32 +86,35 @@ type HyperKit struct {
|
||||
// UUID is a string containing a UUID, it sets BIOS DMI UUID for the VM (as found in /sys/class/dmi/id/product_uuid on Linux).
|
||||
UUID string `json:"uuid"`
|
||||
// Disks contains disk images to use/create.
|
||||
Disks []DiskConfig `json:"disks"`
|
||||
// ISOImage is the (optional) path to a ISO image to attach
|
||||
Disks []Disk `json:"disks"`
|
||||
// ISOImage is the (optional) path to a ISO image to attach.
|
||||
ISOImages []string `json:"iso"`
|
||||
// VSock enables the virtio-socket device and exposes it on the host
|
||||
|
||||
// VSock enables the virtio-socket device and exposes it on the host.
|
||||
VSock bool `json:"vsock"`
|
||||
// VSockPorts is a list of guest VSock ports that should be exposed as sockets on the host
|
||||
// VSockDir specifies where the unix domain sockets will be created. Defaults to StateDir when empty.
|
||||
VSockDir string `json:"vsock_dir"`
|
||||
// VSockPorts is a list of guest VSock ports that should be exposed as sockets on the host.
|
||||
VSockPorts []int `json:"vsock_ports"`
|
||||
// VSock guest CID
|
||||
VSockGuestCID int `json:"vsock_guest_cid"`
|
||||
|
||||
// VMNet whether to create vmnet network
|
||||
// VMNet is whether to create vmnet network.
|
||||
VMNet bool `json:"vmnet"`
|
||||
|
||||
// 9P sockets
|
||||
// Sockets9P holds the 9P sockets.
|
||||
Sockets9P []Socket9P `json:"9p_sockets"`
|
||||
|
||||
// Kernel is the path to the kernel image to boot
|
||||
// Kernel is the path to the kernel image to boot.
|
||||
Kernel string `json:"kernel"`
|
||||
// Initrd is the path to the initial ramdisk to boot off
|
||||
// Initrd is the path to the initial ramdisk to boot off.
|
||||
Initrd string `json:"initrd"`
|
||||
// Bootrom is the path to a boot rom eg for UEFI boot
|
||||
// Bootrom is the path to a boot rom eg for UEFI boot.
|
||||
Bootrom string `json:"bootrom"`
|
||||
|
||||
// CPUs is the number CPUs to configure
|
||||
// CPUs is the number CPUs to configure.
|
||||
CPUs int `json:"cpus"`
|
||||
// Memory is the amount of megabytes of memory for the VM
|
||||
// Memory is the amount of megabytes of memory for the VM.
|
||||
Memory int `json:"memory"`
|
||||
|
||||
// Console defines where the console of the VM should be
|
||||
@ -135,9 +131,7 @@ type HyperKit struct {
|
||||
// CmdLine is a single string of the command line
|
||||
CmdLine string `json:"cmdline"`
|
||||
|
||||
process *os.Process
|
||||
background bool
|
||||
log *log.Logger
|
||||
process *os.Process
|
||||
}
|
||||
|
||||
// New creates a template config structure.
|
||||
@ -169,58 +163,40 @@ func New(hyperkit, vpnkitsock, statedir string) (*HyperKit, error) {
|
||||
return &h, nil
|
||||
}
|
||||
|
||||
// FromState reads a json file from statedir and populates a HyperKit structure.
|
||||
func FromState(statedir string) (*HyperKit, error) {
|
||||
b, err := ioutil.ReadFile(filepath.Join(statedir, jsonFile))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Can't read json file: %s", err)
|
||||
}
|
||||
h := &HyperKit{}
|
||||
err = json.Unmarshal(b, h)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Can't parse json file: %s", err)
|
||||
}
|
||||
|
||||
// Make sure the pid written by hyperkit is the same as in the json
|
||||
d, err := ioutil.ReadFile(filepath.Join(statedir, pidFile))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pid, err := strconv.Atoi(string(d[:]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if h.Pid != pid {
|
||||
return nil, fmt.Errorf("pids do not match %d != %d", h.Pid, pid)
|
||||
}
|
||||
|
||||
h.process, err = os.FindProcess(h.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// SetLogger sets the log instance to use for the output of the hyperkit process itself (not the console of the VM).
|
||||
// This is only relevant when Console is set to ConsoleFile
|
||||
func (h *HyperKit) SetLogger(logger *log.Logger) {
|
||||
h.log = logger
|
||||
}
|
||||
|
||||
// Run the VM with a given command line until it exits
|
||||
// Run the VM with a given command line until it exits.
|
||||
func (h *HyperKit) Run(cmdline string) error {
|
||||
h.background = false
|
||||
return h.execute(cmdline)
|
||||
errCh, err := h.Start(cmdline)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
// Start the VM with a given command line in the background
|
||||
func (h *HyperKit) Start(cmdline string) error {
|
||||
h.background = true
|
||||
return h.execute(cmdline)
|
||||
// Start the VM with a given command line in the background. On
|
||||
// success, returns a channel on which the result of Wait'ing for
|
||||
// hyperkit is sent. Return failures to start the process.
|
||||
func (h *HyperKit) Start(cmdline string) (chan error, error) {
|
||||
log.Debugf("hyperkit: Start %#v", h)
|
||||
if err := h.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.buildArgs(cmdline)
|
||||
cmd, err := h.execute()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
errCh := make(chan error, 1)
|
||||
// Make sure we reap the child when it exits
|
||||
go func() {
|
||||
log.Debugf("hyperkit: Waiting for %#v", cmd)
|
||||
errCh <- cmd.Wait()
|
||||
}()
|
||||
return errCh, nil
|
||||
}
|
||||
|
||||
func (h *HyperKit) execute(cmdline string) error {
|
||||
// check validates `h`. It also creates the disks if needed.
|
||||
func (h *HyperKit) check() error {
|
||||
log.Debugf("hyperkit: check %#v", h)
|
||||
var err error
|
||||
// Sanity checks on configuration
|
||||
if h.Console == ConsoleFile && h.StateDir == "" {
|
||||
@ -234,12 +210,18 @@ func (h *HyperKit) execute(cmdline string) error {
|
||||
return fmt.Errorf("ISO %s does not exist", image)
|
||||
}
|
||||
}
|
||||
if h.VSock && h.StateDir == "" {
|
||||
return fmt.Errorf("If virtio-sockets are enabled, StateDir must be specified")
|
||||
}
|
||||
if !h.VSock && len(h.VSockPorts) > 0 {
|
||||
return fmt.Errorf("To forward vsock ports vsock must be enabled")
|
||||
|
||||
if h.VSock {
|
||||
if h.VSockDir == "" {
|
||||
if h.StateDir == "" {
|
||||
return fmt.Errorf("If virtio-sockets are enabled, VSockDir or StateDir must be specified")
|
||||
}
|
||||
h.VSockDir = h.StateDir
|
||||
}
|
||||
} else if len(h.VSockPorts) > 0 {
|
||||
return fmt.Errorf("To forward vsock ports VSock must be enabled")
|
||||
}
|
||||
|
||||
if h.Bootrom == "" {
|
||||
if _, err = os.Stat(h.Kernel); os.IsNotExist(err) {
|
||||
return fmt.Errorf("Kernel %s does not exist", h.Kernel)
|
||||
@ -258,44 +240,30 @@ func (h *HyperKit) execute(cmdline string) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Create files
|
||||
if h.StateDir != "" {
|
||||
err = os.MkdirAll(h.StateDir, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
// Create directories.
|
||||
for _, dir := range []string{h.VSockDir, h.StateDir} {
|
||||
if dir != "" {
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return fmt.Errorf("Cannot create directory %q: %v", dir, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for idx, config := range h.Disks {
|
||||
if config.Path == "" {
|
||||
for idx, disk := range h.Disks {
|
||||
if disk.GetPath() == "" {
|
||||
if h.StateDir == "" {
|
||||
return fmt.Errorf("Unable to create disk image when neither path nor state dir is set")
|
||||
}
|
||||
if config.Size <= 0 {
|
||||
if disk.GetSize() <= 0 {
|
||||
return fmt.Errorf("Unable to create disk image when size is 0 or not set")
|
||||
}
|
||||
config.Path = fmt.Sprintf(filepath.Clean(filepath.Join(h.StateDir, "disk%02d.img")), idx)
|
||||
h.Disks[idx] = config
|
||||
disk.SetPath(filepath.Clean(filepath.Join(h.StateDir, fmt.Sprintf("disk%02d.img", idx))))
|
||||
h.Disks[idx] = disk
|
||||
}
|
||||
if _, err = os.Stat(config.Path); os.IsNotExist(err) {
|
||||
if config.Size != 0 {
|
||||
err = CreateDiskImage(config.Path, config.Size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("Disk image %s not found and unable to create it as size is not specified", config.Path)
|
||||
}
|
||||
if err := disk.Ensure(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Run
|
||||
h.buildArgs(cmdline)
|
||||
err = h.execHyperKit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -333,8 +301,8 @@ func (h *HyperKit) IsRunning() bool {
|
||||
|
||||
// isDisk checks if the specified path is used as a disk image
|
||||
func (h *HyperKit) isDisk(path string) bool {
|
||||
for _, config := range h.Disks {
|
||||
if filepath.Clean(path) == filepath.Clean(config.Path) {
|
||||
for _, disk := range h.Disks {
|
||||
if filepath.Clean(path) == filepath.Clean(disk.GetPath()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -360,12 +328,10 @@ func (h *HyperKit) Remove(keepDisk bool) error {
|
||||
files, _ := ioutil.ReadDir(h.StateDir)
|
||||
for _, f := range files {
|
||||
fn := filepath.Clean(filepath.Join(h.StateDir, f.Name()))
|
||||
if h.isDisk(fn) {
|
||||
continue
|
||||
}
|
||||
err := os.Remove(fn)
|
||||
if err != nil {
|
||||
return err
|
||||
if !h.isDisk(fn) {
|
||||
if err := os.Remove(fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -380,24 +346,6 @@ func (h *HyperKit) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// CreateDiskImage creates a empty file suitable for use as a disk image for a hyperkit VM.
|
||||
func CreateDiskImage(location string, sizeMB int) error {
|
||||
diskDir := path.Dir(location)
|
||||
if diskDir != "." {
|
||||
if err := os.MkdirAll(diskDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
f, err := os.Create(location)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return f.Truncate(int64(sizeMB) * int64(1024) * int64(1024))
|
||||
}
|
||||
|
||||
func intArrayToString(i []int, sep string) string {
|
||||
if len(i) == 0 {
|
||||
return ""
|
||||
@ -445,24 +393,13 @@ func (h *HyperKit) buildArgs(cmdline string) {
|
||||
a = append(a, "-U", h.UUID)
|
||||
}
|
||||
|
||||
for _, p := range h.Disks {
|
||||
// Default the driver to virtio-blk
|
||||
driver := "virtio-blk"
|
||||
if p.Driver != "" {
|
||||
driver = p.Driver
|
||||
}
|
||||
arg := fmt.Sprintf("%d:0,%s,%s", nextSlot, driver, p.Path)
|
||||
|
||||
// Add on a format instruction if specified.
|
||||
if p.Format != "" {
|
||||
arg += ",format=" + p.Format
|
||||
}
|
||||
a = append(a, "-s", arg)
|
||||
for _, disk := range h.Disks {
|
||||
a = append(a, "-s", fmt.Sprintf("%d:0,%s", nextSlot, disk.AsArgument()))
|
||||
nextSlot++
|
||||
}
|
||||
|
||||
if h.VSock {
|
||||
l := fmt.Sprintf("%d,virtio-sock,guest_cid=%d,path=%s", nextSlot, h.VSockGuestCID, h.StateDir)
|
||||
l := fmt.Sprintf("%d,virtio-sock,guest_cid=%d,path=%s", nextSlot, h.VSockGuestCID, h.VSockDir)
|
||||
if len(h.VSockPorts) > 0 {
|
||||
l = fmt.Sprintf("%s,guest_forwards=%s", l, intArrayToString(h.VSockPorts, ";"))
|
||||
}
|
||||
@ -499,12 +436,18 @@ func (h *HyperKit) buildArgs(cmdline string) {
|
||||
|
||||
h.Arguments = a
|
||||
h.CmdLine = h.HyperKit + " " + strings.Join(a, " ")
|
||||
log.Debugf("hyperkit: Arguments: %#v", h.Arguments)
|
||||
log.Debugf("hyperkit: CmdLine: %#v", h.CmdLine)
|
||||
}
|
||||
|
||||
// Execute hyperkit and plumb stdin/stdout/stderr.
|
||||
func (h *HyperKit) execHyperKit() error {
|
||||
// execute forges the command to run hyperkit, runs and returns it.
|
||||
// It also plumbs stdin/stdout/stderr.
|
||||
func (h *HyperKit) execute() (*exec.Cmd, error) {
|
||||
|
||||
cmd := exec.Command(h.HyperKit, h.Arguments...)
|
||||
if h.Argv0 != "" {
|
||||
cmd.Args[0] = h.Argv0
|
||||
}
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
// Plumb in stdin/stdout/stderr.
|
||||
@ -528,15 +471,13 @@ func (h *HyperKit) execHyperKit() error {
|
||||
go func() {
|
||||
ttyPath := fmt.Sprintf("%s/tty", h.StateDir)
|
||||
var tty *os.File
|
||||
var err error
|
||||
for {
|
||||
var err error
|
||||
tty, err = os.OpenFile(ttyPath, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
time.Sleep(10 * 1000 * 1000 * time.Nanosecond)
|
||||
continue
|
||||
} else {
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
saneTerminal(tty)
|
||||
setRaw(tty)
|
||||
@ -544,16 +485,17 @@ func (h *HyperKit) execHyperKit() error {
|
||||
tty.Close()
|
||||
}()
|
||||
}
|
||||
} else if h.log != nil {
|
||||
} else if log != nil {
|
||||
log.Debugf("hyperkit: Redirecting stdout/stderr to logger")
|
||||
stdoutChan := make(chan string)
|
||||
stderrChan := make(chan string)
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
stream(stdout, stdoutChan)
|
||||
stream(stderr, stderrChan)
|
||||
@ -563,9 +505,9 @@ func (h *HyperKit) execHyperKit() error {
|
||||
for {
|
||||
select {
|
||||
case stderrl := <-stderrChan:
|
||||
log.Printf("%s", stderrl)
|
||||
log.Infof("%s", stderrl)
|
||||
case stdoutl := <-stdoutChan:
|
||||
log.Printf("%s", stdoutl)
|
||||
log.Infof("%s", stdoutl)
|
||||
case <-done:
|
||||
return
|
||||
}
|
||||
@ -573,27 +515,21 @@ func (h *HyperKit) execHyperKit() error {
|
||||
}()
|
||||
}
|
||||
|
||||
log.Debugf("hyperkit: Starting %#v", cmd)
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
h.Pid = cmd.Process.Pid
|
||||
log.Debugf("hyperkit: Pid is %v", h.Pid)
|
||||
h.process = cmd.Process
|
||||
err = h.writeState()
|
||||
if err != nil {
|
||||
log.Debugf("hyperkit: Cannot write state: %v, killing %v", err, h.Pid)
|
||||
h.process.Kill()
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if !h.background {
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Make sure we reap the child when it exits
|
||||
go cmd.Wait()
|
||||
}
|
||||
return nil
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// writeState write the state to a JSON file
|
||||
|
57
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/log.go
generated
vendored
Normal file
57
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/log.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
package hyperkit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
golog "log"
|
||||
)
|
||||
|
||||
// Logger is an interface for logging.
|
||||
type Logger interface {
|
||||
// Debugf logs a message with "debug" severity (very verbose).
|
||||
Debugf(format string, v ...interface{})
|
||||
// Infof logs a message with "info" severity (less verbose).
|
||||
Infof(format string, v ...interface{})
|
||||
// Warnf logs a message with "warn" (non-fatal) severity.
|
||||
Warnf(format string, v ...interface{})
|
||||
// Errorf logs an (non-fatal) error.
|
||||
Errorf(format string, v ...interface{})
|
||||
// Fatalf logs a fatal error message, and exits 1.
|
||||
Fatalf(format string, v ...interface{})
|
||||
}
|
||||
|
||||
// StandardLogger makes the go standard logger comply to our Logger interface.
|
||||
type StandardLogger struct{}
|
||||
|
||||
// Debugf logs a message with "debug" severity.
|
||||
func (*StandardLogger) Debugf(f string, v ...interface{}) {
|
||||
golog.Printf("DEBUG: %v", fmt.Sprintf(f, v...))
|
||||
}
|
||||
|
||||
// Infof logs a message with "info" severity.
|
||||
func (*StandardLogger) Infof(f string, v ...interface{}) {
|
||||
golog.Printf("INFO : %v", fmt.Sprintf(f, v...))
|
||||
}
|
||||
|
||||
// Warnf logs a message with "warn" (non-fatal) severity.
|
||||
func (*StandardLogger) Warnf(f string, v ...interface{}) {
|
||||
golog.Printf("WARN : %v", fmt.Sprintf(f, v...))
|
||||
}
|
||||
|
||||
// Errorf logs an (non-fatal) error.
|
||||
func (*StandardLogger) Errorf(f string, v ...interface{}) {
|
||||
golog.Printf("ERROR: %v", fmt.Sprintf(f, v...))
|
||||
}
|
||||
|
||||
// Fatalf logs a fatal error message, and exits 1.
|
||||
func (*StandardLogger) Fatalf(f string, v ...interface{}) {
|
||||
golog.Fatalf("FATAL: %v", fmt.Sprintf(f, v...))
|
||||
}
|
||||
|
||||
// Log receives stdout/stderr of the hyperkit process itself, if set.
|
||||
// It defaults to the go standard logger.
|
||||
var log Logger = &StandardLogger{}
|
||||
|
||||
// SetLogger sets the logger to use.
|
||||
func SetLogger(l Logger) {
|
||||
log = l
|
||||
}
|
7
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/pty_util_fallback.go
generated
vendored
7
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/pty_util_fallback.go
generated
vendored
@ -3,22 +3,21 @@
|
||||
package hyperkit
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func saneTerminal(f *os.File) error {
|
||||
log.Fatal("Function not supported on your OS")
|
||||
log.Fatalf("Function not supported on your OS")
|
||||
return nil
|
||||
}
|
||||
|
||||
func setRaw(f *os.File) error {
|
||||
log.Fatal("Function not supported on your OS")
|
||||
log.Fatalf("Function not supported on your OS")
|
||||
return nil
|
||||
}
|
||||
|
||||
// isTerminal checks if the provided file is a terminal
|
||||
func isTerminal(f *os.File) bool {
|
||||
log.Fatal("Function not supported on your OS")
|
||||
log.Fatalf("Function not supported on your OS")
|
||||
return false
|
||||
}
|
||||
|
7
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/block_if.c
generated
vendored
7
src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/block_if.c
generated
vendored
@ -697,7 +697,12 @@ blockif_open(const char *optstr, const char *ident)
|
||||
perror("Could not open backing file");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Lock the file to prevent concurrent write+write or read+write as this
|
||||
would usually lead to corruption */
|
||||
if (flock(fd, LOCK_NB | (ro ? LOCK_SH : LOCK_EX)) < 0) {
|
||||
perror("Could not lock backing file");
|
||||
goto err;
|
||||
}
|
||||
if (fstat(fd, &sbuf) < 0) {
|
||||
perror("Could not stat backing file");
|
||||
goto err;
|
||||
|
Loading…
Reference in New Issue
Block a user