1
2
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
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
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
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
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
137 spec.Linux.CgroupsPath = "/containers/" + id
138
139
140 spec.Windows = nil
141
142 return nil
143 }
144
View as plain text