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 <[email protected]>
Authored: Mon Oct 28 14:01:46 2013 +0000
Committer: Alasdair Hodge <[email protected]>
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', 
'[email protected]','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();
+       
+    } 
+}

Reply via email to