mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-11-06 05:08:19 +00:00
169 lines
5.4 KiB
Python
Executable File
169 lines
5.4 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
import os
|
|
import sys
|
|
import argparse
|
|
import datetime
|
|
import subprocess
|
|
import pwd
|
|
import logging
|
|
import re
|
|
|
|
logging.basicConfig()
|
|
logger = logging.getLogger('docker_shell')
|
|
logger.setLevel(logging.INFO)
|
|
|
|
g_dry = False
|
|
|
|
def fatal(msg, rc=1):
|
|
logger.critical(msg)
|
|
sys.exit(rc)
|
|
|
|
def execute(cmd, msg=None):
|
|
logger.debug('+ %s ...' % cmd)
|
|
rc = 0
|
|
if not g_dry:
|
|
rc = subprocess.call(cmd, shell=True)
|
|
if rc == 0:
|
|
logger.debug('+ %s [OK]' % cmd)
|
|
else:
|
|
logger.debug('+ %s [FAILED (%d)]' % (cmd, rc))
|
|
if msg:
|
|
fatal(msg)
|
|
else:
|
|
logger.debug('+ %s [DRY]' % cmd)
|
|
return rc
|
|
|
|
class User(object):
|
|
|
|
default_shell="/bin/bash"
|
|
default_user="root:0"
|
|
|
|
def __init__(self, uspec):
|
|
|
|
(self.name, c, rest) = uspec.partition(':')
|
|
self.validate_name()
|
|
|
|
(self.uid, c, rest) = rest.partition(':')
|
|
self.validate_uid()
|
|
|
|
(self.shell, c, rest) = rest.partition(':')
|
|
if self.shell == '':
|
|
self.shell = User.default_shell
|
|
if not os.path.exists(self.shell):
|
|
fatal("Requested shell '%s' does not exist." % self.shell)
|
|
|
|
(self.home, c, rest) = rest.partition(':')
|
|
|
|
logger.debug("User(%s) initialized." % self)
|
|
|
|
def __str__(self):
|
|
return "%s:%s:%s" % (self.name, self.uid, self.shell)
|
|
|
|
def validate_name(self):
|
|
NAME_REGEX=r"[a-z][-a-z0-9]*"
|
|
if re.match(NAME_REGEX, self.name) is None:
|
|
fatal("'%s' is not a valid username." % self.name)
|
|
logger.debug("username %s is validated." % self.name)
|
|
|
|
def validate_uid(self):
|
|
try:
|
|
self.uid = int(self.uid)
|
|
logger.debug("uid %d is validated." % self.uid)
|
|
except:
|
|
if self.uid == '':
|
|
if self.name == 'root':
|
|
self.uid = 0
|
|
else:
|
|
fatal("A user id is required for user '%s'" % self.name)
|
|
else:
|
|
fatal("'%s' is not a valid user id." % self.uid)
|
|
|
|
|
|
def add(self):
|
|
logger.debug("Process user %s ..." % self)
|
|
existing_user = None
|
|
try:
|
|
existing_user = pwd.getpwnam(self.name)
|
|
if existing_user and existing_user.pw_uid != self.uid:
|
|
fatal("User %s already exists with a different uid (%d).\n" % (self.name, existing_user.pw_uid))
|
|
except KeyError:
|
|
logger.debug("User %s does not exist." % self.name)
|
|
|
|
try:
|
|
existing_uid = pwd.getpwuid(self.uid)
|
|
if existing_uid and existing_uid.pw_name != self.name:
|
|
fatal("UID %d already exists with a different user (%s).\n" % (self.uid, existing_uid.pw_name))
|
|
except KeyError:
|
|
logger.debug("UID %d does not exist." % self.uid)
|
|
|
|
if existing_user:
|
|
logger.debug("User %s already exists." % self)
|
|
else:
|
|
logger.debug("Creating user %s ..." % (self))
|
|
cmd = "useradd %s --uid %s --shell %s" % (self.name, self.uid, self.shell)
|
|
if self.home not in [ None, '' ]:
|
|
cmd += " -d %s" % (self.home)
|
|
execute(cmd, "User creation failed for user %s" % self)
|
|
|
|
if not g_dry and self.name != 'root':
|
|
with open("/etc/sudoers.d/%s" % self.name, "w") as f:
|
|
f.write("%s ALL=(ALL:ALL) NOPASSWD:ALL\n" % self.name)
|
|
|
|
|
|
############################################################
|
|
|
|
ap = argparse.ArgumentParser("ONL Docker Shell Build and Development Container Init Script.")
|
|
|
|
ap.add_argument("--user", "-u",
|
|
help="Run as the given user:uid. The user is created if necessary. The default is %s" % User.default_user,
|
|
default=User.default_user,
|
|
metavar="USERNAME:UID[:SHELL]")
|
|
ap.add_argument("--addusers", "-a",
|
|
help="Add additional users.",
|
|
nargs='+',
|
|
metavar="USERNAME:UID[:SHELL]",
|
|
default=[])
|
|
ap.add_argument("--verbose", "-v",
|
|
help="Set verbose logging.",
|
|
action='store_true')
|
|
ap.add_argument("--start-cacher",
|
|
help="Start apt-cacher-ng in the container. It does not run by default.",
|
|
action='store_true')
|
|
ap.add_argument("--dry",
|
|
help="Dry run.",
|
|
action='store_true')
|
|
ap.add_argument('--command', '-c',
|
|
help="The command to run. All arguments after this option are considered part of the command.",
|
|
nargs=argparse.REMAINDER,
|
|
default=["/bin/bash"])
|
|
|
|
ops = ap.parse_args()
|
|
opsdict = vars(ops)
|
|
g_dry = ops.dry
|
|
|
|
if ops.verbose or ops.dry:
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
g_user = User(ops.user)
|
|
g_user.add()
|
|
|
|
for u in ops.addusers:
|
|
User(u).add()
|
|
|
|
if ops.start_cacher:
|
|
execute("/etc/init.d/apt-cacher-ng start", "The apt-cacher-ng service could not be started.")
|
|
|
|
logger.debug("checking if qemu-ppc exists")
|
|
|
|
if os.path.isfile("/proc/sys/fs/binfmt_misc/qemu-ppc"):
|
|
logger.debug("qemu-ppc already exists")
|
|
else:
|
|
if not os.path.ismount("/proc/sys/fs/binfmt_misc"):
|
|
execute("sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc", "The binfmt_misc system could not be mounted.")
|
|
execute("sudo /etc/init.d/binfmt-support start", "The binfmt-support service could not be started.")
|
|
|
|
# Fixme: change this to os.execvp()
|
|
c = "/usr/bin/sudo -E -u %s %s" % (g_user.name, " ".join(ops.command))
|
|
sys.exit(execute(c))
|