github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/daemon/oci_windows.go (about) 1 package daemon 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path/filepath" 8 "syscall" 9 10 "github.com/docker/docker/container" 11 "github.com/docker/docker/image" 12 "github.com/docker/docker/layer" 13 "github.com/docker/docker/libcontainerd" 14 "github.com/docker/docker/libcontainerd/windowsoci" 15 "github.com/docker/docker/oci" 16 ) 17 18 func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, error) { 19 s := oci.DefaultSpec() 20 21 linkedEnv, err := daemon.setupLinkedContainers(c) 22 if err != nil { 23 return nil, err 24 } 25 26 // TODO Windows - this can be removed. Not used (UID/GID) 27 rootUID, rootGID := daemon.GetRemappedUIDGID() 28 if err := c.SetupWorkingDirectory(rootUID, rootGID); err != nil { 29 return nil, err 30 } 31 32 img, err := daemon.imageStore.Get(c.ImageID) 33 if err != nil { 34 return nil, fmt.Errorf("Failed to graph.Get on ImageID %s - %s", c.ImageID, err) 35 } 36 37 // In base spec 38 s.Hostname = c.FullHostname() 39 40 // In s.Mounts 41 mounts, err := daemon.setupMounts(c) 42 if err != nil { 43 return nil, err 44 } 45 for _, mount := range mounts { 46 s.Mounts = append(s.Mounts, windowsoci.Mount{ 47 Source: mount.Source, 48 Destination: mount.Destination, 49 Readonly: !mount.Writable, 50 }) 51 } 52 53 // In s.Process 54 s.Process.Args = append([]string{c.Path}, c.Args...) 55 if !c.Config.ArgsEscaped { 56 s.Process.Args = escapeArgs(s.Process.Args) 57 } 58 s.Process.Cwd = c.Config.WorkingDir 59 s.Process.Env = c.CreateDaemonEnvironment(linkedEnv) 60 s.Process.InitialConsoleSize = c.HostConfig.ConsoleSize 61 s.Process.Terminal = c.Config.Tty 62 s.Process.User.User = c.Config.User 63 64 // In spec.Root 65 s.Root.Path = c.BaseFS 66 s.Root.Readonly = c.HostConfig.ReadonlyRootfs 67 68 // In s.Windows 69 s.Windows.FirstStart = !c.HasBeenStartedBefore 70 71 // s.Windows.LayerFolder. 72 m, err := c.RWLayer.Metadata() 73 if err != nil { 74 return nil, fmt.Errorf("Failed to get layer metadata - %s", err) 75 } 76 s.Windows.LayerFolder = m["dir"] 77 78 // s.Windows.LayerPaths 79 var layerPaths []string 80 if img.RootFS != nil && (img.RootFS.Type == image.TypeLayers || img.RootFS.Type == image.TypeLayersWithBase) { 81 // Get the layer path for each layer. 82 start := 1 83 if img.RootFS.Type == image.TypeLayersWithBase { 84 // Include an empty slice to get the base layer ID. 85 start = 0 86 } 87 max := len(img.RootFS.DiffIDs) 88 for i := start; i <= max; i++ { 89 img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i] 90 path, err := layer.GetLayerPath(daemon.layerStore, img.RootFS.ChainID()) 91 if err != nil { 92 return nil, fmt.Errorf("Failed to get layer path from graphdriver %s for ImageID %s - %s", daemon.layerStore, img.RootFS.ChainID(), err) 93 } 94 // Reverse order, expecting parent most first 95 layerPaths = append([]string{path}, layerPaths...) 96 } 97 } 98 s.Windows.LayerPaths = layerPaths 99 100 // Are we going to run as a Hyper-V container? 101 hv := false 102 if c.HostConfig.Isolation.IsDefault() { 103 // Container is set to use the default, so take the default from the daemon configuration 104 hv = daemon.defaultIsolation.IsHyperV() 105 } else { 106 // Container is requesting an isolation mode. Honour it. 107 hv = c.HostConfig.Isolation.IsHyperV() 108 } 109 if hv { 110 hvr := &windowsoci.HvRuntime{} 111 if img.RootFS != nil && img.RootFS.Type == image.TypeLayers { 112 // For TP5, the utility VM is part of the base layer. 113 // TODO-jstarks: Add support for separate utility VM images 114 // once it is decided how they can be stored. 115 uvmpath := filepath.Join(layerPaths[len(layerPaths)-1], "UtilityVM") 116 _, err = os.Stat(uvmpath) 117 if err != nil { 118 if os.IsNotExist(err) { 119 err = errors.New("container image does not contain a utility VM") 120 } 121 return nil, err 122 } 123 124 hvr.ImagePath = uvmpath 125 } 126 127 s.Windows.HvRuntime = hvr 128 } 129 130 // In s.Windows.Networking 131 // Connect all the libnetwork allocated networks to the container 132 var epList []string 133 if c.NetworkSettings != nil { 134 for n := range c.NetworkSettings.Networks { 135 sn, err := daemon.FindNetwork(n) 136 if err != nil { 137 continue 138 } 139 140 ep, err := c.GetEndpointInNetwork(sn) 141 if err != nil { 142 continue 143 } 144 145 data, err := ep.DriverInfo() 146 if err != nil { 147 continue 148 } 149 if data["hnsid"] != nil { 150 epList = append(epList, data["hnsid"].(string)) 151 } 152 } 153 } 154 s.Windows.Networking = &windowsoci.Networking{ 155 EndpointList: epList, 156 } 157 158 // In s.Windows.Resources 159 // @darrenstahlmsft implement these resources 160 cpuShares := uint64(c.HostConfig.CPUShares) 161 s.Windows.Resources = &windowsoci.Resources{ 162 CPU: &windowsoci.CPU{ 163 //TODO Count: ..., 164 //TODO Percent: ..., 165 Shares: &cpuShares, 166 }, 167 Memory: &windowsoci.Memory{ 168 //TODO Limit: ..., 169 //TODO Reservation: ..., 170 }, 171 Network: &windowsoci.Network{ 172 //TODO Bandwidth: ..., 173 }, 174 Storage: &windowsoci.Storage{ 175 //TODO Bps: ..., 176 //TODO Iops: ..., 177 //TODO SandboxSize: ..., 178 }, 179 } 180 return (*libcontainerd.Spec)(&s), nil 181 } 182 183 func escapeArgs(args []string) []string { 184 escapedArgs := make([]string, len(args)) 185 for i, a := range args { 186 escapedArgs[i] = syscall.EscapeArg(a) 187 } 188 return escapedArgs 189 }