Implement CreateContainer
Signed-off-by: Haiyan Meng <hmeng@redhat.com>
This commit is contained in:
parent
e3a34aa26d
commit
c2ee13d187
8 changed files with 567 additions and 12 deletions
|
@ -6,6 +6,8 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
pb "github.com/kubernetes/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||
"github.com/mrunalp/ocid/oci"
|
||||
"github.com/mrunalp/ocid/utils"
|
||||
"github.com/opencontainers/ocitools/generate"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -87,9 +89,10 @@ func (s *Server) CreatePodSandbox(ctx context.Context, req *pb.CreatePodSandboxR
|
|||
|
||||
labels := req.GetConfig().GetLabels()
|
||||
s.addSandbox(&sandbox{
|
||||
name: name,
|
||||
logDir: logDir,
|
||||
labels: labels,
|
||||
name: name,
|
||||
logDir: logDir,
|
||||
labels: labels,
|
||||
containers: []*oci.Container{},
|
||||
})
|
||||
|
||||
annotations := req.GetConfig().GetAnnotations()
|
||||
|
@ -156,8 +159,244 @@ func (s *Server) ListPodSandbox(context.Context, *pb.ListPodSandboxRequest) (*pb
|
|||
}
|
||||
|
||||
// CreateContainer creates a new container in specified PodSandbox
|
||||
func (s *Server) CreateContainer(context.Context, *pb.CreateContainerRequest) (*pb.CreateContainerResponse, error) {
|
||||
return nil, nil
|
||||
func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerRequest) (*pb.CreateContainerResponse, error) {
|
||||
// The id of the PodSandbox
|
||||
podSandboxId := req.GetPodSandboxId()
|
||||
if !s.hasSandbox(podSandboxId) {
|
||||
return nil, fmt.Errorf("the pod sandbox (%s) does not exist", podSandboxId)
|
||||
}
|
||||
|
||||
// The config of the container
|
||||
containerConfig := req.GetConfig()
|
||||
if containerConfig == nil {
|
||||
return nil, fmt.Errorf("CreateContainerRequest.ContainerConfig is nil")
|
||||
}
|
||||
|
||||
name := containerConfig.GetName()
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("CreateContainerRequest.ContainerConfig.Name is empty")
|
||||
}
|
||||
|
||||
// containerDir is the dir for the container bundle.
|
||||
containerDir := filepath.Join(s.runtime.ContainerDir(), name)
|
||||
|
||||
if _, err := os.Stat(containerDir); err == nil {
|
||||
return nil, fmt.Errorf("container (%s) already exists", containerDir)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(containerDir, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imageSpec := containerConfig.GetImage()
|
||||
if imageSpec == nil {
|
||||
return nil, fmt.Errorf("CreateContainerRequest.ContainerConfig.Image is nil")
|
||||
}
|
||||
|
||||
image := imageSpec.GetImage()
|
||||
if image == "" {
|
||||
return nil, fmt.Errorf("CreateContainerRequest.ContainerConfig.Image.Image is empty")
|
||||
}
|
||||
|
||||
// creates a spec Generator with the default spec.
|
||||
specgen := generate.New()
|
||||
|
||||
// by default, the root path is an empty string.
|
||||
// here set it to be "rootfs".
|
||||
specgen.SetRootPath("rootfs")
|
||||
|
||||
args := containerConfig.GetArgs()
|
||||
if args == nil {
|
||||
args = []string{"/bin/sh"}
|
||||
}
|
||||
specgen.SetProcessArgs(args)
|
||||
|
||||
cwd := containerConfig.GetWorkingDir()
|
||||
if cwd == "" {
|
||||
cwd = "/"
|
||||
}
|
||||
specgen.SetProcessCwd(cwd)
|
||||
|
||||
envs := containerConfig.GetEnvs()
|
||||
if envs != nil {
|
||||
for _, item := range envs {
|
||||
key := item.GetKey()
|
||||
value := item.GetValue()
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
env := fmt.Sprintf("%s=%s", key, value)
|
||||
specgen.AddProcessEnv(env)
|
||||
}
|
||||
}
|
||||
|
||||
mounts := containerConfig.GetMounts()
|
||||
for _, mount := range mounts {
|
||||
dest := mount.GetContainerPath()
|
||||
if dest == "" {
|
||||
return nil, fmt.Errorf("Mount.ContainerPath is empty")
|
||||
}
|
||||
|
||||
src := mount.GetHostPath()
|
||||
if src == "" {
|
||||
return nil, fmt.Errorf("Mount.HostPath is empty")
|
||||
}
|
||||
|
||||
options := "rw"
|
||||
if mount.GetReadonly() {
|
||||
options = "ro"
|
||||
}
|
||||
|
||||
//TODO(hmeng): how to use this info? Do we need to handle relabel a FS with Selinux?
|
||||
selinuxRelabel := mount.GetSelinuxRelabel()
|
||||
fmt.Printf("selinuxRelabel: %v\n", selinuxRelabel)
|
||||
|
||||
specgen.AddBindMount(src, dest, options)
|
||||
|
||||
}
|
||||
|
||||
labels := containerConfig.GetLabels()
|
||||
|
||||
annotations := containerConfig.GetAnnotations()
|
||||
if annotations != nil {
|
||||
for k, v := range annotations {
|
||||
specgen.AddAnnotation(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
if containerConfig.GetPrivileged() {
|
||||
specgen.SetupPrivileged(true)
|
||||
}
|
||||
|
||||
if containerConfig.GetReadonlyRootfs() {
|
||||
specgen.SetRootReadonly(true)
|
||||
}
|
||||
|
||||
logPath := containerConfig.GetLogPath()
|
||||
|
||||
if containerConfig.GetTty() {
|
||||
specgen.SetProcessTerminal(true)
|
||||
}
|
||||
|
||||
linux := containerConfig.GetLinux()
|
||||
if linux != nil {
|
||||
resources := linux.GetResources()
|
||||
if resources != nil {
|
||||
cpuPeriod := resources.GetCpuPeriod()
|
||||
if cpuPeriod != 0 {
|
||||
specgen.SetLinuxResourcesCPUPeriod(uint64(cpuPeriod))
|
||||
}
|
||||
|
||||
cpuQuota := resources.GetCpuQuota()
|
||||
if cpuQuota != 0 {
|
||||
specgen.SetLinuxResourcesCPUQuota(uint64(cpuQuota))
|
||||
}
|
||||
|
||||
cpuShares := resources.GetCpuShares()
|
||||
if cpuShares != 0 {
|
||||
specgen.SetLinuxResourcesCPUShares(uint64(cpuShares))
|
||||
}
|
||||
|
||||
memoryLimit := resources.GetMemoryLimitInBytes()
|
||||
if memoryLimit != 0 {
|
||||
specgen.SetLinuxResourcesMemoryLimit(uint64(memoryLimit))
|
||||
}
|
||||
|
||||
oomScoreAdj := resources.GetOomScoreAdj()
|
||||
specgen.SetLinuxResourcesOOMScoreAdj(int(oomScoreAdj))
|
||||
}
|
||||
|
||||
capabilities := linux.GetCapabilities()
|
||||
if capabilities != nil {
|
||||
addCaps := capabilities.GetAddCapabilities()
|
||||
if addCaps != nil {
|
||||
for _, cap := range addCaps {
|
||||
if err := specgen.AddProcessCapability(cap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dropCaps := capabilities.GetDropCapabilities()
|
||||
if dropCaps != nil {
|
||||
for _, cap := range dropCaps {
|
||||
if err := specgen.DropProcessCapability(cap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selinuxOptions := linux.GetSelinuxOptions()
|
||||
if selinuxOptions != nil {
|
||||
user := selinuxOptions.GetUser()
|
||||
if user == "" {
|
||||
return nil, fmt.Errorf("SELinuxOption.User is empty")
|
||||
}
|
||||
|
||||
role := selinuxOptions.GetRole()
|
||||
if role == "" {
|
||||
return nil, fmt.Errorf("SELinuxOption.Role is empty")
|
||||
}
|
||||
|
||||
t := selinuxOptions.GetType()
|
||||
if t == "" {
|
||||
return nil, fmt.Errorf("SELinuxOption.Type is empty")
|
||||
}
|
||||
|
||||
level := selinuxOptions.GetLevel()
|
||||
if level == "" {
|
||||
return nil, fmt.Errorf("SELinuxOption.Level is empty")
|
||||
}
|
||||
|
||||
specgen.SetProcessSelinuxLabel(fmt.Sprintf("%s:%s:%s:%s", user, role, t, level))
|
||||
}
|
||||
|
||||
user := linux.GetUser()
|
||||
if user != nil {
|
||||
uid := user.GetUid()
|
||||
specgen.SetProcessUID(uint32(uid))
|
||||
|
||||
gid := user.GetGid()
|
||||
specgen.SetProcessGID(uint32(gid))
|
||||
|
||||
groups := user.GetAdditionalGids()
|
||||
if groups != nil {
|
||||
for _, group := range groups {
|
||||
specgen.AddProcessAdditionalGid(uint32(group))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The config of the PodSandbox
|
||||
sandboxConfig := req.GetSandboxConfig()
|
||||
fmt.Printf("sandboxConfig: %v\n", sandboxConfig)
|
||||
|
||||
if err := specgen.SaveToFile(filepath.Join(containerDir, "config.json")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: copy the rootfs into the bundle.
|
||||
// Currently, utils.CreateFakeRootfs is used to populate the rootfs.
|
||||
if err := utils.CreateFakeRootfs(containerDir, image); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
container, err := oci.NewContainer(name, containerDir, logPath, labels, podSandboxId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.runtime.CreateContainer(container); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.addContainer(container)
|
||||
|
||||
return &pb.CreateContainerResponse{
|
||||
ContainerId: &name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// StartContainer starts the container.
|
||||
|
|
|
@ -37,25 +37,44 @@ func New(runtimePath, sandboxDir, containerDir string) (*Server, error) {
|
|||
return nil, err
|
||||
}
|
||||
sandboxes := make(map[string]*sandbox)
|
||||
containers := make(map[string]*oci.Container)
|
||||
return &Server{
|
||||
runtime: r,
|
||||
sandboxDir: sandboxDir,
|
||||
state: &serverState{
|
||||
sandboxes: sandboxes,
|
||||
sandboxes: sandboxes,
|
||||
containers: containers,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type serverState struct {
|
||||
sandboxes map[string]*sandbox
|
||||
sandboxes map[string]*sandbox
|
||||
containers map[string]*oci.Container
|
||||
}
|
||||
|
||||
type sandbox struct {
|
||||
name string
|
||||
logDir string
|
||||
labels map[string]string
|
||||
name string
|
||||
logDir string
|
||||
labels map[string]string
|
||||
containers []*oci.Container
|
||||
}
|
||||
|
||||
func (s *Server) addSandbox(sb *sandbox) {
|
||||
s.state.sandboxes[sb.name] = sb
|
||||
}
|
||||
|
||||
func (s *Server) hasSandbox(name string) bool {
|
||||
_, ok := s.state.sandboxes[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (s *sandbox) addContainer(c *oci.Container) {
|
||||
s.containers = append(s.containers, c)
|
||||
}
|
||||
|
||||
func (s *Server) addContainer(c *oci.Container) {
|
||||
sandbox := s.state.sandboxes[c.Sandbox()]
|
||||
sandbox.addContainer(c)
|
||||
s.state.containers[c.Name()] = c
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue