Skip to content

Commit

Permalink
remove container
Browse files Browse the repository at this point in the history
  • Loading branch information
tonicmuroq committed Jun 21, 2016
1 parent 449c633 commit 3e551c3
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 55 deletions.
10 changes: 8 additions & 2 deletions cluster/calcium/build_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ shift
if err := f.Sync(); err != nil {
return err
}
if err := f.Chmod(0755); err != nil {
return err
}

fr, err := os.Create(filepath.Join(buildDir, "launcheroot"))
if err != nil {
Expand All @@ -225,6 +228,9 @@ shift
if err := fr.Sync(); err != nil {
return err
}
if err := fr.Chmod(0755); err != nil {
return err
}

return nil
}
Expand All @@ -240,8 +246,8 @@ func createDockerfile(buildDir, uid, reponame string, specs types.Specs) error {
f.WriteString(fmt.Sprintf("FROM %s\n", specs.Base))
f.WriteString("ENV ERU 1\n")
f.WriteString(fmt.Sprintf("ADD %s /%s\n", reponame, specs.Appname))
f.WriteString("ADD launcher /user/local/bin/launcher\n")
f.WriteString("ADD launcheroot /user/local/bin/launcheroot\n")
f.WriteString("ADD launcher /usr/local/bin/launcher\n")
f.WriteString("ADD launcheroot /usr/local/bin/launcheroot\n")
f.WriteString(fmt.Sprintf("WORKDIR /%s\n", specs.Appname))
f.WriteString(fmt.Sprintf("RUN useradd -u %s -d /nonexistent -s /sbin/nologin -U %s\n", uid, specs.Appname))
for _, cmd := range specs.Build {
Expand Down
8 changes: 4 additions & 4 deletions cluster/calcium/create_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
// Create Container
// Use specs and options to create
// TODO need to call agent's API to create network
func (c *Calcium) CreateContainer(specs *types.Specs, opts *types.DeployOptions) (chan *types.CreateContainerMessage, error) {
func (c *Calcium) CreateContainer(specs types.Specs, opts *types.DeployOptions) (chan *types.CreateContainerMessage, error) {
ch := make(chan *types.CreateContainerMessage)

result, err := c.prepareNodes(opts.Podname, opts.CPUQuota, opts.Count)
Expand Down Expand Up @@ -118,7 +118,7 @@ func doPullImage(node *types.Node, image string) error {
return nil
}

func (c *Calcium) doCreateContainer(nodename string, cpumap []types.CPUMap, specs *types.Specs, opts *types.DeployOptions) []*types.CreateContainerMessage {
func (c *Calcium) doCreateContainer(nodename string, cpumap []types.CPUMap, specs types.Specs, opts *types.DeployOptions) []*types.CreateContainerMessage {
ms := make([]*types.CreateContainerMessage, len(cpumap))
node, err := c.GetNode(opts.Podname, nodename)
if err != nil {
Expand Down Expand Up @@ -159,7 +159,7 @@ func (c *Calcium) doCreateContainer(nodename string, cpumap []types.CPUMap, spec
continue
}

_, err = c.store.AddContainer(info.ID, opts.Podname, node.Name, containerName)
_, err = c.store.AddContainer(info.ID, opts.Podname, node.Name, containerName, quota)
if err != nil {
c.releaseQuota(node, quota)
continue
Expand All @@ -183,7 +183,7 @@ func (c *Calcium) releaseQuota(node *types.Node, quota types.CPUMap) {
c.store.UpdateNode(node)
}

func (c *Calcium) makeContainerOptions(quota map[string]int, specs *types.Specs, opts *types.DeployOptions) (
func (c *Calcium) makeContainerOptions(quota map[string]int, specs types.Specs, opts *types.DeployOptions) (
*enginecontainer.Config,
*enginecontainer.HostConfig,
*enginenetwork.NetworkingConfig,
Expand Down
11 changes: 10 additions & 1 deletion cluster/calcium/remove_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ func (c *Calcium) removeOneContainer(container *types.Container) error {
return err
}

// will be used later to update
node, err := c.GetNode(container.Podname, container.Nodename)
if err != nil {
return err
}

timeout := 5 * time.Second
err = container.Engine.ContainerStop(context.Background(), info.ID, &timeout)
if err != nil {
Expand All @@ -66,7 +72,6 @@ func (c *Calcium) removeOneContainer(container *types.Container) error {

rmOpts := enginetypes.ContainerRemoveOptions{
RemoveVolumes: true,
RemoveLinks: true,
Force: true,
}
err = container.Engine.ContainerRemove(context.Background(), info.ID, rmOpts)
Expand All @@ -84,5 +89,9 @@ func (c *Calcium) removeOneContainer(container *types.Container) error {
}
go container.Engine.ImageRemove(context.Background(), info.Image, rmiOpts)

node.CPU.Add(container.CPU)
if err := c.store.UpdateNode(node); err != nil {
return err
}
return c.store.RemoveContainer(info.ID)
}
2 changes: 1 addition & 1 deletion cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Cluster interface {

// cluster methods
BuildImage(repository, version, uid string) (chan *types.BuildImageMessage, error)
CreateContainer(*types.Specs, *types.DeployOptions) (chan *types.CreateContainerMessage, error)
CreateContainer(types.Specs, *types.DeployOptions) (chan *types.CreateContainerMessage, error)
// TODO add them later
// UpdateContainer() error
// MigrateContainer() error
Expand Down
59 changes: 59 additions & 0 deletions devtools/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,64 @@ def build_image(ctx, repo, version, uid):
click.echo(click.style('done', fg='green'))


@cli.command('deploy')
@click.pass_context
def create_container(ctx):
stub = _get_stub(ctx)
specs = """appname: "test-ci"
entrypoints:
web:
cmd: "python run.py"
ports:
- "5000/tcp"
network_mode: "none"
restart:
cmd: "python test_restart.py"
restart: "always"
log:
cmd: "python log.py"
fullcpu:
cmd: "python fullcpu.py"
restart: "always"
build:
- "pip install -r requirements.txt -i https://pypi.doubanio.com/simple/"
base: "hub.ricebook.net/base/alpine:python-2016.04.24"
"""
opts = pb.DeployOptions(specs=specs,
appname='test-ci',
image='hub.ricebook.net/test-ci:966fd83',
podname='dev',
entrypoint='log',
cpu_quota=1,
count=1,
env=['ENV_A=1', 'ENV_B=2'])

try:
for m in stub.CreateContainer(opts, 3600):
click.echo(m)
except AbortionError as e:
click.echo(click.style('abortion error: %s' % e.details, fg='red', bold=True))
ctx.exit(-1)

click.echo(click.style('done', fg='green'))


@cli.command('remove')
@click.argument('ids', nargs=-1)
@click.pass_context
def remove_container(ctx, ids):
stub = _get_stub(ctx)
ids = pb.ContainerIDs(ids=[pb.ContainerID(id=i) for i in ids])

try:
for m in stub.RemoveContainer(ids, 3600):
click.echo('%s: success %s, message: %s' % (m.id, m.success, m.message))
except AbortionError as e:
click.echo(click.style('abortion error: %s' % e.details, fg='red', bold=True))
ctx.exit(-1)

click.echo(click.style('done', fg='green'))


if __name__ == '__main__':
cli()
47 changes: 47 additions & 0 deletions rpc/rpc.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package rpc

import (
"fmt"

"gitlab.ricebook.net/platform/core/cluster"
"gitlab.ricebook.net/platform/core/rpc/gen"
"gitlab.ricebook.net/platform/core/types"
Expand Down Expand Up @@ -119,6 +121,7 @@ func (v *Virbranium) GetContainers(ctx context.Context, cids *pb.ContainerIDs) (
}

// streamed returned functions
// caller must ensure that timeout will not be too short because these actions take a little time
func (v *Virbranium) BuildImage(opts *pb.BuildImageOptions, stream pb.CoreRPC_BuildImageServer) error {
ch, err := v.cluster.BuildImage(opts.Repo, opts.Version, opts.Uid)
if err != nil {
Expand All @@ -134,14 +137,58 @@ func (v *Virbranium) BuildImage(opts *pb.BuildImageOptions, stream pb.CoreRPC_Bu
}

func (v *Virbranium) CreateContainer(opts *pb.DeployOptions, stream pb.CoreRPC_CreateContainerServer) error {
specs, err := types.LoadSpecs(opts.Specs)
if err != nil {
return err
}

ch, err := v.cluster.CreateContainer(specs, toCoreDeployOptions(opts))
if err != nil {
return err
}

for m := range ch {
if err := stream.Send(toRPCCreateContainerMessage(m)); err != nil {
return err
}
}
return nil
}

func (v *Virbranium) RemoveContainer(cids *pb.ContainerIDs, stream pb.CoreRPC_RemoveContainerServer) error {
ids := []string{}
for _, id := range cids.Ids {
ids = append(ids, id.Id)
}

if len(ids) == 0 {
return fmt.Errorf("No container ids given")
}

ch, err := v.cluster.RemoveContainer(ids)
if err != nil {
return err
}

for m := range ch {
if err := stream.Send(toRPCRemoveContainerMessage(m)); err != nil {
return err
}
}
return nil
}

func (v *Virbranium) RemoveImage(opts *pb.RemoveImageOptions, stream pb.CoreRPC_RemoveImageServer) error {
ch, err := v.cluster.RemoveImage(opts.Podname, opts.Nodename, opts.Images)
if err != nil {
return err
}

for m := range ch {
if err := stream.Send(toRPCRemoveImageMessage(m)); err != nil {
return err
}
}
return nil
}

Expand Down
57 changes: 51 additions & 6 deletions rpc/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@ import (
"gitlab.ricebook.net/platform/core/types"
)

func toRPCCPUMap(m types.CPUMap) map[string]int64 {
cpu := make(map[string]int64)
for label, value := range m {
cpu[label] = int64(value)
}
return cpu
}

func toRPCPod(p *types.Pod) *pb.Pod {
return &pb.Pod{Name: p.Name, Desc: p.Desc}
}

func toRPCNode(n *types.Node) *pb.Node {
cpu := make(map[string]int64)
for label, value := range n.CPU {
cpu[label] = int64(value)
}

return &pb.Node{
Name: n.Name,
Endpoint: n.Endpoint,
Podname: n.Podname,
Public: n.Public,
Cpu: cpu,
Cpu: toRPCCPUMap(n.CPU),
}
}

Expand All @@ -40,3 +43,45 @@ func toRPCBuildImageMessage(b *types.BuildImageMessage) *pb.BuildImageMessage {
},
}
}

func toCoreDeployOptions(d *pb.DeployOptions) *types.DeployOptions {
return &types.DeployOptions{
Appname: d.Appname,
Image: d.Image,
Podname: d.Podname,
Nodename: d.Nodename,
Entrypoint: d.Entrypoint,
CPUQuota: d.CpuQuota,
Count: int(d.Count),
Env: d.Env,
Networks: d.Networks,
Raw: d.Raw,
}
}

func toRPCCreateContainerMessage(c *types.CreateContainerMessage) *pb.CreateContainerMessage {
return &pb.CreateContainerMessage{
Podname: c.Podname,
Nodename: c.Nodename,
Id: c.ContainerID,
Name: c.ContainerName,
Success: c.Success,
Cpu: toRPCCPUMap(c.CPU),
}
}

func toRPCRemoveImageMessage(r *types.RemoveImageMessage) *pb.RemoveImageMessage {
return &pb.RemoveImageMessage{
Image: r.Image,
Success: r.Success,
Messages: r.Messages,
}
}

func toRPCRemoveContainerMessage(r *types.RemoveContainerMessage) *pb.RemoveContainerMessage {
return &pb.RemoveContainerMessage{
Id: r.ContainerID,
Success: r.Success,
Message: r.Message,
}
}
3 changes: 2 additions & 1 deletion store/etcd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (k *Krypton) GetContainers(ids []string) ([]*types.Container, error) {
// actually if we already know its node, we will know its pod
// but we still store it
// storage path in etcd is `/eru-core/container/:containerid`
func (k *Krypton) AddContainer(id, podname, nodename, name string) (*types.Container, error) {
func (k *Krypton) AddContainer(id, podname, nodename, name string, cpu types.CPUMap) (*types.Container, error) {
// first we check if node really exists
node, err := k.GetNode(podname, nodename)
if err != nil {
Expand All @@ -81,6 +81,7 @@ func (k *Krypton) AddContainer(id, podname, nodename, name string) (*types.Conta
Podname: podname,
Nodename: nodename,
Name: name,
CPU: cpu,
Engine: node.Engine,
}

Expand Down
2 changes: 1 addition & 1 deletion store/etcd/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (k *Krypton) GetNodesByPod(podname string) ([]*types.Node, error) {
// update a node, save it to etcd
// storage path in etcd is `/eru-core/pod/:podname/node/:nodename/info`
func (k *Krypton) UpdateNode(node *types.Node) error {
key := fmt.Sprintf(podNodesKey, node.Podname, node.Name)
key := fmt.Sprintf(nodeInfoKey, node.Podname, node.Name)
bytes, err := json.Marshal(node)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Store interface {
UpdateNode(*types.Node) error

// container
AddContainer(id, podname, nodename, name string) (*types.Container, error)
AddContainer(id, podname, nodename, name string, cpu types.CPUMap) (*types.Container, error)
GetContainer(id string) (*types.Container, error)
GetContainers(ids []string) ([]*types.Container, error)
RemoveContainer(id string) error
Expand Down
1 change: 1 addition & 0 deletions types/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Container struct {
Podname string `json:"podname"`
Nodename string `json:"nodename"`
Name string `json:"name"`
CPU CPUMap `json:"cpu"`
Engine *engineapi.Client `json:"-"`
}

Expand Down
Loading

0 comments on commit 3e551c3

Please sign in to comment.