170 lines
7.0 KiB
Plaintext
170 lines
7.0 KiB
Plaintext
|
#!/usr/bin/python3
|
||
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
import argparse
|
||
|
import shlex
|
||
|
import os
|
||
|
|
||
|
from spoc.container import Container
|
||
|
from spoc.image import Image
|
||
|
from spoc.paths import VOLUME_DIR
|
||
|
|
||
|
ACTION_CREATE = 1
|
||
|
ACTION_MODIFY = 2
|
||
|
ACTION_DESTROY = 3
|
||
|
ACTION_START = 4
|
||
|
ACTION_STOP = 5
|
||
|
ACTION_STATUS = 6
|
||
|
ACTION_EXEC = 7
|
||
|
|
||
|
def modify_depend(container, depend):
|
||
|
if depend.startswith('!'):
|
||
|
try:
|
||
|
container.depends.remove(depend[1:])
|
||
|
except KeyError:
|
||
|
pass
|
||
|
else:
|
||
|
# Add the dependency and remove duplicates
|
||
|
container.depends.append(depend)
|
||
|
container.depends = list(set(container.depends))
|
||
|
|
||
|
def modify_mount(container, mount):
|
||
|
volume,mountpoint = mount.split(':', 1)
|
||
|
mountpoint = mountpoint.lstrip('/')
|
||
|
if mountpoint:
|
||
|
# If the volume doesn't exist yet, assume it will be a directory
|
||
|
is_dir = not os.path.isfile(os.path.join(VOLUME_DIR, volume))
|
||
|
container.mounts[volume] = (mountpoint, is_dir)
|
||
|
else:
|
||
|
try:
|
||
|
del container.mounts[volume]
|
||
|
except KeyError:
|
||
|
pass
|
||
|
|
||
|
def modify_env(container, env):
|
||
|
key,value = env.split('=', 1)
|
||
|
if value:
|
||
|
container.env[key] = value
|
||
|
else:
|
||
|
try:
|
||
|
del container.env[key]
|
||
|
except KeyError:
|
||
|
pass
|
||
|
|
||
|
def modify_container(container, depends, mounts, envs, uid, gid, cmd, cwd, ready, halt, autostart):
|
||
|
for depend in depends:
|
||
|
modify_depend(container, depend)
|
||
|
for mount in mounts:
|
||
|
modify_mount(container, mount)
|
||
|
for env in envs:
|
||
|
modify_env(container, env)
|
||
|
autostart = autostart == 'on'
|
||
|
args = locals()
|
||
|
for member in ('uid', 'gid', 'cmd', 'cwd', 'ready', 'halt', 'autostart'):
|
||
|
value = args[member]
|
||
|
if value:
|
||
|
setattr(container, member, value)
|
||
|
|
||
|
def create(container_name, image_name, depends, mounts, env, uid, gid, cmd, cwd, ready, halt, autostart):
|
||
|
container = Image(image_name, True).get_container(container_name)
|
||
|
modify_container(container, depends, mounts, env, uid, gid, cmd, cwd, ready, halt, autostart)
|
||
|
container.create()
|
||
|
|
||
|
def modify(container_name, depends, mounts, env, uid, gid, cmd, cwd, ready, halt, autostart):
|
||
|
container = Container(container_name, True)
|
||
|
modify_container(container, depends, mounts, env, uid, gid, cmd, cwd, ready, halt, autostart)
|
||
|
container.create()
|
||
|
|
||
|
def destroy(container_name):
|
||
|
container = Container(container_name)
|
||
|
container.destroy()
|
||
|
|
||
|
def start(container_name):
|
||
|
container = Container(container_name, True)
|
||
|
container.start()
|
||
|
|
||
|
def stop(container_name):
|
||
|
container = Container(container_name, True)
|
||
|
container.stop()
|
||
|
|
||
|
def status(container_name):
|
||
|
container = Container(container_name, True)
|
||
|
print(container.get_state().value)
|
||
|
|
||
|
def execute(container_name, command):
|
||
|
container = Container(container_name, True)
|
||
|
container.execute(command)
|
||
|
|
||
|
parser = argparse.ArgumentParser(description='SPOC container manager')
|
||
|
parser.set_defaults(action=None)
|
||
|
subparsers = parser.add_subparsers()
|
||
|
|
||
|
parser_create = subparsers.add_parser('create')
|
||
|
parser_create.set_defaults(action=ACTION_CREATE)
|
||
|
parser_create.add_argument('-d', '--depends', action='append', default=[], help='Add another container as a start dependency')
|
||
|
parser_create.add_argument('-m', '--mount', action='append', default=[], help='Add mount to the container - format volume:mountpoint')
|
||
|
parser_create.add_argument('-e', '--env', action='append', default=[], help='Add environment variable for the container - format KEY=value')
|
||
|
parser_create.add_argument('-u', '--uid', help='Sets the container init UID')
|
||
|
parser_create.add_argument('-g', '--gid', help='Sets the container init GID')
|
||
|
parser_create.add_argument('-c', '--cmd', help='Sets the container init command')
|
||
|
parser_create.add_argument('-w', '--workdir', help='Sets the container init working directory')
|
||
|
parser_create.add_argument('-r', '--ready', help='Sets the container ready command')
|
||
|
parser_create.add_argument('-s', '--stopsig', help='Sets the signal to be sent to init on container shutdown')
|
||
|
parser_create.add_argument('-a', '--autostart', choices=('on', 'off'), help='Sets the container to be automatically started after the host boots up')
|
||
|
parser_create.add_argument('container')
|
||
|
parser_create.add_argument('image')
|
||
|
|
||
|
parser_modify = subparsers.add_parser('modify')
|
||
|
parser_modify.set_defaults(action=ACTION_MODIFY)
|
||
|
parser_modify.add_argument('-d', '--depends', action='append', default=[], help='Add another container as a start dependency - prepend the name with ! to remove the dependency')
|
||
|
parser_modify.add_argument('-m', '--mount', action='append', default=[], help='Add mount to the container - format volume:mountpoint - specify empty mountpoint to remove the mount')
|
||
|
parser_modify.add_argument('-e', '--env', action='append', default=[], help='Add environment variable for the container - format KEY=value - specify empty value to remove the env')
|
||
|
parser_modify.add_argument('-u', '--uid', help='Sets the container init UID')
|
||
|
parser_modify.add_argument('-g', '--gid', help='Sets the container init GID')
|
||
|
parser_modify.add_argument('-c', '--cmd', help='Sets the container init command')
|
||
|
parser_modify.add_argument('-w', '--workdir', help='Sets the container init working directory')
|
||
|
parser_modify.add_argument('-r', '--ready', help='Sets the container ready command')
|
||
|
parser_modify.add_argument('-s', '--stopsig', help='Sets the signal to be sent to init on container shutdown')
|
||
|
parser_modify.add_argument('-a', '--autostart', choices=('on', 'off'), help='Sets the container to be automatically started after the host boots up')
|
||
|
parser_modify.add_argument('container')
|
||
|
|
||
|
parser_destroy = subparsers.add_parser('destroy')
|
||
|
parser_destroy.set_defaults(action=ACTION_DESTROY)
|
||
|
parser_destroy.add_argument('container')
|
||
|
|
||
|
parser_start = subparsers.add_parser('start')
|
||
|
parser_start.set_defaults(action=ACTION_START)
|
||
|
parser_start.add_argument('container')
|
||
|
|
||
|
parser_stop = subparsers.add_parser('uninstall')
|
||
|
parser_stop.set_defaults(action=ACTION_STOP)
|
||
|
parser_stop.add_argument('container')
|
||
|
|
||
|
parser_status = subparsers.add_parser('start')
|
||
|
parser_status.set_defaults(action=ACTION_STATUS)
|
||
|
parser_status.add_argument('container')
|
||
|
|
||
|
parser_exec = subparsers.add_parser('exec')
|
||
|
parser_exec.set_defaults(action=ACTION_EXEC)
|
||
|
parser_exec.add_argument('container')
|
||
|
parser_exec.add_argument('command', nargs=argparse.REMAINDER)
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
if args.action == ACTION_CREATE:
|
||
|
create(args.container, args.image, args.depends, args.mount, args.env, args.uid, args.gid, args.cmd, args.workdir, args.ready, args.stopsig, args.autostart)
|
||
|
elif args.action == ACTION_MODIFY:
|
||
|
modify(args.container, args.depends, args.mount, args.env, args.uid, args.gid, args.cmd, args.workdir, args.ready, args.stopsig, args.autostart)
|
||
|
elif args.action == ACTION_DESTROY:
|
||
|
destroy(args.container)
|
||
|
elif args.action == ACTION_START:
|
||
|
start(args.container)
|
||
|
elif args.action == ACTION_STOP:
|
||
|
stop(args.container)
|
||
|
elif args.action == ACTION_STATUS:
|
||
|
status(args.container)
|
||
|
elif args.action == ACTION_EXEC:
|
||
|
execute(args.container, args.command)
|
||
|
else:
|
||
|
parser.print_usage()
|