...

Source file src/github.com/Microsoft/hcsshim/internal/guest/runtime/hcsv2/standalone_container.go

Documentation: github.com/Microsoft/hcsshim/internal/guest/runtime/hcsv2

     1  //go:build linux
     2  // +build linux
     3  
     4  package hcsv2
     5  
     6  import (
     7  	"context"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	oci "github.com/opencontainers/runtime-spec/specs-go"
    13  	"github.com/pkg/errors"
    14  	"go.opencensus.io/trace"
    15  
    16  	"github.com/Microsoft/hcsshim/internal/guest/network"
    17  	specInternal "github.com/Microsoft/hcsshim/internal/guest/spec"
    18  	"github.com/Microsoft/hcsshim/internal/guestpath"
    19  	"github.com/Microsoft/hcsshim/internal/oc"
    20  )
    21  
    22  func getStandaloneRootDir(id string) string {
    23  	return filepath.Join(guestpath.LCOWRootPrefixInUVM, id)
    24  }
    25  
    26  func getStandaloneHostnamePath(id string) string {
    27  	return filepath.Join(getStandaloneRootDir(id), "hostname")
    28  }
    29  
    30  func getStandaloneHostsPath(id string) string {
    31  	return filepath.Join(getStandaloneRootDir(id), "hosts")
    32  }
    33  
    34  func getStandaloneResolvPath(id string) string {
    35  	return filepath.Join(getStandaloneRootDir(id), "resolv.conf")
    36  }
    37  
    38  func setupStandaloneContainerSpec(ctx context.Context, id string, spec *oci.Spec) (err error) {
    39  	ctx, span := oc.StartSpan(ctx, "hcsv2::setupStandaloneContainerSpec")
    40  	defer span.End()
    41  	defer func() { oc.SetSpanStatus(span, err) }()
    42  	span.AddAttributes(trace.StringAttribute("cid", id))
    43  
    44  	// Generate the standalone root dir
    45  	rootDir := getStandaloneRootDir(id)
    46  	if err := os.MkdirAll(rootDir, 0755); err != nil {
    47  		return errors.Wrapf(err, "failed to create container root directory %q", rootDir)
    48  	}
    49  	defer func() {
    50  		if err != nil {
    51  			_ = os.RemoveAll(rootDir)
    52  		}
    53  	}()
    54  
    55  	hostname := spec.Hostname
    56  	if hostname == "" {
    57  		var err error
    58  		hostname, err = os.Hostname()
    59  		if err != nil {
    60  			return errors.Wrap(err, "failed to get hostname")
    61  		}
    62  	}
    63  
    64  	// Write the hostname
    65  	if !specInternal.MountPresent("/etc/hostname", spec.Mounts) {
    66  		standaloneHostnamePath := getStandaloneHostnamePath(id)
    67  		if err := os.WriteFile(standaloneHostnamePath, []byte(hostname+"\n"), 0644); err != nil {
    68  			return errors.Wrapf(err, "failed to write hostname to %q", standaloneHostnamePath)
    69  		}
    70  
    71  		mt := oci.Mount{
    72  			Destination: "/etc/hostname",
    73  			Type:        "bind",
    74  			Source:      getStandaloneHostnamePath(id),
    75  			Options:     []string{"bind"},
    76  		}
    77  		if isRootReadonly(spec) {
    78  			mt.Options = append(mt.Options, "ro")
    79  		}
    80  		spec.Mounts = append(spec.Mounts, mt)
    81  	}
    82  
    83  	// Write the hosts
    84  	if !specInternal.MountPresent("/etc/hosts", spec.Mounts) {
    85  		standaloneHostsContent := network.GenerateEtcHostsContent(ctx, hostname)
    86  		standaloneHostsPath := getStandaloneHostsPath(id)
    87  		if err := os.WriteFile(standaloneHostsPath, []byte(standaloneHostsContent), 0644); err != nil {
    88  			return errors.Wrapf(err, "failed to write standalone hosts to %q", standaloneHostsPath)
    89  		}
    90  
    91  		mt := oci.Mount{
    92  			Destination: "/etc/hosts",
    93  			Type:        "bind",
    94  			Source:      getStandaloneHostsPath(id),
    95  			Options:     []string{"bind"},
    96  		}
    97  		if isRootReadonly(spec) {
    98  			mt.Options = append(mt.Options, "ro")
    99  		}
   100  		spec.Mounts = append(spec.Mounts, mt)
   101  	}
   102  
   103  	// Write resolv.conf
   104  	if !specInternal.MountPresent("/etc/resolv.conf", spec.Mounts) {
   105  		ns := GetOrAddNetworkNamespace(getNetworkNamespaceID(spec))
   106  		var searches, servers []string
   107  		for _, n := range ns.Adapters() {
   108  			if len(n.DNSSuffix) > 0 {
   109  				searches = network.MergeValues(searches, strings.Split(n.DNSSuffix, ","))
   110  			}
   111  			if len(n.DNSServerList) > 0 {
   112  				servers = network.MergeValues(servers, strings.Split(n.DNSServerList, ","))
   113  			}
   114  		}
   115  		resolvContent, err := network.GenerateResolvConfContent(ctx, searches, servers, nil)
   116  		if err != nil {
   117  			return errors.Wrap(err, "failed to generate standalone resolv.conf content")
   118  		}
   119  		standaloneResolvPath := getStandaloneResolvPath(id)
   120  		if err := os.WriteFile(standaloneResolvPath, []byte(resolvContent), 0644); err != nil {
   121  			return errors.Wrap(err, "failed to write standalone resolv.conf")
   122  		}
   123  
   124  		mt := oci.Mount{
   125  			Destination: "/etc/resolv.conf",
   126  			Type:        "bind",
   127  			Source:      getStandaloneResolvPath(id),
   128  			Options:     []string{"bind"},
   129  		}
   130  		if isRootReadonly(spec) {
   131  			mt.Options = append(mt.Options, "ro")
   132  		}
   133  		spec.Mounts = append(spec.Mounts, mt)
   134  	}
   135  
   136  	// Force the parent cgroup into our /containers root
   137  	spec.Linux.CgroupsPath = "/containers/" + id
   138  
   139  	// Clear the windows section as we dont want to forward to runc
   140  	spec.Windows = nil
   141  
   142  	return nil
   143  }
   144  

View as plain text