org.linkedin.glu.agent.impl.AgentImpl.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.linkedin.glu.agent-impl
Show all versions of org.linkedin.glu.agent-impl
GLU Deployment Automation Platform
/*
* Copyright (c) 2010-2010 LinkedIn, Inc
* Portions Copyright (c) 2011 Yan Pujante
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.linkedin.glu.agent.impl
import org.linkedin.glu.agent.api.Agent
import org.linkedin.glu.agent.impl.script.AgentContext
import org.linkedin.glu.agent.api.Shell
import org.linkedin.glu.agent.impl.script.MOP
import org.linkedin.glu.agent.api.MountPoint
import org.linkedin.glu.agent.impl.script.ScriptManagerImpl
import org.linkedin.glu.agent.impl.script.ScriptManager
import org.linkedin.glu.agent.impl.script.StateKeeperScriptManager
import org.linkedin.glu.agent.impl.capabilities.MOPImpl
import org.hyperic.sigar.Sigar
import org.hyperic.sigar.SigarException
import org.linkedin.glu.agent.api.AgentException
import java.util.concurrent.TimeoutException
import org.linkedin.util.lifecycle.Shutdownable
import org.linkedin.util.clock.Clock
import org.linkedin.util.clock.SystemClock
import org.linkedin.util.io.resource.Resource
import org.linkedin.util.clock.Timespan
import org.linkedin.glu.agent.api.TimeOutException
import org.linkedin.glu.utils.tags.Taggeable
import org.linkedin.glu.utils.tags.TaggeableTreeSetImpl
import org.linkedin.glu.agent.impl.script.ScriptNode
import java.util.concurrent.ExecutionException
/**
* The main implementation of the agent
*/
def class AgentImpl implements Agent, AgentContext, Shutdownable
{
public static final String MODULE = AgentImpl.class.getName();
public static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MODULE);
Clock clock = SystemClock.instance()
private Sigar _sigar
private Shell _shellForScripts
private Shell _rootShell
private Resource _agentLogDir
private ScriptManager _scriptManager
private MOP _mop
private Closure _sync
private Taggeable _taggeable
private volatile _shutdown = false
/********************************************************************
* Boot
********************************************************************/
/**
* Boots the agent.
*
*
* restartSoftware
: the flag indicates whether the software that were running
* before the agent was shutdown should be started again (default to false
)
*
*/
void boot(args)
{
_shellForScripts = args.shellForScripts
_rootShell = args.rootShell
_agentLogDir = args.agentLogDir
_sigar = args.sigar
_mop = args.mop ?: new MOPImpl()
_scriptManager = args.scriptManager ?: new ScriptManagerImpl(agentContext: this)
def storage = args.storage
if(storage != null)
_scriptManager = new StateKeeperScriptManager(scriptManager: _scriptManager,
storage: storage)
if(!_scriptManager.isMounted(MountPoint.ROOT))
_scriptManager.installRootScript([:])
_sync = args.sync
_taggeable = args.taggeable ?: new TaggeableTreeSetImpl()
}
def getClock()
{
return clock
}
/**
* Default shutdown: stops the containers and shut downs the agent
*
* @see #shutdown(boolean)
*/
void shutdown()
{
if(!_shutdown)
{
_shutdown = true
_scriptManager.shutdown()
}
}
/**
* Shuts down the agent
*
* @param stopSoftware true
if the software should be stopped or
* false
if it should be left running.
*/
void shutdown(boolean stopSoftware)
{
shutdown()
}
/**
* Waits for the agent to be completely down (but no longer than the timeout).
* @return true
if it shutdown or false
if the timeout elapsed before
* termination
*/
void waitForShutdown(timeout)
{
if(!_shutdown)
throw new IllegalStateException('call shutdown first!')
timeout = Timespan.parse(timeout?.toString()) ?: Timespan.ZERO_MILLISECONDS
_scriptManager.waitForShutdown(timeout.durationInMilliseconds)
}
public void waitForShutdown()
{
waitForShutdown(0)
}
public getMountPoints()
{
handleException {
return _scriptManager.mountPoints
}
}
/**
* {@inheritdoc}
*/
public def getHostInfo()
{
handleException {
log.info "getHostInfo()"
def res = [:]
if(_sigar)
{
// cpus
res.cpus = _sigar.cpuInfoList?.collect { it.toMap() }
// memory
res.mem = _sigar.mem.toMap()
}
return res
}
}
/**
* {@inheritdoc}
*/
public def ps()
{
handleException {
log.info "ps()"
def ps = [:]
def procList = _sigar?.procList ?: []
procList.each { pid ->
def proc = [:]
ps[pid] = proc
[
'env': 'getProcEnv',
'args': 'getProcArgs',
'cpu': 'getProcCpu',
// 'cred': 'getProcCred',
'credName': 'getProcCredName',
'exe': 'getProcExe',
'fd': 'getProcFd',
'mem': 'getProcMem',
'modules': 'getProcModules',
'state': 'getProcState',
'time': 'getProcTime'
].each { k, v ->
try
{
def res = _sigar."${v}"(pid)
if(res.respondsTo('toMap'))
res = res.toMap()
proc[k] = res
}
catch (SigarException e)
{
if(log.isDebugEnabled())
log.debug("ignored exception", e)
}
}
}
return ps
}
}
/**
* {@inheritdoc}
*/
public void kill(long pid, int signal)
{
handleException {
try
{
log.info "Sending signal ${signal} to process ${pid}"
_sigar?.kill(pid, signal)
}
catch (SigarException e)
{
log.warn("Exception while sending signal ${signal} to process ${pid} (ignored)", e)
throw new AgentException(e)
}
}
}
/**
* {@inheritdoc}
*/
public void sync()
{
handleException {
log.info "sync()"
if(_sync)
_sync()
}
}
/**
* {@inheritdoc}
*/
void installScript(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("installScript(${args})")
_scriptManager.installScript(args)
}
}
/**
* {@inheritdoc}
*/
void uninstallScript(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("uninstallScript(${args})")
def force = args.force != null ? args.force : false
if(force instanceof String)
force = Boolean.parseBoolean(force)
if(force)
interruptAction(args)
_scriptManager.uninstallScript(args.mountPoint, force)
}
}
/**
* {@inheritdoc}
*/
String executeAction(args)
{
handleException {
if(log.isDebugEnabled()) {
log.debug("executeAction(" + args + ")")
}
_scriptManager.executeAction(args).id
}
}
/**
* {@inheritdoc}
*/
def waitForAction(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("waitForAction(${args})")
_scriptManager.waitForAction(args)
}
}
/**
* {@inheritdoc}
*/
def executeActionAndWait(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("executeActionAndWait(${args})")
def future = _scriptManager.executeAction(args)
def timeout = Timespan.parse(args.timeout?.toString()) ?: Timespan.ZERO_MILLISECONDS
try
{
def res = future.get(timeout)
if(log.isDebugEnabled())
{
if(res instanceof InputStream)
log.debug("executeActionAndWait(${args}): InputStream")
else
log.debug("executeActionAndWait(${args}): ${res}")
}
return res
}
catch(ExecutionException e)
{
throw e.cause
}
catch (TimeoutException e)
{
if(log.isDebugEnabled())
log.debug("executeActionAndWait(${args}): TimeoutException[${e.message}]")
throw new TimeoutException()
}
}
}
/*
* {@inheritdoc}
*/
boolean interruptAction(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("interruptAction(${args})")
_scriptManager.interruptAction(args)
}
}
/**
* {@inheritdoc}
*/
void clearError(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("clearError(" + args + ")")
_scriptManager.clearError(MountPoint.create(args.mountPoint))
}
}
/**
* {@inheritdoc}
*/
def executeCall(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("executeCall(" + args + ")")
return _scriptManager.executeCall(args)
}
}
/**
* {@inheritdoc}
*/
public getState(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("getState(" + args + ")")
return _scriptManager.getState(args.mountPoint)
}
}
/**
* {@inheritdoc}
*/
public getFullState(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("getFullState(" + args + ")")
return _scriptManager.getFullState(args.mountPoint);
}
}
/**
* {@inheritdoc}
*/
boolean waitForState(args)
{
handleException {
if(log.isDebugEnabled())
log.debug("waitForState(${args})")
return _scriptManager.waitForState(args)
}
}
/**
* {@inheritdoc}
*/
boolean executeActionAndWaitForState(Object args)
{
executeAction(args)
return waitForState(args);
}
/**
* {@inheritdoc}
*/
InputStream tailAgentLog(args)
{
handleException {
args.location = _agentLogDir.createRelative(args.log?.toString() ?: "${_rootShell.env['org.linkedin.app.name']}.out")
getFileContent(args)
}
}
/**
* {@inheritdoc}
*/
def getFileContent(args) throws IOException, AgentException
{
handleException {
log.info "getFileContent: ${args}"
def location = _rootShell.toResource(args.location)
if(location.isDirectory())
{
def resources = _rootShell.ls(location)
def res = [:]
resources.each {
def file = it.file
def details = [:]
res[file.name] = details
details.canonicalPath = file.canonicalPath
details.length = file.length()
details.lastModified = file.lastModified()
details.isDirectory = file.isDirectory()
}
return res
}
else
{
return _rootShell.tail(args)
}
}
}
public Shell getShellForScripts()
{
return _shellForScripts;
}
public MOP getMop()
{
return _mop;
}
@Override
int getTagsCount()
{
handleException {
return _taggeable.tagsCount
}
}
@Override
boolean hasTags()
{
handleException {
return _taggeable.hasTags()
}
}
@Override
Set getTags()
{
handleException {
return _taggeable.tags
}
}
@Override
boolean hasTag(String tag)
{
handleException {
return _taggeable.hasTag(tag)
}
}
@Override
boolean hasAllTags(Collection tags)
{
handleException {
return _taggeable.hasAllTags(tags)
}
}
@Override
boolean hasAnyTag(Collection tags)
{
handleException {
return _taggeable.hasAnyTag(tags)
}
}
@Override
boolean addTag(String tag)
{
handleException {
log.info "adding tag: ${tag}"
return _taggeable.addTag(tag)
}
}
@Override
Set addTags(Collection tags)
{
handleException {
log.info "adding tags: ${tags}"
return _taggeable.addTags(tags)
}
}
@Override
boolean removeTag(String tag)
{
handleException {
log.info "removing tag: ${tag}"
return _taggeable.removeTag(tag)
}
}
@Override
Set removeTags(Collection tags)
{
handleException {
log.info "removing tags: ${tags}"
return _taggeable.removeTags(tags)
}
}
@Override
void setTags(Collection tags)
{
handleException {
log.info "setting tags: ${tags}"
return _taggeable.setTags(tags)
}
}
private def handleException(Closure closure)
{
try
{
return closure()
}
catch(RuntimeException e)
{
throw e
}
catch(TimeoutException e)
{
// adapting timeout exception...
def toex = new TimeOutException(e.message)
toex.initCause(e)
throw toex
}
catch (AgentException e)
{
throw e
}
catch(Throwable th)
{
throw new AgentException('unexpected exception', th)
}
}
/**
* @return a script previously installed (or null
if not found)
*/
ScriptNode findScript(mountPoint)
{
return _scriptManager.findScript(mountPoint)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy