added docker service file from r603
This commit is contained in:
parent
90f3c6569f
commit
c5f1fa7d13
1 changed files with 182 additions and 0 deletions
182
daemon/core/services/dockersvc.py
Normal file
182
daemon/core/services/dockersvc.py
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
#
|
||||||
|
# CORE
|
||||||
|
# Copyright (c)2014 the Boeing Company.
|
||||||
|
# See the LICENSE file included in this distribution.
|
||||||
|
#
|
||||||
|
# authors: Stuart Marsden
|
||||||
|
# Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||||
|
#
|
||||||
|
''' Docker service allows running docker containers within CORE nodes.
|
||||||
|
|
||||||
|
The running of Docker within a CORE node allows for additional extensibility to
|
||||||
|
the CORE services. This allows network applications and protocols to be easily
|
||||||
|
packaged and run on any node.
|
||||||
|
|
||||||
|
This service that will add a new group to the services list. This
|
||||||
|
will have a service called Docker which will just start the docker service
|
||||||
|
within the node but not run anything. It will also scan all docker images on
|
||||||
|
the host machine. If any are tagged with 'core' then they will be added as a
|
||||||
|
service to the Docker group. The image will then be auto run if that service is
|
||||||
|
selected.
|
||||||
|
|
||||||
|
This requires a recent version of Docker. This was tested using a PPA on Ubuntu
|
||||||
|
with version 1.2.0. The version in the standard Ubuntu repo is to old for
|
||||||
|
this purpose (we need --net host).
|
||||||
|
|
||||||
|
It also requires docker-py (https://pypi.python.org/pypi/docker-py) which can be
|
||||||
|
installed with 'pip install docker-py'. This is used to interface with Docker
|
||||||
|
from the python service.
|
||||||
|
|
||||||
|
An example use case is to pull an image from Docker.com. A test image has been
|
||||||
|
uploaded for this purpose:
|
||||||
|
|
||||||
|
sudo docker pull stuartmarsden/multicastping
|
||||||
|
|
||||||
|
This downloads an image which is based on Ubuntu 14.04 with python and twisted.
|
||||||
|
It runs a simple program that sends a multicast ping and listens and records
|
||||||
|
any it receives.
|
||||||
|
|
||||||
|
In order for this to appear as a docker service it must be tagged with core.
|
||||||
|
Find out the id by running 'sudo docker images'. You should see all installed
|
||||||
|
images and the one you want looks like this:
|
||||||
|
|
||||||
|
stuartmarsden/multicastping latest 4833487e66d2 20 hours
|
||||||
|
ago 487 MB
|
||||||
|
|
||||||
|
The id will be different on your machine so use it in the following command:
|
||||||
|
|
||||||
|
sudo docker tag 4833487e66d2 stuartmarsden/multicastping:core
|
||||||
|
|
||||||
|
This image will be listed in the services after we restart the core-daemon:
|
||||||
|
|
||||||
|
sudo service core-daemon restart
|
||||||
|
|
||||||
|
You can set up a simple network with a number of PCs connected to a switch. Set
|
||||||
|
the stuartmarsden/multicastping service for all the PCs. When started they will
|
||||||
|
all begin sending Multicast pings.
|
||||||
|
|
||||||
|
In order to see what is happening you can go in to the terminal of a node and
|
||||||
|
look at the docker log. Easy shorthand is:
|
||||||
|
|
||||||
|
docker logs $(docker ps -q)
|
||||||
|
|
||||||
|
Which just shows the log of the running docker container (usually just one per
|
||||||
|
node). I have added this as an observer node to my setup: Name: docker logs
|
||||||
|
Command: bash -c 'docker logs $(docker ps -q) | tail -20'
|
||||||
|
|
||||||
|
So I can just hover over to see the log which looks like this:
|
||||||
|
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.0.20', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.5.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.3.20', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.4.20', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.4.20', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.1.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.4.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.4.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.5.20', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.0.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.3.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.0.20', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.5.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.3.20', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.4.20', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.4.20', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.1.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.4.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.4.21', 8005)
|
||||||
|
Datagram 'Client: Ping' received from ('10.0.5.20', 8005)
|
||||||
|
|
||||||
|
Limitations:
|
||||||
|
|
||||||
|
1. Docker images must be downloaded on the host as usually a CORE node does not
|
||||||
|
have access to the internet.
|
||||||
|
2. Each node isolates running containers (keeps things simple)
|
||||||
|
3. Recent version of docker needed so that --net host can be used. This does
|
||||||
|
not further abstract the network within a node and allows multicast which
|
||||||
|
is not enabled within Docker containers at the moment.
|
||||||
|
4. The core-daemon must be restarted for new images to show up.
|
||||||
|
5. A Docker-daemon is run within each node but the images are shared. This
|
||||||
|
does mean that the daemon attempts to access an SQLlite database within the
|
||||||
|
host. At startup all the nodes will try to access this and it will be locked
|
||||||
|
for most due to contention. The service just does a hackish wait for 1 second
|
||||||
|
and retry. This means all the docker containers can take a while to come up
|
||||||
|
depending on how many nodes you have.
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
try:
|
||||||
|
from docker import Client
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
from core.service import CoreService, addservice
|
||||||
|
from core.misc.ipaddr import IPv4Prefix, IPv6Prefix
|
||||||
|
|
||||||
|
class DockerService(CoreService):
|
||||||
|
''' This is a service which will allow running docker containers in a CORE
|
||||||
|
node.
|
||||||
|
'''
|
||||||
|
_name = "Docker"
|
||||||
|
_group = "Docker"
|
||||||
|
_depends = ()
|
||||||
|
_dirs = ('/var/lib/docker/containers/', '/run/shm', '/run/resolvconf',)
|
||||||
|
_configs = ('docker.sh', )
|
||||||
|
_startindex = 50
|
||||||
|
_startup = ('sh docker.sh',)
|
||||||
|
_shutdown = ('service docker stop', )
|
||||||
|
# Container image to start
|
||||||
|
_image = ""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generateconfig(cls, node, filename, services):
|
||||||
|
''' Returns a string having contents of a docker.sh script that
|
||||||
|
can be modified to start a specific docker image.
|
||||||
|
'''
|
||||||
|
cfg = "#!/bin/sh\n"
|
||||||
|
cfg += "# auto-generated by Docker (docker.py)\n"
|
||||||
|
# Docker likes to think it has DNS set up or it complains.
|
||||||
|
# Unless your network was attached to the Internet this is
|
||||||
|
# non-functional but hides error messages.
|
||||||
|
cfg += 'echo "nameserver 8.8.8.8" > /run/resolvconf/resolv.conf\n'
|
||||||
|
# Starts the docker service. In Ubuntu this is docker.io; in other
|
||||||
|
# distros may just be docker
|
||||||
|
cfg += 'service docker start\n'
|
||||||
|
cfg += "# you could add a command to start a image here eg:\n"
|
||||||
|
if not cls._image:
|
||||||
|
cfg += "# docker run -d --net host --name coreDock <imagename>\n"
|
||||||
|
else:
|
||||||
|
cfg += """\
|
||||||
|
result=1
|
||||||
|
until [ $result -eq 0 ]; do
|
||||||
|
docker run -d --net host --name coreDock %s
|
||||||
|
result=$?
|
||||||
|
# this is to alleviate contention to docker's SQLite database
|
||||||
|
sleep 0.3
|
||||||
|
done
|
||||||
|
""" % (cls._image, )
|
||||||
|
return cfg
|
||||||
|
|
||||||
|
addservice(DockerService)
|
||||||
|
|
||||||
|
# This auto-loads Docker images having a :core tag, adding them to the list
|
||||||
|
# of services under the "Docker" group.
|
||||||
|
if 'Client' in globals():
|
||||||
|
client = Client(version='1.10')
|
||||||
|
images = client.images()
|
||||||
|
del client
|
||||||
|
else:
|
||||||
|
images = []
|
||||||
|
for image in images:
|
||||||
|
if u'<none>' in image['RepoTags'][0]:
|
||||||
|
continue
|
||||||
|
for repo in image['RepoTags']:
|
||||||
|
if u':core' not in repo:
|
||||||
|
continue
|
||||||
|
dockerid = repo.encode('ascii','ignore').split(':')[0]
|
||||||
|
SubClass = type('SubClass', (DockerService,),
|
||||||
|
{'_name': dockerid, '_image': dockerid})
|
||||||
|
addservice(SubClass)
|
||||||
|
del images
|
Loading…
Reference in a new issue