167 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//+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 windows
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/Microsoft/hcsshim"
 | 
						|
	"github.com/containerd/containerd/errdefs"
 | 
						|
	specs "github.com/opencontainers/runtime-spec/specs-go"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
)
 | 
						|
 | 
						|
// newContainerConfig generates a hcsshim container configuration from the
 | 
						|
// provided OCI Spec
 | 
						|
func newContainerConfig(ctx context.Context, owner, id string, spec *specs.Spec) (*hcsshim.ContainerConfig, error) {
 | 
						|
	var (
 | 
						|
		conf = &hcsshim.ContainerConfig{
 | 
						|
			SystemType: "Container",
 | 
						|
			Name:       id,
 | 
						|
			Owner:      owner,
 | 
						|
			HostName:   spec.Hostname,
 | 
						|
		}
 | 
						|
	)
 | 
						|
 | 
						|
	if spec.Windows.Network != nil {
 | 
						|
		conf.AllowUnqualifiedDNSQuery = spec.Windows.Network.AllowUnqualifiedDNSQuery
 | 
						|
		conf.EndpointList = spec.Windows.Network.EndpointList
 | 
						|
		conf.NetworkSharedContainerName = spec.Windows.Network.NetworkSharedContainerName
 | 
						|
		if spec.Windows.Network.DNSSearchList != nil {
 | 
						|
			conf.DNSSearchList = strings.Join(spec.Windows.Network.DNSSearchList, ",")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return conf, nil
 | 
						|
}
 | 
						|
 | 
						|
// newWindowsContainerConfig generates a hcsshim Windows container
 | 
						|
// configuration from the provided OCI Spec
 | 
						|
func newWindowsContainerConfig(ctx context.Context, owner, id string, spec *specs.Spec) (*hcsshim.ContainerConfig, error) {
 | 
						|
	conf, err := newContainerConfig(ctx, owner, id, spec)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	conf.IgnoreFlushesDuringBoot = spec.Windows.IgnoreFlushesDuringBoot
 | 
						|
 | 
						|
	if len(spec.Windows.LayerFolders) < 2 {
 | 
						|
		return nil, errors.Wrap(errdefs.ErrInvalidArgument,
 | 
						|
			"spec.Windows.LayerFolders must have at least 2 layers")
 | 
						|
	}
 | 
						|
	var (
 | 
						|
		layerFolderPath = spec.Windows.LayerFolders[0]
 | 
						|
		layerFolders    = spec.Windows.LayerFolders[1:]
 | 
						|
		layerID         = filepath.Base(layerFolderPath)
 | 
						|
	)
 | 
						|
 | 
						|
	// TODO: use the create request Mount for those
 | 
						|
	for _, layerPath := range layerFolders {
 | 
						|
		_, filename := filepath.Split(layerPath)
 | 
						|
		guid, err := hcsshim.NameToGuid(filename)
 | 
						|
		if err != nil {
 | 
						|
			return nil, errors.Wrapf(err, "unable to get GUID for %s", filename)
 | 
						|
		}
 | 
						|
		conf.Layers = append(conf.Layers, hcsshim.Layer{
 | 
						|
			ID:   guid.ToString(),
 | 
						|
			Path: layerPath,
 | 
						|
		})
 | 
						|
	}
 | 
						|
	conf.LayerFolderPath = layerFolderPath
 | 
						|
 | 
						|
	var di = hcsshim.DriverInfo{
 | 
						|
		HomeDir: filepath.Dir(layerFolderPath),
 | 
						|
	}
 | 
						|
	conf.VolumePath, err = hcsshim.GetLayerMountPath(di, layerID)
 | 
						|
	if err != nil {
 | 
						|
		return nil, errors.Wrapf(err, "failed to getmount path for layer %s: driverInfo: %#v", id, di)
 | 
						|
	}
 | 
						|
 | 
						|
	if spec.Windows.HyperV != nil {
 | 
						|
		conf.HvPartition = true
 | 
						|
		for _, layerPath := range layerFolders {
 | 
						|
			utilityVMPath := spec.Windows.HyperV.UtilityVMPath
 | 
						|
			_, err := os.Stat(utilityVMPath)
 | 
						|
			if err == nil {
 | 
						|
				conf.HvRuntime = &hcsshim.HvRuntime{ImagePath: utilityVMPath}
 | 
						|
				break
 | 
						|
			} else if !os.IsNotExist(err) {
 | 
						|
				return nil, errors.Wrapf(err, "failed to access layer %s", layerPath)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if spec.Windows.CredentialSpec != nil {
 | 
						|
		conf.Credentials = spec.Windows.CredentialSpec.(string)
 | 
						|
	}
 | 
						|
 | 
						|
	if len(spec.Mounts) > 0 {
 | 
						|
		mds := make([]hcsshim.MappedDir, len(spec.Mounts))
 | 
						|
		for i, mount := range spec.Mounts {
 | 
						|
			mds[i] = hcsshim.MappedDir{
 | 
						|
				HostPath:      mount.Source,
 | 
						|
				ContainerPath: mount.Destination,
 | 
						|
				ReadOnly:      false,
 | 
						|
			}
 | 
						|
			for _, o := range mount.Options {
 | 
						|
				if strings.ToLower(o) == "ro" {
 | 
						|
					mds[i].ReadOnly = true
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		conf.MappedDirectories = mds
 | 
						|
	}
 | 
						|
 | 
						|
	return conf, nil
 | 
						|
}
 | 
						|
 | 
						|
func newProcessConfig(processSpec *specs.Process, pset *pipeSet) *hcsshim.ProcessConfig {
 | 
						|
	conf := &hcsshim.ProcessConfig{
 | 
						|
		EmulateConsole:   pset.src.Terminal,
 | 
						|
		CreateStdInPipe:  pset.stdin != nil,
 | 
						|
		CreateStdOutPipe: pset.stdout != nil,
 | 
						|
		CreateStdErrPipe: pset.stderr != nil,
 | 
						|
		User:             processSpec.User.Username,
 | 
						|
		Environment:      make(map[string]string),
 | 
						|
		WorkingDirectory: processSpec.Cwd,
 | 
						|
	}
 | 
						|
 | 
						|
	if processSpec.ConsoleSize != nil {
 | 
						|
		conf.ConsoleSize = [2]uint{processSpec.ConsoleSize.Height, processSpec.ConsoleSize.Width}
 | 
						|
	}
 | 
						|
 | 
						|
	// Convert OCI Env format to HCS's
 | 
						|
	for _, s := range processSpec.Env {
 | 
						|
		arr := strings.SplitN(s, "=", 2)
 | 
						|
		if len(arr) == 2 {
 | 
						|
			conf.Environment[arr[0]] = arr[1]
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return conf
 | 
						|
}
 | 
						|
 | 
						|
func newWindowsProcessConfig(processSpec *specs.Process, pset *pipeSet) *hcsshim.ProcessConfig {
 | 
						|
	conf := newProcessConfig(processSpec, pset)
 | 
						|
	conf.CommandLine = strings.Join(processSpec.Args, " ")
 | 
						|
	return conf
 | 
						|
}
 |