You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by im...@apache.org on 2013/12/20 05:03:51 UTC
[2/3] git commit: Implemented standalone cartridge agent component
Implemented standalone cartridge agent component
Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/c8985d58
Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/c8985d58
Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/c8985d58
Branch: refs/heads/master
Commit: c8985d585c88320ad3e6781d2383db75f994b7df
Parents: 195dc22
Author: Imesh Gunaratne <im...@apache.org>
Authored: Fri Dec 20 09:32:27 2013 +0530
Committer: Imesh Gunaratne <im...@apache.org>
Committed: Fri Dec 20 09:32:27 2013 +0530
----------------------------------------------------------------------
.../org.apache.stratos.cartridge.agent/pom.xml | 98 +++
.../stratos/cartridge/agent/CartridgeAgent.java | 131 ++++
.../apache/stratos/cartridge/agent/Main.java | 57 ++
.../cartridge/agent/RepositoryFileListener.java | 41 ++
.../synchronizer/RepositoryInformation.java | 65 ++
.../git/impl/GitBasedArtifactRepository.java | 682 +++++++++++++++++++
.../CustomJschConfigSessionFactory.java | 64 ++
.../GitDeploymentSynchronizerConstants.java | 61 ++
.../git/internal/RepositoryContext.java | 131 ++++
.../synchronizer/git/util/Utilities.java | 73 ++
.../config/CartridgeAgentConfiguration.java | 163 +++++
.../config/configurator/JndiConfigurator.java | 105 +++
.../publisher/CartridgeAgentEventPublisher.java | 52 ++
.../publisher/HealthStatisticsNotifier.java | 113 +++
.../publisher/HealthStatisticsPublisher.java | 90 +++
.../publisher/HealthStatisticsReader.java | 47 ++
.../agent/util/CartridgeAgentConstants.java | 41 ++
.../agent/util/CartridgeAgentUtils.java | 114 ++++
components/pom.xml | 2 +
19 files changed, 2130 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/pom.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/pom.xml b/components/org.apache.stratos.cartridge.agent/pom.xml
new file mode 100644
index 0000000..ecd46a8
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ # 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <parent>
+ <groupId>org.apache.stratos</groupId>
+ <artifactId>stratos-components-parent</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>org.apache.stratos.cartridge.agent</artifactId>
+ <packaging>jar</packaging>
+ <name>Apache Stratos - Cartridge Agent</name>
+ <description>Apache Stratos Cartridge Agent</description>
+ <url>http://apache.org</url>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.stratos</groupId>
+ <artifactId>org.apache.stratos.common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.wso2.andes.wso2</groupId>
+ <artifactId>andes-client</artifactId>
+ <version>0.13.wso2v8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs.wso2</groupId>
+ <artifactId>geronimo-jms_1.1_spec</artifactId>
+ <version>1.1.0.wso2v1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.7.5</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.stratos</groupId>
+ <artifactId>org.apache.stratos.messaging</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit</artifactId>
+ <version>2.1.0.wso2v1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit</artifactId>
+ <version>2.1.0.wso2v1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.jcraft</groupId>
+ <artifactId>jsch</artifactId>
+ <version>0.1.49.wso2v1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.wso2.carbon</groupId>
+ <artifactId>org.wso2.carbon.utils</artifactId>
+ <version>4.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.wso2.carbon</groupId>
+ <artifactId>org.wso2.carbon.databridge.agent.thrift</artifactId>
+ <version>4.1.0</version>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/CartridgeAgent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/CartridgeAgent.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/CartridgeAgent.java
new file mode 100644
index 0000000..807e950
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/CartridgeAgent.java
@@ -0,0 +1,131 @@
+package org.apache.stratos.cartridge.agent;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.RepositoryInformation;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.impl.GitBasedArtifactRepository;
+import org.apache.stratos.cartridge.agent.event.publisher.CartridgeAgentEventPublisher;
+import org.apache.stratos.cartridge.agent.util.CartridgeAgentConstants;
+import org.apache.stratos.cartridge.agent.util.CartridgeAgentUtils;
+import org.apache.stratos.messaging.event.Event;
+import org.apache.stratos.messaging.event.instance.notifier.ArtifactUpdatedEvent;
+import org.apache.stratos.messaging.listener.instance.notifier.ArtifactUpdateEventListener;
+import org.apache.stratos.messaging.message.processor.instance.notifier.InstanceNotifierMessageProcessorChain;
+import org.apache.stratos.messaging.message.receiver.instance.notifier.InstanceNotifierEventMessageDelegator;
+import org.apache.stratos.messaging.message.receiver.instance.notifier.InstanceNotifierEventMessageReceiver;
+
+/**
+ * Cartridge agent runnable.
+ */
+public class CartridgeAgent implements Runnable {
+
+ private static final Log log = LogFactory.getLog(CartridgeAgent.class);
+
+ private boolean terminated;
+
+ @Override
+ public void run() {
+ if(log.isInfoEnabled()) {
+ log.info("Cartridge agent started");
+ }
+
+ String jndiPropertiesDir = System.getProperty(CartridgeAgentConstants.JNDI_PROPERTIES_DIR);
+ if(StringUtils.isBlank(jndiPropertiesDir)) {
+ throw new RuntimeException(String.format("System property not found: %s", CartridgeAgentConstants.JNDI_PROPERTIES_DIR));
+ }
+
+ String payloadPath = System.getProperty(CartridgeAgentConstants.PARAM_FILE_PATH);
+ if(StringUtils.isBlank(payloadPath)) {
+ throw new RuntimeException(String.format("System property not found: %s", CartridgeAgentConstants.PARAM_FILE_PATH));
+ }
+
+ // Start instance notifier listener thread
+ if(log.isDebugEnabled()) {
+ log.debug("Starting instance notifier event message receiver thread");
+ }
+ InstanceNotifierMessageProcessorChain processorChain = new InstanceNotifierMessageProcessorChain();
+ processorChain.addEventListener(new ArtifactUpdateEventListener() {
+ @Override
+ protected void onEvent(Event event) {
+ onArtifactUpdateEvent((ArtifactUpdatedEvent) event);
+ }
+ });
+ InstanceNotifierEventMessageDelegator messageDelegator = new InstanceNotifierEventMessageDelegator(processorChain);
+ InstanceNotifierEventMessageReceiver messageReceiver = new InstanceNotifierEventMessageReceiver(messageDelegator);
+ Thread messageReceiverThread = new Thread(messageReceiver);
+ messageReceiverThread.start();
+
+ // Wait until message receiver is subscribed to the topic to
+ // send the instance started event
+ while (!messageReceiver.isSubscribed()) {
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ // Publish instance started event
+ CartridgeAgentEventPublisher.publishInstanceStartedEvent();
+
+ // Wait for all ports to be active
+ CartridgeAgentUtils.waitUntilPortsActive();
+
+ // Check repo url
+ String repoUrl = CartridgeAgentConfiguration.getInstance().getRepoUrl();
+ if ("null".equals(repoUrl) || StringUtils.isBlank(repoUrl)) {
+ if(log.isInfoEnabled()) {
+ log.info("No repo url found");
+ }
+
+ // Publish instance activated event
+ CartridgeAgentEventPublisher.publishInstanceActivatedEvent();
+ }
+
+ // TODO: Start this thread only if this node is configured as a commit true node
+ // Start periodical file checker task
+ // ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+ // scheduler.scheduleWithFixedDelay(new RepositoryFileListener(), 0, 10, TimeUnit.SECONDS);
+
+ // Keep the thread live until terminated
+ while (!terminated);
+ }
+
+ private void onArtifactUpdateEvent(ArtifactUpdatedEvent event) {
+ ArtifactUpdatedEvent artifactUpdatedEvent = (ArtifactUpdatedEvent) event;
+ if(log.isDebugEnabled()) {
+ log.debug(String.format("Artifact update event received: $s", artifactUpdatedEvent.toString()));
+ }
+
+ String clusterIdInPayload = CartridgeAgentConfiguration.getInstance().getClusterId();
+ String localRepoPath = CartridgeAgentConfiguration.getInstance().getAppPath();
+ String clusterIdInMessage = artifactUpdatedEvent.getClusterId();
+ String repoURL = artifactUpdatedEvent.getRepoURL();
+ String repoPassword = CartridgeAgentUtils.decryptPassword(artifactUpdatedEvent.getRepoPassword());
+ String repoUsername = artifactUpdatedEvent.getRepoUserName();
+ String tenantId = artifactUpdatedEvent.getTenantId();
+
+ if(StringUtils.isNotEmpty(repoURL) && (clusterIdInPayload != null) && clusterIdInPayload.equals(clusterIdInMessage)) {
+ if(log.isDebugEnabled()) {
+ log.debug("Executing git checkout");
+ }
+ RepositoryInformation repoInformation = new RepositoryInformation();
+ repoInformation.setRepoUsername(repoUsername);
+ repoInformation.setRepoPassword(repoPassword);
+ repoInformation.setRepoUrl(repoURL);
+ repoInformation.setRepoPath(localRepoPath);
+ repoInformation.setTenantId(tenantId);
+ boolean cloneExists = GitBasedArtifactRepository.cloneExists(repoInformation);
+ GitBasedArtifactRepository.checkout(repoInformation);
+ if(!cloneExists){
+ // Executed git clone, publish instance activated event
+ CartridgeAgentEventPublisher.publishInstanceActivatedEvent();
+ }
+ }
+ }
+
+ public void terminate() {
+ terminated = true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/Main.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/Main.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/Main.java
new file mode 100644
index 0000000..0506dd2
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/Main.java
@@ -0,0 +1,57 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
+import org.apache.stratos.cartridge.agent.config.configurator.JndiConfigurator;
+
+/**
+ * Cartridge agent main class.
+ */
+public class Main {
+
+ private static final Log log = LogFactory.getLog(Main.class);
+ private static CartridgeAgent cartridgeAgent;
+
+ public static void main(String[] args) {
+ try {
+ // Configure log4j properties
+ PropertyConfigurator.configure(System.getProperty("log4j.properties.file.path"));
+
+ // Generate jndi.properties file
+ JndiConfigurator.configure();
+
+ cartridgeAgent = new CartridgeAgent();
+ Thread thread = new Thread(cartridgeAgent);
+ thread.start();
+ } catch (Exception e) {
+ if (log.isErrorEnabled()) {
+ log.error(e);
+ }
+ if (cartridgeAgent != null) {
+ cartridgeAgent.terminate();
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/RepositoryFileListener.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/RepositoryFileListener.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/RepositoryFileListener.java
new file mode 100644
index 0000000..c6e53b5
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/RepositoryFileListener.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.impl.GitBasedArtifactRepository;
+
+public class RepositoryFileListener implements Runnable {
+
+ private static final Log log = LogFactory.getLog(RepositoryFileListener.class);
+
+ @Override
+ public void run() {
+ if(log.isInfoEnabled()) {
+ log.info("Executing repository file listener");
+ }
+ boolean commitStatus = GitBasedArtifactRepository.commit();
+ if(log.isInfoEnabled()) {
+ log.info("Commit status: " + commitStatus);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/RepositoryInformation.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/RepositoryInformation.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/RepositoryInformation.java
new file mode 100644
index 0000000..57d6042
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/RepositoryInformation.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer;
+
+/**
+ * @author wso2
+ *
+ */
+public class RepositoryInformation {
+
+ private String repoUrl;
+ private String repoUsername;
+ private String repoPassword;
+ private String repoPath;
+ private String tenantId;
+
+ public String getRepoUrl() {
+ return repoUrl;
+ }
+ public void setRepoUrl(String repoUrl) {
+ this.repoUrl = repoUrl;
+ }
+ public String getRepoUsername() {
+ return repoUsername;
+ }
+ public void setRepoUsername(String repoUsername) {
+ this.repoUsername = repoUsername;
+ }
+ public String getRepoPassword() {
+ return repoPassword;
+ }
+ public void setRepoPassword(String repoPassword) {
+ this.repoPassword = repoPassword;
+ }
+ public String getRepoPath() {
+ return repoPath;
+ }
+ public void setRepoPath(String repoPath) {
+ this.repoPath = repoPath;
+ }
+ public String getTenantId() {
+ return tenantId;
+ }
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/impl/GitBasedArtifactRepository.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/impl/GitBasedArtifactRepository.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/impl/GitBasedArtifactRepository.java
new file mode 100644
index 0000000..21aaa64
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/impl/GitBasedArtifactRepository.java
@@ -0,0 +1,682 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.RepositoryInformation;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.internal.CustomJschConfigSessionFactory;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.internal.GitDeploymentSynchronizerConstants;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.internal.RepositoryContext;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.util.Utilities;
+import org.eclipse.jgit.api.*;
+import org.eclipse.jgit.api.errors.*;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.storage.file.FileRepository;
+import org.eclipse.jgit.transport.SshSessionFactory;
+import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Git based artifact repository.
+ *
+ *
+ */
+public class GitBasedArtifactRepository {
+
+ private static final Log log = LogFactory.getLog(GitBasedArtifactRepository.class);
+
+ //Map to keep track of git context per tenant (remote urls, jgit git objects, etc.)
+ private static ConcurrentHashMap<Integer, RepositoryContext>
+ tenantToRepoContextMap = new ConcurrentHashMap<Integer, RepositoryContext>();
+
+ private GitBasedArtifactRepository () {
+
+ }
+
+ /**
+ * initializes and populates the git context with relevant data
+ *
+ * @param repositoryInformation id of the tenant
+ *
+ */
+ private static void initGitContext (RepositoryInformation repositoryInformation) {
+
+ /* if (tenantId == GitDeploymentSynchronizerConstants.SUPER_TENANT_ID)
+ return;*/
+
+ log.info("In init git context............");
+
+ int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
+ String gitLocalRepoPath = repositoryInformation.getRepoPath();
+ RepositoryContext gitRepoCtx = new RepositoryContext();
+ String gitRemoteRepoUrl = repositoryInformation.getRepoUrl();
+
+ log.info("local path " + gitLocalRepoPath);
+ log.info("remote url " + gitRemoteRepoUrl);
+ log.info("tenant " + tenantId);
+
+ gitRepoCtx.setTenantId(tenantId);
+ gitRepoCtx.setGitLocalRepoPath(gitLocalRepoPath);
+ gitRepoCtx.setGitRemoteRepoUrl(gitRemoteRepoUrl);
+
+ gitRepoCtx.setRepoUsername(repositoryInformation.getRepoUsername());
+ gitRepoCtx.setRepoPassword(repositoryInformation.getRepoPassword());
+
+ try {
+ if(isKeyBasedAuthentication(gitRemoteRepoUrl, tenantId)) {
+ gitRepoCtx.setKeyBasedAuthentication(true);
+ initSSHAuthentication();
+ }
+ else
+ gitRepoCtx.setKeyBasedAuthentication(false);
+ } catch (Exception e1) {
+ log.error("Exception occurred.. " + e1.getMessage(), e1);
+ }
+
+ FileRepository localRepo = null;
+ try {
+ localRepo = new FileRepository(new File(gitLocalRepoPath + "/.git"));
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ gitRepoCtx.setLocalRepo(localRepo);
+ gitRepoCtx.setGit(new Git(localRepo));
+ gitRepoCtx.setCloneExists(false);
+
+ cacheGitRepoContext(tenantId, gitRepoCtx);
+ }
+
+ /**
+ * Checks if key based authentication (SSH) is required
+ *
+ * @param url git repository url for the tenant
+ * @param tenantId id of the tenant
+ *
+ * @return true if SSH authentication is required, else false
+ */
+ private static boolean isKeyBasedAuthentication(String url, int tenantId) {
+
+ if (url.startsWith(GitDeploymentSynchronizerConstants.GIT_HTTP_REPO_URL_PREFIX) ||
+ url.startsWith(GitDeploymentSynchronizerConstants.GIT_HTTPS_REPO_URL_PREFIX)) {//http or https url
+ // authentication with username and password, not key based
+ return false;
+ }
+
+ else if (url.startsWith(GitDeploymentSynchronizerConstants.GITHUB_READ_ONLY_REPO_URL_PREFIX)) { //github read-only repo url
+ // no authentication required
+ return false;
+ }
+
+ else if (url.startsWith(GitDeploymentSynchronizerConstants.GIT_REPO_SSH_URL_PREFIX) ||
+ url.contains(GitDeploymentSynchronizerConstants.GIT_REPO_SSH_URL_SUBSTRING)) { //other repo, needs ssh authentication
+ // key based authentication
+ return true;
+ }
+
+ else {
+ log.error("Invalid git URL provided for tenant " + tenantId);
+ throw new RuntimeException("Invalid git URL provided for tenant " + tenantId);
+ }
+ }
+
+ /**
+ * Initializes SSH authentication
+ */
+ private static void initSSHAuthentication () {
+
+ SshSessionFactory.setInstance(new CustomJschConfigSessionFactory());
+ }
+
+ /**
+ * Caches RepositoryContext against tenant repository path
+ *
+ * @param tenantId tenant repository path
+ * @param gitRepoCtx RepositoryContext instance for tenant
+ */
+ private static void cacheGitRepoContext(int tenantId, RepositoryContext gitRepoCtx) {
+
+ log.info("caching repo context....");
+ tenantToRepoContextMap.put(tenantId, gitRepoCtx);
+ }
+
+ /**
+ * Retrieve cached RepositoryContext relevant to the tenant's local repo path
+ *
+ * @param tenantId
+ *
+ * @return corresponding RepositoryContext instance for the
+ * tenant's local repo if available, else null
+ */
+ private static RepositoryContext retrieveCachedGitContext (int tenantId) {
+
+ return tenantToRepoContextMap.get(tenantId);
+ }
+
+ /**
+ * Commits any changes in the local repository to the relevant remote repository
+ *
+ * @return
+ *
+ */
+ public static boolean commit() {
+
+ // foreach tenant's local path check for commit
+ // TODO implement later, this is applicable for management node.
+ //log.info(" In commit.... map count : " + tenantToRepoContextMap.size());
+
+ for (Entry<Integer, RepositoryContext> tenantMap : tenantToRepoContextMap
+ .entrySet()) {
+
+ int tenantId = tenantMap.getKey();
+ //log.info("map count has values..tenant Id : " + tenantId);
+
+ RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
+ if (gitRepoCtx == null) {
+
+ log.info("No git repository context information found for tenant "
+ + tenantId);
+
+ return false;
+ }
+
+ Git git = gitRepoCtx.getGit();
+ StatusCommand statusCmd = git.status();
+ Status status = null;
+ try {
+ status = statusCmd.call();
+
+ } catch (GitAPIException e) {
+ log.error(
+ "Git status operation for tenant "
+ + gitRepoCtx.getTenantId() + " failed, ", e);
+ return false;
+ }
+ //log.info("status : " + status.toString());
+ if (status.isClean()) {// no changes, nothing to commit
+
+ log.info("No changes detected in the local repository for tenant "
+ + tenantId);
+ return false;
+ }
+
+ addArtifacts(gitRepoCtx, getNewArtifacts(status));
+ addArtifacts(gitRepoCtx, getModifiedArtifacts(status));
+ removeArtifacts(gitRepoCtx, getRemovedArtifacts(status));
+ commitToLocalRepo(gitRepoCtx);
+ pushToRemoteRepo(gitRepoCtx);
+
+ return false;
+
+ }
+ return false;
+ }
+
+ /**
+ * Returns the newly added artifact set relevant to the current status of the repository
+ *
+ * @param status git status
+ *
+ * @return artifact names set
+ */
+ private static Set<String> getNewArtifacts (Status status) {
+
+ return status.getUntracked();
+ }
+
+ /**
+ * Returns the removed (undeployed) artifact set relevant to the current status of the repository
+ *
+ * @param status git status
+ *
+ * @return artifact names set
+ */
+ private static Set<String> getRemovedArtifacts (Status status) {
+
+ return status.getMissing();
+ }
+
+ /**
+ * Return the modified artifacts set relevant to the current status of the repository
+ *
+ * @param status git status
+ *
+ * @return artifact names set
+ */
+ private static Set<String> getModifiedArtifacts (Status status) {
+
+ return status.getModified();
+ }
+
+ /**
+ * Adds the artifacts to the local staging area
+ *
+ * @param gitRepoCtx RepositoryContext instance
+ * @param artifacts set of artifacts
+ */
+ private static void addArtifacts (RepositoryContext gitRepoCtx, Set<String> artifacts) {
+
+ if(artifacts.isEmpty())
+ return;
+
+ AddCommand addCmd = gitRepoCtx.getGit().add();
+ Iterator<String> it = artifacts.iterator();
+ while(it.hasNext())
+ addCmd.addFilepattern(it.next());
+
+ try {
+ addCmd.call();
+
+ } catch (GitAPIException e) {
+ log.error("Adding artifact to the local repository at " + gitRepoCtx.getGitLocalRepoPath() + "failed", e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Removes the set of artifacts from local repo
+ *
+ * @param gitRepoCtx RepositoryContext instance
+ * @param artifacts Set of artifact names to remove
+ */
+ private static void removeArtifacts (RepositoryContext gitRepoCtx, Set<String> artifacts) {
+
+ if(artifacts.isEmpty())
+ return;
+
+ RmCommand rmCmd = gitRepoCtx.getGit().rm();
+ Iterator<String> it = artifacts.iterator();
+ while (it.hasNext()) {
+ rmCmd.addFilepattern(it.next());
+ }
+
+ try {
+ rmCmd.call();
+
+ } catch (GitAPIException e) {
+ log.error("Removing artifact from the local repository at " + gitRepoCtx.getGitLocalRepoPath() + "failed", e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Commits changes for a tenant to relevant the local repository
+ *
+ * @param gitRepoCtx RepositoryContext instance for the tenant
+ */
+ private static void commitToLocalRepo (RepositoryContext gitRepoCtx) {
+
+ CommitCommand commitCmd = gitRepoCtx.getGit().commit();
+ commitCmd.setMessage("tenant " + gitRepoCtx.getTenantId() + "'s artifacts committed to local repo at " +
+ gitRepoCtx.getGitLocalRepoPath());
+
+ try {
+ commitCmd.call();
+
+ } catch (GitAPIException e) {
+ log.error("Committing artifacts to local repository failed for tenant " + gitRepoCtx.getTenantId(), e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Pushes the artifacts of the tenant to relevant remote repository
+ *
+ * @param gitRepoCtx RepositoryContext instance for the tenant
+ */
+ private static void pushToRemoteRepo(RepositoryContext gitRepoCtx) {
+
+ PushCommand pushCmd = gitRepoCtx.getGit().push();
+ if(!gitRepoCtx.getKeyBasedAuthentication()) {
+ UsernamePasswordCredentialsProvider credentialsProvider = createCredentialsProvider(gitRepoCtx);
+ if (credentialsProvider != null)
+ pushCmd.setCredentialsProvider(credentialsProvider);
+ }
+
+ try {
+ pushCmd.call();
+
+ } catch (GitAPIException e) {
+ log.error("Pushing artifacts to remote repository failed for tenant " + gitRepoCtx.getTenantId(), e);
+ e.printStackTrace();
+ }
+ }
+
+ public static boolean checkout(RepositoryInformation repositoryInformation) {
+
+ log.info("In checkout............");
+
+ int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
+
+ // if context for tenant is not initialized
+ if(tenantToRepoContextMap.get(tenantId) == null)
+ initGitContext(repositoryInformation);
+
+
+ RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
+ if(gitRepoCtx == null) { //to handle super tenant scenario
+ // if(log.isDebugEnabled())
+ log.info("No git repository context information found for deployment synchronizer ");
+
+ return true;
+ }
+
+ /*if(gitRepoCtx.getTenantId() == GitDeploymentSynchronizerConstants.SUPER_TENANT_ID)
+ return true; */
+ if(!gitRepoCtx.cloneExists())
+ cloneRepository(gitRepoCtx);
+
+ return pullArtifacts(gitRepoCtx);
+ }
+
+
+
+ public static boolean cloneExists(RepositoryInformation repositoryInformation) {
+
+ int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
+
+ // if context for tenant is not initialized
+ if(tenantToRepoContextMap.get(tenantId) == null)
+ initGitContext(repositoryInformation);
+
+
+ RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
+ if(gitRepoCtx == null) {
+ return false;
+ }
+
+ /*if(gitRepoCtx.getTenantId() == GitDeploymentSynchronizerConstants.SUPER_TENANT_ID)
+ return true; */
+ return gitRepoCtx.cloneExists();
+ }
+
+ /**
+ * Pulling if any updates are available in the remote git repository. If basic authentication is required,
+ * will call 'RepositoryInformationService' for credentials.
+ *
+ * @param gitRepoCtx RepositoryContext instance for tenant
+ *
+ * @return true if success, else false
+ */
+ private static boolean pullArtifacts (RepositoryContext gitRepoCtx) {
+
+ log.info("Pulling artifacts.....");
+ PullCommand pullCmd = gitRepoCtx.getGit().pull();
+
+ if(!gitRepoCtx.getKeyBasedAuthentication()) {
+ UsernamePasswordCredentialsProvider credentialsProvider = createCredentialsProvider(gitRepoCtx);
+ if (credentialsProvider != null)
+ pullCmd.setCredentialsProvider(credentialsProvider);
+ }
+
+ try {
+ pullCmd.call();
+
+ } catch (InvalidConfigurationException e) {
+ log.warn("Git pull unsuccessful for tenant " + gitRepoCtx.getTenantId() + ", " + e.getMessage());
+ //handleInvalidConfigurationError(gitRepoCtx);
+ //return false;
+ Utilities.deleteFolderStructure(new File(gitRepoCtx.getGitLocalRepoPath()));
+ cloneRepository(gitRepoCtx);
+ return true;
+
+ } catch (JGitInternalException e) {
+ log.warn("Git pull unsuccessful for tenant " + gitRepoCtx.getTenantId() + ", " + e.getMessage());
+ return false;
+
+ } catch (TransportException e) {
+ log.error("Accessing remote git repository " + gitRepoCtx.getGitRemoteRepoUrl() + " failed for tenant " + gitRepoCtx.getTenantId(), e);
+ e.printStackTrace();
+ return false;
+
+ } catch (CheckoutConflictException e) { //TODO: handle conflict efficiently. Currently the whole directory is deleted and re-cloned
+ log.warn("Git pull for the path " + e.getConflictingPaths().toString() + " failed due to conflicts");
+ Utilities.deleteFolderStructure(new File(gitRepoCtx.getGitLocalRepoPath()));
+ cloneRepository(gitRepoCtx);
+ return true;
+
+ } catch (GitAPIException e) {
+ log.error("Git pull operation for tenant " + gitRepoCtx.getTenantId() + " failed", e);
+ e.printStackTrace();
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Handles the Invalid configuration issues
+ *
+ * @param gitRepoCtx RepositoryContext instance of the tenant
+ */
+ private void handleInvalidConfigurationError (RepositoryContext gitRepoCtx) {
+
+ StoredConfig storedConfig = gitRepoCtx.getLocalRepo().getConfig();
+ boolean modifiedConfig = false;
+ if(storedConfig != null) {
+
+ if(storedConfig.getString("branch", "master", "remote") == null ||
+ storedConfig.getString("branch", "master", "remote").isEmpty()) {
+
+ storedConfig.setString("branch", "master", "remote", "origin");
+ modifiedConfig = true;
+ }
+
+ if(storedConfig.getString("branch", "master", "merge") == null ||
+ storedConfig.getString("branch", "master", "merge").isEmpty()) {
+
+ storedConfig.setString("branch", "master", "merge", "refs/heads/master");
+ modifiedConfig = true;
+ }
+
+ if(modifiedConfig) {
+ try {
+ storedConfig.save();
+ // storedConfig.load();
+
+ } catch (IOException e) {
+ log.error("Error saving git configuration file in local repo at " + gitRepoCtx.getGitLocalRepoPath(), e);
+ e.printStackTrace();
+
+ } /*catch (ConfigInvalidException e) {
+ log.error("Invalid configurations in local repo at " + gitRepoCtx.getGitLocalRepoPath(), e);
+ e.printStackTrace();
+ } */
+ }
+ }
+ }
+
+ /**
+ * Clones the remote repository to the local one. If basic authentication is required,
+ * will call 'RepositoryInformationService' for credentials.
+ *
+ * @param gitRepoCtx RepositoryContext for the tenant
+ */
+ private static void cloneRepository (RepositoryContext gitRepoCtx) { //should happen only at the beginning
+
+ File gitRepoDir = new File(gitRepoCtx.getGitLocalRepoPath());
+ if (gitRepoDir.exists()) {
+ if(isValidGitRepo(gitRepoCtx)) { //check if a this is a valid git repo
+ log.info("Existing git repository detected for tenant " + gitRepoCtx.getTenantId() + ", no clone required");
+ gitRepoCtx.setCloneExists(true);
+ return;
+ }
+ else {
+ if(log.isDebugEnabled())
+ log.debug("Repository for tenant " + gitRepoCtx.getTenantId() + " is not a valid git repo");
+ Utilities.deleteFolderStructure(gitRepoDir); //if not a valid git repo but non-empty, delete it (else the clone will not work)
+ }
+ }
+
+ CloneCommand cloneCmd = gitRepoCtx.getGit().cloneRepository().
+ setURI(gitRepoCtx.getGitRemoteRepoUrl()).
+ setDirectory(gitRepoDir);
+
+ if(!gitRepoCtx.getKeyBasedAuthentication()) {
+ UsernamePasswordCredentialsProvider credentialsProvider = createCredentialsProvider(gitRepoCtx);
+ if (credentialsProvider != null)
+ cloneCmd.setCredentialsProvider(credentialsProvider);
+ }
+
+ try {
+ cloneCmd.call();
+ log.info("Git clone operation for tenant " + gitRepoCtx.getTenantId() + " successful");
+ gitRepoCtx.setCloneExists(true);
+
+ } catch (TransportException e) {
+ log.error("Accessing remote git repository failed for tenant " + gitRepoCtx.getTenantId(), e);
+ e.printStackTrace();
+
+ } catch (GitAPIException e) {
+ log.error("Git clone operation for tenant " + gitRepoCtx.getTenantId() + " failed", e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Queries the RepositoryInformationService to obtain credentials for the tenant id + cartridge type
+ * and creates a UsernamePasswordCredentialsProvider from a valid username and a password
+ *
+ * @param gitRepoCtx RepositoryContext instance
+ *
+ * @return UsernamePasswordCredentialsProvider instance or null if service invocation failed or
+ * username/password is not valid
+ */
+ private static UsernamePasswordCredentialsProvider createCredentialsProvider (RepositoryContext gitRepoCtx) {
+
+ //RepositoryCredentials repoCredentials = null;
+ // TODO - set repo creds using the received message
+ //repoCredentials = new RepositoryCredentials();
+
+ /*try {
+ repoCredentials = gitRepoCtx.getRepoInfoServiceClient().
+ getJsonRepositoryInformation(gitRepoCtx.getTenantId(), cartridgeShortName);
+
+ } catch (Exception e) {
+ log.error("Git json repository information query failed", e);
+ return null;
+ }*/
+
+ /*if (repoCredentials != null) {
+ String userName = repoCredentials.getUserName();
+ String password = repoCredentials.getPassword();
+
+ log.info("Recieved repo url [" + repoCredentials.getUrl() + "] for tenant " + gitRepoCtx.getTenantId() +
+ ", username " + userName);
+
+ if (userName!= null && password != null) {
+ return new UsernamePasswordCredentialsProvider(userName, password);
+ }
+ }*/
+
+ return new UsernamePasswordCredentialsProvider(gitRepoCtx.getRepoUsername(), gitRepoCtx.getRepoPassword());
+ }
+
+ /**
+ * Checks if an existing local repository is a valid git repository
+ *
+ * @param gitRepoCtx RepositoryContext instance
+ *
+ * @return true if a valid git repo, else false
+ */
+ private static boolean isValidGitRepo (RepositoryContext gitRepoCtx) {
+
+ for (Ref ref : gitRepoCtx.getLocalRepo().getAllRefs().values()) { //check if has been previously cloned successfully, not empty
+ if (ref.getObjectId() == null)
+ continue;
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Calls a utility method to extract the username from a json string
+ *
+ * @param repoInfoJsonString json format string
+ *
+ * @return username if exists, else an empty String
+ */
+ private String getUserName (String repoInfoJsonString) {
+ return Utilities.getMatch(repoInfoJsonString,
+ GitDeploymentSynchronizerConstants.USERNAME_REGEX, 1);
+ }
+
+ /**
+ * Calls a utility method to extract the password from a json string
+ *
+ * @param repoInfoJsonString json format string
+ *
+ * @return password if exists, else an empty String
+ */
+ private String getPassword (String repoInfoJsonString) {
+ return Utilities.getMatch(repoInfoJsonString,
+ GitDeploymentSynchronizerConstants.PASSWORD_REGEX, 1);
+ }
+
+ /* public void initAutoCheckout(boolean b) throws Exception {
+
+ }*/
+
+ public void cleanupAutoCheckout() {
+
+ }
+
+ public String getRepositoryType() {
+
+ return /*DeploymentSynchronizerConstants.REPOSITORY_TYPE_GIT;*/null;
+ }
+
+ /* public List<RepositoryConfigParameter> getParameters() {
+
+ return null;
+ }*/
+
+ //public boolean update(String rootPath, String filePath, int depth) throws DeploymentSynchronizerException {
+
+ // TODO - implemetn later
+
+ /*RepositoryContext gitRepoCtx = retrieveCachedGitContext(filePath);
+ if(gitRepoCtx == null) {
+ if(log.isDebugEnabled())
+ log.debug("No git repository context information found for deployment synchonizer at " + filePath);
+
+ return false;
+ }
+ if(gitRepoCtx.getTenantId() == GitDeploymentSynchronizerConstants.SUPER_TENANT_ID)
+ return true; //Super Tenant is inactive
+ if(gitRepoCtx.cloneExists())
+ return pullArtifacts(gitRepoCtx);*/
+
+ /* return false;
+ }*/
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/CustomJschConfigSessionFactory.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/CustomJschConfigSessionFactory.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/CustomJschConfigSessionFactory.java
new file mode 100644
index 0000000..2594071
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/CustomJschConfigSessionFactory.java
@@ -0,0 +1,64 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.internal;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import org.eclipse.jgit.transport.JschConfigSessionFactory;
+import org.eclipse.jgit.transport.OpenSshConfig;
+import org.eclipse.jgit.util.FS;
+import org.wso2.carbon.base.ServerConfiguration;
+
+/**
+ * overrides the default org.eclipse.jgit.transport.JschConfigSessionFactory
+ */
+public class CustomJschConfigSessionFactory extends JschConfigSessionFactory {
+
+ @Override
+ protected void configure(OpenSshConfig.Host host, Session session) {
+ java.util.Properties config = new java.util.Properties();
+ config.put("StrictHostKeyChecking", "no");
+ session.setConfig(config);
+ }
+
+ @Override
+ protected JSch createDefaultJSch(FS fs) throws JSchException {
+
+ JSch def = super.createDefaultJSch(fs);
+ String keyName = ServerConfiguration.getInstance().
+ getFirstProperty(GitDeploymentSynchronizerConstants.SSH_PRIVATE_KEY_NAME);
+ String keyPath = ServerConfiguration.getInstance().
+ getFirstProperty(GitDeploymentSynchronizerConstants.SSH_PRIVATE_KEY_PATH);
+
+ if(keyName == null || keyName.isEmpty())
+ keyName = GitDeploymentSynchronizerConstants.SSH_KEY;
+
+ if(keyPath == null || keyPath.isEmpty())
+ keyPath = System.getProperty("user.home") + "/" + GitDeploymentSynchronizerConstants.SSH_KEY_DIRECTORY;
+
+ if(keyPath.endsWith("/"))
+ def.addIdentity(keyPath + keyName);
+ else
+ def.addIdentity(keyPath + "/" + keyName);
+
+ return def;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/GitDeploymentSynchronizerConstants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/GitDeploymentSynchronizerConstants.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/GitDeploymentSynchronizerConstants.java
new file mode 100644
index 0000000..19c104d
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/GitDeploymentSynchronizerConstants.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.internal;
+
+
+/**
+ * Git based DeploymentSynchronizer constansts
+ */
+public class GitDeploymentSynchronizerConstants {
+
+ //Git repo url related constansts
+ //public static final String GITHUB_HTTP_REPO_URL_PREFIX = "http://github.com";
+ public static final String GIT_HTTP_REPO_URL_PREFIX = "http://";
+ //public static final String GITHUB_HTTPS_REPO_URL_PREFIX = "https://github.com";
+ public static final String GIT_HTTPS_REPO_URL_PREFIX = "https://";
+ public static final String GITHUB_READ_ONLY_REPO_URL_PREFIX = "git://github.com";
+ public static final String GIT_REPO_SSH_URL_PREFIX = "ssh://";
+ public static final String GIT_REPO_SSH_URL_SUBSTRING = "@";
+
+ //SSH related constants
+ public static final String SSH_KEY_DIRECTORY = ".ssh";
+ public static final String SSH_KEY = "wso2";
+
+ //super tenant Id
+ public static final int SUPER_TENANT_ID = -1234;
+
+ //ServerKey property name from carbon.xml, for the cartridge short name --> not used. CARTRIDGE_ALIAS is used instead.
+ //public static final String SERVER_KEY = "ServerKey";
+
+ //EPR for the repository Information Service
+ public static final String REPO_INFO_SERVICE_EPR = "RepoInfoServiceEpr";
+
+ //CartridgeAlias property name from carbon.xml
+ public static final String CARTRIDGE_ALIAS = "CartridgeAlias";
+
+ //key name and path for ssh based authentication
+ public static final String SSH_PRIVATE_KEY_NAME = /*DEPLOYMENT_SYNCHRONIZER + */".SshPrivateKeyName";
+ public static final String SSH_PRIVATE_KEY_PATH = /*DEPLOYMENT_SYNCHRONIZER +*/ ".SshPrivateKeyPath";
+
+ //regular expressions for extracting username and password form json string
+ public static final String USERNAME_REGEX = "username:(.*?),";
+ public static final String PASSWORD_REGEX = "password:(.*?)}";
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/RepositoryContext.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/RepositoryContext.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/RepositoryContext.java
new file mode 100644
index 0000000..c769a4b
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/RepositoryContext.java
@@ -0,0 +1,131 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.internal;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.lib.Repository;
+
+import java.io.File;
+
+/**
+ * Git Repository Context class. Keeps track of git configurations per tenant.
+ */
+public class RepositoryContext {
+
+ private static final Log log = LogFactory.getLog(RepositoryContext.class);
+
+ private String gitRemoteRepoUrl;
+ private String gitLocalRepoPath;
+ private Repository localRepo;
+ private Git git;
+ private boolean cloneExists;
+ private int tenantId;
+ private File gitRepoDir;
+ private boolean keyBasedAuthentication;
+ private String repoUsername;
+ private String repoPassword;
+
+ public RepositoryContext () {
+
+ }
+
+ public String getGitRemoteRepoUrl() {
+ return gitRemoteRepoUrl;
+ }
+
+ public void setGitRemoteRepoUrl(String gitRemoteRepoUrl) {
+ this.gitRemoteRepoUrl = gitRemoteRepoUrl;
+ }
+
+ public String getGitLocalRepoPath() {
+ return gitLocalRepoPath;
+ }
+
+ public void setGitLocalRepoPath(String gitLocalRepoPath) {
+ this.gitLocalRepoPath = gitLocalRepoPath;
+ }
+
+ public Repository getLocalRepo() {
+ return localRepo;
+ }
+
+ public void setLocalRepo(Repository localRepo) {
+ this.localRepo = localRepo;
+ }
+
+ public Git getGit() {
+ return git;
+ }
+
+ public void setGit(Git git) {
+ this.git = git;
+ }
+
+ public boolean cloneExists() {
+ return cloneExists;
+ }
+
+ public void setCloneExists(boolean cloneExists) {
+ this.cloneExists = cloneExists;
+ }
+
+ public int getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(int tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public File getGitRepoDir() {
+ return gitRepoDir;
+ }
+
+ public void setGitRepoDir(File gitRepoDir) {
+ this.gitRepoDir = gitRepoDir;
+ }
+
+ public boolean getKeyBasedAuthentication() {
+ return keyBasedAuthentication;
+ }
+
+ public void setKeyBasedAuthentication(boolean keyBasedAuthentication) {
+ this.keyBasedAuthentication = keyBasedAuthentication;
+ }
+
+ public String getRepoUsername() {
+ return repoUsername;
+ }
+
+ public void setRepoUsername(String repoUsername) {
+ this.repoUsername = repoUsername;
+ }
+
+ public String getRepoPassword() {
+ return repoPassword;
+ }
+
+ public void setRepoPassword(String repoPassword) {
+ this.repoPassword = repoPassword;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/util/Utilities.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/util/Utilities.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/util/Utilities.java
new file mode 100644
index 0000000..a6c2f4b
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/util/Utilities.java
@@ -0,0 +1,73 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.util;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * String Utility methods
+ */
+public class Utilities {
+
+ private static final Log log = LogFactory.getLog(Utilities.class);
+
+ /**
+ * Searches for a match in a input String against a regex
+ *
+ * @param input input String
+ * @param regex regex to match
+ * @param group grouping,
+ *
+ * @return result of the match if found, else empty String
+ */
+ public static String getMatch (String input, String regex, int group) {
+
+ String whitespaceRemovedJsonString = input.replaceAll("\\s+","");
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(whitespaceRemovedJsonString);
+ if(!matcher.find())
+ return "";
+ else
+ return matcher.group(group).trim();
+ }
+
+ /**
+ * Deletes a folder structure recursively
+ *
+ * @param existingDir folder to delete
+ */
+ public static void deleteFolderStructure (File existingDir) {
+
+ try {
+ FileUtils.deleteDirectory(existingDir);
+
+ } catch (IOException e) {
+ log.error("Deletion of existing non-git repository structure failed");
+ e.printStackTrace();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/CartridgeAgentConfiguration.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/CartridgeAgentConfiguration.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/CartridgeAgentConfiguration.java
new file mode 100644
index 0000000..f5e9dc7
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/CartridgeAgentConfiguration.java
@@ -0,0 +1,163 @@
+package org.apache.stratos.cartridge.agent.config;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cartridge.agent.util.CartridgeAgentConstants;
+import org.apache.stratos.cartridge.agent.util.CartridgeAgentUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+/**
+ * Cartridge agent configuration.
+ */
+public class CartridgeAgentConfiguration {
+
+ private static final Log log = LogFactory.getLog(CartridgeAgentConfiguration.class);
+ private static volatile CartridgeAgentConfiguration instance;
+
+ private final String serviceName;
+ private final String clusterId;
+ private final String networkPartitionId;
+ private final String partitionId;
+ private final String memberId;
+ private final String cartridgeKey;
+ private final String appPath;
+ private final String repoUrl;
+ private final List<Integer> ports;
+ private CharSequence mbIp;
+ private Object mbPort;
+
+ private CartridgeAgentConfiguration() {
+ serviceName = readParameterValue(CartridgeAgentConstants.SERVICE_NAME);
+ clusterId = readParameterValue(CartridgeAgentConstants.CLUSTER_ID);
+ networkPartitionId = readParameterValue(CartridgeAgentConstants.NETWORK_PARTITION_ID);
+ partitionId = readParameterValue(CartridgeAgentConstants.PARTITION_ID);
+ memberId = readParameterValue(CartridgeAgentConstants.MEMBER_ID);
+ cartridgeKey = readParameterValue(CartridgeAgentConstants.CARTRIDGE_KEY);
+ appPath = readParameterValue(CartridgeAgentConstants.APP_PATH);
+ repoUrl = readParameterValue(CartridgeAgentConstants.REPO_URL);
+ ports = readPorts();
+
+ if(log.isInfoEnabled()) {
+ log.info("Cartridge agent configuration initialized");
+ }
+
+ if(log.isDebugEnabled()) {
+ log.debug(String.format("service-name: %s", serviceName));
+ log.debug(String.format("cluster-id: %s", clusterId));
+ log.debug(String.format("network-partition-id: %s", networkPartitionId));
+ log.debug(String.format("partition-id: %s", partitionId));
+ log.debug(String.format("member-id: %s", memberId));
+ log.debug(String.format("cartridge-key: %s", cartridgeKey));
+ log.debug(String.format("app-path: %s", appPath));
+ log.debug(String.format("repo-url: %s", repoUrl));
+ log.debug(String.format("ports: %s", ports.toString()));
+ }
+ }
+
+ /**
+ * Get cartridge agent configuration singleton instance.
+ *
+ * @return
+ */
+ public static synchronized CartridgeAgentConfiguration getInstance() {
+ if (instance == null) {
+ synchronized (CartridgeAgentConfiguration.class) {
+ if (instance == null) {
+ instance = new CartridgeAgentConfiguration();
+ }
+ }
+ }
+ return instance;
+ }
+
+ private String readParameterValue(String parameterName) {
+ try {
+ // read launch params
+ File file = new File(System.getProperty(CartridgeAgentConstants.PARAM_FILE_PATH));
+ if(!file.exists()) {
+ throw new RuntimeException(String.format("File not found: %s", CartridgeAgentConstants.PARAM_FILE_PATH));
+ }
+ Scanner scanner = new Scanner(file);
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine();
+ String[] params = line.split(",");
+ for (String string : params) {
+ String[] var = string.split("=");
+ if(parameterName.equals(var[0])){
+ return var[1];
+ }
+ }
+ }
+ scanner.close();
+ } catch (Exception e) {
+ throw new RuntimeException("Could not read launch parameter file", e);
+ }
+ return null;
+ }
+
+ private List<Integer> readPorts() {
+ List<Integer> ports = new ArrayList<Integer>();
+ String portsStr = readParameterValue(CartridgeAgentConstants.PORTS);
+ List<String> portsStrList = CartridgeAgentUtils.splitUsingTokenizer(portsStr, "|");
+ for(String portStr : portsStrList) {
+ ports.add(Integer.parseInt(portsStr));
+ }
+ return ports;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public String getClusterId() {
+ return clusterId;
+ }
+
+ public String getNetworkPartitionId() {
+ return networkPartitionId;
+ }
+
+ public String getPartitionId() {
+ return partitionId;
+ }
+
+ public String getMemberId() {
+ return memberId;
+ }
+
+ public String getCartridgeKey() {
+ return cartridgeKey;
+ }
+
+ public String getAppPath() {
+ return appPath;
+ }
+
+ public String getRepoUrl() {
+ return repoUrl;
+ }
+
+ public List<Integer> getPorts() {
+ return ports;
+ }
+
+ public CharSequence getMbIp() {
+ return mbIp;
+ }
+
+ public void setMbIp(CharSequence mbIp) {
+ this.mbIp = mbIp;
+ }
+
+ public Object getMbPort() {
+ return mbPort;
+ }
+
+ public void setMbPort(Object mbPort) {
+ this.mbPort = mbPort;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/configurator/JndiConfigurator.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/configurator/JndiConfigurator.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/configurator/JndiConfigurator.java
new file mode 100644
index 0000000..1b48743
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/configurator/JndiConfigurator.java
@@ -0,0 +1,105 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.config.configurator;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Jndi configurator to configure message broker related settings and generate jndi.properties file.
+ */
+public class JndiConfigurator {
+
+ private static boolean configured;
+
+ public static void configure() {
+ generateJndiPropertiesFile();
+ configured = true;
+ }
+
+ private static void generateJndiPropertiesFile() {
+ String mbIp = System.getProperty("mb.ip");
+ if(StringUtils.isBlank(mbIp)) {
+ throw new RuntimeException("System property not found: mb.ip");
+ }
+ String mbPort = System.getProperty("mb.port");
+ if(StringUtils.isBlank(mbPort)) {
+ throw new RuntimeException("System property not found: mb.port");
+ }
+ String templateFilePath = System.getProperty("jndi.properties.template.file.path");
+ if(StringUtils.isBlank(templateFilePath)) {
+ throw new RuntimeException("System property not found: jndi.properties.template.file.path");
+ }
+ String jndiFileDir = System.getProperty("jndi.properties.dir");
+ if(StringUtils.isBlank(jndiFileDir)) {
+ throw new RuntimeException("System property not found: jndi.properties.dir");
+ }
+ String jndiFilePath = null;
+ if(jndiFileDir.endsWith("/")) {
+ jndiFilePath = jndiFileDir + "jndi.properties";
+ }
+ else {
+ jndiFilePath = jndiFileDir = "/" + "jndi.properties";
+ }
+
+ File templateFile = new File(templateFilePath);
+ if (!templateFile.exists()) {
+ throw new RuntimeException(String.format("File not found: %s", templateFilePath));
+ }
+ try {
+ // Read template file
+ String content = readFileContent(templateFilePath);
+
+ // Update message broker configuration
+ content = content.replace("$mb_ip", mbIp);
+ content = content.replace("$mb_port", mbPort);
+
+ // Write jndi.properties file
+ writeFileContent(content, jndiFilePath);
+ } catch (Exception e) {
+ throw new RuntimeException("Could not write jndi.properties file", e);
+ }
+ }
+
+ private static String readFileContent(String templateFilePath) throws IOException {
+ FileInputStream inputStream = new FileInputStream(templateFilePath);
+ try {
+ return IOUtils.toString(inputStream);
+ } finally {
+ inputStream.close();
+ }
+ }
+
+ private static void writeFileContent(String content, String filePath) throws IOException {
+ FileOutputStream outputStream = new FileOutputStream(filePath);
+ IOUtils.write(content, outputStream);
+ }
+
+ public static boolean isConfigured() {
+ return configured;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/event/publisher/CartridgeAgentEventPublisher.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/event/publisher/CartridgeAgentEventPublisher.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/event/publisher/CartridgeAgentEventPublisher.java
new file mode 100644
index 0000000..97bf23b
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/event/publisher/CartridgeAgentEventPublisher.java
@@ -0,0 +1,52 @@
+package org.apache.stratos.cartridge.agent.event.publisher;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
+import org.apache.stratos.messaging.broker.publish.EventPublisher;
+import org.apache.stratos.messaging.event.instance.status.InstanceActivatedEvent;
+import org.apache.stratos.messaging.event.instance.status.InstanceStartedEvent;
+import org.apache.stratos.messaging.util.Constants;
+
+/**
+ * Cartridge agent event publisher.
+ */
+public class CartridgeAgentEventPublisher {
+ private static final Log log = LogFactory.getLog(CartridgeAgentEventPublisher.class);
+
+ public static void publishInstanceStartedEvent() {
+ if(log.isDebugEnabled()) {
+ log.debug("Publishing instance started event");
+ }
+ InstanceStartedEvent event = new InstanceStartedEvent(
+ CartridgeAgentConfiguration.getInstance().getServiceName(),
+ CartridgeAgentConfiguration.getInstance().getClusterId(),
+ CartridgeAgentConfiguration.getInstance().getNetworkPartitionId(),
+ CartridgeAgentConfiguration.getInstance().getPartitionId(),
+ CartridgeAgentConfiguration.getInstance().getMemberId());
+
+ EventPublisher eventPublisher = new EventPublisher(Constants.INSTANCE_STATUS_TOPIC);
+ eventPublisher.publish(event);
+ if(log.isDebugEnabled()) {
+ log.debug("Instance started event published");
+ }
+ }
+
+ public static void publishInstanceActivatedEvent() {
+ if(log.isDebugEnabled()) {
+ log.debug("Publishing instance activated event");
+ }
+ InstanceActivatedEvent event = new InstanceActivatedEvent(
+ CartridgeAgentConfiguration.getInstance().getServiceName(),
+ CartridgeAgentConfiguration.getInstance().getClusterId(),
+ CartridgeAgentConfiguration.getInstance().getNetworkPartitionId(),
+ CartridgeAgentConfiguration.getInstance().getPartitionId(),
+ CartridgeAgentConfiguration.getInstance().getMemberId());
+
+ EventPublisher eventPublisher = new EventPublisher(Constants.INSTANCE_STATUS_TOPIC);
+ eventPublisher.publish(event);
+ if(log.isDebugEnabled()) {
+ log.debug("Instance activated event published");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsNotifier.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsNotifier.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsNotifier.java
new file mode 100644
index 0000000..9412e28
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsNotifier.java
@@ -0,0 +1,113 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.statistics.publisher;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
+import org.apache.stratos.cartridge.agent.util.CartridgeAgentConstants;
+import org.apache.stratos.cartridge.agent.util.CartridgeAgentUtils;
+
+/**
+ * Health statistics notifier thread for publishing statistics periodically to CEP.
+ */
+public class HealthStatisticsNotifier implements Runnable {
+ private static final Log log = LogFactory.getLog(HealthStatisticsNotifier.class);
+
+ private final HealthStatisticsPublisher statsPublisher;
+ private long statsPublisherInterval = 15000;
+ private boolean terminated;
+
+ public HealthStatisticsNotifier() {
+ this.statsPublisher = new HealthStatisticsPublisher();
+
+ String interval = System.getProperty("stats.notifier.interval");
+ if (interval != null) {
+ statsPublisherInterval = Long.getLong(interval);
+ }
+ }
+
+ @Override
+ public void run() {
+ while (!terminated) {
+ try {
+ try {
+ Thread.sleep(statsPublisherInterval);
+ } catch (InterruptedException ignore) {
+ }
+
+ if (statsPublisher.isEnabled()) {
+ if(!CartridgeAgentUtils.checkPortsActive()) {
+ if(log.isInfoEnabled()) {
+ log.info("Publishing ports not open event");
+ }
+ statsPublisher.publish(
+ CartridgeAgentConfiguration.getInstance().getClusterId(),
+ CartridgeAgentConfiguration.getInstance().getNetworkPartitionId(),
+ CartridgeAgentConfiguration.getInstance().getMemberId(),
+ CartridgeAgentConfiguration.getInstance().getPartitionId(),
+ CartridgeAgentConstants.PORTS_NOT_OPEN,
+ "1"
+ );
+ }
+
+ String memoryConsumption = String.valueOf(HealthStatisticsReader.getMemoryConsumption());
+ if(log.isInfoEnabled()) {
+ log.info(String.format("Publishing memory consumption: %s", memoryConsumption));
+ }
+ statsPublisher.publish(
+ CartridgeAgentConfiguration.getInstance().getClusterId(),
+ CartridgeAgentConfiguration.getInstance().getNetworkPartitionId(),
+ CartridgeAgentConfiguration.getInstance().getMemberId(),
+ CartridgeAgentConfiguration.getInstance().getPartitionId(),
+ CartridgeAgentConstants.MEMORY_CONSUMPTION,
+ memoryConsumption
+ );
+
+ String loadAverage = String.valueOf(HealthStatisticsReader.getLoadAverage());
+ if(log.isInfoEnabled()) {
+ log.info(String.format("Publishing load average: %s", loadAverage));
+ }
+ statsPublisher.publish(
+ CartridgeAgentConfiguration.getInstance().getClusterId(),
+ CartridgeAgentConfiguration.getInstance().getNetworkPartitionId(),
+ CartridgeAgentConfiguration.getInstance().getMemberId(),
+ CartridgeAgentConfiguration.getInstance().getPartitionId(),
+ CartridgeAgentConstants.LOAD_AVERAGE,
+ loadAverage
+ );
+ } else if (log.isWarnEnabled()) {
+ log.warn("Statistics publisher is disabled");
+ }
+ } catch (Exception e) {
+ if (log.isErrorEnabled()) {
+ log.error("Could not publish health statistics", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Terminate load balancer statistics notifier thread.
+ */
+ public void terminate() {
+ terminated = true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsPublisher.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsPublisher.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsPublisher.java
new file mode 100644
index 0000000..1c23cb9
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsPublisher.java
@@ -0,0 +1,90 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.statistics.publisher;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.common.statistics.publisher.WSO2CEPStatisticsPublisher;
+import org.wso2.carbon.databridge.commons.Attribute;
+import org.wso2.carbon.databridge.commons.AttributeType;
+import org.wso2.carbon.databridge.commons.StreamDefinition;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Health statistics publisher for publishing statistics to CEP.
+ */
+public class HealthStatisticsPublisher extends WSO2CEPStatisticsPublisher {
+ private static final Log log = LogFactory.getLog(HealthStatisticsPublisher.class);
+
+ private static final String DATA_STREAM_NAME = "cartridge_agent_health_stats";
+ private static final String VERSION = "1.0.0";
+
+ private static StreamDefinition createStreamDefinition() {
+ try {
+ StreamDefinition streamDefinition = new StreamDefinition(DATA_STREAM_NAME, VERSION);
+ streamDefinition.setNickName("agent health stats");
+ streamDefinition.setDescription("agent health stats");
+ List<Attribute> payloadData = new ArrayList<Attribute>();
+
+ payloadData.add(new Attribute("cluster_id", AttributeType.STRING));
+ payloadData.add(new Attribute("network_partition_id", AttributeType.STRING));
+ payloadData.add(new Attribute("member_id", AttributeType.STRING));
+ payloadData.add(new Attribute("partition_id", AttributeType.STRING));
+ payloadData.add(new Attribute("health_description", AttributeType.STRING));
+ payloadData.add(new Attribute("value", AttributeType.STRING));
+
+ streamDefinition.setPayloadData(payloadData);
+ return streamDefinition;
+ } catch (Exception e) {
+ throw new RuntimeException("Could not create stream definition", e);
+ }
+ }
+
+ public HealthStatisticsPublisher() {
+ super(createStreamDefinition());
+ }
+
+ /**
+ * Publish health statistics to cep.
+ * @param clusterId
+ * @param networkPartitionId
+ * @param memberId
+ * @param partitionId
+ * @param health
+ * @param value
+ */
+ public void publish(String clusterId, String networkPartitionId, String memberId, String partitionId, String health, String value) {
+ if(log.isInfoEnabled()) {
+ log.info(String.format("Publishing health statistics: [cluster] %s [network-partition] %s [partition] %s [member] %s [health] %s [value] %s",
+ clusterId, networkPartitionId, partitionId, memberId, health, value));
+ }
+ List<Object> payload = new ArrayList<Object>();
+ // Payload values
+ payload.add(clusterId);
+ payload.add(networkPartitionId);
+ payload.add(memberId);
+ payload.add(partitionId);
+ payload.add(health);
+ payload.add(value);
+ super.publish(payload.toArray());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/c8985d58/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsReader.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsReader.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsReader.java
new file mode 100644
index 0000000..1b186be
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/statistics/publisher/HealthStatisticsReader.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.apache.stratos.cartridge.agent.statistics.publisher;
+
+import org.apache.stratos.cartridge.agent.util.CartridgeAgentUtils;
+
+import java.lang.management.ManagementFactory;
+
+/**
+ * Health statistics reader.
+ */
+public class HealthStatisticsReader {
+ private static final int MB = 1024 * 1024;
+
+ public static double getMemoryConsumption() {
+ Runtime runtime = Runtime.getRuntime();
+ double totalMemory = (double)(runtime.totalMemory() / MB);
+ double usedMemory = (double)((totalMemory - (runtime.freeMemory() / MB) ));
+ double memoryConsumption = (usedMemory / totalMemory) * 100;
+ return memoryConsumption;
+ }
+
+ public static double getLoadAverage() {
+ return (double)ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
+ }
+
+ public static boolean allPortsActive() {
+ return CartridgeAgentUtils.checkPortsActive();
+ }
+}
\ No newline at end of file