Skip to content

Commit

Permalink
#63: implemented deployer
Browse files Browse the repository at this point in the history
  • Loading branch information
ypujante committed May 28, 2011
1 parent 6ffa3fc commit 709d7c3
Show file tree
Hide file tree
Showing 26 changed files with 709 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ import org.linkedin.glu.provisioner.impl.agent.DefaultDescriptionProvider
import org.linkedin.glu.provisioner.core.action.IDescriptionProvider
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.linkedin.glu.orchestration.engine.action.descriptor.AgentURIProvider

/**
* @author ypujante
*/
class AgentsServiceImpl implements AgentsService
class AgentsServiceImpl implements AgentsService, AgentURIProvider
{
public static final String MODULE = AgentsServiceImpl.class.getName ();
public static final Logger log = LoggerFactory.getLogger(MODULE);
Expand All @@ -72,6 +73,15 @@ class AgentsServiceImpl implements AgentsService
@Initializable
IDescriptionProvider descriptionProvider = DefaultDescriptionProvider.INSTANCE

@Override
URI getAgentURI(String fabric, String agent) throws NoSuchAgentException
{
AgentInfo info = trackerService.getAgentInfo(fabric, agent)
if(!info)
throw new NoSuchAgentException(agent)
return info.getURI()
}

def getAllInfosWithAccuracy(Fabric fabric)
{
return trackerService.getAllInfosWithAccuracy(fabric)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* 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.orchestration.engine.core.action.execution

import org.linkedin.glu.orchestration.engine.action.execution.ActionExecutionFactory
import org.linkedin.glu.orchestration.engine.action.execution.ActionExecution
import org.linkedin.glu.orchestration.engine.action.descriptor.ActionDescriptor
import org.linkedin.glu.orchestration.engine.action.descriptor.NoOpActionDescriptor
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.linkedin.glu.orchestration.engine.action.descriptor.ScriptTransitionActionDescriptor
import org.linkedin.glu.agent.rest.client.AgentFactory
import org.linkedin.util.annotations.Initializable
import org.linkedin.glu.orchestration.engine.action.descriptor.AgentActionDescriptor
import org.linkedin.glu.orchestration.engine.action.descriptor.AgentURIProvider
import org.linkedin.glu.agent.api.Agent
import org.linkedin.glu.agent.rest.client.EncryptionKeysProvider
import org.linkedin.util.clock.Timespan
import org.linkedin.glu.orchestration.engine.action.descriptor.ScriptLifecycleInstallActionDescriptor
import org.linkedin.glu.orchestration.engine.action.descriptor.ScriptLifecycleUninstallActionDescriptor

/**
* This implementation uses a convention:
* @author yan@pongasoft.com */
public class ActionExecutionFactoryImpl implements ActionExecutionFactory
{
public static final String MODULE = ActionExecutionFactoryImpl.class.getName();
public static final Logger log = LoggerFactory.getLogger(MODULE);

public static final String ENCRYPTION_KEYS = 'encryptionKeys'

@Initializable(required = true)
AgentFactory factory

@Initializable(required = true)
AgentURIProvider agentURIProvider

@Initializable(required = false)
EncryptionKeysProvider encryptionKeysProvider

/**
* the timeout for the agent operations */
@Initializable(required = false)
Timespan timeout = Timespan.parse('10s')

/**
* For NoOpActionDescriptor: do nothing
*/
def NoOpActionDescriptor_execution = { NoOpActionDescriptor ad ->
// nothing to do (noop)
if(log.isDebugEnabled())
log.debug("noop: ${ad.toMetadata()}")
}

/**
* For ScriptTransitionActionDescriptor: execute the action (transition) on the agent and wait
* for the action to complete
*/
def ScriptTransitionActionDescriptor_execution = { ScriptTransitionActionDescriptor ad ->
withAgent(ad) { Agent agent ->

String mountPoint = ad.mountPoint

// 1. we clear any error which could be left over
agent.clearError(mountPoint: mountPoint)

// 2. we execute the transition action
Map actionArgs = computeActionArgs(ad)
agent.executeAction(mountPoint: mountPoint, action: ad.action, actionArgs: actionArgs)

// 3. we wait for the action to be completed
def success = false
while(!success)
{
success = agent.waitForState(mountPoint: mountPoint, state: ad.endState, timeout: timeout)
if(!success)
{
if(Thread.currentThread().isInterrupted())
{
agent.interruptAction(mountPoint: mountPoint, action: ad.action)
throw new InterruptedException()
}
}
}
}
}

/**
* For ScriptLifecycleInstallActionDescriptor: installs the script
*/
def ScriptLifecycleInstallActionDescriptor_execution = { ScriptLifecycleInstallActionDescriptor ad ->
withAgent(ad) { Agent agent ->
agent.installScript(mountPoint: ad.mountPoint,
scriptLocation: ad.script,
parent: ad.parent,
initParameters: ad.initParameters)
}
}

/**
* For ScriptLifecycleUninstallActionDescriptor: uninstalls the script
*/
def ScriptLifecycleUninstallActionDescriptor_execution = { ScriptLifecycleUninstallActionDescriptor ad ->
withAgent(ad) { Agent agent ->
agent.clearError(mountPoint: ad.mountPoint)

agent.uninstallScript(mountPoint: ad.mountPoint)
}
}

/**
* Compute the action args (automatically adds encryption keys if any present)
*/
Map computeActionArgs(ScriptTransitionActionDescriptor ad)
{
def Map args = [ : ]

Map encryptionKeys = encryptionKeysProvider?.getEncryptionKeys()

if (encryptionKeys) {
args.put(ENCRYPTION_KEYS, encryptionKeys)
}

if(ad.actionArgs)
args.putAll(ad.actionArgs)

return args
}

/**
* Compute the agent URI and call the closure with the {@link Agent}.
*/
private def withAgent(AgentActionDescriptor ad, Closure closure)
{
factory.withRemoteAgent(agentURIProvider.getAgentURI(ad.fabric, ad.agent), closure)
}

@Override
<V> ActionExecution<V> createAction(ActionDescriptor actionDescriptor)
{
Closure actionClosure = this."${actionDescriptor.class.name}_execution"

return new ClosureActionExecution<V>(actionDescriptor: actionDescriptor,
actionClosure: actionClosure)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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.orchestration.engine.core.action.execution

import org.linkedin.glu.orchestration.engine.action.execution.ActionExecution
import org.linkedin.glu.orchestration.engine.action.descriptor.ActionDescriptor

/**
* @author yan@pongasoft.com */
public class ClosureActionExecution<V> implements ActionExecution<V>
{
ActionDescriptor actionDescriptor
Closure actionClosure

@Override
V call()
{
return actionClosure(actionDescriptor)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ interface TrackerService
{
Map<String, AgentInfo> getAgentInfos(Fabric fabric)

AgentInfo getAgentInfo(String fabric, String agentName)

AgentInfo getAgentInfo(Fabric fabric, String agentName)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ class TrackerServiceImpl implements TrackerService, Destroyable
return getAgentsTrackerByFabric(fabric).getAgentInfos()
}

AgentInfo getAgentInfo(String fabric, String agentName)
{
getAgentInfo(fabricService.findFabric(fabric), agentName)
}

AgentInfo getAgentInfo(Fabric fabric, String agentName)
{
return getAgentsTrackerByFabric(fabric).getAgentInfo(agentName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* the License.
*/

package org.linkedin.glu.orchestration.engine.planner;
package org.linkedin.glu.orchestration.engine.action.descriptor;

import java.util.Map;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* the License.
*/

package org.linkedin.glu.orchestration.engine.planner;
package org.linkedin.glu.orchestration.engine.action.descriptor;

import java.util.Map;

Expand All @@ -24,14 +24,15 @@
public class AgentActionDescriptor extends BaseActionDescriptor
{
private final String _agent;
private final String _fabric;

/**
* Constructor
*/
public AgentActionDescriptor(String agent,
String description)
public AgentActionDescriptor(String description, String fabric, String agent)
{
super(description);
_fabric = fabric;
_agent = agent;
}

Expand All @@ -40,10 +41,16 @@ public String getAgent()
return _agent;
}

public String getFabric()
{
return _fabric;
}

@Override
public void toMetadata(Map<String, Object> metadata)
{
super.toMetadata(metadata);
metadata.put("agent", _agent);
metadata.put("fabric", _fabric);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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.orchestration.engine.action.descriptor;

import org.linkedin.glu.orchestration.engine.agents.NoSuchAgentException;

import java.net.URI;

/**
* @author yan@pongasoft.com
*/
public interface AgentURIProvider
{
/**
* @return the agent uri given the agent name
* @throws NoSuchAgentException if agent cannot be found
*/
URI getAgentURI(String fabric, String agent) throws NoSuchAgentException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
* the License.
*/

package org.linkedin.glu.orchestration.engine.planner;
package org.linkedin.glu.orchestration.engine.action.descriptor;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;

/**
* @author yan@pongasoft.com
Expand All @@ -34,6 +34,7 @@ public BaseActionDescriptor(String description)
_description = description;
}

@Override
public String getDescription()
{
return _description;
Expand All @@ -42,7 +43,7 @@ public String getDescription()
@Override
public Map<String, Object> toMetadata()
{
LinkedHashMap<String, Object> metadata = new LinkedHashMap<String, Object>();
Map<String, Object> metadata = new TreeMap<String, Object>();
toMetadata(metadata);
return metadata;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* the License.
*/

package org.linkedin.glu.orchestration.engine.planner;
package org.linkedin.glu.orchestration.engine.action.descriptor;

import java.util.Map;

Expand All @@ -28,11 +28,12 @@ public class MountPointActionDescriptor extends AgentActionDescriptor
/**
* Constructor
*/
public MountPointActionDescriptor(String agent,
String mountPoint,
String description)
public MountPointActionDescriptor(String description,
String fabric,
String agent,
String mountPoint)
{
super(agent, description);
super(description, fabric, agent);
_mountPoint = mountPoint;
}

Expand Down
Loading

0 comments on commit 709d7c3

Please sign in to comment.