Repository: incubator-brooklyn Updated Branches: refs/heads/master 6de3afc5d -> 4243d5311
brooklyn-software-osgi: add org.apache package prefix Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/8601629a Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/8601629a Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/8601629a Branch: refs/heads/master Commit: 8601629a4f524dd2780663b96b6bc775c78a028a Parents: d85719b Author: Ciprian Ciubotariu <[email protected]> Authored: Wed Aug 12 11:07:50 2015 +0300 Committer: Ciprian Ciubotariu <[email protected]> Committed: Wed Aug 12 11:08:38 2015 +0300 ---------------------------------------------------------------------- .../entity/osgi/karaf/KarafContainer.java | 137 --------- .../entity/osgi/karaf/KarafContainerImpl.java | 298 ------------------- .../brooklyn/entity/osgi/karaf/KarafDriver.java | 30 -- .../entity/osgi/karaf/KarafSshDriver.java | 149 ---------- .../entity/osgi/karaf/KarafContainer.java | 137 +++++++++ .../entity/osgi/karaf/KarafContainerImpl.java | 298 +++++++++++++++++++ .../brooklyn/entity/osgi/karaf/KarafDriver.java | 30 ++ .../entity/osgi/karaf/KarafSshDriver.java | 149 ++++++++++ .../osgi/karaf/KarafContainerEc2LiveTest.java | 53 ---- .../entity/osgi/karaf/KarafContainerTest.java | 147 --------- .../osgi/karaf/KarafContainerEc2LiveTest.java | 53 ++++ .../entity/osgi/karaf/KarafContainerTest.java | 147 +++++++++ 12 files changed, 814 insertions(+), 814 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafContainer.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafContainer.java b/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafContainer.java deleted file mode 100644 index 7a0edb6..0000000 --- a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafContainer.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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.osgi.karaf; - -import java.net.URISyntaxException; -import java.util.Map; - -import org.apache.brooklyn.catalog.Catalog; -import brooklyn.config.ConfigKey; -import brooklyn.entity.annotation.Effector; -import brooklyn.entity.annotation.EffectorParam; -import brooklyn.entity.basic.ConfigKeys; -import brooklyn.entity.basic.MethodEffector; -import brooklyn.entity.basic.SoftwareProcess; -import brooklyn.entity.java.UsesJava; -import brooklyn.entity.java.UsesJmx; -import brooklyn.entity.proxying.ImplementedBy; -import brooklyn.event.basic.BasicAttributeSensor; -import brooklyn.event.basic.BasicAttributeSensorAndConfigKey; -import brooklyn.event.basic.MapConfigKey; -import brooklyn.event.basic.PortAttributeSensorAndConfigKey; -import brooklyn.util.flags.SetFromFlag; - -/** - * This sets up a Karaf OSGi container - */ -@Catalog(name="Karaf", description="Apache Karaf is a small OSGi based runtime which provides a lightweight container onto which various components and applications can be deployed.", iconUrl="classpath:///karaf-logo.png") -@ImplementedBy(KarafContainerImpl.class) -public interface KarafContainer extends SoftwareProcess, UsesJava, UsesJmx { - - // TODO Better way of setting/overriding defaults for config keys that are defined in super class SoftwareProcess - - public static final String WRAP_SCHEME = "wrap"; - public static final String FILE_SCHEME = "file"; - public static final String MVN_SCHEME = "mvn"; - public static final String HTTP_SCHEME = "http"; - - public static final MethodEffector<Map<Long,Map<String,?>>> LIST_BUNDLES = new MethodEffector(KarafContainer.class, "listBundles"); - public static final MethodEffector<Long> INSTALL_BUNDLE = new MethodEffector<Long>(KarafContainer.class, "installBundle"); - public static final MethodEffector<Void> UNINSTALL_BUNDLE = new MethodEffector<Void>(KarafContainer.class, "uninstallBundle"); - public static final MethodEffector<Void> INSTALL_FEATURE = new MethodEffector<Void>(KarafContainer.class, "installFeature"); - public static final MethodEffector<Void> UPDATE_SERVICE_PROPERTIES = new MethodEffector<Void>(KarafContainer.class, "updateServiceProperties"); - - @SetFromFlag("version") - public static final ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault( - SoftwareProcess.SUGGESTED_VERSION, "2.3.0"); - - @SetFromFlag("downloadUrl") - public static final BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new BasicAttributeSensorAndConfigKey<String>( - SoftwareProcess.DOWNLOAD_URL, "http://apache.mirror.anlx.net/karaf/${version}/apache-karaf-${version}.tar.gz"); - - @SetFromFlag("karafName") - public static final BasicAttributeSensorAndConfigKey<String> KARAF_NAME = new BasicAttributeSensorAndConfigKey<String>( - String.class, "karaf.name", "Karaf instance name", "root"); - - // TODO too complicated? Used by KarafContainer; was in JavaApp; where should it be in brave new world? - public static final MapConfigKey<Map<String,String>> NAMED_PROPERTY_FILES = new MapConfigKey( - Map.class, "karaf.runtime.files", "Property files to be generated, referenced by name relative to runDir"); - - @SetFromFlag("jmxUser") - public static final BasicAttributeSensorAndConfigKey<String> JMX_USER = new BasicAttributeSensorAndConfigKey<String>( - UsesJmx.JMX_USER, "karaf"); - - @SetFromFlag("jmxPassword") - public static final BasicAttributeSensorAndConfigKey<String> JMX_PASSWORD = new BasicAttributeSensorAndConfigKey<String>( - UsesJmx.JMX_PASSWORD, "karaf"); - - @SetFromFlag("jmxPort") - public static final PortAttributeSensorAndConfigKey JMX_PORT = new PortAttributeSensorAndConfigKey( - UsesJmx.JMX_PORT, "44444+"); - - @SetFromFlag("rmiRegistryPort") - public static final PortAttributeSensorAndConfigKey RMI_REGISTRY_PORT = UsesJmx.RMI_REGISTRY_PORT; - - @SetFromFlag("jmxContext") - public static final BasicAttributeSensorAndConfigKey<String> JMX_CONTEXT = new BasicAttributeSensorAndConfigKey<String>( - UsesJmx.JMX_CONTEXT, "karaf-"+KARAF_NAME.getConfigKey().getDefaultValue()); - - public static final BasicAttributeSensor<Map> KARAF_INSTANCES = new BasicAttributeSensor<Map>( - Map.class, "karaf.admin.instances", "Karaf admin instances"); - public static final BasicAttributeSensor<Boolean> KARAF_ROOT = new BasicAttributeSensor<Boolean>( - Boolean.class, "karaf.admin.isRoot", "Karaf admin isRoot"); - public static final BasicAttributeSensor<String> KARAF_JAVA_OPTS = new BasicAttributeSensor<String>( - String.class, "karaf.admin.java_opts", "Karaf Java opts"); - public static final BasicAttributeSensor<String> KARAF_INSTALL_LOCATION = new BasicAttributeSensor<String>( - String.class, "karaf.admin.location", "Karaf install location"); - public static final BasicAttributeSensor<Integer> KARAF_PID = new BasicAttributeSensor<Integer>( - Integer.class, "karaf.admin.pid", "Karaf instance PID"); - public static final BasicAttributeSensor<Integer> KARAF_SSH_PORT = new BasicAttributeSensor<Integer>( - Integer.class, "karaf.admin.ssh_port", "Karaf SSH Port"); - public static final BasicAttributeSensor<Integer> KARAF_RMI_REGISTRY_PORT = new BasicAttributeSensor<Integer>( - Integer.class, "karaf.admin.rmi_registry_port", "Karaf instance RMI registry port"); - public static final BasicAttributeSensor<Integer> KARAF_RMI_SERVER_PORT = new BasicAttributeSensor<Integer>( - Integer.class, "karaf.admin.rmi_server_port", "Karaf RMI (JMX) server port"); - public static final BasicAttributeSensor<String> KARAF_STATE = new BasicAttributeSensor<String>( - String.class, "karaf.admin.state", "Karaf instance state"); - - @Effector(description="Updates the OSGi Service's properties, adding (and overriding) the given key-value pairs") - public void updateServiceProperties( - @EffectorParam(name="serviceName", description="Name of the OSGi service") String serviceName, - Map<String,String> additionalVals); - - @Effector(description="Installs the given OSGi feature") - public void installFeature( - @EffectorParam(name="featureName", description="Name of the feature - see org.apache.karaf:type=features#installFeature()") final String featureName) - throws Exception; - - @Effector(description="Lists all the karaf bundles") - public Map<Long,Map<String,?>> listBundles(); - - /** - * throws URISyntaxException If bundle name is not a valid URI - */ - @Effector(description="Deploys the given bundle, returning the bundle id - see osgi.core:type=framework#installBundle()") - public long installBundle( - @EffectorParam(name="bundle", description="URI of bundle to be deployed") String bundle) throws URISyntaxException; - - @Effector(description="Undeploys the bundle with the given id") - public void uninstallBundle( - @EffectorParam(name="bundleId", description="Id of the bundle") Long bundleId); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafContainerImpl.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafContainerImpl.java b/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafContainerImpl.java deleted file mode 100644 index b73fd7f..0000000 --- a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafContainerImpl.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * 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.osgi.karaf; - -import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; - -import javax.management.ObjectName; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.TabularData; - -import org.osgi.jmx.JmxConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.entity.annotation.Effector; -import brooklyn.entity.annotation.EffectorParam; -import brooklyn.entity.basic.SoftwareProcessImpl; -import brooklyn.entity.java.JmxSupport; -import brooklyn.event.SensorEvent; -import brooklyn.event.SensorEventListener; -import brooklyn.event.feed.ConfigToAttributes; -import brooklyn.event.feed.jmx.JmxAttributePollConfig; -import brooklyn.event.feed.jmx.JmxFeed; -import brooklyn.event.feed.jmx.JmxHelper; -import brooklyn.event.feed.jmx.JmxValueFunctions; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.exceptions.Exceptions; -import brooklyn.util.os.Os; -import brooklyn.util.repeat.Repeater; - -import com.google.common.base.Function; -import com.google.common.collect.Maps; - -/** - * This sets up a Karaf OSGi container - */ -public class KarafContainerImpl extends SoftwareProcessImpl implements KarafContainer { - - // TODO Better way of setting/overriding defaults for config keys that are defined in super class SoftwareProcess - - private static final Logger LOG = LoggerFactory.getLogger(KarafContainerImpl.class); - - public static final String KARAF_ADMIN = "org.apache.karaf:type=admin,name=%s"; - public static final String KARAF_FEATURES = "org.apache.karaf:type=features,name=%s"; - - public static final String OSGI_BUNDLE_STATE = "osgi.core:type=bundleState,version=1.5"; - public static final String OSGI_FRAMEWORK = "osgi.core:type=framework,version=1.5"; - public static final String OSGI_COMPENDIUM = "osgi.compendium:service=cm,version=1.3"; - - protected JmxHelper jmxHelper; - - private JmxFeed jmxFeed; - - public KarafContainerImpl() { - super(); - } - - @Override - public Class<KarafDriver> getDriverInterface() { - return KarafDriver.class; - } - - @Override - public KarafDriver getDriver() { - return (KarafDriver) super.getDriver(); - } - - @Override - public void init() { - super.init(); - new JmxSupport(this, null).recommendJmxRmiCustomAgent(); - } - - @Override - protected void postDriverStart() { - super.postDriverStart(); - uploadPropertyFiles(getConfig(NAMED_PROPERTY_FILES)); - - jmxHelper = new JmxHelper(this); - jmxHelper.connect(0); // i.e. don't block - } - - @Override - protected void connectSensors() { - super.connectSensors(); - - //FIXME should have a better way of setting config -- firstly, not here! - //preferred style is to have config auto-applied to attributes, and have default values in their definition, not here - //use of "properties.{user,password}" is non-standard; is that requried? use default jmxUser, jmxPassword flags? - setAttribute(JMX_CONTEXT, String.format("karaf-%s", getConfig(KARAF_NAME.getConfigKey()))); - - ConfigToAttributes.apply(this); - - ObjectName karafAdminObjectName = JmxHelper.createObjectName(String.format(KARAF_ADMIN, getConfig(KARAF_NAME.getConfigKey()))); - - jmxFeed = JmxFeed.builder() - .entity(this) - .helper(jmxHelper) - .period(500, TimeUnit.MILLISECONDS) - .pollAttribute(new JmxAttributePollConfig<Map>(KARAF_INSTANCES) - .objectName(karafAdminObjectName) - .attributeName("Instances") - .onSuccess(new Function<Object, Map>() { - @Override - public Map apply(Object input) { - return JmxValueFunctions.tabularDataToMap((TabularData)input); - } - }) - .onException(new Function<Exception,Map>() { - @Override public Map apply(Exception input) { - // If MBean is unreachable, then mark as service-down - if (Boolean.TRUE.equals(getAttribute(SERVICE_UP))) { - LOG.debug("Entity "+this+" is not reachable on JMX"); - setAttribute(SERVICE_UP, false); - } - return null; - }})) - .build(); - - - - // INSTANCES aggregates data for the other sensors. - subscribe(this, KARAF_INSTANCES, new SensorEventListener<Map>() { - @Override public void onEvent(SensorEvent<Map> event) { - Map map = event.getValue(); - if (map == null) return; - - setAttribute(SERVICE_UP, "Started".equals(map.get("State"))); - setAttribute(KARAF_ROOT, (Boolean) map.get("Is Root")); - setAttribute(KARAF_JAVA_OPTS, (String) map.get("JavaOpts")); - setAttribute(KARAF_INSTALL_LOCATION, (String) map.get("Location")); - setAttribute(KARAF_NAME, (String) map.get("Name")); - setAttribute(KARAF_PID, (Integer) map.get("Pid")); - setAttribute(KARAF_SSH_PORT, (Integer) map.get("Ssh Port")); - setAttribute(KARAF_RMI_REGISTRY_PORT, (Integer) map.get("RMI Registry Port")); - setAttribute(KARAF_RMI_SERVER_PORT, (Integer) map.get("RMI Server Port")); - setAttribute(KARAF_STATE, (String) map.get("State")); - }}); - - } - - @Override - protected void disconnectSensors() { - super.disconnectSensors(); - if (jmxFeed != null) jmxFeed.stop(); - } - - @Override - protected void preStop() { - super.preStop(); - - if (jmxHelper != null) jmxHelper.terminate(); - } - - @Effector(description="Updates the OSGi Service's properties, adding (and overriding) the given key-value pairs") - public void updateServiceProperties( - @EffectorParam(name="serviceName", description="Name of the OSGi service") String serviceName, - Map<String,String> additionalVals) { - TabularData table = (TabularData) jmxHelper.operation(OSGI_COMPENDIUM, "getProperties", serviceName); - - try { - for (Map.Entry<String, String> entry: additionalVals.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - CompositeData data = new CompositeDataSupport( - JmxConstants.PROPERTY_TYPE, - MutableMap.of(JmxConstants.KEY, key, JmxConstants.TYPE, "String", JmxConstants.VALUE, value)); - table.remove(data.getAll(new String[] {JmxConstants.KEY})); - table.put(data); - } - } catch (OpenDataException e) { - throw Exceptions.propagate(e); - } - - LOG.info("Updating monterey-service configuration with changes {}", additionalVals); - if (LOG.isTraceEnabled()) LOG.trace("Updating monterey-service configuration with new configuration {}", table); - - jmxHelper.operation(OSGI_COMPENDIUM, "update", serviceName, table); - } - - @Effector(description="Updates the OSGi Service's properties, adding (and overriding) the given key-value pairs") - public void installFeature( - @EffectorParam(name="featureName", description="Name of the feature - see org.apache.karaf:type=features#installFeature()") final String featureName) throws Exception { - - LOG.info("Installing feature {} via JMX", featureName); - - Repeater.create("Wait for Karaf, to install feature "+featureName) - .limitIterationsTo(40) - .every(500, TimeUnit.MILLISECONDS) - .until(new Callable<Boolean>() { - public Boolean call() { - jmxHelper.operation(String.format(KARAF_FEATURES, getConfig(KARAF_NAME.getConfigKey())), "installFeature", featureName); - return true; - }}) - .rethrowException() - .run(); - } - - public Map<Long,Map<String,?>> listBundles() { - TabularData table = (TabularData) jmxHelper.operation(OSGI_BUNDLE_STATE, "listBundles"); - Map<List<?>, Map<String, Object>> map = JmxValueFunctions.tabularDataToMapOfMaps(table); - - Map<Long,Map<String,?>> result = Maps.newLinkedHashMap(); - for (Map.Entry<List<?>, Map<String, Object>> entry : map.entrySet()) { - result.put((Long)entry.getKey().get(0), entry.getValue()); - } - return result; - } - - /** - * throws URISyntaxException If bundle name is not a valid URI - */ - @Effector(description="Deploys the given bundle, returning the bundle id - see osgi.core:type=framework#installBundle()") - public long installBundle( - @EffectorParam(name="bundle", description="URI of bundle to be deployed") String bundle) throws URISyntaxException { - - // TODO Consider switching to use either: - // - org.apache.karaf:type=bundles#install(String), or - // - dropping file into $RUN_DIR/deploy (but that would be async) - - URI uri = new URI(bundle); - boolean wrap = false; - if (WRAP_SCHEME.equals(uri.getScheme())) { - bundle = bundle.substring(WRAP_SCHEME.length() + 1); - uri = new URI(bundle); - wrap = true; - } - if (FILE_SCHEME.equals(uri.getScheme())) { - LOG.info("Deploying bundle {} via file copy", bundle); - File source = new File(uri); - String target = getDriver().getRunDir() + "/" + source.getName(); - getDriver().copyResource(source, target); - return (Long) jmxHelper.operation(OSGI_FRAMEWORK, "installBundle", (wrap ? WRAP_SCHEME + ":" : "") + FILE_SCHEME + "://" + target); - } else { - LOG.info("Deploying bundle {} via JMX", bundle); - return (Long) jmxHelper.operation(OSGI_FRAMEWORK, "installBundle", (wrap ? WRAP_SCHEME + ":" : "") + bundle); - } - } - - @Effector(description="Undeploys the bundle with the given id") - public void uninstallBundle( - @EffectorParam(name="bundleId", description="Id of the bundle") Long bundleId) { - - // TODO Consider switching to use either: - // - org.apache.karaf:type=bundles#install(String), or - // - dropping file into $RUN_DIR/deploy (but that would be async) - - jmxHelper.operation(OSGI_FRAMEWORK, "uninstallBundle", bundleId); - } - - protected void uploadPropertyFiles(Map<String,Map<String,String>> propertyFiles) { - if (propertyFiles == null) return; - - for (Map.Entry<String,Map<String,String>> entry : propertyFiles.entrySet()) { - String file = entry.getKey(); - Map<String,String> contents = entry.getValue(); - - Properties props = new Properties(); - for (Map.Entry<String,String> prop : contents.entrySet()) { - props.setProperty(prop.getKey(), prop.getValue()); - } - - File local = Os.writePropertiesToTempFile(props, "karaf-"+getId(), ".cfg"); - local.setReadable(true); - try { - String remote = getDriver().getRunDir() + "/" + file; - getDriver().copyResource(local, remote); - } finally { - local.delete(); - } - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafDriver.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafDriver.java b/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafDriver.java deleted file mode 100644 index a3144fd..0000000 --- a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafDriver.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.osgi.karaf; - -import java.io.File; - -import brooklyn.entity.java.JavaSoftwareProcessDriver; - -public interface KarafDriver extends JavaSoftwareProcessDriver { - - public String getRunDir(); - - public int copyResource(File src, String destination); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafSshDriver.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafSshDriver.java b/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafSshDriver.java deleted file mode 100644 index 0e529d9..0000000 --- a/software/osgi/src/main/java/brooklyn/entity/osgi/karaf/KarafSshDriver.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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.osgi.karaf; - -import static java.lang.String.format; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import brooklyn.entity.basic.Entities; -import brooklyn.entity.java.JavaSoftwareProcessSshDriver; -import brooklyn.location.basic.SshMachineLocation; -import brooklyn.util.collections.MutableList; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.net.Networking; -import brooklyn.util.os.Os; -import brooklyn.util.ssh.BashCommands; - -import com.google.common.collect.ImmutableList; - -public class KarafSshDriver extends JavaSoftwareProcessSshDriver implements KarafDriver { - - // TODO getJmxJavaSystemProperties(), don't set via JAVA_OPTS; set ourselves manually - // (karaf reads from props files) - // but do set "java.rmi.server.hostname" - - public KarafSshDriver(KarafContainerImpl entity, SshMachineLocation machine) { - super(entity, machine); - } - - @Override - public KarafContainerImpl getEntity() { - return (KarafContainerImpl) super.getEntity(); - } - - @Override - protected String getLogFileLocation() { - return Os.mergePaths(getRunDir(), "data", "karaf.out"); - } - - @Override - public void preInstall() { - resolver = Entities.newDownloader(this); - setExpandedInstallDir(Os.mergePaths(getInstallDir(), resolver.getUnpackedDirectoryName(format("apache-karaf-%s", getVersion())))); - } - - @Override - public void install() { - List<String> urls = resolver.getTargets(); - String saveAs = resolver.getFilename(); - - List<String> commands = ImmutableList.<String>builder() - .addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs)) - .add(BashCommands.INSTALL_TAR) - .add("tar xzfv " + saveAs) - .build(); - - newScript(INSTALLING) - .body.append(commands) - .execute(); - } - - @Override - public void customize() { - Map<String, Object> ports = new HashMap<String, Object>(); - ports.put("jmxPort", getJmxPort()); - ports.put("rmiRegistryPort", getRmiRegistryPort()); - Networking.checkPortsValid(ports); - - newScript(CUSTOMIZING) - .body.append( - format("cd %s", getRunDir()), - format("cp -R %s/{bin,etc,lib,system,deploy} . || exit $!", getExpandedInstallDir()), - format("sed -i.bk 's/rmiRegistryPort = 1099/rmiRegistryPort = %s/g' etc/org.apache.karaf.management.cfg", getRmiRegistryPort()), - format("sed -i.bk 's/rmiServerPort = 44444/rmiServerPort = %s/g' etc/org.apache.karaf.management.cfg", getJmxPort()) - ) - .execute(); - } - - @Override - public void launch() { - newScript(MutableMap.of(USE_PID_FILE, true), LAUNCHING) - .body.append("nohup ./bin/start") - .execute(); - } - - @Override - public boolean isRunning() { - // TODO Can we use the pidFile, auto-generated by launch? - - Integer pid = entity.getAttribute(KarafContainer.KARAF_PID); - // This method is called on startup, before JMX is initialised, so pid won't always be available. - if (pid != null) { - return newScript(CHECK_RUNNING) - .body.append(format("ps aux | grep 'karaf' | grep %s > /dev/null", pid)) - .execute() == 0; - } else { - // Simple method isn't available, use pid in instance.properties. - return newScript(CHECK_RUNNING) - .body.append( - format("cd %s/instances/",getRunDir()), - "[ $(uname) = \"Darwin\" ] && pid=$(sed -n -e 's/.*pid=\\([0-9]*\\)$/\\1/p' instance.properties) || pid=$(sed -r -n -e 's/.*pid=([0-9]*)$/\\1/p' instance.properties)", - "ps aux | grep 'karaf' | grep $(echo ${pid:-X}) > /dev/null" - ) - .execute() == 0; - } - } - - @Override - public void stop() { - newScript(STOPPING) - .environmentVariablesReset() - .body.append(format("%s/bin/stop",getRunDir())) - .execute(); - } - - @Override - public void kill() { - stop(); // TODO no pid file to easily do `kill -9` - } - - @Override - protected List<String> getCustomJavaConfigOptions() { - return MutableList.<String>builder() - .addAll(super.getCustomJavaConfigOptions()) - .add("-Xms200m") - .add("-Xmx800m") - .add("-XX:MaxPermSize=400m") - .build(); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainer.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainer.java b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainer.java new file mode 100644 index 0000000..8aa2ef5 --- /dev/null +++ b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainer.java @@ -0,0 +1,137 @@ +/* + * 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.brooklyn.entity.osgi.karaf; + +import java.net.URISyntaxException; +import java.util.Map; + +import org.apache.brooklyn.catalog.Catalog; +import brooklyn.config.ConfigKey; +import brooklyn.entity.annotation.Effector; +import brooklyn.entity.annotation.EffectorParam; +import brooklyn.entity.basic.ConfigKeys; +import brooklyn.entity.basic.MethodEffector; +import brooklyn.entity.basic.SoftwareProcess; +import brooklyn.entity.java.UsesJava; +import brooklyn.entity.java.UsesJmx; +import brooklyn.entity.proxying.ImplementedBy; +import brooklyn.event.basic.BasicAttributeSensor; +import brooklyn.event.basic.BasicAttributeSensorAndConfigKey; +import brooklyn.event.basic.MapConfigKey; +import brooklyn.event.basic.PortAttributeSensorAndConfigKey; +import brooklyn.util.flags.SetFromFlag; + +/** + * This sets up a Karaf OSGi container + */ +@Catalog(name="Karaf", description="Apache Karaf is a small OSGi based runtime which provides a lightweight container onto which various components and applications can be deployed.", iconUrl="classpath:///karaf-logo.png") +@ImplementedBy(KarafContainerImpl.class) +public interface KarafContainer extends SoftwareProcess, UsesJava, UsesJmx { + + // TODO Better way of setting/overriding defaults for config keys that are defined in super class SoftwareProcess + + public static final String WRAP_SCHEME = "wrap"; + public static final String FILE_SCHEME = "file"; + public static final String MVN_SCHEME = "mvn"; + public static final String HTTP_SCHEME = "http"; + + public static final MethodEffector<Map<Long,Map<String,?>>> LIST_BUNDLES = new MethodEffector(KarafContainer.class, "listBundles"); + public static final MethodEffector<Long> INSTALL_BUNDLE = new MethodEffector<Long>(KarafContainer.class, "installBundle"); + public static final MethodEffector<Void> UNINSTALL_BUNDLE = new MethodEffector<Void>(KarafContainer.class, "uninstallBundle"); + public static final MethodEffector<Void> INSTALL_FEATURE = new MethodEffector<Void>(KarafContainer.class, "installFeature"); + public static final MethodEffector<Void> UPDATE_SERVICE_PROPERTIES = new MethodEffector<Void>(KarafContainer.class, "updateServiceProperties"); + + @SetFromFlag("version") + public static final ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault( + SoftwareProcess.SUGGESTED_VERSION, "2.3.0"); + + @SetFromFlag("downloadUrl") + public static final BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new BasicAttributeSensorAndConfigKey<String>( + SoftwareProcess.DOWNLOAD_URL, "http://apache.mirror.anlx.net/karaf/${version}/apache-karaf-${version}.tar.gz"); + + @SetFromFlag("karafName") + public static final BasicAttributeSensorAndConfigKey<String> KARAF_NAME = new BasicAttributeSensorAndConfigKey<String>( + String.class, "karaf.name", "Karaf instance name", "root"); + + // TODO too complicated? Used by KarafContainer; was in JavaApp; where should it be in brave new world? + public static final MapConfigKey<Map<String,String>> NAMED_PROPERTY_FILES = new MapConfigKey( + Map.class, "karaf.runtime.files", "Property files to be generated, referenced by name relative to runDir"); + + @SetFromFlag("jmxUser") + public static final BasicAttributeSensorAndConfigKey<String> JMX_USER = new BasicAttributeSensorAndConfigKey<String>( + UsesJmx.JMX_USER, "karaf"); + + @SetFromFlag("jmxPassword") + public static final BasicAttributeSensorAndConfigKey<String> JMX_PASSWORD = new BasicAttributeSensorAndConfigKey<String>( + UsesJmx.JMX_PASSWORD, "karaf"); + + @SetFromFlag("jmxPort") + public static final PortAttributeSensorAndConfigKey JMX_PORT = new PortAttributeSensorAndConfigKey( + UsesJmx.JMX_PORT, "44444+"); + + @SetFromFlag("rmiRegistryPort") + public static final PortAttributeSensorAndConfigKey RMI_REGISTRY_PORT = UsesJmx.RMI_REGISTRY_PORT; + + @SetFromFlag("jmxContext") + public static final BasicAttributeSensorAndConfigKey<String> JMX_CONTEXT = new BasicAttributeSensorAndConfigKey<String>( + UsesJmx.JMX_CONTEXT, "karaf-"+KARAF_NAME.getConfigKey().getDefaultValue()); + + public static final BasicAttributeSensor<Map> KARAF_INSTANCES = new BasicAttributeSensor<Map>( + Map.class, "karaf.admin.instances", "Karaf admin instances"); + public static final BasicAttributeSensor<Boolean> KARAF_ROOT = new BasicAttributeSensor<Boolean>( + Boolean.class, "karaf.admin.isRoot", "Karaf admin isRoot"); + public static final BasicAttributeSensor<String> KARAF_JAVA_OPTS = new BasicAttributeSensor<String>( + String.class, "karaf.admin.java_opts", "Karaf Java opts"); + public static final BasicAttributeSensor<String> KARAF_INSTALL_LOCATION = new BasicAttributeSensor<String>( + String.class, "karaf.admin.location", "Karaf install location"); + public static final BasicAttributeSensor<Integer> KARAF_PID = new BasicAttributeSensor<Integer>( + Integer.class, "karaf.admin.pid", "Karaf instance PID"); + public static final BasicAttributeSensor<Integer> KARAF_SSH_PORT = new BasicAttributeSensor<Integer>( + Integer.class, "karaf.admin.ssh_port", "Karaf SSH Port"); + public static final BasicAttributeSensor<Integer> KARAF_RMI_REGISTRY_PORT = new BasicAttributeSensor<Integer>( + Integer.class, "karaf.admin.rmi_registry_port", "Karaf instance RMI registry port"); + public static final BasicAttributeSensor<Integer> KARAF_RMI_SERVER_PORT = new BasicAttributeSensor<Integer>( + Integer.class, "karaf.admin.rmi_server_port", "Karaf RMI (JMX) server port"); + public static final BasicAttributeSensor<String> KARAF_STATE = new BasicAttributeSensor<String>( + String.class, "karaf.admin.state", "Karaf instance state"); + + @Effector(description="Updates the OSGi Service's properties, adding (and overriding) the given key-value pairs") + public void updateServiceProperties( + @EffectorParam(name="serviceName", description="Name of the OSGi service") String serviceName, + Map<String,String> additionalVals); + + @Effector(description="Installs the given OSGi feature") + public void installFeature( + @EffectorParam(name="featureName", description="Name of the feature - see org.apache.karaf:type=features#installFeature()") final String featureName) + throws Exception; + + @Effector(description="Lists all the karaf bundles") + public Map<Long,Map<String,?>> listBundles(); + + /** + * throws URISyntaxException If bundle name is not a valid URI + */ + @Effector(description="Deploys the given bundle, returning the bundle id - see osgi.core:type=framework#installBundle()") + public long installBundle( + @EffectorParam(name="bundle", description="URI of bundle to be deployed") String bundle) throws URISyntaxException; + + @Effector(description="Undeploys the bundle with the given id") + public void uninstallBundle( + @EffectorParam(name="bundleId", description="Id of the bundle") Long bundleId); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerImpl.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerImpl.java b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerImpl.java new file mode 100644 index 0000000..30be663 --- /dev/null +++ b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerImpl.java @@ -0,0 +1,298 @@ +/* + * 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.brooklyn.entity.osgi.karaf; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +import javax.management.ObjectName; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.OpenDataException; +import javax.management.openmbean.TabularData; + +import org.osgi.jmx.JmxConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import brooklyn.entity.annotation.Effector; +import brooklyn.entity.annotation.EffectorParam; +import brooklyn.entity.basic.SoftwareProcessImpl; +import brooklyn.entity.java.JmxSupport; +import brooklyn.event.SensorEvent; +import brooklyn.event.SensorEventListener; +import brooklyn.event.feed.ConfigToAttributes; +import brooklyn.event.feed.jmx.JmxAttributePollConfig; +import brooklyn.event.feed.jmx.JmxFeed; +import brooklyn.event.feed.jmx.JmxHelper; +import brooklyn.event.feed.jmx.JmxValueFunctions; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.exceptions.Exceptions; +import brooklyn.util.os.Os; +import brooklyn.util.repeat.Repeater; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; + +/** + * This sets up a Karaf OSGi container + */ +public class KarafContainerImpl extends SoftwareProcessImpl implements KarafContainer { + + // TODO Better way of setting/overriding defaults for config keys that are defined in super class SoftwareProcess + + private static final Logger LOG = LoggerFactory.getLogger(KarafContainerImpl.class); + + public static final String KARAF_ADMIN = "org.apache.karaf:type=admin,name=%s"; + public static final String KARAF_FEATURES = "org.apache.karaf:type=features,name=%s"; + + public static final String OSGI_BUNDLE_STATE = "osgi.core:type=bundleState,version=1.5"; + public static final String OSGI_FRAMEWORK = "osgi.core:type=framework,version=1.5"; + public static final String OSGI_COMPENDIUM = "osgi.compendium:service=cm,version=1.3"; + + protected JmxHelper jmxHelper; + + private JmxFeed jmxFeed; + + public KarafContainerImpl() { + super(); + } + + @Override + public Class<KarafDriver> getDriverInterface() { + return KarafDriver.class; + } + + @Override + public KarafDriver getDriver() { + return (KarafDriver) super.getDriver(); + } + + @Override + public void init() { + super.init(); + new JmxSupport(this, null).recommendJmxRmiCustomAgent(); + } + + @Override + protected void postDriverStart() { + super.postDriverStart(); + uploadPropertyFiles(getConfig(NAMED_PROPERTY_FILES)); + + jmxHelper = new JmxHelper(this); + jmxHelper.connect(0); // i.e. don't block + } + + @Override + protected void connectSensors() { + super.connectSensors(); + + //FIXME should have a better way of setting config -- firstly, not here! + //preferred style is to have config auto-applied to attributes, and have default values in their definition, not here + //use of "properties.{user,password}" is non-standard; is that requried? use default jmxUser, jmxPassword flags? + setAttribute(JMX_CONTEXT, String.format("karaf-%s", getConfig(KARAF_NAME.getConfigKey()))); + + ConfigToAttributes.apply(this); + + ObjectName karafAdminObjectName = JmxHelper.createObjectName(String.format(KARAF_ADMIN, getConfig(KARAF_NAME.getConfigKey()))); + + jmxFeed = JmxFeed.builder() + .entity(this) + .helper(jmxHelper) + .period(500, TimeUnit.MILLISECONDS) + .pollAttribute(new JmxAttributePollConfig<Map>(KARAF_INSTANCES) + .objectName(karafAdminObjectName) + .attributeName("Instances") + .onSuccess(new Function<Object, Map>() { + @Override + public Map apply(Object input) { + return JmxValueFunctions.tabularDataToMap((TabularData)input); + } + }) + .onException(new Function<Exception,Map>() { + @Override public Map apply(Exception input) { + // If MBean is unreachable, then mark as service-down + if (Boolean.TRUE.equals(getAttribute(SERVICE_UP))) { + LOG.debug("Entity "+this+" is not reachable on JMX"); + setAttribute(SERVICE_UP, false); + } + return null; + }})) + .build(); + + + + // INSTANCES aggregates data for the other sensors. + subscribe(this, KARAF_INSTANCES, new SensorEventListener<Map>() { + @Override public void onEvent(SensorEvent<Map> event) { + Map map = event.getValue(); + if (map == null) return; + + setAttribute(SERVICE_UP, "Started".equals(map.get("State"))); + setAttribute(KARAF_ROOT, (Boolean) map.get("Is Root")); + setAttribute(KARAF_JAVA_OPTS, (String) map.get("JavaOpts")); + setAttribute(KARAF_INSTALL_LOCATION, (String) map.get("Location")); + setAttribute(KARAF_NAME, (String) map.get("Name")); + setAttribute(KARAF_PID, (Integer) map.get("Pid")); + setAttribute(KARAF_SSH_PORT, (Integer) map.get("Ssh Port")); + setAttribute(KARAF_RMI_REGISTRY_PORT, (Integer) map.get("RMI Registry Port")); + setAttribute(KARAF_RMI_SERVER_PORT, (Integer) map.get("RMI Server Port")); + setAttribute(KARAF_STATE, (String) map.get("State")); + }}); + + } + + @Override + protected void disconnectSensors() { + super.disconnectSensors(); + if (jmxFeed != null) jmxFeed.stop(); + } + + @Override + protected void preStop() { + super.preStop(); + + if (jmxHelper != null) jmxHelper.terminate(); + } + + @Effector(description="Updates the OSGi Service's properties, adding (and overriding) the given key-value pairs") + public void updateServiceProperties( + @EffectorParam(name="serviceName", description="Name of the OSGi service") String serviceName, + Map<String,String> additionalVals) { + TabularData table = (TabularData) jmxHelper.operation(OSGI_COMPENDIUM, "getProperties", serviceName); + + try { + for (Map.Entry<String, String> entry: additionalVals.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + CompositeData data = new CompositeDataSupport( + JmxConstants.PROPERTY_TYPE, + MutableMap.of(JmxConstants.KEY, key, JmxConstants.TYPE, "String", JmxConstants.VALUE, value)); + table.remove(data.getAll(new String[] {JmxConstants.KEY})); + table.put(data); + } + } catch (OpenDataException e) { + throw Exceptions.propagate(e); + } + + LOG.info("Updating monterey-service configuration with changes {}", additionalVals); + if (LOG.isTraceEnabled()) LOG.trace("Updating monterey-service configuration with new configuration {}", table); + + jmxHelper.operation(OSGI_COMPENDIUM, "update", serviceName, table); + } + + @Effector(description="Updates the OSGi Service's properties, adding (and overriding) the given key-value pairs") + public void installFeature( + @EffectorParam(name="featureName", description="Name of the feature - see org.apache.karaf:type=features#installFeature()") final String featureName) throws Exception { + + LOG.info("Installing feature {} via JMX", featureName); + + Repeater.create("Wait for Karaf, to install feature "+featureName) + .limitIterationsTo(40) + .every(500, TimeUnit.MILLISECONDS) + .until(new Callable<Boolean>() { + public Boolean call() { + jmxHelper.operation(String.format(KARAF_FEATURES, getConfig(KARAF_NAME.getConfigKey())), "installFeature", featureName); + return true; + }}) + .rethrowException() + .run(); + } + + public Map<Long,Map<String,?>> listBundles() { + TabularData table = (TabularData) jmxHelper.operation(OSGI_BUNDLE_STATE, "listBundles"); + Map<List<?>, Map<String, Object>> map = JmxValueFunctions.tabularDataToMapOfMaps(table); + + Map<Long,Map<String,?>> result = Maps.newLinkedHashMap(); + for (Map.Entry<List<?>, Map<String, Object>> entry : map.entrySet()) { + result.put((Long)entry.getKey().get(0), entry.getValue()); + } + return result; + } + + /** + * throws URISyntaxException If bundle name is not a valid URI + */ + @Effector(description="Deploys the given bundle, returning the bundle id - see osgi.core:type=framework#installBundle()") + public long installBundle( + @EffectorParam(name="bundle", description="URI of bundle to be deployed") String bundle) throws URISyntaxException { + + // TODO Consider switching to use either: + // - org.apache.karaf:type=bundles#install(String), or + // - dropping file into $RUN_DIR/deploy (but that would be async) + + URI uri = new URI(bundle); + boolean wrap = false; + if (WRAP_SCHEME.equals(uri.getScheme())) { + bundle = bundle.substring(WRAP_SCHEME.length() + 1); + uri = new URI(bundle); + wrap = true; + } + if (FILE_SCHEME.equals(uri.getScheme())) { + LOG.info("Deploying bundle {} via file copy", bundle); + File source = new File(uri); + String target = getDriver().getRunDir() + "/" + source.getName(); + getDriver().copyResource(source, target); + return (Long) jmxHelper.operation(OSGI_FRAMEWORK, "installBundle", (wrap ? WRAP_SCHEME + ":" : "") + FILE_SCHEME + "://" + target); + } else { + LOG.info("Deploying bundle {} via JMX", bundle); + return (Long) jmxHelper.operation(OSGI_FRAMEWORK, "installBundle", (wrap ? WRAP_SCHEME + ":" : "") + bundle); + } + } + + @Effector(description="Undeploys the bundle with the given id") + public void uninstallBundle( + @EffectorParam(name="bundleId", description="Id of the bundle") Long bundleId) { + + // TODO Consider switching to use either: + // - org.apache.karaf:type=bundles#install(String), or + // - dropping file into $RUN_DIR/deploy (but that would be async) + + jmxHelper.operation(OSGI_FRAMEWORK, "uninstallBundle", bundleId); + } + + protected void uploadPropertyFiles(Map<String,Map<String,String>> propertyFiles) { + if (propertyFiles == null) return; + + for (Map.Entry<String,Map<String,String>> entry : propertyFiles.entrySet()) { + String file = entry.getKey(); + Map<String,String> contents = entry.getValue(); + + Properties props = new Properties(); + for (Map.Entry<String,String> prop : contents.entrySet()) { + props.setProperty(prop.getKey(), prop.getValue()); + } + + File local = Os.writePropertiesToTempFile(props, "karaf-"+getId(), ".cfg"); + local.setReadable(true); + try { + String remote = getDriver().getRunDir() + "/" + file; + getDriver().copyResource(local, remote); + } finally { + local.delete(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafDriver.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafDriver.java b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafDriver.java new file mode 100644 index 0000000..80e972d --- /dev/null +++ b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafDriver.java @@ -0,0 +1,30 @@ +/* + * 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.brooklyn.entity.osgi.karaf; + +import java.io.File; + +import brooklyn.entity.java.JavaSoftwareProcessDriver; + +public interface KarafDriver extends JavaSoftwareProcessDriver { + + public String getRunDir(); + + public int copyResource(File src, String destination); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafSshDriver.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafSshDriver.java b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafSshDriver.java new file mode 100644 index 0000000..3d8281a --- /dev/null +++ b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafSshDriver.java @@ -0,0 +1,149 @@ +/* + * 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.brooklyn.entity.osgi.karaf; + +import static java.lang.String.format; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import brooklyn.entity.basic.Entities; +import brooklyn.entity.java.JavaSoftwareProcessSshDriver; +import brooklyn.location.basic.SshMachineLocation; +import brooklyn.util.collections.MutableList; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.net.Networking; +import brooklyn.util.os.Os; +import brooklyn.util.ssh.BashCommands; + +import com.google.common.collect.ImmutableList; + +public class KarafSshDriver extends JavaSoftwareProcessSshDriver implements KarafDriver { + + // TODO getJmxJavaSystemProperties(), don't set via JAVA_OPTS; set ourselves manually + // (karaf reads from props files) + // but do set "java.rmi.server.hostname" + + public KarafSshDriver(KarafContainerImpl entity, SshMachineLocation machine) { + super(entity, machine); + } + + @Override + public KarafContainerImpl getEntity() { + return (KarafContainerImpl) super.getEntity(); + } + + @Override + protected String getLogFileLocation() { + return Os.mergePaths(getRunDir(), "data", "karaf.out"); + } + + @Override + public void preInstall() { + resolver = Entities.newDownloader(this); + setExpandedInstallDir(Os.mergePaths(getInstallDir(), resolver.getUnpackedDirectoryName(format("apache-karaf-%s", getVersion())))); + } + + @Override + public void install() { + List<String> urls = resolver.getTargets(); + String saveAs = resolver.getFilename(); + + List<String> commands = ImmutableList.<String>builder() + .addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs)) + .add(BashCommands.INSTALL_TAR) + .add("tar xzfv " + saveAs) + .build(); + + newScript(INSTALLING) + .body.append(commands) + .execute(); + } + + @Override + public void customize() { + Map<String, Object> ports = new HashMap<String, Object>(); + ports.put("jmxPort", getJmxPort()); + ports.put("rmiRegistryPort", getRmiRegistryPort()); + Networking.checkPortsValid(ports); + + newScript(CUSTOMIZING) + .body.append( + format("cd %s", getRunDir()), + format("cp -R %s/{bin,etc,lib,system,deploy} . || exit $!", getExpandedInstallDir()), + format("sed -i.bk 's/rmiRegistryPort = 1099/rmiRegistryPort = %s/g' etc/org.apache.karaf.management.cfg", getRmiRegistryPort()), + format("sed -i.bk 's/rmiServerPort = 44444/rmiServerPort = %s/g' etc/org.apache.karaf.management.cfg", getJmxPort()) + ) + .execute(); + } + + @Override + public void launch() { + newScript(MutableMap.of(USE_PID_FILE, true), LAUNCHING) + .body.append("nohup ./bin/start") + .execute(); + } + + @Override + public boolean isRunning() { + // TODO Can we use the pidFile, auto-generated by launch? + + Integer pid = entity.getAttribute(KarafContainer.KARAF_PID); + // This method is called on startup, before JMX is initialised, so pid won't always be available. + if (pid != null) { + return newScript(CHECK_RUNNING) + .body.append(format("ps aux | grep 'karaf' | grep %s > /dev/null", pid)) + .execute() == 0; + } else { + // Simple method isn't available, use pid in instance.properties. + return newScript(CHECK_RUNNING) + .body.append( + format("cd %s/instances/",getRunDir()), + "[ $(uname) = \"Darwin\" ] && pid=$(sed -n -e 's/.*pid=\\([0-9]*\\)$/\\1/p' instance.properties) || pid=$(sed -r -n -e 's/.*pid=([0-9]*)$/\\1/p' instance.properties)", + "ps aux | grep 'karaf' | grep $(echo ${pid:-X}) > /dev/null" + ) + .execute() == 0; + } + } + + @Override + public void stop() { + newScript(STOPPING) + .environmentVariablesReset() + .body.append(format("%s/bin/stop",getRunDir())) + .execute(); + } + + @Override + public void kill() { + stop(); // TODO no pid file to easily do `kill -9` + } + + @Override + protected List<String> getCustomJavaConfigOptions() { + return MutableList.<String>builder() + .addAll(super.getCustomJavaConfigOptions()) + .add("-Xms200m") + .add("-Xmx800m") + .add("-XX:MaxPermSize=400m") + .build(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/test/java/brooklyn/entity/osgi/karaf/KarafContainerEc2LiveTest.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/test/java/brooklyn/entity/osgi/karaf/KarafContainerEc2LiveTest.java b/software/osgi/src/test/java/brooklyn/entity/osgi/karaf/KarafContainerEc2LiveTest.java deleted file mode 100644 index 9c2bd89..0000000 --- a/software/osgi/src/test/java/brooklyn/entity/osgi/karaf/KarafContainerEc2LiveTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.osgi.karaf; - -import org.apache.brooklyn.test.EntityTestUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.Test; - -import brooklyn.entity.AbstractEc2LiveTest; -import brooklyn.entity.proxying.EntitySpec; -import brooklyn.location.Location; -import brooklyn.util.text.Identifiers; - -import com.google.common.collect.ImmutableList; - -public class KarafContainerEc2LiveTest extends AbstractEc2LiveTest { - - @SuppressWarnings("unused") - private static final Logger LOG = LoggerFactory.getLogger(KarafContainerEc2LiveTest.class); - - @Override - protected void doTest(Location loc) throws Exception { - KarafContainer karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) - .configure("name", Identifiers.makeRandomId(8)) - .configure("displayName", "Karaf Test") - .configure("jmxPort", "8099+") - .configure("rmiRegistryPort", "9099+")); - - app.start(ImmutableList.of(loc)); - - EntityTestUtils.assertAttributeEqualsEventually(karaf, KarafContainer.SERVICE_UP, true); - } - - @Test(enabled=false) - public void testDummy() {} // Convince testng IDE integration that this really does have test methods -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/test/java/brooklyn/entity/osgi/karaf/KarafContainerTest.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/test/java/brooklyn/entity/osgi/karaf/KarafContainerTest.java b/software/osgi/src/test/java/brooklyn/entity/osgi/karaf/KarafContainerTest.java deleted file mode 100644 index eb5c561..0000000 --- a/software/osgi/src/test/java/brooklyn/entity/osgi/karaf/KarafContainerTest.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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.osgi.karaf; - -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; - -import java.net.URL; -import java.util.Map; - -import org.apache.brooklyn.test.EntityTestUtils; -import org.apache.brooklyn.test.TestResourceUnavailableException; -import org.testng.Assert; -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.proxying.EntitySpec; -import brooklyn.entity.software.SshEffectorTasks; -import brooklyn.location.NoMachinesAvailableException; -import brooklyn.location.basic.LocalhostMachineProvisioningLocation; -import brooklyn.test.Asserts; -import brooklyn.util.exceptions.Exceptions; -import brooklyn.util.text.Identifiers; - -import com.google.common.collect.ImmutableList; - -public class KarafContainerTest extends BrooklynAppLiveTestSupport { - - private static final String HELLO_WORLD_JAR = "/hello-world.jar"; - - LocalhostMachineProvisioningLocation localhost; - KarafContainer karaf; - - @BeforeMethod(alwaysRun=true) - public void setUp() throws Exception { - super.setUp(); - localhost = app.newLocalhostProvisioningLocation(); - } - - // FIXME Test failing in jenkins; not sure why. The karaf log shows the mbeans never being - // registered so we are never able to connect to them over jmx. - @Test(groups = {"Integration", "WIP"}) - public void canStartupAndShutdown() throws Exception { - karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) - .configure("name", Identifiers.makeRandomId(8)) - .configure("displayName", "Karaf Test")); - - app.start(ImmutableList.of(localhost)); - EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, true); - - Entities.dumpInfo(karaf); - final int pid = karaf.getAttribute(KarafContainer.KARAF_PID); - Entities.submit(app, SshEffectorTasks.requirePidRunning(pid).machine(localhost.obtain())).get(); - - karaf.stop(); - EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, false); - - Asserts.succeedsEventually(new Runnable() { - public void run() { - try { - Assert.assertFalse(Entities.submit(app, SshEffectorTasks.isPidRunning(pid).machine(localhost.obtain())).get()); - } catch (NoMachinesAvailableException e) { - throw Exceptions.propagate(e); - } - }}); - } - - @Test(groups = {"Integration", "WIP"}) - public void canStartupAndShutdownExplicitJmx() throws Exception { - karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) - .configure("name", Identifiers.makeRandomId(8)) - .configure("displayName", "Karaf Test") - .configure("rmiRegistryPort", "8099+") - .configure("jmxPort", "9099+")); - - app.start(ImmutableList.of(localhost)); - EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, true); - - karaf.stop(); - EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, false); - } - - @Test(groups = {"Integration", "WIP"}) - public void canStartupAndShutdownLegacyJmx() throws Exception { - karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) - .configure("name", Identifiers.makeRandomId(8)) - .configure("displayName", "Karaf Test") - .configure("jmxPort", "8099+") - .configure("rmiRegistryPort", "9099+")); - // NB: now the above parameters have the opposite semantics to before - - app.start(ImmutableList.of(localhost)); - EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, true); - - karaf.stop(); - EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, false); - } - - // FIXME Test failing in jenkins; not sure why. The karaf log shows the mbeans never being - // registered so we are never able to connect to them over jmx. - @Test(groups = {"Integration", "WIP"}) - public void testCanInstallAndUninstallBundle() throws Exception { - TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), HELLO_WORLD_JAR); - URL jarUrl = getClass().getResource(HELLO_WORLD_JAR); - assertNotNull(jarUrl); - - karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) - .configure("name", Identifiers.makeRandomId(8)) - .configure("displayName", "Karaf Test") - .configure("jmxPort", "8099+") - .configure("rmiRegistryPort", "9099+")); - - app.start(ImmutableList.of(localhost)); - - long bundleId = karaf.installBundle("wrap:"+jarUrl.toString()); - - Map<Long, Map<String,?>> bundles = karaf.listBundles(); - Map<String,?> bundle = bundles.get(bundleId); - assertNotNull(bundle, "expected="+bundleId+"; actual="+bundles.keySet()); - - // Undeploy: expect bundle to no longer be listed - karaf.uninstallBundle(bundleId); - - Map<Long, Map<String,?>> bundles2 = karaf.listBundles(); - Map<String,?> bundle2 = bundles2.get(bundleId); - assertNull(bundle2, "expectedAbsent="+bundleId+"; actual="+bundles2.keySet()); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/test/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerEc2LiveTest.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/test/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerEc2LiveTest.java b/software/osgi/src/test/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerEc2LiveTest.java new file mode 100644 index 0000000..d6c69d9 --- /dev/null +++ b/software/osgi/src/test/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerEc2LiveTest.java @@ -0,0 +1,53 @@ +/* + * 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.brooklyn.entity.osgi.karaf; + +import org.apache.brooklyn.test.EntityTestUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +import brooklyn.entity.AbstractEc2LiveTest; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.location.Location; +import brooklyn.util.text.Identifiers; + +import com.google.common.collect.ImmutableList; + +public class KarafContainerEc2LiveTest extends AbstractEc2LiveTest { + + @SuppressWarnings("unused") + private static final Logger LOG = LoggerFactory.getLogger(KarafContainerEc2LiveTest.class); + + @Override + protected void doTest(Location loc) throws Exception { + KarafContainer karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) + .configure("name", Identifiers.makeRandomId(8)) + .configure("displayName", "Karaf Test") + .configure("jmxPort", "8099+") + .configure("rmiRegistryPort", "9099+")); + + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(karaf, KarafContainer.SERVICE_UP, true); + } + + @Test(enabled=false) + public void testDummy() {} // Convince testng IDE integration that this really does have test methods +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8601629a/software/osgi/src/test/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerTest.java ---------------------------------------------------------------------- diff --git a/software/osgi/src/test/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerTest.java b/software/osgi/src/test/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerTest.java new file mode 100644 index 0000000..03c9bc6 --- /dev/null +++ b/software/osgi/src/test/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainerTest.java @@ -0,0 +1,147 @@ +/* + * 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.brooklyn.entity.osgi.karaf; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; + +import java.net.URL; +import java.util.Map; + +import org.apache.brooklyn.test.EntityTestUtils; +import org.apache.brooklyn.test.TestResourceUnavailableException; +import org.testng.Assert; +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.proxying.EntitySpec; +import brooklyn.entity.software.SshEffectorTasks; +import brooklyn.location.NoMachinesAvailableException; +import brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import brooklyn.test.Asserts; +import brooklyn.util.exceptions.Exceptions; +import brooklyn.util.text.Identifiers; + +import com.google.common.collect.ImmutableList; + +public class KarafContainerTest extends BrooklynAppLiveTestSupport { + + private static final String HELLO_WORLD_JAR = "/hello-world.jar"; + + LocalhostMachineProvisioningLocation localhost; + KarafContainer karaf; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + super.setUp(); + localhost = app.newLocalhostProvisioningLocation(); + } + + // FIXME Test failing in jenkins; not sure why. The karaf log shows the mbeans never being + // registered so we are never able to connect to them over jmx. + @Test(groups = {"Integration", "WIP"}) + public void canStartupAndShutdown() throws Exception { + karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) + .configure("name", Identifiers.makeRandomId(8)) + .configure("displayName", "Karaf Test")); + + app.start(ImmutableList.of(localhost)); + EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, true); + + Entities.dumpInfo(karaf); + final int pid = karaf.getAttribute(KarafContainer.KARAF_PID); + Entities.submit(app, SshEffectorTasks.requirePidRunning(pid).machine(localhost.obtain())).get(); + + karaf.stop(); + EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, false); + + Asserts.succeedsEventually(new Runnable() { + public void run() { + try { + Assert.assertFalse(Entities.submit(app, SshEffectorTasks.isPidRunning(pid).machine(localhost.obtain())).get()); + } catch (NoMachinesAvailableException e) { + throw Exceptions.propagate(e); + } + }}); + } + + @Test(groups = {"Integration", "WIP"}) + public void canStartupAndShutdownExplicitJmx() throws Exception { + karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) + .configure("name", Identifiers.makeRandomId(8)) + .configure("displayName", "Karaf Test") + .configure("rmiRegistryPort", "8099+") + .configure("jmxPort", "9099+")); + + app.start(ImmutableList.of(localhost)); + EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, true); + + karaf.stop(); + EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, false); + } + + @Test(groups = {"Integration", "WIP"}) + public void canStartupAndShutdownLegacyJmx() throws Exception { + karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) + .configure("name", Identifiers.makeRandomId(8)) + .configure("displayName", "Karaf Test") + .configure("jmxPort", "8099+") + .configure("rmiRegistryPort", "9099+")); + // NB: now the above parameters have the opposite semantics to before + + app.start(ImmutableList.of(localhost)); + EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, true); + + karaf.stop(); + EntityTestUtils.assertAttributeEqualsEventually(karaf, Attributes.SERVICE_UP, false); + } + + // FIXME Test failing in jenkins; not sure why. The karaf log shows the mbeans never being + // registered so we are never able to connect to them over jmx. + @Test(groups = {"Integration", "WIP"}) + public void testCanInstallAndUninstallBundle() throws Exception { + TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), HELLO_WORLD_JAR); + URL jarUrl = getClass().getResource(HELLO_WORLD_JAR); + assertNotNull(jarUrl); + + karaf = app.createAndManageChild(EntitySpec.create(KarafContainer.class) + .configure("name", Identifiers.makeRandomId(8)) + .configure("displayName", "Karaf Test") + .configure("jmxPort", "8099+") + .configure("rmiRegistryPort", "9099+")); + + app.start(ImmutableList.of(localhost)); + + long bundleId = karaf.installBundle("wrap:"+jarUrl.toString()); + + Map<Long, Map<String,?>> bundles = karaf.listBundles(); + Map<String,?> bundle = bundles.get(bundleId); + assertNotNull(bundle, "expected="+bundleId+"; actual="+bundles.keySet()); + + // Undeploy: expect bundle to no longer be listed + karaf.uninstallBundle(bundleId); + + Map<Long, Map<String,?>> bundles2 = karaf.listBundles(); + Map<String,?> bundle2 = bundles2.get(bundleId); + assertNull(bundle2, "expectedAbsent="+bundleId+"; actual="+bundles2.keySet()); + } +}
