[lxc-users] Problem with lxc-info, lxc-stop

Haralds Ulmanis haralds at evilezh.net
Mon Mar 17 14:46:58 UTC 2014


btw, there is also is another "glitch". When I run that gradle script from
console, after it finishes, I need to reset terminal, otherwise I do not
see echo from keys while typing.

At the end is some parts from host gradle script, which is responsible for
launching/managing lxc.
init function is used to initialize container and launch to start.
In my scenario we need 4 machines to perform single test.
1st is main and 3 other is running different software.

on main container there is also injected gradle script which actually
performs tests.
main - run injected gradle script
2,3,4 - run some program

part of injected script on main:
task testx(dependsOn: ":ready") << {
    module = module.replace("_sub_", "/")
    println "MODULE PROCESSING: " + module
    JmxLauncher jmxc = new JmxLauncher(module: module, basePath: basePath,
ips: ips, logDir: logDir)
    jmxc.scan()
    println ":*:exit"
}

Currently i wrote different function to terminate guests, which literally
kills processes inside container and therefore container terminates, maybe
not the best solution but as workaround works well:
 static def killContainer = { String cname ->
        println "Stopping $cname"
        "cat
${cgroupMount()}/lxc/$cname/cgroup.procs".execute().in.text.eachLine {
            println "killing processid: $it"
            "kill -9 $it".execute().waitFor()
        }
    }



build.gradle (main script on host) ->
class LxcProcess extends Thread {
    String mod, type, cmd, scmd, fcmd, cmdPrefix = ":*:"
    CmdListener listener
    int retry = 1
    boolean stdout = false, stderr = false
    private Process proc
    private boolean shutdown = false, finished = false
    private final Object lock = new Object();
    private InputStream out, err

    def isAlive = { Process p ->
        try {
            p.exitValue()
            false
        } catch (Exception e) {
            true
        }
    }

    private def stopProc = {
        //Process fproc = fcmd.execute()
        //fproc.waitFor()
        Fn.killContainer("$mod-$type")
/*
        if (isAlive(proc)) {
            println "Can't stop $container"
        }
*/
    }

    private def closeStreams() {
        try {
            if (out) out.close()
        } catch (Exception e) {
        }
        try {
            if (err) err.close()
        } catch (Exception e) {
        }
    }

    private def startProc = {
//        println "START PROC !!!!\n CMD: $cmd\n SCMD: $scmd\n FCMD: $fcmd"
        closeStreams()
        proc = scmd.execute()
        out = proc.in
        err = proc.err
        String prefix = "$mod-$type"

        if (stderr) {
            new OutputReader(inputStream: err, prefix: prefix + "
err:").start()
        }
        if (stdout || listener) {
            if (!listener) {
                println "READER WITHOUT LISTENER"
                new OutputReader(inputStream: out, prefix: prefix + "
out:").start()
            } else {
                println "READER WITH LISTENER"
                new OutputReader(inputStream: out, prefix: prefix + "
out:", listener: listener, output: stdout, cmdPrefix: cmdPrefix).start()
            }
        }
    }

    public void run() {
        scmd = "lxc-start -n $mod-$type -- $cmd"
        fcmd = "lxc-stop -n $mod-$type -k"

        while (!shutdown) {
            if (!proc)
                startProc()
            int exit = proc.waitFor()
            println "EXIT CODE: $exit"
            if (exit == 0)
                shutdown = true
            if (!shutdown) {
                synchronized (lock) { //sync with restart command to avoid
duplicates
                    if (retry > 0) {
                        startProc()
                        retry--
                    } else
                        shutdown = true
                }
            }
            sleep(100)
//            println "AFTER SLEEP: " + shutdown
        }
//        println "Shutdown: " + shutdown
        finished = true
    }

    def restart() {
        synchronized (lock) {
            stopProc()
            proc = scmd.execute()
        }
    }

    def finish() {
        shutdown = true;
        stopProc()
        while (!finished)
            sleep(50)
    }

    def waitFor() {
//        println "PROC NULL:" + proc == null
        //proc.waitFor()
        while (!finished)
            sleep(50)
    }

    public boolean isFinished() {
        finished
    }
}

class OutputReader extends Thread {
    public InputStream inputStream
    public String prefix
    public CmdListener listener
    public boolean output = true
    public cmdPrefix = ":*:"

    public void run() {
        BufferedReader reader = new BufferedReader(new
InputStreamReader(inputStream))
        String line
        try {
            while ((line = reader.readLine()) != null) {
                if (output) println(prefix ? prefix + ": " + line : line)
                if (listener && line.startsWith(cmdPrefix)) {
//                        println "EVENT: " +
line.substring(cmdPrefix.length() - 1)
                    listener.event(line.substring(cmdPrefix.length()))
                }
            }
        } catch (IOException e) {
        } finally {
            try {
                if (reader != null)
                    reader.close()
                if (inputStream != null)
                    inputStream.close()
            } catch (Exception e) {
                e.printStackTrace()
            }
        }
    }
}

class Instance implements CmdListener {
    Map<String, Container> containers
    def mod
    java.nio.file.Path rwPath, logDir
    private LxcProcess mgmtProc, routerProc, mpProc, mainProc
    private boolean mainReady = false, destroyed = false

    def init() {
        if (destroyed) return
        Fn.execShell "brctl addbr ${Fn.checksum(mod)}br1"
        Fn.execShell "ifconfig ${Fn.checksum(mod)}br1 up"
        containers.each { it.value.init(mod) }
    }

    def launch() {
        if (destroyed) return
        containers["main"].start(mod, this) // we will receive events from
main
        boolean isRunning = true
        while (isRunning) {
            if (!containers["main"].isFinished() && !mainReady) {
                sleep(50)
            } else if (containers["main"].isFinished()) {
                isRunning = false
            } else if (mainReady) {
                ["mp", "router", "mgmt"].each {
                    if (containers[it].isFinished()) {
                        isRunning = false
                    }
                }
            }
            sleep(50)
        }
        [_cnlist].each {
            if (!containers[it].isFinished())
                containers[it].finish()
        }
    }

    def destroy() {
        containers.each { it.value.destroy() }
        Fn.execShell "ifconfig ${Fn.checksum(mod)}br1 down"
        Fn.execShell "brctl delbr ${Fn.checksum(mod)}br1"
        destroyed = true
    }

    def collectLogs() {
        try {
            def srcLogDir = rwPath.resolve("$mod-main/$mod-main/var/log")
            def dstLogDir = logDir.resolve("$mod")
            println "Source log dir: " + srcLogDir.toString() + "\n Dst log
dir: " + dstLogDir.toString()
            copy {
                from(srcLogDir.toString()) {
                    include '**/*'
                }
                into dstLogDir.toString()
            }
            println "Collect 4"
        } catch (Exception e) {
            e.printStackTrace()
        }
    }

    def finish() {

    }

    def getLogs() {

    }

    @Override
    void event(String cmdLine) {
        String[] cmd = cmdLine.split(" ")
        switch (cmd[0]) {
            case "ready":
                containers["mgmt"].start(mod)
                containers["router"].start(mod)
                containers["mp"].start(mod)
                mainReady = true;
                break;
            case "start":
                containers[cmd[1]].start(mod)
                break
            case "stop":
                containers[cmd[1]].finish()
                break
            case "restart":
                containers[cmd[1]].finish()
                containers[cmd[1]].start(mod)
                break
            case "exit":
                containers["main"].finish()
                break
            default:
                println "UNKNOW COMMMAND: " + cmdLine
        }
    }
}

class Container {
    String rwPath, runCmd, name, lxcBasePath = "/var/lib/lxc"
    String[] paths
    private LxcProcess proc
    Map bindings
    static def templateEngine = new SimpleTemplateEngine()
    static def templateText = new File('config.template').text
    private boolean destroyed = false
    private def ant = new groovy.util.AntBuilder()
    private def initMod

    def init(def modName, CmdListener listener = null) {
        def mainMountEntry = "lxc.mount.entry=/tmp2/writeable
$lxcBasePath/$modName-$name/rootfs/slave none bind 0 0"
        if (destroyed)
            return
        initMod = modName
        def cname = modName + "-" + name
        def writeDir = "${rwPath}/${modName}-${name}"
        ant.delete(dir: "$lxcBasePath/${cname}", quiet: true)
        ant.mkdir(dir: "$lxcBasePath/${cname}")
        ant.mkdir(dir: "$lxcBasePath/${cname}/rootfs")
        ant.delete(dir: writeDir, quiet: true)
        ant.mkdir(dir: writeDir)
        bindings["localBridge"] = "${Fn.checksum(modName)}br1"
        bindings["publicBridge"] = "pubbr0"
        bindings["gw"] = "10.0.0.1"
        Fn.execShell "mount -t aufs -o br=${writeDir}=rw:${paths.join(":")}
-o udba=reval none ${lxcBasePath + "/${cname}/rootfs"}"
        def binding = ["privateIp": bindings["privateIp"], "localBridge":
bindings["localBridge"], "publicIp": bindings["publicIp"],
                "publicBridge": bindings["publicBridge"], "gw":
bindings["gw"], "srvname": cname]
        //bindings for template
        def template =
templateEngine.createTemplate(templateText).make(binding)
        if (name.equals("main")) {
            ant.mkdir(dir: "$lxcBasePath/$modName-$name/rootfs/slave")
            Files.write(Paths.get(lxcBasePath + "/${cname}/config"),
(template.toString() + "\n$mainMountEntry\n").getBytes())
        } else
            Files.write(Paths.get(lxcBasePath + "/${cname}/config"),
template.toString().getBytes())
        ant.echo(file: "$lxcBasePath/${cname}/rootfs/etc/hosts", append:
true, message: "${bindings["privateIp"]} $modName-$name\n")
        proc = new LxcProcess(mod: modName, type: name, cmd: runCmd)
    }

    def destroy() {
        def item = "$initMod-$name"
        "lxc-ls --active".execute().text.split(" ").grep {
item.toString().equals(it.toString()) }.each {
            Fn.execShell "lxc-stop -n $item -k"
        }
        Fn.execShell "umount -f $lxcBasePath/${item}/rootfs"
        Fn.deleteDir("$lxcBasePath/${item}")
        Fn.deleteDir("/tmp2/writeable/${item}")
//                ant.delete(dir: "/tmp2/writeable/${it}", quiet: true)
        destroyed = true
    }

    def start(String modName, CmdListener listener = null) {
        if (destroyed)
            return
        proc.listener = listener
        proc.start()
    }

    def finish() {
        proc.finish()
    }

    def waitFor() {
        proc.waitFor()
    }

    def isFinished() {
        proc.isFinished() || proc.getState() == Thread.State.TERMINATED
    }
}


template:
lxc.network.type = veth
lxc.network.flags = up
lxc.network.ipv4 = $privateIp/24
lxc.network.link = $localBridge

lxc.network.type = veth
lxc.network.flags = up
lxc.network.ipv4 = $publicIp/16
lxc.network.link = $publicBridge
lxc.network.ipv4.gateway = $gw

lxc.utsname = $srvname
lxc.devttydir = lxc
lxc.tty = 1
lxc.pts = 1024
lxc.rootfs = /var/lib/lxc/$srvname/rootfs

lxc.mount.auto = proc:mixed sys:ro

lxc.mount.entry=proc /var/lib/lxc/$srvname/proc proc nodev,noexec,nosuid 0 0
lxc.mount.entry=sys  /var/lib/lxc/$srvname/sys sysfs defaults 0 0
lxc.mount.entry=shm  /var/lib/lxc/$srvname/dev/shm tmpfs
rw,nosuid,nodev,noexec,relatime 0 0
lxc.mount.entry=tmp  /var/lib/lxc/$srvname/tmp tmpfs rw,nosuid,nodev,noexec
0 0
lxc.mount.entry=run  /var/lib/lxc/$srvname/run tmpfs
rw,nosuid,nodev,relatime,mode=755 0 0

lxc.cgroup.devices.deny = a
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
lxc.cgroup.devices.allow = c 5:1 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 4:0 rwm
lxc.cgroup.devices.allow = c 4:1 rwm
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
lxc.cgroup.devices.allow = c 254:0 rwm

#lxc.cgroup.memory.limit_in_bytes = 512M


On 17 March 2014 14:25, Serge Hallyn <serge.hallyn at ubuntu.com> wrote:

> Quoting Haralds Ulmanis (haralds at evilezh.net):
> > So, when i run from shell that gradle script - everything is fine and
> > perfect. When i run from jenkins - I can't stop/kill, get info from
> > containers.
> > LXC is version 1.0.0 with kernel 3.13.0
> > Any suggestions ?
>
> Please show us the gradle script.
> _______________________________________________
> lxc-users mailing list
> lxc-users at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxcontainers.org/pipermail/lxc-users/attachments/20140317/29da2fa6/attachment-0001.html>


More information about the lxc-users mailing list