Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions daemon/mgr/cri.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package mgr
import (
"bytes"
"fmt"
"os"
"path"
"time"

apitypes "github.com/alibaba/pouch/apis/types"
Expand Down Expand Up @@ -51,6 +53,9 @@ const (

namespaceModeHost = "host"
namespaceModeNone = "none"

// resolvConfPath is the abs path of resolv.conf on host or container.
resolvConfPath = "/etc/resolv.conf"
)

var (
Expand Down Expand Up @@ -78,6 +83,9 @@ type CriManager struct {

// StreamServer is the stream server of CRI serves container streaming request.
StreamServer stream.Server

// SandboxBaseDir is the directory used to store sandbox files like /etc/hosts, /etc/resolv.conf, etc.
SandboxBaseDir string
}

// NewCriManager creates a brand new cri manager.
Expand All @@ -88,10 +96,11 @@ func NewCriManager(config *config.Config, ctrMgr ContainerMgr, imgMgr ImageMgr)
}

c := &CriManager{
ContainerMgr: ctrMgr,
ImageMgr: imgMgr,
CniMgr: NewCniManager(&config.CriConfig),
StreamServer: streamServer,
ContainerMgr: ctrMgr,
ImageMgr: imgMgr,
CniMgr: NewCniManager(&config.CriConfig),
StreamServer: streamServer,
SandboxBaseDir: path.Join(config.HomeDir, "sandboxes"),
}

return NewCriWrapper(c), nil
Expand Down Expand Up @@ -149,6 +158,18 @@ func (c *CriManager) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
return nil, fmt.Errorf("failed to start sandbox container for pod %q: %v", config.Metadata.Name, err)
}

sandboxRootDir := path.Join(c.SandboxBaseDir, id)
err = os.MkdirAll(sandboxRootDir, 0755)
if err != nil {
return nil, fmt.Errorf("failed to create sandbox root directory: %v", err)
}

// Setup sandbox file /etc/resolv.conf.
err = setupSandboxFiles(sandboxRootDir, config)
if err != nil {
return nil, fmt.Errorf("failed to setup sandbox files: %v", err)
}

// Step 4: Setup networking for the sandbox.
container, err := c.ContainerMgr.Get(ctx, id)
if err != nil {
Expand Down Expand Up @@ -260,6 +281,13 @@ func (c *CriManager) RemovePodSandbox(ctx context.Context, r *runtime.RemovePodS
return nil, fmt.Errorf("failed to remove sandbox %q: %v", podSandboxID, err)
}

// Cleanup the sandbox root directory.
sandboxRootDir := path.Join(c.SandboxBaseDir, podSandboxID)
err = os.RemoveAll(sandboxRootDir)
if err != nil {
return nil, fmt.Errorf("failed to remove root directory %q: %v", sandboxRootDir, err)
}

return &runtime.RemovePodSandboxResponse{}, nil
}

Expand Down Expand Up @@ -380,6 +408,10 @@ func (c *CriManager) CreateContainer(ctx context.Context, r *runtime.CreateConta
return nil, err
}

// Bindings to overwrite the container's /etc/resolv.conf, /etc/hosts etc.
sandboxRootDir := path.Join(c.SandboxBaseDir, podSandboxID)
createConfig.HostConfig.Binds = append(createConfig.HostConfig.Binds, generateContainerMounts(sandboxRootDir)...)

// TODO: devices and security option configurations.

containerName := makeContainerName(sandboxConfig, config)
Expand Down
85 changes: 85 additions & 0 deletions daemon/mgr/cri_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package mgr
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -91,6 +95,18 @@ func extractLabels(input map[string]string) (map[string]string, map[string]strin
return labels, annotations
}

// generateContainerMounts sets up necessary container mounts including /dev/shm, /etc/hosts
// and /etc/resolv.conf.
func generateContainerMounts(sandboxRootDir string) []string {
// TODO: more attr and check whether these bindings is included in cri mounts.
result := []string{}
hostPath := path.Join(sandboxRootDir, "resolv.conf")
containerPath := resolvConfPath
result = append(result, fmt.Sprintf("%s:%s", hostPath, containerPath))

return result
}

func generateMountBindings(mounts []*runtime.Mount) []string {
result := make([]string, 0, len(mounts))
for _, m := range mounts {
Expand Down Expand Up @@ -300,6 +316,75 @@ func filterCRISandboxes(sandboxes []*runtime.PodSandbox, filter *runtime.PodSand
return filtered
}

// parseDNSOptions parse DNS options into resolv.conf format content,
// if none option is specified, will return empty with no error.
func parseDNSOptions(servers, searches, options []string) (string, error) {
resolvContent := ""

if len(searches) > 0 {
resolvContent += fmt.Sprintf("search %s\n", strings.Join(searches, " "))
}

if len(servers) > 0 {
resolvContent += fmt.Sprintf("nameserver %s\n", strings.Join(servers, "\nnameserver "))
}

if len(options) > 0 {
resolvContent += fmt.Sprintf("options %s\n", strings.Join(options, " "))
}

return resolvContent, nil
}

// copyFile copys src file to dest file
func copyFile(src, dest string, perm os.FileMode) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()

out, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
if err != nil {
return err
}
defer out.Close()

_, err = io.Copy(out, in)
return err
}

// setupSandboxFiles sets up necessary sandbox files.
func setupSandboxFiles(sandboxRootDir string, config *runtime.PodSandboxConfig) error {
// Set DNS options. Maintain a resolv.conf for the sandbox.
var resolvContent string
resolvPath := path.Join(sandboxRootDir, "resolv.conf")

var err error
dnsConfig := config.GetDnsConfig()
if dnsConfig != nil {
resolvContent, err = parseDNSOptions(dnsConfig.Servers, dnsConfig.Searches, dnsConfig.Options)
if err != nil {
return fmt.Errorf("failed to parse sandbox DNSConfig %+v: %v", dnsConfig, err)
}
}

if resolvContent == "" {
// Copy host's resolv.conf to resolvPath.
err = copyFile(resolvConfPath, resolvPath, 0644)
if err != nil {
return fmt.Errorf("failed to copy host's resolv.conf to %q: %v", resolvPath, err)
}
} else {
err = ioutil.WriteFile(resolvPath, []byte(resolvContent), 0644)
if err != nil {
return fmt.Errorf("failed to write resolv content to %q: %v", resolvPath, err)
}
}

return nil
}

// Container related tool functions.

func makeContainerName(s *runtime.PodSandboxConfig, c *runtime.ContainerConfig) string {
Expand Down
2 changes: 1 addition & 1 deletion hack/cri-test/test-cri.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ POUCH_SOCK="/var/run/pouchcri.sock"

# CRI_FOCUS focuses the test to run.
# With the CRI manager completes its function, we may need to expand this field.
CRI_FOCUS=${CRI_FOCUS:-"PodSandbox|AppArmor|Privileged is true|basic operations on container|Runtime info|mount propagation|volume and device|RunAsUser|container port|Streaming|NamespaceOption|SupplementalGroups"}
CRI_FOCUS=${CRI_FOCUS:-"PodSandbox|AppArmor|Privileged is true|basic operations on container|Runtime info|mount propagation|volume and device|RunAsUser|Networking|Streaming|NamespaceOption|SupplementalGroups"}

# CRI_SKIP skips the test to skip.
CRI_SKIP=${CRI_SKIP:-"RunAsUserName|HostNetwork"}
Expand Down