dspawn/dspawn/container.py

157 lines
4.9 KiB
Python
Executable File

#!/usr/bin/env python
import os
import glob
import apt
from dspawn.netconf import MachineConfig
import logging
logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger(__name__)
defaults = {
'arch': os.uname()[4],
'basepath': '/var/lib/machines',
'mirror': 'http://deb.debian.org/debian/'}
default_configuration = [
'apt-get install -y openssh-server dbus locales',
'test -d /root/.ssh || mkdir /root/.ssh',
'systemctl enable systemd-networkd']
jessie_fix = [
'echo "deb http://ftp.debian.org/debian jessie-backports main" >'
'/etc/apt/sources.list.d/backports.list',
'apt update; apt install -y -t jessie-backports dbus systemd systemd-sysv'
]
pub_keys = glob.glob('/home/*/.ssh/id_rsa.pub') + \
glob.glob('/root/.ssh/id_rsa.pub') + \
glob.glob('/home/*/.ssh/authorized_keys')
def use_aptcacherng():
c = apt.cache.Cache()
try:
return c['apt-cacher-ng'].is_installed
except KeyError:
return False
class Machine(object):
def __init__(self, name, release='stable', mode='private', address=None,
proxy=False, macaddress=None, privateoff=False, bind=None,
enable=False, **kwargs):
if isinstance(name, list):
self.name = name[0]
else:
self.name = name
for k, v in defaults.items():
setattr(self, k, v)
self.path = os.path.join(self.basepath, self.name)
self.release = release
self.address = address
self.bind = bind
self.macaddress = macaddress
self.proxy = proxy
self.mode = mode
self.enable = enable
self.privateoff = privateoff
self.modelpath = ".%s-%s" % (release, defaults['arch'])
self.config_file = '/etc/systemd/nspawn/%s.nspawn' % self.name
self.init = default_configuration
if self.release == 'jessie':
self.init = jessie_fix + self.init
self.configuration = MachineConfig(self)
if not os.system('cd %s' % self.basepath) == 0:
raise(Exception(
'You do not have permission to access %s, please use sudo'
% self.basepath))
config_dir = os.path.dirname(self.config_file)
if not os.path.isdir(config_dir):
os.mkdir(config_dir)
def exist(self):
if os.path.isdir(self.path):
return True
def config(self):
self.chroot('rm /etc/machine-id /var/lib/dbus/machine-id; dbus-uuidgen --ensure=/etc/machine-id; dbus-uuidgen --ensure')
self.configuration.realize()
if self.enable:
os.system('systemctl enable systemd-nspawn@%s.service' % self.name)
def start(self):
os.system('machinectl start %s' % self.name)
def stop(self):
os.system('machinectl poweroff %s' % self.name)
def terminate(self):
os.system('machinectl terminate %s' % self.name)
def create(self):
if self.exist():
logger.warning('container "%s" already exists' % self.name)
self.start()
return
model = Machine(self.modelpath, self.release)
if not model.exist():
model._create()
logger.debug('copying base model %s to %s' % (model.path, self.path))
# shutil.copytree(model.path, self.path, symlinks=True)
os.system('cp -r %s %s' % (model.path, self.path))
self.copy_keys()
self.set_hostname()
self.config()
self.start()
def _create(self):
logger.info('creating base model %s' % self.path)
if use_aptcacherng():
env = 'http_proxy=http://localhost:3142 '
logger.info('Found apt-cacher-ng process, using it (%s)' % env)
else:
env = ''
bootstrap = '%sdebootstrap %s %s %s' % (
env, self.release, self.path, self.mirror)
os.system(bootstrap)
for c in self.init:
self.chroot(c)
os.system('rm -r %s/var/lib/apt/lists/*' % self.path)
def chroot(self, command):
logger.debug('in chroot: %s' % command)
cmd = "chroot %s /bin/bash -c '%s'" % (self.path, command)
os.system(cmd)
def copy_keys(self):
keydir = os.path.join(self.path, 'root/.ssh')
if not os.path.isdir(keydir):
os.mkdir(keydir)
ah = os.path.join(keydir, 'authorized_keys')
fh = open(ah, 'a')
rsa_lines = []
for key_file in pub_keys:
rsa_lines += open(key_file).readlines()
for rsa in set(rsa_lines):
fh.write('%s\n' % rsa)
def set_hostname(self):
if self.name.count('.') <= 1:
hostname = self.name
elif self.name.count('.') > 1:
hostname = self.name.partition('.')[0]
# domainname = name.partition('.')[2]
self.chroot('echo "127.0.1.1 %s %s" >> /etc/hosts' % (
self.name, hostname))
self.chroot('echo %s > /etc/hostname' % hostname)