You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2016/02/01 18:46:33 UTC
[03/50] brooklyn-library git commit: Initial MariaDB entity,
largely a clone of the existing mySQL entity.
Initial MariaDB entity, largely a clone of the existing mySQL entity.
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-library/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-library/commit/2e0516df
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-library/tree/2e0516df
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-library/diff/2e0516df
Branch: refs/heads/0.6.0
Commit: 2e0516df17a9597b71f6b36d1c13483cc57676e1
Parents: 25b37b3
Author: Alasdair Hodge <al...@cloudsoftcorp.com>
Authored: Mon Oct 28 14:01:46 2013 +0000
Committer: Alasdair Hodge <al...@cloudsoftcorp.com>
Committed: Mon Oct 28 19:14:01 2013 +0000
----------------------------------------------------------------------
.../entity/database/mariadb/MariaDbDriver.java | 10 +
.../entity/database/mariadb/MariaDbNode.java | 84 ++++++++
.../database/mariadb/MariaDbNodeImpl.java | 119 ++++++++++
.../database/mariadb/MariaDbSshDriver.java | 216 +++++++++++++++++++
.../brooklyn/entity/database/mariadb/my.cnf | 19 ++
.../src/main/resources/mariadb-logo-180x119.png | Bin 0 -> 9659 bytes
.../mariadb/MariaDbIntegrationTest.groovy | 105 +++++++++
.../database/mariadb/MariaDbLiveEc2Test.java | 27 +++
.../mariadb/MariaDbLiveRackspaceTest.java | 80 +++++++
9 files changed, 660 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e0516df/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbDriver.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbDriver.java b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbDriver.java
new file mode 100644
index 0000000..3061f5e
--- /dev/null
+++ b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbDriver.java
@@ -0,0 +1,10 @@
+package brooklyn.entity.database.mariadb;
+
+import brooklyn.entity.basic.SoftwareProcessDriver;
+
+/**
+ * The {@link SoftwareProcessDriver} for MariaDB.
+ */
+public interface MariaDbDriver extends SoftwareProcessDriver {
+ public String getStatusCmd();
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e0516df/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNode.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNode.java b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNode.java
new file mode 100644
index 0000000..256ce8a
--- /dev/null
+++ b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNode.java
@@ -0,0 +1,84 @@
+package brooklyn.entity.database.mariadb;
+
+import brooklyn.catalog.Catalog;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.database.DatabaseNode;
+import brooklyn.entity.proxying.ImplementedBy;
+import brooklyn.entity.trait.HasShortName;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
+import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSensorAndConfigKey;
+import brooklyn.event.basic.MapConfigKey;
+import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+import brooklyn.event.basic.Sensors;
+import brooklyn.location.basic.PortRanges;
+import brooklyn.util.flags.SetFromFlag;
+
+@Catalog(name="MariaDB Node", description="MariaDB is an open source relational database management system (RDBMS)", iconUrl="classpath:///mariadb-logo-180x119.png")
+@ImplementedBy(MariaDbNodeImpl.class)
+public interface MariaDbNode extends DatabaseNode, HasShortName {
+
+ @SetFromFlag("version")
+ public static final ConfigKey<String> SUGGESTED_VERSION =
+ ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "5.5.33a");
+
+ // https://downloads.mariadb.org/interstitial/mariadb-5.5.33a/kvm-bintar-hardy-amd64/mariadb-5.5.33a-linux-x86_64.tar.gz/from/http://mirrors.coreix.net/mariadb
+ // above link points to a "donate" page, then ultimately downloads the artifact from:
+ // 64-bit: http://mirrors.coreix.net/mariadb/mariadb-5.5.33a/kvm-bintar-hardy-amd64/mariadb-5.5.33a-linux-x86_64.tar.gz
+ // 32-bit: http://mirrors.coreix.net/mariadb/mariadb-5.5.33a/kvm-bintar-hardy-x86/mariadb-5.5.33a-linux-i686.tar.gz
+
+ @SetFromFlag("downloadUrl")
+ public static final BasicAttributeSensorAndConfigKey<String> DOWNLOAD_URL = new StringAttributeSensorAndConfigKey(
+ Attributes.DOWNLOAD_URL, "${driver.mirrorUrl}/mariadb-${version}/${driver.downloadParentDir}/mariadb-${version}-${driver.osTag}.tar.gz");
+
+ /** download mirror, if desired */
+ @SetFromFlag("mirrorUrl")
+ public static final ConfigKey<String> MIRROR_URL = ConfigKeys.newStringConfigKey("mariadb.install.mirror.url", "URL of mirror",
+ "http://mirrors.coreix.net/mariadb/"
+ );
+
+ @SetFromFlag("port")
+ public static final PortAttributeSensorAndConfigKey MARIADB_PORT =
+ new PortAttributeSensorAndConfigKey("mariadb.port", "MariaDB port", PortRanges.fromString("3306, 13306+"));
+
+ @SetFromFlag("creationScriptContents")
+ public static final ConfigKey<String> CREATION_SCRIPT_CONTENTS =
+ ConfigKeys.newStringConfigKey("mariadb.creation.script.contents", "MariaDB creation script (SQL contents)", "");
+
+ @SetFromFlag("creationScriptUrl")
+ public static final ConfigKey<String> CREATION_SCRIPT_URL =
+ ConfigKeys.newStringConfigKey("mariadb.creation.script.url", "URL where MariaDB creation script can be found", "");
+
+ @SetFromFlag("dataDir")
+ public static final ConfigKey<String> DATA_DIR = ConfigKeys.newStringConfigKey(
+ "mariadb.datadir", "Directory for writing data files", null);
+
+ @SetFromFlag("serverConf")
+ public static final MapConfigKey<Object> MARIADB_SERVER_CONF = new MapConfigKey<Object>(
+ Object.class, "mariadb.server.conf", "Configuration options for MariaDB server");
+
+ public static final ConfigKey<Object> MARIADB_SERVER_CONF_LOWER_CASE_TABLE_NAMES =
+ MARIADB_SERVER_CONF.subKey("lower_case_table_names", "See MariaDB (or MySQL!) guide. Set 1 to ignore case in table names (useful for OS portability)");
+
+ @SetFromFlag("password")
+ public static final StringAttributeSensorAndConfigKey PASSWORD = new StringAttributeSensorAndConfigKey(
+ "mariadb.password", "Database admin password (or randomly generated if not set)", null);
+
+ @SetFromFlag("socketUid")
+ public static final StringAttributeSensorAndConfigKey SOCKET_UID = new StringAttributeSensorAndConfigKey(
+ "mariadb.socketUid", "Socket uid, for use in file /tmp/mysql.sock.<uid>.3306 (or randomly generated if not set)", null);
+
+ public static final AttributeSensor<String> MARIADB_URL = DB_URL;
+
+ @SetFromFlag("configurationTemplateUrl")
+ static final BasicAttributeSensorAndConfigKey<String> TEMPLATE_CONFIGURATION_URL = new StringAttributeSensorAndConfigKey(
+ "mariadb.template.configuration.url", "Template file (in freemarker format) for the my.cnf file",
+ "classpath://brooklyn/entity/database/mariadb/my.cnf");
+
+ public static final AttributeSensor<Double> QUERIES_PER_SECOND_FROM_MARIADB =
+ Sensors.newDoubleSensor("mariadb.queries.perSec.fromMariadb");
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e0516df/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
new file mode 100644
index 0000000..e370367
--- /dev/null
+++ b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
@@ -0,0 +1,119 @@
+package brooklyn.entity.database.mariadb;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.SoftwareProcessImpl;
+import brooklyn.event.feed.ssh.SshFeed;
+import brooklyn.event.feed.ssh.SshPollConfig;
+import brooklyn.event.feed.ssh.SshPollValue;
+import brooklyn.location.Location;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+
+public class MariaDbNodeImpl extends SoftwareProcessImpl implements MariaDbNode {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MariaDbNodeImpl.class);
+
+ private SshFeed feed;
+
+ public MariaDbNodeImpl() {
+ }
+
+ public MariaDbNodeImpl(Entity parent) {
+ this(MutableMap.of(), parent);
+ }
+
+ public MariaDbNodeImpl(Map<?,?> flags) {
+ super(flags, null);
+ }
+
+ public MariaDbNodeImpl(Map<?,?> flags, Entity parent) {
+ super(flags, parent);
+ }
+
+ @Override
+ public Class<?> getDriverInterface() {
+ return MariaDbDriver.class;
+ }
+
+ @Override
+ public MariaDbDriver getDriver() {
+ return (MariaDbDriver) super.getDriver();
+ }
+
+ @Override
+ protected void connectSensors() {
+ super.connectSensors();
+ setAttribute(DB_URL, String.format("mysql://%s:%s/", getAttribute(HOSTNAME), getAttribute(MARIADB_PORT)));
+
+ /*
+ * TODO status gives us things like:
+ * Uptime: 2427 Threads: 1 Questions: 581 Slow queries: 0 Opens: 53 Flush tables: 1 Open tables: 35 Queries per second avg: 0.239
+ * So can extract lots of sensors from that.
+ */
+ Location machine = Iterables.get(getLocations(), 0, null);
+
+ if (machine instanceof SshMachineLocation) {
+ String cmd = getDriver().getStatusCmd();
+ feed = SshFeed.builder()
+ .entity(this)
+ .period(Duration.FIVE_SECONDS)
+ .machine((SshMachineLocation) machine)
+ .poll(new SshPollConfig<Boolean>(SERVICE_UP)
+ .command(cmd)
+ .setOnSuccess(true)
+ .setOnFailureOrException(false))
+ .poll(new SshPollConfig<Double>(QUERIES_PER_SECOND_FROM_MARIADB)
+ .command(cmd)
+ .onSuccess(new Function<SshPollValue, Double>() {
+ public Double apply(SshPollValue input) {
+ String q = Strings.getFirstWordAfter(input.getStdout(), "Queries per second avg:");
+ return (q == null) ? null : Double.parseDouble(q);
+ }})
+ .setOnFailureOrException(null) )
+ .build();
+ } else {
+ LOG.warn("Location(s) %s not an ssh-machine location, so not polling for status; setting serviceUp immediately", getLocations());
+ setAttribute(SERVICE_UP, true);
+ }
+ }
+
+ @Override
+ protected void disconnectSensors() {
+ if (feed != null) feed.stop();
+ }
+
+ public int getPort() {
+ return getAttribute(MARIADB_PORT);
+ }
+
+ public String getSocketUid() {
+ String result = getAttribute(MariaDbNode.SOCKET_UID);
+ if (Strings.isBlank(result))
+ setAttribute(MariaDbNode.SOCKET_UID, (result = Identifiers.makeRandomId(6)));
+ return result;
+ }
+
+ public String getPassword() {
+ String result = getAttribute(MariaDbNode.PASSWORD);
+ if (Strings.isBlank(result))
+ setAttribute(MariaDbNode.PASSWORD, (result = Identifiers.makeRandomId(6)));
+ return result;
+ }
+
+ @Override
+ public String getShortName() {
+ return "MariaDB";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e0516df/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbSshDriver.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbSshDriver.java b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbSshDriver.java
new file mode 100644
index 0000000..5c85903
--- /dev/null
+++ b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbSshDriver.java
@@ -0,0 +1,216 @@
+package brooklyn.entity.database.mariadb;
+
+import static brooklyn.util.GroovyJavaMethods.elvis;
+import static brooklyn.util.GroovyJavaMethods.truth;
+import static brooklyn.util.ssh.BashCommands.installPackage;
+import static brooklyn.util.ssh.BashCommands.ok;
+import static java.lang.String.format;
+
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.drivers.downloads.DownloadResolver;
+import brooklyn.entity.drivers.downloads.DownloadResolverManager;
+import brooklyn.location.OsDetails;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.management.ManagementContext;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.text.Strings;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * The SSH implementation of the {@link MariaDbDriver}.
+ */
+public class MariaDbSshDriver extends AbstractSoftwareProcessSshDriver implements MariaDbDriver {
+
+ public static final Logger log = LoggerFactory.getLogger(MariaDbSshDriver.class);
+
+ private String expandedInstallDir;
+
+ public MariaDbSshDriver(MariaDbNodeImpl entity, SshMachineLocation machine) {
+ super(entity, machine);
+ }
+
+ public String getOsTag() {
+ OsDetails os = getLocation().getOsDetails();
+ if (os == null) return "linux-i686";
+ if (os.isLinux()) return "linux-" + (os.is64bit() ? "x86_64" : "i686");
+ throw new UnsupportedOperationException("only support linux versions just now");
+ }
+
+ public String getDownloadParentDir() {
+ OsDetails os = getLocation().getOsDetails();
+ if (os == null) return "kvm-bintar-hardy-x86";
+ if (os.isLinux()) return "kvm-bintar-hardy-" + (os.is64bit() ? "amd64" : "x86");
+ throw new UnsupportedOperationException("only support linux versions just now");
+ }
+
+ public String getMirrorUrl() {
+ return entity.getConfig(MariaDbNode.MIRROR_URL);
+ }
+
+ public String getBasedir() {
+ return getExpandedInstallDir();
+ }
+
+ public String getDatadir() {
+ String result = entity.getConfig(MariaDbNode.DATA_DIR);
+ return (result == null) ? "." : result;
+ }
+
+ public String getInstallFilename() {
+ return String.format("mariadb-%s-%s.tar.gz", getVersion(), getOsTag());
+ }
+
+ private String getExpandedInstallDir() {
+ if (expandedInstallDir == null)
+ throw new IllegalStateException("'expandedInstallDir' is null; most likely install was not called");
+ return expandedInstallDir;
+ }
+
+ @Override
+ public void install() {
+ // mariadb-${version}-${driver.osTag}.tar.gz
+
+ ManagementContext managementContext = ((EntityInternal) entity).getManagementContext();
+ DownloadResolverManager downloadManager = managementContext.getEntityDownloadsManager();
+ DownloadResolver resolver = downloadManager.newDownloader(
+ this, ImmutableMap.of("filename", getInstallFilename()));
+ List<String> urls = resolver.getTargets();
+ String saveAs = resolver.getFilename();
+ expandedInstallDir = getInstallDir() + "/" + resolver.getUnpackedDirectoryName(format("mariadb-%s-%s", getVersion(), getOsTag()));
+
+ List<String> commands = new LinkedList<String>();
+ commands.add(BashCommands.INSTALL_TAR);
+ commands.add(BashCommands.INSTALL_CURL);
+
+ commands.add("echo installing extra packages");
+ commands.add(installPackage(ImmutableMap.of("yum", "libgcc_s.so.1"), null));
+ commands.add(installPackage(ImmutableMap.of("yum", "libaio.so.1 libncurses.so.5", "apt", "libaio1 libaio-dev"), null));
+ // these deps are needed on some OS versions but others don't need them so ignore failures (ok(...))
+ commands.add(ok(installPackage(ImmutableMap.of("yum", "libaio", "apt", "ia32-libs"), null)));
+ commands.add("echo finished installing extra packages");
+
+ commands.addAll(BashCommands.commandsToDownloadUrlsAs(urls, saveAs));
+ commands.add(format("tar xfvz %s", saveAs));
+
+ newScript(INSTALLING).
+ body.append(commands).execute();
+ }
+
+ public MariaDbNodeImpl getEntity() { return (MariaDbNodeImpl) super.getEntity(); }
+ public int getPort() { return getEntity().getPort(); }
+ public String getSocketUid() { return getEntity().getSocketUid(); }
+ public String getPassword() { return getEntity().getPassword(); }
+
+ @Override
+ public void customize() {
+ copyDatabaseCreationScript();
+ copyDatabaseConfigScript();
+
+ newScript(CUSTOMIZING).
+ updateTaskAndFailOnNonZeroResultCode().
+ body.append(
+ "chmod 600 my.cnf",
+ getBasedir()+"/scripts/mysql_install_db "+
+ "--basedir="+getBasedir()+" --datadir="+getDatadir()+" "+
+ "--defaults-file=my.cnf",
+ getBasedir()+"/bin/mysqld --defaults-file=my.cnf --user=`whoami` &", //--user=root needed if we are root
+ "export MYSQL_PID=$!",
+ "sleep 20",
+ "echo launching mysqladmin",
+ getBasedir()+"/bin/mysqladmin --defaults-file=my.cnf --password= password "+getPassword(),
+ "sleep 20",
+ "echo launching mysql creation script",
+ getBasedir()+"/bin/mysql --defaults-file=my.cnf < creation-script.cnf",
+ "echo terminating mysql on customization complete",
+ "kill $MYSQL_PID"
+ ).execute();
+ }
+
+ private void copyDatabaseCreationScript() {
+ newScript(CUSTOMIZING).
+ body.append("echo copying creation script").
+ execute(); //create the directory
+
+ Reader creationScript;
+ String url = entity.getConfig(MariaDbNode.CREATION_SCRIPT_URL);
+ if (!Strings.isBlank(url))
+ creationScript = new InputStreamReader(new ResourceUtils(entity).getResourceFromUrl(url));
+ else creationScript =
+ new StringReader((String) elvis(entity.getConfig(MariaDbNode.CREATION_SCRIPT_CONTENTS), ""));
+ getMachine().copyTo(creationScript, getRunDir() + "/creation-script.cnf");
+ }
+
+ private void copyDatabaseConfigScript() {
+ newScript(CUSTOMIZING).
+ body.append("echo copying server config script").
+ execute(); //create the directory
+
+ String configScriptContents = processTemplate(entity.getAttribute(MariaDbNode.TEMPLATE_CONFIGURATION_URL));
+ Reader configContents = new StringReader(configScriptContents);
+
+ getMachine().copyTo(configContents, getRunDir() + "/my.cnf");
+ }
+
+ public String getMariaDbServerOptionsString() {
+ Map<String, Object> options = entity.getConfig(MariaDbNode.MARIADB_SERVER_CONF);
+ if (!truth(options)) return "";
+ String result = "";
+ for (Map.Entry<String, Object> entry : options.entrySet()) {
+ if("".equals(entry.getValue())){
+ result += ""+entry.getKey()+"\n";
+ }else{
+ result += ""+entry.getKey()+" = "+entry.getValue()+"\n";
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public void launch() {
+ newScript(MutableMap.of("usePidFile", true), LAUNCHING).
+ updateTaskAndFailOnNonZeroResultCode().
+ body.append(
+ format("nohup %s/bin/mysqld --defaults-file=my.cnf --user=`whoami` > out.log 2> err.log < /dev/null &", getBasedir())
+ ).execute();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return newScript(MutableMap.of("usePidFile", false), CHECK_RUNNING)
+ .body.append(getStatusCmd())
+ .execute() == 0;
+ }
+
+ @Override
+ public void stop() {
+ newScript(MutableMap.of("usePidFile", true), STOPPING).execute();
+ }
+
+ @Override
+ public void kill() {
+ newScript(MutableMap.of("usePidFile", true), KILLING).execute();
+ }
+
+ @Override
+ public String getStatusCmd() {
+ // TODO Is this very bad, to include the password in the command being executed
+ // (so is in `ps` listing temporarily, and in .bash_history)
+ return format("%s/bin/mysqladmin --user=%s --password=%s --socket=/tmp/mysql.sock.%s.%s status",
+ getExpandedInstallDir(), "root", getPassword(), getSocketUid(), getPort());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e0516df/software/database/src/main/resources/brooklyn/entity/database/mariadb/my.cnf
----------------------------------------------------------------------
diff --git a/software/database/src/main/resources/brooklyn/entity/database/mariadb/my.cnf b/software/database/src/main/resources/brooklyn/entity/database/mariadb/my.cnf
new file mode 100644
index 0000000..f9946b1
--- /dev/null
+++ b/software/database/src/main/resources/brooklyn/entity/database/mariadb/my.cnf
@@ -0,0 +1,19 @@
+[client]
+port = ${driver.port?c}
+socket = /tmp/mysql.sock.${entity.socketUid}.${driver.port?c}
+user = root
+password = ${entity.password}
+
+# Here follows entries for some specific programs
+
+# The MariaDB server, which (confusingly) uses MySQL terminology for backwards compatibility
+[mysqld]
+port = ${driver.port?c}
+socket = /tmp/mysql.sock.${entity.socketUid}.${driver.port?c}
+basedir = ${driver.basedir}
+datadir = ${driver.datadir}
+bind-address = 0.0.0.0
+# skip-networking
+
+# Custom configuration options
+${driver.mariaDbServerOptionsString}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e0516df/software/database/src/main/resources/mariadb-logo-180x119.png
----------------------------------------------------------------------
diff --git a/software/database/src/main/resources/mariadb-logo-180x119.png b/software/database/src/main/resources/mariadb-logo-180x119.png
new file mode 100644
index 0000000..cea7acd
Binary files /dev/null and b/software/database/src/main/resources/mariadb-logo-180x119.png differ
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e0516df/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbIntegrationTest.groovy
----------------------------------------------------------------------
diff --git a/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbIntegrationTest.groovy b/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbIntegrationTest.groovy
new file mode 100644
index 0000000..7ca7986
--- /dev/null
+++ b/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbIntegrationTest.groovy
@@ -0,0 +1,105 @@
+package brooklyn.entity.database.mariadb
+
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.testng.Assert
+import org.testng.annotations.AfterMethod
+import org.testng.annotations.BeforeMethod
+import org.testng.annotations.Test
+
+import brooklyn.config.BrooklynProperties
+import brooklyn.entity.basic.ApplicationBuilder
+import brooklyn.entity.basic.Entities
+import brooklyn.entity.database.VogellaExampleAccess
+import brooklyn.entity.proxying.EntitySpec
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation
+import brooklyn.management.ManagementContext
+import brooklyn.management.internal.LocalManagementContext
+import brooklyn.test.entity.TestApplication
+import brooklyn.util.collections.MutableMap
+import brooklyn.util.text.Strings
+
+/**
+ * Runs a slightly modified version of the popular Vogella MySQL tutorial,
+ * from
+ * http://www.vogella.de/articles/MySQLJava/article.html
+ */
+public class MariaDbIntegrationTest {
+
+ public static final Logger log = LoggerFactory.getLogger(MariaDbIntegrationTest.class);
+
+ protected BrooklynProperties brooklynProperties;
+ protected ManagementContext managementContext;
+ protected TestApplication tapp;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() {
+ brooklynProperties = BrooklynProperties.Factory.newDefault();
+ managementContext = new LocalManagementContext(brooklynProperties);
+ tapp = ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void ensureShutDown() {
+ if (tapp != null) {
+ Entities.destroyAll(tapp.getManagementContext());
+ tapp = null;
+ }
+ }
+
+ // can start in AWS by running this -- or use brooklyn CLI/REST for most clouds, or programmatic/config for set of fixed IP machines
+ static String hostname = java.net.InetAddress.getLocalHost().getHostName()
+
+ //from http://www.vogella.de/articles/MySQLJava/article.html
+ public static final String CREATION_SCRIPT = """
+CREATE DATABASE feedback;
+CREATE USER 'sqluser'@'localhost' IDENTIFIED BY 'sqluserpw';
+GRANT USAGE ON *.* TO 'sqluser'@'localhost';
+GRANT ALL PRIVILEGES ON feedback.* TO 'sqluser'@'localhost';
+CREATE USER 'sqluser'@'%' IDENTIFIED BY 'sqluserpw';
+GRANT USAGE ON *.* TO 'sqluser'@'%';
+GRANT ALL PRIVILEGES ON feedback.* TO 'sqluser'@'%';
+CREATE USER 'sqluser'@'$hostname' IDENTIFIED BY 'sqluserpw';
+GRANT USAGE ON *.* TO 'sqluser'@'$hostname';
+GRANT ALL PRIVILEGES ON feedback.* TO 'sqluser'@'$hostname';
+FLUSH PRIVILEGES;
+USE feedback;
+CREATE TABLE COMMENTS (
+ id INT NOT NULL AUTO_INCREMENT,
+ MYUSER VARCHAR(30) NOT NULL,
+ EMAIL VARCHAR(30),
+ WEBPAGE VARCHAR(100) NOT NULL,
+ DATUM DATE NOT NULL,
+ SUMMARY VARCHAR(40) NOT NULL,
+ COMMENTS VARCHAR(400) NOT NULL,
+ PRIMARY KEY (ID)
+ );
+
+INSERT INTO COMMENTS values (default, 'lars', 'myemail@gmail.com','http://www.vogella.de', '2009-09-14 10:33:11', 'Summary','My first comment' );
+""";
+
+ @Test(groups = ["Integration"])
+ public void test_localhost() throws Exception {
+ String dataDir = "/tmp/mariadb-data-" + Strings.makeRandomId(8);
+ MariaDbNode mariadb = tapp.createAndManageChild(EntitySpec.create(MariaDbNode.class)
+ .configure(MariaDbNode.MARIADB_SERVER_CONF, MutableMap.of("skip-name-resolve",""))
+ .configure("creationScriptContents", CREATION_SCRIPT)
+ .configure("dataDir", dataDir));
+ LocalhostMachineProvisioningLocation location = new LocalhostMachineProvisioningLocation();
+
+ tapp.start([location]);
+ log.info("MariaDB started");
+
+ new VogellaExampleAccess("com.mysql.jdbc.Driver", mariadb.getAttribute(MariaDbNode.DB_URL)).readModifyAndRevertDataBase();
+
+ log.info("Ran vogella MySQL example -- SUCCESS");
+
+ // Ensure the data directory was successfully overridden.
+ File dataDirFile = new File(dataDir);
+ File mariadbSubdirFile = new File(dataDirFile, "mysql");
+ Assert.assertTrue(mariadbSubdirFile.exists());
+
+ // Clean up.
+ dataDirFile.deleteDir();
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e0516df/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbLiveEc2Test.java
----------------------------------------------------------------------
diff --git a/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbLiveEc2Test.java b/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbLiveEc2Test.java
new file mode 100644
index 0000000..a7199a0
--- /dev/null
+++ b/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbLiveEc2Test.java
@@ -0,0 +1,27 @@
+package brooklyn.entity.database.mariadb;
+
+import org.testng.annotations.Test;
+
+import brooklyn.entity.AbstractEc2LiveTest;
+import brooklyn.entity.database.VogellaExampleAccess;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.Location;
+
+import com.google.common.collect.ImmutableList;
+
+@Test(groups = { "Live" })
+public class MariaDbLiveEc2Test extends AbstractEc2LiveTest {
+
+ @Override
+ protected void doTest(Location loc) throws Exception {
+
+ MariaDbNode mariadb = app.createAndManageChild(EntitySpec.create(MariaDbNode.class)
+ .configure("creationScriptContents", MariaDbIntegrationTest.CREATION_SCRIPT));
+
+ app.start(ImmutableList.of(loc));
+
+ new VogellaExampleAccess("com.mysql.jdbc.Driver", mariadb.getAttribute(MariaDbNode.DB_URL)).readModifyAndRevertDataBase();
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/2e0516df/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbLiveRackspaceTest.java
----------------------------------------------------------------------
diff --git a/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbLiveRackspaceTest.java b/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbLiveRackspaceTest.java
new file mode 100644
index 0000000..3196b6e
--- /dev/null
+++ b/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbLiveRackspaceTest.java
@@ -0,0 +1,80 @@
+package brooklyn.entity.database.mariadb;
+
+import org.testng.annotations.Test;
+
+import brooklyn.entity.database.VogellaExampleAccess;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.location.jclouds.JcloudsLocation;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * The MariaDbLiveTest installs MariaDb on various operating systems like Ubuntu, CentOS, Red Hat etc. To make sure that
+ * MariaDb works like expected on these Operating Systems.
+ */
+public class MariaDbLiveRackspaceTest extends MariaDbIntegrationTest {
+ @Test(groups = {"Live"})
+ public void test_Debian_6() throws Exception {
+ test("Debian 6");
+ }
+
+ @Test(groups = {"Live"})
+ public void test_Ubuntu_10_0() throws Exception {
+ test("Ubuntu 10.0");
+ }
+
+ @Test(groups = {"Live"})
+ public void test_Ubuntu_11_0() throws Exception {
+ test("Ubuntu 11.0");
+ }
+
+ @Test(groups = {"Live", "Live-sanity"})
+ public void test_Ubuntu_12_0() throws Exception {
+ test("Ubuntu 12.0");
+ }
+
+ @Test(groups = {"Live"})
+ public void test_CentOS_6_0() throws Exception {
+ test("CentOS 6.0");
+ }
+
+ @Test(groups = {"Live"})
+ public void test_CentOS_5_6() throws Exception {
+ test("CentOS 5.6");
+ }
+
+ @Test(groups = {"Live"})
+ public void test_Fedora_17() throws Exception {
+ test("Fedora 17");
+ }
+
+ @Test(groups = {"Live"})
+ public void test_Red_Hat_Enterprise_Linux_6() throws Exception {
+ test("Red Hat Enterprise Linux 6");
+ }
+
+ @Test(groups = {"Live"})
+ public void test_localhost() throws Exception {
+ super.test_localhost();
+ }
+
+ public void test(String osRegex) throws Exception {
+ MariaDbNode mariadb = tapp.createAndManageChild(EntitySpec.create(MariaDbNode.class)
+ .configure("creationScriptContents", CREATION_SCRIPT));
+
+ brooklynProperties.put("brooklyn.jclouds.rackspace-cloudservers-uk.image-name-regex", osRegex);
+ brooklynProperties.remove("brooklyn.jclouds.rackspace-cloudservers-uk.image-id");
+ brooklynProperties.put("inboundPorts", "22, 3306");
+ JcloudsLocation jcloudsLocation = (JcloudsLocation) managementContext.getLocationRegistry().resolve("jclouds:rackspace-cloudservers-uk");
+
+ tapp.start(ImmutableList.of(jcloudsLocation));
+
+ SshMachineLocation l = (SshMachineLocation) mariadb.getLocations().iterator().next();
+ //hack to get the port for mysql open; is the inbounds property not respected on rackspace??
+ l.exec(ImmutableList.of("iptables -I INPUT -p tcp --dport 3306 -j ACCEPT"));
+
+ new VogellaExampleAccess("com.mysql.jdbc.Driver", mariadb.getAttribute(MariaDbNode.DB_URL)).readModifyAndRevertDataBase();
+
+ }
+}