Skip to content

Commit bdbf90b

Browse files
support create a container with a given id
Signed-off-by: allen.wang <[email protected]>
1 parent a0171dc commit bdbf90b

File tree

13 files changed

+422
-72
lines changed

13 files changed

+422
-72
lines changed

Makefile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# Copyright The PouchContainer Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
115
# TEST_FLAGS used as flags of go test.
216
TEST_FLAGS ?= -v --race
317

@@ -16,6 +30,13 @@ INTEGRATION_TESTCASE_BINARY_NAME=pouchd-integration-test
1630
# DEST_DIR is base path used to install pouch & pouchd
1731
DEST_DIR=/usr/local
1832

33+
# PREFIX is base path to install pouch & pouchd
34+
# PREFIX will override the value of DEST_DIR when specified
35+
# example: make install PREFIX=/usr
36+
ifdef PREFIX
37+
DEST_DIR := $(PREFIX)
38+
endif
39+
1940
# the following variables used for the daemon build
2041

2142
# API_VERSION is used for daemon API Version in go build.

VAGRANT.md

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
# Vagrant support for pouch
1+
# Vagrant support for PouchContainer
22

3-
You can using Vagrant to quickly experience pouch or cross compile on non-linux.
3+
You can using [Vagrant](https://www.vagrantup.com) to quickly experience PouchContainer or cross compile on non-linux.
44

55
## Requirements
66

77
* Vagrant 1.9.x or newer
88
* VirtuaBox
99

10-
## Get started
10+
## Getting Started
1111

1212
```bash
1313
vagrant up
@@ -18,22 +18,56 @@ pouch run -d --name nginx -p 80:80 nginx
1818
curl http://localhost
1919
```
2020

21-
## Build pouch with vagrant
21+
## Getting Started with Kubernetes
2222

2323
```bash
24+
# On macOS or Linux
25+
POUCH_KUBE=true vagrant up
2426

25-
# On MacOS or Linux
26-
export POUCH_BUILD=true
27+
# On Windows
28+
set POUCH_KUBE=true
2729
vagrant up
2830

31+
vagrant ssh -c "sudo -i"
32+
33+
$ kubectl cluster-info
34+
Kubernetes master is running at https://10.0.2.15:6443
35+
KubeDNS is running at https://10.0.2.15:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
36+
37+
38+
$ kubectl get cs
39+
NAME STATUS MESSAGE
40+
controller-manager Healthy ok
41+
scheduler Healthy ok
42+
etcd-0 Healthy {"health": "true"}
43+
44+
$ kubectl get po -o wide --all-namespaces
45+
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
46+
default nginx-6dc97b4cbd-cq4pb 1/1 Running 0 2m 10.244.0.2 pouch
47+
default nginx-6dc97b4cbd-ktlwc 1/1 Running 0 2m 10.244.0.3 pouch
48+
kube-system etcd-pouch 1/1 Running 0 3m 10.0.2.15 pouch
49+
kube-system kube-apiserver-pouch 1/1 Running 0 2m 10.0.2.15 pouch
50+
kube-system kube-controller-manager-pouch 1/1 Running 0 2m 10.0.2.15 pouch
51+
kube-system kube-dns-b4bd9576-gwqzv 3/3 Running 0 2m 10.244.0.4 pouch
52+
kube-system kube-flannel-ds-amd64-vd466 1/1 Running 1 2m 10.0.2.15 pouch
53+
kube-system kube-proxy-c8l8j 1/1 Running 0 2m 10.0.2.15 pouch
54+
kube-system kube-scheduler-pouch 1/1 Running 0 2m 10.0.2.15 pouch
55+
```
56+
57+
## Build pouch with vagrant
58+
59+
```bash
60+
# On macOS or Linux
61+
POUCH_BUILD=true vagrant up
62+
2963
# On Windows
3064
set POUCH_BUILD=true
3165
vagrant up
3266

33-
# Install compiled pouch binarys for pouch service.
67+
# Install compiled pouch binaries for pouch service.
3468
vagrant ssh -c "sudo -i"
3569
cd ~/go/src/github.com/alibaba/pouch
36-
make DEST_DIR=/usr install
70+
make PREFIX=/usr install
3771
systemctl restart pouch
3872
pouch version
39-
```
73+
```

Vagrantfile

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ Vagrant.configure("2") do |config|
1313
config.vm.define :pouch do |pouch|
1414
pouch.vm.hostname = "pouch"
1515
pouch.vm.box = "ubuntu/xenial64"
16+
pouch.vm.provider 'virtualbox' do |v, override|
17+
v.memory = 2048
18+
end
19+
1620
pouch.vm.provision "shell", inline: <<-SHELL
1721
until apt-get update &> /dev/null; do echo "Waiting apt-get for 3 seconds..."; sleep 3; done
1822
apt-get --no-install-recommends install lxcfs
@@ -40,8 +44,31 @@ Vagrant.configure("2") do |config|
4044
4145
mkdir -p $GOPATH/src/github.com/alibaba
4246
ln -s /vagrant $GOPATH/src/github.com/alibaba/pouch
43-
cd $GOPATH/src/github.com/alibaba/pouch && make install
47+
cd $GOPATH/src/github.com/alibaba/pouch
48+
make PREFIX=/usr install
49+
systemctl restart pouch
4450
SHELL
4551
end
52+
53+
if ENV["POUCH_KUBE"] == "true"
54+
env = {
55+
"KUBERNETES_VERSION" => "1.10",
56+
"CRI_VERSION" => "v1alpha2",
57+
"RELEASE_UBUNTU" => "v1.10.2",
58+
"MASTER_NODE" => "true",
59+
"INSTALL_FLANNEL" => "true",
60+
"INSTALL_SAMPLE" => "true"
61+
}
62+
63+
if ENV["http_proxy"] != ""
64+
proxy = ENV["http_proxy"]
65+
66+
env["http_proxy"] = proxy
67+
env["https_proxy"] = proxy
68+
env["no_proxy"] = "localhost,127.0.0.1,10.96.0.0/16,10.0.0.0/16,10.244.0.0/16"
69+
end
70+
71+
pouch.vm.provision "install_kubernetes", type: "shell", path: "hack/kubernetes/allinone_aliyun.sh", env: env
72+
end
4673
end
4774
end

apis/server/container_bridge.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ func (s *Server) createContainer(ctx context.Context, rw http.ResponseWriter, re
4343
logCreateOptions("container", config)
4444

4545
name := req.FormValue("name")
46+
//consider set specific id by url params
47+
specificID := req.FormValue("recover-id")
48+
if specificID != "" {
49+
config.SpecificID = specificID
50+
}
4651

4752
// to do compensation to potential nil pointer after validation
4853
if config.HostConfig == nil {

apis/swagger.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,6 +2211,13 @@ definitions:
22112211
description: "net priority."
22122212
type: "integer"
22132213
default: 0
2214+
SpecificID:
2215+
type: "string"
2216+
description: |
2217+
Create container with given id.
2218+
The length of given id should be in [12,64].
2219+
The characters of given id should be in 0123456789abcdef.
2220+
By default, given id is unnecessary.
22142221
22152222
ContainerCreateResp:
22162223
description: "response returned by daemon when container create successfully"

apis/types/container_config.go

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/common_flags.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ func addCommonFlags(flagSet *pflag.FlagSet) *container {
6161
flagSet.Int64Var(&c.oomScoreAdj, "oom-score-adj", -500, "Tune host's OOM preferences (-1000 to 1000)")
6262

6363
flagSet.StringVar(&c.name, "name", "", "Specify name of container")
64+
flagSet.StringVar(&c.specificID, "specific-id", "", "Specify id of container, length of id should be in [12,64], characters of id should be in '0123456789abcdef'")
6465

6566
flagSet.StringSliceVar(&c.networks, "net", nil, "Set networks to container")
6667
flagSet.StringSliceVarP(&c.ports, "port", "p", nil, "Set container ports mapping")

cli/container.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type container struct {
2525
hostname string
2626
rm bool
2727
disableNetworkFiles bool
28+
specificID string
2829

2930
blkioWeight uint16
3031
blkioWeightDevice config.WeightDevice
@@ -194,6 +195,7 @@ func (c *container) config() (*types.ContainerCreateConfig, error) {
194195
QuotaID: c.quotaID,
195196
SpecAnnotation: specAnnotation,
196197
NetPriority: c.netPriority,
198+
SpecificID: c.specificID,
197199
},
198200

199201
HostConfig: &types.HostConfig{

ctrd/container.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,18 @@ func (c *Client) execContainer(ctx context.Context, process *Process) error {
122122
exitTime: status.ExitTime(),
123123
}
124124

125-
// run hook if not got fail here
126-
if err := <-fail; err == nil {
127-
for _, hook := range c.hooks {
128-
if err := hook(process.ExecID, msg); err != nil {
129-
logrus.Errorf("failed to execute the exec exit hooks: %v", err)
130-
break
131-
}
125+
if err := <-fail; err != nil {
126+
msg.err = err
127+
// exit code should not be zero when exec get failed.
128+
if msg.exitCode == 0 {
129+
msg.exitCode = 126
130+
}
131+
}
132+
// XXX: if exec process get run, io should be closed in this function,
133+
for _, hook := range c.hooks {
134+
if err := hook(process.ExecID, msg); err != nil {
135+
logrus.Errorf("failed to execute the exec exit hooks: %v", err)
136+
break
132137
}
133138
}
134139

@@ -141,7 +146,6 @@ func (c *Client) execContainer(ctx context.Context, process *Process) error {
141146
// start the exec process
142147
if err := execProcess.Start(ctx); err != nil {
143148
fail <- err
144-
return errors.Wrap(err, "failed to exec process")
145149
}
146150

147151
return nil

daemon/mgr/container.go

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package mgr
33
import (
44
"context"
55
"fmt"
6+
"io"
67
"io/ioutil"
78
"os"
89
"os/exec"
@@ -34,6 +35,7 @@ import (
3435
containerdtypes "github.com/containerd/containerd/api/types"
3536
"github.com/containerd/containerd/errdefs"
3637
"github.com/containerd/containerd/mount"
38+
"github.com/docker/docker/pkg/stdcopy"
3739
"github.com/docker/libnetwork"
3840
"github.com/go-openapi/strfmt"
3941
"github.com/imdario/mergo"
@@ -263,6 +265,9 @@ func (mgr *ContainerManager) Restore(ctx context.Context) error {
263265

264266
// Create checks passed in parameters and create a Container object whose status is set at Created.
265267
func (mgr *ContainerManager) Create(ctx context.Context, name string, config *types.ContainerCreateConfig) (resp *types.ContainerCreateResp, err error) {
268+
var (
269+
id = ""
270+
)
266271
// cleanup allocated resources when failed
267272
cleanups := []func() error{}
268273
defer func() {
@@ -291,16 +296,43 @@ func (mgr *ContainerManager) Create(ctx context.Context, name string, config *ty
291296
return nil, errors.Wrapf(errtypes.ErrInvalidParam, "NetworkingConfig cannot be empty")
292297
}
293298

294-
id, err := mgr.generateID()
295-
if err != nil {
296-
return nil, err
299+
if config.SpecificID != "" {
300+
if len(config.SpecificID) < 12 || len(config.SpecificID) > 64 {
301+
return nil, errors.Wrap(errtypes.ErrInvalidParam, "Container id length should be in [12,64]")
302+
}
303+
//characters of containerID should be in "0123456789abcdef"
304+
for _, c := range []byte(config.SpecificID) {
305+
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) {
306+
return nil, errors.Wrap(errtypes.ErrInvalidParam, "The characters of container id should be in '0123456789abcdef'")
307+
}
308+
}
309+
310+
if mgr.cache.Get(config.SpecificID).Exist() {
311+
return nil, errors.Wrap(errtypes.ErrAlreadyExisted, "container id: "+config.SpecificID)
312+
}
313+
id = config.SpecificID
314+
} else {
315+
tmpID, err := mgr.generateID()
316+
if err != nil {
317+
return nil, err
318+
}
319+
id = tmpID
297320
}
321+
//put container id to cache to prevent concurrent containerCreateReq with same specific id
322+
mgr.cache.Put(id, nil)
323+
defer func() {
324+
//clear cache
325+
if err != nil {
326+
mgr.cache.Remove(id)
327+
}
328+
}()
298329

299330
if name == "" {
300331
name = mgr.generateName(id)
301332
} else if mgr.NameToID.Get(name).Exist() {
302333
return nil, errors.Wrapf(errtypes.ErrAlreadyExisted, "container name %s", name)
303334
}
335+
//todo: consider to do as the former ?
304336

305337
// set hostname.
306338
if config.Hostname.String() == "" {
@@ -1860,17 +1892,21 @@ func (mgr *ContainerManager) execExitedAndRelease(id string, m *ctrd.Message) er
18601892
execConfig.Running = false
18611893
execConfig.Error = m.RawError()
18621894

1863-
io := mgr.IOs.Get(id)
1864-
if io == nil {
1895+
eio := mgr.IOs.Get(id)
1896+
if eio == nil {
18651897
return nil
18661898
}
18671899

18681900
if err := m.RawError(); err != nil {
1869-
fmt.Fprintf(io.Stdout, "%v\n", err)
1901+
var stdout io.Writer = eio.Stdout
1902+
if !execConfig.Tty && !eio.MuxDisabled {
1903+
stdout = stdcopy.NewStdWriter(stdout, stdcopy.Stdout)
1904+
}
1905+
stdout.Write([]byte(err.Error() + "\r\n"))
18701906
}
18711907

18721908
// close io
1873-
io.Close()
1909+
eio.Close()
18741910
mgr.IOs.Remove(id)
18751911

18761912
return nil

0 commit comments

Comments
 (0)