You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/04/01 23:46:20 UTC

[1/3] incubator-brooklyn git commit: System Service enricher

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 63c03b15e -> 1f1491740


System Service enricher

Installs the entity being enriched as a system service. Saves the launch script and uses it to start the entity.


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/ac42ffc1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/ac42ffc1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/ac42ffc1

Branch: refs/heads/master
Commit: ac42ffc1dbff8fce6f466fcde3d9a24ccfc4c116
Parents: 0ff4216
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Tue Mar 17 20:08:49 2015 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Tue Mar 31 14:33:04 2015 +0300

----------------------------------------------------------------------
 .../entity/service/EntityLaunchListener.java    | 111 ++++++++++++++
 .../entity/service/InitdServiceInstaller.java   | 135 ++++++++++++++++
 .../entity/service/SystemServiceEnricher.java   | 152 +++++++++++++++++++
 .../entity/service/SystemServiceInstaller.java  |  25 +++
 .../service/SystemServiceInstallerFactory.java  |  28 ++++
 .../brooklyn/entity/service/service.sh          |  51 +++++++
 6 files changed, 502 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ac42ffc1/software/base/src/main/java/brooklyn/entity/service/EntityLaunchListener.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/service/EntityLaunchListener.java b/software/base/src/main/java/brooklyn/entity/service/EntityLaunchListener.java
new file mode 100644
index 0000000..a374ffe
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/service/EntityLaunchListener.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 brooklyn.entity.service;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.BrooklynTaskTags.EffectorCallTag;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.event.SensorEvent;
+import brooklyn.event.SensorEventListener;
+import brooklyn.management.ExecutionManager;
+import brooklyn.management.Task;
+import brooklyn.util.task.Tasks;
+
+public class EntityLaunchListener implements Runnable, SensorEventListener<Lifecycle> {
+    private static final String SSH_LAUNCH_TASK_PREFIX = "ssh: launching";
+    private static final String LAUNCH_CHECK_SKIP_TAG = "system-service-update";
+
+    private final AtomicReference<Task<?>> launchTaskRef = new AtomicReference<Task<?>>();
+    private final SystemServiceEnricher enricher;
+
+    public EntityLaunchListener(SystemServiceEnricher enricher) {
+        this.enricher = checkNotNull(enricher, "enricher");
+    }
+
+    @Override
+    public void onEvent(SensorEvent<Lifecycle> event) {
+        if (event.getValue() == Lifecycle.RUNNING) {
+            Task<?>launchTask = getLatestLaunchTask(enricher.getEntity());
+            if (launchTask != null) {
+                launchTaskRef.set(launchTask);
+                if (!launchTask.isDone()) {
+                    launchTask.addListener(this, enricher.getEntityExecutionContext());
+                }
+                if (launchTask.isDone()) {
+                    run();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void run() {
+        Task<?> launchTask = launchTaskRef.getAndSet(null);
+        if (launchTask == null) return;
+        if (launchTask.isError()) return;
+        enricher.onLaunched(launchTask);
+    }
+
+    private Task<?> getLatestLaunchTask(Entity entity) {
+        Task<?> startEffector = null;
+        ExecutionManager executionmgr = enricher.getManagementContext().getExecutionManager();
+        Set<Task<?>> entityTasks = BrooklynTaskTags.getTasksInEntityContext(executionmgr, entity);
+        for (Task<?> t : entityTasks) {
+            if (BrooklynTaskTags.isEffectorTask(t)) {
+                EffectorCallTag effectorTag = BrooklynTaskTags.getEffectorCallTag(t, false);
+                if (SystemServiceEnricher.LAUNCH_EFFECTOR_NAMES.contains(effectorTag.getEffectorName()) &&
+                        !BrooklynTaskTags.hasTag(t, LAUNCH_CHECK_SKIP_TAG)) {
+                    if (startEffector == null || startEffector.getStartTimeUtc() < t.getStartTimeUtc()) {
+                        startEffector = t;
+                    }
+                    BrooklynTaskTags.addTagDynamically(t, LAUNCH_CHECK_SKIP_TAG);
+                }
+            }
+        }
+        if (startEffector != null) {
+            Task<?> launchTask = findSshLaunchChild(startEffector);
+            if (launchTask != null) {
+                return launchTask;
+            }
+        }
+        return null;
+    }
+
+    private Task<?> findSshLaunchChild(Task<?> t) {
+        Iterable<Task<?>> children = Tasks.children(t);
+        for (Task<?> c : children) {
+            if (c.getDisplayName().startsWith(SSH_LAUNCH_TASK_PREFIX)) {
+                return c;
+            }
+        }
+        for (Task<?> c : children) {
+            Task<?> launchTask = findSshLaunchChild(c);
+            if (launchTask != null) {
+                return launchTask;
+            }
+        }
+        return null;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ac42ffc1/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java b/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java
new file mode 100644
index 0000000..ce52038
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 brooklyn.entity.service;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+import java.util.Map;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.effector.EffectorTasks;
+import brooklyn.entity.trait.HasShortName;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.location.cloud.CloudMachineNamer;
+import brooklyn.management.Task;
+import brooklyn.policy.Enricher;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.os.Os;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.task.ssh.SshPutTaskWrapper;
+import brooklyn.util.task.ssh.SshTasks;
+import brooklyn.util.task.system.ProcessTaskWrapper;
+import brooklyn.util.text.TemplateProcessor;
+
+
+public class InitdServiceInstaller implements SystemServiceInstaller {
+    private static final ConfigKey<String> SERVICE_TEMPLATE = ConfigKeys.newStringConfigKey(
+            "service.initd.service_template", "URL of the template to be used as the /etc/init.d service", "classpath:///brooklyn/entity/service/service.sh");
+
+    private final Entity entity;
+    private final Enricher enricher;
+
+    public InitdServiceInstaller(Entity entity, Enricher enricher) {
+        this.entity = checkNotNull(entity, "entity");
+        this.enricher = checkNotNull(enricher, "enricher");
+    }
+
+    @Override
+    public Task<?> getServiceInstallTask() {
+        ResourceUtils resource = new ResourceUtils(this);
+        String pidFile = entity.getAttribute(SoftwareProcess.PID_FILE);
+        String template = resource.getResourceAsString(enricher.config().get(SERVICE_TEMPLATE));
+        String serviceName = getServiceName();
+        SshMachineLocation sshMachine = EffectorTasks.getSshMachine(entity);
+        Map<String, Object> params = MutableMap.<String, Object>of(
+                "service.launch_script", Os.mergePaths(getRunDir(), getStartScriptName()),
+                "service.name", serviceName,
+                "service.user", sshMachine.getUser(),
+                "service.log_path", getLogLocation());
+        if (pidFile != null) {
+            params.put("service.pid_file", pidFile);
+        }
+        String service = TemplateProcessor.processTemplateContents(template, (EntityInternal)entity, params);
+        String tmpServicePath = Os.mergePaths(getRunDir(), serviceName);
+        String servicePath = "/etc/init.d/" + serviceName;
+        SshPutTaskWrapper putServiceTask = SshTasks.newSshPutTaskFactory(sshMachine, tmpServicePath)
+                .contents(service)
+                .newTask();
+        ProcessTaskWrapper<Integer> installServiceTask = SshTasks.newSshExecTaskFactory(sshMachine,
+                BashCommands.chain(
+                    BashCommands.sudo("mv " + tmpServicePath + " " + servicePath),
+                    BashCommands.sudo("chmod 0755 " + servicePath),
+                    BashCommands.sudo("chkconfig --add " + serviceName),
+                    BashCommands.sudo("chkconfig " + serviceName + " on")))
+            .requiringExitCodeZero()
+            .newTask();
+
+        return Tasks.<Void>builder()
+            .name("install (init.d)")
+            .description("Install init.d service")
+            .add(putServiceTask)
+            .add(installServiceTask)
+            .build();
+    }
+
+    private String getServiceName() {
+        String serviceNameTemplate = enricher.config().get(SystemServiceEnricher.SERVICE_NAME);
+        return serviceNameTemplate
+                .replace("${id}", entity.getId())
+                .replace("${entity_name}", getEntityName());
+    }
+
+    private CharSequence getEntityName() {
+        String name;
+        if (entity instanceof HasShortName) {
+            name = ((HasShortName)entity).getShortName();
+        } else if (entity instanceof Entity) {
+            name = ((Entity)entity).getDisplayName();
+        } else {
+            name = "brooklyn-service";
+        }
+        return CloudMachineNamer.sanitize(name.toString()).toLowerCase();
+    }
+
+    private String getStartScriptName() {
+        return enricher.config().get(SystemServiceEnricher.LAUNCH_SCRIPT_NAME);
+    }
+
+    private String getRunDir() {
+        return entity.getAttribute(SoftwareProcess.RUN_DIR);
+    }
+
+    private String getLogLocation() {
+        String logFileLocation = entity.getAttribute(Attributes.LOG_FILE_LOCATION);
+        if (logFileLocation != null) {
+            return new File(logFileLocation).getParent();
+        } else {
+            return "/tmp";
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ac42ffc1/software/base/src/main/java/brooklyn/entity/service/SystemServiceEnricher.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/service/SystemServiceEnricher.java b/software/base/src/main/java/brooklyn/entity/service/SystemServiceEnricher.java
new file mode 100644
index 0000000..e47e375
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/service/SystemServiceEnricher.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 brooklyn.entity.service;
+
+import java.util.Set;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.enricher.basic.AbstractEnricher;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.BrooklynTaskTags.WrappedStream;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.effector.EffectorTasks;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.management.ExecutionContext;
+import brooklyn.management.Task;
+import brooklyn.policy.Enricher;
+import brooklyn.util.net.Urls;
+import brooklyn.util.task.BasicExecutionManager;
+import brooklyn.util.task.DynamicTasks;
+import brooklyn.util.task.TaskBuilder;
+import brooklyn.util.task.ssh.SshPutTaskWrapper;
+import brooklyn.util.task.ssh.SshTasks;
+import brooklyn.util.task.system.ProcessTaskFactory;
+import brooklyn.util.task.system.ProcessTaskWrapper;
+
+import com.google.common.collect.ImmutableSet;
+
+public class SystemServiceEnricher extends AbstractEnricher implements Enricher {
+    public static final String DEFAULT_ENRICHER_UNIQUE_TAG = "systemService.tag";
+    protected static final Set<String> LAUNCH_EFFECTOR_NAMES = ImmutableSet.of("start", "restart");
+    public static final ConfigKey<String> LAUNCH_SCRIPT_NAME = ConfigKeys.newStringConfigKey(
+            "service.script_name", "The name of the launch script to be created in the runtime directory of the entity.", "service-launch.sh");
+    public static final ConfigKey<String> SERVICE_NAME = ConfigKeys.newStringConfigKey(
+            "service.name", "The name of the system service. Can use ${entity_name} and ${id} variables to template the value.", "${entity_name}-${id}");
+
+    @Override
+    public void setEntity(EntityLocal entity) {
+        super.setEntity(entity);
+        subscribeLaunch();
+        uniqueTag = DEFAULT_ENRICHER_UNIQUE_TAG;
+    }
+
+    private void subscribeLaunch() {
+        subscribe(entity, Attributes.SERVICE_STATE_ACTUAL, new EntityLaunchListener(this));
+    }
+
+    public void onLaunched(Task<?> task) {
+        WrappedStream streamStdin = BrooklynTaskTags.stream(task, BrooklynTaskTags.STREAM_STDIN);
+        if (streamStdin == null) return;
+
+        WrappedStream streamEnv = BrooklynTaskTags.stream(task, BrooklynTaskTags.STREAM_ENV);
+        String stdin = streamStdin.streamContents.get();
+        String env = streamEnv.streamContents.get();
+
+        final SshMachineLocation sshMachine = EffectorTasks.getSshMachine(entity);
+        final String launchScriptPath = Urls.mergePaths(getRunDir(), getStartScriptName());
+
+        Task<Void> installerTask = TaskBuilder.<Void>builder()
+                .name("install (service)")
+                .description("Install as a system service")
+                .body(new Runnable() {
+                    @Override
+                    public void run() {
+                        ProcessTaskFactory<Integer> taskFactory = SshTasks.newSshExecTaskFactory(sshMachine, "[ -e '" + launchScriptPath + "' ]")
+                                .summary("check installed")
+                                .allowingNonZeroExitCode();
+                        boolean isInstalled = DynamicTasks.queue(taskFactory).get() == 0;
+                        if (!isInstalled) {
+                            Task<?> serviceInstallTask = SystemServiceInstallerFactory.of(entity, SystemServiceEnricher.this).getServiceInstallTask();
+                            DynamicTasks.queue(serviceInstallTask);
+                        }
+                    }
+                })
+                .build();
+
+        SshPutTaskWrapper updateLaunchScriptTask = SshTasks.newSshPutTaskFactory(sshMachine, launchScriptPath).contents(getLaunchScript(stdin, env)).newTask();
+        ProcessTaskWrapper<Integer> makeExecutableTask = SshTasks.newSshExecTaskFactory(sshMachine, "chmod +x " + launchScriptPath)
+                .requiringExitCodeZero()
+                .newTask();
+        Task<Void> udpateTask = TaskBuilder.<Void>builder()
+                .name("update-launch")
+                .description("Update launch script used by the system service")
+                .add(updateLaunchScriptTask)
+                .add(makeExecutableTask)
+                .build();
+
+        Task<Void> updateService = TaskBuilder.<Void>builder()
+                .name("update-system-service")
+                .description("Update system service")
+                .add(installerTask)
+                .add(udpateTask)
+                .tag(BrooklynTaskTags.tagForContextEntity(entity))
+                .tag(BrooklynTaskTags.NON_TRANSIENT_TASK_TAG)
+                .build();
+
+        submitTopLevel(updateService);
+    }
+
+    private void submitTopLevel(Task<Void> updateService) {
+        Task<?> currentTask = BasicExecutionManager.getPerThreadCurrentTask().get();
+        BasicExecutionManager.getPerThreadCurrentTask().set(null);
+        try {
+            Entities.submit(entity, updateService);
+        } finally {
+            BasicExecutionManager.getPerThreadCurrentTask().set(currentTask);
+        }
+    }
+
+    private String getLaunchScript(String stdin, String env) {
+        // (?m) - multiline enable
+        // insert export at beginning of each line
+        return env.replaceAll("(?m)^", "export ") + "\n" + stdin;
+    }
+
+    private String getRunDir() {
+        return entity.getAttribute(SoftwareProcess.RUN_DIR);
+    }
+
+    private String getStartScriptName() {
+        return config().get(LAUNCH_SCRIPT_NAME);
+    }
+
+    ExecutionContext getEntityExecutionContext() {
+        return getManagementContext().getExecutionContext(entity);
+    }
+
+    protected Entity getEntity() {
+        return entity;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ac42ffc1/software/base/src/main/java/brooklyn/entity/service/SystemServiceInstaller.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/service/SystemServiceInstaller.java b/software/base/src/main/java/brooklyn/entity/service/SystemServiceInstaller.java
new file mode 100644
index 0000000..a4d8b6d
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/service/SystemServiceInstaller.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 brooklyn.entity.service;
+
+import brooklyn.management.Task;
+
+public interface SystemServiceInstaller {
+    Task<?> getServiceInstallTask();
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ac42ffc1/software/base/src/main/java/brooklyn/entity/service/SystemServiceInstallerFactory.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/service/SystemServiceInstallerFactory.java b/software/base/src/main/java/brooklyn/entity/service/SystemServiceInstallerFactory.java
new file mode 100644
index 0000000..08da83a
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/service/SystemServiceInstallerFactory.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 brooklyn.entity.service;
+
+import brooklyn.entity.Entity;
+import brooklyn.policy.Enricher;
+
+public class SystemServiceInstallerFactory {
+    public static SystemServiceInstaller of(Entity entity, Enricher systemServiceEnricher) {
+        return new InitdServiceInstaller(entity, systemServiceEnricher);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ac42ffc1/software/base/src/main/resources/brooklyn/entity/service/service.sh
----------------------------------------------------------------------
diff --git a/software/base/src/main/resources/brooklyn/entity/service/service.sh b/software/base/src/main/resources/brooklyn/entity/service/service.sh
new file mode 100644
index 0000000..4a1b293
--- /dev/null
+++ b/software/base/src/main/resources/brooklyn/entity/service/service.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+# chkconfig: - 80 20
+#
+### BEGIN INIT INFO
+# Provides:          ${service.name}
+# Required-Start:    $network $syslog
+# Required-Stop:     $network $syslog
+# Default-Start:
+# Default-Stop:
+# Short-Description: Brooklyn entity service
+# Description:       Service for Brooklyn managed entity
+### END INIT INFO
+
+case $1 in
+ start)
+  touch ${service.log_path}/${service.name}.log
+  chown ${service.user} ${service.log_path}/${service.name}.log
+  sudo -u ${service.user} ${service.launch_script} >> ${service.log_path}/${service.name}.log 2>&1
+  ;;
+# stop)
+#  ;;
+# restart)
+#  ;;
+# status)
+#  ;;
+# reload)
+#  ;;
+ *)
+#  echo "Usage: $0 {start|stop|restart|reload|status}"
+  echo "Usage: $0 {start}"
+  exit 2
+  ;;
+esac


[2/3] incubator-brooklyn git commit: Test for the system service installer

Posted by al...@apache.org.
Test for the system service installer


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/6470cc51
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/6470cc51
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/6470cc51

Branch: refs/heads/master
Commit: 6470cc511469defac92b794645486ed2b8fd6544
Parents: ac42ffc
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Wed Mar 25 12:29:54 2015 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Tue Mar 31 14:33:12 2015 +0300

----------------------------------------------------------------------
 .../service/SystemServiceEnricherTest.java      | 95 ++++++++++++++++++++
 1 file changed, 95 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6470cc51/software/base/src/test/java/brooklyn/entity/service/SystemServiceEnricherTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/service/SystemServiceEnricherTest.java b/software/base/src/test/java/brooklyn/entity/service/SystemServiceEnricherTest.java
new file mode 100644
index 0000000..6436fa9
--- /dev/null
+++ b/software/base/src/test/java/brooklyn/entity/service/SystemServiceEnricherTest.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 brooklyn.entity.service;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppLiveTestSupport;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityPredicates;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.VanillaSoftwareProcess;
+import brooklyn.entity.basic.VanillaSoftwareProcessImpl;
+import brooklyn.entity.basic.VanillaSoftwareProcessSshDriver;
+import brooklyn.entity.effector.EffectorTasks;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.location.jclouds.JcloudsLocation;
+import brooklyn.policy.EnricherSpec;
+import brooklyn.test.Asserts;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class SystemServiceEnricherTest extends BrooklynAppLiveTestSupport {
+    //requires /etc/init.d OS, for example CentOS 6.5
+    private static final String LOCATION_SPEC = "named:service-live-test-location";
+    private JcloudsLocation location;
+
+    @Override
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        super.setUp();
+        location = (JcloudsLocation) mgmt.getLocationRegistry().resolve(LOCATION_SPEC);
+    }
+
+    @Test(groups = "Live")
+    public void testRestartLaunchesService() {
+        String launchCmd = "nohup bash -c \"echo \\$\\$ > $PID_FILE; while true; do sleep 1000; done\" &";
+        EntitySpec<VanillaSoftwareProcess> procSpec = EntitySpec.create(VanillaSoftwareProcess.class)
+                .configure(VanillaSoftwareProcess.LAUNCH_COMMAND, launchCmd)
+                .enricher(EnricherSpec.create(SystemServiceEnricher.class));
+        VanillaSoftwareProcess proc = app.createAndManageChild(procSpec);
+        app.start(ImmutableList.of(location));
+
+        waitHealthy(proc);
+
+        SshMachineLocation machine = EffectorTasks.getSshMachine(proc);
+        String pidFile = getPidFile(proc);
+        String killCmd = "kill -9 `cat " + pidFile + "`";
+        machine.execCommands("kill process", ImmutableList.of(killCmd));
+
+        waitFailed(proc);
+
+        int restartCode = machine.execCommands("restart machine", ImmutableList.of(BashCommands.sudo("/sbin/shutdown -r now")));
+        assertEquals(restartCode, 0);
+
+        waitHealthy(proc);
+    }
+
+    private String getPidFile(VanillaSoftwareProcess proc) {
+        VanillaSoftwareProcessImpl impl = (VanillaSoftwareProcessImpl)Entities.deproxy(proc);
+        return ((VanillaSoftwareProcessSshDriver)impl.getDriver()).getPidFile();
+    }
+
+    private void waitFailed(VanillaSoftwareProcess proc) {
+        Asserts.eventually(ImmutableMap.of("timeout", Duration.FIVE_MINUTES), Suppliers.ofInstance(proc), EntityPredicates.attributeEqualTo(Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE));
+    }
+
+    private void waitHealthy(VanillaSoftwareProcess proc) {
+        Asserts.eventually(ImmutableMap.of("timeout", Duration.FIVE_MINUTES), Suppliers.ofInstance(proc), EntityPredicates.attributeEqualTo(Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING));
+    }
+}


[3/3] incubator-brooklyn git commit: This closes #556

Posted by al...@apache.org.
This closes #556


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/1f149174
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/1f149174
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/1f149174

Branch: refs/heads/master
Commit: 1f1491740ca8b3442eb6f75788449e0288edad5a
Parents: 63c03b1 6470cc5
Author: Aled Sage <al...@gmail.com>
Authored: Wed Apr 1 22:46:04 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Apr 1 22:46:04 2015 +0100

----------------------------------------------------------------------
 .../entity/service/EntityLaunchListener.java    | 111 ++++++++++++++
 .../entity/service/InitdServiceInstaller.java   | 135 ++++++++++++++++
 .../entity/service/SystemServiceEnricher.java   | 152 +++++++++++++++++++
 .../entity/service/SystemServiceInstaller.java  |  25 +++
 .../service/SystemServiceInstallerFactory.java  |  28 ++++
 .../brooklyn/entity/service/service.sh          |  51 +++++++
 .../service/SystemServiceEnricherTest.java      |  95 ++++++++++++
 7 files changed, 597 insertions(+)
----------------------------------------------------------------------