Skip to content

Commit 57e7fc3

Browse files
Sivaram Mothikimboersma
authored andcommitted
feat(swarm): add run functionality
feat(swarm): add default value to swarm host key in templates feat(swarm): add deis/scheduler keys to confd fix(swarm): adjust swarm.py python coding style fix(swarm): add confd template fix(swarm): modify swarm host etcd key fix(swarm): change swarm etcdpath end point fix(scheduler): create seperate etcd directory for deis scheduler fix(swarm): make docker-py client cpu limits compatible with docker swarm fix(tests): check welcome to ngnix page if error is 503
1 parent 757a4e1 commit 57e7fc3

9 files changed

Lines changed: 134 additions & 57 deletions

File tree

contrib/coreos/user-data.example

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,19 @@ coreos:
3232
ExecStart=/usr/bin/bash -c 'if fleetd --version | grep -q 0.9.1; then curl -sSL --retry 5 --retry-delay 2 -o /opt/bin/fleetd-0.9.2 https://s3-us-west-2.amazonaws.com/opdemand/fleetd-v0.9.2 && chmod +x /opt/bin/fleetd-0.9.2 && mkdir -p /etc/systemd/system/fleet.service.d/ && ln -sf /opt/conf/fleetd-092-custom-binary.conf /etc/systemd/system/fleet.service.d/99-upgrade-fleet-091.conf; else rm -f /etc/systemd/system/fleet.service.d/99-upgrade-fleet-091.conf; fi'
3333
RemainAfterExit=yes
3434
Type=oneshot
35-
- name: docker.service
36-
command: restart
35+
- name: docker-tcp.socket
36+
command: start
37+
enable: true
3738
content: |
3839
[Unit]
39-
Description=Docker Application Container Engine
40-
Documentation=http://docs.docker.io
41-
After=network.target
42-
[Service]
43-
ExecStartPre=/bin/mount --make-rprivate /
44-
# Run docker but don't have docker automatically restart
45-
# containers. This is a job for systemd and unit files.
46-
ExecStart=/usr/bin/docker -d -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock -D
40+
Description=Docker Socket for the API
4741

42+
[Socket]
43+
ListenStream=2375
44+
BindIPv6Only=both
45+
Service=docker.service
4846
[Install]
49-
WantedBy=multi-user.target
47+
WantedBy=sockets.target
5048
- name: stop-update-engine.service
5149
command: start
5250
content: |
@@ -128,7 +126,7 @@ write_files:
128126
content: |
129127
[Service]
130128
EnvironmentFile=/etc/environment_proxy
131-
Environment="DOCKER_OPTS=--insecure-registry 10.0.0.0/8 --insecure-registry 172.16.0.0/12 --insecure-registry 192.168.0.0/16 --insecure-registry 100.64.0.0/10 --insecure-registry registry.smothiki.io:5000"
129+
Environment="DOCKER_OPTS=--insecure-registry 10.0.0.0/8 --insecure-registry 172.16.0.0/12 --insecure-registry 192.168.0.0/16 --insecure-registry 100.64.0.0/10 "
132130
- path: /run/deis/bin/get_image
133131
permissions: '0755'
134132
content: |

controller/conf.d/confd_settings.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ keys = [
1010
"/deis/registry",
1111
"/deis/domains",
1212
"/deis/platform",
13-
"/deis/scheduler/swarm/host",
13+
"/deis/scheduler",
1414
]
1515
reload_cmd = "/app/bin/reload"

controller/scheduler/swarm.py

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,49 @@
1-
import logging
2-
from docker import Client
1+
import re
2+
import time
33

44
from django.conf import settings
5+
from docker import Client
6+
7+
from .states import JobState
58

69

10+
MATCH = re.compile(
11+
r'(?P<app>[a-z0-9-]+)_?(?P<version>v[0-9]+)?\.?(?P<c_type>[a-z-_]+)?.(?P<c_num>[0-9]+)')
12+
713

814
class SwarmClient(object):
9-
def __init__(self,target, auth, options, pkey):
10-
self.target = settings.SWARM_HOST
15+
16+
def __init__(self, target, auth, options, pkey):
17+
self.target = settings.SWARM_HOST
1118
# single global connection
12-
self.registry = settings.REGISTRY_HOST+":"+settings.REGISTRY_PORT
13-
self.docker_cli = Client(base_url='tcp://'+self.target+':'+"2395",timeout=1200)
19+
self.registry = settings.REGISTRY_HOST + ':' + settings.REGISTRY_PORT
20+
self.docker_cli = Client("tcp://{}:2395".format(self.target),
21+
timeout=1200, version='1.17')
1422

1523
def create(self, name, image, command='', template=None, **kwargs):
1624
"""Create a container"""
17-
cimage=self.registry+"/"+image
18-
cname=name
19-
ccommand=command
20-
# self.docker_cli.pull(cimage, stream=False,insecure_registry=True)
21-
self.docker_cli.create_container(image=cimage,name=cname,command=ccommand)#,hostname=self._get_hostname(cname),ports=self._get_ports(cimage))
22-
self.docker_cli.start(cname, port_bindings=self._get_portbindings(cimage),publish_all_ports=True)
25+
cimage = self.registry + '/' + image
26+
affinity = "affinity:container!=~/{}*/".format(re.split(r'_v\d.', name)[0])
27+
l = locals().copy()
28+
l.update(re.match(MATCH, name).groupdict())
29+
mem = kwargs.get('memory', {}).get(l['c_type'])
30+
if mem:
31+
mem = mem.lower()
32+
if mem[-2:-1].isalpha() and mem[-1].isalpha():
33+
mem = mem[:-1]
34+
cpu = kwargs.get('cpu', {}).get(l['c_type'])
35+
self.docker_cli.create_container(image=cimage, name=name,
36+
command=command.encode('utf-8'), mem_limit=mem,
37+
cpu_shares=cpu,
38+
environment=[affinity])
39+
self.docker_cli.stop(name)
2340

2441
def start(self, name):
2542
"""
2643
Start a container
2744
"""
28-
self.docker_cli.start(name)
45+
self.docker_cli.start(name, publish_all_ports=True)
46+
2947
return
3048

3149
def stop(self, name):
@@ -34,54 +52,94 @@ def stop(self, name):
3452
"""
3553
self.docker_cli.stop(name)
3654
return
55+
3756
def destroy(self, name):
3857
"""
3958
Destroy a container
4059
"""
41-
self.docker_cli.stop(name)
60+
self.stop(name)
4261
self.docker_cli.remove_container(name)
4362
return
4463

4564
def run(self, name, image, entrypoint, command):
4665
"""
4766
Run a one-off command
4867
"""
49-
# dump input into a json object for testing purposes
50-
return 0, json.dumps({'name': name,
51-
'image': image,
52-
'entrypoint': entrypoint,
53-
'command': command})
68+
cimage = self.registry + '/' + image
69+
# use affinity for nodes that already have the image
70+
affinity = "affinity:image==~{}".format(cimage)
71+
self.docker_cli.create_container(image=cimage, name=name,
72+
command=command.encode('utf-8'),
73+
environment=[affinity],
74+
entrypoint=[entrypoint])
75+
time.sleep(2)
76+
self.start(name)
77+
rc = 0
78+
while (True):
79+
if self._get_container_state(name) == JobState.created:
80+
break
81+
time.sleep(1)
82+
try:
83+
output = self.docker_cli.logs(name)
84+
return rc, output
85+
except:
86+
rc = 1
87+
return rc, output
88+
89+
def _get_container_state(self, name):
90+
try:
91+
if self.docker_cli.inspect_container(name)['State']['Running']:
92+
return JobState.up
93+
else:
94+
return JobState.created
95+
except:
96+
return JobState.destroyed
97+
98+
def state(self, name):
99+
try:
100+
# NOTE (bacongobbler): this call to ._get_unit() acts as a pre-emptive check to
101+
# determine if the job no longer exists (will raise a RuntimeError on 404)
102+
for _ in range(30):
103+
return self._get_container_state(name)
104+
time.sleep(1)
105+
# FIXME (bacongobbler): when fleet loads a job, sometimes it'll automatically start and
106+
# stop the container, which in our case will return as 'failed', even though
107+
# the container is perfectly fine.
108+
except KeyError:
109+
# failed retrieving a proper response from the fleet API
110+
return JobState.error
111+
except RuntimeError:
112+
# failed to retrieve a response from the fleet API,
113+
# which means it does not exist
114+
return JobState.destroyed
54115

55116
def attach(self, name):
56117
"""
57118
Attach to a job's stdin, stdout and stderr
58119
"""
59-
return StringIO(), StringIO(), StringIO()
120+
raise NotImplementedError
60121

61122
def _get_hostname(self, application_name):
62123
hostname = settings.UNIT_HOSTNAME
63-
if hostname == "default":
124+
if hostname == 'default':
64125
return ''
65-
elif hostname == "application":
126+
elif hostname == 'application':
66127
# replace underscore with dots, since underscore is not valid in DNS hostnames
67-
dns_name = application_name.replace("_", ".")
128+
dns_name = application_name.replace('_', '.')
68129
return dns_name
69-
elif hostname == "server":
130+
elif hostname == 'server':
70131
raise NotImplementedError
71132
else:
72133
raise RuntimeError('Unsupported hostname: ' + hostname)
73134

74-
def _get_portbindings(self,image):
75-
dictports=self.docker_cli.inspect_image(image)["ContainerConfig"]["ExposedPorts"]
76-
for port,mapping in dictports.items():
77-
dictports[port]=None
135+
def _get_portbindings(self, image):
136+
dictports = self.docker_cli.inspect_image(image)['ContainerConfig']['ExposedPorts']
137+
for port, mapping in dictports.items():
138+
dictports[port] = None
78139
return dictports
79140

80-
def _get_ports(self,image):
81-
ports=[]
82-
dictports=self.docker_cli.inspect_image(image)["ContainerConfig"]["ExposedPorts"]
83-
for port,mapping in dictports.items():
84-
ports.append(int(port.split('/')[0]))
85-
return ports
141+
def _get_ports(self, image):
142+
dictports = self.docker_cli.inspect_image(image)['ContainerConfig']['ExposedPorts']
143+
return [int(port.split('/')[0]) for port in dictports.iterkeys()]
86144

87145
SchedulerClient = SwarmClient

controller/templates/confd_settings.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
SCHEDULER_OPTIONS = {}
1212

1313
# scheduler swarm manager host
14-
SWARM_HOST = """{{ or (.deis_scheduler_swarm_host) "" }}"""
14+
SWARM_HOST = '{{ if exists "/deis/scheduler/swarm/host" }}{{ getv "/deis/scheduler/swarm/host" }}{{ else }}127.0.0.1{{ end }}'
15+
#SWARM_HOST = '{{ or (.deis_scheduler_swarm_host) "127.0.0.1" }}'
16+
1517

1618
# base64-encoded SSH private key to facilitate current version of "deis run"
1719
SSH_PRIVATE_KEY = """{{ if exists "/deis/platform/sshPrivateKey" }}{{ getv "/deis/platform/sshPrivateKey" }}{{ else }}""{{end}}"""

deisctl/units/deis-controller.service

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ After=deis-store-volume.service
66
[Service]
77
EnvironmentFile=/etc/environment
88
TimeoutStartSec=20m
9+
ExecStartPre=-/usr/bin/etcdctl mkdir /deis/scheduler >/dev/null 2>&1
910
ExecStartPre=/bin/sh -c "IMAGE=`/run/deis/bin/get_image /deis/controller` && docker history $IMAGE >/dev/null 2>&1 || docker pull $IMAGE"
1011
ExecStartPre=/bin/sh -c "docker inspect deis-controller >/dev/null 2>&1 && docker rm -f deis-controller || true"
11-
ExecStart=/bin/sh -c "IMAGE=`/run/deis/bin/get_image /deis/controller` && docker run --name deis-controller --rm -p 8000:8000 -e EXTERNAL_PORT=8000 -e HOST=$COREOS_PRIVATE_IPV4 -v /var/run/fleet.sock:/var/run/fleet.sock -v /var/lib/deis/store:/data $IMAGE"
12+
ExecStartPre=-/bin/sh -c "etcdctl get /deis/scheduler/module >/dev/null 2>&1 || etcdctl mk /deis/scheduler/module 'fleet' "
13+
ExecStart=/bin/sh -c "DOCKER_VERSION=`docker -v | sed 's/^.*[^0-9]\([0-9]*\.[0-9]*\.[0-9]*\).*$/\1/'` && IMAGE=`/run/deis/bin/get_image /deis/controller` && docker run --name deis-controller --rm -p 8000:8000 -e EXTERNAL_PORT=8000 -e HOST=$COREOS_PRIVATE_IPV4 -e DOCKER_VERSION=$DOCKER_VERSION -v /var/run/fleet.sock:/var/run/fleet.sock -v /var/lib/deis/store:/data $IMAGE"
1214
ExecStopPost=-/usr/bin/docker rm -f deis-controller
1315
Restart=on-failure
1416
RestartSec=5

deisctl/units/deis-swarm-manager.service

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ EnvironmentFile=/etc/environment
66
TimeoutStartSec=20m
77
ExecStartPre=/bin/sh -c "docker history smothiki/swarm >/dev/null || docker pull smothiki/swarm"
88
ExecStartPre=/bin/sh -c "docker inspect deis-swarm-manager >/dev/null && docker rm -f deis-swarm-manager || true"
9-
ExecStart=/bin/sh -c "docker run -p 2395:2375 --name deis-swarm-manager -e HOST=$COREOS_PRIVATE_IPV4 smothiki/swarm manage"
9+
ExecStart=/bin/sh -c "docker run -p 2395:2375 --name deis-swarm-manager -e HOST=$COREOS_PRIVATE_IPV4 deis/swarm:2.0 manage"
1010
ExecStopPost=-/usr/bin/docker rm -f deis-swarm-manager
1111
Restart=on-failure
1212
RestartSec=5

deisctl/units/deis-swarm-node.service

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ EnvironmentFile=/etc/environment
66
TimeoutStartSec=20m
77
ExecStartPre=/bin/sh -c "docker history smothiki/swarm >/dev/null || docker pull smothiki/swarm "
88
ExecStartPre=/bin/sh -c "docker inspect deis-swarm-node >/dev/null && docker rm -f deis-swarm-node || true"
9-
ExecStart=/bin/sh -c "docker run --name deis-swarm-node -e HOST=$COREOS_PRIVATE_IPV4 smothiki/swarm join"
9+
ExecStart=/bin/sh -c "docker run --name deis-swarm-node -e HOST=$COREOS_PRIVATE_IPV4 deis/swarm:2.0 join"
1010
ExecStopPost=-/usr/bin/docker rm -f deis-swarm-node
1111
Restart=on-failure
1212
RestartSec=5

swarm/Dockerfile

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
1-
FROM golang:1.3
1+
FROM golang:1.4
2+
3+
WORKDIR /go/src/github.com/docker
4+
RUN git clone https://github.com/deis/swarm
5+
WORKDIR /go/src/github.com/docker/swarm
6+
RUN git fetch origin nodefailover
7+
RUN git checkout nodefailover
8+
ENV GOPATH /go/src/github.com/docker/swarm/Godeps/_workspace:$GOPATH
9+
RUN CGO_ENABLED=0 go install -v -a -tags netgo -ldflags "-w -X github.com/docker/swarm/version.GITCOMMIT `git rev-parse --short HEAD`"
210
WORKDIR /go/src/github.com/deis
3-
RUN git clone https://github.com/smothiki/deis
11+
RUN git clone https://github.com/deis/deis
412
WORKDIR /go/src/github.com/deis/deis
513
RUN git fetch origin swarm
614
RUN git checkout swarm
715
WORKDIR /go/src/github.com/deis/deis/swarm
16+
RUN mv /go/bin/swarm /bin/deis-swarm
17+
RUN chmod +x /bin/deis-swarm
818
ENV GOPATH /go/src/github.com/deis/deis/Godeps/_workspace:$GOPATH
919
RUN CGO_ENABLED=0 go install -v -a "github.com/deis/deis/swarm"
1020
ENV SWARM_HOST :2375
1121
EXPOSE 2375
12-
RUN wget https://github.com/docker/swarm/releases/download/v0.1.0-rc2/docker-swarm_linux-amd64
13-
RUN mv docker-swarm_linux-amd64 deis-swarm
14-
RUN chmod 777 deis-swarm
1522
VOLUME $HOME/.deis-swarm
1623
ENTRYPOINT ["swarm"]
17-
CMD ["--help"]
24+
CMD ["--help]

tests/utils/itutils.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,22 @@ func CurlWithFail(t *testing.T, url string, failFlag bool, expect string) {
168168
if strings.Contains(string(err.Error()), expect) {
169169
fmt.Println("(Error expected...ok) " + expect)
170170
} else {
171+
if expect == "503" {
172+
if strings.Contains(string(err.Error()), "Welcome to nginx!") {
173+
return
174+
}
175+
}
171176
t.Fatal(err)
172177
}
173178
} else {
174179
if strings.Contains(string(body), expect) {
175180
fmt.Println("(Error expected...ok) " + expect)
176181
} else {
182+
if expect == "503" {
183+
if strings.Contains(string(err.Error()), "Welcome to nginx!") {
184+
return
185+
}
186+
}
177187
t.Fatal(err)
178188
}
179189
}

0 commit comments

Comments
 (0)