containers.py 3.35 KB
Newer Older
1
2
3
from __future__ import print_function

from aci import ImageManifest
4
from collections import namedtuple
5
6
import logging
import os
7
from subprograms import ChrtClient, NodeOSClient, resources
8

9
logger = logging.getLogger('nrm')
10
Container = namedtuple('Container', ['uuid', 'manifest', 'process'])
11

12
13
14
15
16
17

class ContainerManager(object):

    """Manages the creation, listing and deletion of containers, using a
    container runtime underneath."""

18
    def __init__(self, rm):
19
        self.containers = dict()
20
21
22
23
        self.pids = dict()
        self.resourcemanager = rm
        self.nodeos = NodeOSClient()
        self.chrt = ChrtClient()
24
25
26
27
28
29
30
31

    def create(self, request):
        """Create a container according to the request.

        Returns the pid of the container or a negative number for errors."""
        manifestfile = request['manifest']
        command = request['file']
        args = request['args']
32
33
34
        logger.info("run: manifest file: %s", manifestfile)
        logger.info("run: command:       %s", command)
        logger.info("run: args:          %r", args)
35
36
        manifest = ImageManifest()
        if not manifest.load(manifestfile):
37
            logger.error("Manifest is invalid")
38
39
            return -1

40
41
42
43
        # ask the resource manager for resources
        req = resources(int(manifest.app.isolators.container.cpus.value),
                        int(manifest.app.isolators.container.mems.value))
        allocation = self.resourcemanager.schedule(request['uuid'], req)
44
        logger.info("run: allocation: %r", allocation)
45
46
47
48
49
50
51
52

        # build context to execute
        environ = os.environ
        environ['PATH'] = ("/usr/local/sbin:"
                           "/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
        environ['AC_APP_NAME'] = manifest.name
        environ['AC_METADATA_URL'] = "localhost"
        environ['container'] = 'argo'
53
        logger.info("run: environ: %r", environ)
54
55
56

        # create container
        container_name = request['uuid']
57
        logger.info("creating container %s", container_name)
58
        self.nodeos.create(container_name, allocation)
59
        logger.info("created container %s", container_name)
60

61
62
63
64
        # run my command
        if hasattr(manifest.app.isolators, 'scheduler'):
            sched = manifest.app.isolators.scheduler
            argv = self.chrt.getwrappedcmd(sched)
65
        else:
66
67
68
69
70
71
72
73
            argv = []

        argv.append(command)
        argv.extend(args)
        process = self.nodeos.execute(container_name, argv, environ)
        c = Container(container_name, manifest, process)
        self.pids[process.pid] = c
        self.containers[container_name] = c
74
        return process
75
76
77

    def delete(self, uuid):
        """Delete a container and kill all related processes."""
78
        self.nodeos.delete(uuid, kill=True)
79
        self.resourcemanager.update(uuid)
80
81
        c = self.containers[uuid]
        del self.containers[uuid]
82
        del self.pids[c.process.pid]
83

Swann Perarnau's avatar
Swann Perarnau committed
84
85
86
87
    def kill(self, uuid):
        """Kill all the processes of a container."""
        if uuid in self.containers:
            c = self.containers[uuid]
88
            logger.debug("killing %r:", c)
Swann Perarnau's avatar
Swann Perarnau committed
89
            try:
90
                c.process.proc.terminate()
Swann Perarnau's avatar
Swann Perarnau committed
91
92
93
            except OSError:
                pass

94
95
    def list(self):
        """List the containers in the system."""
96
        return [{'uuid': c.uuid, 'pid': c.process.pid} for c in
97
                self.containers.values()]