157 lines
4.9 KiB
Python
Executable File
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)
|