[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