From 5100557238e2c65467b5264f6e673b9e17bb4dde Mon Sep 17 00:00:00 2001 From: Andreas Bader Date: Wed, 27 Jan 2016 21:08:42 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 46 + GenerateRandomCSV.py | 6 + MakeDebianIso.py | 163 ++ MakeDebianQcow2.py | 92 + MakeSpecialDiagram.py | 372 ++++ ProcessYcsbLog.py | 1565 +++++++++++++++++ README.md | 132 ++ RunWorkload.py | 491 ++++++ SetupVsphere.py | 523 ++++++ TSDBBench.py | 435 +++++ Util.py | 191 ++ Vm.py | 155 ++ databases/__init__.py | 18 + databases/basicdb.py | 64 + databases/basicjdbc.py | 64 + databases/basickairosdb.py | 64 + databases/basicopentsdb.py | 64 + databases/blueflood_cl1_rf1.py | 75 + databases/blueflood_cl5_rf1.py | 80 + databases/blueflood_cl5_rf2.py | 80 + databases/blueflood_cl5_rf5.py | 80 + databases/druid_cl1_rf1.py | 78 + databases/druid_cl5_rf1.py | 87 + databases/druid_cl5_rf2.py | 90 + databases/druid_cl5_rf5.py | 90 + databases/influxdb_cl1_rf1.py | 70 + databases/influxdb_cl5_rf1.py | 81 + databases/influxdb_cl5_rf2.py | 81 + databases/influxdb_cl5_rf5.py | 81 + databases/kairosdb_cl1_rf1.py | 67 + databases/kairosdb_cl5_rf1.py | 78 + databases/kairosdb_cl5_rf2.py | 78 + databases/kairosdb_cl5_rf5.py | 78 + databases/kairosdb_h2_cl1_rf1.py | 64 + databases/monetdb_cl1_rf1.py | 75 + databases/mysql_cl1_rf1.py | 67 + databases/newts_cl1_rf1.py | 76 + databases/newts_cl5_rf1.py | 80 + databases/newts_cl5_rf2.py | 80 + databases/newts_cl5_rf5.py | 80 + databases/opentsdb_cl1_rf1.py | 74 + databases/opentsdb_cl5_rf1.py | 111 ++ databases/opentsdb_cl5_rf2.py | 111 ++ databases/opentsdb_cl5_rf5.py | 111 ++ databases/postgres_cl1_rf1.py | 69 + databases/rhombus_cl1_rf1.py | 68 + databases/rhombus_cl5_rf1.py | 72 + databases/rhombus_cl5_rf2.py | 72 + databases/rhombus_cl5_rf5.py | 72 + dummy.box | Bin 0 -> 156 bytes hooks/post-merge | 16 + hooks/pre-commit | 20 + preseed-openstack.cfg | 167 ++ preseed-vsphere-controlvm.cfg | 259 +++ preseed-vsphere.cfg | 136 ++ template.html | 59 + template_multi.html | 62 + vagrant_files/basic/blueflood.rb | 9 + vagrant_files/basic/cassandra.rb | 10 + vagrant_files/basic/change_hostname.rb | 3 + vagrant_files/basic/copy_files.rb | 4 + vagrant_files/basic/druid.rb | 13 + vagrant_files/basic/druid_mysql.rb | 4 + vagrant_files/basic/hadoop.rb | 6 + vagrant_files/basic/hadoop_cluster.rb | 6 + vagrant_files/basic/hadoop_master.rb | 6 + vagrant_files/basic/hbase.rb | 8 + vagrant_files/basic/hbase_cluster.rb | 6 + vagrant_files/basic/hbase_cluster_repl1.rb | 4 + vagrant_files/basic/hbase_cluster_repl2.rb | 4 + vagrant_files/basic/hbase_cluster_repl5.rb | 4 + vagrant_files/basic/hbase_lzo_build.rb | 9 + vagrant_files/basic/hbase_lzo_copy.rb | 5 + vagrant_files/basic/hbase_solo.rb | 4 + vagrant_files/basic/influxdb.rb | 16 + vagrant_files/basic/influxdb_cluster.rb | 7 + vagrant_files/basic/kairosdb.rb | 9 + vagrant_files/basic/kairosdb_repl1.rb | 4 + vagrant_files/basic/kairosdb_repl2.rb | 4 + vagrant_files/basic/kairosdb_repl5.rb | 4 + vagrant_files/basic/monetdb.rb | 10 + vagrant_files/basic/mysql.rb | 8 + vagrant_files/basic/newts.rb | 18 + vagrant_files/basic/opentsdb.rb | 7 + vagrant_files/basic/opentsdb_cluster.rb | 4 + vagrant_files/basic/sleep_5.rb | 3 + vagrant_files/basic/update.rb | 3 + vagrant_files/basic/zookeeper.rb | 4 + .../blueflood_cl1_rf1_0.vagrant | 16 + .../files/blueflood-log4j.properties | 11 + .../blueflood_cl1_rf1/files/blueflood.conf | 59 + .../blueflood_cl1_rf1/files/blueflood.service | 13 + .../files/blueflood_cassandra.cli | 30 + .../blueflood_cl5_rf1_0.vagrant | 16 + .../blueflood_cl5_rf1_1.vagrant | 15 + .../blueflood_cl5_rf1_2.vagrant | 15 + .../blueflood_cl5_rf1_3.vagrant | 15 + .../blueflood_cl5_rf1_4.vagrant | 15 + .../files/blueflood-log4j.properties | 11 + .../blueflood_cl5_rf1/files/blueflood.conf | 59 + .../blueflood_cl5_rf1/files/blueflood.service | 13 + .../files/blueflood_cassandra.cli | 30 + .../blueflood_cl5_rf2_0.vagrant | 16 + .../blueflood_cl5_rf2_1.vagrant | 15 + .../blueflood_cl5_rf2_2.vagrant | 15 + .../blueflood_cl5_rf2_3.vagrant | 15 + .../blueflood_cl5_rf2_4.vagrant | 15 + .../files/blueflood-log4j.properties | 11 + .../blueflood_cl5_rf2/files/blueflood.conf | 59 + .../blueflood_cl5_rf2/files/blueflood.service | 13 + .../files/blueflood_cassandra.cli | 30 + .../blueflood_cl5_rf5_0.vagrant | 16 + .../blueflood_cl5_rf5_1.vagrant | 15 + .../blueflood_cl5_rf5_2.vagrant | 15 + .../blueflood_cl5_rf5_3.vagrant | 15 + .../blueflood_cl5_rf5_4.vagrant | 15 + .../files/blueflood-log4j.properties | 11 + .../blueflood_cl5_rf5/files/blueflood.conf | 59 + .../blueflood_cl5_rf5/files/blueflood.service | 13 + .../files/blueflood_cassandra.cli | 30 + .../druid_cl1_rf1/druid_cl1_rf1_0.vagrant | 18 + .../config/_common/common.runtime.properties | 34 + .../files/config/broker/runtime.properties | 5 + .../config/coordinator/runtime.properties | 3 + .../config/historical/runtime.properties | 10 + .../config/middleManager/runtime.properties | 18 + .../files/config/overlord/runtime.properties | 6 + .../druid_cl1_rf1/files/druid.service | 12 + .../druid_cl1_rf1/files/druid_broker.service | 13 + .../files/druid_coordinator.service | 14 + .../files/druid_historical.service | 14 + .../files/druid_middlemanager.service | 13 + .../files/druid_overlord.service | 13 + .../druid_cl5_rf1/druid_cl5_rf1_0.vagrant | 18 + .../druid_cl5_rf1/druid_cl5_rf1_1.vagrant | 15 + .../druid_cl5_rf1/druid_cl5_rf1_2.vagrant | 15 + .../druid_cl5_rf1/druid_cl5_rf1_3.vagrant | 15 + .../druid_cl5_rf1/druid_cl5_rf1_4.vagrant | 15 + .../config/_common/common.runtime.properties | 34 + .../files/config/broker/runtime.properties | 5 + .../config/coordinator/runtime.properties | 5 + .../config/historical/runtime.properties | 10 + .../config/middleManager/runtime.properties | 18 + .../files/config/overlord/runtime.properties | 6 + .../druid_cl5_rf1/files/druid_broker.service | 11 + .../files/druid_coordinator.service | 13 + .../files/druid_historical.service | 11 + .../files/druid_middlemanager.service | 11 + .../files/druid_overlord.service | 11 + .../druid_cl5_rf2/druid_cl5_rf2_0.vagrant | 18 + .../druid_cl5_rf2/druid_cl5_rf2_1.vagrant | 15 + .../druid_cl5_rf2/druid_cl5_rf2_2.vagrant | 15 + .../druid_cl5_rf2/druid_cl5_rf2_3.vagrant | 15 + .../druid_cl5_rf2/druid_cl5_rf2_4.vagrant | 15 + .../config/_common/common.runtime.properties | 34 + .../files/config/broker/runtime.properties | 5 + .../config/coordinator/runtime.properties | 5 + .../config/historical/runtime.properties | 10 + .../config/middleManager/runtime.properties | 18 + .../files/config/overlord/runtime.properties | 6 + .../druid_cl5_rf2/files/druid_broker.service | 11 + .../files/druid_coordinator.service | 13 + .../files/druid_historical.service | 11 + .../files/druid_middlemanager.service | 11 + .../files/druid_overlord.service | 11 + .../druid_cl5_rf5/druid_cl5_rf5_0.vagrant | 18 + .../druid_cl5_rf5/druid_cl5_rf5_1.vagrant | 15 + .../druid_cl5_rf5/druid_cl5_rf5_2.vagrant | 15 + .../druid_cl5_rf5/druid_cl5_rf5_3.vagrant | 15 + .../druid_cl5_rf5/druid_cl5_rf5_4.vagrant | 15 + .../config/_common/common.runtime.properties | 34 + .../files/config/broker/runtime.properties | 5 + .../config/coordinator/runtime.properties | 5 + .../config/historical/runtime.properties | 10 + .../config/middleManager/runtime.properties | 18 + .../files/config/overlord/runtime.properties | 6 + .../druid_cl5_rf5/files/druid_broker.service | 11 + .../files/druid_coordinator.service | 13 + .../files/druid_historical.service | 11 + .../files/druid_middlemanager.service | 11 + .../files/druid_overlord.service | 11 + vagrant_files/generator/files/RunWorkload.py | 491 ++++++ .../generator/files/databases/__init__.py | 18 + .../generator/files/databases/basicdb.py | 64 + .../generator/files/databases/basicjdbc.py | 64 + .../files/databases/basickairosdb.py | 64 + .../files/databases/basicopentsdb.py | 64 + .../generator/files/databases/blueflood1.py | 75 + .../generator/files/databases/blueflood2.py | 80 + .../generator/files/databases/blueflood3.py | 80 + .../generator/files/databases/blueflood4.py | 80 + .../files/databases/blueflood_cl1.py | 75 + .../files/databases/blueflood_cl1_rf1.py | 75 + .../files/databases/blueflood_cl5_rf1.py | 80 + .../files/databases/blueflood_cl5_rf2.py | 80 + .../files/databases/blueflood_cl5_rf5.py | 80 + .../generator/files/databases/druid1.py | 78 + .../generator/files/databases/druid2.py | 90 + .../generator/files/databases/druid3.py | 87 + .../files/databases/druid_cl1_rf1.py | 78 + .../files/databases/druid_cl5_rf1.py | 87 + .../files/databases/druid_cl5_rf2.py | 90 + .../files/databases/druid_cl5_rf5.py | 90 + .../generator/files/databases/influxdb1.py | 70 + .../generator/files/databases/influxdb2.py | 81 + .../generator/files/databases/influxdb3.py | 81 + .../generator/files/databases/influxdb4.py | 81 + .../files/databases/influxdb_cl1_rf1.py | 70 + .../files/databases/influxdb_cl5_rf1.py | 81 + .../files/databases/influxdb_cl5_rf2.py | 81 + .../files/databases/influxdb_cl5_rf5.py | 81 + .../generator/files/databases/kairosdb1.py | 64 + .../generator/files/databases/kairosdb2.py | 67 + .../generator/files/databases/kairosdb3.py | 78 + .../generator/files/databases/kairosdb4.py | 78 + .../generator/files/databases/kairosdb5.py | 78 + .../files/databases/kairosdb_cl1_rf1.py | 67 + .../files/databases/kairosdb_cl5_rf1.py | 78 + .../files/databases/kairosdb_cl5_rf2.py | 78 + .../files/databases/kairosdb_cl5_rf5.py | 78 + .../files/databases/kairosdb_h2_cl1_rf1.py | 64 + .../files/databases/monetdb_cl1_rf1.py | 75 + .../generator/files/databases/mysql.py | 66 + .../generator/files/databases/mysql1.py | 67 + .../files/databases/mysql_cl1_rf1.py | 67 + .../generator/files/databases/newts1.py | 76 + .../generator/files/databases/newts2.py | 80 + .../generator/files/databases/newts3.py | 80 + .../generator/files/databases/newts4.py | 80 + .../files/databases/newts_cl1_rf1.py | 76 + .../files/databases/newts_cl5_rf1.py | 80 + .../files/databases/newts_cl5_rf2.py | 80 + .../files/databases/newts_cl5_rf5.py | 80 + .../generator/files/databases/opentsdb.py | 95 + .../generator/files/databases/opentsdb1.py | 74 + .../generator/files/databases/opentsdb2.py | 111 ++ .../generator/files/databases/opentsdb3.py | 111 ++ .../generator/files/databases/opentsdb4.py | 111 ++ .../files/databases/opentsdb_cl1_rf1.py | 74 + .../files/databases/opentsdb_cl5_rf1.py | 111 ++ .../files/databases/opentsdb_cl5_rf2.py | 111 ++ .../files/databases/opentsdb_cl5_rf5.py | 111 ++ .../generator/files/databases/postgres.py | 68 + .../generator/files/databases/postgres1.py | 69 + .../files/databases/postgres_cl1_rf1.py | 69 + .../generator/files/databases/rhombus1.py | 68 + .../generator/files/databases/rhombus2.py | 72 + .../generator/files/databases/rhombus3.py | 72 + .../generator/files/databases/rhombus4.py | 72 + .../files/databases/rhombus_cl1_rf1.py | 68 + .../files/databases/rhombus_cl5_rf1.py | 72 + .../files/databases/rhombus_cl5_rf2.py | 72 + .../files/databases/rhombus_cl5_rf5.py | 72 + .../generator/files/rhombus_repl1.json | 46 + .../generator/files/rhombus_repl2.json | 46 + .../generator/files/rhombus_repl5.json | 46 + vagrant_files/generator/generator_0.vagrant | 27 + .../influxdb_cl1_rf1_0.vagrant | 15 + .../influxdb_cl5_rf1_0.vagrant | 18 + .../influxdb_cl5_rf1_1.vagrant | 18 + .../influxdb_cl5_rf1_2.vagrant | 18 + .../influxdb_cl5_rf1_3.vagrant | 19 + .../influxdb_cl5_rf1_4.vagrant | 19 + .../influxdb_cl5_rf2_0.vagrant | 18 + .../influxdb_cl5_rf2_1.vagrant | 18 + .../influxdb_cl5_rf2_2.vagrant | 18 + .../influxdb_cl5_rf2_3.vagrant | 19 + .../influxdb_cl5_rf2_4.vagrant | 19 + .../influxdb_cl5_rf5_0.vagrant | 18 + .../influxdb_cl5_rf5_1.vagrant | 18 + .../influxdb_cl5_rf5_2.vagrant | 18 + .../influxdb_cl5_rf5_3.vagrant | 19 + .../influxdb_cl5_rf5_4.vagrant | 19 + .../files/kairos_cassandra.cli | 4 + .../kairosdb_cl1_rf1_0.vagrant | 34 + .../files/kairos_cassandra.cli | 4 + .../kairosdb_cl5_rf1_0.vagrant | 19 + .../kairosdb_cl5_rf1_1.vagrant | 17 + .../kairosdb_cl5_rf1_2.vagrant | 17 + .../kairosdb_cl5_rf1_3.vagrant | 17 + .../kairosdb_cl5_rf1_4.vagrant | 17 + .../files/kairos_cassandra.cli | 4 + .../kairosdb_cl5_rf2_0.vagrant | 19 + .../kairosdb_cl5_rf2_1.vagrant | 17 + .../kairosdb_cl5_rf2_2.vagrant | 17 + .../kairosdb_cl5_rf2_3.vagrant | 17 + .../kairosdb_cl5_rf2_4.vagrant | 17 + .../files/kairos_cassandra.cli | 4 + .../kairosdb_cl5_rf5_0.vagrant | 19 + .../kairosdb_cl5_rf5_1.vagrant | 17 + .../kairosdb_cl5_rf5_2.vagrant | 17 + .../kairosdb_cl5_rf5_3.vagrant | 17 + .../kairosdb_cl5_rf5_4.vagrant | 17 + .../kairosdb_h2_cl1_rf1_0.vagrant | 25 + .../files/create_table.monetdb | 25 + .../monetdb_cl1_rf1/monetdb_cl1_rf1_0.vagrant | 15 + .../mysql_cl1_rf1/files/create_table.mysql | 16 + .../mysql_cl1_rf1/mysql_cl1_rf1_0.vagrant | 23 + .../newts_cl1_rf1/files/newts.service | 10 + .../newts_cl1_rf1/files/newts_cassandra.cli | 1 + .../newts_cl1_rf1/newts_cl1_rf1_0.vagrant | 16 + .../newts_cl5_rf1/files/newts.service | 10 + .../newts_cl5_rf1/files/newts_cassandra.cli | 1 + .../newts_cl5_rf1/newts_cl5_rf1_0.vagrant | 17 + .../newts_cl5_rf1/newts_cl5_rf1_1.vagrant | 16 + .../newts_cl5_rf1/newts_cl5_rf1_2.vagrant | 16 + .../newts_cl5_rf1/newts_cl5_rf1_3.vagrant | 16 + .../newts_cl5_rf1/newts_cl5_rf1_4.vagrant | 16 + .../newts_cl5_rf2/files/newts.service | 10 + .../newts_cl5_rf2/files/newts_cassandra.cli | 1 + .../newts_cl5_rf2/newts_cl5_rf2_0.vagrant | 17 + .../newts_cl5_rf2/newts_cl5_rf2_1.vagrant | 16 + .../newts_cl5_rf2/newts_cl5_rf2_2.vagrant | 16 + .../newts_cl5_rf2/newts_cl5_rf2_3.vagrant | 16 + .../newts_cl5_rf2/newts_cl5_rf2_4.vagrant | 16 + .../newts_cl5_rf5/files/newts.service | 10 + .../newts_cl5_rf5/files/newts_cassandra.cli | 1 + .../newts_cl5_rf5/newts_cl5_rf5_0.vagrant | 17 + .../newts_cl5_rf5/newts_cl5_rf5_1.vagrant | 16 + .../newts_cl5_rf5/newts_cl5_rf5_2.vagrant | 16 + .../newts_cl5_rf5/newts_cl5_rf5_3.vagrant | 16 + .../newts_cl5_rf5/newts_cl5_rf5_4.vagrant | 16 + .../files/lzo/hadoop-lzo-0.4.15.tar.gz | Bin 0 -> 156334 bytes .../opentsdb_cl1_rf1_0.vagrant | 20 + .../files/lzo/hadoop-lzo-0.4.15.tar.gz | Bin 0 -> 156334 bytes .../opentsdb_cl5_rf1_0.vagrant | 24 + .../opentsdb_cl5_rf1_1.vagrant | 23 + .../opentsdb_cl5_rf1_2.vagrant | 23 + .../opentsdb_cl5_rf1_3.vagrant | 23 + .../opentsdb_cl5_rf1_4.vagrant | 23 + .../files/lzo/hadoop-lzo-0.4.15.tar.gz | Bin 0 -> 156334 bytes .../opentsdb_cl5_rf2_0.vagrant | 24 + .../opentsdb_cl5_rf2_1.vagrant | 23 + .../opentsdb_cl5_rf2_2.vagrant | 23 + .../opentsdb_cl5_rf2_3.vagrant | 23 + .../opentsdb_cl5_rf2_4.vagrant | 23 + .../files/lzo/hadoop-lzo-0.4.15.tar.gz | Bin 0 -> 156334 bytes .../opentsdb_cl5_rf5_0.vagrant | 29 + .../opentsdb_cl5_rf5_1.vagrant | 23 + .../opentsdb_cl5_rf5_2.vagrant | 23 + .../opentsdb_cl5_rf5_3.vagrant | 23 + .../opentsdb_cl5_rf5_4.vagrant | 23 + .../postgres_cl1_rf1/files/create_table.psql | 15 + .../postgres_cl1_rf1_0.vagrant | 24 + .../rhombus_cl1_rf1/rhombus_cl1_rf1_0.vagrant | 15 + .../rhombus_cl5_rf1/rhombus_cl5_rf1_0.vagrant | 15 + .../rhombus_cl5_rf1/rhombus_cl5_rf1_1.vagrant | 15 + .../rhombus_cl5_rf1/rhombus_cl5_rf1_2.vagrant | 15 + .../rhombus_cl5_rf1/rhombus_cl5_rf1_3.vagrant | 15 + .../rhombus_cl5_rf1/rhombus_cl5_rf1_4.vagrant | 15 + .../rhombus_cl5_rf2/rhombus_cl5_rf2_0.vagrant | 15 + .../rhombus_cl5_rf2/rhombus_cl5_rf2_1.vagrant | 15 + .../rhombus_cl5_rf2/rhombus_cl5_rf2_2.vagrant | 15 + .../rhombus_cl5_rf2/rhombus_cl5_rf2_3.vagrant | 15 + .../rhombus_cl5_rf2/rhombus_cl5_rf2_4.vagrant | 15 + .../rhombus_cl5_rf5/rhombus_cl5_rf5_0.vagrant | 15 + .../rhombus_cl5_rf5/rhombus_cl5_rf5_1.vagrant | 15 + .../rhombus_cl5_rf5/rhombus_cl5_rf5_2.vagrant | 15 + .../rhombus_cl5_rf5/rhombus_cl5_rf5_3.vagrant | 15 + .../rhombus_cl5_rf5/rhombus_cl5_rf5_4.vagrant | 15 + vagrant_files/vagrantconf.rb | 30 + vagrant_files/vagrantconf_db.rb | 8 + vagrant_files/vagrantconf_gen.rb | 8 + 363 files changed, 17322 insertions(+) create mode 100644 .gitignore create mode 100755 GenerateRandomCSV.py create mode 100755 MakeDebianIso.py create mode 100755 MakeDebianQcow2.py create mode 100755 MakeSpecialDiagram.py create mode 100755 ProcessYcsbLog.py create mode 100644 README.md create mode 100755 RunWorkload.py create mode 100755 SetupVsphere.py create mode 100755 TSDBBench.py create mode 100644 Util.py create mode 100644 Vm.py create mode 100644 databases/__init__.py create mode 100644 databases/basicdb.py create mode 100644 databases/basicjdbc.py create mode 100644 databases/basickairosdb.py create mode 100644 databases/basicopentsdb.py create mode 100644 databases/blueflood_cl1_rf1.py create mode 100644 databases/blueflood_cl5_rf1.py create mode 100644 databases/blueflood_cl5_rf2.py create mode 100644 databases/blueflood_cl5_rf5.py create mode 100644 databases/druid_cl1_rf1.py create mode 100644 databases/druid_cl5_rf1.py create mode 100644 databases/druid_cl5_rf2.py create mode 100644 databases/druid_cl5_rf5.py create mode 100644 databases/influxdb_cl1_rf1.py create mode 100644 databases/influxdb_cl5_rf1.py create mode 100644 databases/influxdb_cl5_rf2.py create mode 100644 databases/influxdb_cl5_rf5.py create mode 100644 databases/kairosdb_cl1_rf1.py create mode 100644 databases/kairosdb_cl5_rf1.py create mode 100644 databases/kairosdb_cl5_rf2.py create mode 100644 databases/kairosdb_cl5_rf5.py create mode 100644 databases/kairosdb_h2_cl1_rf1.py create mode 100644 databases/monetdb_cl1_rf1.py create mode 100644 databases/mysql_cl1_rf1.py create mode 100644 databases/newts_cl1_rf1.py create mode 100644 databases/newts_cl5_rf1.py create mode 100644 databases/newts_cl5_rf2.py create mode 100644 databases/newts_cl5_rf5.py create mode 100644 databases/opentsdb_cl1_rf1.py create mode 100644 databases/opentsdb_cl5_rf1.py create mode 100644 databases/opentsdb_cl5_rf2.py create mode 100644 databases/opentsdb_cl5_rf5.py create mode 100644 databases/postgres_cl1_rf1.py create mode 100644 databases/rhombus_cl1_rf1.py create mode 100644 databases/rhombus_cl5_rf1.py create mode 100644 databases/rhombus_cl5_rf2.py create mode 100644 databases/rhombus_cl5_rf5.py create mode 100644 dummy.box create mode 100755 hooks/post-merge create mode 100755 hooks/pre-commit create mode 100644 preseed-openstack.cfg create mode 100644 preseed-vsphere-controlvm.cfg create mode 100644 preseed-vsphere.cfg create mode 100644 template.html create mode 100644 template_multi.html create mode 100644 vagrant_files/basic/blueflood.rb create mode 100644 vagrant_files/basic/cassandra.rb create mode 100644 vagrant_files/basic/change_hostname.rb create mode 100644 vagrant_files/basic/copy_files.rb create mode 100644 vagrant_files/basic/druid.rb create mode 100644 vagrant_files/basic/druid_mysql.rb create mode 100644 vagrant_files/basic/hadoop.rb create mode 100644 vagrant_files/basic/hadoop_cluster.rb create mode 100644 vagrant_files/basic/hadoop_master.rb create mode 100644 vagrant_files/basic/hbase.rb create mode 100644 vagrant_files/basic/hbase_cluster.rb create mode 100644 vagrant_files/basic/hbase_cluster_repl1.rb create mode 100644 vagrant_files/basic/hbase_cluster_repl2.rb create mode 100644 vagrant_files/basic/hbase_cluster_repl5.rb create mode 100644 vagrant_files/basic/hbase_lzo_build.rb create mode 100644 vagrant_files/basic/hbase_lzo_copy.rb create mode 100644 vagrant_files/basic/hbase_solo.rb create mode 100644 vagrant_files/basic/influxdb.rb create mode 100644 vagrant_files/basic/influxdb_cluster.rb create mode 100644 vagrant_files/basic/kairosdb.rb create mode 100644 vagrant_files/basic/kairosdb_repl1.rb create mode 100644 vagrant_files/basic/kairosdb_repl2.rb create mode 100644 vagrant_files/basic/kairosdb_repl5.rb create mode 100644 vagrant_files/basic/monetdb.rb create mode 100644 vagrant_files/basic/mysql.rb create mode 100644 vagrant_files/basic/newts.rb create mode 100644 vagrant_files/basic/opentsdb.rb create mode 100644 vagrant_files/basic/opentsdb_cluster.rb create mode 100644 vagrant_files/basic/sleep_5.rb create mode 100644 vagrant_files/basic/update.rb create mode 100644 vagrant_files/basic/zookeeper.rb create mode 100644 vagrant_files/blueflood_cl1_rf1/blueflood_cl1_rf1_0.vagrant create mode 100644 vagrant_files/blueflood_cl1_rf1/files/blueflood-log4j.properties create mode 100644 vagrant_files/blueflood_cl1_rf1/files/blueflood.conf create mode 100644 vagrant_files/blueflood_cl1_rf1/files/blueflood.service create mode 100644 vagrant_files/blueflood_cl1_rf1/files/blueflood_cassandra.cli create mode 100644 vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_0.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_1.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_2.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_3.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_4.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf1/files/blueflood-log4j.properties create mode 100644 vagrant_files/blueflood_cl5_rf1/files/blueflood.conf create mode 100644 vagrant_files/blueflood_cl5_rf1/files/blueflood.service create mode 100644 vagrant_files/blueflood_cl5_rf1/files/blueflood_cassandra.cli create mode 100644 vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_0.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_1.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_2.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_3.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_4.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf2/files/blueflood-log4j.properties create mode 100644 vagrant_files/blueflood_cl5_rf2/files/blueflood.conf create mode 100644 vagrant_files/blueflood_cl5_rf2/files/blueflood.service create mode 100644 vagrant_files/blueflood_cl5_rf2/files/blueflood_cassandra.cli create mode 100644 vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_0.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_1.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_2.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_3.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_4.vagrant create mode 100644 vagrant_files/blueflood_cl5_rf5/files/blueflood-log4j.properties create mode 100644 vagrant_files/blueflood_cl5_rf5/files/blueflood.conf create mode 100644 vagrant_files/blueflood_cl5_rf5/files/blueflood.service create mode 100644 vagrant_files/blueflood_cl5_rf5/files/blueflood_cassandra.cli create mode 100644 vagrant_files/druid_cl1_rf1/druid_cl1_rf1_0.vagrant create mode 100644 vagrant_files/druid_cl1_rf1/files/config/_common/common.runtime.properties create mode 100644 vagrant_files/druid_cl1_rf1/files/config/broker/runtime.properties create mode 100644 vagrant_files/druid_cl1_rf1/files/config/coordinator/runtime.properties create mode 100644 vagrant_files/druid_cl1_rf1/files/config/historical/runtime.properties create mode 100644 vagrant_files/druid_cl1_rf1/files/config/middleManager/runtime.properties create mode 100644 vagrant_files/druid_cl1_rf1/files/config/overlord/runtime.properties create mode 100644 vagrant_files/druid_cl1_rf1/files/druid.service create mode 100644 vagrant_files/druid_cl1_rf1/files/druid_broker.service create mode 100644 vagrant_files/druid_cl1_rf1/files/druid_coordinator.service create mode 100644 vagrant_files/druid_cl1_rf1/files/druid_historical.service create mode 100644 vagrant_files/druid_cl1_rf1/files/druid_middlemanager.service create mode 100644 vagrant_files/druid_cl1_rf1/files/druid_overlord.service create mode 100644 vagrant_files/druid_cl5_rf1/druid_cl5_rf1_0.vagrant create mode 100644 vagrant_files/druid_cl5_rf1/druid_cl5_rf1_1.vagrant create mode 100644 vagrant_files/druid_cl5_rf1/druid_cl5_rf1_2.vagrant create mode 100644 vagrant_files/druid_cl5_rf1/druid_cl5_rf1_3.vagrant create mode 100644 vagrant_files/druid_cl5_rf1/druid_cl5_rf1_4.vagrant create mode 100644 vagrant_files/druid_cl5_rf1/files/config/_common/common.runtime.properties create mode 100644 vagrant_files/druid_cl5_rf1/files/config/broker/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf1/files/config/coordinator/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf1/files/config/historical/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf1/files/config/middleManager/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf1/files/config/overlord/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf1/files/druid_broker.service create mode 100644 vagrant_files/druid_cl5_rf1/files/druid_coordinator.service create mode 100644 vagrant_files/druid_cl5_rf1/files/druid_historical.service create mode 100644 vagrant_files/druid_cl5_rf1/files/druid_middlemanager.service create mode 100644 vagrant_files/druid_cl5_rf1/files/druid_overlord.service create mode 100644 vagrant_files/druid_cl5_rf2/druid_cl5_rf2_0.vagrant create mode 100644 vagrant_files/druid_cl5_rf2/druid_cl5_rf2_1.vagrant create mode 100644 vagrant_files/druid_cl5_rf2/druid_cl5_rf2_2.vagrant create mode 100644 vagrant_files/druid_cl5_rf2/druid_cl5_rf2_3.vagrant create mode 100644 vagrant_files/druid_cl5_rf2/druid_cl5_rf2_4.vagrant create mode 100644 vagrant_files/druid_cl5_rf2/files/config/_common/common.runtime.properties create mode 100644 vagrant_files/druid_cl5_rf2/files/config/broker/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf2/files/config/coordinator/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf2/files/config/historical/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf2/files/config/middleManager/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf2/files/config/overlord/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf2/files/druid_broker.service create mode 100644 vagrant_files/druid_cl5_rf2/files/druid_coordinator.service create mode 100644 vagrant_files/druid_cl5_rf2/files/druid_historical.service create mode 100644 vagrant_files/druid_cl5_rf2/files/druid_middlemanager.service create mode 100644 vagrant_files/druid_cl5_rf2/files/druid_overlord.service create mode 100644 vagrant_files/druid_cl5_rf5/druid_cl5_rf5_0.vagrant create mode 100644 vagrant_files/druid_cl5_rf5/druid_cl5_rf5_1.vagrant create mode 100644 vagrant_files/druid_cl5_rf5/druid_cl5_rf5_2.vagrant create mode 100644 vagrant_files/druid_cl5_rf5/druid_cl5_rf5_3.vagrant create mode 100644 vagrant_files/druid_cl5_rf5/druid_cl5_rf5_4.vagrant create mode 100644 vagrant_files/druid_cl5_rf5/files/config/_common/common.runtime.properties create mode 100644 vagrant_files/druid_cl5_rf5/files/config/broker/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf5/files/config/coordinator/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf5/files/config/historical/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf5/files/config/middleManager/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf5/files/config/overlord/runtime.properties create mode 100644 vagrant_files/druid_cl5_rf5/files/druid_broker.service create mode 100644 vagrant_files/druid_cl5_rf5/files/druid_coordinator.service create mode 100644 vagrant_files/druid_cl5_rf5/files/druid_historical.service create mode 100644 vagrant_files/druid_cl5_rf5/files/druid_middlemanager.service create mode 100644 vagrant_files/druid_cl5_rf5/files/druid_overlord.service create mode 100755 vagrant_files/generator/files/RunWorkload.py create mode 100644 vagrant_files/generator/files/databases/__init__.py create mode 100644 vagrant_files/generator/files/databases/basicdb.py create mode 100644 vagrant_files/generator/files/databases/basicjdbc.py create mode 100644 vagrant_files/generator/files/databases/basickairosdb.py create mode 100644 vagrant_files/generator/files/databases/basicopentsdb.py create mode 100644 vagrant_files/generator/files/databases/blueflood1.py create mode 100644 vagrant_files/generator/files/databases/blueflood2.py create mode 100644 vagrant_files/generator/files/databases/blueflood3.py create mode 100644 vagrant_files/generator/files/databases/blueflood4.py create mode 100644 vagrant_files/generator/files/databases/blueflood_cl1.py create mode 100644 vagrant_files/generator/files/databases/blueflood_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/blueflood_cl5_rf1.py create mode 100644 vagrant_files/generator/files/databases/blueflood_cl5_rf2.py create mode 100644 vagrant_files/generator/files/databases/blueflood_cl5_rf5.py create mode 100644 vagrant_files/generator/files/databases/druid1.py create mode 100644 vagrant_files/generator/files/databases/druid2.py create mode 100644 vagrant_files/generator/files/databases/druid3.py create mode 100644 vagrant_files/generator/files/databases/druid_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/druid_cl5_rf1.py create mode 100644 vagrant_files/generator/files/databases/druid_cl5_rf2.py create mode 100644 vagrant_files/generator/files/databases/druid_cl5_rf5.py create mode 100644 vagrant_files/generator/files/databases/influxdb1.py create mode 100644 vagrant_files/generator/files/databases/influxdb2.py create mode 100644 vagrant_files/generator/files/databases/influxdb3.py create mode 100644 vagrant_files/generator/files/databases/influxdb4.py create mode 100644 vagrant_files/generator/files/databases/influxdb_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/influxdb_cl5_rf1.py create mode 100644 vagrant_files/generator/files/databases/influxdb_cl5_rf2.py create mode 100644 vagrant_files/generator/files/databases/influxdb_cl5_rf5.py create mode 100644 vagrant_files/generator/files/databases/kairosdb1.py create mode 100644 vagrant_files/generator/files/databases/kairosdb2.py create mode 100644 vagrant_files/generator/files/databases/kairosdb3.py create mode 100644 vagrant_files/generator/files/databases/kairosdb4.py create mode 100644 vagrant_files/generator/files/databases/kairosdb5.py create mode 100644 vagrant_files/generator/files/databases/kairosdb_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/kairosdb_cl5_rf1.py create mode 100644 vagrant_files/generator/files/databases/kairosdb_cl5_rf2.py create mode 100644 vagrant_files/generator/files/databases/kairosdb_cl5_rf5.py create mode 100644 vagrant_files/generator/files/databases/kairosdb_h2_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/monetdb_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/mysql.py create mode 100644 vagrant_files/generator/files/databases/mysql1.py create mode 100644 vagrant_files/generator/files/databases/mysql_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/newts1.py create mode 100644 vagrant_files/generator/files/databases/newts2.py create mode 100644 vagrant_files/generator/files/databases/newts3.py create mode 100644 vagrant_files/generator/files/databases/newts4.py create mode 100644 vagrant_files/generator/files/databases/newts_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/newts_cl5_rf1.py create mode 100644 vagrant_files/generator/files/databases/newts_cl5_rf2.py create mode 100644 vagrant_files/generator/files/databases/newts_cl5_rf5.py create mode 100644 vagrant_files/generator/files/databases/opentsdb.py create mode 100644 vagrant_files/generator/files/databases/opentsdb1.py create mode 100644 vagrant_files/generator/files/databases/opentsdb2.py create mode 100644 vagrant_files/generator/files/databases/opentsdb3.py create mode 100644 vagrant_files/generator/files/databases/opentsdb4.py create mode 100644 vagrant_files/generator/files/databases/opentsdb_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/opentsdb_cl5_rf1.py create mode 100644 vagrant_files/generator/files/databases/opentsdb_cl5_rf2.py create mode 100644 vagrant_files/generator/files/databases/opentsdb_cl5_rf5.py create mode 100644 vagrant_files/generator/files/databases/postgres.py create mode 100644 vagrant_files/generator/files/databases/postgres1.py create mode 100644 vagrant_files/generator/files/databases/postgres_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/rhombus1.py create mode 100644 vagrant_files/generator/files/databases/rhombus2.py create mode 100644 vagrant_files/generator/files/databases/rhombus3.py create mode 100644 vagrant_files/generator/files/databases/rhombus4.py create mode 100644 vagrant_files/generator/files/databases/rhombus_cl1_rf1.py create mode 100644 vagrant_files/generator/files/databases/rhombus_cl5_rf1.py create mode 100644 vagrant_files/generator/files/databases/rhombus_cl5_rf2.py create mode 100644 vagrant_files/generator/files/databases/rhombus_cl5_rf5.py create mode 100644 vagrant_files/generator/files/rhombus_repl1.json create mode 100644 vagrant_files/generator/files/rhombus_repl2.json create mode 100644 vagrant_files/generator/files/rhombus_repl5.json create mode 100644 vagrant_files/generator/generator_0.vagrant create mode 100644 vagrant_files/influxdb_cl1_rf1/influxdb_cl1_rf1_0.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_0.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_1.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_2.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_3.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_4.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_0.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_1.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_2.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_3.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_4.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_0.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_1.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_2.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_3.vagrant create mode 100644 vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_4.vagrant create mode 100644 vagrant_files/kairosdb_cl1_rf1/files/kairos_cassandra.cli create mode 100644 vagrant_files/kairosdb_cl1_rf1/kairosdb_cl1_rf1_0.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf1/files/kairos_cassandra.cli create mode 100644 vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_0.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_1.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_2.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_3.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_4.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf2/files/kairos_cassandra.cli create mode 100644 vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_0.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_1.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_2.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_3.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_4.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf5/files/kairos_cassandra.cli create mode 100644 vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_0.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_1.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_2.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_3.vagrant create mode 100644 vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_4.vagrant create mode 100644 vagrant_files/kairosdb_h2_cl1_rf1/kairosdb_h2_cl1_rf1_0.vagrant create mode 100644 vagrant_files/monetdb_cl1_rf1/files/create_table.monetdb create mode 100644 vagrant_files/monetdb_cl1_rf1/monetdb_cl1_rf1_0.vagrant create mode 100644 vagrant_files/mysql_cl1_rf1/files/create_table.mysql create mode 100644 vagrant_files/mysql_cl1_rf1/mysql_cl1_rf1_0.vagrant create mode 100644 vagrant_files/newts_cl1_rf1/files/newts.service create mode 100644 vagrant_files/newts_cl1_rf1/files/newts_cassandra.cli create mode 100644 vagrant_files/newts_cl1_rf1/newts_cl1_rf1_0.vagrant create mode 100644 vagrant_files/newts_cl5_rf1/files/newts.service create mode 100644 vagrant_files/newts_cl5_rf1/files/newts_cassandra.cli create mode 100644 vagrant_files/newts_cl5_rf1/newts_cl5_rf1_0.vagrant create mode 100644 vagrant_files/newts_cl5_rf1/newts_cl5_rf1_1.vagrant create mode 100644 vagrant_files/newts_cl5_rf1/newts_cl5_rf1_2.vagrant create mode 100644 vagrant_files/newts_cl5_rf1/newts_cl5_rf1_3.vagrant create mode 100644 vagrant_files/newts_cl5_rf1/newts_cl5_rf1_4.vagrant create mode 100644 vagrant_files/newts_cl5_rf2/files/newts.service create mode 100644 vagrant_files/newts_cl5_rf2/files/newts_cassandra.cli create mode 100644 vagrant_files/newts_cl5_rf2/newts_cl5_rf2_0.vagrant create mode 100644 vagrant_files/newts_cl5_rf2/newts_cl5_rf2_1.vagrant create mode 100644 vagrant_files/newts_cl5_rf2/newts_cl5_rf2_2.vagrant create mode 100644 vagrant_files/newts_cl5_rf2/newts_cl5_rf2_3.vagrant create mode 100644 vagrant_files/newts_cl5_rf2/newts_cl5_rf2_4.vagrant create mode 100644 vagrant_files/newts_cl5_rf5/files/newts.service create mode 100644 vagrant_files/newts_cl5_rf5/files/newts_cassandra.cli create mode 100644 vagrant_files/newts_cl5_rf5/newts_cl5_rf5_0.vagrant create mode 100644 vagrant_files/newts_cl5_rf5/newts_cl5_rf5_1.vagrant create mode 100644 vagrant_files/newts_cl5_rf5/newts_cl5_rf5_2.vagrant create mode 100644 vagrant_files/newts_cl5_rf5/newts_cl5_rf5_3.vagrant create mode 100644 vagrant_files/newts_cl5_rf5/newts_cl5_rf5_4.vagrant create mode 100644 vagrant_files/opentsdb_cl1_rf1/files/lzo/hadoop-lzo-0.4.15.tar.gz create mode 100644 vagrant_files/opentsdb_cl1_rf1/opentsdb_cl1_rf1_0.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf1/files/lzo/hadoop-lzo-0.4.15.tar.gz create mode 100644 vagrant_files/opentsdb_cl5_rf1/opentsdb_cl5_rf1_0.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf1/opentsdb_cl5_rf1_1.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf1/opentsdb_cl5_rf1_2.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf1/opentsdb_cl5_rf1_3.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf1/opentsdb_cl5_rf1_4.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf2/files/lzo/hadoop-lzo-0.4.15.tar.gz create mode 100644 vagrant_files/opentsdb_cl5_rf2/opentsdb_cl5_rf2_0.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf2/opentsdb_cl5_rf2_1.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf2/opentsdb_cl5_rf2_2.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf2/opentsdb_cl5_rf2_3.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf2/opentsdb_cl5_rf2_4.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf5/files/lzo/hadoop-lzo-0.4.15.tar.gz create mode 100644 vagrant_files/opentsdb_cl5_rf5/opentsdb_cl5_rf5_0.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf5/opentsdb_cl5_rf5_1.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf5/opentsdb_cl5_rf5_2.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf5/opentsdb_cl5_rf5_3.vagrant create mode 100644 vagrant_files/opentsdb_cl5_rf5/opentsdb_cl5_rf5_4.vagrant create mode 100644 vagrant_files/postgres_cl1_rf1/files/create_table.psql create mode 100644 vagrant_files/postgres_cl1_rf1/postgres_cl1_rf1_0.vagrant create mode 100644 vagrant_files/rhombus_cl1_rf1/rhombus_cl1_rf1_0.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_0.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_1.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_2.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_3.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_4.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_0.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_1.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_2.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_3.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_4.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_0.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_1.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_2.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_3.vagrant create mode 100644 vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_4.vagrant create mode 100644 vagrant_files/vagrantconf.rb create mode 100644 vagrant_files/vagrantconf_db.rb create mode 100644 vagrant_files/vagrantconf_gen.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f566754 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Git ignore File +.* +*.pyc +*/*.pyc +*/*/*.pyc +*/*/*/*.pyc +*/*/*/*/*.pyc +*/__pycache__ +*/*/__pycache__ +*/*/*/__pycache__ +!/.gitignore +*.directory +*/*.directory +*/*/*.directory +*/*/*/*.directory +*/*/*/*/*.directory +data.csv +*/data.csv +*/*/data.csv +*/*/*/data.csv +*.log +*/*.log +*/*/*.log +*/*/*/*.log +*/*/*/*/*.log +*.out +*/*.out +*/*/*.out +*/*/*/*.out +*/*/*/*/*.out +*.ydc +*/*.ydc +*/*/*.ydc +*/*/*/*.ydc +*/*/*/*/*.ydc +*.html +*/*.html +*/*/*.html +*/*/*/*.html +*/*/*/*/*.html +*.pdf +*/*.pdf +*/*/*.pdf +*/*/*/*.pdf +*/*/*/*/*.pdf +*.idea \ No newline at end of file diff --git a/GenerateRandomCSV.py b/GenerateRandomCSV.py new file mode 100755 index 0000000..b50632f --- /dev/null +++ b/GenerateRandomCSV.py @@ -0,0 +1,6 @@ +#!/usr/bin/python2 +import sys +from random import randint +print "FIELD1,FIELD2,FIELD3,FIELD4,FIELD5,FIELD6,FIELD7,FIELD8,FIELD9,FIELD10" +for i in range(0,1000000): + print "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s" %(randint(0,sys.maxint),randint(0,sys.maxint),randint(0,sys.maxint),randint(0,sys.maxint),randint(0,sys.maxint),randint(0,sys.maxint),randint(0,sys.maxint),randint(0,sys.maxint),randint(0,sys.maxint),randint(0,sys.maxint),) diff --git a/MakeDebianIso.py b/MakeDebianIso.py new file mode 100755 index 0000000..426f238 --- /dev/null +++ b/MakeDebianIso.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +import argparse +import logging +import Util +import os +import shutil +from fabric.api import * + +outputFileNameSuffix="-autoinstall" + +neededTools = ["which", "sed","7z", "genisoimage", "gzip", "find", "cpio", "md5sum"] + +# Configure ArgumentParser +parser = argparse.ArgumentParser(prog="MakeDebianIso.py",version=__version__,description="Bla", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="") +parser.add_argument("-t", "--tmpfolder", metavar="TMPFOLDER", required=True, help="path to tmp space (> 5 gb)") +parser.add_argument("-i", "--isofile", metavar="ISOFILE", required=True, help="path to Debian Iso") +parser.add_argument("-f", "--outputfolder", metavar="OUTPUTFOLDER", required=True, help="path to outputfolder (will be created if not existent)") +parser.add_argument("-p", "--presseedfile", metavar="PRESEEDFILE", required=True, help="path to preseedfile") +parser.add_argument("-o", "--overwrite", action="store_true", help="overwrite if ISO is existing") +parser.add_argument("-l", "--log", action='store_true', help="Be more verbose, log vagrant output.") +args = parser.parse_args() + +# Configure Logging +logLevel = logging.WARN +if args.log: + logLevel = logging.DEBUG +logging.basicConfig(level=logLevel) +logger = logging.getLogger(__name__) + +# Check ob alle Tools da sind +for tool in neededTools: + with settings(warn_only=True), hide('output','running','warnings'): + ret=local("which '%s'" %(tool)) + if ret.return_code != 0: + logger.error("'%s' not found, please install." %(tool)) + exit(-1) + +if not (Util.check_file_exists(args.presseedfile) and Util.check_file_readable(args.presseedfile)): + logger.error("Preseedfile %s does not exist or is not readable." %(args.presseedfile)) + exit(-1) + +if not (Util.check_file_exists(args.isofile) and Util.check_file_readable(args.isofile)): + logger.error("Isofile %s does not exist or is not readable." %(args.isofile)) + exit(-1) + +if not Util.check_folder(args.outputfolder,logger,False,True): + if not Util.create_folder(args.outputfolder) or not Util.check_folder(args.outputfolder,logger): + logger.error("Can't create %s." %(args.outputfolder)) + exit(-1) + +if not Util.check_folder(args.tmpfolder,logger,False,True): + if not Util.create_folder(args.tmpfolder) or not Util.check_folder(args.tmpfolder,logger): + logger.error("Can't create %s." %(args.tmpfolder)) + exit(-1) +else: + Util.delete_folder(args.tmpfolder,logger) + if not Util.create_folder(args.tmpfolder) or not Util.check_folder(args.tmpfolder,logger): + logger.error("Can't create %s." %(args.tmpfolder)) + exit(-1) + +isoFileName=os.path.basename(args.isofile) +isoFileBase="default" +if len(os.path.splitext(args.isofile)) > 0: + isoFileBase=os.path.splitext(isoFileName)[0] +isoFileExt=".iso" +if len(os.path.splitext(args.isofile)) > 1: + isoFileExt=os.path.splitext(isoFileName)[1] +preseedSuffix="" +if len(os.path.splitext(os.path.basename(args.presseedfile))[0].split("-")) > 1: + for suffix in os.path.splitext(os.path.basename(args.presseedfile))[0].split("-")[1:]: + preseedSuffix += "-%s" %(suffix) +newIsoFileName="%s%s%s%s" %(isoFileBase,preseedSuffix,outputFileNameSuffix,isoFileExt) +isoPath=os.path.join(args.tmpfolder,isoFileName) + +if Util.check_file_exists(os.path.join(args.outputfolder,newIsoFileName)): + if args.overwrite: + if not Util.delete_file(os.path.join(args.outputfolder,newIsoFileName),logger): + logger.error("Error while deleting %s." %(os.path.join(args.outputfolder,newIsoFileName))) + exit(-1) + else: + logger.error("Outputfile %s does exist." %(os.path.join(args.outputfolder,newIsoFileName))) + exit(-1) + +# Copy Iso to tmpfolder +try: + shutil.copy(args.isofile, isoPath) +except Exception, e: + logger.error("Can't copy %s to %s." %(args.isofile,args.tmpfolder), exc_info=True) + exit(-1) + +# Unpack it with 7z +with lcd(args.tmpfolder), settings(warn_only=True), hide('output','running','warnings'): + ret=local("7z x '%s'" %(isoFileName), capture=True) + if not ret.succeeded: + logger.error("Can't unpack %s. Error: %s" %(isoPath,ret.stderr)) + exit(-1) + +# Delete ISO +if not Util.delete_file(isoPath, logger): + logger.error("Can't delete %s." %(isoPath)) + exit(-1) + +# mkdir irmod, unzip initrd.gz +if not Util.create_folder(os.path.join(args.tmpfolder,"irmod")): + logger.error("Can't create %s." %(os.path.join(args.tmpfolder,"irmod"))) + exit(-1) +with lcd(os.path.join(args.tmpfolder,"irmod")), settings(warn_only=True), hide('output','running','warnings'): + ret=local("gzip -d < ../install.amd/initrd.gz | cpio --extract --verbose --make-directories --no-absolute-filenames") + if ret.return_code != 2: + logger.error("Can't unpack %s. Error: %s" %(os.path.join(args.tmpfolder,"install.amd/initrd.gz"),ret.stderr)) + exit(-1) + +# Copy Pressed file in place +if not Util.copy_file(args.presseedfile, os.path.join(args.tmpfolder,"irmod","preseed.cfg"),logger): + logger.error("Can't copy %s to %s." %(args.presseedfile, os.path.join(args.tmpfolder,"irmod","preseed.cfg"))) + exit(-1) + +# Pack & Compress it again +with lcd(os.path.join(args.tmpfolder,"irmod")), settings(warn_only=True), hide('output','running','warnings'): + ret=local("find . | cpio -H newc --create --verbose | gzip -9 > ../install.amd/initrd.gz") + if not ret.succeeded: + logger.error("Can't pack %s. Error: %s" %(os.path.join(args.tmpfolder,"install.amd/initrd.gz"),ret.stderr)) + exit(-1) + +# Delete irmod +if not Util.delete_folder(os.path.join(args.tmpfolder,"irmod"),logger): + logger.error("Can't delete %s." %(os.path.join(args.tmpfolder,"irmod"))) + exit(-1) + +# Running sed + generating md5sum + genisoimage +with lcd(args.tmpfolder), settings(warn_only=True), hide('output','running','warnings'): + ret=local("sed -i \"s/timeout 0/timeout 2/g\" isolinux/isolinux.cfg") + if not ret.succeeded: + logger.error("Error while sed run on %s. Error: %s" %(os.path.join(args.tmpfolder,"isolinux/isolinux.cfg"),ret.stderr)) + exit(-1) + ret=local("sed -i \"s/quiet/ipv6.disable=1 quiet/g\" isolinux/txt.cfg") + if not ret.succeeded: + logger.error("Error while sed run on %s. Error: %s" %(os.path.join(args.tmpfolder,"isolinux/txt.cfg"),ret.stderr)) + exit(-1) + ret=local("md5sum `find -follow -type f` > md5sum.txt") + if not ret.succeeded: + logger.error("Error while md5sum+find run. Error: %s" %(ret.stderr)) + exit(-1) + ret=local("genisoimage -o \"%s\" -r -J -no-emul-boot -boot-load-size 4 -boot-info-table -b isolinux/isolinux.bin -c isolinux/boot.cat ." %(os.path.join(args.tmpfolder,newIsoFileName))) + if not ret.succeeded: + logger.error("Error while genisoimage run. Error: %s" %(ret.stderr)) + exit(-1) + +# Copy Iso, delete tmpfolder +if os.path.join(args.tmpfolder,newIsoFileName) != os.path.join(args.outputfolder,newIsoFileName): + if not Util.copy_file(os.path.join(args.tmpfolder,newIsoFileName),os.path.join(args.outputfolder,newIsoFileName),logger): + logger.error("Could not copy %s to %s." %(os.path.join(args.tmpfolder,newIsoFileName),os.path.join(args.outputfolder,newIsoFileName))) + exit(-1) +if not Util.delete_folder(args.tmpfolder,logger): + logger.error("Can't delete %s." %(args.tmpfolder)) + exit(-1) +logger.info("Done.") +exit(0) \ No newline at end of file diff --git a/MakeDebianQcow2.py b/MakeDebianQcow2.py new file mode 100755 index 0000000..4fd8b8d --- /dev/null +++ b/MakeDebianQcow2.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +import argparse +import logging +import Util +import os +import shutil +from fabric.api import * + +outputFileNameSuffix="-autoinstall" + +neededTools = ["which", "qemu-img","kvm"] + +# Configure ArgumentParser +parser = argparse.ArgumentParser(prog="MakeDebianQcow2.py",version=__version__,description="Bla", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="") +parser.add_argument("-i", "--isofile", metavar="ISOFILE", required=True, help="path to Debian Autoinstall Iso") +parser.add_argument("-f", "--outputfolder", metavar="OUTPUTFOLDER", required=True, help="path to outputfolder (will be created if not existent) (> 5 gb)") +parser.add_argument("-g", "--graphic", action="store_true", help="show graphic output, normally -nographic is used. Useful if you don't use a preseeded iso.") +parser.add_argument("-o", "--overwrite", action="store_true", help="overwrite if QCOW2 File is existing") +parser.add_argument("-l", "--log", action='store_true', help="Be more verbose, log vagrant output.") +parser.add_argument("-s", "--size", metavar="SIZE", type=int, default=50, help="Size in Gigabyte (50 is default), e.g. 50 for 50G (will be compressed, Qcow2 file size will be much lesser!)") +args = parser.parse_args() + +# Configure Logging +logLevel = logging.WARN +if args.log: + logLevel = logging.DEBUG +logging.basicConfig(level=logLevel) +logger = logging.getLogger(__name__) + +# Check ob alle Tools da sind +for tool in neededTools: + with settings(warn_only=True), hide('output','running','warnings'): + ret=local("which '%s'" %(tool)) + if ret.return_code != 0: + logger.error("'%s' not found, please install." %(tool)) + exit(-1) + +if not (Util.check_file_exists(args.isofile) and Util.check_file_readable(args.isofile)): + logger.error("Isofile %s does not exist or is not readable." %(args.isofile)) + exit(-1) + +if not Util.check_folder(args.outputfolder,logger,False,True): + if not Util.create_folder(args.outputfolder) or not Util.check_folder(args.outputfolder,logger): + logger.error("Can't create %s." %(args.outputfolder)) + exit(-1) + +isoFileName=os.path.basename(args.isofile) +imgFileBase="default" +if len(os.path.splitext(args.isofile)) > 0: + imgFileBase=os.path.splitext(isoFileName)[0] +imgFileExtRaw=".img" +imgFileExtQcow2=".qcow2" +imgFileRaw="%s%s" %(imgFileBase,imgFileExtRaw) +imgFileQcow2="%s%s" %(imgFileBase, imgFileExtQcow2) + +for file in [imgFileRaw,imgFileQcow2]: + if Util.check_file_exists(os.path.join(args.outputfolder,file)): + if args.overwrite: + if not Util.delete_file(os.path.join(args.outputfolder,file),logger): + logger.error("Error while deleting %s." %(os.path.join(args.outputfolder,file))) + exit(-1) + else: + logger.error("Outputfile %s does exist." %(os.path.join(args.outputfolder,file))) + exit(-1) + +with lcd(os.path.join(args.outputfolder)), settings(warn_only=True), hide('output','running','warnings'): + ret=local("qemu-img create -f qcow2 \"%s\" %sG" %(imgFileRaw,args.size)) + if ret.return_code != 0: + logger.error("Can't create %s. Error: %s" %(os.path.join(args.outputfolder,imgFileRaw),ret.stderr)) + exit(-1) + graphic=" -nographic" + if args.graphic: + graphic="" + ret=local("kvm -hda \"%s\" -cdrom \"%s\" -m 2048 -smp 2%s" %(imgFileRaw,args.isofile,graphic)) + if ret.return_code != 0: + logger.error("Can't install %s on %s with kvm. Error: %s" %(args.isofile,os.path.join(args.outputfolder,imgFileRaw),ret.stderr)) + exit(-1) + # compat needed if NOT using an very old qemu-img! + ret=local("qemu-img convert -f qcow2 -c \"%s\" -o compat=0.10 -O qcow2 \"%s\"" %(imgFileRaw,imgFileQcow2)) + if ret.return_code != 0: + logger.error("Can't compress %s to %s. Error: %s" %(os.path.join(args.outputfolder,imgFileRaw),os.path.join(args.outputfolder,imgFileQcow2),ret.stderr)) + exit(-1) + +if not Util.delete_file(os.path.join(args.outputfolder,imgFileRaw), logger): + logger.error("Can't delete %s." %(os.path.join(args.outputfolder,imgFileRaw))) + exit(-1) +exit(0) \ No newline at end of file diff --git a/MakeSpecialDiagram.py b/MakeSpecialDiagram.py new file mode 100755 index 0000000..68efef0 --- /dev/null +++ b/MakeSpecialDiagram.py @@ -0,0 +1,372 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +import copy +import gzip +from dateutil import tz +import jinja2 +import logging +import argparse +import magic +import os +import re +import datetime +import locale +import cPickle +import bokeh.charts +import bokeh.io +from itertools import islice +import pdfkit +import pytz +import Util +import webcolors +import threading +import signal + +__author__ = 'Andreas Bader' +__version__ = "0.03" + +# Helpscript if you need a quick diagram! + +plotColorDict={"DEFAULT" : "blue", + "INSERT0" : "red", + "INSERT1" : "darkred", + "READ0" : "orange", + "READ1" : "darkorange", + "CLEAN0" : "green", + "CLEAN1" : "darkgreen", + "UPDATE0" : "purple", + "UPDATE1" : "darkpurple" + } + +defaultPlotColor=plotColorDict["DEFAULT"] +convertFromUsToMs = ["AverageLatency(us)", "MinLatency(us)", "MaxLatency(us)", "99thPercentileLatency(us)", "95thPercentileLatency(us)" ] + +def openCompressedFile(ycsbfile, dict, key, logger): + try: + file = gzip.open(ycsbfile,"r") + dict[key]=cPickle.load(file) + file.close() + except Exception, e: + logger.error("Can't open '%s'. Is it really a compressed .ydc file?" %(ycsbfile), exc_info=True) + os._exit(-1) + +def decompressFile(fileDict, newFileName,logger): + neededKeys = ["timeseries","granularity","description","bucket","startTime","startLoadTime","runtimeLoad", + "throughputLoad","description","endLoadTime","startRunTime","runtimeRun","throughputRun", + "description","endRunTime", "endTime", "spaceBegin", "blocks", "errors", "warnings", "exceptions"] + neededBlockKeys = ["Operations","LatencyList","MaxLatency(us)","MinLatency(us)","99thPercentileLatency(us)", + "95thPercentileLatency(us)", "AverageLatency(us)"] + # return not in this list, as CLEANUP blocks have no return + for key in neededKeys: + if key not in fileDict.keys(): + logger.error("'%s' is missing in ydc file, abort." %(key)) + return False + file = open("%s" % (newFileName), "w") + if "timeseries" in fileDict.keys(): + if fileDict["timeseries"]: + file.write("TIMESERIES: 1\n") + else: + file.write("TIMESERIES: 0\n") + if "granularity" in fileDict.keys(): + file.write("GRANULARITY: %s\n" %(fileDict["granularity"])) + if "dbDesc" in fileDict.keys(): + des=fileDict["dbDesc"] + if des[-1] == "\n": + des = des[:-1] + file.write("DESCRIPTION: %s\n" %(des)) + if "bucket" in fileDict.keys(): + file.write("BUCKET: %s\n" %(fileDict["bucket"])) + if "startTime" in fileDict.keys(): + file.write("START: %s: Start Test\n" %(fileDict["startTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "startLoadTime" in fileDict.keys(): + file.write("START: %s: Start Load\n" %(fileDict["startLoadTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "runtimeLoad" in fileDict.keys(): + file.write("[OVERALL], RunTime(ms), %s\n" %(fileDict["runtimeLoad"])) + if "throughputLoad" in fileDict.keys(): + file.write("[OVERALL], Throughput(ops/sec), %s\n" %(fileDict["throughputLoad"])) + ## load blocks + for key in ["CLEANUP", "INSERT" ]: + if key in fileDict["blocks"] and len(fileDict["blocks"][key]) > 0: + for key2 in neededBlockKeys: + if key2 not in fileDict["blocks"][key][0].keys(): + logger.error("'%s' is missing in ydc file block '%s'0, abort." %(key2, key)) + return False + if "Operations" in fileDict["blocks"][key][0].keys(): + file.write("[%s], Operations, %s\n" %(key,fileDict["blocks"][key][0]["Operations"])) + if "AverageLatency(us)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], AverageLatency(us), %s\n" %(key,fileDict["blocks"][key][0]["AverageLatency(us)"])) + if "MinLatency(us)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], MinLatency(us), %s\n" %(key,fileDict["blocks"][key][0]["MinLatency(us)"])) + if "MaxLatency(us)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], MaxLatency(us), %s\n" %(key,fileDict["blocks"][key][0]["MaxLatency(us)"])) + if "95thPercentileLatency(ms)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], 95thPercentileLatency(ms), %s\n" %(key,fileDict["blocks"][key][0]["95thPercentileLatency(ms)"])) + if "99thPercentileLatency(ms)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], 99thPercentileLatency(ms), %s\n" %(key,fileDict["blocks"][key][0]["99thPercentileLatency(ms)"])) + if "Return" in fileDict["blocks"][key][0].keys(): + for returnVal in fileDict["blocks"][key][0]["Return"]: + file.write("[%s], Return=%s, %s\n" %(key,returnVal[0],returnVal[1])) + if "LatencyList" in fileDict["blocks"][key][0].keys(): + for counter in range(0,len(fileDict["blocks"][key][0]["LatencyList"])-1): + file.write("[%s], %s, %s\n" %(key, counter, fileDict["blocks"][key][0]["LatencyList"][counter])) + file.write("[%s], >%s, %s\n" %(key, len(fileDict["blocks"][key][0]["LatencyList"])-1, fileDict["blocks"][key][0]["LatencyList"][-1])) + # block latency data + if "description" in fileDict.keys(): + des=fileDict["description"] + if des[-1] == "\n": + des = des[:-1] + file.write("[DESCRIPTION], %s\n" %(des)) + if "endLoadTime" in fileDict.keys(): + file.write("END: %s: End Load\n" %(fileDict["endLoadTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "startRunTime" in fileDict.keys(): + file.write("START: %s: Start Run\n" %(fileDict["startRunTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "runtimeRun" in fileDict.keys(): + file.write("[OVERALL], RunTime(ms), %s\n" %(fileDict["runtimeRun"])) + if "throughputRun" in fileDict.keys(): + file.write("[OVERALL], Throughput(ops/sec), %s\n" %(fileDict["throughputRun"])) + ## run blöcke + for key in ["CLEANUP", "INSERT", "READ", "UPDATE", "SCAN", "AVG", "SUM", "COUNT"]: + if key in fileDict["blocks"] and len(fileDict["blocks"][key]) > 0: + for index in range(0,len(fileDict["blocks"][key])): + if index == 0 and key in ["CLEANUP", "INSERT" ]: + # First Cleanup/Insert block is from load phase -> ignore it + continue + for key2 in neededBlockKeys: + if key2 not in fileDict["blocks"][key][index].keys(): + logger.error("'%s' is missing in ydc file block '%s'0, abort." %(key2, key)) + return False + if "Operations" in fileDict["blocks"][key][index].keys(): + file.write("[%s], Operations, %s\n" %(key,fileDict["blocks"][key][index]["Operations"])) + if "AverageLatency(us)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], AverageLatency(us), %s\n" %(key,fileDict["blocks"][key][index]["AverageLatency(us)"])) + if "MinLatency(us)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], MinLatency(us), %s\n" %(key,fileDict["blocks"][key][index]["MinLatency(us)"])) + if "MaxLatency(us)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], MaxLatency(us), %s\n" %(key,fileDict["blocks"][key][index]["MaxLatency(us)"])) + if "95thPercentileLatency(ms)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], 95thPercentileLatency(ms), %s\n" %(key,fileDict["blocks"][key][index]["95thPercentileLatency(ms)"])) + if "99thPercentileLatency(ms)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], 99thPercentileLatency(ms), %s\n" %(key,fileDict["blocks"][key][index]["99thPercentileLatency(ms)"])) + if "Return" in fileDict["blocks"][key][index].keys(): + for returnVal in fileDict["blocks"][key][index]["Return"]: + file.write("[%s], Return=%s, %s\n" %(key,returnVal[index],returnVal[1])) + if "LatencyList" in fileDict["blocks"][key][index].keys(): + for counter in range(0,len(fileDict["blocks"][key][index]["LatencyList"])-1): + file.write("[%s], %s, %s\n" %(key, counter, fileDict["blocks"][key][index]["LatencyList"][counter])) + file.write("[%s], >%s, %s\n" %(key, len(fileDict["blocks"][key][index]["LatencyList"])-1, fileDict["blocks"][key][index]["LatencyList"][-1])) + if "description" in fileDict.keys(): + des=fileDict["description"] + if des[-1] == "\n": + des = des[:-1] + file.write("[DESCRIPTION], %s\n" %(des)) + if "endRunTime" in fileDict.keys(): + file.write("END: %s: End Run\n" %(fileDict["endRunTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "endTime" in fileDict.keys(): + file.write("END: %s: End Test\n" %(fileDict["endTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "errors" in fileDict.keys(): + for line in fileDict["errors"]: + line2 = line + if line2[-1] == "\n": + line2=line2[:-1] + file.write("%s\n" %(line2)) + if "exceptions" in fileDict.keys(): + for line in fileDict["exceptions"]: + line2 = line + if line2[-1] == "\n": + line2=line2[:-1] + file.write("%s\n" %(line2)) + if "warnings" in fileDict.keys(): + for line in fileDict["warnings"]: + line2 = line + if line2[-1] == "\n": + line2=line2[:-1] + file.write("%s\n" %(line2)) + if "spaceBegin" in fileDict.keys() and "spaceBetween" in fileDict.keys() and "spaceEnd" in fileDict.keys(): + file.write("SPACE: %s %s %s\n" %(fileDict["spaceBegin"],fileDict["spaceBetween"],fileDict["spaceEnd"])) + file.flush() + file.close() + +# replaces bokeh.charts.Bar because it can't do logarithmic scale +def generate_bar_plot(dataDict, cat, legendPos, title, ylabel, xlabel, width, height, logger): + maxValue=0 + for dataKey in dataDict.keys(): + for dataPoint in dataDict[dataKey]: + if dataPoint >= maxValue: + try: + dataPointStr = str(dataPoint) + if "." in dataPointStr: + dataPointStr = dataPointStr.split(".")[0] + maxValue = 10**len(dataPointStr) + except: + logger.error("Can't convert '%s' to string. Can't generate bar plot." %(dataPoint)) + return None + if maxValue == 0: + logger.error("Maximum value is 0. Can't generate bar plot.") + return None + p = bokeh.plotting.figure(title=title, y_axis_type="log", x_range=cat, y_range=[0,maxValue], width=width, height=height) + dataLen = -1 + for dataKey in dataDict.keys(): + if dataLen == -1: + dataLen = len(dataDict[dataKey]) + else: + if dataLen != len(dataDict[dataKey]): + logger.error("Some dataLists in dataDict have different lengths. Can't generate bar plot.") + return None + if dataLen == -1: + logger.error("Can't find list length. Can't generate bar plot.") + return None + keyLen = float(len(dataDict.keys())) + + groupSep = min(max(0.0015,1.0/dataLen),0.1) + barSep = min(max(0.00015,1.0/keyLen),0.025) + barStart = (groupSep - (barSep*(keyLen/2.0)) + barSep)/2.0 + barWidth = max((1.0-groupSep-(barSep*keyLen))/keyLen,0.005) + #groupSep = 0.2 + defaultColors=[66,88,104,32,131,143,40,92,41,45] + # colors that are hard to see against white (see http://www.w3schools.com/cssref/css_colornames.asp) + chosenColors=[122,48,144,142,109,24,107,55,126,90,91,36,112,76,133,103,130,128,132,94,46,6,58,14,146,70,23,28,96,10,20,99,80,113,31,137] + for dataKey in sorted(dataDict.keys()): + left=[] + right=[] + top=[] + bottom=[] + color = Util.get_random_int_with_chosen_default(0, len(webcolors.css3_names_to_hex),chosenColors,defaultColors) + if color == None: + logger.error("Not enough colors. Can't generate bar plot.") + return None + chosenColors.append(color) + for dataPoint in dataDict[dataKey]: + if len(right) != len(left) != len(top): + logger.error("Some error occured. Can't generate bar plot.") + return None + counter=len(left)+1-((barWidth*keyLen)+groupSep+(barSep*(keyLen/2.0)))/2.0 + left.append(counter+barStart) + right.append(counter+barStart+barWidth) + top.append(dataPoint) + bottom.append(0) + logger.info("%s %s %s %s %s %s %s %s %s" %(dataKey, barStart, barWidth, dataLen, counter, groupSep, barSep, left,right)) + #p.quad(bottom=bottom, top=top, left=left, right=right, color=webcolors.css3_names_to_hex[webcolors.css3_names_to_hex.keys()[color]], legend="%s_%s"%(dataKey,counter2)) + # There is an error on Bokeh in the line above: If any of the top values is zero, alle bars/quads will be drawn as zero. Drawing them non-grouped fixes this. + # This is independent from the set y-range (-1 or 0 does not effect this) + # See https://github.com/bokeh/bokeh/issues/3022 + for i in range(0,len(top)): + p.quad(bottom=bottom[i], top=top[i], left=left[i], right=right[i], color=webcolors.css3_names_to_hex[webcolors.css3_names_to_hex.keys()[color]], legend=dataKey) + barStart+= barWidth + barSep + p.xaxis.axis_label_text_font_size = "10pt" + p.yaxis.axis_label_text_font_size = "10pt" + p.yaxis.axis_label = ylabel + p.xaxis.axis_label = xlabel + #p.y_range = (0, 10000) + p.legend.orientation = legendPos + return p + +# Configure ArgumentParser +parser = argparse.ArgumentParser(prog="ProcessYcsbLog.py",version=__version__,description="Generates some special diagrams (not needed for pyTsdbBench). Only supportd .ydc files.", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="") +parser.add_argument("-l", "--log", action='store_true', help="Be more verbose") +parser.add_argument("-f", "--ycsbfiles", metavar="YCSBFILE", nargs='+', required=True, help="Path to YCSB YDC file(s).") +parser.add_argument("-o", "--overwrite", action='store_true', help="Overwrite existing files") +parser.add_argument("-k", "--keys", metavar="KEYS",nargs='+', required=True, choices=['COUNT', 'INSERT', 'SCAN', 'SUM', 'CLEANUP', 'AVG', 'READ'], help="Which key do you want to use? (only takes first one!)") +parser.add_argument("-t", "--type", metavar="TYPE", required=True, choices=['MaxLatency(us)', 'MinLatency(us)', '99thPercentileLatency(ms)', '95thPercentileLatency(ms)', 'AverageLatency(us)'], help="Which type do you want to use?") + +args = parser.parse_args() + +# Configure Logging +logLevel = logging.WARN +if args.log: + logLevel = logging.DEBUG +logging.basicConfig(level=logLevel) +logger = logging.getLogger(__name__) + +dicts={} +nameDict={} # stores names for dictKeys +threads=[] +for ycsbfile in args.ycsbfiles: + # Compressing Output + mime = magic.open(magic.MAGIC_MIME) + mime.load() + try: + basename="%s" %(os.path.splitext(os.path.basename(ycsbfile))[0]).split("_")[1] + except IndexError: + logger.warning("'%s' is not a normal filename for ycsb-ts logfiles." %(os.path.basename(ycsbfile))) + basename="%s" %(os.path.splitext(os.path.basename(ycsbfile))[0]) + except: + logger.error("Can't process filename '%s' as basename." %(os.path.basename(ycsbfile))) + os._exit(-1) + if basename in dicts.keys(): + basename="%s_%s" %(basename,dicts.keys().count(basename)+1) + # print unicode(ycsbfile.decode('utf8').encode('utf8')) + if mime.file(ycsbfile) == "application/gzip; charset=binary": + # if a compressed file is found do decompress or graph + logger.info("Found Mime type '%s' in '%s'." %(ycsbfile,mime.file(ycsbfile))) + # if decompress is what you want... + if Util.check_file_exists(ycsbfile) and os.access(ycsbfile, os.R_OK): + dicts[basename] = {} + nameDict[basename]=os.path.splitext(os.path.basename(ycsbfile))[0] + threads.append(threading.Thread(target=openCompressedFile, args=(ycsbfile, dicts, basename, logger))) + threads[-1].setDaemon(True) + threads[-1].start() + else: + logger.error("Can't open '%s'. Does it exist?" %(ycsbfile), exc_info=True) + exit(-1) + + else: + logger.error("%s has an unkown mimetype '%s', sure it is a ycsb log or .ydc file?" %(ycsbfile,mime.file(ycsbfile))) + exit(-1) + + +def generate_plot(dicts, keys, type, overwrite, logger): + fileName = "ycsb_combined_%s_%s.html" % (type.rsplit("(")[0].lower(),datetime.datetime.now().strftime("%Y%m%d%H%M")) + dataDict={} + factor=1.0 + if type in convertFromUsToMs: + factor=0.001 + for dicKey in sorted(dicts.keys()): + if not "blocks" in dicts[dicKey].keys(): + logger.error("\"blocks\" not found in %s." %(dicKey)) + return False + else: + for key in keys: + if not key in dicts[dicKey]["blocks"].keys(): + logger.error("\"%s\" not found in %s." %(key, dicKey)) + return False + else: + if len(dicts[dicKey]["blocks"][key]) < 1: + logger.error("\"%s\" has zero arrays in %s." %(key, dicKey)) + return False + elif len(dicts[dicKey]["blocks"][key]) > 1: + logger.warning("\"%s\" has more than one array in %s, only using first one." %(key, dicKey)) + if type not in dicts[dicKey]["blocks"][key][0].keys(): + logger.error("\"%s\" not in first array of \"%s\" in %s." %(type, key, dicKey)) + return False + if dicKey not in dataDict.keys(): + dataDict[dicKey]=[] + dataDict[dicKey].append(dicts[dicKey]["blocks"][key][0][type]*factor) + if Util.check_file_exists(fileName): + if overwrite: + if not Util.delete_file(fileName, logger, True): + logger.error("\"%s\" does exist, overwrite is enabled, overwrite failed. Please delete manually. Abort." %(fileName)) + return False + else: + logger.error("\"%s\" does exist, overwrite is disabled. Abort." %(fileName)) + return False + bokeh.plotting.output_file(fileName) + barPlot = generate_bar_plot(dataDict, keys, "top_right", "Comparison of %s" %(type.rsplit("(")[0]), "Latency in ms", "Querytype", 1000, 650, logger) + bokeh.io.save(barPlot) + return True + +# Wait until all threads are done +logger.debug("Waiting until all files are loaded...") +# only join() would make ctrl+c not work in combination with daemon=true +# Main thread is always there, because of that: >1 +while threading.activeCount() > 1: + for thread in threads: + thread.join(100) +threads=[] + +if len(dicts.keys())==len(args.ycsbfiles): + generate_plot(dicts,args.keys,args.type, args.overwrite, logger) +else: + logger.error(" %s Files and %s Dicts do not match, this should not happen." %(len(args.ycsbfiles),len(dicts.keys()))) + exit(-1) + +exit(0) \ No newline at end of file diff --git a/ProcessYcsbLog.py b/ProcessYcsbLog.py new file mode 100755 index 0000000..8e7f59b --- /dev/null +++ b/ProcessYcsbLog.py @@ -0,0 +1,1565 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +import copy +import gzip +from dateutil import tz +import jinja2 +import logging +import argparse +import magic +import os +import re +import datetime +import locale +import cPickle +import bokeh.charts +from itertools import islice +import pdfkit +import pytz +import Util +import webcolors +import threading +import signal + +__author__ = 'Andreas Bader' +__version__ = "0.03" + +# in 0.02 some dicts were replaced with lists. +# reason: when parsing large result files (100k buckets = 400k lines) +# .keys() is getting relatevly slow, but amound of keys stays the same +# which is kind of strange +# so replacing those dicts with lists helps a great deal +# also some other speed-affecting changes were made +# Threading, blockwise-reading etc. +# some variable names will a bit weird (like Dict for a list) because of this +# Also since 0.02 we won't save the whole log file into ydc anymore, as this seem to be a bit overkill +# This should not affect older 0.01 logs, but could happen. However, "LatencyList" was renamed, so this version can't read 0.01 anymore. +# Also correct timezone awareness was added +# 0.03 calculates 99% and 95% also in us, old files cannot be read. This reflects the update to YCSB 0.4.0 +# For reading 0.2.0 files, replace "99thPercentileLatency(us)" with "99thPercentileLatency(ms)" and for 95th accordingly +# in Line 74, 75, 156, 157, 1207, 1208, 1252, 1253, 1254, 1255, 1296, 1297, 1298, 1299 + +plotColorDict={"DEFAULT" : "blue", + "INSERT0" : "red", + "INSERT1" : "darkred", + "READ0" : "orange", + "READ1" : "darkorange", + "CLEAN0" : "green", + "CLEAN1" : "darkgreen", + "UPDATE0" : "purple", + "UPDATE1" : "darkpurple" + } +defaultPlotColor=plotColorDict["DEFAULT"] +maxTableColumnsSingle=6 +maxTableColumnsMulti=10 + +templateFile="template.html" #Jinja2 Template, see http://bokeh.pydata.org/en/latest/docs/reference/resources_embedding.html#bokeh.embed.file_html +templateFileMulti="template_multi.html" #Jinja2 Template, see http://bokeh.pydata.org/en/latest/docs/reference/resources_embedding.html#bokeh.embed.file_html + +pdfOptions = { + 'page-size': 'A4', + 'margin-top': '0.5cm', + 'margin-right': '0.5cm', + 'margin-bottom': '0.5cm', + 'margin-left': '0.5cm', + 'encoding': "UTF-8", + 'no-outline': None, + 'quiet': '', + 'dpi' : 600, + 'image-dpi' : 600, + 'image-quality' : 94, + 'title' : "" +} + +ignoreParams = ["Operations", "Return", "LatencyList"] # parameters that should be ignored (LatencyList e.g.) +possibleMissingParams = ["99thPercentileLatency(us)","95thPercentileLatency(us)"] #Params that can be missing, replaced by -1 +convertFromUsToMs = ["AverageLatency(us)", "MinLatency(us)", "MaxLatency(us)", "99thPercentileLatency(us)","95thPercentileLatency(us)" ] # Some special parameters need to be converted + +def signal_handler(signal, frame): + os._exit(0) + +signal.signal(signal.SIGINT, signal_handler) + +def find_time(timeString,logger): + timeRegex="[A-Za-z]+\s+[A-Za-z]+\s+[0-9]+\s+[0-9]+:[0-9]+:[0-9]+\s+[A-Za-z]+\s+[0-9]+" + if re.search(timeRegex,timeString) != None: + act_loc=locale.getlocale() + try: + locale.setlocale(locale.LC_ALL,'en_US.UTF-8') + except Exception, e: + logger.error('Failed to set locale, do you have locale en_US.UTF-8 installed?', exc_info=True) + os._exit(-1) + try: + timeObj=datetime.datetime.strptime(re.search(timeRegex,timeString).group(), '%a %b %d %H:%M:%S %Z %Y') + timeObj=timeObj.replace(tzinfo=tz.gettz(re.search(timeRegex,timeString).group().split(" ")[4])) + locale.setlocale(locale.LC_ALL,act_loc) + return timeObj + except Exception, e: + logger.warning("Failed to parste timezone from '%s', got '%s'. Setting it to UTC, this may be wrong." + %(re.search(timeRegex,timeString).group(), + re.search(timeRegex,timeString).group().split(" ")[4]), exc_info=True) + timeObj=timeObj.replace(tzinfo=tz.gettz('UTC')) + locale.setlocale(locale.LC_ALL,act_loc) + return timeObj + else: + logger.error("Can't find time in '%s'." %(timeString)) + os._exit(-1) + +# converts timestring to timeobject +# checks if value is already set (should not happen that a value is found twice) +def process_time(line,key,dict,logger): + if key in dict.keys(): + logger.error("Found two %s, this should not happen!" %(key)) + os._exit(-1) + dict[key] = find_time(line,logger) + +# converts spacestring +def process_space(line, dict,logger): + spaceSplitters = line.replace("SPACE: ","").split(" ") + if len(spaceSplitters) == 3: + dict["spaceBegin"] = spaceSplitters[0] + dict["spaceBetween"] = spaceSplitters[1] + dict["spaceEnd"] = spaceSplitters[2] + else: + logger.error("Error while processing space string '%s'" %(line)) + os._exit(-1) + +# converts float (throughput, runtime) +def process_float(line, dict, key, logger): + splitters = line.split(", ") + if len(splitters) == 3: + dict[key] = float(splitters[2]) + else: + logger.error("Error while processing float string '%s'" %(line)) + os._exit(-1) + +# checks if we have a line according to one of the known blocks +def check_block(line, knownBlocktypes): + for type in knownBlocktypes: + if re.search("^\[%s\]" %(type),line) != None: + return True + return False + +# parses one actual line (=value) into a existing block dict +# blockDict = dict which contains values of the actual block (block ex. READ) +# two typical ycsb lines as example: +# [READ], 99thPercentileLatency(us), 4 +# [READ], 0, 397 +# this translates as follows to the arguments: +# [blockName], name, value +# rewrote in 0.02 for using lists in some steps instead of dicts, brings some speedup! +def parse_block(blockDict, blockName, name, value, timeSeries, logger): + # save every known name + conversion method + knownValues={"Operations": int, + "AverageLatency(us)" : float, + "MinLatency(us)" : int, + "MaxLatency(us)" : int, + "95thPercentileLatency(us)": int, + "99thPercentileLatency(us)" : int} + if name in knownValues.keys(): + # Check if value was already found in this block, should not happen! + if name not in blockDict.keys(): + try: + blockDict[name] = knownValues[name](value) + except ValueError: + logger.error("Error while convertion in block '%s' with value '%s'." %(blockName, value)) + os._exit(-1) + else: + logger.error("Found another '%s' value in block '%s' with value '%s'. Should not happen." %(name, blockName, value)) + os._exit(-1) + elif "Return=" in name: + # Return Value looks like this name: Return=0, value: 123 + if "Return" not in blockDict.keys(): + blockDict["Return"] = [] + try: + blockDict["Return"].append([int(name.replace("Return=","")),int(value)]) + except ValueError: + logger.error("Error while convertion in block '%s' with value '%s'." %(blockName, value)) + os._exit(-1) + else: + # here we should have only histogram or timeseries values + # ex. [READ], 0, 397 + # ex. [READ], 1, 101 + # the last value has propbably a ">" in its name, ignore that. + try: + if "LatencyList" not in blockDict.keys(): + blockDict["LatencyList"] = [] + if timeSeries: + blockDict["LatencyList"].append(float(value)/1000.0) + else: + blockDict["LatencyList"].append(int(value)) + except ValueError: + logger.error("Error while convertion in block '%s' with value '%s' and name '%s'." %(blockName, value, name)) + os._exit(-1) + except: + logger.error("Unknown error occured while convertion in block '%s' with value '%s' and name '%s'. Maybe unknwon block value?" %(blockName, value, name)) + os._exit(-1) + +# processes one actual known block +# look below at process_file(..) for more explanation (data structure,..) +# actBlock should be mutable, but Strings are immutable, so actBlock should be a list with a string in it.. ;) +# rewrote in 0.02 for using lists in some steps instead of dicts, brings some speedup! +def process_block(fileDict, line, blockIndices, actBlock, timeSeries, logger): + splitters = line.split(", ") + if len(splitters) == 3: + # check if it is the first block we ever encounter or if we are at a new block + blockName=splitters[0].replace("[","").replace("]","") + if actBlock[0] == "" or blockName != actBlock[0]: + # save that we are in a new block + actBlock[0] = blockName + # check if fileDict contains the blocks dict + if "blocks" not in fileDict.keys(): + fileDict["blocks"] = {} + # check if dict already knews it + if blockName not in fileDict["blocks"].keys(): + fileDict["blocks"][blockName] = [] + # fileDict["blocks"][blockName] = {} + # search for new index if types of this block already exist + newIndex=0 + if len(fileDict["blocks"][blockName]) > 0: + newIndex = len(fileDict["blocks"][blockName]) + fileDict["blocks"][blockName].append({}) + parse_block(fileDict["blocks"][blockName][newIndex], blockName, splitters[1], splitters[2], timeSeries, logger) + else: + # okay we just have to add some value to this already seen block + parse_block(fileDict["blocks"][blockName][-1], blockName, splitters[1], splitters[2], timeSeries, logger) + else: + logger.error("Error while processing line '%s'" %(line)) + os._exit(-1) + +def process_file(filename, timeSeries, fileDict, compressedFileName, logger): + if not Util.check_file_readable(filename): + logger.error("Can't open %s." % (filename)) + return + file = open(filename,"r") + actBlock=[""] # saves in which type of block we are, must be mutable! + knownBlocktypes=["CLEANUP", "INSERT", "READ", "UPDATE", "SCAN", "AVG", "SUM", "COUNT"] # saves which types of blocks we know + # fileDict must be mutable! + # the following keys can exist + # dbName -> name of dbms (mysql e.q.) + # dbDesc -> description of dbms (mysql e.q.) + # description -> description of the workload + # errors -> [] (errors occured) + # warnings -> [] (warnings occured) + # exceptions -> [] (exceptions occured) + # workload -> name of workload (workloada e.g.) + # startTime -> overall start time + # endTime -> overall end time + # startRunTime -> RUN phase start time + # endRunTime -> RUN phase end time + # startLoadTime -> LOAD phase start time + # endLoadTime -> LOAD phase end time + # spaceBegin -> Space of DB folder before any workload (before LOAD phase) + # spaceBetween -> Space of DB folder between LOAD and RUN phase + # spaceEnd -> Space of DB folder after RUN phase + # runtimeLoad -> runtime (ycsb) of LOAD phase + # runtimeRun -> runtime (ycsb) of RUN phase + # throughputLoad -> throughput (ycsb) of RUN phase + # throughputRun -> throughput (ycsb) of RUN phase + # blocks -> dict of blocks (ycsb) + # filecontent -> content of original ycsb file (ycsb) -> Dropped with 0.02! + # timeseries -> true/false -> generate ts output (arguments can overwrite it) + # granularity -> integer for ts granularity + # bucket -> integer for histogram buckets + # (ycsb) means that this is measured by ycsb + + # blocks itself looks like: + # {"CLEANUP": {}, "INSERT": {}, "READ": {}, "UPDATE": {}} + # the embedded dicts look like this (ex. for INSERT) + # {0 : {}, 1 : {}} # 0 = first encountered INSERT block, 1 = second encountered INSERT block ... + # {} contains the actual values of one block + # ex. one READ Block (latencies are truncated) + # [READ], Operations, 511 + # [READ], AverageLatency(us), 860.4833659491194 + # [READ], MinLatency(us), 404 + # [READ], MaxLatency(us), 14309 + # [READ], 95thPercentileLatency(us), 1 + # [READ], 99thPercentileLatency(us), 4 + # [READ], Return=0, 511 + # [READ], 0, 397 + # [READ], 1, 101 + # ... + # the dict would be.: {"Operations" : 511, "AverageLatency(us)" : 860.4833659491194, "MinLatency(us)": 404, "MaxLatency(us)" : 14309 ,"95thPercentileLatency(us)" : 1, "99thPercentileLatency(us)" : 4, "Return" : [0,511] , "LatencyList" : {0 : 397, 1 : 101, ,...} } + # look at https://github.com/brianfrankcooper/YCSB/wiki/Running-a-Workload how to interpret the ycsb values + # in case timeseries instead of histogramm is used, there will be floats instead of integers as values (ex. [READ], 1, 101.11) + + # split filename to get db & workload name + # e.g. ycsb_mysql_workloada_201507282238.log + fileNameSplitters=filename.split("_") + if len(fileNameSplitters) >= 4: + fileDict["dbName"]=fileNameSplitters[1] + for splitter in fileNameSplitters[2:len(fileNameSplitters)-2]: + fileDict["dbName"]+="_%s" %(splitter) + fileDict["workload"]=fileNameSplitters[len(fileNameSplitters)-2] + else: + logger.error("Can't parse filename '%s'." %(filename)) + os._exit(-1) + fileDict["errors"] = []; + fileDict["warnings"] = []; + fileDict["exceptions"] = []; + fileDict["description"] = ""; + # process lines + # Using the blockwise list(islice(..)) version, as it is a little bit faster than pure 'for line in file:' + while True: + lines = list(islice(file, 100)) + if not lines: + break + for line in lines: + if re.search("Start Test$",line) != None: + # Starttime whole measurement + process_time(line,"startTime", fileDict, logger) + elif re.search("error",line.lower()) != None: + fileDict["errors"].append(line) + elif re.search("warn",line.lower()) != None: + fileDict["warnings"].append(line) + elif re.search("exception",line.lower()) != None: + fileDict["exceptions"].append(line) + elif re.search("^\[DESCRIPTION\]",line) != None: + fileDict["description"] = line.replace("[DESCRIPTION],","") + if fileDict["description"][0] == " ": + fileDict["description"] = fileDict["description"][1:] + continue + elif re.search("^DESCRIPTION",line) != None: + try: + fileDict["dbDesc"] = line.split("DESCRIPTION: ")[1] + except Exception, e: + logger.warning("Couldn't process DESCRIPTION line '%s', ignoring it." %(line), exc_info=True) + fileDict["dbDesc"] = "" + elif re.search("Start Load$",line) != None: + # Starttime LOAD phase + process_time(line,"startLoadTime", fileDict, logger) + elif re.search("End Load$",line) != None: + # Endtime LOAD phase + process_time(line,"endLoadTime", fileDict, logger) + elif re.search("Start Run$",line) != None: + # Starttime RUN phase + process_time(line,"startRunTime", fileDict, logger) + elif re.search("End Run$",line) != None: + # Endtime RUN phase + process_time(line,"endRunTime", fileDict, logger) + elif re.search("End Test$",line) != None: + # Endtime whole measurement + process_time(line,"endTime", fileDict, logger) + elif re.search("^SPACE:",line) != None: + # found line with space + process_space(line, fileDict, logger) + elif re.search("^TIMESERIES",line) != None: + # if Timeseries is set or unset + if re.search("1$",line) != None: + fileDict["timeseries"] = True + timeSeries = True + elif re.search("0$",line) != None: + fileDict["timeseries"] = False + else: + logger.warning("Couldn't process TIMESERIES line '%s', ignoring it." %(line)) + elif re.search("^GRANULARITY",line) != None: + # Granularity for ts + try: + fileDict["granularity"] = int(line.split("GRANULARITY: ")[1]) + except Exception, e: + logger.warning("Couldn't process GRANULARITY line '%s', ignoring it." %(line), exc_info=True) + elif re.search("^BUCKET",line) != None: + # histogram Buckets + try: + fileDict["bucket"] = int(line.split("BUCKET: ")[1]) + except Exception, e: + logger.warning("Couldn't process BUCKET line '%s', ignoring it." %(line), exc_info=True) + elif re.search("^\[OVERALL\]",line) != None: + if "RunTime" in line: + if "runtimeLoad" in fileDict.keys(): + # runtimeLoad was found, now it has to be Run + process_float(line, fileDict, "runtimeRun", logger) + elif "runtimeRun" in fileDict.keys(): + # both already found, third one should not happen + logger.error("Found third runTime in '%s'." %(line)) + os._exit(-1) + else: + # nothing set, must be Load phase + process_float(line, fileDict, "runtimeLoad", logger) + elif "Throughput" in line: + if "throughputLoad" in fileDict.keys(): + # throughputLoad was found, now it has to be Run + process_float(line, fileDict, "throughputRun", logger) + elif "throughputRun" in fileDict.keys(): + # both already found, third one should not happen + logger.error("Found third throughput in '%s'." %(line)) + os._exit(-1) + else: + # nothing set, must be Load phase + process_float(line, fileDict, "throughputLoad", logger) + else: + logger.error("Did not found 'RunTime' nor 'Throughput' in '%s'." %(line)) + os._exit(-1) + # found line with space + process_space(line, fileDict, logger) + elif check_block(line, knownBlocktypes): + # check if fileDict contains the blocks dict + process_block(fileDict, line, knownBlocktypes, actBlock, timeSeries, logger) + ## AVG,SUM, usw. + for blockKey in fileDict["blocks"].keys(): + ## AVG0,SUM0, usw. + for listBlock in fileDict["blocks"][blockKey]: + if "LatencyList" not in listBlock.keys(): + logger.error("The 'LatencyList' is missing Block %s in %s." %(blockKey,listBlock,filename)) + os._exit(-1) + # "0"-"999" + ">1000" = 1001 Entrys for 1000 buckets for ex. + if len(listBlock["LatencyList"]) != int(fileDict["bucket"])+1: + logger.error("There are buckets missing for %s%s in %s. Available Buckets: %s, configured amount of buckets: %s(+1)." %(blockKey,listBlock,filename,len(listBlock["LatencyList"]),int(fileDict["bucket"]))) + os._exit(-1) + + try: + file = gzip.open(compressedFileName,"w") + cPickle.dump(fileDict,file) + file.flush() + file.close() + except Exception, e: + logger.error("Can't open '%s' to write. Is it writable?" %(compressedFileName), exc_info=True) + os._exit(-1) + return fileDict + +# replaces bokeh.charts.Bar because it can't do logarithmic scale +def generate_bar_plot(dataDict, cat, legendPos, title, ylabel, xlabel, width, height, logger): + maxValue=0 + for dataKey in dataDict.keys(): + for dataPoint in dataDict[dataKey]: + if dataPoint >= maxValue: + try: + dataPointStr = str(dataPoint) + if "." in dataPointStr: + dataPointStr = dataPointStr.split(".")[0] + maxValue = 10**len(dataPointStr) + except: + logger.error("Can't convert '%s' to string. Can't generate bar plot." %(dataPoint)) + return None + if maxValue == 0: + logger.error("Maximum value is 0. Can't generate bar plot.") + return None + p = bokeh.plotting.figure(title=title, y_axis_type="log", x_range=cat, y_range=[0,maxValue], width=width, height=height) + dataLen = -1 + for dataKey in dataDict.keys(): + if dataLen == -1: + dataLen = len(dataDict[dataKey]) + else: + if dataLen != len(dataDict[dataKey]): + logger.error("Some dataLists in dataDict have different lengths. Can't generate bar plot.") + return None + if dataLen == -1: + logger.error("Can't find list length. Can't generate bar plot.") + return None + keyLen = float(len(dataDict.keys())) + + groupSep = min(max(0.0015,1.0/dataLen),0.1) + barSep = min(max(0.00015,1.0/keyLen),0.025) + barStart = (groupSep - (barSep*(keyLen/2.0)) + barSep)/2.0 + barWidth = max((1.0-groupSep-(barSep*keyLen))/keyLen,0.005) + #groupSep = 0.2 + defaultColors=[66,88,104,32,131,143,40,92,41,45] + # colors that are hard to see against white (see http://www.w3schools.com/cssref/css_colornames.asp) + chosenColors=[122,48,144,142,109,24,107,55,126,90,91,36,112,76,133,103,130,128,132,94,46,6,58,14,146,70,23,28,96,10,20,99,80,113,31,137] + for dataKey in sorted(dataDict.keys()): + left=[] + right=[] + top=[] + bottom=[] + color = Util.get_random_int_with_chosen_default(0, len(webcolors.css3_names_to_hex.keys())-1,chosenColors,defaultColors) + if color == None: + logger.error("Not enough colors. Can't generate bar plot.") + return None + chosenColors.append(color) + # for dataPoint in dataDict[dataKey][::-1]: + for dataPoint in dataDict[dataKey]: + if len(right) != len(left) != len(top): + logger.error("Some error occured. Can't generate bar plot.") + return None + counter=len(left)+1-((barWidth*keyLen)+groupSep+(barSep*(keyLen/2.0)))/2.0 + left.append(counter+barStart) + right.append(counter+barStart+barWidth) + top.append(dataPoint) + bottom.append(0) + logger.info("%s %s %s %s %s %s %s %s %s" %(dataKey, barStart, barWidth, dataLen, counter, groupSep, barSep, left,right)) + #p.quad(bottom=bottom, top=top, left=left, right=right, color=webcolors.css3_names_to_hex[webcolors.css3_names_to_hex.keys()[color]], legend="%s_%s"%(dataKey,counter2)) + # There is an error on Bokeh in the line above: If any of the top values is zero, alle bars/quads will be drawn as zero. Drawing them non-grouped fixes this. + # This is independent from the set y-range (-1 or 0 does not effect this) + # See https://github.com/bokeh/bokeh/issues/3022 + for i in range(0,len(top)): + p.quad(bottom=bottom[i], top=top[i], left=left[i], right=right[i], color=webcolors.css3_names_to_hex[webcolors.css3_names_to_hex.keys()[color]], legend=dataKey) + barStart+= barWidth + barSep + p.xaxis.axis_label_text_font_size = "10pt" + p.yaxis.axis_label_text_font_size = "10pt" + p.yaxis.axis_label = ylabel + p.xaxis.axis_label = xlabel + #p.y_range = (0, 10000) + p.legend.orientation = legendPos + return p + +# generates plots for every block/index in dict +# Only for one measurement -> "single" +def generate_plot_single(dict, timeseries, logger, tick=1000): + dataDict = { "histogram" : {}, "general" : {} } + gridplotList = [] + gridRowCount = 0 + gridRowMax = 2 + # Get Data for both plots + if args.debug: + Util.log_timestamp("Start Generating histogramm data",logger) + for block in dict["blocks"].keys(): + counter=0 + for blockList in dict["blocks"][block]: + dataDict["histogram"]["%s%s" %(block,counter)] = generate_histogram_data(blockList["LatencyList"], logger) + counter += 1 + if args.debug: + Util.log_timestamp("Start Generating general data",logger) + dataDict["general"] = generate_general_data(dict["blocks"], True, False, logger) + if "TIMESERIES" in dataDict.keys() and dataDict["TIMESERIES"]: + timeseries = True + if "GRANULARITY" in dataDict.keys(): + tick = dataDict["GRANULARITY"] + elif timeseries: + try: + tick = sorted(dataDict["histogram"][dataDict["histogram"].keys()[0]]["cat"])[1]-sorted(dataDict["histogram"][dataDict["histogram"].keys()[0]]["cat"])[0] + except Exception, e: + logger.warning("Couldn't process GRANULARITY on base of histogramm data. Default to 1000.", exc_info=True) + tick=1000 + # generate General block plot + #p = bokeh.charts.Bar(dataDict["general"]["data"], cat=dataDict["general"]["cat"], legend="top_right", title="Block results:", + # ylabel='Latency in ms', xlabel = "Type of latency", width=650, height=350) + if args.debug: + Util.log_timestamp("Start Generating bar plot",logger) + p = generate_bar_plot(dataDict["general"]["data"], dataDict["general"]["cat"], "top_left", "Block results:", + "Latency in ms", "Type of latency", 650, 350, logger) + if args.debug: + Util.log_timestamp("End Generating bar plot",logger) + if p == None: + return None + if gridRowMax < 2: + gridplotList.append(p) + elif gridRowCount == gridRowMax-1: + gridplotList[-1].append(p) + gridRowCount=0 + else: + gridplotList.append([p]) + gridRowCount+=1 + if args.debug: + Util.log_timestamp("Start Generating histograms",logger) + # Generate histograms + for key in dataDict["histogram"].keys(): + if len(dataDict["histogram"][key]["data"]) < 2 and \ + len(dataDict["histogram"][key]["data2"]) < 2 and \ + len(dataDict["histogram"][key]["cat"]) < 2: + if "CLEANUP" in key and timeseries: + logger.info("Do not produce '%s' plots since timeseries is active and therefore only 1 value is given." %(key)) + else: + logger.warning("Only 1 value for '%s', can't produce plots for this block." %(key)) + continue + p = bokeh.plotting.figure(title="Query time for %s" %(key), + x_range=[0,max(dataDict["histogram"][key]["cat"])], y_range=[0, max(dataDict["histogram"][key]["data"])+max(dataDict["histogram"][key]["data"])/10.0], + plot_width=650, plot_height=350) + p.xaxis.axis_label_text_font_size = "10pt" + p.yaxis.axis_label_text_font_size = "10pt" + if timeseries: + p.yaxis.axis_label = "Avg. Latency since last tick (every %s ms) in ms" %(tick) + p.xaxis.axis_label = "Elapsed time in ms" + p.xaxis[0].ticker = bokeh.models.SingleIntervalTicker(interval=tick) + else: + p.xaxis.axis_label = "Time in ms" + p.yaxis.axis_label = "Amount of queries completed" + color = defaultPlotColor + if key in plotColorDict.keys(): + color = plotColorDict[key] + if timeseries: + sortedCatList, sortedDataList = (list(t) for t in zip(*sorted(zip(dataDict["histogram"][key]["cat"], dataDict["histogram"][key]["data"])))) + p.line(sortedCatList, sortedDataList, line_width=2) + p.circle(dataDict["histogram"][key]["cat"], dataDict["histogram"][key]["data"], fill_color="white", size=8) + else: + p.rect(x=dataDict["histogram"][key]["cat"], y=dataDict["histogram"][key]["data2"], width=0.8, + height=dataDict["histogram"][key]["data"], color=color, alpha=1) + if gridRowMax < 2: + gridplotList.append(p) + continue + if gridRowCount == gridRowMax-1: + gridplotList[-1].append(p) + gridRowCount=0 + else: + gridplotList.append([p]) + gridRowCount+=1 + if args.debug: + Util.log_timestamp("End Generating histograms",logger) + if args.debug: + Util.log_timestamp("Start adding plots to bokeh",logger) + p = bokeh.io.gridplot(gridplotList) + if args.debug: + Util.log_timestamp("End adding plots to bokeh",logger) + return p + +# generates plots for every block/index and every dict in dicts +# Only for more than one measurement -> "multi" +# no histogram in combined plots +# only comparison plots/tables +def generate_plot_multi(dicts, timeseries, logger, tick=1000): + gridplotList = [] + dataDictBlocks = {} + # structure of dataDictBlocks should look like this: + # + # -> "data" + # -> + # -> [1,2,3] + # ... + # ... + # -> "cat" + # -> + # -> ... + # e.g. "INSERT0" + # e.g. "MySQL" + # e.g. "AvgLatency" + + # getting blocktypes and data + generate_block_data(dataDictBlocks, dicts, True, False, logger) + + # generating general graphs like avgLatency etcpp. + for blockKey in dataDictBlocks.keys(): + #p = bokeh.charts.Bar(dataDictBlocks[blockKey]["data"], cat = dataDictBlocks[blockKey]["cat"], legend = "top_right", + # title = "Results for block %s:" % (blockKey), ylabel = 'Latency in ms', xlabel = "Type of latency", width=1300, height=700) + # dataDictBlocks[blockKey]["cat"]=['Avg.', '95Perc.', '99Perc.', 'Min', 'Max',] + # p = generate_bar_plot(dataDictBlocks[blockKey]["data"], dataDictBlocks[blockKey]["cat"][::-1], + p = generate_bar_plot(dataDictBlocks[blockKey]["data"], dataDictBlocks[blockKey]["cat"], + "top_left", "Results for block %s:" % (blockKey), + "Latency in ms", "Type of latency", 1300, 700, logger) + if p != None: + gridplotList.append([p]) + else: + logger.error("An error occured while generting plot for %s." %(blockKey)) + + # generating graphs for runtimeRun/Load + runtimeDict = { "data" : {}, "cat" : [ "runtimeLoad", "runtimeRun" ] } + for key in dicts.keys(): + if "runtimeLoad" in dicts[key].keys() and "runtimeRun" in dicts[key].keys(): + runtimeDict["data"][key]=[dicts[key]["runtimeLoad"],dicts[key]["runtimeRun"]] + else: + logger.error("Can't find 'runtimeLoad' or/and 'runtimeRun' in %s dict. Can't go on." %(key)) + os._exit(-1) + # p = bokeh.charts.Bar(runtimeDict["data"], cat = runtimeDict["cat"], legend = "top_right", + # title = "Results for runtime:", ylabel = 'Runtime in ms', xlabel = "Type of runtime", width=1300, height=700) + # gridplotList.append([p]) + p = generate_bar_plot(runtimeDict["data"], runtimeDict["cat"], + "top_left", "Results for runtime:", + "Runtime in ms", "Type of runtime", 1300, 700, logger) + if p != None: + gridplotList.append([p]) + else: + logger.error("An error occured while generting plot for runtimeDict.") + + + # generating graphs for throughputLoad/Run + runtimeDict = { "data" : {}, "cat" : [ "throughputLoad", "throughputRun" ] } + for key in dicts.keys(): + if "throughputLoad" in dicts[key].keys() and "throughputRun" in dicts[key].keys(): + runtimeDict["data"][key]=[dicts[key]["throughputLoad"],dicts[key]["throughputRun"]] + else: + logger.error("Can't find 'throughputLoad' or/and 'throughputRun' in %s dict. Can't go on." %(key)) + os._exit(-1) + # p = bokeh.charts.Bar(runtimeDict["data"], cat = runtimeDict["cat"], legend = "top_right", + # title = "Results for throughput:", ylabel = 'Throughput in operations per sec.', xlabel = "Type of throughput", width=1300, height=700) + # gridplotList.append([p]) + p = generate_bar_plot(runtimeDict["data"], runtimeDict["cat"], + "top_left", "Results for throughput:", + "Throughput in operations per sec.", "Type of throughput", 1300, 700, logger) + if p != None: + gridplotList.append([p]) + else: + logger.error("An error occured while generting plot for throughput.") + + + # generating graphs for spaceLoad/spaceRun: + # spaceLoad = spaceBetween - spaceBegin + # spaceRun = spaceEnd - spaceBetween + runtimeDict = { "data" : {}, "cat" : [ "spaceLoad", "spaceRun" ] } + for key in dicts.keys(): + if "spaceBegin" in dicts[key].keys() and "spaceEnd" in dicts[key].keys() and "spaceBetween" in dicts[key].keys(): + try: + runtimeDict["data"][key]=[int(dicts[key]["spaceBetween"]) - int(dicts[key]["spaceBegin"]), int(dicts[key]["spaceEnd"]) - int(dicts[key]["spaceBetween"])] + except: + logger.error("Error while converting 'spaceBegin' '%s' or/and 'spaceBetween' '%s' or/and 'spaceEnd' '%s' in %s dict to int. Can't go on." %(dicts[key]["spaceBegin"], dicts[key]["spaceBetween"], dicts[key]["spaceEnd"], key)) + os._exit(-1) + else: + logger.error("Can't find 'spaceBegin' or/and 'spaceBetween' or/and 'spaceEnd' in %s dict. Can't go on." %(key)) + os._exit(-1) + # p = bokeh.charts.Bar(runtimeDict["data"], cat = runtimeDict["cat"], legend = "top_right", + # title = "Results for space consumption:", ylabel = 'Space consumption in Kilobyte (kB)', xlabel = "Type of space consumption", width=1300, height=700) + # gridplotList.append([p]) + p = generate_bar_plot(runtimeDict["data"], runtimeDict["cat"], + "top_left", "Results for space consumption:", + "Space consumption in Kilobyte (kB)", "Type of space consumption", 1300, 700, logger) + if p != None: + gridplotList.append([p]) + else: + logger.error("An error occured while generting plot for space consumption.") + + + p = bokeh.io.gridplot(gridplotList) + return p + +# generates block data for multi dict block graphs +# in dataDictBlocks the following structure is found after returning: +# +# -> "data" +# -> +# -> [1,2,3] +# ... +# ... +# -> "cat" +# -> +# -> ... +# e.g. "INSERT0" +# e.g. "MySQL" +# e.g. "AvgLatency" +def generate_block_data(dataDictBlocks, dicts, ignoreSomeParameters, ignoreLess, logger): + firstRound = True # check if everyone has same block types + for key in dicts.keys(): + # generate_general_data deliveres the following structure: + # "data" + # -> + # -> + # "cat" + # -> + # -> ... + # we have to move that a little bit... + data = generate_general_data(dicts[key]["blocks"], ignoreSomeParameters, ignoreLess, logger) + keyCopyTmp = list(dataDictBlocks.keys()) # True Copy # check if every block is in every dict + for block in dicts[key]["blocks"].keys(): + for index in range(0,len(dicts[key]["blocks"][block])): + blockname = "%s%s" % (block, index) + if firstRound and blockname not in dataDictBlocks.keys(): + dataDictBlocks[blockname] = {"data": {}, "cat": []} + if dataDictBlocks[blockname]["cat"] == []: + dataDictBlocks[blockname]["cat"] = data["cat"] + elif blockname not in dataDictBlocks.keys(): + logger.error( + "Found blocktype '%s' (index '%s') that does only belong to dict '%s'. Can't move on." % ( + block, index, key)) + os._exit(-1) + else: + keyCopyTmp.remove(blockname) + if key not in dataDictBlocks[blockname]["data"].keys(): + dataDictBlocks[blockname]["data"][key] = data["data"][blockname] + else: + logger.error("Found key '%s' more than once for block '%s', index '%s'. Can't move on." % ( + key, block, index)) + os._exit(-1) + # check if the right amount of parameters is there + if len(dataDictBlocks[blockname]["data"][key]) != len(dataDictBlocks[blockname]["cat"]) and not ignoreLess: + logger.error("Found more or less parameters than needed in key '%s'. Needed: %s, Found: %s." % ( + key, len(dataDictBlocks[blockname]["cat"]), len(dataDictBlocks[blockname]["data"][key]))) + os._exit(-1) + if not firstRound: + if len(keyCopyTmp) > 0: + logger.error("Found less keys than needed in '%s'. Needed: '%s'." % (key, keyCopyTmp)) + os._exit(-1) + firstRound = False + + +# generates html file for given html text +def generate_html(p, templateFile, templateDict, outputFile, overwrite, logger): + if not Util.check_file_exists(templateFile): + logger.error("Template file does not exist: '%s'" %(templateFile)) + os._exit(-1) + try: + template = jinja2.Environment(loader = jinja2.FileSystemLoader(searchpath=os.path.split(templateFile)[0])).get_template(os.path.split(templateFile)[1]) + except Exception, e: + logger.error("Failed load template file '%s'" %(templateFile), exc_info=True) + os._exit(-1) + html = bokeh.embed.file_html(plot_object=p, resources=bokeh.resources.INLINE, title=templateDict["title"] , template=template, template_variables=templateDict) + if Util.check_file_exists(outputFile) and not overwrite: + logger.error("Html file does exist: '%s'. Delete or use overwrite flag." %(outputFile)) + os._exit(-1) + try: + file = open(outputFile,"w") + file.write(html) + file.close() + except Exception, e: + logger.error("Error while writing html file '%s'" %(outputFile), exc_info=True) + os._exit(-1) + +# generates bokeh histogram_data +# gets data from every "LatencyList" +# data2 is just data/2.0 +# commented out code is old and better to read but much slower due to "key not in" - if +def generate_histogram_data(list, logger): + if args.debug: + Util.log_timestamp("Start Generating histogram",logger) + dataDict = { "data" : [], "data2" : [], "cat" : []} + # consits of dicts: data and cat + # counter=0 + dataDict["data"]=list + dataDict["data2"]=[i/2.0 for i in list] + dataDict["cat"]=range(0,len(list)) + + # for value in list: + # # factor 2 has to be divided as you set a "center point" for your rectangles, otherwise 0 won't be 0 + # dataDict["data"].append(value) + # dataDict["data2"].append(value/2.0) + # if key not in dataDict["cat"]: + # Util.log_timestamp(counter,logger) + # dataDict["cat"].append(counter) + # counter += 1 + if args.debug: + Util.log_timestamp("End Generating histogram",logger) + return dataDict + +# generates bokeh general block data +# gets the "blocks" key of fileDict (see above method process_file(...)) +# use data from every block in blocks, from every index in every block +# gets every "Throughput","AverageLatency",... +# if you set param you only get your chosen value like Throughput e.g. +def generate_general_data(dict, ignoreSomeParameters, ignoreLess, logger): + dataDict = { "data" : {}, "cat" : [] } + firstRun = True + for block in dict.keys(): + for counter in range(0,len(dict[block])): + dataDict["data"]["%s%s" % (block,counter)] = [] + parameterArrayCopy = list(dataDict["cat"]) # real copy, not just reference! + for parameter in possibleMissingParams: + if parameter not in dict[block][counter].keys(): + logger.warning("Possible that all querys of %s run more than the maximum time measurement period? %s will be -1 for %s." %("%s%s" %(block,counter),parameter, "%s%s" %(block,counter))) + dict[block][counter][parameter]=-1 + for parameter in dict[block][counter].keys(): + parameterClean = parameter.replace("(ms)","").replace("(us)","").replace("Latency","").replace("thPercentile","Perc.").replace("Average","Avg.") + if parameter not in ignoreParams or (not ignoreSomeParameters and parameter != "LatencyList" ): + if not firstRun and parameterClean not in dataDict["cat"]: + logger.error("There were more parameter in '%s' than in other blocks, that does not work. Parameter %s is too much." %("%s%s" % (block,counter),parameter)) + os._exit(-1) + if parameter in convertFromUsToMs: + dataDict["data"]["%s%s" % (block,counter)].append(dict[block][counter][parameter]/1000.0) + else: + dataDict["data"]["%s%s" % (block,counter)].append(dict[block][counter][parameter]) + if firstRun: + dataDict["cat"].append(parameterClean) + else: + parameterArrayCopy.remove(parameterClean) + if not firstRun: + if len(parameterArrayCopy) > 0: + if not ignoreLess: + logger.error("There were less parameter in '%s' than in other blocks, that does not work. Parameter left (cleaned -> without (us) or (ms)!): %s." %("%s%s" % (block,counter),parameterArrayCopy)) + os._exit(-1) + else: + for param in parameterArrayCopy: + dataDict["data"]["%s%s" % (block,counter)].insert(list(dataDict["cat"]).index(param),"-") + firstRun = False + return dataDict + +# Generate resulting html table for single measurement page +def generate_results_table_single(dict, logger): + templateDict={} + templateDict["results_table_name"] = "General results:" + templateDict["block_results_table_name"] = "Block results:" + if dict["dbDesc"] != "": + templateDict["dbdesc_name"] = "Database Description:" + templateDict["dbdesc"] = dict["dbDesc"] + if dict["description"] != "": + templateDict["description_name"] = "Description:" + templateDict["description"] = dict["description"] + if dict["errors"] != []: + templateDict["errors_name"] = "Erros:" + templateDict["errors"] = "" + for error in dict["errors"]: + templateDict["errors"] += "%s
" %(error) + if dict["warnings"] != []: + templateDict["warnings_name"] = "Warnings:" + templateDict["warnings"] = "" + for warning in dict["warnings"]: + templateDict["warnings"] += "%s
" %(warning) + if dict["exceptions"] != []: + templateDict["exceptions_name"] = "Exceptions:" + templateDict["exceptions"] = "" + for exception in dict["exceptions"]: + templateDict["exceptions"] += "%s
" %(exception) + templateDict["title"] = "%s_%s_%s" %(dict["dbName"], dict["workload"], dict["startTime"].strftime("%Y%m%d%H%M")) + # Generate 'General' Results Table + tableHtml="Parametername:Value:" + tableHtml+="" + for key in dict.keys(): + if key != "blocks": + tableHtml+="%s%s" % (key,dict[key]) + tableHtml+="" + templateDict["results_table"] = tableHtml + # Generate 'Block' Results Table + # which means results of every block + # no histogram/timeseries data ('LatencyList'), only more general values like throughput,etc. + paramDict={} # dict of parameterName : [value1,value2..] -> represents table rows! + firstRun=True # check if all blocks have all parameters (same parameter set) + # creates dict for html table, every key has an array of one row + for block in dict["blocks"]: + for index in range(0,len(dict["blocks"][block])): + tmpparamDict = paramDict.copy() #check if all entries were there, if not use "-" + for param in dict["blocks"][block][index]: + if param == "LatencyList": + continue + if param not in paramDict.keys(): + if not firstRun: + logger.error("Found '%s' in '%s%s' which other blocks do not have." %(param,block,index)) + os._exit(-1) + paramDict[param]=[dict["blocks"][block][index][param]] + else: + paramDict[param].append(dict["blocks"][block][index][param]) + if dict["blocks"][block][index][param] == -1 and param in possibleMissingParams : + if dict["warnings"] == []: + templateDict["warnings_name"] = "Warnings:" + templateDict["warnings"] = "" + paramStr = "" + for possibleMissingParam in possibleMissingParams: + paramStr += ", %s" %(possibleMissingParam) + paramStr = paramStr[2:] + templateDict["warnings"] += "%s
" %("Values of -1 for %s means that these values were not calculated by ycsb, mostly due to query times longer than the given bucketsize." %(paramStr)) + if not firstRun: + tmpparamDict.pop(param) + # Fix missing parameters for this row + if not firstRun: + for key in tmpparamDict: + paramDict[key].append("-") + firstRun = False + + # counting amount of columns needed + tableColumnsCounter = 1 # 1 because left column is already there + indexSaver = 0 # Saves next index in case of row break + indexMax = 0 + tableHtml="" + for block in dict["blocks"]: + for index in dict["blocks"][block]: + indexMax += 1 + while indexSaver < indexMax: + if indexSaver+tableColumnsCounter > indexMax: + break + if tableColumnsCounter >= maxTableColumnsSingle: + indexSaver+=tableColumnsCounter-1 + if indexSaver >= indexMax: + break + tableColumnsCounter = 1 + tableHtml+="" + for k in range(0,maxTableColumnsSingle+1): + tableHtml+="" + tableHtml+="" + continue + tableHtml+="Parametername:" + indexCounter=0 # to find the right index again + for block in dict["blocks"]: + for index in range(0,len(dict["blocks"][block])): + if indexCounter >= indexSaver: + if tableColumnsCounter >= maxTableColumnsSingle: + break + else: + tableHtml+="%s%s:" % (block,index) + tableColumnsCounter += 1 + + indexCounter+=1 + tableHtml+="" + tableHtml+="" + for key in paramDict.keys(): + tableHtml+="%s" % (key) + tableColumnsCounter2 = 1 + indexCounter2=0 # to find the right index again + for number in paramDict[key]: + if indexCounter2 >= indexSaver: + if tableColumnsCounter2 >= maxTableColumnsSingle: + break + else: + tableHtml+="%s" % (number) + tableColumnsCounter2+=1 + indexCounter2+=1 + tableHtml+="" + + tableHtml+="" + templateDict["block_results_table"] = tableHtml + return templateDict + +# Generate resulting html table for multi measurement page +def generate_results_table_multi(dicts, fileName, logger): + dataDictBlocks = {} + # structure of dataDictBlocks should look like this: + # + # -> "data" + # -> + # -> [1,2,3] + # ... + # ... + # -> "cat" + # -> + # -> ... + # e.g. "INSERT0" + # e.g. "MySQL" + # e.g. "AvgLatency" + # we do the same here as for multi dict block plots + generate_block_data(dataDictBlocks, dicts, False, True, logger) + + templateDict={} + templateDict["results_table_name"] = "General results:" + templateDict["block_results_table_name"] = "Block results:" + templateDict["title"] = fileName + if len(dicts.keys()) > 0: + if dicts[dicts.keys()[0]]["description"] != "": + templateDict["description_name"] = "Description:" + templateDict["description"] = dicts[dicts.keys()[0]]["description"] + templateDict["dbdesc_name"] = "Database Descriptions:" + dbDescStr = "" + counter=0 + for dbKey in sorted(dicts.keys()): + if counter%2 == 0: + dbDescStr += "" + dbDescStr += "" %(dicts[dbKey]["dbName"],dicts[dbKey]["dbDesc"]) + if counter%2 != 0: + dbDescStr += "" + counter+=1 + templateDict["dbdesc"] = dbDescStr + "
%s:%s
" + errorsOccurred = False + errors = [] + warningsOccurred = False + warnings = [] + exceptionsOccurred = False + exceptions = [] + for dictKey in sorted(dicts.keys()): + if dicts[dictKey]["errors"] != []: + errorsOccurred = True + errors.append(dictKey) + if dicts[dictKey]["warnings"] != []: + warningsOccurred = True + warnings.append(dictKey) + if dicts[dictKey]["exceptions"] != []: + exceptionsOccurred = True + exceptions.append(dictKey) + if errorsOccurred: + templateDict["errors"] = "Errors occured in some of the measurements (%s)." %(errors) + if warningsOccurred: + templateDict["warnings"] = "Warnings occured in some of the measurements (%s)." %(warnings) + # Search for -1 in 95th and 99th Percentiles + minus1Occured = False + for blockType in dataDictBlocks.keys(): + if "99Perc." in dataDictBlocks[blockType]["cat"] or \ + "95Perc." in dataDictBlocks[blockType]["cat"]: + for dbKey in dataDictBlocks[blockType]["data"].keys(): + if dataDictBlocks[blockType]["data"][dbKey][dataDictBlocks[blockType]["cat"].index("99Perc.")] == -1 or \ + dataDictBlocks[blockType]["data"][dbKey][dataDictBlocks[blockType]["cat"].index("95Perc.")] == -1: + minus1Occured = True + if minus1Occured: + if "warnings" not in templateDict.keys() or templateDict["warnings"] == None or templateDict["warnings"] == "": + templateDict["warnings"] = "Warning: %s" %("Values of -1 for 99Perc. or 95Perc. means that these values were not calculated by ycsb, mostly due to query times longer than the given bucketsize.") + else: + templateDict["warnings"] += "
Warning:%s" %("Values of -1 for 99Perc. or 95Perc. means that these values were not calculated by ycsb, mostly due to query times longer than the given bucketsize.") + + if exceptionsOccurred: + templateDict["exceptions"] = "Exceptions occured in some of the measurements (%s)." %(exceptions) + # generate for every block one table: + tableHtml="

Block results:

" + for blockType in dataDictBlocks.keys(): + tableColumnsCounter = 1 # 1 because left column is already there + indexSaver = 0 # Saves next index in case of row break + tableHtml+="

%s

" %(blockType) + while indexSaver < len(sorted(dataDictBlocks[blockType]["data"].keys())): + if tableColumnsCounter > len(dataDictBlocks[blockType]["data"].keys()): + break + if tableColumnsCounter >= maxTableColumnsMulti: + indexSaver+=tableColumnsCounter-1 + if indexSaver >= len(dataDictBlocks[blockType]["data"].keys()) : + break + tableColumnsCounter = 1 + tableHtml+="" + for k in range(0,maxTableColumnsMulti+1): + tableHtml+="" + tableHtml+="" + continue + # print blockType + tableHtml+="" + indexCounter=0 # to find the right index again + # go through all dbs + for dbKey in sorted(dataDictBlocks[blockType]["data"].keys()): + if indexCounter >= indexSaver: + if tableColumnsCounter >= maxTableColumnsMulti: + break + else: + tableHtml+="" % (dbKey) + tableColumnsCounter += 1 + indexCounter+=1 + tableHtml+="" + tableHtml+="" + # go through all parameters + for param in dataDictBlocks[blockType]["cat"]: + tableHtml+="" % (param) + tableColumnsCounter2 = 1 + indexCounter2=0 # to find the right index again + for dbKey in sorted(dataDictBlocks[blockType]["data"].keys()): + if indexCounter2 >= indexSaver: + if tableColumnsCounter2 >= maxTableColumnsMulti: + break + else: + tableHtml+="" % (dataDictBlocks[blockType]["data"][dbKey][dataDictBlocks[blockType]["cat"].index(param)]) + tableColumnsCounter2+=1 + indexCounter2+=1 + tableHtml+="" + tableHtml+="
Parametername:%s:
%s%s
" + templateDict["block_results_table"] = tableHtml + # generate general result table + tableHtml="

General results:

" + parameterArr = [] + ignoreParams = ["blocks"] # ignore complete + subParams = ["timeseries","granularity", "bucket"] # substitute with "-" + valueDict = {} # every table row should be inside + firstRound = True # again to check that every dict has every parameter + dbNameKey = "dbNameKey" # some name that identifies our dbName row + for dictKey in dicts: + if dbNameKey not in valueDict.keys(): + valueDict[dbNameKey] = [dictKey] + elif dbNameKey in valueDict.keys() and firstRound: + logger.error("A parameter is named 'dbNameKey', please change it. Abort.") + os._exit(-1) + else: + valueDict[dbNameKey].append(dictKey) + copyParameterArr = list(parameterArr) #real copy to check if nothings missing + for key in dicts[dictKey]: + if key in ignoreParams: + continue + if firstRound: + if key not in parameterArr: + parameterArr.append(key) + else: + try: + copyParameterArr.remove(key) + except Exception, e: + logger.error("Error: '%s' has too many keys." %(key), exc_info=True) + os._exit(-1) + if key not in valueDict.keys(): + valueDict[key] = [dicts[dictKey][key]] + else: + valueDict[key].append(dicts[dictKey][key]) + if not firstRound: + if len(copyParameterArr) > 0: + for arg in list(copyParameterArr): #copy otherwise removing kills it + if arg in subParams: + valueDict[arg].append("-") + copyParameterArr.remove(arg) + if len(copyParameterArr) == 0: + continue + logger.error("Error: '%s' has too less keys. Left: '%s'" %(dictKey, copyParameterArr), exc_info=True) + os._exit(-1) + firstRound = False + + tableColumnsCounter = 1 # 1 because left column is already there + indexSaver = 0 # Saves next index in case of row break + #print valueDict + for rowKey in valueDict: + if tableColumnsCounter > len(valueDict[dbNameKey]): + break + if tableColumnsCounter >= maxTableColumnsMulti: + indexSaver+=tableColumnsCounter-1 + if indexSaver >= len(valueDict[dbNameKey]) : + break + tableColumnsCounter = 1 + tableHtml+="" + for k in range(0,maxTableColumnsMulti+1): + tableHtml+="" + tableHtml+="" + tableHtml+="" + continue + indexCounter=0 # to find the right index again + # go through all dbs + for dbKey in sorted(valueDict[dbNameKey]): + if indexCounter >= indexSaver: + if tableColumnsCounter >= maxTableColumnsMulti: + break + else: + tableHtml+="" % (dbKey) + tableColumnsCounter += 1 + indexCounter+=1 + tableHtml+="" + tableHtml+="" + # go through all parameters + for param in sorted(valueDict.keys()): + if param == dbNameKey: + continue + tableHtml+="" % (param) + tableColumnsCounter2 = 1 + indexCounter2=0 # to find the right index again + for value in valueDict[param]: + if indexCounter2 >= indexSaver: + if tableColumnsCounter2 >= maxTableColumnsMulti: + break + else: + tableHtml+="" % (value) + tableColumnsCounter2+=1 + indexCounter2+=1 + tableHtml+="" + tableHtml+="
Parametername:
Parametername:%s:
%s%s
" + templateDict["general_results_table"] = tableHtml + return templateDict + +def generate_pdf(htmlFile, overwrite, pdfOptions, logger): + if not Util.check_file_exists(htmlFile): + logger.error("Html file does not exist: '%s'" %(htmlFile)) + os._exit(-1) + pdfOptions["title"]= "%s" %(os.path.splitext(os.path.basename(htmlFile))[0]) + pdfFile="%s.pdf" % (pdfOptions["title"]) + if Util.check_file_exists(pdfFile) and not overwrite: + logger.error("Pdf file does already exist: '%s'. Use overwrite flag or delete it." %(pdfFile)) + os._exit(-1) + try: + pdfkit.from_file(htmlFile,pdfFile,options=pdfOptions) + except Exception, e: + logger.error("Failed to produce pdf file '%s.pdf'" %(pdfFile), exc_info=True) + os._exit(-1) + +def openCompressedFile(ycsbfile, dict, key, decompress, overwrite, logger): + try: + file = gzip.open(ycsbfile,"r") + dict[key]=cPickle.load(file) + file.close() + except Exception, e: + logger.error("Can't open '%s'. Is it really a compressed .ydc file?" %(ycsbfile), exc_info=True) + os._exit(-1) + # if you truly just want to decompress it, stop after saving plain ycsb file + if decompress: + try: + newFileName=os.path.splitext(os.path.basename(ycsbfile))[0]+".log" + if (not Util.check_file_exists(newFileName) or overwrite) and os.access(".", os.W_OK): + if key in dict.keys() and dict[key] != None: + decompressFile(dict[key], newFileName, logger) + else: + logger.error("Dictionary does not have filecontent or is null." , exc_info=True) + os._exit(-1) + else: + logger.error("Can't create '%s' to write. Does it already exist?" %(newFileName), exc_info=True) + os._exit(-1) + except Exception, e: + logger.error("Can't open '%s'." %("%s.log.log" %(os.path.basename(ycsbfile))), exc_info=True) + os._exit(-1) + +def decompressFile(fileDict, newFileName,logger): + neededKeys = ["timeseries","granularity","description","bucket","startTime","startLoadTime","runtimeLoad", + "throughputLoad","description","endLoadTime","startRunTime","runtimeRun","throughputRun", + "description","endRunTime", "endTime", "spaceBegin", "blocks", "errors", "warnings", "exceptions"] + neededBlockKeys = ["Operations","LatencyList","MaxLatency(us)","MinLatency(us)","99thPercentileLatency(us)", + "95thPercentileLatency(us)", "AverageLatency(us)"] + # return not in this list, as CLEANUP blocks have no return + for key in neededKeys: + if key not in fileDict.keys(): + logger.error("'%s' is missing in ydc file, abort." %(key)) + return False + file = open("%s" % (newFileName), "w") + if "timeseries" in fileDict.keys(): + if fileDict["timeseries"]: + file.write("TIMESERIES: 1\n") + else: + file.write("TIMESERIES: 0\n") + if "granularity" in fileDict.keys(): + file.write("GRANULARITY: %s\n" %(fileDict["granularity"])) + if "dbDesc" in fileDict.keys(): + des=fileDict["dbDesc"] + if des[-1] == "\n": + des = des[:-1] + file.write("DESCRIPTION: %s\n" %(des)) + if "bucket" in fileDict.keys(): + file.write("BUCKET: %s\n" %(fileDict["bucket"])) + if "startTime" in fileDict.keys(): + file.write("START: %s: Start Test\n" %(fileDict["startTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "startLoadTime" in fileDict.keys(): + file.write("START: %s: Start Load\n" %(fileDict["startLoadTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "runtimeLoad" in fileDict.keys(): + file.write("[OVERALL], RunTime(ms), %s\n" %(fileDict["runtimeLoad"])) + if "throughputLoad" in fileDict.keys(): + file.write("[OVERALL], Throughput(ops/sec), %s\n" %(fileDict["throughputLoad"])) + ## load blocks + for key in ["CLEANUP", "INSERT" ]: + if key in fileDict["blocks"] and len(fileDict["blocks"][key]) > 0: + for key2 in neededBlockKeys: + if key2 not in fileDict["blocks"][key][0].keys(): + logger.error("'%s' is missing in ydc file block '%s'0, abort." %(key2, key)) + return False + if "Operations" in fileDict["blocks"][key][0].keys(): + file.write("[%s], Operations, %s\n" %(key,fileDict["blocks"][key][0]["Operations"])) + if "AverageLatency(us)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], AverageLatency(us), %s\n" %(key,fileDict["blocks"][key][0]["AverageLatency(us)"])) + if "MinLatency(us)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], MinLatency(us), %s\n" %(key,fileDict["blocks"][key][0]["MinLatency(us)"])) + if "MaxLatency(us)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], MaxLatency(us), %s\n" %(key,fileDict["blocks"][key][0]["MaxLatency(us)"])) + if "95thPercentileLatency(us)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], 95thPercentileLatency(us), %s\n" %(key,fileDict["blocks"][key][0]["95thPercentileLatency(us)"])) + if "99thPercentileLatency(us)" in fileDict["blocks"][key][0].keys(): + file.write("[%s], 99thPercentileLatency(us), %s\n" %(key,fileDict["blocks"][key][0]["99thPercentileLatency(us)"])) + if "Return" in fileDict["blocks"][key][0].keys(): + for returnVal in fileDict["blocks"][key][0]["Return"]: + file.write("[%s], Return=%s, %s\n" %(key,returnVal[0],returnVal[1])) + if "LatencyList" in fileDict["blocks"][key][0].keys(): + for counter in range(0,len(fileDict["blocks"][key][0]["LatencyList"])-1): + file.write("[%s], %s, %s\n" %(key, counter, fileDict["blocks"][key][0]["LatencyList"][counter])) + file.write("[%s], >%s, %s\n" %(key, len(fileDict["blocks"][key][0]["LatencyList"])-1, fileDict["blocks"][key][0]["LatencyList"][-1])) + # block latency data + if "description" in fileDict.keys(): + des=fileDict["description"] + if des[-1] == "\n": + des = des[:-1] + file.write("[DESCRIPTION], %s\n" %(des)) + if "endLoadTime" in fileDict.keys(): + file.write("END: %s: End Load\n" %(fileDict["endLoadTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "startRunTime" in fileDict.keys(): + file.write("START: %s: Start Run\n" %(fileDict["startRunTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "runtimeRun" in fileDict.keys(): + file.write("[OVERALL], RunTime(ms), %s\n" %(fileDict["runtimeRun"])) + if "throughputRun" in fileDict.keys(): + file.write("[OVERALL], Throughput(ops/sec), %s\n" %(fileDict["throughputRun"])) + ## run blöcke + for key in ["CLEANUP", "INSERT", "READ", "UPDATE", "SCAN", "AVG", "SUM", "COUNT"]: + if key in fileDict["blocks"] and len(fileDict["blocks"][key]) > 0: + for index in range(0,len(fileDict["blocks"][key])): + if index == 0 and key in ["CLEANUP", "INSERT" ]: + # First Cleanup/Insert block is from load phase -> ignore it + continue + for key2 in neededBlockKeys: + if key2 not in fileDict["blocks"][key][index].keys(): + logger.error("'%s' is missing in ydc file block '%s'0, abort." %(key2, key)) + return False + if "Operations" in fileDict["blocks"][key][index].keys(): + file.write("[%s], Operations, %s\n" %(key,fileDict["blocks"][key][index]["Operations"])) + if "AverageLatency(us)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], AverageLatency(us), %s\n" %(key,fileDict["blocks"][key][index]["AverageLatency(us)"])) + if "MinLatency(us)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], MinLatency(us), %s\n" %(key,fileDict["blocks"][key][index]["MinLatency(us)"])) + if "MaxLatency(us)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], MaxLatency(us), %s\n" %(key,fileDict["blocks"][key][index]["MaxLatency(us)"])) + if "95thPercentileLatency(us)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], 95thPercentileLatency(us), %s\n" %(key,fileDict["blocks"][key][index]["95thPercentileLatency(us)"])) + if "99thPercentileLatency(us)" in fileDict["blocks"][key][index].keys(): + file.write("[%s], 99thPercentileLatency(us), %s\n" %(key,fileDict["blocks"][key][index]["99thPercentileLatency(us)"])) + if "Return" in fileDict["blocks"][key][index].keys(): + for returnVal in fileDict["blocks"][key][index]["Return"]: + file.write("[%s], Return=%s, %s\n" %(key,returnVal[index],returnVal[1])) + if "LatencyList" in fileDict["blocks"][key][index].keys(): + for counter in range(0,len(fileDict["blocks"][key][index]["LatencyList"])-1): + file.write("[%s], %s, %s\n" %(key, counter, fileDict["blocks"][key][index]["LatencyList"][counter])) + file.write("[%s], >%s, %s\n" %(key, len(fileDict["blocks"][key][index]["LatencyList"])-1, fileDict["blocks"][key][index]["LatencyList"][-1])) + if "description" in fileDict.keys(): + des=fileDict["description"] + if des[-1] == "\n": + des = des[:-1] + file.write("[DESCRIPTION], %s\n" %(des)) + if "endRunTime" in fileDict.keys(): + file.write("END: %s: End Run\n" %(fileDict["endRunTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "endTime" in fileDict.keys(): + file.write("END: %s: End Test\n" %(fileDict["endTime"].strftime('%a %b %d %H:%M:%S %Z %Y'))) + if "errors" in fileDict.keys(): + for line in fileDict["errors"]: + line2 = line + if line2[-1] == "\n": + line2=line2[:-1] + file.write("%s\n" %(line2)) + if "exceptions" in fileDict.keys(): + for line in fileDict["exceptions"]: + line2 = line + if line2[-1] == "\n": + line2=line2[:-1] + file.write("%s\n" %(line2)) + if "warnings" in fileDict.keys(): + for line in fileDict["warnings"]: + line2 = line + if line2[-1] == "\n": + line2=line2[:-1] + file.write("%s\n" %(line2)) + if "spaceBegin" in fileDict.keys() and "spaceBetween" in fileDict.keys() and "spaceEnd" in fileDict.keys(): + file.write("SPACE: %s %s %s\n" %(fileDict["spaceBegin"],fileDict["spaceBetween"],fileDict["spaceEnd"])) + file.flush() + file.close() + + +# Generates (html, pdf) Output for every single measurement file +def generate_single_output(dict, templateFile, name, timeseries, overwrite, pdfOptions, logger): + if args.debug: + Util.log_timestamp("Start Generating Single Plot",logger) + p = generate_plot_single(dict, timeseries, logger) + if p == None: + logger.error("Can't generate plots for %s." %(name)) + return + if args.debug: + Util.log_timestamp("Start Generating Single Results Table",logger) + templateDict = generate_results_table_single(dict, logger) + if args.debug: + Util.log_timestamp("Start Generating HTML File",logger) + # Generating html + generate_html(p, templateFile, templateDict, "%s.html" % (name), overwrite, logger) + # Generating pdf (if wanted) + if args.pdf: + if args.debug: + Util.log_timestamp("Start Generating PDF File",logger) + generate_pdf("%s.html" % (name), overwrite, pdfOptions, logger) + +# Generates (html, pdf) Output for multi (combined) measurement files +def generate_multi_output(dicts, templateFile, timeseries, overwrite, logger, granularity=1000): + granularity=granularity + ts=None + for dictKey in dicts.keys(): + if "granularity" in dicts[dictKey].keys(): + granularity = dicts[dictKey]["granularity"] + if ts == None and "timeseries" in dicts[dictKey].keys(): + ts = dicts[dictKey]["timeseries"] + elif ts != None and "timeseries" in dicts[dictKey].keys() and ts != dicts[dictKey]["timeseries"]: + logger.error("Found one timeseries and one non timeseries type. Abort.") + exit(-1) + if not ts and timeseries: + logger.error("Found at least one non timeseries type and timeseries flag is set. Abort.") + exit(-1) + if ts == None and timeseries: + ts = True + elif ts == None: + ts = False + fileName = "ycsb_combined_%s" % (datetime.datetime.now().strftime("%Y%m%d%H%M")) + p = generate_plot_multi(dicts, ts, logger, ) + templateDict = generate_results_table_multi(dicts, fileName, logger) + # Generating html + generate_html(p, templateFile, templateDict, "%s.html" % (fileName), overwrite, logger) + +# Configure ArgumentParser +parser = argparse.ArgumentParser(prog="ProcessYcsbLog.py",version=__version__,description="Generates a nice pdf out of YCSB's output.", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="") +parser.add_argument("-l", "--log", action='store_true', help="Be more verbose") +parser.add_argument("-t", "--timeseries", action='store_true', help="Use this flag if you generated timeseries instead of a histogram in ycsb") +parser.add_argument("-f", "--ycsbfiles", metavar="YCSBFILE", nargs='+', required=True, help="Path to YCSB file(s) (can be ycsb outputfile, compressed .ydc file)") +parser.add_argument("-d", "--decompress", action='store_true', help="Decompress ycsb file out of given ydc file") +parser.add_argument("-c", "--compress", action='store_true', help="Stop after making compressed ydc file (do not generate plots/html/pdf)") +parser.add_argument("-o", "--overwrite", action='store_true', help="Overwrite existing files") +parser.add_argument("-p", "--pdf", action='store_true', help="Generate PDF file. (otherwise only pdf is generated)") +parser.add_argument("-s", "--single", action='store_true', help="if given multiple files, also generate single html/pdf for each") +parser.add_argument("--debug", action='store_true', help="Be much more verbose, print timestamps. (also activates -l)") +args = parser.parse_args() + +if args.debug: + args.log=True + +# Configure Logging +logLevel = logging.WARN +if args.log: + logLevel = logging.DEBUG +if args.debug: + FORMAT = '%(asctime)-15s: %(message)s' + logging.basicConfig(level=logLevel,format=FORMAT) +else: + logging.basicConfig(level=logLevel) +logger = logging.getLogger(__name__) + +if args.debug: + Util.log_timestamp("Start",logger) + +# delete non unique files, even if they're given as ycb output and ydc +for ycsbfile in args.ycsbfiles: + if args.ycsbfiles.count("%s.ydc" %(os.path.splitext(os.path.basename(ycsbfile))[0])) \ + + args.ycsbfiles.count("%s.log" %(os.path.splitext(os.path.basename(ycsbfile))[0])) \ + > 1: + args.ycsbfiles.remove(ycsbfile) + logger.warning("'%s' exists more than once (as .log or .ydc), ignoring it." %(ycsbfile)) + +dicts={} +nameDict={} # stores names for dictKeys +threads=[] +if args.debug: + Util.log_timestamp("Start Loading/Parsing Files",logger) +for ycsbfile in args.ycsbfiles: + # Compressing Output + mime = magic.open(magic.MAGIC_MIME) + mime.load() + try: + basename="%s" %("_".join(os.path.splitext(os.path.basename(ycsbfile))[0].split("_")[1:-2])) + except IndexError: + logger.warning("'%s' is not a normal filename for ycsb-ts logfiles." %(os.path.basename(ycsbfile))) + basename="%s" %(os.path.splitext(os.path.basename(ycsbfile))[0]) + except: + logger.error("Can't process filename '%s' as basename." %(os.path.basename(ycsbfile))) + os._exit(-1) + if basename in dicts.keys(): + basename="%s_%s" %(basename,dicts.keys().count(basename)+1) + if mime.file(ycsbfile) == "text/plain; charset=us-ascii" or mime.file(ycsbfile) == "text/plain; charset=utf-8": + newFileName="%s.ydc" %(os.path.splitext(os.path.basename(ycsbfile))[0]) + # if it is an plain ycsb file, compress it + logger.info("Found Mime type '%s' in '%s'." %(ycsbfile,mime.file(ycsbfile))) + if (not Util.check_file_exists(newFileName) or args.overwrite) and os.access(".", os.W_OK): + dicts[basename] = {} + nameDict[basename]=os.path.splitext(os.path.basename(ycsbfile))[0] + threads.append(threading.Thread(target=process_file, args=(ycsbfile, args.timeseries, dicts[basename], newFileName, logger))) + threads[-1].setDaemon(True) + threads[-1].start() + else: + logger.error("Can't create '%s' to write. Does it already exist?" %(newFileName), exc_info=True) + exit(-1) + elif mime.file(ycsbfile) == "application/gzip; charset=binary": + # if a compressed file is found do decompress or graph + logger.info("Found Mime type '%s' in '%s'." %(ycsbfile,mime.file(ycsbfile))) + # if decompress is what you want... + if Util.check_file_exists(ycsbfile) and os.access(ycsbfile, os.R_OK): + dicts[basename] = {} + nameDict[basename]=os.path.splitext(os.path.basename(ycsbfile))[0] + threads.append(threading.Thread(target=openCompressedFile, args=(ycsbfile, dicts, basename, args.decompress, args.overwrite, logger))) + threads[-1].setDaemon(True) + threads[-1].start() + else: + logger.error("Can't open '%s'. Does it exist?" %(ycsbfile), exc_info=True) + exit(-1) + + else: + logger.error("%s has an unkown mimetype '%s', sure it is a ycsb log or .ydc file?" %(ycsbfile,mime.file(ycsbfile))) + exit(-1) +# Wait until all threads are done +logger.debug("Waiting until all files are loaded...") +# only join() would make ctrl+c not work in combination with daemon=true +# Main thread is always there, because of that: >1 +while threading.activeCount() > 1: + for thread in threads: + thread.join(100) +threads=[] +if args.debug: + Util.log_timestamp("End Loading/Parsing Files",logger) + +# if only compression/decompression is requested, do it and exit +if args.compress or args.decompress: + exit(0) + +if (len(args.ycsbfiles)==1 and len(dicts.keys())==1) or (len(args.ycsbfiles)>1 and args.single): + if args.debug: + Util.log_timestamp("Start Generating Single HTML File",logger) + for key in dicts.keys(): + # at this stage we should have something in dict, wheter it was from a plain ycsb file or from a compressed ydc file + # Generating Graph + if maxTableColumnsSingle < 2: + logger.error("maxTableColumnsSingle has to be > 1") + exit(-1) + threads.append(threading.Thread(target=generate_single_output, + args=(dicts[key], templateFile, nameDict[key], + args.timeseries, args.overwrite, pdfOptions.copy(), logger))) + threads[-1].setDaemon(True) + threads[-1].start() + +if len(args.ycsbfiles)>1: + if len(dicts.keys())==len(args.ycsbfiles): + logger.info("Found more than one ycsb/ydc file, doing combined stuff...") + if args.debug: + Util.log_timestamp("Start Generating Multiple HTML Files",logger) + if maxTableColumnsMulti < 2: + logger.error("maxTableColumnsMulti has to be > 1") + exit(-1) + # in dicts there should be every ycsbfile now + # First check: are both non timeseries or timeseries + # 3 cases that are allowed: + # - all are set as timeseries + # - all are set as non-timeseries + # - all have no flag set and are just used as histogram or forced to be used as timeseries by flag + # Case 1 and 2: + threads.append(threading.Thread(target=generate_multi_output, + args=(dicts, templateFileMulti, args.timeseries, args.overwrite, logger))) + threads[-1].setDaemon(True) + threads[-1].start() + else: + logger.error(" %s Files and %s Dicts do not match, this should not happen." %(len(args.ycsbfiles),len(dicts.keys()))) + exit(-1) + +# Wait until all threads are done +logger.debug("Waiting until all .html/.pdf files are generated...") +# only join() would make ctrl+c not work in combination with daemon=true +# Main thread is always there, because of that: >1 +while threading.activeCount() > 1: + for thread in threads: + thread.join(100) +if args.debug: + Util.log_timestamp("End Generating HTML File(s)",logger) + + +exit(0) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c8674fa --- /dev/null +++ b/README.md @@ -0,0 +1,132 @@ +# TSDBBench +The Python and Vagrant part of TSDBBench + +The VMs are running on vSphere or Openstack, but you can choose to run TSDBBench.py on your local pc or on a Control VM. + +# Setup Elastic Infrastrcture +For your elastic infrastructure you need image(s) as bases for vagrant to derive generator and tsdb vms from. You can choose wheter you want to use vSohere or Openstack, you don't need both. + +1. Create/Copy images: + - All images are available at http://nemarcontrolvm.iaas.uni-stuttgart.de/isos/, you can use them directly from there (no need to download to your local pc!). + - for vSphere: + - Copy http://nemarcontrolvm.iaas.uni-stuttgart.de/isos/debian-8.1.0-amd64-netinst-vsphere-autoinstall.iso to your vSphere datastore + - for Openstack: + - Copy http://nemarcontrolvm.iaas.uni-stuttgart.de/isos/debian-8.1.0-amd64-netinst-openstack-autoinstall.qcow2 to your images in Openstack + - If you still want to create own images (changed preseed file e.g.) (run on your local pc): + - for vSphere: + + cd /path/to/another/folder/ + wget http://cdimage.debian.org/debian-cd/8.2.0/amd64/iso-cd/debian-8.2.0-amd64-netinst.iso + cd /path/to/some/folder/ + git clone https://github.com/baderas/TSDBBench + cd TSDBBench + ./MakeDebianIso.py -t /path/to/tmpfolder -i /path/to/another/folder/debian-8.2.0-amd64-netinst.iso -f /path/to/outputfolder/ -p preseed-vsphere.cfg + - for Openstack + + sudo apt-get install qemu-kvm libvirt-bin + sudo gpasswd -a $USER kvm + sudo gpasswd -a $USER libvirt + sudo reboot (or logout and login) + cd /path/to/another/folder/ + wget http://cdimage.debian.org/debian-cd/8.2.0/amd64/iso-cd/debian-8.2.0-amd64-netinst.iso + cd /path/to/some/folder/ + git clone https://github.com/baderas/TSDBBench + cd TSDBBench + ./MakeDebianIso.py -t /path/to/tmpfolder -i /path/to/another/folder/debian-8.2.0-amd64-netinst.iso -f /path/to/outputfolder/ -p preseed-openstack.cfg + ./MakeDebianQcow2.py -i /path/to/outputfolder/debian-8.2.0-amd64-netinst-openstack-autoinstall.iso -f /path/to/outputfolder/ + upload the resulting file to your Openstack Storage +2. (Only for vSphere) Create templates (run on your local pc): + + cd /path/to/some/folder/ + git clone https://github.com/baderas/TSDBBench + cd TSDBBench + nano vagrant_files/vagrantconf.rb (add everything that says '') + nano vagrant_files/vagrantconf_db.rb (add everything that says '') + nano vagrant_files/vagrantconf_gen.rb (add everything that says '') + ./pySetupVsphere.py -f /path/to/some/folder/TSDBBench/vagrant_files/ + +# Setup +Everything was tested and used on Debian Jessie x64, but should work on Ubuntu. But Ubuntu has different package names for a lot of the packages, you need to find and change them! +## Choice 1: local pc +1. Install packages: + + sudo apt-get install python-dateutil python-jinja2 python-numpy python-pandas python-flask python-redis python-requests python-six python-tornado python-werkzeug python-markupsafe python-greenlet python-zmq python-yaml python-pip wkhtmltopdf python-magic fabric vagrant zlib1g-dev zlib1g libxml2 libxml2-dev libxslt1.1 libxslt1-dev python-webcolors python-pyvmomi +2. Install pip packages: + + sudo pip install bokeh python-vagrant pdfkit +3. Install vagrant plugins: + + vagrant plugin install vagrant-vsphere + vagrant plugin install vagrant-openstack-provider +4. Reconfigure locales and make sure that en_US.UTF-8 is generated + + sudo dpkg-reconfigure locales +5. Checking out & Prepairing Git Repo + + cd /path/to/some/folder/ + git clone https://github.com/baderas/TSDBBench + cd TSDBBench + vagrant box add --name dummy dummy.box + copy hooks/pre-commit .git/hooks/ + cd .. +6. Edit Config (change everything that says '') + + cd /path/to/some/folder/TSDBBench + nano vagrant_files/vagrantconf.rb + nano vagrant_files/vagrantconf_db.rb + nano vagrant_files/vagrantconf_gen.rb + +## Choice 2: Control VM + - Coming soon... + +# Running a testworkload + - without creating html file: + + cd /path/to/some/folder/TSDBBench + ./TSDBBench.py -t /path/to/tmpfolder -f /path/to/some/folder/TSDBBench/vagrant_files -d mysql1 -l --provider 'vsphere' -w "testworkloada" + - with creating html file: + + cd /path/to/some/folder/TSDBBench + ./TSDBBench.py -t /path/to/tmpfolder -f /path/to/some/folder/TSDBBench/vagrant_files -d mysql1 -l --provider 'vsphere' -w "testworkloada" -m + +# Creating html files (when not using -m) + - Creating a html file from a ycsb_*.log file: + + cd /path/to/some/folder/TSDBBench + ./ProcessYcsbLog.py -f some_ycsb_logfile.log + + - Creating a html file from a ycsb_*.ydc file: + + cd /path/to/some/folder/TSDBBench + ./ProcessYcsbLog.py -f some_ycsb_logfile.ydc + + - Creating a combined html file a set of from a ycsb_*.ydc/.log files: + + cd /path/to/some/folder/TSDBBench + ./ProcessYcsbLog.py -f some_ycsb_logfile1.ydc ome_ycsb_logfile2.log ome_ycsb_logfile3.ydc ... + +# Steps to add a new TSDB: +for this example consider your new tsdb would be opentsdb: + 1. Add Vagrantfiles: + 1. Create at least one folder in /path/to/some/folder/TSDBBench/vagrant_files + - e.g. opentsdb1 + 2. Create at least one Vagrantfile in this new folder + - named same as the folder but with _ + number + .vagrant as suffix + - e.g. /path/to/some/folder/TSDBBench/vagrant_files/opentsdb1/opentsdb1_0 + 3. In this Vagrantfile put deployment tasks like installing and configuring + - but nothing where you need to know IPs from other nodes of the cluster (that comes later) + 4. Use basic scripts as much as possible + - see /path/to/some/folder/TSDBBench/vagrant_files/basic + 2. Add the python part + 1. Add a python file to /path/to/some/folder/TSDBBench/databases + - named like the folder + .py (.e.g. opentsdb1.py) + 2. In this file you add: + 1. Deployment tasks that requires IPs from all nodes of the cluster + 2. Checks that the database is running + 3. Some basic db configs (everything that starts with db_) + 3. Look at other database python files, there are comments that explain every field in every file + 3. Testing + - You need to copy the database files to /path/to/some/folder/TSDBBench/vagrant_files/generator/files/databases/ + - You can run either run "hooks/pre-commit" or "git commit -a" (runs the hook as well if setup correctly). + + diff --git a/RunWorkload.py b/RunWorkload.py new file mode 100755 index 0000000..56d982c --- /dev/null +++ b/RunWorkload.py @@ -0,0 +1,491 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +## replaces old workload_.sh scripts for better multi vm support + +import argparse +import logging +import databases +from fabric.api import * +import re +import locale +import time + +def clean_exit(code, hostnames, shutdown=True): + if shutdown: + for hostname in hostnames: + run_on_vm(hostname, "/home/vagrant/.ssh/id_rsa", True, "sudo poweroff",logger,False,True,True,False) + exit(code) + +def run_on_vm (hostString, keyFilename, disableKnownHosts,command,logger,warn_only=False,quiet=False,test=False,getResult=False): + # Same as TSDBBench.py run_on_vm + with settings(host_string= hostString, + key_filename = keyFilename, + disable_known_hosts = disableKnownHosts): + result = run(command,warn_only=warn_only, quiet=quiet) + if result.return_code == 0 or (warn_only and result.return_code == 255) or (test and result.return_code == -1): + if getResult: + return result + return True + else: + logger.error("Command '%s' on %s returned %s." %(command, hostString, result.return_code)) + if getResult: + return result + return False + +def run_local (command, logger, test=False, getResult=False): + result = local(command, capture=True) + if result.return_code == 0 or (test and result.return_code == -1): + if getResult: + return result + return True + else: + logger.error("Command '%s' returned %s (local)." %(command, result.return_code)) + if getResult: + return result + return False + +def get_local_ip(logger): + result = run_local('sudo ifconfig | grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" | head -n1',logger,False,True) + if result != None and result != False and result.return_code == 0: + return result.stdout + else: + if result != None and result != False: + logger.error("Can't get local IP. Return Code: '%s' STDOUT: '%s'." %(result.return_code,result.stdout)) + else: + logger.error("Can't get local IP.") + return None + +def check_keys(dict, keys): + foundAll = True + for key in keys: + if key not in dict.keys(): + foundAll = False + return foundAll + +def get_time_file(): + act_loc=locale.getlocale() + try: + locale.setlocale(locale.LC_ALL,'en_US.UTF-8') + except Exception, e: + logger.error('Failed to set locale, do you have locale en_US.UTF-8 installed?', exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + timeStr=time.strftime("%Y%m%d%H%M",time.localtime()) + locale.setlocale(locale.LC_ALL,act_loc) + return timeStr + +def get_time_log(): + act_loc=locale.getlocale() + try: + locale.setlocale(locale.LC_ALL,'en_US.UTF-8') + except Exception, e: + logger.error('Failed to set locale, do you have locale en_US.UTF-8 installed?', exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + timeStr=time.strftime("%a %b %d %H:%M:%S %Z %Y",time.localtime()) + locale.setlocale(locale.LC_ALL,act_loc) + return timeStr + +# gets space for every db for every folder and appends it to spaceDict +def get_space(ips, spaceDict, folders, local): + if local: + space=0 + if "basic" not in spaceDict.keys(): + spaceDict["basic"]=[] + for folder in folders: + spaceStr = run_local("sudo du %s --summarize" %(folder), logger, False, True) + if spaceStr == None or spaceStr == "": + logger.error('Failed to get space for folder %s (local).' %(folder)) + clean_exit(-1, args.ip, not args.noshutdown) + try: + searchRes = re.search("[0-9]+",spaceStr) + if searchRes == None: + logger.error('Failed to get space for folder %s (local).' %(folder)) + clean_exit(-1, args.ip, not args.noshutdown) + try: + space += int(searchRes.group(0)) + except Exception, e: + logger.error("Can't convert %s to int." %(space), exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + except Exception, e: + logger.error('Failed to get space for folder %s (local).' %(folder), exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + spaceDict["basic"] += [space] + else: + for ip in ips: + if ip not in spaceDict.keys(): + spaceDict[ip] = [] + space=0 + for folder in folders: + spaceStr = run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True,"sudo du %s --summarize" %(folder),logger,False,True,False, True) + if spaceStr == None or spaceStr == "": + logger.error('Failed to get space for folder %s for vm %s.' %(folder, ip)) + clean_exit(-1, args.ip, not args.noshutdown) + try: + searchRes = re.search("[0-9]+",spaceStr) + if searchRes == None: + logger.error('Failed to get space for folder %s for vm %s.' %(folder, ip)) + clean_exit(-1, args.ip, not args.noshutdown) + try: + space += int(searchRes.group(0)) + except Exception, e: + logger.error("Can't convert %s to int." %(space), exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + except Exception, e: + logger.error('Failed to get space for folder %s for vm %s.' %(folder, ip), exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + spaceDict[ip] += [space] + +def check_add_space(spaceDict): + listLen = -1 + totalSpace=[] + for key in spaceDict.keys(): + if listLen == -1: + listLen = len(spaceDict[key]) + totalSpace = list(spaceDict[key]) + elif len(spaceDict[key]) != listLen: + logger.error('Got two space lists that do not have the same length. This should not happen.') + clean_exit(-1, args.ip, not args.noshutdown) + else: + for i in range(0,len(spaceDict[key])): + totalSpace[i] += spaceDict[key][i] + return totalSpace + +def make_space_str(spaceList): + spaceStr="" + for element in spaceList: + if spaceStr == "": + spaceStr+="%s" %(element) + else: + spaceStr+=" %s" %(element) + return spaceStr + +def remote_sync(ips): + for ip in ips: + if not run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True,"sudo sync",logger,False,True,False, False): + logger.error('Failed to sync for %s.' %(ip)) + clean_exit(-1, args.ip, not args.noshutdown) + +def local_sync(): + run_local("sudo sync",logger,False) + +def replStr(ips, ip, str, localIp): + commandRepl=str + commandRepl=commandRepl.replace("%%IP%%",ip); + commandRepl=commandRepl.replace("%%IPgen%%",localIp); + ipAll="" + for ipAddr in ips: + ipAll+="%s " %(ip) + ipAll="\"%s\"" %(ipAll[:-1]) + commandRepl=commandRepl.replace("%%IPall%%",ipAll); + findallRes = re.findall("%%IP[0-9]+%%", commandRepl) + for res in findallRes: + searchRes = re.search("[0-9]+", res) + if searchRes != None: + try: + key = int(searchRes.group(0)) + if len(ips) > key: + commandRepl=commandRepl.replace(res,ips[key]); + else: + logger.error('Key to high, not enough ips for key %s.' %(key)) + clean_exit(-1, ips, not args.noshutdown) + except: + logger.error("Can't convert key to int: %s." %(key)) + clean_exit(-1, ips, not args.noshutdown) + else: + logger.error('Failed to find number in %s.' %(res)) + clean_exit(-1, ips, not args.noshutdown) + return commandRepl + +# Configure ArgumentParser +parser = argparse.ArgumentParser(prog="RunWorkload.py",version=__version__,description="replaces old workload_.sh scripts for better multi vm support", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="") +parser.add_argument("-d", "--database", metavar="DATABASE", required=True, help="Process database DATABASE") +parser.add_argument("-w", "--workload", metavar="WORKLOAD", required=True, help="Process workload WORKLOAD") +parser.add_argument("-i", "--ip", metavar="IP", required=True, nargs='+', help="connect to IP; Can be more than one.") +parser.add_argument("-g", "--granularity", metavar="GRANULARITY", type=int, default=1000, help="use TS Granularity") +parser.add_argument("-b", "--bucket", metavar="BUCKET", type=int, default=10000, help="set Bucketsize for histogram measurements") +parser.add_argument("-t", "--timeseries", action='store_true', help="do timeseries instead of histogramm") +parser.add_argument("-n", "--noshutdown", action='store_true', help="Don't shutdown vms at cleanup/exit (for debugging only)") +parser.add_argument("-p", "--prerunonly", action='store_true', help="Stop after prerun.") +parser.add_argument("--debug", action='store_false', help="Debug remote commands.") +args = parser.parse_args() + +logLevel = logging.WARN +logging.addLevelName(31,"TIMESERIES") +logging.addLevelName(32,"GRANULARITY") +logging.addLevelName(33,"BUCKET") +logging.addLevelName(34,"SPACE") +logging.addLevelName(35,"START") +logging.addLevelName(36,"END") +logging.addLevelName(37,"DESCRIPTION") +logger = logging.getLogger(__name__) +handler = logging.FileHandler("/home/vagrant/ycsb_%s_%s_%s.log" %(args.database.lower(), args.workload.lower(), get_time_file())) +handler.setLevel(logLevel) +formatter = logging.Formatter('%(levelname)s: %(message)s') +handler.setFormatter(formatter) +logger.addHandler(handler) +handler = logging.StreamHandler() +handler.setFormatter(formatter) +logger.addHandler(handler) + +dbConfig=databases.getDict(logger) +if dbConfig == None or dbConfig == {}: + clean_exit(-1, args.ip, not args.noshutdown) + +# this is a dict which holds configs (also dicts) for every special database +# format: key -> dbname +# this results in a dict with the following keys: +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +knownKeys=["db_folders","db_client","db_args","db_name","db_desc","jvm_args","prerun_once","postrun_once", "prerun","postrun", "check","prerun_master","postrun_master", "check_master", "prerun_slaves","postrun_slaves", "check_slaves","basic", "prerun_dict", "postrun_dict", "check_dict", "sequence"] + +if args.database.lower() in dbConfig.keys(): + localIp = get_local_ip(logger) + if localIp == None: + logger.error("Can't get local IP, abort.") + clean_exit(-1,args.ip, not args.noshutdown) + # Sort ips once and for all + ips=[] + if len(dbConfig[args.database.lower()]["sequence"]) != len(args.ip): + logger.error("Sequence list has not the same length as IP list. That can not work!") + clean_exit(-1,args.ip, not args.noshutdown) + for ipIdx in dbConfig[args.database.lower()]["sequence"]: + # do not sort here! this would only sort ips/hostnames alphanumerically. they must be come in sorted and then use the given sequence + ips.append(args.ip[ipIdx]) + if not check_keys(dbConfig[args.database.lower()], knownKeys): + logger.error("Some keys are missing for %s" %(args.database.lower())) + clean_exit(-1,ips, not args.noshutdown) + logger.info("Running prerun commands for %s." %(args.database.lower())) + # Prerun once + for command in dbConfig[args.database.lower()]["prerun_once"]: + commandRepl = command + commandRepl = replStr(args.ip, ips[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_local (commandRepl,logger, False) + # Prerun for all vms + for command in dbConfig[args.database.lower()]["prerun"]: + for ip in ips: + commandRepl = command + commandRepl = replStr(args.ip, ip ,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Prerun for master (first) vm + for command in dbConfig[args.database.lower()]["prerun_master"]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[0], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Prerun for slave (all without first) vm + for command in dbConfig[args.database.lower()]["prerun_slaves"]: + ipsWithoutMaster=list(ips) + ipsWithoutMaster.remove(args.ip[0]) + if len(ipsWithoutMaster) > 0: + for ip in ipsWithoutMaster: + commandRepl = command + commandRepl = replStr(args.ip, ip,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + else: + logger.warning("There is only one db vm or more sequence keys than vms, can't run slave prerun commands via ssh.") + # Prerun for dict + for key in dbConfig[args.database.lower()]["sequence"]: + if key in dbConfig[args.database.lower()]["prerun_dict"].keys(): + if len(args.ip) > key: + for command in dbConfig[args.database.lower()]["prerun_dict"][key]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[key],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[key], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + logger.warning("Key to high, not enough IPs to run prerun command for key: %s." %(key)) + # Check for all vms + for command in dbConfig[args.database.lower()]["check"]: + for ip in ips: + commandRepl = command + commandRepl = replStr(args.ip, ip ,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Check for master (first) vm + for command in dbConfig[args.database.lower()]["check_master"]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[0], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Check for slave (all without first) vm + for command in dbConfig[args.database.lower()]["check_slaves"]: + ipsWithoutMaster=list(ips) + ipsWithoutMaster.remove(args.ip[0]) + if len(ipsWithoutMaster) > 0: + for ip in ipsWithoutMaster: + commandRepl = command + commandRepl = replStr(args.ip, ip,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + else: + logger.warning("There is only one db vm or more sequence keys than vms, can't run slave check commands via ssh.") + # Check for dict + for key in dbConfig[args.database.lower()]["sequence"]: + if key in dbConfig[args.database.lower()]["check_dict"].keys(): + if len(args.ip) > key: + for command in dbConfig[args.database.lower()]["check_dict"][key]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[key],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[key], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + logger.warning("Key to high, not enough IPs to run check command for key: %s." %(key)) + if args.prerunonly: + logger.info("Prerun only, stopping here.") + clean_exit(0,ips, not args.noshutdown) + command = "ycsb/bin/ycsb" + if dbConfig[args.database.lower()]["jvm_args"] != None and dbConfig[args.database.lower()]["jvm_args"] != "": + command += " %s" %(dbConfig[args.database.lower()]["jvm_args"]) + command += " %s" # for load/run + command += " %s" %(dbConfig[args.database.lower()]["db_client"]) + command += " -P ycsb/workloads/%s" %(args.workload) + if len(args.ip) > 0: + command += " %s" %(replStr(args.ip, args.ip[0],dbConfig[args.database.lower()]["db_args"], localIp)) + else: + command += " %s" %(dbConfig[args.database.lower()]["db_args"]) + if args.timeseries: + logger.log(31,1) + command += " -p measurementtype=timeseries" + else: + logger.log(31,0) + logger.log(32,args.granularity) + logger.log(37,dbConfig[args.database.lower()]["db_desc"]) + command += " -p timeseries.granularity=%s" %(args.granularity) + logger.log(33,args.bucket) + command += " -p histogram.buckets=%s" %(args.bucket) + spaceDict={} # contains every db vm as key, for every key an List of 3 space values (start, between, end) + logger.log(35,"%s: Start Test" %(get_time_log())) + get_space(ips,spaceDict,dbConfig[args.database.lower()]["db_folders"],dbConfig[args.database.lower()]["basic"]) + logger.log(35,"%s: Start Load" %(get_time_log())) + res = run_local(command %("load"),logger,False,True) + logger.log(35, res.stdout ) + logger.log(35, res.stderr ) + logger.log(36,"%s: End Load" %(get_time_log())) + local_sync() + remote_sync(ips) + get_space(ips,spaceDict,dbConfig[args.database.lower()]["db_folders"],dbConfig[args.database.lower()]["basic"]) + logger.log(35,"%s: Start Run" %(get_time_log())) + res = run_local(command %("run"),logger,False,True) + logger.log(35, res.stdout ) + logger.log(35, res.stderr ) + logger.log(36,"%s: End Run" %(get_time_log())) + remote_sync(ips) + get_space(ips,spaceDict,dbConfig[args.database.lower()]["db_folders"],dbConfig[args.database.lower()]["basic"]) + logger.log(36,"%s: End Test" %(get_time_log())) + logger.log(34,"%s" %(make_space_str(check_add_space(spaceDict)))) + logger.info("Running postrun commands for %s." %(args.database.lower())) + # Postrun once + for command in dbConfig[args.database.lower()]["postrun_once"]: + commandRepl = command + commandRepl = replStr(args.ip, ips[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_local (commandRepl,logger, False) + # Postrun for all vms + for command in dbConfig[args.database.lower()]["postrun"]: + for ip in ips: + commandRepl = command + commandRepl = replStr(args.ip, ip ,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Postrun for master (first) vm + for command in dbConfig[args.database.lower()]["postrun_master"]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[0], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Postrun for slave (all without first) vm + for command in dbConfig[args.database.lower()]["postrun_slaves"]: + ipsWithoutMaster=list(ips) + ipsWithoutMaster.remove(args.ip[0]) + if len(ipsWithoutMaster) > 0: + for ip in ipsWithoutMaster: + commandRepl = command + commandRepl = replStr(args.ip, ip,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + else: + logger.warning("There is only one db vm or more sequence keys than vms, can't run slave postrun commands via ssh.") + # Postrun for dict + for key in dbConfig[args.database.lower()]["sequence"]: + if key in dbConfig[args.database.lower()]["postrun_dict"].keys(): + if len(args.ip) > key: + for command in dbConfig[args.database.lower()]["postrun_dict"][key]: + commandRepl = command + commandRepl = replStr(ips, args.ip[key],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[key], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + logger.warning("Key to high, not enough IPs to run postrun command for key: %s." %(key)) + clean_exit(0,args.ip, not args.noshutdown) +else: + logger.error("%s is an unknown database." %(args.database)) + clean_exit(-1,args.ip, not args.noshutdown) \ No newline at end of file diff --git a/SetupVsphere.py b/SetupVsphere.py new file mode 100755 index 0000000..c0351d5 --- /dev/null +++ b/SetupVsphere.py @@ -0,0 +1,523 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +from pyVim import connect +from pyVmomi import vmodl, vim +import Util +import os +import argparse +import logging +import atexit +import time +import datetime + +# First: Default without template name +# Second: Only Generator template name +# Third: Only DB template name +vagrantCredFiles=["vagrantconf.rb", "vagrantconf_gen.rb", "vagrantconf_db.rb"] + +requiredConfigValues={"vsphere.host" : None, # Name + Conversion Method, None = no conversion required only clean '' out + "vsphere.compute_resource_name" : None, + "vsphere.resource_pool_name" : None, + "vsphere.template_name_gen" : None, + "vsphere.template_name_db" : None, + "vm_base_path" : None, + "vsphere.data_store_name" : None, + "vsphere.user" : None, + "vsphere.password" : None} + +baseDbVmConfig={ "name" : "BaseDB-VM", + "cpu" : 8, + "ram" : 16384, + "hdd" : 50, #in GB + "network" : "VM Network IAAS", + "iso" : "[dsNEMAR_NFS_nemarcontrolvm_v2] debian-8.1.0-amd64-netinst-autoinstall.iso"} +baseGenVmConfig={ "name" : "BaseGen-VM", + "cpu" : 4, + "ram" : 8192, + "hdd" : 50, #in GB + "network" : "VM Network IAAS", + "iso" : "[dsNEMAR_NFS_nemarcontrolvm_v2] debian-8.1.0-amd64-netinst-autoinstall.iso"} +TestVmConfig={ "name" : "TEST", + "cpu" : 1, + "ram" : 1024, + "hdd" : 10, #in GB + "network" : "VM Network IAAS", + "iso" : "[dsNEMAR_NFS_nemarcontrolvm_v2] debian-8.1.0-amd64-netinst-autoinstall.iso"} + +vmDictList = [baseGenVmConfig, baseDbVmConfig] + +####################################################################### +# Fix for not validated SSL Certs +# Better (when available): https://github.com/hartsock/pyvmomi/commit/3e12779a6d1fd9e9cfd7ae6f614652b740d25303 +import requests +requests.packages.urllib3.disable_warnings() +import ssl +try: + _create_unverified_https_context = ssl._create_unverified_context +except AttributeError: + # Legacy Python that doesn't verify HTTPS certificates by default + pass +else: + # Handle target environment that doesn't support HTTPS verification + ssl._create_default_https_context = _create_unverified_https_context +####################################################################### + +def convert_config_item(parameter, item, logger): + str = item + if parameter in requiredConfigValues.keys(): + if requiredConfigValues[parameter] == None: + return str + try: + str = requiredConfigValues[parameter](item) + except Exception, e: + logger.error("Could not convert %s:%s." %(parameter, item), exc_info=True) + return str + +def handle_vsphere_config_line(line,dict,logger): + str = Util.clean_newline_space(line) + strList = str.split("=") + if len(strList) != 2: + logger.error("Can't parse line '%s'." %(line)) + return False + strList[0] = Util.clean_quote_space(strList[0].lower()) + strList[1] = Util.clean_quote_space(strList[1]) + if "template_name" in strList[0]: + if "vsphere.template_name_gen" in dict.keys() and not "vsphere.template_name_db" in dict.keys(): + strList[0] = "vsphere.template_name_db" + elif not "vsphere.template_name_db" in dict.keys() and not "vsphere.template_name_gen" in dict.keys(): + strList[0] = "vsphere.template_name_gen" + else: + logger.error("template_name_gen or template_name_db was defined twice. Please use only one template_name \ + argument in gen and in db template file and put them in correct order into the array.") + return False + if strList[0] in dict.keys(): + logger.error("Configfile contains '%s' two times." %(strList[0])) + return False + dict[strList[0]] = convert_config_item(strList[0], strList[1], logger) + if dict[strList[0]] == "" or dict[strList[0]] == None: + if strList[0] in requiredConfigValues: + logger.error("Empty value for '%s' which is required." %(strList[0])) + return False + else: + logger.warning("Empty value for '%s'." %(strList[0])) + return True + +def get_vsphere_config(vagrantFolder, files,logger): + dict={} + for file in files: + path=os.path.join(vagrantFolder,file) + if not Util.check_file_readable(path): + logger.error("Can't read %s." %(path)) + return {} + file = open(path,"r") + state = 0 # 0=outside, 1=inside vsphere provider block + for line in file: + if "config.vm.provider" in line.lower() and "vsphere" in line.lower(): + if state == 0: + state = 1 + else: + logger.error("Found a vsphere provider line two times without and end in between.") + return {} + elif "end" in line.lower() and state == 1: + break + elif state == 1: + if not handle_vsphere_config_line(line,dict,logger): + return {} + keys = requiredConfigValues.keys() + for key in dict.keys(): + if key in keys: + keys.remove(key) + if len(keys) > 0: + logger.error("Not all required values are set. Missing: %s" %(keys)) + return {} + return dict + +def wait_for_task(task): + while (task.info.state == vim.TaskInfo.State.running and task.info.cancelled == False): + time.sleep(2) + +def check_task(task): + if task.info.state == vim.TaskInfo.State.success and task.info.error == None and task.info.cancelled == False: + return True + else: + return False + +def create_vm(vmDict, vmFolder, resourcePool, dataStore, logger): + + datastorePath = '[' + dataStore + '] ' + vmDict["name"] + #datastorePath = '[' + datastore + ']' + # bare minimum VM shell, no disks. Feel free to edit + vmx_file = vim.vm.FileInfo(logDirectory=None, + snapshotDirectory=None, + suspendDirectory=None, + vmPathName=datastorePath) + + # Sources: + # https://github.com/karmab/nuages/blob/master/portal/vsphere2.py + # http://jensd.be/370/linux/create-a-new-virtual-machine-in-vsphere-with-python-pysphere-and-the-vmware-api + devChanges = [] + scsiSpec = vim.vm.device.VirtualDeviceSpec() + scsiSpec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add + #scsiCtrl = vim.vm.device.VirtualLsiLogicController() + scsiCtrl = vim.vm.device.ParaVirtualSCSIController() + scsiCtrl.key = 1000 + scsiCtrl.busNumber = 0 + scsiCtrl.sharedBus = vim.vm.device.VirtualSCSIController.Sharing.noSharing + scsiSpec.device = scsiCtrl + devChanges.append(scsiSpec) + diskSize = int(vmDict["hdd"]) * 1024 * 1024 + # if int(datastore.freeSpace)/1024/1024/1024 - diskSize) <= 0: + # error zu wenig speicher, aber bei thin egal? + diskSpec = vim.vm.device.VirtualDeviceSpec() + diskSpec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add + diskSpec.fileOperation = vim.vm.device.VirtualDeviceSpec.FileOperation.create + diskSpec.device = vim.vm.device.VirtualDisk() + diskSpec.device.controllerKey = 1000 + diskSpec.device.backing = vim.vm.device.VirtualDisk.FlatVer2BackingInfo() + diskSpec.device.backing.thinProvisioned = True + diskSpec.device.backing.diskMode = 'persistent' + diskSpec.device.unitNumber = 0 + diskSpec.device.capacityInKB = diskSize + devChanges.append(diskSpec) + nicSpec = vim.vm.device.VirtualDeviceSpec() + nicSpec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add + nic = vim.vm.device.VirtualVmxnet3() + desc = vim.Description() + desc.label = "Network Adapter 1" + nicBacking = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo() + desc.summary = vmDict["network"] + nicBacking.deviceName = vmDict["network"] + nic.backing = nicBacking + nic.key = 0 + nic.deviceInfo = desc + nic.addressType = 'generated' + nicSpec.device = nic + devChanges.append(nicSpec) + cdSpec = vim.vm.device.VirtualDeviceSpec() + cdSpec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add + connect = vim.vm.device.VirtualDevice.ConnectInfo() + connect.startConnected = True + connect.allowGuestControl = True + connect.connected = True + cd = vim.vm.device.VirtualCdrom() + cd.connectable = connect + cdBacking = vim.vm.device.VirtualCdrom.IsoBackingInfo() + cdBacking.fileName = vmDict["iso"] + cd.backing = cdBacking + cd.controllerKey = 201 + cd.unitNumber = 0 + cd.key = -1 + cdSpec.device = cd + devChanges.append(cdSpec) + videoSpec = vim.vm.device.VirtualDeviceSpec() + videoSpec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add + videoSpec.device = vim.vm.device.VirtualVideoCard() + videoSpec.device.videoRamSizeInKB = 8 * 1024 + videoSpec.device.numDisplays = 1 + videoSpec.device.enable3DSupport = False + videoSpec.device.use3dRenderer = "automatic" + devChanges.append(videoSpec) + toolConfigInfo = vim.vm.ToolsConfigInfo() + toolConfigInfo.syncTimeWithHost = True + flagInfo = vim.vm.FlagInfo() + flagInfo.runWithDebugInfo = False + + config = vim.vm.ConfigSpec(name=vmDict["name"], memoryMB=vmDict["ram"], numCPUs=vmDict["cpu"], files=vmx_file, guestId='debian6_64Guest', + version='vmx-10', deviceChange=devChanges, tools=toolConfigInfo, flags=flagInfo, + guestAutoLockEnabled=False) + logger.info("Creating VM %s (vm_folder: %s, resource_pool: %s, datastore: %s)..." %(vmDict["name"], vmFolder.name, resourcePool.name, dataStore)) + task = vmFolder.CreateVM_Task(config=config, pool=resourcePool) + wait_for_task(task) + if check_task(task): + return task.info.result + else: + logger.error("Can't create vm '%s': %s" %(vmDict["name"], task.info.error.msg)) + return None + +def destroy_vm(vm, logger): + # vms = search_vm_by_name("TEST", vmFolder) + # if len(vms) > 1: + # logger.info("Found more than 1 VM with name %s, deleting all." %(vmName)) + # elif len(vms) < 1: + # return True + # for vm in vms: + logger.info("Destroying %s..." %(vm.name)) + if format(vm.runtime.powerState) == "poweredOn": + logger.info("Attempting to power off %s first." %(vm.name)) + task = vm.PowerOffVM_Task() + wait_for_task(task) + if not check_task(task): + logger.error("Error while powering off VM %s." %(vm.name)) + task = vm.Destroy_Task() + wait_for_task(task) + if not check_task(task): + logger.error("Error while destroying off VM %s." %(vm.name)) + +def drop_iso(vm, logger): + # Source https://github.com/rreubenur/vmware-pyvmomi-examples/blob/master/boot_vm_from_iso.py + cdSpec = None + for device in vm.config.hardware.device: + if isinstance(device, vim.vm.device.VirtualCdrom): + cdSpec = vim.vm.device.VirtualDeviceSpec() + cdSpec.device = device + cdSpec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit + cdSpec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo() + cdSpec.device.connectable.startConnected = False + cdSpec.device.connectable.connected = False + if cdSpec == None: + logger.warning("Can't find VirtualCdrom on VM %s. " %(vm.name)) + return True + vmConf = vim.vm.ConfigSpec() + vmConf.deviceChange = [cdSpec] + task = vm.ReconfigVM_Task(vmConf) + wait_for_task(task) + if not check_task(task): + logger.error("Can't drop out VirtualCdrom of VM %s." %(vm.name)) + return False + return True + +def clone_vm_to_template(vm, destFolder, name, logger): + logger.info("Cloning %s to template %s in ds: %s..." %(vm.name, name,destFolder.name)) + cloneSpec = vim.vm.CloneSpec() + cloneSpec.location = vim.vm.RelocateSpec() + cloneSpec.location.datastore = vm.datastore[0] + cloneSpec.location.pool = vm.resourcePool + cloneSpec.template = True + cloneSpec.powerOn = False + task = vm.CloneVM_Task(destFolder,name,cloneSpec) + wait_for_task(task) + if not check_task(task): + logger.error("Error while cloning off VM %s to template %s in ds: %s." %(vm.name, name,destFolder.name)) + return False + return True + +def search_vm_by_name(name, vmFolder, depth=1): + maxdepth=10 + vmList=[] + if hasattr(vmFolder, 'childEntity'): + if depth > maxdepth: + return [] + for child in vmFolder.childEntity: + found = search_vm_by_name(name,child,depth+1) + if found != None and found != []: + for element in found: + vmList.append(element) + + else: + if vmFolder.name.lower() == name.lower(): + return [vmFolder] + else: + return [] + return vmList + +def check_if_exist(name,vmFolder, logger): + res = search_vm_by_name(name,vmFolder) + if res == None or len(res) <= 0: + return None + if len(res) > 1: + logger.warning("Found more than 1 VM with name %s." %(name)) + return res[0] + +def power_on_vm(vm, logger): + logger.info("Attempting to power on %s." %(vm.name)) + if vm.runtime.powerState != vim.VirtualMachinePowerState.poweredOn: + task = vm.PowerOnVM_Task() + wait_for_task(task) + if check_task(task): + return True + else: + logger.error("Error while powering on VM %s." %(vm.name)) + return False + else: + logger.warning("VM %s is already powered on." %(vm.name)) + return False + +def wait_for_power_off(vm, logger, timeout=3600): + logger.info("Waiting for %s to power off." %(vm.name)) + start = datetime.datetime.now() + while vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn: + time.sleep(2) + if (datetime.datetime.now()-start).total_seconds() > timeout: + logger.error("Waiting for %s to end install process timed out after %s seconds" %(vm["name"],timeout)) + return False + return True + +# Configure ArgumentParser +parser = argparse.ArgumentParser(prog="SetupVsphere.py",version=__version__,description="Bla", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="") +parser.add_argument("-l", "--log", action='store_true', help="Be more verbose, log vagrant output.") +parser.add_argument("-f", "--vagrantfolder", metavar="VAGRANT", required=True, help="Path to folder with Vagrantfiles") +parser.add_argument("-o", "--overwrite", action='store_true', help="Deletes eventually existing templates/vms before creating them") +args = parser.parse_args() + +# Configure Logging +logLevel = logging.WARN +if args.log: + logLevel = logging.DEBUG +logging.basicConfig(level=logLevel) +logger = logging.getLogger(__name__) + +# File checks and deletions (if necessary) +if not Util.check_folder(args.vagrantfolder,logger): + exit(-1) +for vagrantCredFile in vagrantCredFiles: + if not Util.check_file_exists(os.path.join(args.vagrantfolder,vagrantCredFile)): + logger.error("%s not found." %(os.path.join(args.vagrantfolder,vagrantCredFile))) + exit(-1) + +vsphereConfigDict = get_vsphere_config(args.vagrantfolder, vagrantCredFiles, logger) +if len(vsphereConfigDict.keys()) < 1: + logger.error("Error while parsing '%s'" %(os.path.join(args.vagrantfolder,vagrantCredFile))) + exit(-1) + + +# def PrintVmInfo(vm, depth=1): +# """ +# Print information for a particular virtual machine or recurse into a folder +# with depth protection +# """ +# maxdepth = 10 +# +# # if this is a group it will have children. if it does, recurse into them +# # and then return +# if hasattr(vm, 'childEntity'): +# if depth > maxdepth: +# return +# vmList = vm.childEntity +# for c in vmList: +# PrintVmInfo(c, depth+1) +# return +# +# summary = vm.summary +# print vm.summary +# print("Name : ", summary.config.name) +# print("Path : ", summary.config.vmPathName) +# print("Guest : ", summary.config.guestFullName) +# annotation = summary.config.annotation +# if annotation != None and annotation != "": +# print("Annotation : ", annotation) +# print("State : ", summary.runtime.powerState) +# if summary.guest != None: +# ip = summary.guest.ipAddress +# if ip != None and ip != "": +# print("IP : ", ip) +# if summary.runtime.question != None: +# print("Question : ", summary.runtime.question.text) +# print("") +# +# +# def get_obj(content, vimtype, name): +# """ +# Return an object by name, if name is None the +# first found object is returned +# """ +# obj = None +# container = content.viewManager.CreateContainerView( +# content.rootFolder, vimtype, True) +# for c in container.view: +# if name: +# if c.name == name: +# obj = c +# break +# else: +# obj = c +# break +# +# return obj + + +serviceInstance = None +try: + serviceInstance = connect.SmartConnect(host=vsphereConfigDict["vsphere.host"], + user=vsphereConfigDict["vsphere.user"], + pwd=vsphereConfigDict["vsphere.password"], + port=443) + if not serviceInstance: + logger.error("Could not connect to %s:443." % (vsphereConfigDict["vsphere.host"])) + exit(-1) + atexit.register(connect.Disconnect, serviceInstance) + session_id = serviceInstance.content.sessionManager.currentSession.key + # find datacenter + content = serviceInstance.RetrieveContent() + if len(content.rootFolder.childEntity) > 1: + logger.warning("Found more than one datacenter, using first one.") + elif len(content.rootFolder.childEntity) < 1: + logger.error("Found no datacenters.") + exit(-1) + dc = content.rootFolder.childEntity[0] + vmFolder = dc.vmFolder + hosts = dc.hostFolder.childEntity + if len(hosts) < 1: + logger.error("Found no hosts in datacenter '%s'." %(dc.name)) + exit(-1) + computeResource=None + for cR in hosts: + if cR.name.lower() == vsphereConfigDict["vsphere.compute_resource_name"].lower(): + computeResource = cR + if computeResource == None: + logger.error("Could not found compute resource '%s'." %(vsphereConfigDict["vsphere.compute_resource_name"])) + exit(-1) + if len(computeResource.resourcePool.resourcePool) < 1: + logger.error("Found no resourcePools in datacenter '%s' on compute resource '%s'." %(dc.name, computeResource.name)) + exit(-1) + resourcePool=None + for rP in computeResource.resourcePool.resourcePool: + if rP.name.lower() == vsphereConfigDict["vsphere.resource_pool_name"].lower(): + resourcePool = rP + if resourcePool == None: + logger.error("Could not found resource pool '%s'." %(vsphereConfigDict["vsphere.resource_pool_name"])) + exit(-1) + # + # content = service_instance.RetrieveContent() + # for child in content.rootFolder.childEntity: + # if hasattr(child, 'vmFolder'): + # datacenter = child + # vmFolder = datacenter.vmFolder + # vmList = vmFolder.childEntity + # for vm in vmList: + # PrintVmInfo(vm) + container = content.viewManager.CreateContainerView( + dc.vmFolder, [vim.Folder], True) + destFolder=None + searchFolder=vsphereConfigDict["vm_base_path"].split("/")[-1] + for folder in container.view: + if folder.name.lower() == searchFolder.lower(): + if destFolder != None: + logger.warning("Found folder '%' more than one time, using first one." %(searchFolder.lower())) + else: + destFolder = folder + + # destfolder = get_obj(content, [vim.Folder], "nemar/baderas") + # print destfolder.name + for vmDict in vmDictList: + for vmName in [vmDict["name"], "%s-Vorlage" %(vmDict["name"])]: + vm = check_if_exist(vmName, dc.vmFolder, logger) + if vm != None: + if not args.overwrite: + logger.error("VM '%s' already exists, overwrite not enabled." %(vm.name)) + exit(-1) + else: + destroy_vm(vm, logger) + vm = create_vm(vmDict, destFolder, resourcePool, vsphereConfigDict["vsphere.data_store_name"], logger) + if vm != None: + if not power_on_vm(vm, logger): + exit(-1) + if not wait_for_power_off(vm, logger, 3600): + exit(-1) + if not drop_iso(vm, logger): + exit(-1) + if not clone_vm_to_template(vm, destFolder, "%s-Vorlage" %(vmDict["name"]), logger): + exit(-1) + destroy_vm(vm, logger) + else: + logger.error("'%s' wasn't created, abort." %(vmDict["name"])) + exit(-1) + +except vmodl.MethodFault as error: + print "Caught vmodl fault : " + error.msg + connect.Disconnect(serviceInstance) + exit(-1) +exit(0) \ No newline at end of file diff --git a/TSDBBench.py b/TSDBBench.py new file mode 100755 index 0000000..d18291c --- /dev/null +++ b/TSDBBench.py @@ -0,0 +1,435 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +import logging +import argparse +from fabric.api import * +import os +import time +import Util +import subprocess +import threading +import Vm + +logFile='pyvagrant.log' +pyYcsbPdfGenPath="ProcessYcsbLog.py" +testDBs=['basicdb','basicjdbc','basickairosdb','basicopentsdb'] +vagrantCredFiles=["vagrantconf.rb", "vagrantconf_gen.rb", "vagrantconf_db.rb"] +vagrantBasicFilesFolder="basic" + +availProviders=['vsphere', 'openstack'] # First one is default + +def run_workload(genDict, dbDict, dbName, workloadName, timeseries, granularity, bucket, test, onlyPrerun, debug, logger): + if test: + command = "" + else: + command = "nohup " + ipStr = "" + for dbKey in sorted(dbDict.keys()): + if dbDict[dbKey] == None or dbDict[dbKey] == "": + ipStr += "%s " %(dbDict[dbKey].vm.hostname()) + logger.warning("IP of vm %s is None or an empty string, using hostname instead. This does not work on some providers (e.g. OpenStack)!" %(dbKey)) + else: + ipStr += "%s " %(dbDict[dbKey].ip) + ip0 = dbDict[dbDict.keys()[0]].ip + if ip0 == None or ip0 == "": + ip0 = dbDict[dbDict.keys()[0]].vm.hostname() + logger.info("BEGIN: Running workload '%s' on %s with ip string %s." %(workloadName,ip0,ipStr)) + command+="python2 /home/vagrant/files/RunWorkload.py -d %s -w %s -i %s" %(dbName,workloadName,ipStr) + if timeseries: + command+=" -t" + if granularity: + command+=" -g %s" % (granularity) + if onlyPrerun: + command+=" -p" + if not test: + command += " -n" + if bucket: + command+=" -b %s" % (bucket) + if debug: + command += " --debug" + if not test: + command += " 3600: + logger.error("VM % is still up, waiting for it to shutdown timeouted after %s seconds." %(Vm.hostname(),timeout)) + return False + if noshutdown: + logger.info("Noshutdown is activated, trying to boot it up again.") + for vmKey in sorted(vms.keys()): + vms[vmKey].vm.up(provider="vsphere") + return True + +def get_remote_file(vm,remotePath,localPath,logger): + with settings(host_string= vm.user_hostname_port(), + key_filename = vm.keyfile(), + disable_known_hosts = True): + ret = get(remote_path=remotePath, local_path=localPath) + if len(ret) > 1: + logger.warning("More than one file copied from %s to %s: %s." %(remotePath, localPath, ret)) + if len(ret) < 1: + logger.error("No files copied from %s to %s." %(remotePath, localPath)) + return ret + +def rm_remote_file(vm,remotePath,logger): + with settings(host_string= vm.user_hostname_port(), + key_filename = vm.keyfile(), + disable_known_hosts = True): + run ("rm %s" %(remotePath)) + +def get_ycsb_file(vm,dbName,workloadName,logger): + ret = get_remote_file(vm,"/home/vagrant/ycsb_%s_%s_*.log" %(dbName,workloadName),".",logger) + if len(ret) > 1: + logger.warning("More than one file copied for %s %s: %s. Taking first one." %(dbName, workloadName, ret)) + if len(ret) < 1: + return None + return ret[0] + +def check_result_file(path): + if Util.check_file_exists(path): + file = open(path,"r") + errorsFound = False + errors = [] + warningsFound = False + warnings = [] + exceptionsFound = False + exceptions = [] + for line in file: + if "warn" in line.lower(): + warningsFound = True + warnings.append(line) + if "error" in line.lower(): + errorsFound = True + errors.append(line) + if "exception" in line.lower(): + exceptionsFound = True + exceptions.append(line) + file.close(); + if errorsFound: + logger.error("The following errors occurred: ") + for error in errors: + logger.error(error) + if warningsFound: + logger.warning("The following warnings occurred: ") + for warning in warnings: + logger.warning(warning) + if exceptionsFound: + logger.error("The following exceptions occurred: ") + for exception in exceptions: + logger.error(exception) + else: + logger.error("%s not found, can't check for errors." %(path)) + +def generate_html(paths, pdf, overwrite): + if Util.check_file_exists(pyYcsbPdfGenPath): + tsString = "" + if args.timeseries: + tsString=" -t" + overwriteString = "" + if overwrite: + overwriteString=" -o" + ycsbFileString = "-f" + if len(paths) < 1: + logger.error("Can't create html or pdf, paths is empty." ) + return False + for path in paths: + ycsbFileString += " %s" %(path) + pdfString = "" + if args.pdf: + pdfString = " -p" + multiStr = "" + if len(paths) > 1: + multiStr = " -s" + try: + retcode = subprocess.call("python2 %s %s%s%s%s%s" %(pyYcsbPdfGenPath,ycsbFileString,tsString,pdfString,overwriteString,multiStr), shell=True) + if retcode != 0: + logger.error("Generation of pdf/html returned with %s." %(retcode)) + else: + logger.info("Successfully generated pdf/html file.") + except OSError, e: + logger.error("Errors occured while running pdf/html creation process.", exc_info=True) + + else: + logger.error("Can't create html or pdf, %s does not exist." %(pyYcsbPdfGenPath)) + +def cleanup_vm(name, vm, pathFolder, pathVagrantfile, logger, linear): + logger.info("Cleaning up %s." %(name)) + if vm != None and linear: + vm.destroy() + if pathFolder != None and pathFolder != "": + if not Util.delete_folder(pathFolder,logger,True): + logger.warning("Error while cleaning up %s." %(name)) + return False + if pathVagrantfile != None and pathVagrantfile != "": + if not Util.delete_file(pathVagrantfile,logger,True): + logger.warning("Error while cleaning up %s." %(name)) + return False + return True + +def cleanup_vms(vmDict,logger, linear): + logger.info("Begin Cleaning up.") + if not linear: + logger.info("Waiting to finish creation if not finished...") + for key in vmDict.keys(): + # Wait for Creation to finish if unfinished + vmDict[key].join() + if vmDict[key].created: + # Start Destroying if created :) + vmDict[key].start() + # Wait for Destroying to finish if unfinished + vmDict[key].join() + for key in vmDict.keys(): + cleanup_vm(key, vmDict[key].vm,vmDict[key].pathFolder,vmDict[key].pathVagrantfile, logger, linear) + vmDict.pop(key) + +# Configure ArgumentParser +parser = argparse.ArgumentParser(prog="TSDBBench.py",version=__version__,description="Bla", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="") +parser.add_argument("-l", "--log", action='store_true', help="Be more verbose, log vagrant output.") +parser.add_argument("-t", "--tmpfolder", metavar="TMP", required=True, help="Path to Temp Space") +parser.add_argument("-f", "--vagrantfolder", metavar="VAGRANT", required=True, help="Path to folder with Vagrantfiles") +parser.add_argument("-w", "--workload", metavar="WORKLOAD", help="Only process workload WORKLOAD") +parser.add_argument("-d", "--databases", metavar="DATABASES", nargs='+', help="Only process workloads for all machines for DATABASE (Generator will always be created!), Set to 'all' for all DATABASES, set to 'test' for some special test DB set.)") +parser.add_argument("-n", "--nodestroy", action='store_true', help="Do not destroy VMs") +parser.add_argument("-o", "--noshutdown", action='store_true', help="Do not shutdown db vms, leave them running. Remember: After finishing workload they are rebooted!") +parser.add_argument("-s", "--timeseries", action='store_true', help="Force workload to do timeseries output") +parser.add_argument("-g", "--granularity", metavar="GRANULARITY", type=int, default=1000, help="If forcing to do timeseries output, use granularity GRANULARITY. Default:1000") +parser.add_argument("-b", "--bucket", metavar="BUCKET", type=int, default=100000, help="Use BUCKET bucket size for measurement histograms. Default:100000") +parser.add_argument("-m", "--html", action='store_true', help="Generate html output (ProcessYcsbLog.py required!") +parser.add_argument("-p", "--pdf", action='store_true', help="Generate pdf output (ProcessYcsbLog.py required!") +parser.add_argument("-u", "--nohup", action='store_true', help="Also fetch nohup output (for debugging only)") +parser.add_argument("-c", "--linear", action='store_true', help="Create VMs linear, do not use parallelisation.") +parser.add_argument("-r", "--provider", metavar="PROVIDER", type=str, default=availProviders[0], choices=availProviders, help="Which provider to use. Available: %s" %(availProviders)) + +args = parser.parse_args() + +# Configure Logging +logLevel = logging.WARN +if args.log: + logLevel = logging.DEBUG +logging.basicConfig(level=logLevel) +logger = logging.getLogger(__name__) +handler = logging.FileHandler(logFile) +handler.setLevel(logLevel) +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +handler.setFormatter(formatter) +logger.addHandler(handler) + +# File checks and deletions (if necessary) +if not Util.check_folder(args.vagrantfolder,logger): + exit(-1) +for vagrantCredFile in vagrantCredFiles: + if not Util.check_file_exists(os.path.join(args.vagrantfolder,vagrantCredFile)): + logger.error("%s not found." %(os.path.join(args.vagrantfolder,vagrantCredFile))) + exit(-1) +if not Util.check_folder(args.tmpfolder,logger): + exit(-1) +if not Util.delete_file(logFile,logger,True): + exit(-1) + +generators={} # list of generator vms +dbs={} # dictinary of db vms +# format "name" = {"path_folder" : "/bla/tmppath", "path_vagrantfile":"/bla/tmppath/file", "vm": vm} + + +# Generating Generator VMs +generatorFound=False +for path in sorted(os.listdir(args.vagrantfolder)): + if os.path.isdir(os.path.join(args.vagrantfolder,path)) and path == "generator": + generatorFound=True + found=0 # how many .vagrant files are found, At least 1 is needed! + for path2 in sorted(os.listdir(os.path.join(args.vagrantfolder,"generator"))): + if os.path.isfile(os.path.join(args.vagrantfolder,"generator",path2)): + split = path2.rsplit(".vagrant",1) + # if rsplit is used on bla.vagrant, the result should be ["bla",""] + if len(split)>1 and split[1] == "": + found+=1 + # check if Generator, generator, Generator_1, etcpp. as machine is used, but always create if + # something else than Generator is given (Generator is always created!) + if not args.databases or args.databases == None or args.databases == [] \ + or not Util.check_if_in_databases("generator", args.databases) \ + or (args.databases and Util.check_if_eq_databases(split[0], args.databases)) \ + or (args.databases and Util.check_if_eq_databases(split[0].rsplit("_",1)[0], args.databases)): + if args.linear: + virtMachine = Vm.Vm(args.vagrantfolder, vagrantCredFiles, vagrantBasicFilesFolder, args.tmpfolder, split[0], logger, args.provider, args.log) + virtMachine.create_vm() + generators[virtMachine.name] = virtMachine + if not virtMachine.created: + logger.error("VM %s could not be created." %(split[0])) + if not args.nodestroy: + cleanup_vms(generators,logger, args.linear) + exit(-1) + else: + virtMachine = Vm.Vm(args.vagrantfolder, vagrantCredFiles, vagrantBasicFilesFolder, args.tmpfolder, split[0], logger, args.provider, args.log) + virtMachine.start() + Util.sleep_random(1.0,5.0) # needed for openstack, otherwise two vms get the same floating ip + generators[virtMachine.name] = virtMachine + if found == 0: + logger.error("No .vagrant files found in %s." %(os.path.join(args.vagrantfolder,"generator"))) + exit(-1) + break + +if not generatorFound: + logger.error("No Generator found, %s does not exist." %(os.path.join(args.vagrantfolder,"generator"))) + exit(-1) + +if args.databases and (Util.check_if_eq_databases("generator",args.databases) or Util.check_if_eq_databases_rsplit("generator",args.databases)): + if not args.linear: + for generatorKey in generators.keys(): + logger.info("Wait for creation of %s to finish." %(generators[generatorKey].name)) + generators[generatorKey].join() + if not generators[generatorKey].created: + logger.error("VM %s could not be created." %(generators[generatorKey].name)) + if not args.nodestroy: + cleanup_vms(generators, logger, args.linear) + exit(-1) + if not args.nodestroy: + cleanup_vms(generators, logger, args.linear) + exit(0) + +ycsbfiles=[] + +# Doing Tests if basic or test is in given dbs +if args.databases and (Util.check_if_eq_databases("basic", args.databases) or Util.check_if_eq_databases("test", args.databases)): + if not args.linear: + for generatorKey in generators.keys(): + logger.info("Wait for creation of %s to finish." %(generators[generatorKey].name)) + generators[generatorKey].join() + if not generators[generatorKey].created: + logger.error("VM %s could not be created." %(generators[generatorKey].name)) + if not args.nodestroy: + cleanup_vms(generators, logger, args.linear) + exit(-1) + logger.info("Processing Test Databases") + for database in testDBs: + if args.workload: + logger.info("Starting workload '%s' on Generator %s." %(database,generators[generators.keys()[0]].vm.hostname())) + run_workload(generators, generators, database, args.workload, args.timeseries, args.granularity, args.bucket, True, False, args.log, logger) + ycsbFile = get_ycsb_file(generators[generators.keys()[0]].vm,database.lower(),args.workload.lower(),logger) + ycsbfiles.append(ycsbFile) + check_result_file(ycsbFile) + if (args.html or args.pdf) and len(ycsbfiles) == 1: + generate_html([ycsbFile],args.pdf,False) + + else: + logger.info("No Workload given, doing nothing.") + if not args.nodestroy: + cleanup_vms(generators, logger, args.linear) +else: + # Generating Database VMs + logger.info("Processing Database VMs" ) + for path in sorted(os.listdir(args.vagrantfolder)): + if os.path.isdir(os.path.join(args.vagrantfolder,path)): + if path=="generator" or path.find(".")==0: + continue + found=0 # how many .vagrant files are found, At least 1 is needed! + if not args.databases or args.databases == "" \ + or (args.databases and not Util.check_if_eq_databases(path, args.databases) and not Util.check_if_eq_databases("all", args.databases)): + continue + logger.info("Processing %s." %(path)) + for path2 in sorted(os.listdir(os.path.join(args.vagrantfolder,path))): + if os.path.isfile(os.path.join(args.vagrantfolder,path, path2)): + split = path2.rsplit(".vagrant",1) + # if rsplit is used on bla.vagrant, the result should be ["bla",""] + if len(split)>1 and split[1] == "": + found+=1 + if args.databases and args.databases != None and args.databases != [] \ + and (Util.check_if_eq_databases(split[0], args.databases) \ + or Util.check_if_eq_databases(split[0].rsplit("_",1)[0], args.databases) \ + or Util.check_if_eq_databases("all", args.databases)): + if args.linear: + virtMachine = Vm.Vm(args.vagrantfolder, vagrantCredFiles, vagrantBasicFilesFolder, args.tmpfolder, split[0], logger, args.provider, args.log) + virtMachine.create_vm() + dbs[virtMachine.name] = virtMachine + if not virtMachine.created: + logger.error("VM %s could not be created." %(split[0])) + if not args.nodestroy: + cleanup_vms(generators, logger, args.linear) + cleanup_vms(dbs, logger, args.linear) + exit(-1) + else: + virtMachine = Vm.Vm(args.vagrantfolder, vagrantCredFiles, vagrantBasicFilesFolder, args.tmpfolder, split[0], logger, args.provider, args.log) + virtMachine.start() + Util.sleep_random(1.0,5.0) # needed for openstack, otherwise two vms get the same floating ip + dbs[virtMachine.name] = virtMachine + if not args.linear: + for generatorKey in generators.keys(): + logger.info("Wait for creation of %s to finish." %(generators[generatorKey].name)) + generators[generatorKey].join() + if not generators[generatorKey].created: + logger.error("VM %s could not be created." %(generators[generatorKey].name)) + if not args.nodestroy: + cleanup_vms(generators, logger, args.linear) + cleanup_vms(dbs, logger, args.linear) + exit(-1) + for dbKey in dbs.keys(): + logger.info("Wait for creation of %s to finish." %(dbs[dbKey].name)) + dbs[dbKey].join() + if not dbs[dbKey].created: + logger.error("VM %s could not be created." %(dbs[dbKey].name)) + if not args.nodestroy: + cleanup_vms(generators, logger, args.linear) + cleanup_vms(dbs, logger, args.linear) + exit(-1) + if found == 0: + logger.error("No .vagrant files found in %s." %(os.path.join(args.vagrantfolder,path))) + + + if args.workload: + logger.info("Starting workload '%s' on %s on Generator %s." %(args.workload,dbs[dbs.keys()[0]].vm.hostname(),generators[generators.keys()[0]].vm.hostname())) + run_workload(generators, dbs, path, args.workload, args.timeseries, args.granularity, args.bucket, False, False, args.log, logger) + logger.info("Waiting for workload to finish...") + wait_for_vm(dbs, logger, 3600, args.noshutdown) + ycsbFile = get_ycsb_file(generators[generators.keys()[0]].vm,path.lower(),args.workload.lower(),logger) + ycsbfiles.append(ycsbFile) + if args.nohup: + logger.info("Trying to fetch nohup files from generators.") + nohupCounter=0 + for generatorKey in generators.keys(): + get_remote_file(generators[generatorKey].vm,"/home/vagrant/nohup.out","./nohup_%s_%s_%s.out" %(path.lower(),args.workload.lower(),nohupCounter),logger) + rm_remote_file(generators[generatorKey].vm,"/home/vagrant/nohup.out",logger) + nohupCounter+=1; + + check_result_file(ycsbFile) + if (args.html or args.pdf) and len(args.databases) == 1 and len(ycsbfiles) == 1: + generate_html([ycsbFile],args.pdf,False) + + else: + logger.info("No Workload given, just running Prerun commands.") + run_workload(generators, dbs, path, args.workload, args.timeseries, args.granularity, args.bucket, False, True, args.log, logger) + if args.nohup: + logger.info("Trying to fetch nohup files from generators.") + nohupCounter=0 + for generatorKey in generators.keys(): + get_remote_file(generators[generatorKey].vm,"/home/vagrant/nohup.out","./nohup_%s_%s_%s.out" %(path.lower(),"none",nohupCounter),logger) + rm_remote_file(generators[generatorKey].vm,"/home/vagrant/nohup.out",logger) + nohupCounter+=1; + + if not args.nodestroy and not args.noshutdown: + cleanup_vms(dbs,logger, args.linear) + + if not args.nodestroy and not args.noshutdown: + cleanup_vms(dbs, logger, args.linear) + cleanup_vms(generators, logger , args.linear) + +if (args.html or args.pdf) and len(ycsbfiles) > 1: + logger.info("More than one DB given, also generating combined html/pdf file.") + generate_html(ycsbfiles,args.pdf,True) + +exit(0) \ No newline at end of file diff --git a/Util.py b/Util.py new file mode 100644 index 0000000..c2789c9 --- /dev/null +++ b/Util.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +import os +import shutil +import time +import random + +def check_file_readable(filename): + if check_file_exists(filename) and os.access(filename, os.R_OK): + return True + return False + +def check_file_exists(filename): + if os.path.isfile(filename): + return True + return False + +# Check if folder exists +def check_folder(path,logger,reverseLogic=False, noError=False): + if not(os.path.isdir(path) and os.path.exists(path)): + if not reverseLogic: + if not noError: + logger.error("%s does not exist." %(path)) + return False + else: + return True + if not reverseLogic: + return True + else: + if not noError: + logger.error("%s does exist." %(path)) + return False + +def delete_folder(path,logger,no_error=False): + if check_folder(path,logger): + try: + shutil.rmtree(path) + except Exception, e: + logger.warning('Failed to delete %s.' %(path), exc_info=True) + return False + return True + else: + if no_error: + return True + return False + +def delete_file(path,logger,no_error=False): + if os.path.isfile(path): + try: + os.remove(path) + except Exception, e: + logger.error('Failed to remove file', exc_info=True) + return False + return True + else: + if no_error: + return True + return False + + +def copy_folder(path1,path2,logger): + try: + shutil.copytree(path1, path2, symlinks=False, ignore=None) + except Exception, e: + logger.error('Failed to copy %s to %s.' %(path1,path2), exc_info=True) + return False + return True + +def copy_file(path1,path2,logger): + try: + shutil.copyfile(path1,path2) + except Exception, e: + logger.error('Failed to copy %s to %s.' %(path1,path2), exc_info=True) + return False + return True + +# delete *.vagrant files in given path +def clear_vagrant_files(path,logger): + if check_folder(path,logger): + for path2 in os.listdir(path): + if os.path.isfile(os.path.join(path,path2)): + split = path2.rsplit(".vagrant",1) + # if rsplit is used on bla.vagrant, the result should be ["bla",""] + if len(split) > 1 and split[1] == "": + try: + os.remove(os.path.join(path,path2)) + except Exception, e: + logger.warning('Failed to remove file.', exc_info=True) + else: + logger.warning("Can't clean %s." %(path)) + +def check_if_in_databases(str, databases): + for database in databases: + if str.lower() in database.lower(): + return True + return False + +def check_if_in_databases_rsplit(str, databases): + for database in databases: + if str.lower() in database.rsplit("_",1)[0].lower(): + return True + return False + +def check_if_eq_databases(str, databases): + for database in databases: + if str.lower() in database.lower(): + return True + return False + +def check_if_eq_databases_rsplit(str, databases): + for database in databases: + if str.lower() == database.rsplit("_",1)[0].lower(): + return True + return False + +def clean_space(line): + str = line + while str[0] == ' ': + str = str[1:] + while str[-1] == ' ': + str = str[:-1] + return str + +def clean_quote(line): + str = line + while str[0] == '\'': + str = str[1:] + while str[-1] == '\'': + str = str[:-1] + return str + +def clean_newline(line): + str = line + while str[0] == '\n': + str = str[1:] + while str[-1] == '\n': + str = str[:-1] + return str + +def clean_newline_space(line): + str = line + while str[0] == '\n' or str[0] == ' ': + str = str[1:] + while str[-1] == '\n' or str[-1] == ' ': + str = str[:-1] + return str + +def clean_quote_space(line): + str = line + while str[0] == '\'' or str[0] == ' ': + str = str[1:] + while str[-1] == '\'' or str[-1] == ' ': + str = str[:-1] + return str + +def create_folder(folder): + try: + os.makedirs(folder) + except: + return False + return True + +def get_random_int(start,end): + return random.randint(start,end) + +def get_random_float(start,end): + return random.uniform(start,end) + +def sleep_random(start,end): + time.sleep(get_random_float(start,end)) + +def get_random_int_with_chosen(start, end, chosenList): + return get_random_int_with_chosen_default(start,end,chosenList,[]) + +def get_random_int_with_chosen_default(start, end, chosenList, defaultList): + if abs(end-start) <= len(chosenList): + return None + for value in defaultList: + if value not in chosenList and value >= start and value <= end: + return value + randomInt = random.randint(start,end) + while randomInt in chosenList: + randomInt = random.randint(start,end) + return randomInt + +def log_timestamp(str,logger): + logger.debug("Timestamp at %s" %(str)) \ No newline at end of file diff --git a/Vm.py b/Vm.py new file mode 100644 index 0000000..f7d0522 --- /dev/null +++ b/Vm.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +import threading +import time +import vagrant +import os +import Util +from fabric.api import * + +class Vm(): + + vagrantFolder=None + pathVagrantfile=None + credFiles=None + basicFilesFolder=None + pathFolder=None + tmpFolder=None + name=None + logging=False + logger=None + created=False + vm=None + thread=None + provider=None + ip=None + + # vagrantFolder: Folder inside which vagrantfiles+folders are + # tmpFolder: Path to tempfolder + # name: name of the VM + # logger: Logger instance + # logging: if true, vagrant debug logging will be done + def __init__(self, vagrantFolder, credFiles, basicFilesFolder, tmpFolder, name, logger, provider, logging): + self.vagrantFolder = vagrantFolder + self.credFiles=credFiles + self.basicFilesFolder=basicFilesFolder + self.tmpFolder = tmpFolder + self.name = name + self.logger = logger + self.logging = logging + self.provider = provider + + def start(self): + self.thread = threading.Thread(target=self.run) + self.thread.start() + + def join(self): + self.thread.join() + + def run(self): + if not self.created: + self.create_vm() + else: + self.destroy() + + def destroy(self): + if self.vm != None: + return self.vm.destroy() + return True + + def create_vm(self): + # Check if you want to log + log_cm=None + self.logger.info("BEGIN Creating %s." %(self.name)) + if self.logging: + try: + filename="%s_%s.log" %(self.name,time.strftime("%Y%m%d%H%M%S", time.localtime())) + log_cm = vagrant.make_file_cm(filename) + self.logger.info("Logging creation of %s to %s." % (self.name,filename)) + except Exception, e: + self.logger.error('Failed to open file', exc_info=True) + return False + pathName=self.name.rsplit("_",1)[0] # Name is something like VMNAME_1, split _1 away! + # copy to tmpfolder (already checked that it exist, need to check if vm folder exists) + path=os.path.join(self.vagrantFolder,pathName) + pathTmp=os.path.join(self.tmpFolder,self.name) + if not Util.check_folder(path, self.logger, False): + return False + if not Util.check_folder(pathTmp, self.logger, True): + return False + # Copy Vagrantfile in place + pathVagrantFileOld=os.path.join(pathTmp,"%s.vagrant"%(self.name)) + pathVagrantFileNew=os.path.join(pathTmp,"Vagrantfile") + if not Util.copy_folder(path,pathTmp,self.logger): + return False + self.pathFolder=pathTmp + for credFile in self.credFiles: + pathCredFileOld=os.path.join(self.vagrantFolder,credFile) + pathCredFileNew=os.path.join(pathTmp,credFile) + if not Util.copy_file(pathCredFileOld,pathCredFileNew,self.logger): + return False + pathBasicFileFolderOld=os.path.join(self.vagrantFolder,self.basicFilesFolder) + pathBasicFileFolderNew=os.path.join(pathTmp,self.basicFilesFolder) + if not Util.copy_folder(pathBasicFileFolderOld,pathBasicFileFolderNew,self.logger): + return False + if not Util.copy_file(pathVagrantFileOld,pathVagrantFileNew,self.logger): + return False + self.pathVagrantfile=pathVagrantFileNew + Util.clear_vagrant_files(pathTmp,self.logger) + # Create VM + try: + vm = vagrant.Vagrant(root=pathTmp, out_cm=log_cm, err_cm=log_cm) + self.vm=vm + vm.up(provider=self.provider) + # with settings(host_string= vm.user_hostname_port(), + # key_filename = vm.keyfile(), + # disable_known_hosts = True): + # run("uname -a") + except Exception, e: + self.logger.error('Failed while creating vm %s.' %(self.name), exc_info=True) + self.logger.info('Since creation failed, trying to destroy vm %s.' %(self.name), exc_info=True) + #if not self.vm.destroy(): + # self.logger.error('Can not destroy %s.' %(self.name), exc_info=True) + ## vm.destroy() seems to be always returning false at this stage (opentsack), but destroying works fine -> Ignore it. + self.vm.destroy() + return False + self.logger.info("END Creating %s." %(self.name)) + self.logger.info("GET IP of %s." %(self.name)) + self.ip = self.get_ip() + # the IP Part is needed, because on OpenStack the 'internal' IP differs from the 'external' (SSH) IP + if self.ip == None: + self.logger.error('Failed getting IP while creating vm %s.' %(self.name), exc_info=True) + self.logger.info('Since creation failed, trying to destroy vm %s.' %(self.name), exc_info=True) + self.vm.destroy() + return False + self.created=True + return True + + # Return the output + def run_with_output (self,disableKnownHosts,command,warn_only=False,quiet=False): + with settings(host_string = self.vm.user_hostname_port(), + key_filename = self.vm.keyfile(), + disable_known_hosts = disableKnownHosts): + result = run(command,warn_only=warn_only, quiet=quiet) + return result + + # Only return true/false + def run_without_output (self,disableKnownHosts,command,warn_only=False,quiet=False,test=False): + result = self.run_with_output (disableKnownHosts,command,warn_only,quiet) + if result.return_code == 0 or (warn_only and result.return_code == 255) or (test and result.return_code == -1): + return True + else: + self.logger.error("Command '%s' on %s returned %s." %(command, self.vm.user_hostname_port(), result.return_code)) + return False + + def get_ip(self): + result = self.run_with_output (True,'sudo ifconfig | grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" | head -n1',True, True) + if result.return_code == 0: + return result.stdout + else: + self.logger.error("Can't get IP on %s, command returned %s." %(self.vm.user_hostname_port(), result.return_code)) + return None \ No newline at end of file diff --git a/databases/__init__.py b/databases/__init__.py new file mode 100644 index 0000000..0cb6e0a --- /dev/null +++ b/databases/__init__.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +import pkgutil + +def getDict(logger): + dbConfig = {} + for importer, modname, ispkg in pkgutil.iter_modules(__path__): + try: + m = importer.find_module(modname).load_module(modname) + dbConfig[modname] = m.getDict() + except Exception, e: + logger.error("Can't import %s/%s." %(__path__,modname), exc_info=True) + return {} + return dbConfig diff --git a/databases/basicdb.py b/databases/basicdb.py new file mode 100644 index 0000000..ae44be8 --- /dev/null +++ b/databases/basicdb.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant"] + dbConfig["db_client"]="basicdb" + dbConfig["db_args"]="-p basicdb.verbose=False -p basicdb.randomizedelay=False" + dbConfig["db_name"]="basicdb" + dbConfig["db_desc"]="Basic DB w/o any client" + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= True + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/basicjdbc.py b/databases/basicjdbc.py new file mode 100644 index 0000000..e5a1539 --- /dev/null +++ b/databases/basicjdbc.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p test=True" + dbConfig["db_name"]="basicjdbc" + dbConfig["db_desc"]="Basic JDBC w/o any connection" + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= True + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/basickairosdb.py b/databases/basickairosdb.py new file mode 100644 index 0000000..69abf1f --- /dev/null +++ b/databases/basickairosdb.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p test=True" + dbConfig["db_name"]="basickairosdb" + dbConfig["db_desc"]="Basic Kairos w/o any connection" + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= True + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/basicopentsdb.py b/databases/basicopentsdb.py new file mode 100644 index 0000000..b047efc --- /dev/null +++ b/databases/basicopentsdb.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p test=True" + dbConfig["db_name"]="basicopentsdb" + dbConfig["db_desc"]="Basic OpenTSDB w/o any connection" + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= True + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/blueflood_cl1_rf1.py b/databases/blueflood_cl1_rf1.py new file mode 100644 index 0000000..7f61898 --- /dev/null +++ b/databases/blueflood_cl1_rf1.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood_cl1_rf1" + dbConfig["db_desc"]="Blueflood with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/blueflood.conf'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blueflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/blueflood_cl5_rf1.py b/databases/blueflood_cl5_rf1.py new file mode 100644 index 0000000..2141db1 --- /dev/null +++ b/databases/blueflood_cl5_rf1.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood_cl5_rf1" + dbConfig["db_desc"]="Blueflood with Cassandra together on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|CASSANDRA_HOSTS=localhost:9160|CASSANDRA_HOSTS=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blueflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/blueflood_cl5_rf2.py b/databases/blueflood_cl5_rf2.py new file mode 100644 index 0000000..26d6247 --- /dev/null +++ b/databases/blueflood_cl5_rf2.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood_cl5_rf2" + dbConfig["db_desc"]="Blueflood with Cassandra together on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|CASSANDRA_HOSTS=localhost:9160|CASSANDRA_HOSTS=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blueflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/blueflood_cl5_rf5.py b/databases/blueflood_cl5_rf5.py new file mode 100644 index 0000000..2b9f42b --- /dev/null +++ b/databases/blueflood_cl5_rf5.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood_cl5_rf5" + dbConfig["db_desc"]="Blueflood with Cassandra together on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|CASSANDRA_HOSTS=localhost:9160|CASSANDRA_HOSTS=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blueflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/druid_cl1_rf1.py b/databases/druid_cl1_rf1.py new file mode 100644 index 0000000..181f9a8 --- /dev/null +++ b/databases/druid_cl1_rf1.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP%% -p queryip=%%IP%% -p zookeeperport=2181 -p queryport=8090 -p replicants=1" + dbConfig["db_name"]="druid_cl1_rf1" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 1 VM. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start druid.service'", "bash -c 'sleep 180'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid.service | grep -c \"active (exited)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/druid_cl5_rf1.py b/databases/druid_cl5_rf1.py new file mode 100644 index 0000000..32411d8 --- /dev/null +++ b/databases/druid_cl5_rf1.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP0%% -p queryip=%%IP1%% -p zookeeperport=2181 -p queryport=8090 -p replicants=1" + dbConfig["db_name"]="druid_cl5_rf1" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 5 VMs with Replication Factor 1. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/_common/common.runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP1%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP2%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP3%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP4%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_coordinator.service'"], + 1 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_broker.service'"], + 2 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_historical.service'"], + 3 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_middlemanager.service'"], + 4 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_overlord.service'", + "bash -c 'sleep 180'"] + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'"], + 1 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + } + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/druid_cl5_rf2.py b/databases/druid_cl5_rf2.py new file mode 100644 index 0000000..65396ab --- /dev/null +++ b/databases/druid_cl5_rf2.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +# Does not work with 5 VMs, needs more historical nodes for replication 5 times? +# replication is not expected to bring performance bonus: https://groups.google.com/forum/#!topic/druid-development/0TBL5-3Z2PI + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP0%% -p queryip=%%IP1%% -p zookeeperport=2181 -p queryport=8090 -p replicants=2" + dbConfig["db_name"]="druid_cl5_rf2" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 5 VMs with Replication Factor 2. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/_common/common.runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP1%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP2%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP3%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP4%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_coordinator.service'"], + 1 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_broker.service'"], + 2 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_historical.service'"], + 3 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_middlemanager.service'"], + 4 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_overlord.service'", + "bash -c 'sleep 180'"] + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'"], + 1 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + } + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/druid_cl5_rf5.py b/databases/druid_cl5_rf5.py new file mode 100644 index 0000000..00b45fe --- /dev/null +++ b/databases/druid_cl5_rf5.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +# Does not work with 5 VMs, needs more historical nodes for replication 5 times? +# replication is not expected to bring performance bonus: https://groups.google.com/forum/#!topic/druid-development/0TBL5-3Z2PI + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP0%% -p queryip=%%IP1%% -p zookeeperport=2181 -p queryport=8090 -p replicants=5" + dbConfig["db_name"]="druid_cl5_rf5" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 5 VMs with Replication Factor 5. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/_common/common.runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP1%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP2%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP3%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP4%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_coordinator.service'"], + 1 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_broker.service'"], + 2 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_historical.service'"], + 3 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_middlemanager.service'"], + 4 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_overlord.service'", + "bash -c 'sleep 180'"] + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'"], + 1 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + } + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/influxdb_cl1_rf1.py b/databases/influxdb_cl1_rf1.py new file mode 100644 index 0000000..de622f1 --- /dev/null +++ b/databases/influxdb_cl1_rf1.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb_cl1_rf1" + dbConfig["db_desc"]="InfluxDB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start influxdb.service'", + "sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/influxdb_cl5_rf1.py b/databases/influxdb_cl5_rf1.py new file mode 100644 index 0000000..8d06fb0 --- /dev/null +++ b/databases/influxdb_cl5_rf1.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb_cl5_rf1" + dbConfig["db_desc"]="InfluxDB on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'systemctl start influxdb.service; sleep 5'"] # the sleep makes sure that 0,1,2 are raft, 3,4 are data vms + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : [ + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=ALTER RETENTION POLICY default ON testdb DURATION INF REPLICATION 1\" 2>&1 | grep -c \"error\")'", + ] + } + dbConfig["postrun_dict"]= {} + # Checking that influxdb service runs, not exited and SHOW SERVERS show 3 raft servers + 2 non-raft servers + # For versions > 0.9.4 there is a new coloumn raft-leader for "SHOW SERVERS" + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'", + # "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + # "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"false\")-1))'"] + "%%SSH%%sudo -s bash -c 'exit $(($(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + "$(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -v \"true\" | grep -c \"false\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/influxdb_cl5_rf2.py b/databases/influxdb_cl5_rf2.py new file mode 100644 index 0000000..8223dbb --- /dev/null +++ b/databases/influxdb_cl5_rf2.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb_cl5_rf2" + dbConfig["db_desc"]="InfluxDB on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'systemctl start influxdb.service; sleep 5'"] # the sleep makes sure that 0,1,2 are raft, 3,4 are data vms + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : [ + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=ALTER RETENTION POLICY default ON testdb DURATION INF REPLICATION 2\" 2>&1 | grep -c \"error\")'", + ] + } + dbConfig["postrun_dict"]= {} + # Checking that influxdb service runs, not exited and SHOW SERVERS show 3 raft servers + 2 non-raft servers + # For versions > 0.9.4 there is a new coloumn raft-leader for "SHOW SERVERS" + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'", + # "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + # "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"false\")-1))'"] + "%%SSH%%sudo -s bash -c 'exit $(($(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + "$(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -v \"true\" | grep -c \"false\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/influxdb_cl5_rf5.py b/databases/influxdb_cl5_rf5.py new file mode 100644 index 0000000..06be088 --- /dev/null +++ b/databases/influxdb_cl5_rf5.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb_cl5_rf5" + dbConfig["db_desc"]="InfluxDB on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'systemctl start influxdb.service; sleep 5'"] # the sleep makes sure that 0,1,2 are raft, 3,4 are data vms + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : [ + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=ALTER RETENTION POLICY default ON testdb DURATION INF REPLICATION 5\" 2>&1 | grep -c \"error\")'", + ] + } + dbConfig["postrun_dict"]= {} + # Checking that influxdb service runs, not exited and SHOW SERVERS show 3 raft servers + 2 non-raft servers + # For versions > 0.9.4 there is a new coloumn raft-leader for "SHOW SERVERS" + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'", + # "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + # "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"false\")-1))'"] + "%%SSH%%sudo -s bash -c 'exit $(($(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + "$(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -v \"true\" | grep -c \"false\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/kairosdb_cl1_rf1.py b/databases/kairosdb_cl1_rf1.py new file mode 100644 index 0000000..961f92d --- /dev/null +++ b/databases/kairosdb_cl1_rf1.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_cl1_rf1" + dbConfig["db_desc"]="KairosDB with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'cassandra-cli -h localhost -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/kairosdb_cl5_rf1.py b/databases/kairosdb_cl5_rf1.py new file mode 100644 index 0000000..5a8a35b --- /dev/null +++ b/databases/kairosdb_cl5_rf1.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_cl5_rf1" + dbConfig["db_desc"]="KairosDB with Cassandra on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|kairosdb.datastore.cassandra.host_list=localhost:9160|kairosdb.datastore.cassandra.host_list=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160,|g\" /opt/kairosdb/conf/kairosdb.properties'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'systemctl start kairosdb.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for kairos but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/kairosdb_cl5_rf2.py b/databases/kairosdb_cl5_rf2.py new file mode 100644 index 0000000..3e4fcf7 --- /dev/null +++ b/databases/kairosdb_cl5_rf2.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_cl5_rf2" + dbConfig["db_desc"]="KairosDB with Cassandra on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|kairosdb.datastore.cassandra.host_list=localhost:9160|kairosdb.datastore.cassandra.host_list=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160,|g\" /opt/kairosdb/conf/kairosdb.properties'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'systemctl start kairosdb.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for kairos but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/kairosdb_cl5_rf5.py b/databases/kairosdb_cl5_rf5.py new file mode 100644 index 0000000..59b1581 --- /dev/null +++ b/databases/kairosdb_cl5_rf5.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_cl5_rf5" + dbConfig["db_desc"]="KairosDB with Cassandra on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|kairosdb.datastore.cassandra.host_list=localhost:9160|kairosdb.datastore.cassandra.host_list=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160,|g\" /opt/kairosdb/conf/kairosdb.properties'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'systemctl start kairosdb.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for kairos but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/kairosdb_h2_cl1_rf1.py b/databases/kairosdb_h2_cl1_rf1.py new file mode 100644 index 0000000..2f52c1b --- /dev/null +++ b/databases/kairosdb_h2_cl1_rf1.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/opt/kairosdb/build/h2db"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_h2_cl1_rf1" + dbConfig["db_desc"]="KairosDB with H2 together on one VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/monetdb_cl1_rf1.py b/databases/monetdb_cl1_rf1.py new file mode 100644 index 0000000..7a020d8 --- /dev/null +++ b/databases/monetdb_cl1_rf1.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/monetdb"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=nl.cwi.monetdb.jdbc.MonetDriver -p db.url=jdbc:monetdb://%%IP%%/test -p db.user=vagrant -p db.passwd=vagrant" + dbConfig["db_name"]="monetdb_cl1_rf1" + dbConfig["db_desc"]="MonetDB DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "%%SSH%%sudo -s bash -c 'sed -i \"s|STARTUP=\\\\\"no\\\\\"|STARTUP=\\\\\"yes\\\\\"|g\" /etc/default/monetdb5-sql'", + "%%SSH%%sudo -s bash -c '/etc/init.d/monetdb5-sql start'", + "%%SSH%%sudo -s bash -c 'monetdb create test'", + "%%SSH%%sudo -s bash -c 'monetdb release test'", + "%%SSH%%mclient -d test -s \"CREATE ROLE vagrant_role\"", + "%%SSH%%mclient -d test -s \"GRANT ALL FROM TO vagrant_role\"", + "%%SSH%%mclient -d test -s \"CREATE SCHEMA test AUTHORIZATION vagrant_role\"", + "%%SSH%%mclient -d test -s \"CREATE USER vagrant WITH PASSWORD 'vagrant' NAME 'vagrant' SCHEMA test\"", + "%%SSH%%mclient -d test -s \"GRANT vagrant_role TO vagrant\"", + "%%SSH%%mclient -d test '/home/vagrant/files/create_table.monetdb'", + "%%SSH%%mclient -d test -s \"GRANT ALL ON test.usermetric TO vagrant\""] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"monetdb\" | grep -v \"grep\" | wc -l)-2))'",] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/mysql_cl1_rf1.py b/databases/mysql_cl1_rf1.py new file mode 100644 index 0000000..41aa095 --- /dev/null +++ b/databases/mysql_cl1_rf1.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/mysql"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=com.mysql.jdbc.Driver -p db.url=jdbc:mysql://%%IP%%:3306/test -p db.user=root -p db.passwd=vagrant" + dbConfig["db_name"]="mysql_cl1_rf1" + dbConfig["db_desc"]="MySQL DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "mysql -h \"%%IP%%\" -u root --password='vagrant' -e 'create database test'", + "%%SSH%%mysql -u root --password='vagrant' -e 'source /home/vagrant/files/create_table.mysql'" + ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/newts_cl1_rf1.py b/databases/newts_cl1_rf1.py new file mode 100644 index 0000000..ea4877f --- /dev/null +++ b/databases/newts_cl1_rf1.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts_cl1_rf1" + dbConfig["db_desc"]="NewTS with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/newts_cl5_rf1.py b/databases/newts_cl5_rf1.py new file mode 100644 index 0000000..4f212f9 --- /dev/null +++ b/databases/newts_cl5_rf1.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts_cl5_rf1" + dbConfig["db_desc"]="NewTS with Cassandra together on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP0%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/newts_cl5_rf2.py b/databases/newts_cl5_rf2.py new file mode 100644 index 0000000..e63e0e2 --- /dev/null +++ b/databases/newts_cl5_rf2.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts_cl5_rf2" + dbConfig["db_desc"]="NewTS with Cassandra together on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP0%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/newts_cl5_rf5.py b/databases/newts_cl5_rf5.py new file mode 100644 index 0000000..1f5d3c1 --- /dev/null +++ b/databases/newts_cl5_rf5.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts_cl5_rf5" + dbConfig["db_desc"]="NewTS with Cassandra together on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP0%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/opentsdb_cl1_rf1.py b/databases/opentsdb_cl1_rf1.py new file mode 100644 index 0000000..b4bd51e --- /dev/null +++ b/databases/opentsdb_cl1_rf1.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hbase-1.1.2"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb_cl1_rf1" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-3))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/opentsdb_cl5_rf1.py b/databases/opentsdb_cl5_rf1.py new file mode 100644 index 0000000..c91cdec --- /dev/null +++ b/databases/opentsdb_cl5_rf1.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hadoop"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb_cl5_rf1" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop on 5 VMs and Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-5))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 1 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + } + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/databases/opentsdb_cl5_rf2.py b/databases/opentsdb_cl5_rf2.py new file mode 100644 index 0000000..99241bc --- /dev/null +++ b/databases/opentsdb_cl5_rf2.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hadoop"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb4" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop on 5 VMs and Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-5))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 1 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + } + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/databases/opentsdb_cl5_rf5.py b/databases/opentsdb_cl5_rf5.py new file mode 100644 index 0000000..92812f4 --- /dev/null +++ b/databases/opentsdb_cl5_rf5.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hadoop"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb_cl5_rf5" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop on 5 VMs and Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-5))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 1 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + } + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/databases/postgres_cl1_rf1.py b/databases/postgres_cl1_rf1.py new file mode 100644 index 0000000..66b612e --- /dev/null +++ b/databases/postgres_cl1_rf1.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/postgresql/9.4/main"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=org.postgresql.Driver -p db.url=jdbc:postgresql://%%IP%%/test -p db.user=vagrant -p db.passwd=vagrant" + dbConfig["db_name"]="postgres_cl1_rf1" + dbConfig["db_desc"]="Postgres DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "PGPASSWORD=vagrant psql -h \"%%IP%%\" -U postgres -c 'create database test'", + "PGPASSWORD=vagrant psql test -h \"%%IP%%\" -U postgres -c \"create user vagrant password 'vagrant';\"", + "PGPASSWORD=vagrant psql test -h \"%%IP%%\" -U postgres -c \"GRANT ALL PRIVILEGES ON DATABASE test TO vagrant;\"", + "%%SSH%%PGPASSWORD=vagrant psql -U vagrant test -f '/home/vagrant/files/create_table.psql'", + "%%SSH%%sudo -s bash -c 'echo -e \"host all all %%IPgen%% md5\" >> /etc/postgresql/9.4/main/pg_hba.conf'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/rhombus_cl1_rf1.py b/databases/rhombus_cl1_rf1.py new file mode 100644 index 0000000..9179d35 --- /dev/null +++ b/databases/rhombus_cl1_rf1.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=%%IP%% -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl1.json\"" + dbConfig["db_name"]="rhombus_cl1_rf1" + dbConfig["db_desc"]="Rhombus with Cassandra on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/databases/rhombus_cl5_rf1.py b/databases/rhombus_cl5_rf1.py new file mode 100644 index 0000000..b90a8cd --- /dev/null +++ b/databases/rhombus_cl5_rf1.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\" -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl1.json\"" + dbConfig["db_name"]="rhombus_cl5_rf1" + dbConfig["db_desc"]="Rhombus with Cassandra on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/rhombus_cl5_rf2.py b/databases/rhombus_cl5_rf2.py new file mode 100644 index 0000000..0bae134 --- /dev/null +++ b/databases/rhombus_cl5_rf2.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\" -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl2.json\"" + dbConfig["db_name"]="rhombus4" + dbConfig["db_desc"]="Rhombus with Cassandra on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/databases/rhombus_cl5_rf5.py b/databases/rhombus_cl5_rf5.py new file mode 100644 index 0000000..6f883e8 --- /dev/null +++ b/databases/rhombus_cl5_rf5.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\" -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl5.json\"" + dbConfig["db_name"]="rhombus_cl5_rf5" + dbConfig["db_desc"]="Rhombus with Cassandra on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/dummy.box b/dummy.box new file mode 100644 index 0000000000000000000000000000000000000000..943717e603c52b43086a022cd2755dfd2a7169e4 GIT binary patch literal 156 zcmb2|=3r2C*%Zpa{Pw&z*C7Lu)`va2yC$$+u@SxFyM$46i)!awk?(m&J2_sh==e}S z*?32KLEdhwrBb^ilB;$8M(Q}8zjp8b<(#IvbL`JsHY!%UU%SmQ<8h6F(<|3&dv;8b z+B_vmeD{>(%G> /etc/sudoers"; \ +in-target /bin/sh -c "echo 'export DEBIAN_FRONTEND=noninteractive' >> /home/vagrant/.bashrc"; \ +in-target /bin/sh -c "echo 'export DEBIAN_FRONTEND=noninteractive' >> /root/.bashrc"; \ +in-target /bin/sh -c "echo 'blacklist ipv6' >> /etc/modprobe.d/blacklist.conf"; \ +in-target /bin/sh -c "echo 'net.ipv6.conf.all.disable_ipv6 = 1' >> /etc/sysctl.d/01-disable-ipv6.conf"; \ +in-target mkdir -p /home/vagrant/.ssh; \ +in-target /bin/sh -c "echo 'fs.file-max = 404358' >> /etc/sysctl.conf"; \ +in-target /bin/sh -c "echo 'fs.file-max = 404358' >> /etc/sysctl.d/99-sysctl.conf"; \ +in-target /bin/sh -c "echo '* - nofile 404358' >> /etc/security/limits.conf"; \ +in-target /bin/sh -c "echo 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key' >> /home/vagrant/.ssh/authorized_keys"; \ +in-target /bin/sh -c "echo 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key' >> /home/vagrant/.ssh/id_rsa.pub"; \ +in-target /bin/sh -c "echo 'Host *' >> /home/vagrant/.ssh/config"; \ +in-target /bin/sh -c "echo ' StrictHostKeyChecking no' >> /home/vagrant/.ssh/config"; \ +in-target /bin/sh -c "echo ' UserKnownHostsFile=/dev/null' >> /home/vagrant/.ssh/config"; \ +in-target /bin/sh -c "echo '-----BEGIN RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '+vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s=' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '-----END RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa"; \ +in-target chmod 640 /home/vagrant/.ssh/id_rsa.pub; \ +in-target chmod 600 /home/vagrant/.ssh/id_rsa; \ +in-target chown -R vagrant:vagrant /home/vagrant/; \ +in-target chmod -R go-rwx /home/vagrant/.ssh/authorized_keys; \ +in-target cp -r /home/vagrant/.ssh /root/; \ +in-target chown -R root:root /root/.ssh/; \ +in-target sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config; \ +in-target rm /etc/udev/rules.d/70-persistent-net.rules; \ +in-target /bin/sh -c "echo '#!/bin/bash' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'get_ip=\$(sudo ifconfig | grep -E -o \"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\" | head -n1)' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"echo \\\"\$get_ip \$1\\\" >> /etc/hosts\"' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"sudo hostname \$1;' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"echo \\\"\$1\\\" > /etc/hostname\"' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"sudo sed -i \"s/127.0.1.1.*$//g\" /etc/hosts' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo hostnamectl set-hostname \$1' >> /home/vagrant/change_hostname.sh"; \ +in-target cp /home/vagrant/change_hostname.sh /root/change_hostname.sh; \ +in-target chmod 775 /home/vagrant/change_hostname.sh /root/change_hostname.sh; \ +in-target chown vagrant:vagrant /home/vagrant/change_hostname.sh; \ +in-target chown root:root /root/change_hostname.sh; \ +in-target sed -i 's/name: debian/name: vagrant/g' /etc/cloud/cloud.cfg; \ +in-target sed -i 's/gecos: Debian/gecos: Vagrant/g' /etc/cloud/cloud.cfg; \ +in-target sed -i 's/lock_passwd: True/lock_passwd: False/g' /etc/cloud/cloud.cfg; \ +in-target sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200"/' /etc/default/grub; \ +in-target /bin/sh -c "echo 'ForwardToConsole=yes' >> /etc/systemd/journald.conf"; \ +in-target sed -i 's/^BLANK_TIME=.*/BLANK_TIME=0/' /etc/kbd/config; \ +in-target sed -i 's/^POWERDOWN_TIME=.*/POWERDOWN_TIME=0/' /etc/kbd/config; \ +in-target sed -i 's/^[ \t#]KEYBOARD_DELAY=.*/KEYBOARD_DELAY=1000/' /etc/kbd/config; \ +in-target rm -f /etc/ssh/ssh_host_*; \ +in-target rm -f /etc/udev/rules.d/70-persistent-net.rules; \ +in-target rm -f /lib/udev/write_net_rules; \ +in-target /bin/sh -c "echo '# This file describes the network interfaces available on your system' > /etc/network/interfaces"; \ +in-target /bin/sh -c "echo '# and how to activate them. For more information, see interfaces(5).' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo '# The loopback network interface' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo 'auto lo' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo 'iface lo inet loopback' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo '# The normal eth0' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo 'auto eth0' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo 'iface eth0 inet dhcp' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo '# Maybe the VM has 2 NICs?' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo 'allow-hotplug eth1' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo 'iface eth1 inet dhcp' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo '# Maybe the VM has 3 NICs?' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo 'allow-hotplug eth2' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo 'iface eth2 inet dhcp' >> /etc/network/interfaces"; \ +in-target /bin/sh -c "echo '# to update this file, run dpkg-reconfigure cloud-init' > /etc/cloud/cloud.cfg.d/90_dpkg.cfg"; \ +in-target /bin/sh -c "echo 'datasource_list: [ConfigDrive, Openstack, Ec2]' >> /etc/cloud/cloud.cfg.d/90_dpkg.cfg"; \ +in-target /bin/sh -c "echo \"mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']\" >> /etc/cloud/cloud.cfg"; \ +in-target /bin/sh -c "echo 'manage_etc_hosts: true' >> /etc/cloud/cloud.cfg"; \ +in-target /bin/sh -c 'update-initramfs -u'; \ +in-target /bin/sh -c 'update-grub'; \ +in-target apt-get clean; \ No newline at end of file diff --git a/preseed-vsphere-controlvm.cfg b/preseed-vsphere-controlvm.cfg new file mode 100644 index 0000000..815fc73 --- /dev/null +++ b/preseed-vsphere-controlvm.cfg @@ -0,0 +1,259 @@ +#### Contents of the preconfiguration file (for jessie) +#### Control-VM on vSphere +### Localization +d-i debian-installer/language string en +d-i debian-installer/country string US +d-i debian-installer/locale string en_US.UTF-8 +d-i localechooser/supported-locales multiselect en_US.UTF-8 +d-i keyboard-configuration/xkb-keymap select de +d-i netcfg/choose_interface select auto +d-i netcfg/link_wait_timeout string 10 +d-i netcfg/dhcp_timeout string 60 +d-i netcfg/dhcpv6_timeout string 60 +d-i netcfg/get_hostname string Vagrant-VM +d-i netcfg/get_domain string localdomain +d-i hw-detect/load_firmware boolean true +d-i mirror/country string manual +d-i mirror/http/hostname string ftp.de.debian.org +d-i mirror/http/directory string /debian +d-i mirror/http/proxy string +d-i passwd/root-login boolean false +# Generierung von PW Hashes mit mkpasswd -m sha-512 +#d-i passwd/root-password-crypted password +d-i passwd/root-password password vagrant +d-i passwd/root-password-again password vagrant +d-i passwd/user-fullname string Vagrant +d-i passwd/username string vagrant +d-i passwd/user-password password vagrant +d-i passwd/user-password-again password vagrant +#d-i passwd/user-password-crypted password [MD5 hash] +d-i passwd/user-default-groups string vagrant cdrom floppy audio dip video plugdev netdev sudo +d-i clock-setup/utc boolean true +d-i time/zone string Etc/UTC +d-i clock-setup/ntp boolean true +d-i partman-auto/disk string /dev/sda +d-i partman-auto/method string regular +d-i partman-lvm/device_remove_lvm boolean true +d-i partman-md/device_remove_md boolean true +d-i partman-lvm/confirm boolean true +d-i partman-lvm/confirm_nooverwrite boolean true +#d-i partman-auto/choose_recipe select home +d-i partman-auto/expert_recipe string \ +boot-root :: \ +1000 10000 1000000000000 ext4 \ +$primary{ } $bootable{ } \ +method{ format } format{ } \ +use_filesystem{ } filesystem{ ext4 } \ +mountpoint{ / } \ +. \ +512 512 512 linux-swap \ +method{ swap } format{ } \ +. +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +d-i partman/mount_style select uuid +d-i base-installer/kernel/image string linux-image-amd64 +d-i apt-setup/non-free boolean true +d-i apt-setup/contrib boolean true +d-i apt-setup/services-select multiselect security, updates +d-i apt-setup/security_host string security.debian.org +#d-i apt-setup/multiarch string i386 +tasksel tasksel/first multiselect standard, ssh-server +d-i pkgsel/include string build-essential, ruby-highline, ruby-termios, sudo, ntp, linux-headers-amd64, dpkg, screen, htop, wget, curl, open-vm-tools, rsync, libpam-systemd, python2.7, fabric, resolvconf, linux-image-amd64, openssh-server, python-dateutil, python-jinja2, python-numpy, python-pandas, python-flask, python-redis, python-requests, python-six, python-tornado, python-werkzeug, python-markupsafe, python-greenlet, python-zmq, python-yaml, python-pip, wkhtmltopdf, python-magic, fabric, vagrant, zlib1g-dev, zlib1g, libxml2, libxml2-dev, libxslt1.1, libxslt1-dev, python-webcolors, python-pyvmomi, git, apache2, maven, openjdk-7-jre-headless, openjdk-7-jdk +d-i pkgsel/upgrade select full-upgrade +popularity-contest popularity-contest/participate boolean false +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean true +d-i grub-installer/bootdev string /dev/sda +#d-i grub-installer/bootdev string default +#d-i debian-installer/add-kernel-opts string nousb +d-i finish-install/reboot_in_progress note +d-i cdrom-detect/eject boolean true +d-i debian-installer/exit/poweroff boolean true +d-i preseed/late_command string \ +in-target sed -i 's/^%sudo.*$/%sudo ALL=(ALL:ALL) NOPASSWD: ALL/g' /etc/sudoers; \ +in-target /bin/sh -c "echo 'Defaults env_keep += \"SSH_AUTH_SOCK DEBIAN_FRONTEND\"' >> /etc/sudoers"; \ +in-target /bin/sh -c "echo 'export DEBIAN_FRONTEND=noninteractive' >> /home/vagrant/.bashrc"; \ +in-target /bin/sh -c "echo 'export DEBIAN_FRONTEND=noninteractive' >> /root/.bashrc"; \ +in-target /bin/sh -c "echo 'blacklist ipv6' >> /etc/modprobe.d/blacklist.conf"; \ +in-target /bin/sh -c "echo 'net.ipv6.conf.all.disable_ipv6 = 1' >> /etc/sysctl.d/01-disable-ipv6.conf"; \ +in-target mkdir -p /home/vagrant/.ssh; \ +in-target /bin/sh -c "echo 'fs.file-max = 404358' >> /etc/sysctl.conf"; \ +in-target /bin/sh -c "echo 'fs.file-max = 404358' >> /etc/sysctl.d/99-sysctl.conf"; \ +in-target /bin/sh -c "echo '* - nofile 404358' >> /etc/security/limits.conf"; \ +in-target /bin/sh -c "echo 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key' >> /home/vagrant/.ssh/authorized_keys"; \ +in-target /bin/sh -c "echo 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key' >> /home/vagrant/.ssh/id_rsa.pub"; \ +in-target /bin/sh -c "echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDB7xSmSduIsYZhuQmq6nyglZS7d1qx0XHNFBX7JInOi9BKtMHO4NtAwmz5bwYAazMaN2+1ZySuYaiODvm1CbUq7NbvEPEB6vnzAEbdJtwe8/v9Z1lFX4UvYI5ajTmkF5E8hR7m6DZJz0JWQHvboLluFf6AF2ZeWXK2HVFH9prdbOu2zvt0dhK6K1gm1InmgS063pxfADQQBNwFiDocqUiBvEoxHxUcGKIvq4OA/Df9f/zuFieaP6S6zAS3gutApdUc40jAVXvZnCkIhJRaUiHv29kSWj468zfzOUVgsrdlT2HBjUlp+cSQuFDa4BJOBBjsSSmBaM4Mnv5Jm1X7pFcQob2QpVxp+HnIK5RkpDimaygYMeHdGMESk7MVHtIouvSOVzovYom5BopZwHXkeQFHCJJRfVBn5aQF7MUPSsE+dEvFsz3yRydIOM9KGmbcSQJEYeQl++u8TM1xF3XYHZK3ID6C9z7oHQGqAOo7DOi/5l7SrAhCgIGlUUKQYzyKT0Kj656FI3NKdkITBQY7vi0xiuHtUxy3rjzihvwubsWigNtCA4PKnuVCeT9/1P4eKyCKW0kHFswQknXy9Nh0z/AklH7OFUEhICeeuJ3pi/rmn9dkA7yr9O0n73Es/i/gtTO3YYaJi1T694d59uWs3i0o/Trq6OW8KRZpKIA/WPQ2eQ== insecure public key' >> /home/vagrant/.ssh/id_rsa2.pub"; \ +in-target /bin/sh -c "echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD/nOyuZGM0iXaznEJmD50uMYepaDLeVsbqIexjtHCdHuCJpGk7nTiH9/vs1Uxmn7VF3yecc8A9uONWhIN92KauTPuEqNsGgSK+R7Lu2HwYs0tvi+Lfp+QEy56EcH8gFN8rKA2jS+WejWfECDdIAm1Uimx3aRiVBn28m7w2dtAbDsk8LU/ZusdNh/ih92whoJH2Af+w7dmiyIB8YQWvEBr9xWHfws0L+wR0HI/G7xx02Gua5+vBK7rNtB/N4nfA/Vj8Njge+aOY+Fo390kF22R+jEdaTUcgNH+fIRwgFmmcivJpNATw52JUZ0UwVSZARp2+pUiph4tsacfCZvo08LIWHNOl102IrfCZVSLBNkDmRsWzMkUBZ9MCFWI/Pzn1hAAMj5dBDQ0zefsQIqaPTgY9poikUHqu+W7+LXkIOAxLpaZK7iUeMHJ2mudxCNNs+GVeHnVWXipZ14X+HydSsW2pU/z6JbjMw8xkTQFEXsp9pfixmVizcbWLpS163DMPvbS/bW3nRAOO9vLvbUVj/fBKj5wcdf4aIJvI6hbBNxJNfrQYy+DHgwZCrgnoFSJ63PNYxjAgKpPpEkXL7sTt0yCvcdv8TAE1uckzOWVy//AjhPrzFGtPKKIdJaoyL/6tVWIXKfS0fhYK7h9XpijAt428FZFrFUWCO28Lyho+fAZauQ== insecure public key' >> /home/vagrant/.ssh/id_rsa3.pub"; \ +in-target /bin/sh -c "echo 'Host *' >> /home/vagrant/.ssh/config"; \ +in-target /bin/sh -c "echo ' StrictHostKeyChecking no' >> /home/vagrant/.ssh/config"; \ +in-target /bin/sh -c "echo ' UserKnownHostsFile=/dev/null' >> /home/vagrant/.ssh/config"; \ +in-target /bin/sh -c "echo '-----BEGIN RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '+vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s=' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '-----END RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '-----BEGIN RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'MIIJJwIBAAKCAgEAwe8UpknbiLGGYbkJqup8oJWUu3dasdFxzRQV+ySJzovQSrTB' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'zuDbQMJs+W8GAGszGjdvtWckrmGojg75tQm1KuzW7xDxAer58wBG3SbcHvP7/WdZ' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'RV+FL2COWo05pBeRPIUe5ug2Sc9CVkB726C5bhX+gBdmXllyth1RR/aa3Wzrts77' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'dHYSuitYJtSJ5oEtOt6cXwA0EATcBYg6HKlIgbxKMR8VHBiiL6uDgPw3/X/87hYn' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'mj+kuswEt4LrQKXVHONIwFV72ZwpCISUWlIh79vZElo+OvM38zlFYLK3ZU9hwY1J' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'afnEkLhQ2uASTgQY7EkpgWjODJ7+SZtV+6RXEKG9kKVcafh5yCuUZKQ4pmsoGDHh' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '3RjBEpOzFR7SKLr0jlc6L2KJuQaKWcB15HkBRwiSUX1QZ+WkBezFD0rBPnRLxbM9' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '8kcnSDjPShpm3EkCRGHkJfvrvEzNcRd12B2StyA+gvc+6B0BqgDqOwzov+Ze0qwI' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'QoCBpVFCkGM8ik9Co+uehSNzSnZCEwUGO74tMYrh7VMct6484ob8Lm7FooDbQgOD' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'yp7lQnk/f9T+HisgiltJBxbMEJJ18vTYdM/wJJR+zhVBISAnnrid6Yv65p/XZAO8' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'q/TtJ+9xLP4v4LUzt2GGiYtU+veHefblrN4tKP066ujlvCkWaSiAP1j0NnkCAwEA' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'AQKCAgAO0QRD3Bqwq9d3edqaO0YAQs1VMT41nanTIDi5skXxCM+GFZ9E/friTLhk' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'qi3MNGR4GUooktPDmuR0zgIX6cD0oZmeNC4lll04SoofdUuV9dAHwTCZ0z1qrDbU' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'BjwkJETNWeJNg+o542LPEigkVHg2R+nkwWTpym2wKjc+h0G3rw2nLtMZR7gQjyUx' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '+kT63l2lRMKvo2VW3/grWAgQjoJinw8QB67mMZ+agsEORrbEYFXjnr+x0jD0sIef' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'uZndm43Xoim5wA4xRvP/mZl3+RRsreA8vbZJbLGWnIaHZ8AJNnJihjfYp+NzpxFO' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'V5YubbO1wbUxFN/BKRiGaR69lgWstmtoBW83IjMUV28a+wlHg4psPvixOCRHbBoz' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'FXJwm8IofYvMuQDYiyEdlC2RefOae2hWbYlPtwH2mbLSjGzD/b6Imyez2WfeBtY8' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'qQHQx5zloXfAZXvOr+VQLuTKRX4nfOqiCZ74+AR2ixcVp280qFbMsbOGgAnnEGfe' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'Ca43L1GNdUmql79v5s25QpCL+gr3JqTwwVW8Los6xsg/pKg17mPnAohq6jXdZXPM' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'RGe4t2zyqvZzUCUF/1hSYBCXE61nNbyU1n+pAgtqEF4vjWmGWofRYo9HSWSnhW1q' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'be7wBaSp0zWocqYvAt+PjMnlRn8TqkPRZpvbP8o9ucmXCj+6AQKCAQEA9QUEHvnj' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'znz4sBMrMG0iVEou2xilM352VZ9WPVshfTJpIVdQJ+PQaGELnEmlKFOwVjScI9bD' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '0WHXGgZ3r7U8gFJjOmGBBbCP0WFqSbxDJT2AwJ6QDblC8E3hkjOZ8C6VaU6PBVZk' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '8ejq7pgDhfjk66LGvUEIKYmOQxkbSnAK35nbEJP2Z6EQiqU+Q5OLcyqa3wZO2C3O' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'kiCvSjS6fethJb+YWCNqOD7pu9wxMJN2cYtE7Us7aLFutw+NOCn6DQ4kBdClyu9I' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'tESTLZZvRLiLYRFtw+q8i0VyiCw0d0K2QBHFwieJcSiGRD73hN3xCfLEX2HyL/41' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '9AFGj8Ijca4DOQKCAQEAyp/8GGVBh0k4RPqiGt6PCj3Jxcn5u1xMkJ4kB+MCOHP1' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'EAlOi7VserIWs/1UQFAajm6W1RDdrz7G/6ot6Rqb7P5tr2Y7t/5xtWL1YPpEZeTp' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'WBZmrP99hJU8K67h4ESJCqDcDhRZtCZedjGpQuRl3hRK5befmKYGEJ6e/oF/0WEQ' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'Fe9P7ULHH++n5rsB91DbNA8v7S4hSSIdWpXwV1JGVfPdSXGVfcVm1cQopLlV6XTZ' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '3CrGR/u+URTPjZgT+r3cMqjptHzrtkHU5d8kMtribQkmIyd7HMLPoMrH/QOqJYqu' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'mYSL0gzgOHGLRdUdAQy6IxBCLAhOCQkyI2MByPeNQQKCAQBftorqktFjuzvmhEZt' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'z2QGq0fsfI8kM3WEcw7cPvoxDv00cgg03PBvpeFENxyWSULsGfcYpO+vnlnJp9cf' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'Q1wUAJsUljwxfcxgjX5YuXs9U+400HwTcFhuyO2iEBhFU9032uFRw3MBcOw9MhLG' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'Rfke92JNUdcfasWw/mDDzkrhGBgUPMiXqLpufqh4+20RGwaOsscf+ZzlRnFTOo/T' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'WpyDg3m+jG8U87aYlSZ+BEzThATz8VyOxCksx51x4Cv255w4zU3GnXy4NsWLnGVw' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '4epIi+dmDg+DFCjuet4v7FaHZqnq80jkdGEmzbYhKBXdvgDqBbf2+YYYAFuREtSH' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'tuM5AoIBAAXE7F6dc3IwqYN9R2RQde4quDYDfDLTe/KaLhhzZDrLQm0EdtIPhlkv' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '/Ol/CwkRvs/TYkQKyOUWeoAJDmmWsl3bGLBnzsd8XSx29tmeBpiIHgS+Dopac+50' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'eVQdFJ1YFjbRQbK87Zjthr8Cxvj6m9Po7AECa27jO0T53zkL4uHJS7X0LGhrAFRu' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'dG9jX7j0+mjPDeRI7fWxHPjZUBCMbShBW0meDE2ac0Ue4rFd/Y46H4HfTen6xv50' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'Azza2abIBR8EJDNZYzS7Rx6MbfFsvgmwuv9BPoYhHdxMKcmQcyXCfxor5fdDGpdA' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '1GBWow7Gl/4rlla+ncowEtdjGEfqlIECggEAQjGkL64mz6lFchMT9aA8ODcAUTY4' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'z00PlBefR8zQVR4OCHzr0p1iTQVdkaK5++LMe4k586hE3BnE1gOGjdOQJpf2NS9E' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'IRnjLSRusPh0VbsxZivJqeW5Rf6johz16hdWpPrIE5w10ofCxTF1qaI2Savy+OAg' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'LT/9tqvn15u8/9rYDsZGV7u36S/N3lbRuHMAlrOR3pfBGINtgm63aQb1Gn4j3x+m' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'CZCPFtt5CxsIioAIJOxZT2YRnZo/EDv58u6ZKTo/GvBnsrZ0uXBfwRckl8fck/0E' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo 'ypmDJ/mssWjD7WvXN0tveEjmIw3SWMBSEd4JJnNx4z+jXlt/a2et0E0Xwg==' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '-----END RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa2"; \ +in-target /bin/sh -c "echo '-----BEGIN RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'MIIJKAIBAAKCAgEA/5zsrmRjNIl2s5xCZg+dLjGHqWgy3lbG6iHsY7RwnR7giaRp' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'O504h/f77NVMZp+1Rd8nnHPAPbjjVoSDfdimrkz7hKjbBoEivkey7th8GLNLb4vi' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '36fkBMuehHB/IBTfKygNo0vlno1nxAg3SAJtVIpsd2kYlQZ9vJu8NnbQGw7JPC1P' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '2brHTYf4ofdsIaCR9gH/sO3ZosiAfGEFrxAa/cVh38LNC/sEdByPxu8cdNhrmufr' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'wSu6zbQfzeJ3wP1Y/DY4HvmjmPhaN/dJBdtkfoxHWk1HIDR/nyEcIBZpnIryaTQE' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '8OdiVGdFMFUmQEadvqVIqYeLbGnHwmb6NPCyFhzTpddNiK3wmVUiwTZA5kbFszJF' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'AWfTAhViPz859YQADI+XQQ0NM3n7ECKmj04GPaaIpFB6rvlu/i15CDgMS6WmSu4l' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'HjBydprncQjTbPhlXh51Vl4qWdeF/h8nUrFtqVP8+iW4zMPMZE0BRF7KfaX4sZlY' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 's3G1i6UtetwzD720v21t50QDjvby721FY/3wSo+cHHX+GiCbyOoWwTcSTX60GMvg' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'x4MGQq4J6BUietzzWMYwICqT6RJFy+7E7dMgr3Hb/EwBNbnJMzllcv/wI4T68xRr' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'TyiiHSWqMi/+rVViFyn0tH4WCu4fV6YowLeNvBWRaxVFgjtvC8oaPnwGWrkCAwEA' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'AQKCAgEAwpDTQ6dcMBhWhz7w97j43rmK1vNejQkmnf82bWpiseZX6c2A4IS7DBxB' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '4bM2VYNJuyaygw9EjHbYbPmvETLBJTmp1f+lwFy5cncnB1E3nKGVURH8nluwX8oS' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'HiN3UJcyjCoPv3W9EaP3EStj0OcwC0LWb0pLENyBBvjQGfD0VTQ7Dxg6iLP4ktZl' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '9ftcjngnwkchNq7Fk3fk/UfoyKmMsg/1gRpJc84dRLic5EMLuREnTyErvb0okv2B' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'm/i/SOJPQqOOsl05Hu4j1iffqJqn8v+aLG1YL3ZmklzkiLQmrabCADw9apXlrfNx' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'oemelRxrZDtxhMGM6ffWuu4hk/yGwHLAQ9YvpaFaoyMUx5SavfpiLKnXd34z/DSE' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'zt3/+91X3BFUsmMVouUZts9V2qLl3O7Qc+jHubH92zJRpsIHqdaQ7g3Kci0OGqQS' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'py7soLi6nNRFuJVXs+fcljSblCVkAhP8NXoTpsfZ7AMR2Up/g/ffIfpQNbeilo+t' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'xdK9FqvVgdDUi2tdihAfqr0BcTKnv3v1baLePbGUUzAgw10EUD+PcUAP/h3VG8CI' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'F053DdIpttpQBIvJzZQPBT7iGYqqIOkxjHGZX79A/7V2TWCP5RVa7fgUUhUCsByX' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'lvjXao3A0bRA+DgLyUsjbo5dfkEcYoZ1ImC/H059Cf42/Sku+SUCggEBAP/jIDi6' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'tEeX0209/DJ+xHQ6fgvqd1wG8oh/5eZTA0dHUcLc5wufLH3K4Bhlc/+D3d7WzU63' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'p+Wc9KwtSZKEZGC8blDgvO7wfNp2lH9OBHQ62L18vYmoPFP8ETM/1KWve2X7Wqyp' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'NZ9yyEA+NnAOuByZPBtGTuCdb8TS9TwKBW7y740w8R2DDL7O9kOtIAfsDdlo3RiH' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'elpMaG0plT83zsfNDPfDIQPHJSJ4l+H1zv7DzvuA8geVrCB45LPVc/T1O6JPPLlE' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '5d+MRI8RCZICmwDD6cPxYliQqUOQygn5+Ao07LQrtwGR6+PdvFIpH+v2QZ8RF0Rt' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'tvFZAemB19hk6H8CggEBAP+5xInESSs4zfbWfqFJomd9CylMdLMQ1xfALfLXcupc' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '2lgMHjigme+GYxNZf47HBJwvbpGAGKKAlY0S+z/slGzhlgxfiu8PCPdzyQiLY32L' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'WvMbSzoGLQOcU+khCqruPdFb8LfXvJDOnYnCCqbL/vmS+QdPicH7uVBIGfKP57g9' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'iVUaU2FdLdv8KAXMrkAay7yQZu9V4/4c+omKaa3ipebMml3wfVX0dHbh07Ri5cy6' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'zMbrEF+L7i6tCH68LSYK1joQKlg/1phTkaDnDc6QPnk4/Bw1FhIdm/n+lHrdmhA9' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'qtowxfnAqh4RApiv/qch0XkyfTMDA40lj1Ary26aYMcCggEAeCX5FynzRDpxt7WH' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'GV6Ud86PKKEq8jcA4j7Lf94yh+Fg7pIymi5fAaGkn0/jq3ILV3qcY/2wBAwyhjWt' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'efJX/2P6mFct3zNkLF/JUg0b4kdPRYmwpVYtHXIZ0WqDOlivJC9lX/UDjJ6kkCWm' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'Ae+nWyZIJrZYivbhaBV1uH8sFfBTsoPscuL5tQ4Qa656f73Csvad+cqDFKsTzU3d' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'GhXmLcKF+D/S3KdBNHJTPnHgg5cFNOpSumT4sTaSjC4JiFctbQSvin5jQRfniRWC' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '3OAET9Oti6dnehZSo7r0YsLQSFqZWe+8uiv+CrwulJViu7ShE0M/HY42fBRC5ZVl' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '9+FJmQKCAQBCUYbqw4DGOMERVqcYZOQ9Omx+lVleZuuhOTGxXLZsmQ/27Y2Y2e2R' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '9KQVDIzMFkjXyGVATpwU6IvgPh/ygAQuCILFSrHZNWj544krMhrnIBDCIz3rGlbq' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'LMyGFQ+TLJ3Tgah3xPceBrdMVoo0n4rMZpU2lCYBrKpua4RvJ2rMmQjYjS86fNO7' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'zTUD7AT0kv5rNHe9ceTirdk7ei3V7oVfyYfu/MNEW1Uoz3/7s/oskfUxURy56qwm' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'ZrFhTKPYzc6o2DBjGosojeOieslV3IqXHXQkTJAgupUMzDztcDLYK2X3l9Z/4rs7' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'eOXXeyzrYxXT/IgDhrCRFkCIZhMn59lZAoIBAG0X8H2JXNoB3FczGAC21CxMnvGE' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'sFeiRuaiRhA8LNWNEEwOZm2C8lmAFtjG2yf8vEZuOYB0apxkOVzvwZDA5xZyLSAT' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'se/mWLFft541LPh1xQ0BjU9S1Q+5GCnWlP4wnBc1hF3A27vTmYe1DvrygCjGx8HJ' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'T93cBA5uGSmVH+dWxE+aNOVqeb1kKUNzHnucdbykv/5Hmo4n5n8qtYVRITB64FnQ' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo 'leT9Q08mXv6NmeZtlaCaO8HbtL5IbiVt2kxuys3lmy/MTcDs3VvSCAG5Vl9GJmqe' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '//Ld6aBtceUCLYxtjPvDXdwRKQcthIOiakVP2pMdyBIZeu860uNX16rfSI8=' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target /bin/sh -c "echo '-----END RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa3"; \ +in-target chmod 640 /home/vagrant/.ssh/id_rsa.pub; \ +in-target chmod 600 /home/vagrant/.ssh/id_rsa; \ +n-target chmod 640 /home/vagrant/.ssh/id_rsa2.pub; \ +in-target chmod 600 /home/vagrant/.ssh/id_rsa2; \ +n-target chmod 640 /home/vagrant/.ssh/id_rsa3.pub; \ +in-target chmod 600 /home/vagrant/.ssh/id_rsa3; \ +in-target chown -R vagrant:vagrant /home/vagrant/; \ +in-target chmod -R go-rwx /home/vagrant/.ssh/authorized_keys; \ +in-target cp -r /home/vagrant/.ssh /root/; \ +in-target chown -R root:root /root/.ssh/; \ +in-target sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config; \ +in-target rm /etc/udev/rules.d/70-persistent-net.rules; \ +in-target /bin/sh -c "echo '#!/bin/bash' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'get_ip=\$(sudo ifconfig | grep -E -o \"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\" | head -n1)' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"echo \\\"\$get_ip \$1\\\" >> /etc/hosts\"' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"sudo hostname \$1;' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"echo \\\"\$1\\\" > /etc/hostname\"' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"sudo sed -i \"s/127.0.1.1.*$//g\" /etc/hosts' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo hostnamectl set-hostname \$1' >> /home/vagrant/change_hostname.sh"; \ +in-target cp /home/vagrant/change_hostname.sh /root/change_hostname.sh; \ +in-target chmod 775 /home/vagrant/change_hostname.sh /root/change_hostname.sh; \ +in-target chown vagrant:vagrant /home/vagrant/change_hostname.sh; \ +in-target chown root:root /root/change_hostname.sh; \ +in-target /bin/sh -c "pip install bokeh python-vagrant pdfkit"; \ +/bin/sh -c "rm -f /target/etc/resolv.conf || true"; \ +/bin/sh -c "cp /etc/resolv.conf /target/etc/resolv.conf || true"; \ +chroot /target /bin/sh -c "vagrant plugin install vagrant-vsphere"; \ +chroot /target /bin/sh -c "vagrant plugin install vagrant-openstack-provider"; \ +in-target /bin/sh -c "dpkg-reconfigure locales"; \ +chroot /target ssh-agent bash -c "cd /home/vagrant; ssh-add /home/vagrant/.ssh/id_rsa3; git clone git@github.com:baderas/TSDBBench.git"; \ +chroot /target ssh-agent bash -c "cd /home/vagrant; ssh-add /home/vagrant/.ssh/id_rsa2; git clone git@github.com:baderas/YCSB-TS.git"; \ +chroot /target /bin/sh -c "cd /home/vagrant/TSDBBench; vagrant box add --name dummy dummy.box"; \ +in-target /bin/sh -c "echo 'RedirectMatch ^/$ /TSDBBench/' >> /var/www/html/.htaccess"; \ +in-target /bin/sh -c "awk '/AllowOverride None/{count++;if(count==3){sub(\"AllowOverride None\",\"AllowOverride All\")}}1' /etc/apache2/apache2.conf >> /etc/apache2/apache2.confnew"; \ +in-target /bin/sh -c "mv /etc/apache2/apache2.confnew /etc/apache2/apache2.conf"; \ +chroot /target /bin/sh -c "cd /var/www/html; ln -s /home/vagrant/TSDBBench ."; \ +in-target /bin/sh -c "rm /var/www/html/index.html"; \ +in-target apt-get clean; \ No newline at end of file diff --git a/preseed-vsphere.cfg b/preseed-vsphere.cfg new file mode 100644 index 0000000..41c423a --- /dev/null +++ b/preseed-vsphere.cfg @@ -0,0 +1,136 @@ +#### Contents of the preconfiguration file (for jessie) +### Localization +d-i debian-installer/language string en +d-i debian-installer/country string US +d-i debian-installer/locale string en_US.UTF-8 +d-i localechooser/supported-locales multiselect en_US.UTF-8 +d-i keyboard-configuration/xkb-keymap select de +d-i netcfg/choose_interface select auto +d-i netcfg/link_wait_timeout string 10 +d-i netcfg/dhcp_timeout string 60 +d-i netcfg/dhcpv6_timeout string 60 +d-i netcfg/get_hostname string Vagrant-VM +d-i netcfg/get_domain string localdomain +d-i hw-detect/load_firmware boolean true +d-i mirror/country string manual +d-i mirror/http/hostname string ftp.de.debian.org +d-i mirror/http/directory string /debian +d-i mirror/http/proxy string +d-i passwd/root-login boolean false +# Generierung von PW Hashes mit mkpasswd -m sha-512 +#d-i passwd/root-password-crypted password +d-i passwd/root-password password vagrant +d-i passwd/root-password-again password vagrant +d-i passwd/user-fullname string Vagrant +d-i passwd/username string vagrant +d-i passwd/user-password password vagrant +d-i passwd/user-password-again password vagrant +#d-i passwd/user-password-crypted password [MD5 hash] +d-i passwd/user-default-groups string vagrant cdrom floppy audio dip video plugdev netdev sudo +d-i clock-setup/utc boolean true +d-i time/zone string Etc/UTC +d-i clock-setup/ntp boolean true +d-i partman-auto/disk string /dev/sda +d-i partman-auto/method string regular +d-i partman-lvm/device_remove_lvm boolean true +d-i partman-md/device_remove_md boolean true +d-i partman-lvm/confirm boolean true +d-i partman-lvm/confirm_nooverwrite boolean true +#d-i partman-auto/choose_recipe select home +d-i partman-auto/expert_recipe string \ +boot-root :: \ +1000 10000 1000000000000 ext4 \ +$primary{ } $bootable{ } \ +method{ format } format{ } \ +use_filesystem{ } filesystem{ ext4 } \ +mountpoint{ / } \ +. \ +512 512 512 linux-swap \ +method{ swap } format{ } \ +. +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +d-i partman/mount_style select uuid +d-i base-installer/kernel/image string linux-image-amd64 +d-i apt-setup/non-free boolean true +d-i apt-setup/contrib boolean true +d-i apt-setup/services-select multiselect security, updates +d-i apt-setup/security_host string security.debian.org +#d-i apt-setup/multiarch string i386 +tasksel tasksel/first multiselect standard, ssh-server +d-i pkgsel/include string build-essential, ruby-highline, ruby-termios, sudo, ntp, linux-headers-amd64, dpkg, screen, htop, wget, curl, openjdk-7-jre, open-vm-tools, rsync, libpam-systemd, python2.7, fabric, resolvconf, linux-image-amd64, openssh-server +d-i pkgsel/upgrade select full-upgrade +popularity-contest popularity-contest/participate boolean false +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean true +d-i grub-installer/bootdev string /dev/sda +#d-i grub-installer/bootdev string default +#d-i debian-installer/add-kernel-opts string nousb +d-i finish-install/reboot_in_progress note +d-i cdrom-detect/eject boolean true +d-i debian-installer/exit/poweroff boolean true +d-i preseed/late_command string \ +in-target sed -i 's/^%sudo.*$/%sudo ALL=(ALL:ALL) NOPASSWD: ALL/g' /etc/sudoers; \ +in-target /bin/sh -c "echo 'Defaults env_keep += \"SSH_AUTH_SOCK DEBIAN_FRONTEND\"' >> /etc/sudoers"; \ +in-target /bin/sh -c "echo 'export DEBIAN_FRONTEND=noninteractive' >> /home/vagrant/.bashrc"; \ +in-target /bin/sh -c "echo 'export DEBIAN_FRONTEND=noninteractive' >> /root/.bashrc"; \ +in-target /bin/sh -c "echo 'blacklist ipv6' >> /etc/modprobe.d/blacklist.conf"; \ +in-target /bin/sh -c "echo 'net.ipv6.conf.all.disable_ipv6 = 1' >> /etc/sysctl.d/01-disable-ipv6.conf"; \ +in-target mkdir -p /home/vagrant/.ssh; \ +in-target /bin/sh -c "echo 'fs.file-max = 404358' >> /etc/sysctl.conf"; \ +in-target /bin/sh -c "echo 'fs.file-max = 404358' >> /etc/sysctl.d/99-sysctl.conf"; \ +in-target /bin/sh -c "echo '* - nofile 404358' >> /etc/security/limits.conf"; \ +in-target /bin/sh -c "echo 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key' >> /home/vagrant/.ssh/authorized_keys"; \ +in-target /bin/sh -c "echo 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key' >> /home/vagrant/.ssh/id_rsa.pub"; \ +in-target /bin/sh -c "echo 'Host *' >> /home/vagrant/.ssh/config"; \ +in-target /bin/sh -c "echo ' StrictHostKeyChecking no' >> /home/vagrant/.ssh/config"; \ +in-target /bin/sh -c "echo ' UserKnownHostsFile=/dev/null' >> /home/vagrant/.ssh/config"; \ +in-target /bin/sh -c "echo '-----BEGIN RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '+vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo 'NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s=' >> /home/vagrant/.ssh/id_rsa"; \ +in-target /bin/sh -c "echo '-----END RSA PRIVATE KEY-----' >> /home/vagrant/.ssh/id_rsa"; \ +in-target chmod 640 /home/vagrant/.ssh/id_rsa.pub; \ +in-target chmod 600 /home/vagrant/.ssh/id_rsa; \ +in-target chown -R vagrant:vagrant /home/vagrant/; \ +in-target chmod -R go-rwx /home/vagrant/.ssh/authorized_keys; \ +in-target cp -r /home/vagrant/.ssh /root/; \ +in-target chown -R root:root /root/.ssh/; \ +in-target sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config; \ +in-target rm /etc/udev/rules.d/70-persistent-net.rules; \ +in-target /bin/sh -c "echo '#!/bin/bash' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'get_ip=\$(sudo ifconfig | grep -E -o \"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\" | head -n1)' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"echo \\\"\$get_ip \$1\\\" >> /etc/hosts\"' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"sudo hostname \$1;' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"echo \\\"\$1\\\" > /etc/hostname\"' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo -s bash -c \"sudo sed -i \"s/127.0.1.1.*$//g\" /etc/hosts' >> /home/vagrant/change_hostname.sh"; \ +in-target /bin/sh -c "echo 'sudo hostnamectl set-hostname \$1' >> /home/vagrant/change_hostname.sh"; \ +in-target cp /home/vagrant/change_hostname.sh /root/change_hostname.sh; \ +in-target chmod 775 /home/vagrant/change_hostname.sh /root/change_hostname.sh; \ +in-target chown vagrant:vagrant /home/vagrant/change_hostname.sh; \ +in-target chown root:root /root/change_hostname.sh; \ +in-target apt-get clean; \ No newline at end of file diff --git a/template.html b/template.html new file mode 100644 index 0000000..a5e4afb --- /dev/null +++ b/template.html @@ -0,0 +1,59 @@ + + + + + {{ title if title else "Bokeh Plot" }} + {{ bokeh_js|indent(8)|safe }} + {{ bokeh_css|indent(8)|safe }} + {{ plot_script|indent(8)|safe }} + + +
+

{{ title if title else "Bokeh Plot" }}

+
+ {% if dbdesc and dbdesc != "" %} +
+ {{ dbdesc_name if dbdesc_name else "Database Description:"}} {{ dbdesc if dbdesc }} +
+ {% endif %} + {% if description and description != "" %} +
+ {{ description_name if description_name else "Workload Description:"}} {{ description if description }} +
+ {% endif %} + {% if errors and errors != "" %} +
+ {{ errors_name if errors_name else "Errors:"}} {{ errors if errors }} +
+ {% endif %} + {% if warnings and warnings != "" %} +
+ {{ warnings_name if warnings_name else "Warnings:"}} {{ warnings if warnings }} +
+ {% endif %} + {% if exceptions and exceptions != "" %} +
+ {{ exceptions_name if exceptions_name else "Exceptions:"}} {{ exceptions if exceptions }} +
+ {% endif %} +
+ {{ plot_div | safe }} +
+
+
+
+

{{ results_table_name }}

+ + {{ results_table }} +
+
+
+

{{ block_results_table_name }}

+ + {{ block_results_table }} +
+
+
+
+ + diff --git a/template_multi.html b/template_multi.html new file mode 100644 index 0000000..3aa7b56 --- /dev/null +++ b/template_multi.html @@ -0,0 +1,62 @@ + + + + + {{ title if title else "Bokeh Plot" }} + {{ bokeh_js|indent(8)|safe }} + {{ bokeh_css|indent(8)|safe }} + {{ plot_script|indent(8)|safe }} + + +
+

{{ title if title else "Bokeh Plot" }}

+
+ {% if dbdesc and dbdesc != "" %} +
+ {{ dbdesc_name if dbdesc_name else "Database Descriptions:"}} + {{ dbdesc if dbdesc }} +
+ {% endif %} + {% if description and description != "" %} +
+ {{ description_name if description_name else "Description:"}} {{ description if description }} +
+ {% endif %} + {% if errors and errors != "" %} +
+ {{ errors if errors else "Errors?" }} +
+ {% endif %} + {% if warnings and warnings != "" %} +
+ {{ warnings if warnings else "Warnings?" }} +
+ {% endif %} + {% if exceptions and exceptions != "" %} +
+ {{ exceptions if exceptions else "Exceptions?" }} +
+ {% endif %} +
+ {{ plot_div | safe }} +
+
+
+ + + + + + +
+ {{ block_results_table }} +
+
+
+
+ {{ general_results_table }} +
+
+
+ + diff --git a/vagrant_files/basic/blueflood.rb b/vagrant_files/basic/blueflood.rb new file mode 100644 index 0000000..9bf78f4 --- /dev/null +++ b/vagrant_files/basic/blueflood.rb @@ -0,0 +1,9 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing Blueflood + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"#{$links_blueflood}\"" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install openjdk-7-jre:amd64 " + config.vm.provision "shell", privileged: false, inline: "cp /vagrant/files/{blueflood-log4j.properties,blueflood.conf} /home/vagrant/" + config.vm.provision "shell", inline: "cp /vagrant/files/blueflood.service /etc/systemd/system" + config.vm.provision "shell", inline: "chown root:root /etc/systemd/system/blueflood.service" + config.vm.provision "shell", inline: "systemctl daemon-reload" +end diff --git a/vagrant_files/basic/cassandra.rb b/vagrant_files/basic/cassandra.rb new file mode 100644 index 0000000..0aa48cf --- /dev/null +++ b/vagrant_files/basic/cassandra.rb @@ -0,0 +1,10 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing Cassandra + config.vm.provision "shell", inline: "echo \"deb http://www.apache.org/dist/cassandra/debian 21x main\" >> /etc/apt/sources.list" + config.vm.provision "shell", inline: "echo \"deb-src http://www.apache.org/dist/cassandra/debian 21x main\" >> /etc/apt/sources.list" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y update" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install cassandra" + config.vm.provision "shell", inline: "systemctl stop cassandra.service" + config.vm.provision "shell", inline: "if [ $(ps ax | grep \"cassandra\" | grep -v \"grep\" | wc -l) -ne 0 ]; then for pid in $(ps ax | grep \"cassandra\" | grep -v \"grep\" | grep -Eo \"^[[:blank:]]*[0-9]{1,7}\" | sed \"s:[[:blank:]]::g\"); do echo \"Test\"; kill -9 $pid; done; fi" + config.vm.provision "shell", inline: "rm -rf /var/lib/cassandra/*" +end \ No newline at end of file diff --git a/vagrant_files/basic/change_hostname.rb b/vagrant_files/basic/change_hostname.rb new file mode 100644 index 0000000..effea39 --- /dev/null +++ b/vagrant_files/basic/change_hostname.rb @@ -0,0 +1,3 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.provision "shell", inline: "/root/change_hostname.sh #{HOSTNAME}" +end \ No newline at end of file diff --git a/vagrant_files/basic/copy_files.rb b/vagrant_files/basic/copy_files.rb new file mode 100644 index 0000000..b026796 --- /dev/null +++ b/vagrant_files/basic/copy_files.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.provision "shell", privileged: false, inline: "if [ -d /vagrant/files ]; then cp -r /vagrant/files ~/; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d ~/files ]; then chmod +x -f ~/files/*.sh; exit 0; fi" +end \ No newline at end of file diff --git a/vagrant_files/basic/druid.rb b/vagrant_files/basic/druid.rb new file mode 100644 index 0000000..8fc267a --- /dev/null +++ b/vagrant_files/basic/druid.rb @@ -0,0 +1,13 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing Druid + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"http://static.druid.io/artifacts/releases/druid-0.8.1-bin.tar.gz\"" + config.vm.provision "shell", privileged: false, inline: "tar -xvzf druid-0.8.1-bin.tar.gz" + config.vm.provision "shell", privileged: false, inline: "rm druid-0.8.1-bin.tar.gz" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install openjdk-7-jre:amd64 libmysql-java" + config.vm.provision "shell", privileged: false, inline: "mkdir -p /tmp/druid/indexCache /tmp/persistent/zk_druid /tmp/persistent/task/ /tmp/druid/localStorage" + config.vm.provision "shell", inline: "if [ ! -d /var/lib/mysql ]; then mkdir -p /var/lib/mysql; fi" + config.vm.provision "shell", privileged: false, inline: "cp -r /vagrant/files/config /home/vagrant/" + config.vm.provision "shell", inline: "cp /vagrant/files/druid*.service /etc/systemd/system" + config.vm.provision "shell", inline: "chown root:root /etc/systemd/system/druid*.service" + config.vm.provision "shell", inline: "systemctl daemon-reload" +end diff --git a/vagrant_files/basic/druid_mysql.rb b/vagrant_files/basic/druid_mysql.rb new file mode 100644 index 0000000..a379c35 --- /dev/null +++ b/vagrant_files/basic/druid_mysql.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Setup Mysql for Druid + config.vm.provision "shell", privileged: false, inline: "mysql -u root --password='vagrant' -e \"create database if not exists druid default charset utf8 COLLATE utf8_general_ci;GRANT ALL PRIVILEGES ON druid.* TO druid@'%' IDENTIFIED BY 'diurd';FLUSH PRIVILEGES;\""; +end diff --git a/vagrant_files/basic/hadoop.rb b/vagrant_files/basic/hadoop.rb new file mode 100644 index 0000000..deab7fc --- /dev/null +++ b/vagrant_files/basic/hadoop.rb @@ -0,0 +1,6 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing Hadoop + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"http://ftp.fau.de/apache/hadoop/common/hadoop-2.7.1/hadoop-2.7.1.tar.gz\"" + config.vm.provision "shell", privileged: false, inline: "tar -xvzf hadoop-2.7.1.tar.gz" + config.vm.provision "shell", privileged: false, inline: "rm hadoop-2.7.1.tar.gz" +end \ No newline at end of file diff --git a/vagrant_files/basic/hadoop_cluster.rb b/vagrant_files/basic/hadoop_cluster.rb new file mode 100644 index 0000000..dbc4ffb --- /dev/null +++ b/vagrant_files/basic/hadoop_cluster.rb @@ -0,0 +1,6 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Setting up Hadoop Cloud + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|JAVA_HOME=\\${JAVA_HOME}|JAVA_HOME=$(readlink -f /usr/bin/java | sed 's:bin/java::')|g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/hadoop-env.sh" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s||\\n \\n fs.defaultFS\\n hdfs://vm0:54310\\n \\n \\n hadoop.tmp.dir\\n /home/vagrant/hadoop\\n |g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s||\\n \\n dfs.replication\\n 5\\n |g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/hdfs-site.xml" +end \ No newline at end of file diff --git a/vagrant_files/basic/hadoop_master.rb b/vagrant_files/basic/hadoop_master.rb new file mode 100644 index 0000000..8ea8669 --- /dev/null +++ b/vagrant_files/basic/hadoop_master.rb @@ -0,0 +1,6 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| +# config.vm.provision "shell", privileged: false, inline: "sed -i \"s||\\n \\n yarn.resourcemanager.resource-tracker.address\\n vm0:8025\\n \\n \\n yarn.resourcemanager.scheduler.address\\n vm0:8030\\n \\n \\n yarn.resourcemanager.address\\n vm0:8050\\n |g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml" + config.vm.provision "shell", privileged: false, inline: "echo -e 'vm0\\nvm1\\nvm2\\nvm3\\nvm4' >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves" + config.vm.provision "shell", privileged: false, inline: "echo -e 'vm0' >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters" + +end \ No newline at end of file diff --git a/vagrant_files/basic/hbase.rb b/vagrant_files/basic/hbase.rb new file mode 100644 index 0000000..0fa4df0 --- /dev/null +++ b/vagrant_files/basic/hbase.rb @@ -0,0 +1,8 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing HBase + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"http://ftp-stud.hs-esslingen.de/pub/Mirrors/ftp.apache.org/dist/hbase/1.1.2/hbase-1.1.2-bin.tar.gz\"" + config.vm.provision "shell", privileged: false, inline: "tar -xvzf hbase-1.1.2-bin.tar.gz" + config.vm.provision "shell", privileged: false, inline: "rm hbase-1.1.2-bin.tar.gz" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|# export JAVA_HOME=/usr/java/jdk1.6.0/|export JAVA_HOME=$(readlink -f /usr/bin/java | sed 's:bin/java::')|g\" /home/vagrant/hbase-1.1.2/conf/hbase-env.sh" + config.vm.provision "shell", inline: "mkdir /home/vagrant/zookeeper" +end \ No newline at end of file diff --git a/vagrant_files/basic/hbase_cluster.rb b/vagrant_files/basic/hbase_cluster.rb new file mode 100644 index 0000000..ffa01b2 --- /dev/null +++ b/vagrant_files/basic/hbase_cluster.rb @@ -0,0 +1,6 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Setup HBase Cloud + config.vm.provision "shell", privileged: false, inline: "sed -i \"s||\\n \\n hbase.rootdir\\n hdfs://vm0:54310/hbase\\n \\n \\n hbase.cluster.distributed\\n true\\n \\n \\n hbase.zookeeper.quorum\\n vm0,vm1,vm2,vm3,vm4\\n \\n \\n hbase.zookeeper.property.dataDir\\n /home/vagrant/zookeeper\\n |g\" /home/vagrant/hbase-1.1.2/conf/hbase-site.xml" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|localhost|vm1\\nvm2\\nvm3\\nvm4|\" /home/vagrant/hbase-1.1.2/conf/regionservers" + config.vm.provision "shell", privileged: false, inline: "echo -e \"vm1\\nvm2\" >> /home/vagrant/hbase-1.1.2/conf/backup-masters" +end \ No newline at end of file diff --git a/vagrant_files/basic/hbase_cluster_repl1.rb b/vagrant_files/basic/hbase_cluster_repl1.rb new file mode 100644 index 0000000..373538f --- /dev/null +++ b/vagrant_files/basic/hbase_cluster_repl1.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Setup Replication = 1 + config.vm.provision "shell", privileged: false, inline: "sed -i \"s||\\n \\n dfs.replication\\n 1\\n |g\" /home/vagrant/hbase-1.1.2/conf/hbase-site.xml" +end \ No newline at end of file diff --git a/vagrant_files/basic/hbase_cluster_repl2.rb b/vagrant_files/basic/hbase_cluster_repl2.rb new file mode 100644 index 0000000..40e1e58 --- /dev/null +++ b/vagrant_files/basic/hbase_cluster_repl2.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Setup Replication = 2 + config.vm.provision "shell", privileged: false, inline: "sed -i \"s||\\n \\n dfs.replication\\n 2\\n |g\" /home/vagrant/hbase-1.1.2/conf/hbase-site.xml" +end \ No newline at end of file diff --git a/vagrant_files/basic/hbase_cluster_repl5.rb b/vagrant_files/basic/hbase_cluster_repl5.rb new file mode 100644 index 0000000..209f022 --- /dev/null +++ b/vagrant_files/basic/hbase_cluster_repl5.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Setup Replication = 5 + config.vm.provision "shell", privileged: false, inline: "sed -i \"s||\\n \\n dfs.replication\\n 5\\n |g\" /home/vagrant/hbase-1.1.2/conf/hbase-site.xml" +end \ No newline at end of file diff --git a/vagrant_files/basic/hbase_lzo_build.rb b/vagrant_files/basic/hbase_lzo_build.rb new file mode 100644 index 0000000..9b0a44f --- /dev/null +++ b/vagrant_files/basic/hbase_lzo_build.rb @@ -0,0 +1,9 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install ant liblzo2-dev git openjdk-7-jdk" + config.vm.provision "shell", privileged: false, inline: "git clone git://github.com/cloudera/hadoop-lzo.git" + config.vm.provision "shell", privileged: false, inline: "sed -i 's| | \\n |' /home/vagrant/hadoop-lzo/build.xml" + config.vm.provision "shell", privileged: false, inline: "cd hadoop-lzo && JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 CFLAGS=-m64 CXXFLAGS=-m64 ant compile-native tar" + config.vm.provision "shell", privileged: false, inline: "mkdir -p /home/vagrant/hbase-1.1.2/lib/native" + config.vm.provision "shell", privileged: false, inline: "cp /home/vagrant/hadoop-lzo/build/hadoop-lzo-0.4.15/hadoop-lzo-0.4.15.jar /home/vagrant/hbase-1.1.2/lib" + config.vm.provision "shell", privileged: false, inline: "cp -a /home/vagrant/hadoop-lzo/build/hadoop-lzo-0.4.15/lib/native/* /home/vagrant/hbase-1.1.2/lib/native" +end \ No newline at end of file diff --git a/vagrant_files/basic/hbase_lzo_copy.rb b/vagrant_files/basic/hbase_lzo_copy.rb new file mode 100644 index 0000000..3f814ad --- /dev/null +++ b/vagrant_files/basic/hbase_lzo_copy.rb @@ -0,0 +1,5 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install liblzo2-2" + #config.vm.provision "shell", privileged: false, inline: "if [ -d /vagrant/files/lzo ]; then cp -r /vagrant/files/lzo/* /home/vagrant/hbase-1.1.2/lib/; chown -R vagrant:vagrant /home/vagrant/hbase-1.1.2/lib/; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d /vagrant/files/lzo -a -f /vagrant/files/lzo/hadoop-lzo-0.4.15.tar.gz ]; then tar -xvzf /vagrant/files/lzo/hadoop-lzo-0.4.15.tar.gz -C /home/vagrant/hbase-1.1.2/lib/; chown -R vagrant:vagrant /home/vagrant/hbase-1.1.2/lib/; fi" +end \ No newline at end of file diff --git a/vagrant_files/basic/hbase_solo.rb b/vagrant_files/basic/hbase_solo.rb new file mode 100644 index 0000000..30c5fd5 --- /dev/null +++ b/vagrant_files/basic/hbase_solo.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Setup HBase Solo + config.vm.provision "shell", privileged: false, inline: "sed -i \"s||\\n \\n hbase.rootdir\\n file:///home/vagrant/hbase-1.1.2\\n \\n \\n hbase.zookeeper.property.dataDir\\n /home/vagrant/zookeeper\\n |g\" /home/vagrant/hbase-1.1.2/conf/hbase-site.xml" +end \ No newline at end of file diff --git a/vagrant_files/basic/influxdb.rb b/vagrant_files/basic/influxdb.rb new file mode 100644 index 0000000..b3bd676 --- /dev/null +++ b/vagrant_files/basic/influxdb.rb @@ -0,0 +1,16 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing InfluxDB + # BUG in 0.9.4 (stable): https://github.com/influxdb/influxdb/issues/4170 -> use 0.9.5 (NIGHTLY) + #config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"http://influxdb.s3.amazonaws.com/influxdb_0.9.4.2_amd64.deb\"" + #config.vm.provision "shell", inline: "dpkg -i influxdb_0.9.4.2_amd64.deb" + #config.vm.provision "shell", privileged: false, inline: "rm influxdb_0.9.4.2_amd64.deb" + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"https://s3.amazonaws.com/influxdb/influxdb_nightly_amd64.deb\"" + # temporary fix for nightly, mkdir seems missing in postinst file in package (date: 2015-08-01) # + config.vm.provision "shell", inline: "mkdir /var/lib/influxdb" + config.vm.provision "shell", inline: "mkdir /var/log/influxdb" + config.vm.provision "shell", inline: "touch /etc/lsb-release" + ############################################################ + config.vm.provision "shell", inline: "dpkg -i influxdb_nightly_amd64.deb" + config.vm.provision "shell", privileged: false, inline: "rm influxdb_nightly_amd64.deb" + config.vm.provision "shell", inline: "systemctl stop influxdb.service" +end diff --git a/vagrant_files/basic/influxdb_cluster.rb b/vagrant_files/basic/influxdb_cluster.rb new file mode 100644 index 0000000..e505beb --- /dev/null +++ b/vagrant_files/basic/influxdb_cluster.rb @@ -0,0 +1,7 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Setup InfluxDB Cluster + config.vm.provision "shell", inline: "sed -i 's|hostname = \"localhost\"|hostname = \"#{HOSTNAME}\"|' /etc/influxdb/influxdb.conf" + if INFLUXDBHOSTNAMES != "" + config.vm.provision "shell", inline: "echo 'INFLUXD_OPTS=\"-join #{INFLUXDBHOSTNAMES}\"' >>/etc/default/influxdb" + end +end \ No newline at end of file diff --git a/vagrant_files/basic/kairosdb.rb b/vagrant_files/basic/kairosdb.rb new file mode 100644 index 0000000..b115300 --- /dev/null +++ b/vagrant_files/basic/kairosdb.rb @@ -0,0 +1,9 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing KairosDB + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"https://github.com/kairosdb/kairosdb/releases/download/v1.0.0/kairosdb_1.0.0-1_all.deb\"" + config.vm.provision "shell", inline: "dpkg -i kairosdb_1.0.0-1_all.deb" + config.vm.provision "shell", privileged: false, inline: "rm kairosdb_1.0.0-1_all.deb" + config.vm.provision "shell", inline: "systemctl stop kairosdb.service" + config.vm.provision "shell", inline: "sed -i \"s/kairosdb.service.datastore=org.kairosdb.datastore.h2.H2Module/#kairosdb.service.datastore=org.kairosdb.datastore.h2.H2Module/g\" /opt/kairosdb/conf/kairosdb.properties" + config.vm.provision "shell", inline: "sed -i \"s/#kairosdb.service.datastore=org.kairosdb.datastore.cassandra.CassandraModule/kairosdb.service.datastore=org.kairosdb.datastore.cassandra.CassandraModule/g\" /opt/kairosdb/conf/kairosdb.properties " +end \ No newline at end of file diff --git a/vagrant_files/basic/kairosdb_repl1.rb b/vagrant_files/basic/kairosdb_repl1.rb new file mode 100644 index 0000000..0d8c39c --- /dev/null +++ b/vagrant_files/basic/kairosdb_repl1.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # KairosDB/Cassandra Replication Factor = 1 + config.vm.provision "shell", inline: "sed -i \"s/kairosdb.datastore.cassandra.replication_factor=1/kairosdb.datastore.cassandra.replication_factor=1/g\" /opt/kairosdb/conf/kairosdb.properties" +end \ No newline at end of file diff --git a/vagrant_files/basic/kairosdb_repl2.rb b/vagrant_files/basic/kairosdb_repl2.rb new file mode 100644 index 0000000..710830e --- /dev/null +++ b/vagrant_files/basic/kairosdb_repl2.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # KairosDB/Cassandra Replication Factor = 2 + config.vm.provision "shell", inline: "sed -i \"s/kairosdb.datastore.cassandra.replication_factor=1/kairosdb.datastore.cassandra.replication_factor=2/g\" /opt/kairosdb/conf/kairosdb.properties" +end \ No newline at end of file diff --git a/vagrant_files/basic/kairosdb_repl5.rb b/vagrant_files/basic/kairosdb_repl5.rb new file mode 100644 index 0000000..7c57343 --- /dev/null +++ b/vagrant_files/basic/kairosdb_repl5.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # KairosDB/Cassandra Replication Factor = 5 + config.vm.provision "shell", inline: "sed -i \"s/kairosdb.datastore.cassandra.replication_factor=1/kairosdb.datastore.cassandra.replication_factor=5/g\" /opt/kairosdb/conf/kairosdb.properties" +end \ No newline at end of file diff --git a/vagrant_files/basic/monetdb.rb b/vagrant_files/basic/monetdb.rb new file mode 100644 index 0000000..44cc3e7 --- /dev/null +++ b/vagrant_files/basic/monetdb.rb @@ -0,0 +1,10 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing MonetDB + config.vm.provision "shell", inline: "echo \"deb http://dev.monetdb.org/downloads/deb/ jessie monetdb\" >> /etc/apt/sources.list" + config.vm.provision "shell", inline: "echo \"deb-src http://dev.monetdb.org/downloads/deb/ jessie monetdb\" >> /etc/apt/sources.list" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y update" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install monetdb5-sql monetdb-client" + config.vm.provision "shell", inline: "/etc/init.d/monetdb5-sql stop" + config.vm.provision "shell", privileged: false, inline: "echo -e \"user=monetdb\npassword=monetdb\nlanguage=sql\n\" > /home/vagrant/.monetdb" + config.vm.provision "shell", inline: "echo -e \"user=monetdb\npassword=monetdb\nlanguage=sql\n\" > /root/.monetdb" +end \ No newline at end of file diff --git a/vagrant_files/basic/mysql.rb b/vagrant_files/basic/mysql.rb new file mode 100644 index 0000000..1a1a848 --- /dev/null +++ b/vagrant_files/basic/mysql.rb @@ -0,0 +1,8 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing MySQL + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install mysql-server libmysql-java" + config.vm.provision "shell", inline: "mysqladmin -u root password vagrant" + config.vm.provision "shell", inline: "sed -i \"s/bind-address[[:space:]]*\= 127\.0\.0\.1/bind-address \= \*/g\" /etc/mysql/my.cnf" + config.vm.provision "shell", privileged: false, inline: "mysql -u root --password='vagrant' -e \"GRANT ALL ON *.* to root@'%' IDENTIFIED BY 'vagrant'\""; + config.vm.provision "shell", inline: "systemctl restart mysql.service" +end diff --git a/vagrant_files/basic/newts.rb b/vagrant_files/basic/newts.rb new file mode 100644 index 0000000..8a5501b --- /dev/null +++ b/vagrant_files/basic/newts.rb @@ -0,0 +1,18 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing NewTS + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"https://github.com/OpenNMS/newts/releases/download/1.3.1/newts-1.3.1-bin.tar.gz\"" + config.vm.provision "shell", privileged: false, inline: "tar -xvzf newts-1.3.1-bin.tar.gz" + config.vm.provision "shell", privileged: false, inline: "rm newts-1.3.1-bin.tar.gz" + config.vm.provision "shell", inline: "mkdir /var/log/newts" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|# appenders:|appenders:|\" /home/vagrant/newts-1.3.1/etc/config.yaml" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|# - type: file| - type: file|\" /home/vagrant/newts-1.3.1/etc/config.yaml" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|# currentLogFilename: /path/to/newts.log| currentLogFilename: /var/log/newts/newts.log|\" /home/vagrant/newts-1.3.1/etc/config.yaml" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|# threshold: ALL| threshold: ALL|\" /home/vagrant/newts-1.3.1/etc/config.yaml" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|# archive: true| archive: true|\" /home/vagrant/newts-1.3.1/etc/config.yaml" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|# archivedLogFilenamePattern: /path/to/newts-%d.log| archivedLogFilenamePattern: /var/log/newts/newts-%d.log|\" /home/vagrant/newts-1.3.1/etc/config.yaml" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|# archivedFileCount: 5| archivedFileCount: 5|\" /home/vagrant/newts-1.3.1/etc/config.yaml" + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|# timeZone: UTC| timeZone: UTC|\" /home/vagrant/newts-1.3.1/etc/config.yaml" + config.vm.provision "shell", inline: "cp /vagrant/files/newts.service /etc/systemd/system/" + config.vm.provision "shell", inline: "chown root:root /etc/systemd/system/newts.service" + config.vm.provision "shell", inline: "systemctl daemon-reload" +end diff --git a/vagrant_files/basic/opentsdb.rb b/vagrant_files/basic/opentsdb.rb new file mode 100644 index 0000000..4448b50 --- /dev/null +++ b/vagrant_files/basic/opentsdb.rb @@ -0,0 +1,7 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Installing Opentsdb + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"https://github.com/OpenTSDB/opentsdb/releases/download/v2.2.0RC1/opentsdb-2.2.0RC1_all.deb\"" + config.vm.provision "shell", inline: "dpkg -i opentsdb-2.2.0RC1_all.deb" + config.vm.provision "shell", privileged: false, inline: "rm opentsdb-2.2.0RC1_all.deb" + config.vm.provision "shell", inline: "systemctl stop opentsdb.service" +end diff --git a/vagrant_files/basic/opentsdb_cluster.rb b/vagrant_files/basic/opentsdb_cluster.rb new file mode 100644 index 0000000..0571d1c --- /dev/null +++ b/vagrant_files/basic/opentsdb_cluster.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # Cluster Setting Opentsdb + config.vm.provision "shell", privileged: false, inline: "sed -i \"s|#tsd.storage.hbase.zk_quorum = localhost|tsd.storage.hbase.zk_quorum = vm0,vm1,vm2,vm3,vm4|\" /etc/opentsdb/opentsdb.conf" +end diff --git a/vagrant_files/basic/sleep_5.rb b/vagrant_files/basic/sleep_5.rb new file mode 100644 index 0000000..0ec11f8 --- /dev/null +++ b/vagrant_files/basic/sleep_5.rb @@ -0,0 +1,3 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.provision "shell", privileged: false, inline: "sleep 5" +end \ No newline at end of file diff --git a/vagrant_files/basic/update.rb b/vagrant_files/basic/update.rb new file mode 100644 index 0000000..51e6f93 --- /dev/null +++ b/vagrant_files/basic/update.rb @@ -0,0 +1,3 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y update" +end \ No newline at end of file diff --git a/vagrant_files/basic/zookeeper.rb b/vagrant_files/basic/zookeeper.rb new file mode 100644 index 0000000..2021494 --- /dev/null +++ b/vagrant_files/basic/zookeeper.rb @@ -0,0 +1,4 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install zookeeperd" + config.vm.provision "shell", inline: "systemctl stop zookeeper.service" +end \ No newline at end of file diff --git a/vagrant_files/blueflood_cl1_rf1/blueflood_cl1_rf1_0.vagrant b/vagrant_files/blueflood_cl1_rf1/blueflood_cl1_rf1_0.vagrant new file mode 100644 index 0000000..9bac995 --- /dev/null +++ b/vagrant_files/blueflood_cl1_rf1/blueflood_cl1_rf1_0.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with Cassandra on 1 VM + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/blueflood.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl1_rf1/files/blueflood-log4j.properties b/vagrant_files/blueflood_cl1_rf1/files/blueflood-log4j.properties new file mode 100644 index 0000000..8af05ea --- /dev/null +++ b/vagrant_files/blueflood_cl1_rf1/files/blueflood-log4j.properties @@ -0,0 +1,11 @@ +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %-20.20c{1}:%-3L - %m%n +log4j.logger.com.rackspacecloud.blueflood=WARN # Change to DEBUG for more output from Blueflood +log4j.logger.httpclient.wire.header=WARN +log4j.logger.httpclient.wire.content=WARN +log4j.logger.org.apache.http.client.protocol=WARN +log4j.logger.org.apache.http.wire=WARN +log4j.logger.org.apache.http.impl=WARN +log4j.logger.org.apache.http.headers=WARN +log4j.rootLogger=WARN, console diff --git a/vagrant_files/blueflood_cl1_rf1/files/blueflood.conf b/vagrant_files/blueflood_cl1_rf1/files/blueflood.conf new file mode 100644 index 0000000..fc6172b --- /dev/null +++ b/vagrant_files/blueflood_cl1_rf1/files/blueflood.conf @@ -0,0 +1,59 @@ +CASSANDRA_HOSTS=localhost:9160 +DEFAULT_CASSANDRA_PORT=9160 +# This number is only accurate if MAX_CASSANDRA_CONNECTIONS is evenly divisible by number of hosts +MAX_CASSANDRA_CONNECTIONS=70 + +HTTP_INGESTION_PORT=19000 +HTTP_INGESTION_HOST=localhost +HTTP_METRIC_DATA_QUERY_PORT=19001 +HTTP_QUERY_HOST=localhost + +ROLLUP_KEYSPACE=DATA +CLUSTER_NAME=Test Cluster + +INGESTION_MODULES=com.rackspacecloud.blueflood.service.HttpIngestionService +QUERY_MODULES=com.rackspacecloud.blueflood.service.HttpQueryService +DISCOVERY_MODULES= + +MAX_ROLLUP_THREADS=20 +# Maximum timeout waiting on exhausted connection pools in milliseconds. +# Maps directly to Astyanax's ConnectionPoolConfiguration.setMaxTimeoutWhenExhausted +MAX_TIMEOUT_WHEN_EXHAUSTED=2000 +SCHEDULE_POLL_PERIOD=60000 + +# Config refresh interval (If a new config is pushed out, we need to pick up the changes) +# time is in milliseconds +CONFIG_REFRESH_PERIOD=10000 + +# this is a special string, or a comma list of integers. e.g.: "1,2,3,4" +# valid shards are 0..127 +SHARDS=ALL + +# thread sleep times between shard push/pulls. +SHARD_PUSH_PERIOD=2000 +SHARD_PULL_PERIOD=20000 + +# blueflood uses zookeeper to acquire locks before working on shards +#ZOOKEEPER_CLUSTER=127.0.0.1:22181 +ZOOKEEPER_CLUSTER=NONE + +# 20 min +SHARD_LOCK_HOLD_PERIOD_MS=1200000 +# 1 min +SHARD_LOCK_DISINTERESTED_PERIOD_MS=60000 +# 2 min +SHARD_LOCK_SCAVENGE_INTERVAL_MS=120000 +MAX_ZK_LOCKS_TO_ACQUIRE_PER_CYCLE=1 + +INTERNAL_API_CLUSTER=127.0.0.1:50020,127.0.0.1:50020 + +GRAPHITE_HOST= +GRAPHITE_PORT=2003 +GRAPHITE_PREFIX=unconfiguredNode.metrics. + +INGEST_MODE=true +ROLLUP_MODE=true +QUERY_MODE=true + +# set <= 0 to not retry +CASSANDRA_MAX_RETRIES=5 diff --git a/vagrant_files/blueflood_cl1_rf1/files/blueflood.service b/vagrant_files/blueflood_cl1_rf1/files/blueflood.service new file mode 100644 index 0000000..4e4f2c6 --- /dev/null +++ b/vagrant_files/blueflood_cl1_rf1/files/blueflood.service @@ -0,0 +1,13 @@ +[Unit] +Description=Blueflood + +[Service] +ExecStart=/usr/bin/java -cp /home/vagrant/blueflood-all-2.0.0-SNAPSHOT-jar-with-dependencies.jar \ +-Dblueflood.config=file:///home/vagrant/blueflood.conf \ +-Dlog4j.configuration=file:///home/vagrant/blueflood-log4j.properties \ +-Xms4G \ +-Xmx4G \ +com.rackspacecloud.blueflood.service.BluefloodServiceStarter + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/blueflood_cl1_rf1/files/blueflood_cassandra.cli b/vagrant_files/blueflood_cl1_rf1/files/blueflood_cassandra.cli new file mode 100644 index 0000000..160dc70 --- /dev/null +++ b/vagrant_files/blueflood_cl1_rf1/files/blueflood_cassandra.cli @@ -0,0 +1,30 @@ +CREATE KEYSPACE DATA + WITH placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' + AND strategy_options = {replication_factor:1}; +USE DATA; + +CREATE COLUMN FAMILY metrics_locator WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='LongType' AND default_validation_class='UTF8Type'; +CREATE COLUMN FAMILY metrics_discovery WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='UTF8Type' AND default_validation_class='UTF8Type'; +CREATE COLUMN FAMILY metrics_state WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='LongType' AND default_validation_class='LongType'; +CREATE COLUMN FAMILY metrics_metadata WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_string WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='UTF8Type'; + +CREATE COLUMN FAMILY metrics_full WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_5m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_20m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_60m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_240m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_1440m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; + +CREATE COLUMN FAMILY metrics_preaggregated_full WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_5m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_20m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_60m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_240m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_1440m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; + +CREATE COLUMN FAMILY metrics_histogram_5m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_20m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_60m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_240m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_1440m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_0.vagrant b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_0.vagrant new file mode 100644 index 0000000..2d6829f --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_0.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/blueflood.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_1.vagrant b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_1.vagrant new file mode 100644 index 0000000..4f6b64c --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_1.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_2.vagrant b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_2.vagrant new file mode 100644 index 0000000..eb31f48 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_2.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_3.vagrant b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_3.vagrant new file mode 100644 index 0000000..a883f8e --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_3.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_4.vagrant b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_4.vagrant new file mode 100644 index 0000000..1a2f106 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf1/blueflood_cl5_rf1_4.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf1/files/blueflood-log4j.properties b/vagrant_files/blueflood_cl5_rf1/files/blueflood-log4j.properties new file mode 100644 index 0000000..8af05ea --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf1/files/blueflood-log4j.properties @@ -0,0 +1,11 @@ +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %-20.20c{1}:%-3L - %m%n +log4j.logger.com.rackspacecloud.blueflood=WARN # Change to DEBUG for more output from Blueflood +log4j.logger.httpclient.wire.header=WARN +log4j.logger.httpclient.wire.content=WARN +log4j.logger.org.apache.http.client.protocol=WARN +log4j.logger.org.apache.http.wire=WARN +log4j.logger.org.apache.http.impl=WARN +log4j.logger.org.apache.http.headers=WARN +log4j.rootLogger=WARN, console diff --git a/vagrant_files/blueflood_cl5_rf1/files/blueflood.conf b/vagrant_files/blueflood_cl5_rf1/files/blueflood.conf new file mode 100644 index 0000000..fc6172b --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf1/files/blueflood.conf @@ -0,0 +1,59 @@ +CASSANDRA_HOSTS=localhost:9160 +DEFAULT_CASSANDRA_PORT=9160 +# This number is only accurate if MAX_CASSANDRA_CONNECTIONS is evenly divisible by number of hosts +MAX_CASSANDRA_CONNECTIONS=70 + +HTTP_INGESTION_PORT=19000 +HTTP_INGESTION_HOST=localhost +HTTP_METRIC_DATA_QUERY_PORT=19001 +HTTP_QUERY_HOST=localhost + +ROLLUP_KEYSPACE=DATA +CLUSTER_NAME=Test Cluster + +INGESTION_MODULES=com.rackspacecloud.blueflood.service.HttpIngestionService +QUERY_MODULES=com.rackspacecloud.blueflood.service.HttpQueryService +DISCOVERY_MODULES= + +MAX_ROLLUP_THREADS=20 +# Maximum timeout waiting on exhausted connection pools in milliseconds. +# Maps directly to Astyanax's ConnectionPoolConfiguration.setMaxTimeoutWhenExhausted +MAX_TIMEOUT_WHEN_EXHAUSTED=2000 +SCHEDULE_POLL_PERIOD=60000 + +# Config refresh interval (If a new config is pushed out, we need to pick up the changes) +# time is in milliseconds +CONFIG_REFRESH_PERIOD=10000 + +# this is a special string, or a comma list of integers. e.g.: "1,2,3,4" +# valid shards are 0..127 +SHARDS=ALL + +# thread sleep times between shard push/pulls. +SHARD_PUSH_PERIOD=2000 +SHARD_PULL_PERIOD=20000 + +# blueflood uses zookeeper to acquire locks before working on shards +#ZOOKEEPER_CLUSTER=127.0.0.1:22181 +ZOOKEEPER_CLUSTER=NONE + +# 20 min +SHARD_LOCK_HOLD_PERIOD_MS=1200000 +# 1 min +SHARD_LOCK_DISINTERESTED_PERIOD_MS=60000 +# 2 min +SHARD_LOCK_SCAVENGE_INTERVAL_MS=120000 +MAX_ZK_LOCKS_TO_ACQUIRE_PER_CYCLE=1 + +INTERNAL_API_CLUSTER=127.0.0.1:50020,127.0.0.1:50020 + +GRAPHITE_HOST= +GRAPHITE_PORT=2003 +GRAPHITE_PREFIX=unconfiguredNode.metrics. + +INGEST_MODE=true +ROLLUP_MODE=true +QUERY_MODE=true + +# set <= 0 to not retry +CASSANDRA_MAX_RETRIES=5 diff --git a/vagrant_files/blueflood_cl5_rf1/files/blueflood.service b/vagrant_files/blueflood_cl5_rf1/files/blueflood.service new file mode 100644 index 0000000..4e4f2c6 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf1/files/blueflood.service @@ -0,0 +1,13 @@ +[Unit] +Description=Blueflood + +[Service] +ExecStart=/usr/bin/java -cp /home/vagrant/blueflood-all-2.0.0-SNAPSHOT-jar-with-dependencies.jar \ +-Dblueflood.config=file:///home/vagrant/blueflood.conf \ +-Dlog4j.configuration=file:///home/vagrant/blueflood-log4j.properties \ +-Xms4G \ +-Xmx4G \ +com.rackspacecloud.blueflood.service.BluefloodServiceStarter + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/blueflood_cl5_rf1/files/blueflood_cassandra.cli b/vagrant_files/blueflood_cl5_rf1/files/blueflood_cassandra.cli new file mode 100644 index 0000000..160dc70 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf1/files/blueflood_cassandra.cli @@ -0,0 +1,30 @@ +CREATE KEYSPACE DATA + WITH placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' + AND strategy_options = {replication_factor:1}; +USE DATA; + +CREATE COLUMN FAMILY metrics_locator WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='LongType' AND default_validation_class='UTF8Type'; +CREATE COLUMN FAMILY metrics_discovery WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='UTF8Type' AND default_validation_class='UTF8Type'; +CREATE COLUMN FAMILY metrics_state WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='LongType' AND default_validation_class='LongType'; +CREATE COLUMN FAMILY metrics_metadata WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_string WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='UTF8Type'; + +CREATE COLUMN FAMILY metrics_full WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_5m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_20m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_60m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_240m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_1440m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; + +CREATE COLUMN FAMILY metrics_preaggregated_full WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_5m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_20m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_60m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_240m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_1440m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; + +CREATE COLUMN FAMILY metrics_histogram_5m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_20m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_60m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_240m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_1440m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_0.vagrant b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_0.vagrant new file mode 100644 index 0000000..450a856 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_0.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/blueflood.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_1.vagrant b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_1.vagrant new file mode 100644 index 0000000..55f356a --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_1.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_2.vagrant b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_2.vagrant new file mode 100644 index 0000000..b890d38 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_2.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_3.vagrant b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_3.vagrant new file mode 100644 index 0000000..b8cd39c --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_3.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_4.vagrant b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_4.vagrant new file mode 100644 index 0000000..0954655 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf2/blueflood_cl5_rf2_4.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf2/files/blueflood-log4j.properties b/vagrant_files/blueflood_cl5_rf2/files/blueflood-log4j.properties new file mode 100644 index 0000000..8af05ea --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf2/files/blueflood-log4j.properties @@ -0,0 +1,11 @@ +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %-20.20c{1}:%-3L - %m%n +log4j.logger.com.rackspacecloud.blueflood=WARN # Change to DEBUG for more output from Blueflood +log4j.logger.httpclient.wire.header=WARN +log4j.logger.httpclient.wire.content=WARN +log4j.logger.org.apache.http.client.protocol=WARN +log4j.logger.org.apache.http.wire=WARN +log4j.logger.org.apache.http.impl=WARN +log4j.logger.org.apache.http.headers=WARN +log4j.rootLogger=WARN, console diff --git a/vagrant_files/blueflood_cl5_rf2/files/blueflood.conf b/vagrant_files/blueflood_cl5_rf2/files/blueflood.conf new file mode 100644 index 0000000..fc6172b --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf2/files/blueflood.conf @@ -0,0 +1,59 @@ +CASSANDRA_HOSTS=localhost:9160 +DEFAULT_CASSANDRA_PORT=9160 +# This number is only accurate if MAX_CASSANDRA_CONNECTIONS is evenly divisible by number of hosts +MAX_CASSANDRA_CONNECTIONS=70 + +HTTP_INGESTION_PORT=19000 +HTTP_INGESTION_HOST=localhost +HTTP_METRIC_DATA_QUERY_PORT=19001 +HTTP_QUERY_HOST=localhost + +ROLLUP_KEYSPACE=DATA +CLUSTER_NAME=Test Cluster + +INGESTION_MODULES=com.rackspacecloud.blueflood.service.HttpIngestionService +QUERY_MODULES=com.rackspacecloud.blueflood.service.HttpQueryService +DISCOVERY_MODULES= + +MAX_ROLLUP_THREADS=20 +# Maximum timeout waiting on exhausted connection pools in milliseconds. +# Maps directly to Astyanax's ConnectionPoolConfiguration.setMaxTimeoutWhenExhausted +MAX_TIMEOUT_WHEN_EXHAUSTED=2000 +SCHEDULE_POLL_PERIOD=60000 + +# Config refresh interval (If a new config is pushed out, we need to pick up the changes) +# time is in milliseconds +CONFIG_REFRESH_PERIOD=10000 + +# this is a special string, or a comma list of integers. e.g.: "1,2,3,4" +# valid shards are 0..127 +SHARDS=ALL + +# thread sleep times between shard push/pulls. +SHARD_PUSH_PERIOD=2000 +SHARD_PULL_PERIOD=20000 + +# blueflood uses zookeeper to acquire locks before working on shards +#ZOOKEEPER_CLUSTER=127.0.0.1:22181 +ZOOKEEPER_CLUSTER=NONE + +# 20 min +SHARD_LOCK_HOLD_PERIOD_MS=1200000 +# 1 min +SHARD_LOCK_DISINTERESTED_PERIOD_MS=60000 +# 2 min +SHARD_LOCK_SCAVENGE_INTERVAL_MS=120000 +MAX_ZK_LOCKS_TO_ACQUIRE_PER_CYCLE=1 + +INTERNAL_API_CLUSTER=127.0.0.1:50020,127.0.0.1:50020 + +GRAPHITE_HOST= +GRAPHITE_PORT=2003 +GRAPHITE_PREFIX=unconfiguredNode.metrics. + +INGEST_MODE=true +ROLLUP_MODE=true +QUERY_MODE=true + +# set <= 0 to not retry +CASSANDRA_MAX_RETRIES=5 diff --git a/vagrant_files/blueflood_cl5_rf2/files/blueflood.service b/vagrant_files/blueflood_cl5_rf2/files/blueflood.service new file mode 100644 index 0000000..4e4f2c6 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf2/files/blueflood.service @@ -0,0 +1,13 @@ +[Unit] +Description=Blueflood + +[Service] +ExecStart=/usr/bin/java -cp /home/vagrant/blueflood-all-2.0.0-SNAPSHOT-jar-with-dependencies.jar \ +-Dblueflood.config=file:///home/vagrant/blueflood.conf \ +-Dlog4j.configuration=file:///home/vagrant/blueflood-log4j.properties \ +-Xms4G \ +-Xmx4G \ +com.rackspacecloud.blueflood.service.BluefloodServiceStarter + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/blueflood_cl5_rf2/files/blueflood_cassandra.cli b/vagrant_files/blueflood_cl5_rf2/files/blueflood_cassandra.cli new file mode 100644 index 0000000..a11dd3f --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf2/files/blueflood_cassandra.cli @@ -0,0 +1,30 @@ +CREATE KEYSPACE DATA + WITH placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' + AND strategy_options = {replication_factor:2}; +USE DATA; + +CREATE COLUMN FAMILY metrics_locator WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='LongType' AND default_validation_class='UTF8Type'; +CREATE COLUMN FAMILY metrics_discovery WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='UTF8Type' AND default_validation_class='UTF8Type'; +CREATE COLUMN FAMILY metrics_state WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='LongType' AND default_validation_class='LongType'; +CREATE COLUMN FAMILY metrics_metadata WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_string WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='UTF8Type'; + +CREATE COLUMN FAMILY metrics_full WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_5m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_20m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_60m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_240m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_1440m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; + +CREATE COLUMN FAMILY metrics_preaggregated_full WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_5m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_20m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_60m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_240m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_1440m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; + +CREATE COLUMN FAMILY metrics_histogram_5m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_20m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_60m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_240m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_1440m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_0.vagrant b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_0.vagrant new file mode 100644 index 0000000..ccef741 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_0.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/blueflood.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_1.vagrant b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_1.vagrant new file mode 100644 index 0000000..e6c65ee --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_1.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_2.vagrant b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_2.vagrant new file mode 100644 index 0000000..451a17f --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_2.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_3.vagrant b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_3.vagrant new file mode 100644 index 0000000..8ae49ee --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_3.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_4.vagrant b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_4.vagrant new file mode 100644 index 0000000..ba52384 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf5/blueflood_cl5_rf5_4.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Blueflood with assandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/blueflood_cl5_rf5/files/blueflood-log4j.properties b/vagrant_files/blueflood_cl5_rf5/files/blueflood-log4j.properties new file mode 100644 index 0000000..8af05ea --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf5/files/blueflood-log4j.properties @@ -0,0 +1,11 @@ +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %-20.20c{1}:%-3L - %m%n +log4j.logger.com.rackspacecloud.blueflood=WARN # Change to DEBUG for more output from Blueflood +log4j.logger.httpclient.wire.header=WARN +log4j.logger.httpclient.wire.content=WARN +log4j.logger.org.apache.http.client.protocol=WARN +log4j.logger.org.apache.http.wire=WARN +log4j.logger.org.apache.http.impl=WARN +log4j.logger.org.apache.http.headers=WARN +log4j.rootLogger=WARN, console diff --git a/vagrant_files/blueflood_cl5_rf5/files/blueflood.conf b/vagrant_files/blueflood_cl5_rf5/files/blueflood.conf new file mode 100644 index 0000000..fc6172b --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf5/files/blueflood.conf @@ -0,0 +1,59 @@ +CASSANDRA_HOSTS=localhost:9160 +DEFAULT_CASSANDRA_PORT=9160 +# This number is only accurate if MAX_CASSANDRA_CONNECTIONS is evenly divisible by number of hosts +MAX_CASSANDRA_CONNECTIONS=70 + +HTTP_INGESTION_PORT=19000 +HTTP_INGESTION_HOST=localhost +HTTP_METRIC_DATA_QUERY_PORT=19001 +HTTP_QUERY_HOST=localhost + +ROLLUP_KEYSPACE=DATA +CLUSTER_NAME=Test Cluster + +INGESTION_MODULES=com.rackspacecloud.blueflood.service.HttpIngestionService +QUERY_MODULES=com.rackspacecloud.blueflood.service.HttpQueryService +DISCOVERY_MODULES= + +MAX_ROLLUP_THREADS=20 +# Maximum timeout waiting on exhausted connection pools in milliseconds. +# Maps directly to Astyanax's ConnectionPoolConfiguration.setMaxTimeoutWhenExhausted +MAX_TIMEOUT_WHEN_EXHAUSTED=2000 +SCHEDULE_POLL_PERIOD=60000 + +# Config refresh interval (If a new config is pushed out, we need to pick up the changes) +# time is in milliseconds +CONFIG_REFRESH_PERIOD=10000 + +# this is a special string, or a comma list of integers. e.g.: "1,2,3,4" +# valid shards are 0..127 +SHARDS=ALL + +# thread sleep times between shard push/pulls. +SHARD_PUSH_PERIOD=2000 +SHARD_PULL_PERIOD=20000 + +# blueflood uses zookeeper to acquire locks before working on shards +#ZOOKEEPER_CLUSTER=127.0.0.1:22181 +ZOOKEEPER_CLUSTER=NONE + +# 20 min +SHARD_LOCK_HOLD_PERIOD_MS=1200000 +# 1 min +SHARD_LOCK_DISINTERESTED_PERIOD_MS=60000 +# 2 min +SHARD_LOCK_SCAVENGE_INTERVAL_MS=120000 +MAX_ZK_LOCKS_TO_ACQUIRE_PER_CYCLE=1 + +INTERNAL_API_CLUSTER=127.0.0.1:50020,127.0.0.1:50020 + +GRAPHITE_HOST= +GRAPHITE_PORT=2003 +GRAPHITE_PREFIX=unconfiguredNode.metrics. + +INGEST_MODE=true +ROLLUP_MODE=true +QUERY_MODE=true + +# set <= 0 to not retry +CASSANDRA_MAX_RETRIES=5 diff --git a/vagrant_files/blueflood_cl5_rf5/files/blueflood.service b/vagrant_files/blueflood_cl5_rf5/files/blueflood.service new file mode 100644 index 0000000..4e4f2c6 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf5/files/blueflood.service @@ -0,0 +1,13 @@ +[Unit] +Description=Blueflood + +[Service] +ExecStart=/usr/bin/java -cp /home/vagrant/blueflood-all-2.0.0-SNAPSHOT-jar-with-dependencies.jar \ +-Dblueflood.config=file:///home/vagrant/blueflood.conf \ +-Dlog4j.configuration=file:///home/vagrant/blueflood-log4j.properties \ +-Xms4G \ +-Xmx4G \ +com.rackspacecloud.blueflood.service.BluefloodServiceStarter + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/blueflood_cl5_rf5/files/blueflood_cassandra.cli b/vagrant_files/blueflood_cl5_rf5/files/blueflood_cassandra.cli new file mode 100644 index 0000000..b93c4c5 --- /dev/null +++ b/vagrant_files/blueflood_cl5_rf5/files/blueflood_cassandra.cli @@ -0,0 +1,30 @@ +CREATE KEYSPACE DATA + WITH placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' + AND strategy_options = {replication_factor:5}; +USE DATA; + +CREATE COLUMN FAMILY metrics_locator WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='LongType' AND default_validation_class='UTF8Type'; +CREATE COLUMN FAMILY metrics_discovery WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='UTF8Type' AND default_validation_class='UTF8Type'; +CREATE COLUMN FAMILY metrics_state WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='LongType' AND default_validation_class='LongType'; +CREATE COLUMN FAMILY metrics_metadata WITH column_type='Standard' AND comparator='UTF8Type' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_string WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='UTF8Type'; + +CREATE COLUMN FAMILY metrics_full WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_5m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_20m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_60m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_240m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_1440m WITH column_type='Standard' AND comparator='LongType' AND key_validation_class='UTF8Type' AND default_validation_class='BytesType'; + +CREATE COLUMN FAMILY metrics_preaggregated_full WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_5m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_20m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_60m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_240m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_preaggregated_1440m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; + +CREATE COLUMN FAMILY metrics_histogram_5m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_20m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_60m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_240m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; +CREATE COLUMN FAMILY metrics_histogram_1440m WITH column_type='Standard' and comparator='LongType' and key_validation_class='UTF8Type' and default_validation_class='BytesType'; \ No newline at end of file diff --git a/vagrant_files/druid_cl1_rf1/druid_cl1_rf1_0.vagrant b/vagrant_files/druid_cl1_rf1/druid_cl1_rf1_0.vagrant new file mode 100644 index 0000000..c460f3d --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/druid_cl1_rf1_0.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 1 VM + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/mysql.rb' +load 'basic/druid_mysql.rb' +load 'basic/zookeeper.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl1_rf1/files/config/_common/common.runtime.properties b/vagrant_files/druid_cl1_rf1/files/config/_common/common.runtime.properties new file mode 100644 index 0000000..2cf49d6 --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/config/_common/common.runtime.properties @@ -0,0 +1,34 @@ +# Extensions +druid.extensions.coordinates=["io.druid.extensions:mysql-metadata-storage"] +druid.extensions.localRepository=extensions-repo + +# Zookeeper +druid.zk.service.host=localhost + +# Metadata Storage +druid.metadata.storage.type=mysql +druid.metadata.storage.connector.connectURI=jdbc:mysql://localhost:3306/druid +druid.metadata.storage.connector.user=druid +druid.metadata.storage.connector.password=diurd + +# Deep storage +#druid.storage.type=s3 +#druid.s3.accessKey=#{S3_ACCESS_KEY} +#druid.s3.secretKey=#{S3_SECRET_KEY} + +# Deep storage (local) +druid.storage.type=local +druid.storage.storageDirectory=/tmp/druid/localStorage + +# Query Cache +druid.cache.type=local +druid.cache.sizeInBytes=10000000 + +druid.selectors.indexing.serviceName=overlord + +# Metrics logging +druid.emitter=logging +druid.emitter.logging.loggerClass=LoggingEmitter +druid.emitter.logging.logLevel=error + +druid.discovery.curator.path=/druid/discovery \ No newline at end of file diff --git a/vagrant_files/druid_cl1_rf1/files/config/broker/runtime.properties b/vagrant_files/druid_cl1_rf1/files/config/broker/runtime.properties new file mode 100644 index 0000000..e21f268 --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/config/broker/runtime.properties @@ -0,0 +1,5 @@ +druid.host=localhost +druid.service=broker +druid.port=8090 + +druid.processing.buffer.sizeBytes=4000000 diff --git a/vagrant_files/druid_cl1_rf1/files/config/coordinator/runtime.properties b/vagrant_files/druid_cl1_rf1/files/config/coordinator/runtime.properties new file mode 100644 index 0000000..b0f79ef --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/config/coordinator/runtime.properties @@ -0,0 +1,3 @@ +druid.host=localhost +druid.service=coordinator +druid.port=8081 \ No newline at end of file diff --git a/vagrant_files/druid_cl1_rf1/files/config/historical/runtime.properties b/vagrant_files/druid_cl1_rf1/files/config/historical/runtime.properties new file mode 100644 index 0000000..7996982 --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/config/historical/runtime.properties @@ -0,0 +1,10 @@ +druid.host=localhost +druid.service=historical +druid.port=8082 + +druid.processing.buffer.sizeBytes=1073741824 +druid.server.maxSize=100000000000 +druid.processing.numThreads=4 + +druid.segmentCache.infoPath=/tmp/druid/segmentInfoCache +druid.segmentCache.locations=[{"path": "/tmp/druid/indexCache", "maxSize"\: 100000000000}] diff --git a/vagrant_files/druid_cl1_rf1/files/config/middleManager/runtime.properties b/vagrant_files/druid_cl1_rf1/files/config/middleManager/runtime.properties new file mode 100644 index 0000000..31b3cf9 --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/config/middleManager/runtime.properties @@ -0,0 +1,18 @@ +druid.host=localhost +druid.service=middleManager +druid.port=8100 + +# peon configuration +druid.indexer.fork.property.druid.computation.buffer.size=536870912 +druid.indexer.fork.property.druid.processing.buffer.sizeBytes=536870912 +druid.indexer.fork.property.druid.processing.numThreads=3 +druid.indexer.fork.property.druid.segmentCache.locations=[{"path": "/tmp/persistent/zk_druid", "maxSize": 0}] +druid.indexer.fork.property.druid.server.http.numThreads=50 + +# Resources for peons +druid.indexer.runner.javaOpts=-server -Xmx3g -XX:+UseG1GC -XX:MaxGCPauseMillis=100 +druid.indexer.task.baseTaskDir=/tmp/persistent/task/ +druid.indexer.task.chathandler.type=announce + +# druid.worker.capacity=default (Number of available processors - 1) +druid.worker.ip=localhost diff --git a/vagrant_files/druid_cl1_rf1/files/config/overlord/runtime.properties b/vagrant_files/druid_cl1_rf1/files/config/overlord/runtime.properties new file mode 100644 index 0000000..9e1460b --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/config/overlord/runtime.properties @@ -0,0 +1,6 @@ +druid.host=localhost +druid.port=8080 +druid.service=overlord + +druid.indexer.runner.type=remote +druid.indexer.storage.type=metadata \ No newline at end of file diff --git a/vagrant_files/druid_cl1_rf1/files/druid.service b/vagrant_files/druid_cl1_rf1/files/druid.service new file mode 100644 index 0000000..03d5f95 --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/druid.service @@ -0,0 +1,12 @@ +[Unit] +Description=Druid Cluster +Requires=zookeeper.service mysql.service druid_coordinator.service druid_historical.service druid_middlemanager.service druid_overlord.service druid_broker.service + +[Service] +Type=oneshot +ExecStart=/bin/true +RemainAfterExit=yes +ExecStop=/bin/systemctl stop druid_coordinator.service druid_historical.service druid_middlemanager.service druid_overlord.service druid_broker.service + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/vagrant_files/druid_cl1_rf1/files/druid_broker.service b/vagrant_files/druid_cl1_rf1/files/druid_broker.service new file mode 100644 index 0000000..5844917 --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/druid_broker.service @@ -0,0 +1,13 @@ +[Unit] +Description=Druid Broker Node +After=druid_historical.service +Requires=druid_historical.service + +[Service] +ExecStart=/usr/bin/java -Xmx1g -Xms1g -XX:NewSize=512m -XX:MaxNewSize=512m -XX:MaxDirectMemorySize=2g -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/broker:/home/vagrant/config/_common \ +io.druid.cli.Main server broker + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl1_rf1/files/druid_coordinator.service b/vagrant_files/druid_cl1_rf1/files/druid_coordinator.service new file mode 100644 index 0000000..0b37d54 --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/druid_coordinator.service @@ -0,0 +1,14 @@ +[Unit] +Description=Druid Coordinator Node +After=zookeeper.service mysql.service +Requires=zookeeper.service mysql.service +Before=druid_historical.service druid_middlemanager.service druid_overlord.service druid_broker.service + +[Service] +ExecStart=/usr/bin/java -Xmx1g -Xms1g -XX:NewSize=512m -XX:MaxNewSize=512m -XX:+UseG1GC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/coordinator:/home/vagrant/config/_common \ +io.druid.cli.Main server coordinator + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl1_rf1/files/druid_historical.service b/vagrant_files/druid_cl1_rf1/files/druid_historical.service new file mode 100644 index 0000000..6749e2d --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/druid_historical.service @@ -0,0 +1,14 @@ +[Unit] +Description=Druid Historical Node +After=druid_coordinator.service +Requires=druid_coordinator.service +Before=druid_middlemanager.service druid_overlord.service druid_broker.service + +[Service] +ExecStart=/usr/bin/java -Xmx1g -Xms1g -XX:NewSize=512m -XX:MaxNewSize=512m -XX:MaxDirectMemorySize=8g -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/historical:/home/vagrant/config/_common \ +io.druid.cli.Main server historical + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl1_rf1/files/druid_middlemanager.service b/vagrant_files/druid_cl1_rf1/files/druid_middlemanager.service new file mode 100644 index 0000000..1d5b5fa --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/druid_middlemanager.service @@ -0,0 +1,13 @@ +[Unit] +Description=Druid Middlemanager Node +After=druid_historical.service +Requires=druid_historical.service + +[Service] +ExecStart=/usr/bin/java -Xmx64m -Xms64m -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/middleManager:/home/vagrant/config/_common \ +io.druid.cli.Main server middleManager + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl1_rf1/files/druid_overlord.service b/vagrant_files/druid_cl1_rf1/files/druid_overlord.service new file mode 100644 index 0000000..e25d5d4 --- /dev/null +++ b/vagrant_files/druid_cl1_rf1/files/druid_overlord.service @@ -0,0 +1,13 @@ +[Unit] +Description=Druid Overlord Node +After=druid_historical.service +Requires=druid_historical.service + +[Service] +ExecStart=/usr/bin/java -Xmx2g -Xms2g -XX:NewSize=256m -XX:MaxNewSize=256m -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/overlord:/home/vagrant/config/_common \ +io.druid.cli.Main server overlord + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_0.vagrant b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_0.vagrant new file mode 100644 index 0000000..ebe099d --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_0.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/mysql.rb' +load 'basic/druid_mysql.rb' +load 'basic/zookeeper.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_1.vagrant b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_1.vagrant new file mode 100644 index 0000000..24f995d --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_1.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_2.vagrant b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_2.vagrant new file mode 100644 index 0000000..eb71af9 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_2.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_3.vagrant b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_3.vagrant new file mode 100644 index 0000000..59ecac8 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_3.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_4.vagrant b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_4.vagrant new file mode 100644 index 0000000..78d5f99 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/druid_cl5_rf1_4.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf1/files/config/_common/common.runtime.properties b/vagrant_files/druid_cl5_rf1/files/config/_common/common.runtime.properties new file mode 100644 index 0000000..2cf49d6 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/config/_common/common.runtime.properties @@ -0,0 +1,34 @@ +# Extensions +druid.extensions.coordinates=["io.druid.extensions:mysql-metadata-storage"] +druid.extensions.localRepository=extensions-repo + +# Zookeeper +druid.zk.service.host=localhost + +# Metadata Storage +druid.metadata.storage.type=mysql +druid.metadata.storage.connector.connectURI=jdbc:mysql://localhost:3306/druid +druid.metadata.storage.connector.user=druid +druid.metadata.storage.connector.password=diurd + +# Deep storage +#druid.storage.type=s3 +#druid.s3.accessKey=#{S3_ACCESS_KEY} +#druid.s3.secretKey=#{S3_SECRET_KEY} + +# Deep storage (local) +druid.storage.type=local +druid.storage.storageDirectory=/tmp/druid/localStorage + +# Query Cache +druid.cache.type=local +druid.cache.sizeInBytes=10000000 + +druid.selectors.indexing.serviceName=overlord + +# Metrics logging +druid.emitter=logging +druid.emitter.logging.loggerClass=LoggingEmitter +druid.emitter.logging.logLevel=error + +druid.discovery.curator.path=/druid/discovery \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf1/files/config/broker/runtime.properties b/vagrant_files/druid_cl5_rf1/files/config/broker/runtime.properties new file mode 100644 index 0000000..e21f268 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/config/broker/runtime.properties @@ -0,0 +1,5 @@ +druid.host=localhost +druid.service=broker +druid.port=8090 + +druid.processing.buffer.sizeBytes=4000000 diff --git a/vagrant_files/druid_cl5_rf1/files/config/coordinator/runtime.properties b/vagrant_files/druid_cl5_rf1/files/config/coordinator/runtime.properties new file mode 100644 index 0000000..69a6876 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/config/coordinator/runtime.properties @@ -0,0 +1,5 @@ +druid.host=localhost +druid.service=coordinator +druid.port=8081 + +druid.coordinator.startDelay=PT60s diff --git a/vagrant_files/druid_cl5_rf1/files/config/historical/runtime.properties b/vagrant_files/druid_cl5_rf1/files/config/historical/runtime.properties new file mode 100644 index 0000000..7996982 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/config/historical/runtime.properties @@ -0,0 +1,10 @@ +druid.host=localhost +druid.service=historical +druid.port=8082 + +druid.processing.buffer.sizeBytes=1073741824 +druid.server.maxSize=100000000000 +druid.processing.numThreads=4 + +druid.segmentCache.infoPath=/tmp/druid/segmentInfoCache +druid.segmentCache.locations=[{"path": "/tmp/druid/indexCache", "maxSize"\: 100000000000}] diff --git a/vagrant_files/druid_cl5_rf1/files/config/middleManager/runtime.properties b/vagrant_files/druid_cl5_rf1/files/config/middleManager/runtime.properties new file mode 100644 index 0000000..31b3cf9 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/config/middleManager/runtime.properties @@ -0,0 +1,18 @@ +druid.host=localhost +druid.service=middleManager +druid.port=8100 + +# peon configuration +druid.indexer.fork.property.druid.computation.buffer.size=536870912 +druid.indexer.fork.property.druid.processing.buffer.sizeBytes=536870912 +druid.indexer.fork.property.druid.processing.numThreads=3 +druid.indexer.fork.property.druid.segmentCache.locations=[{"path": "/tmp/persistent/zk_druid", "maxSize": 0}] +druid.indexer.fork.property.druid.server.http.numThreads=50 + +# Resources for peons +druid.indexer.runner.javaOpts=-server -Xmx3g -XX:+UseG1GC -XX:MaxGCPauseMillis=100 +druid.indexer.task.baseTaskDir=/tmp/persistent/task/ +druid.indexer.task.chathandler.type=announce + +# druid.worker.capacity=default (Number of available processors - 1) +druid.worker.ip=localhost diff --git a/vagrant_files/druid_cl5_rf1/files/config/overlord/runtime.properties b/vagrant_files/druid_cl5_rf1/files/config/overlord/runtime.properties new file mode 100644 index 0000000..9e1460b --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/config/overlord/runtime.properties @@ -0,0 +1,6 @@ +druid.host=localhost +druid.port=8080 +druid.service=overlord + +druid.indexer.runner.type=remote +druid.indexer.storage.type=metadata \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf1/files/druid_broker.service b/vagrant_files/druid_cl5_rf1/files/druid_broker.service new file mode 100644 index 0000000..477dfae --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/druid_broker.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Broker Node + +[Service] +ExecStart=/usr/bin/java -Xmx10g -Xms10g -XX:NewSize=4g -XX:MaxNewSize=4g -XX:MaxDirectMemorySize=12g -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/broker:/home/vagrant/config/_common \ +io.druid.cli.Main server broker + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf1/files/druid_coordinator.service b/vagrant_files/druid_cl5_rf1/files/druid_coordinator.service new file mode 100644 index 0000000..2529251 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/druid_coordinator.service @@ -0,0 +1,13 @@ +[Unit] +Description=Druid Coordinator Node +After=zookeeper.service mysql.service +Requires=zookeeper.service mysql.service + +[Service] +ExecStart=/usr/bin/java -Xmx10g -Xms10g -XX:NewSize=512m -XX:MaxNewSize=512m -XX:+UseG1GC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/coordinator:/home/vagrant/config/_common \ +io.druid.cli.Main server coordinator + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf1/files/druid_historical.service b/vagrant_files/druid_cl5_rf1/files/druid_historical.service new file mode 100644 index 0000000..f4ebff3 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/druid_historical.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Historical Node + +[Service] +ExecStart=/usr/bin/java -Xmx10g -Xms10g -XX:NewSize=6g -XX:MaxNewSize=6g -XX:MaxDirectMemorySize=12g -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/historical:/home/vagrant/config/_common \ +io.druid.cli.Main server historical + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf1/files/druid_middlemanager.service b/vagrant_files/druid_cl5_rf1/files/druid_middlemanager.service new file mode 100644 index 0000000..b0b9915 --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/druid_middlemanager.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Middlemanager Node + +[Service] +ExecStart=/usr/bin/java -Xmx64m -Xms64m -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/middleManager:/home/vagrant/config/_common \ +io.druid.cli.Main server middleManager + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf1/files/druid_overlord.service b/vagrant_files/druid_cl5_rf1/files/druid_overlord.service new file mode 100644 index 0000000..63a1cca --- /dev/null +++ b/vagrant_files/druid_cl5_rf1/files/druid_overlord.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Overlord Node + +[Service] +ExecStart=/usr/bin/java -Xmx4g -Xms4g -XX:NewSize=256m -XX:MaxNewSize=256m -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/overlord:/home/vagrant/config/_common \ +io.druid.cli.Main server overlord + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_0.vagrant b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_0.vagrant new file mode 100644 index 0000000..ebe099d --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_0.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/mysql.rb' +load 'basic/druid_mysql.rb' +load 'basic/zookeeper.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_1.vagrant b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_1.vagrant new file mode 100644 index 0000000..24f995d --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_1.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_2.vagrant b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_2.vagrant new file mode 100644 index 0000000..eb71af9 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_2.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_3.vagrant b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_3.vagrant new file mode 100644 index 0000000..59ecac8 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_3.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_4.vagrant b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_4.vagrant new file mode 100644 index 0000000..78d5f99 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/druid_cl5_rf2_4.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf2/files/config/_common/common.runtime.properties b/vagrant_files/druid_cl5_rf2/files/config/_common/common.runtime.properties new file mode 100644 index 0000000..2cf49d6 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/config/_common/common.runtime.properties @@ -0,0 +1,34 @@ +# Extensions +druid.extensions.coordinates=["io.druid.extensions:mysql-metadata-storage"] +druid.extensions.localRepository=extensions-repo + +# Zookeeper +druid.zk.service.host=localhost + +# Metadata Storage +druid.metadata.storage.type=mysql +druid.metadata.storage.connector.connectURI=jdbc:mysql://localhost:3306/druid +druid.metadata.storage.connector.user=druid +druid.metadata.storage.connector.password=diurd + +# Deep storage +#druid.storage.type=s3 +#druid.s3.accessKey=#{S3_ACCESS_KEY} +#druid.s3.secretKey=#{S3_SECRET_KEY} + +# Deep storage (local) +druid.storage.type=local +druid.storage.storageDirectory=/tmp/druid/localStorage + +# Query Cache +druid.cache.type=local +druid.cache.sizeInBytes=10000000 + +druid.selectors.indexing.serviceName=overlord + +# Metrics logging +druid.emitter=logging +druid.emitter.logging.loggerClass=LoggingEmitter +druid.emitter.logging.logLevel=error + +druid.discovery.curator.path=/druid/discovery \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf2/files/config/broker/runtime.properties b/vagrant_files/druid_cl5_rf2/files/config/broker/runtime.properties new file mode 100644 index 0000000..e21f268 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/config/broker/runtime.properties @@ -0,0 +1,5 @@ +druid.host=localhost +druid.service=broker +druid.port=8090 + +druid.processing.buffer.sizeBytes=4000000 diff --git a/vagrant_files/druid_cl5_rf2/files/config/coordinator/runtime.properties b/vagrant_files/druid_cl5_rf2/files/config/coordinator/runtime.properties new file mode 100644 index 0000000..69a6876 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/config/coordinator/runtime.properties @@ -0,0 +1,5 @@ +druid.host=localhost +druid.service=coordinator +druid.port=8081 + +druid.coordinator.startDelay=PT60s diff --git a/vagrant_files/druid_cl5_rf2/files/config/historical/runtime.properties b/vagrant_files/druid_cl5_rf2/files/config/historical/runtime.properties new file mode 100644 index 0000000..7996982 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/config/historical/runtime.properties @@ -0,0 +1,10 @@ +druid.host=localhost +druid.service=historical +druid.port=8082 + +druid.processing.buffer.sizeBytes=1073741824 +druid.server.maxSize=100000000000 +druid.processing.numThreads=4 + +druid.segmentCache.infoPath=/tmp/druid/segmentInfoCache +druid.segmentCache.locations=[{"path": "/tmp/druid/indexCache", "maxSize"\: 100000000000}] diff --git a/vagrant_files/druid_cl5_rf2/files/config/middleManager/runtime.properties b/vagrant_files/druid_cl5_rf2/files/config/middleManager/runtime.properties new file mode 100644 index 0000000..31b3cf9 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/config/middleManager/runtime.properties @@ -0,0 +1,18 @@ +druid.host=localhost +druid.service=middleManager +druid.port=8100 + +# peon configuration +druid.indexer.fork.property.druid.computation.buffer.size=536870912 +druid.indexer.fork.property.druid.processing.buffer.sizeBytes=536870912 +druid.indexer.fork.property.druid.processing.numThreads=3 +druid.indexer.fork.property.druid.segmentCache.locations=[{"path": "/tmp/persistent/zk_druid", "maxSize": 0}] +druid.indexer.fork.property.druid.server.http.numThreads=50 + +# Resources for peons +druid.indexer.runner.javaOpts=-server -Xmx3g -XX:+UseG1GC -XX:MaxGCPauseMillis=100 +druid.indexer.task.baseTaskDir=/tmp/persistent/task/ +druid.indexer.task.chathandler.type=announce + +# druid.worker.capacity=default (Number of available processors - 1) +druid.worker.ip=localhost diff --git a/vagrant_files/druid_cl5_rf2/files/config/overlord/runtime.properties b/vagrant_files/druid_cl5_rf2/files/config/overlord/runtime.properties new file mode 100644 index 0000000..9e1460b --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/config/overlord/runtime.properties @@ -0,0 +1,6 @@ +druid.host=localhost +druid.port=8080 +druid.service=overlord + +druid.indexer.runner.type=remote +druid.indexer.storage.type=metadata \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf2/files/druid_broker.service b/vagrant_files/druid_cl5_rf2/files/druid_broker.service new file mode 100644 index 0000000..477dfae --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/druid_broker.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Broker Node + +[Service] +ExecStart=/usr/bin/java -Xmx10g -Xms10g -XX:NewSize=4g -XX:MaxNewSize=4g -XX:MaxDirectMemorySize=12g -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/broker:/home/vagrant/config/_common \ +io.druid.cli.Main server broker + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf2/files/druid_coordinator.service b/vagrant_files/druid_cl5_rf2/files/druid_coordinator.service new file mode 100644 index 0000000..2529251 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/druid_coordinator.service @@ -0,0 +1,13 @@ +[Unit] +Description=Druid Coordinator Node +After=zookeeper.service mysql.service +Requires=zookeeper.service mysql.service + +[Service] +ExecStart=/usr/bin/java -Xmx10g -Xms10g -XX:NewSize=512m -XX:MaxNewSize=512m -XX:+UseG1GC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/coordinator:/home/vagrant/config/_common \ +io.druid.cli.Main server coordinator + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf2/files/druid_historical.service b/vagrant_files/druid_cl5_rf2/files/druid_historical.service new file mode 100644 index 0000000..f4ebff3 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/druid_historical.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Historical Node + +[Service] +ExecStart=/usr/bin/java -Xmx10g -Xms10g -XX:NewSize=6g -XX:MaxNewSize=6g -XX:MaxDirectMemorySize=12g -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/historical:/home/vagrant/config/_common \ +io.druid.cli.Main server historical + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf2/files/druid_middlemanager.service b/vagrant_files/druid_cl5_rf2/files/druid_middlemanager.service new file mode 100644 index 0000000..b0b9915 --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/druid_middlemanager.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Middlemanager Node + +[Service] +ExecStart=/usr/bin/java -Xmx64m -Xms64m -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/middleManager:/home/vagrant/config/_common \ +io.druid.cli.Main server middleManager + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf2/files/druid_overlord.service b/vagrant_files/druid_cl5_rf2/files/druid_overlord.service new file mode 100644 index 0000000..63a1cca --- /dev/null +++ b/vagrant_files/druid_cl5_rf2/files/druid_overlord.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Overlord Node + +[Service] +ExecStart=/usr/bin/java -Xmx4g -Xms4g -XX:NewSize=256m -XX:MaxNewSize=256m -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/overlord:/home/vagrant/config/_common \ +io.druid.cli.Main server overlord + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_0.vagrant b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_0.vagrant new file mode 100644 index 0000000..4d630c8 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_0.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/mysql.rb' +load 'basic/druid_mysql.rb' +load 'basic/zookeeper.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_1.vagrant b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_1.vagrant new file mode 100644 index 0000000..c88c39b --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_1.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_2.vagrant b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_2.vagrant new file mode 100644 index 0000000..c03bb59 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_2.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_3.vagrant b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_3.vagrant new file mode 100644 index 0000000..85165ff --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_3.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_4.vagrant b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_4.vagrant new file mode 100644 index 0000000..2d5db8f --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/druid_cl5_rf5_4.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Druid on 5 VMs with Replication Factor = 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/druid.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf5/files/config/_common/common.runtime.properties b/vagrant_files/druid_cl5_rf5/files/config/_common/common.runtime.properties new file mode 100644 index 0000000..2cf49d6 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/config/_common/common.runtime.properties @@ -0,0 +1,34 @@ +# Extensions +druid.extensions.coordinates=["io.druid.extensions:mysql-metadata-storage"] +druid.extensions.localRepository=extensions-repo + +# Zookeeper +druid.zk.service.host=localhost + +# Metadata Storage +druid.metadata.storage.type=mysql +druid.metadata.storage.connector.connectURI=jdbc:mysql://localhost:3306/druid +druid.metadata.storage.connector.user=druid +druid.metadata.storage.connector.password=diurd + +# Deep storage +#druid.storage.type=s3 +#druid.s3.accessKey=#{S3_ACCESS_KEY} +#druid.s3.secretKey=#{S3_SECRET_KEY} + +# Deep storage (local) +druid.storage.type=local +druid.storage.storageDirectory=/tmp/druid/localStorage + +# Query Cache +druid.cache.type=local +druid.cache.sizeInBytes=10000000 + +druid.selectors.indexing.serviceName=overlord + +# Metrics logging +druid.emitter=logging +druid.emitter.logging.loggerClass=LoggingEmitter +druid.emitter.logging.logLevel=error + +druid.discovery.curator.path=/druid/discovery \ No newline at end of file diff --git a/vagrant_files/druid_cl5_rf5/files/config/broker/runtime.properties b/vagrant_files/druid_cl5_rf5/files/config/broker/runtime.properties new file mode 100644 index 0000000..e21f268 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/config/broker/runtime.properties @@ -0,0 +1,5 @@ +druid.host=localhost +druid.service=broker +druid.port=8090 + +druid.processing.buffer.sizeBytes=4000000 diff --git a/vagrant_files/druid_cl5_rf5/files/config/coordinator/runtime.properties b/vagrant_files/druid_cl5_rf5/files/config/coordinator/runtime.properties new file mode 100644 index 0000000..69a6876 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/config/coordinator/runtime.properties @@ -0,0 +1,5 @@ +druid.host=localhost +druid.service=coordinator +druid.port=8081 + +druid.coordinator.startDelay=PT60s diff --git a/vagrant_files/druid_cl5_rf5/files/config/historical/runtime.properties b/vagrant_files/druid_cl5_rf5/files/config/historical/runtime.properties new file mode 100644 index 0000000..7996982 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/config/historical/runtime.properties @@ -0,0 +1,10 @@ +druid.host=localhost +druid.service=historical +druid.port=8082 + +druid.processing.buffer.sizeBytes=1073741824 +druid.server.maxSize=100000000000 +druid.processing.numThreads=4 + +druid.segmentCache.infoPath=/tmp/druid/segmentInfoCache +druid.segmentCache.locations=[{"path": "/tmp/druid/indexCache", "maxSize"\: 100000000000}] diff --git a/vagrant_files/druid_cl5_rf5/files/config/middleManager/runtime.properties b/vagrant_files/druid_cl5_rf5/files/config/middleManager/runtime.properties new file mode 100644 index 0000000..31b3cf9 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/config/middleManager/runtime.properties @@ -0,0 +1,18 @@ +druid.host=localhost +druid.service=middleManager +druid.port=8100 + +# peon configuration +druid.indexer.fork.property.druid.computation.buffer.size=536870912 +druid.indexer.fork.property.druid.processing.buffer.sizeBytes=536870912 +druid.indexer.fork.property.druid.processing.numThreads=3 +druid.indexer.fork.property.druid.segmentCache.locations=[{"path": "/tmp/persistent/zk_druid", "maxSize": 0}] +druid.indexer.fork.property.druid.server.http.numThreads=50 + +# Resources for peons +druid.indexer.runner.javaOpts=-server -Xmx3g -XX:+UseG1GC -XX:MaxGCPauseMillis=100 +druid.indexer.task.baseTaskDir=/tmp/persistent/task/ +druid.indexer.task.chathandler.type=announce + +# druid.worker.capacity=default (Number of available processors - 1) +druid.worker.ip=localhost diff --git a/vagrant_files/druid_cl5_rf5/files/config/overlord/runtime.properties b/vagrant_files/druid_cl5_rf5/files/config/overlord/runtime.properties new file mode 100644 index 0000000..782fa6d --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/config/overlord/runtime.properties @@ -0,0 +1,6 @@ +druid.host=localhost +druid.port=8080 +druid.service=overlord + +druid.indexer.runner.type=remote +druid.indexer.storage.type=metadata diff --git a/vagrant_files/druid_cl5_rf5/files/druid_broker.service b/vagrant_files/druid_cl5_rf5/files/druid_broker.service new file mode 100644 index 0000000..477dfae --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/druid_broker.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Broker Node + +[Service] +ExecStart=/usr/bin/java -Xmx10g -Xms10g -XX:NewSize=4g -XX:MaxNewSize=4g -XX:MaxDirectMemorySize=12g -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/broker:/home/vagrant/config/_common \ +io.druid.cli.Main server broker + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf5/files/druid_coordinator.service b/vagrant_files/druid_cl5_rf5/files/druid_coordinator.service new file mode 100644 index 0000000..2529251 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/druid_coordinator.service @@ -0,0 +1,13 @@ +[Unit] +Description=Druid Coordinator Node +After=zookeeper.service mysql.service +Requires=zookeeper.service mysql.service + +[Service] +ExecStart=/usr/bin/java -Xmx10g -Xms10g -XX:NewSize=512m -XX:MaxNewSize=512m -XX:+UseG1GC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/coordinator:/home/vagrant/config/_common \ +io.druid.cli.Main server coordinator + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf5/files/druid_historical.service b/vagrant_files/druid_cl5_rf5/files/druid_historical.service new file mode 100644 index 0000000..f4ebff3 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/druid_historical.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Historical Node + +[Service] +ExecStart=/usr/bin/java -Xmx10g -Xms10g -XX:NewSize=6g -XX:MaxNewSize=6g -XX:MaxDirectMemorySize=12g -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/historical:/home/vagrant/config/_common \ +io.druid.cli.Main server historical + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf5/files/druid_middlemanager.service b/vagrant_files/druid_cl5_rf5/files/druid_middlemanager.service new file mode 100644 index 0000000..b0b9915 --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/druid_middlemanager.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Middlemanager Node + +[Service] +ExecStart=/usr/bin/java -Xmx64m -Xms64m -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/middleManager:/home/vagrant/config/_common \ +io.druid.cli.Main server middleManager + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/druid_cl5_rf5/files/druid_overlord.service b/vagrant_files/druid_cl5_rf5/files/druid_overlord.service new file mode 100644 index 0000000..63a1cca --- /dev/null +++ b/vagrant_files/druid_cl5_rf5/files/druid_overlord.service @@ -0,0 +1,11 @@ +[Unit] +Description=Druid Overlord Node + +[Service] +ExecStart=/usr/bin/java -Xmx4g -Xms4g -XX:NewSize=256m -XX:MaxNewSize=256m -XX:+UseConcMarkSweepGC \ +-Duser.timezone=UTC -Dfile.encoding=UTF-8 \ +-classpath :/usr/share/java/mysql-connector-java.jar:/home/vagrant/druid-0.8.1/lib/*:/home/vagrant/config/overlord:/home/vagrant/config/_common \ +io.druid.cli.Main server overlord + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/generator/files/RunWorkload.py b/vagrant_files/generator/files/RunWorkload.py new file mode 100755 index 0000000..56d982c --- /dev/null +++ b/vagrant_files/generator/files/RunWorkload.py @@ -0,0 +1,491 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +## replaces old workload_.sh scripts for better multi vm support + +import argparse +import logging +import databases +from fabric.api import * +import re +import locale +import time + +def clean_exit(code, hostnames, shutdown=True): + if shutdown: + for hostname in hostnames: + run_on_vm(hostname, "/home/vagrant/.ssh/id_rsa", True, "sudo poweroff",logger,False,True,True,False) + exit(code) + +def run_on_vm (hostString, keyFilename, disableKnownHosts,command,logger,warn_only=False,quiet=False,test=False,getResult=False): + # Same as TSDBBench.py run_on_vm + with settings(host_string= hostString, + key_filename = keyFilename, + disable_known_hosts = disableKnownHosts): + result = run(command,warn_only=warn_only, quiet=quiet) + if result.return_code == 0 or (warn_only and result.return_code == 255) or (test and result.return_code == -1): + if getResult: + return result + return True + else: + logger.error("Command '%s' on %s returned %s." %(command, hostString, result.return_code)) + if getResult: + return result + return False + +def run_local (command, logger, test=False, getResult=False): + result = local(command, capture=True) + if result.return_code == 0 or (test and result.return_code == -1): + if getResult: + return result + return True + else: + logger.error("Command '%s' returned %s (local)." %(command, result.return_code)) + if getResult: + return result + return False + +def get_local_ip(logger): + result = run_local('sudo ifconfig | grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" | head -n1',logger,False,True) + if result != None and result != False and result.return_code == 0: + return result.stdout + else: + if result != None and result != False: + logger.error("Can't get local IP. Return Code: '%s' STDOUT: '%s'." %(result.return_code,result.stdout)) + else: + logger.error("Can't get local IP.") + return None + +def check_keys(dict, keys): + foundAll = True + for key in keys: + if key not in dict.keys(): + foundAll = False + return foundAll + +def get_time_file(): + act_loc=locale.getlocale() + try: + locale.setlocale(locale.LC_ALL,'en_US.UTF-8') + except Exception, e: + logger.error('Failed to set locale, do you have locale en_US.UTF-8 installed?', exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + timeStr=time.strftime("%Y%m%d%H%M",time.localtime()) + locale.setlocale(locale.LC_ALL,act_loc) + return timeStr + +def get_time_log(): + act_loc=locale.getlocale() + try: + locale.setlocale(locale.LC_ALL,'en_US.UTF-8') + except Exception, e: + logger.error('Failed to set locale, do you have locale en_US.UTF-8 installed?', exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + timeStr=time.strftime("%a %b %d %H:%M:%S %Z %Y",time.localtime()) + locale.setlocale(locale.LC_ALL,act_loc) + return timeStr + +# gets space for every db for every folder and appends it to spaceDict +def get_space(ips, spaceDict, folders, local): + if local: + space=0 + if "basic" not in spaceDict.keys(): + spaceDict["basic"]=[] + for folder in folders: + spaceStr = run_local("sudo du %s --summarize" %(folder), logger, False, True) + if spaceStr == None or spaceStr == "": + logger.error('Failed to get space for folder %s (local).' %(folder)) + clean_exit(-1, args.ip, not args.noshutdown) + try: + searchRes = re.search("[0-9]+",spaceStr) + if searchRes == None: + logger.error('Failed to get space for folder %s (local).' %(folder)) + clean_exit(-1, args.ip, not args.noshutdown) + try: + space += int(searchRes.group(0)) + except Exception, e: + logger.error("Can't convert %s to int." %(space), exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + except Exception, e: + logger.error('Failed to get space for folder %s (local).' %(folder), exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + spaceDict["basic"] += [space] + else: + for ip in ips: + if ip not in spaceDict.keys(): + spaceDict[ip] = [] + space=0 + for folder in folders: + spaceStr = run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True,"sudo du %s --summarize" %(folder),logger,False,True,False, True) + if spaceStr == None or spaceStr == "": + logger.error('Failed to get space for folder %s for vm %s.' %(folder, ip)) + clean_exit(-1, args.ip, not args.noshutdown) + try: + searchRes = re.search("[0-9]+",spaceStr) + if searchRes == None: + logger.error('Failed to get space for folder %s for vm %s.' %(folder, ip)) + clean_exit(-1, args.ip, not args.noshutdown) + try: + space += int(searchRes.group(0)) + except Exception, e: + logger.error("Can't convert %s to int." %(space), exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + except Exception, e: + logger.error('Failed to get space for folder %s for vm %s.' %(folder, ip), exc_info=True) + clean_exit(-1, args.ip, not args.noshutdown) + spaceDict[ip] += [space] + +def check_add_space(spaceDict): + listLen = -1 + totalSpace=[] + for key in spaceDict.keys(): + if listLen == -1: + listLen = len(spaceDict[key]) + totalSpace = list(spaceDict[key]) + elif len(spaceDict[key]) != listLen: + logger.error('Got two space lists that do not have the same length. This should not happen.') + clean_exit(-1, args.ip, not args.noshutdown) + else: + for i in range(0,len(spaceDict[key])): + totalSpace[i] += spaceDict[key][i] + return totalSpace + +def make_space_str(spaceList): + spaceStr="" + for element in spaceList: + if spaceStr == "": + spaceStr+="%s" %(element) + else: + spaceStr+=" %s" %(element) + return spaceStr + +def remote_sync(ips): + for ip in ips: + if not run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True,"sudo sync",logger,False,True,False, False): + logger.error('Failed to sync for %s.' %(ip)) + clean_exit(-1, args.ip, not args.noshutdown) + +def local_sync(): + run_local("sudo sync",logger,False) + +def replStr(ips, ip, str, localIp): + commandRepl=str + commandRepl=commandRepl.replace("%%IP%%",ip); + commandRepl=commandRepl.replace("%%IPgen%%",localIp); + ipAll="" + for ipAddr in ips: + ipAll+="%s " %(ip) + ipAll="\"%s\"" %(ipAll[:-1]) + commandRepl=commandRepl.replace("%%IPall%%",ipAll); + findallRes = re.findall("%%IP[0-9]+%%", commandRepl) + for res in findallRes: + searchRes = re.search("[0-9]+", res) + if searchRes != None: + try: + key = int(searchRes.group(0)) + if len(ips) > key: + commandRepl=commandRepl.replace(res,ips[key]); + else: + logger.error('Key to high, not enough ips for key %s.' %(key)) + clean_exit(-1, ips, not args.noshutdown) + except: + logger.error("Can't convert key to int: %s." %(key)) + clean_exit(-1, ips, not args.noshutdown) + else: + logger.error('Failed to find number in %s.' %(res)) + clean_exit(-1, ips, not args.noshutdown) + return commandRepl + +# Configure ArgumentParser +parser = argparse.ArgumentParser(prog="RunWorkload.py",version=__version__,description="replaces old workload_.sh scripts for better multi vm support", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="") +parser.add_argument("-d", "--database", metavar="DATABASE", required=True, help="Process database DATABASE") +parser.add_argument("-w", "--workload", metavar="WORKLOAD", required=True, help="Process workload WORKLOAD") +parser.add_argument("-i", "--ip", metavar="IP", required=True, nargs='+', help="connect to IP; Can be more than one.") +parser.add_argument("-g", "--granularity", metavar="GRANULARITY", type=int, default=1000, help="use TS Granularity") +parser.add_argument("-b", "--bucket", metavar="BUCKET", type=int, default=10000, help="set Bucketsize for histogram measurements") +parser.add_argument("-t", "--timeseries", action='store_true', help="do timeseries instead of histogramm") +parser.add_argument("-n", "--noshutdown", action='store_true', help="Don't shutdown vms at cleanup/exit (for debugging only)") +parser.add_argument("-p", "--prerunonly", action='store_true', help="Stop after prerun.") +parser.add_argument("--debug", action='store_false', help="Debug remote commands.") +args = parser.parse_args() + +logLevel = logging.WARN +logging.addLevelName(31,"TIMESERIES") +logging.addLevelName(32,"GRANULARITY") +logging.addLevelName(33,"BUCKET") +logging.addLevelName(34,"SPACE") +logging.addLevelName(35,"START") +logging.addLevelName(36,"END") +logging.addLevelName(37,"DESCRIPTION") +logger = logging.getLogger(__name__) +handler = logging.FileHandler("/home/vagrant/ycsb_%s_%s_%s.log" %(args.database.lower(), args.workload.lower(), get_time_file())) +handler.setLevel(logLevel) +formatter = logging.Formatter('%(levelname)s: %(message)s') +handler.setFormatter(formatter) +logger.addHandler(handler) +handler = logging.StreamHandler() +handler.setFormatter(formatter) +logger.addHandler(handler) + +dbConfig=databases.getDict(logger) +if dbConfig == None or dbConfig == {}: + clean_exit(-1, args.ip, not args.noshutdown) + +# this is a dict which holds configs (also dicts) for every special database +# format: key -> dbname +# this results in a dict with the following keys: +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +knownKeys=["db_folders","db_client","db_args","db_name","db_desc","jvm_args","prerun_once","postrun_once", "prerun","postrun", "check","prerun_master","postrun_master", "check_master", "prerun_slaves","postrun_slaves", "check_slaves","basic", "prerun_dict", "postrun_dict", "check_dict", "sequence"] + +if args.database.lower() in dbConfig.keys(): + localIp = get_local_ip(logger) + if localIp == None: + logger.error("Can't get local IP, abort.") + clean_exit(-1,args.ip, not args.noshutdown) + # Sort ips once and for all + ips=[] + if len(dbConfig[args.database.lower()]["sequence"]) != len(args.ip): + logger.error("Sequence list has not the same length as IP list. That can not work!") + clean_exit(-1,args.ip, not args.noshutdown) + for ipIdx in dbConfig[args.database.lower()]["sequence"]: + # do not sort here! this would only sort ips/hostnames alphanumerically. they must be come in sorted and then use the given sequence + ips.append(args.ip[ipIdx]) + if not check_keys(dbConfig[args.database.lower()], knownKeys): + logger.error("Some keys are missing for %s" %(args.database.lower())) + clean_exit(-1,ips, not args.noshutdown) + logger.info("Running prerun commands for %s." %(args.database.lower())) + # Prerun once + for command in dbConfig[args.database.lower()]["prerun_once"]: + commandRepl = command + commandRepl = replStr(args.ip, ips[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_local (commandRepl,logger, False) + # Prerun for all vms + for command in dbConfig[args.database.lower()]["prerun"]: + for ip in ips: + commandRepl = command + commandRepl = replStr(args.ip, ip ,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Prerun for master (first) vm + for command in dbConfig[args.database.lower()]["prerun_master"]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[0], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Prerun for slave (all without first) vm + for command in dbConfig[args.database.lower()]["prerun_slaves"]: + ipsWithoutMaster=list(ips) + ipsWithoutMaster.remove(args.ip[0]) + if len(ipsWithoutMaster) > 0: + for ip in ipsWithoutMaster: + commandRepl = command + commandRepl = replStr(args.ip, ip,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + else: + logger.warning("There is only one db vm or more sequence keys than vms, can't run slave prerun commands via ssh.") + # Prerun for dict + for key in dbConfig[args.database.lower()]["sequence"]: + if key in dbConfig[args.database.lower()]["prerun_dict"].keys(): + if len(args.ip) > key: + for command in dbConfig[args.database.lower()]["prerun_dict"][key]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[key],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[key], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + logger.warning("Key to high, not enough IPs to run prerun command for key: %s." %(key)) + # Check for all vms + for command in dbConfig[args.database.lower()]["check"]: + for ip in ips: + commandRepl = command + commandRepl = replStr(args.ip, ip ,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Check for master (first) vm + for command in dbConfig[args.database.lower()]["check_master"]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[0], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Check for slave (all without first) vm + for command in dbConfig[args.database.lower()]["check_slaves"]: + ipsWithoutMaster=list(ips) + ipsWithoutMaster.remove(args.ip[0]) + if len(ipsWithoutMaster) > 0: + for ip in ipsWithoutMaster: + commandRepl = command + commandRepl = replStr(args.ip, ip,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + else: + logger.warning("There is only one db vm or more sequence keys than vms, can't run slave check commands via ssh.") + # Check for dict + for key in dbConfig[args.database.lower()]["sequence"]: + if key in dbConfig[args.database.lower()]["check_dict"].keys(): + if len(args.ip) > key: + for command in dbConfig[args.database.lower()]["check_dict"][key]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[key],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[key], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + logger.warning("Key to high, not enough IPs to run check command for key: %s." %(key)) + if args.prerunonly: + logger.info("Prerun only, stopping here.") + clean_exit(0,ips, not args.noshutdown) + command = "ycsb/bin/ycsb" + if dbConfig[args.database.lower()]["jvm_args"] != None and dbConfig[args.database.lower()]["jvm_args"] != "": + command += " %s" %(dbConfig[args.database.lower()]["jvm_args"]) + command += " %s" # for load/run + command += " %s" %(dbConfig[args.database.lower()]["db_client"]) + command += " -P ycsb/workloads/%s" %(args.workload) + if len(args.ip) > 0: + command += " %s" %(replStr(args.ip, args.ip[0],dbConfig[args.database.lower()]["db_args"], localIp)) + else: + command += " %s" %(dbConfig[args.database.lower()]["db_args"]) + if args.timeseries: + logger.log(31,1) + command += " -p measurementtype=timeseries" + else: + logger.log(31,0) + logger.log(32,args.granularity) + logger.log(37,dbConfig[args.database.lower()]["db_desc"]) + command += " -p timeseries.granularity=%s" %(args.granularity) + logger.log(33,args.bucket) + command += " -p histogram.buckets=%s" %(args.bucket) + spaceDict={} # contains every db vm as key, for every key an List of 3 space values (start, between, end) + logger.log(35,"%s: Start Test" %(get_time_log())) + get_space(ips,spaceDict,dbConfig[args.database.lower()]["db_folders"],dbConfig[args.database.lower()]["basic"]) + logger.log(35,"%s: Start Load" %(get_time_log())) + res = run_local(command %("load"),logger,False,True) + logger.log(35, res.stdout ) + logger.log(35, res.stderr ) + logger.log(36,"%s: End Load" %(get_time_log())) + local_sync() + remote_sync(ips) + get_space(ips,spaceDict,dbConfig[args.database.lower()]["db_folders"],dbConfig[args.database.lower()]["basic"]) + logger.log(35,"%s: Start Run" %(get_time_log())) + res = run_local(command %("run"),logger,False,True) + logger.log(35, res.stdout ) + logger.log(35, res.stderr ) + logger.log(36,"%s: End Run" %(get_time_log())) + remote_sync(ips) + get_space(ips,spaceDict,dbConfig[args.database.lower()]["db_folders"],dbConfig[args.database.lower()]["basic"]) + logger.log(36,"%s: End Test" %(get_time_log())) + logger.log(34,"%s" %(make_space_str(check_add_space(spaceDict)))) + logger.info("Running postrun commands for %s." %(args.database.lower())) + # Postrun once + for command in dbConfig[args.database.lower()]["postrun_once"]: + commandRepl = command + commandRepl = replStr(args.ip, ips[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_local (commandRepl,logger, False) + # Postrun for all vms + for command in dbConfig[args.database.lower()]["postrun"]: + for ip in ips: + commandRepl = command + commandRepl = replStr(args.ip, ip ,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Postrun for master (first) vm + for command in dbConfig[args.database.lower()]["postrun_master"]: + commandRepl = command + commandRepl = replStr(args.ip, args.ip[0],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[0], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + # Postrun for slave (all without first) vm + for command in dbConfig[args.database.lower()]["postrun_slaves"]: + ipsWithoutMaster=list(ips) + ipsWithoutMaster.remove(args.ip[0]) + if len(ipsWithoutMaster) > 0: + for ip in ipsWithoutMaster: + commandRepl = command + commandRepl = replStr(args.ip, ip,commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (ip, "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + run_local (commandRepl,logger, False) + else: + logger.warning("There is only one db vm or more sequence keys than vms, can't run slave postrun commands via ssh.") + # Postrun for dict + for key in dbConfig[args.database.lower()]["sequence"]: + if key in dbConfig[args.database.lower()]["postrun_dict"].keys(): + if len(args.ip) > key: + for command in dbConfig[args.database.lower()]["postrun_dict"][key]: + commandRepl = command + commandRepl = replStr(ips, args.ip[key],commandRepl, localIp) + if "%%SSH%%" in commandRepl: + commandRepl = commandRepl.replace("%%SSH%%","") + run_on_vm (args.ip[key], "/home/vagrant/.ssh/id_rsa", True, commandRepl,logger,False,args.debug,False,False) + else: + logger.warning("Key to high, not enough IPs to run postrun command for key: %s." %(key)) + clean_exit(0,args.ip, not args.noshutdown) +else: + logger.error("%s is an unknown database." %(args.database)) + clean_exit(-1,args.ip, not args.noshutdown) \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/__init__.py b/vagrant_files/generator/files/databases/__init__.py new file mode 100644 index 0000000..0cb6e0a --- /dev/null +++ b/vagrant_files/generator/files/databases/__init__.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +import pkgutil + +def getDict(logger): + dbConfig = {} + for importer, modname, ispkg in pkgutil.iter_modules(__path__): + try: + m = importer.find_module(modname).load_module(modname) + dbConfig[modname] = m.getDict() + except Exception, e: + logger.error("Can't import %s/%s." %(__path__,modname), exc_info=True) + return {} + return dbConfig diff --git a/vagrant_files/generator/files/databases/basicdb.py b/vagrant_files/generator/files/databases/basicdb.py new file mode 100644 index 0000000..ae44be8 --- /dev/null +++ b/vagrant_files/generator/files/databases/basicdb.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant"] + dbConfig["db_client"]="basicdb" + dbConfig["db_args"]="-p basicdb.verbose=False -p basicdb.randomizedelay=False" + dbConfig["db_name"]="basicdb" + dbConfig["db_desc"]="Basic DB w/o any client" + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= True + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/basicjdbc.py b/vagrant_files/generator/files/databases/basicjdbc.py new file mode 100644 index 0000000..e5a1539 --- /dev/null +++ b/vagrant_files/generator/files/databases/basicjdbc.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p test=True" + dbConfig["db_name"]="basicjdbc" + dbConfig["db_desc"]="Basic JDBC w/o any connection" + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= True + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/basickairosdb.py b/vagrant_files/generator/files/databases/basickairosdb.py new file mode 100644 index 0000000..69abf1f --- /dev/null +++ b/vagrant_files/generator/files/databases/basickairosdb.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p test=True" + dbConfig["db_name"]="basickairosdb" + dbConfig["db_desc"]="Basic Kairos w/o any connection" + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= True + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/basicopentsdb.py b/vagrant_files/generator/files/databases/basicopentsdb.py new file mode 100644 index 0000000..b047efc --- /dev/null +++ b/vagrant_files/generator/files/databases/basicopentsdb.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p test=True" + dbConfig["db_name"]="basicopentsdb" + dbConfig["db_desc"]="Basic OpenTSDB w/o any connection" + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= True + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/blueflood1.py b/vagrant_files/generator/files/databases/blueflood1.py new file mode 100644 index 0000000..9936209 --- /dev/null +++ b/vagrant_files/generator/files/databases/blueflood1.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood1" + dbConfig["db_desc"]="Blueflood with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/blueflood.conf'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blieflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/blueflood2.py b/vagrant_files/generator/files/databases/blueflood2.py new file mode 100644 index 0000000..ad909c0 --- /dev/null +++ b/vagrant_files/generator/files/databases/blueflood2.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood2" + dbConfig["db_desc"]="Blueflood with Cassandra together on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|CASSANDRA_HOSTS=localhost:9160|CASSANDRA_HOSTS=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blieflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/blueflood3.py b/vagrant_files/generator/files/databases/blueflood3.py new file mode 100644 index 0000000..cff30a2 --- /dev/null +++ b/vagrant_files/generator/files/databases/blueflood3.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood3" + dbConfig["db_desc"]="Blueflood with Cassandra together on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|CASSANDRA_HOSTS=localhost:9160|CASSANDRA_HOSTS=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blieflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/blueflood4.py b/vagrant_files/generator/files/databases/blueflood4.py new file mode 100644 index 0000000..56e7cd5 --- /dev/null +++ b/vagrant_files/generator/files/databases/blueflood4.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood4" + dbConfig["db_desc"]="Blueflood with Cassandra together on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|CASSANDRA_HOSTS=localhost:9160|CASSANDRA_HOSTS=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blieflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/blueflood_cl1.py b/vagrant_files/generator/files/databases/blueflood_cl1.py new file mode 100644 index 0000000..e36a94e --- /dev/null +++ b/vagrant_files/generator/files/databases/blueflood_cl1.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood_cl1" + dbConfig["db_desc"]="Blueflood with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/blueflood.conf'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blieflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/blueflood_cl1_rf1.py b/vagrant_files/generator/files/databases/blueflood_cl1_rf1.py new file mode 100644 index 0000000..7f61898 --- /dev/null +++ b/vagrant_files/generator/files/databases/blueflood_cl1_rf1.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood_cl1_rf1" + dbConfig["db_desc"]="Blueflood with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/blueflood.conf'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blueflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/blueflood_cl5_rf1.py b/vagrant_files/generator/files/databases/blueflood_cl5_rf1.py new file mode 100644 index 0000000..2141db1 --- /dev/null +++ b/vagrant_files/generator/files/databases/blueflood_cl5_rf1.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood_cl5_rf1" + dbConfig["db_desc"]="Blueflood with Cassandra together on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|CASSANDRA_HOSTS=localhost:9160|CASSANDRA_HOSTS=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blueflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/blueflood_cl5_rf2.py b/vagrant_files/generator/files/databases/blueflood_cl5_rf2.py new file mode 100644 index 0000000..26d6247 --- /dev/null +++ b/vagrant_files/generator/files/databases/blueflood_cl5_rf2.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood_cl5_rf2" + dbConfig["db_desc"]="Blueflood with Cassandra together on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|CASSANDRA_HOSTS=localhost:9160|CASSANDRA_HOSTS=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blueflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/blueflood_cl5_rf5.py b/vagrant_files/generator/files/databases/blueflood_cl5_rf5.py new file mode 100644 index 0000000..2b9f42b --- /dev/null +++ b/vagrant_files/generator/files/databases/blueflood_cl5_rf5.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="blueflood" + dbConfig["db_args"]="-p ip=%%IP%% -p ingestPort=19000 -p queryPort=19001" + dbConfig["db_name"]="blueflood_cl5_rf5" + dbConfig["db_desc"]="Blueflood with Cassandra together on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|CASSANDRA_HOSTS=localhost:9160|CASSANDRA_HOSTS=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/blueflood.conf'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/blueflood_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'systemctl start blueflood.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status blueflood.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status blueflood.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/druid1.py b/vagrant_files/generator/files/databases/druid1.py new file mode 100644 index 0000000..d7670ea --- /dev/null +++ b/vagrant_files/generator/files/databases/druid1.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP%% -p queryip=%%IP%% -p zookeeperport=2181 -p queryport=8090 -p replicants=1" + dbConfig["db_name"]="druid1" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 1 VM. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start druid.service'", "bash -c 'sleep 180'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid.service | grep -c \"active (exited)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/druid2.py b/vagrant_files/generator/files/databases/druid2.py new file mode 100644 index 0000000..2e6b303 --- /dev/null +++ b/vagrant_files/generator/files/databases/druid2.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +# Does not work with 5 VMs, needs more historical nodes for replication 5 times? +# replication is not expected to bring performance bonus: https://groups.google.com/forum/#!topic/druid-development/0TBL5-3Z2PI + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP0%% -p queryip=%%IP1%% -p zookeeperport=2181 -p queryport=8090 -p replicants=5" + dbConfig["db_name"]="druid2" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 5 VMs with Replication Factor 5. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/_common/common.runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP1%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP2%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP3%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP4%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_coordinator.service'"], + 1 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_broker.service'"], + 2 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_historical.service'"], + 3 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_middlemanager.service'"], + 4 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_overlord.service'", + "bash -c 'sleep 180'"] + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'"], + 1 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + } + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/druid3.py b/vagrant_files/generator/files/databases/druid3.py new file mode 100644 index 0000000..cdb9329 --- /dev/null +++ b/vagrant_files/generator/files/databases/druid3.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP0%% -p queryip=%%IP1%% -p zookeeperport=2181 -p queryport=8090 -p replicants=1" + dbConfig["db_name"]="druid2" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 5 VMs with Replication Factor 1. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/_common/common.runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP1%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP2%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP3%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP4%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_coordinator.service'"], + 1 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_broker.service'"], + 2 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_historical.service'"], + 3 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_middlemanager.service'"], + 4 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_overlord.service'", + "bash -c 'sleep 180'"] + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'"], + 1 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + } + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/druid_cl1_rf1.py b/vagrant_files/generator/files/databases/druid_cl1_rf1.py new file mode 100644 index 0000000..181f9a8 --- /dev/null +++ b/vagrant_files/generator/files/databases/druid_cl1_rf1.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP%% -p queryip=%%IP%% -p zookeeperport=2181 -p queryport=8090 -p replicants=1" + dbConfig["db_name"]="druid_cl1_rf1" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 1 VM. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start druid.service'", "bash -c 'sleep 180'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid.service | grep -c \"active (exited)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/druid_cl5_rf1.py b/vagrant_files/generator/files/databases/druid_cl5_rf1.py new file mode 100644 index 0000000..32411d8 --- /dev/null +++ b/vagrant_files/generator/files/databases/druid_cl5_rf1.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP0%% -p queryip=%%IP1%% -p zookeeperport=2181 -p queryport=8090 -p replicants=1" + dbConfig["db_name"]="druid_cl5_rf1" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 5 VMs with Replication Factor 1. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/_common/common.runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP1%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP2%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP3%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP4%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_coordinator.service'"], + 1 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_broker.service'"], + 2 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_historical.service'"], + 3 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_middlemanager.service'"], + 4 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_overlord.service'", + "bash -c 'sleep 180'"] + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'"], + 1 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + } + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/druid_cl5_rf2.py b/vagrant_files/generator/files/databases/druid_cl5_rf2.py new file mode 100644 index 0000000..65396ab --- /dev/null +++ b/vagrant_files/generator/files/databases/druid_cl5_rf2.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +# Does not work with 5 VMs, needs more historical nodes for replication 5 times? +# replication is not expected to bring performance bonus: https://groups.google.com/forum/#!topic/druid-development/0TBL5-3Z2PI + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP0%% -p queryip=%%IP1%% -p zookeeperport=2181 -p queryport=8090 -p replicants=2" + dbConfig["db_name"]="druid_cl5_rf2" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 5 VMs with Replication Factor 2. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/_common/common.runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP1%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP2%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP3%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP4%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_coordinator.service'"], + 1 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_broker.service'"], + 2 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_historical.service'"], + 3 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_middlemanager.service'"], + 4 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_overlord.service'", + "bash -c 'sleep 180'"] + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'"], + 1 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + } + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/druid_cl5_rf5.py b/vagrant_files/generator/files/databases/druid_cl5_rf5.py new file mode 100644 index 0000000..00b45fe --- /dev/null +++ b/vagrant_files/generator/files/databases/druid_cl5_rf5.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +# Does not work with 5 VMs, needs more historical nodes for replication 5 times? +# replication is not expected to bring performance bonus: https://groups.google.com/forum/#!topic/druid-development/0TBL5-3Z2PI + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/tmp/druid/indexCache", "/tmp/persistent/zk_druid", "/tmp/persistent/task/", "/tmp/druid/localStorage", "/var/lib/mysql"] + dbConfig["db_client"]="druid" + dbConfig["db_args"]="-p zookeeperip=%%IP0%% -p queryip=%%IP1%% -p zookeeperport=2181 -p queryport=8090 -p replicants=5" + dbConfig["db_name"]="druid_cl5_rf5" + dbConfig["db_desc"]="Druid (Broker,Coordinator,Historical,MiddleManager,Overlord) on 5 VMs with Replication Factor 5. Ingest via Tranquility/Finagle, Query via REST." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/_common/common.runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP1%%|g\" /home/vagrant/config/broker/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP0%%|g\" /home/vagrant/config/coordinator/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP2%%|g\" /home/vagrant/config/historical/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP3%%|g\" /home/vagrant/config/middleManager/runtime.properties'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|localhost|%%IP4%%|g\" /home/vagrant/config/overlord/runtime.properties'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_coordinator.service'"], + 1 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_broker.service'"], + 2 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_historical.service'"], + 3 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_middlemanager.service'"], + 4 : ["%%SSH%%sudo -s bash -c 'systemctl start druid_overlord.service'", + "bash -c 'sleep 180'"] + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_coordinator.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_coordinator.service | grep -c \"active (running)\")-1))'"], + 1 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_broker.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_broker.service | grep -c \"active (running)\")-1))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_historical.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_historical.service | grep -c \"active (running)\")-1))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_middlemanager.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_middlemanager.service | grep -c \"active (running)\")-1))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(systemctl status druid_overlord.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status druid_overlord.service | grep -c \"active (running)\")-1))'"] + } + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/influxdb1.py b/vagrant_files/generator/files/databases/influxdb1.py new file mode 100644 index 0000000..3afd1e7 --- /dev/null +++ b/vagrant_files/generator/files/databases/influxdb1.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/opt/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb1" + dbConfig["db_desc"]="InfluxDB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start influxdb.service'", + "sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/influxdb2.py b/vagrant_files/generator/files/databases/influxdb2.py new file mode 100644 index 0000000..c10a2b8 --- /dev/null +++ b/vagrant_files/generator/files/databases/influxdb2.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/opt/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb2" + dbConfig["db_desc"]="InfluxDB on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'systemctl start influxdb.service; sleep 5'"] # the sleep makes sure that 0,1,2 are raft, 3,4 are data vms + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : [ + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=ALTER RETENTION POLICY default ON testdb DURATION INF REPLICATION 5\" 2>&1 | grep -c \"error\")'", + ] + } + dbConfig["postrun_dict"]= {} + # Checking that influxdb service runs, not exited and SHOW SERVERS show 3 raft servers + 2 non-raft servers + # For versions > 0.9.4 there is a new coloumn raft-leader for "SHOW SERVERS" + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'", + # "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + # "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"false\")-1))'"] + "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -v \"true\" | grep -c \"false\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/influxdb3.py b/vagrant_files/generator/files/databases/influxdb3.py new file mode 100644 index 0000000..51cf0e3 --- /dev/null +++ b/vagrant_files/generator/files/databases/influxdb3.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/opt/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb3" + dbConfig["db_desc"]="InfluxDB on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'systemctl start influxdb.service; sleep 5'"] # the sleep makes sure that 0,1,2 are raft, 3,4 are data vms + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : [ + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=ALTER RETENTION POLICY default ON testdb DURATION INF REPLICATION 1\" 2>&1 | grep -c \"error\")'", + ] + } + dbConfig["postrun_dict"]= {} + # Checking that influxdb service runs, not exited and SHOW SERVERS show 3 raft servers + 2 non-raft servers + # For versions > 0.9.4 there is a new coloumn raft-leader for "SHOW SERVERS" + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'", + # "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + # "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"false\")-1))'"] + "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -v \"true\" | grep -c \"false\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/influxdb4.py b/vagrant_files/generator/files/databases/influxdb4.py new file mode 100644 index 0000000..12a79c3 --- /dev/null +++ b/vagrant_files/generator/files/databases/influxdb4.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/opt/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb4" + dbConfig["db_desc"]="InfluxDB on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'systemctl start influxdb.service; sleep 5'"] # the sleep makes sure that 0,1,2 are raft, 3,4 are data vms + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : [ + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=ALTER RETENTION POLICY default ON testdb DURATION INF REPLICATION 2\" 2>&1 | grep -c \"error\")'", + ] + } + dbConfig["postrun_dict"]= {} + # Checking that influxdb service runs, not exited and SHOW SERVERS show 3 raft servers + 2 non-raft servers + # For versions > 0.9.4 there is a new coloumn raft-leader for "SHOW SERVERS" + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'", + # "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + # "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"false\")-1))'"] + "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -v \"true\" | grep -c \"false\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/influxdb_cl1_rf1.py b/vagrant_files/generator/files/databases/influxdb_cl1_rf1.py new file mode 100644 index 0000000..de622f1 --- /dev/null +++ b/vagrant_files/generator/files/databases/influxdb_cl1_rf1.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb_cl1_rf1" + dbConfig["db_desc"]="InfluxDB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c 'systemctl start influxdb.service'", + "sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/influxdb_cl5_rf1.py b/vagrant_files/generator/files/databases/influxdb_cl5_rf1.py new file mode 100644 index 0000000..8d06fb0 --- /dev/null +++ b/vagrant_files/generator/files/databases/influxdb_cl5_rf1.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb_cl5_rf1" + dbConfig["db_desc"]="InfluxDB on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'systemctl start influxdb.service; sleep 5'"] # the sleep makes sure that 0,1,2 are raft, 3,4 are data vms + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : [ + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=ALTER RETENTION POLICY default ON testdb DURATION INF REPLICATION 1\" 2>&1 | grep -c \"error\")'", + ] + } + dbConfig["postrun_dict"]= {} + # Checking that influxdb service runs, not exited and SHOW SERVERS show 3 raft servers + 2 non-raft servers + # For versions > 0.9.4 there is a new coloumn raft-leader for "SHOW SERVERS" + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'", + # "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + # "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"false\")-1))'"] + "%%SSH%%sudo -s bash -c 'exit $(($(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + "$(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -v \"true\" | grep -c \"false\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/influxdb_cl5_rf2.py b/vagrant_files/generator/files/databases/influxdb_cl5_rf2.py new file mode 100644 index 0000000..8223dbb --- /dev/null +++ b/vagrant_files/generator/files/databases/influxdb_cl5_rf2.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb_cl5_rf2" + dbConfig["db_desc"]="InfluxDB on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'systemctl start influxdb.service; sleep 5'"] # the sleep makes sure that 0,1,2 are raft, 3,4 are data vms + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : [ + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=ALTER RETENTION POLICY default ON testdb DURATION INF REPLICATION 2\" 2>&1 | grep -c \"error\")'", + ] + } + dbConfig["postrun_dict"]= {} + # Checking that influxdb service runs, not exited and SHOW SERVERS show 3 raft servers + 2 non-raft servers + # For versions > 0.9.4 there is a new coloumn raft-leader for "SHOW SERVERS" + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'", + # "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + # "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"false\")-1))'"] + "%%SSH%%sudo -s bash -c 'exit $(($(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + "$(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -v \"true\" | grep -c \"false\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/influxdb_cl5_rf5.py b/vagrant_files/generator/files/databases/influxdb_cl5_rf5.py new file mode 100644 index 0000000..06be088 --- /dev/null +++ b/vagrant_files/generator/files/databases/influxdb_cl5_rf5.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/influxdb"] # because /var/opt/influxdb/data does not exist at start (was: ["/var/opt/influxdb/data", "/var/opt/influxdb/wal"]) + dbConfig["db_client"]="influxdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8086" + dbConfig["db_name"]="influxdb_cl5_rf5" + dbConfig["db_desc"]="InfluxDB on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'systemctl start influxdb.service; sleep 5'"] # the sleep makes sure that 0,1,2 are raft, 3,4 are data vms + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : [ + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=CREATE DATABASE testdb\" 2>&1 | grep -c \"error\")'", + "%%SSH%%sudo -s bash -c 'exit $(curl -G http://localhost:8086/query --data-urlencode \"q=ALTER RETENTION POLICY default ON testdb DURATION INF REPLICATION 5\" 2>&1 | grep -c \"error\")'", + ] + } + dbConfig["postrun_dict"]= {} + # Checking that influxdb service runs, not exited and SHOW SERVERS show 3 raft servers + 2 non-raft servers + # For versions > 0.9.4 there is a new coloumn raft-leader for "SHOW SERVERS" + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status influxdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status influxdb.service | grep -c \"active (running)\")-1))'", + # "%%SSH%%sudo -s bash -c 'exit $(($(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + # "$(/opt/influxdb/influx -execute \"SHOW SERVERS\"| grep -c \"false\")-1))'"] + "%%SSH%%sudo -s bash -c 'exit $(($(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -c \"true\")-"+ + "$(/usr/bin/influx -execute \"SHOW SERVERS\"| grep -v \"true\" | grep -c \"false\")-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb1.py b/vagrant_files/generator/files/databases/kairosdb1.py new file mode 100644 index 0000000..a26e68a --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb1.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/opt/kairosdb/build/h2db"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb1" + dbConfig["db_desc"]="KairosDB with H2 together on one VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb2.py b/vagrant_files/generator/files/databases/kairosdb2.py new file mode 100644 index 0000000..248bb7c --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb2.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb2" + dbConfig["db_desc"]="KairosDB with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'cassandra-cli -h localhost -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb3.py b/vagrant_files/generator/files/databases/kairosdb3.py new file mode 100644 index 0000000..5dec31f --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb3.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb3" + dbConfig["db_desc"]="KairosDB with Cassandra on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|kairosdb.datastore.cassandra.host_list=localhost:9160|kairosdb.datastore.cassandra.host_list=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160,|g\" /opt/kairosdb/conf/kairosdb.properties'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'systemctl start kairosdb.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for kairos but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb4.py b/vagrant_files/generator/files/databases/kairosdb4.py new file mode 100644 index 0000000..b25b3c6 --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb4.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb4" + dbConfig["db_desc"]="KairosDB with Cassandra on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|kairosdb.datastore.cassandra.host_list=localhost:9160|kairosdb.datastore.cassandra.host_list=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160,|g\" /opt/kairosdb/conf/kairosdb.properties'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'systemctl start kairosdb.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for kairos but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb5.py b/vagrant_files/generator/files/databases/kairosdb5.py new file mode 100644 index 0000000..703fd33 --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb5.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb5" + dbConfig["db_desc"]="KairosDB with Cassandra on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|kairosdb.datastore.cassandra.host_list=localhost:9160|kairosdb.datastore.cassandra.host_list=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160,|g\" /opt/kairosdb/conf/kairosdb.properties'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'systemctl start kairosdb.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for kairos but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb_cl1_rf1.py b/vagrant_files/generator/files/databases/kairosdb_cl1_rf1.py new file mode 100644 index 0000000..961f92d --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb_cl1_rf1.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_cl1_rf1" + dbConfig["db_desc"]="KairosDB with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'cassandra-cli -h localhost -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb_cl5_rf1.py b/vagrant_files/generator/files/databases/kairosdb_cl5_rf1.py new file mode 100644 index 0000000..5a8a35b --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb_cl5_rf1.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_cl5_rf1" + dbConfig["db_desc"]="KairosDB with Cassandra on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|kairosdb.datastore.cassandra.host_list=localhost:9160|kairosdb.datastore.cassandra.host_list=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160,|g\" /opt/kairosdb/conf/kairosdb.properties'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'systemctl start kairosdb.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for kairos but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb_cl5_rf2.py b/vagrant_files/generator/files/databases/kairosdb_cl5_rf2.py new file mode 100644 index 0000000..3e4fcf7 --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb_cl5_rf2.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_cl5_rf2" + dbConfig["db_desc"]="KairosDB with Cassandra on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|kairosdb.datastore.cassandra.host_list=localhost:9160|kairosdb.datastore.cassandra.host_list=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160,|g\" /opt/kairosdb/conf/kairosdb.properties'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'systemctl start kairosdb.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for kairos but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb_cl5_rf5.py b/vagrant_files/generator/files/databases/kairosdb_cl5_rf5.py new file mode 100644 index 0000000..59b1581 --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb_cl5_rf5.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_cl5_rf5" + dbConfig["db_desc"]="KairosDB with Cassandra on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|kairosdb.datastore.cassandra.host_list=localhost:9160|kairosdb.datastore.cassandra.host_list=%%IP0%%:9160,%%IP1%%:9160,%%IP2%%:9160,%%IP3%%:9160,%%IP4%%:9160,|g\" /opt/kairosdb/conf/kairosdb.properties'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'systemctl start kairosdb.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/kairos_cassandra.cli'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for kairos but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status kairosdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status kairosdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/kairosdb_h2_cl1_rf1.py b/vagrant_files/generator/files/databases/kairosdb_h2_cl1_rf1.py new file mode 100644 index 0000000..2f52c1b --- /dev/null +++ b/vagrant_files/generator/files/databases/kairosdb_h2_cl1_rf1.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/opt/kairosdb/build/h2db"] + dbConfig["db_client"]="kairosdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=8080" + dbConfig["db_name"]="kairosdb_h2_cl1_rf1" + dbConfig["db_desc"]="KairosDB with H2 together on one VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/monetdb_cl1_rf1.py b/vagrant_files/generator/files/databases/monetdb_cl1_rf1.py new file mode 100644 index 0000000..7a020d8 --- /dev/null +++ b/vagrant_files/generator/files/databases/monetdb_cl1_rf1.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/monetdb"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=nl.cwi.monetdb.jdbc.MonetDriver -p db.url=jdbc:monetdb://%%IP%%/test -p db.user=vagrant -p db.passwd=vagrant" + dbConfig["db_name"]="monetdb_cl1_rf1" + dbConfig["db_desc"]="MonetDB DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "%%SSH%%sudo -s bash -c 'sed -i \"s|STARTUP=\\\\\"no\\\\\"|STARTUP=\\\\\"yes\\\\\"|g\" /etc/default/monetdb5-sql'", + "%%SSH%%sudo -s bash -c '/etc/init.d/monetdb5-sql start'", + "%%SSH%%sudo -s bash -c 'monetdb create test'", + "%%SSH%%sudo -s bash -c 'monetdb release test'", + "%%SSH%%mclient -d test -s \"CREATE ROLE vagrant_role\"", + "%%SSH%%mclient -d test -s \"GRANT ALL FROM TO vagrant_role\"", + "%%SSH%%mclient -d test -s \"CREATE SCHEMA test AUTHORIZATION vagrant_role\"", + "%%SSH%%mclient -d test -s \"CREATE USER vagrant WITH PASSWORD 'vagrant' NAME 'vagrant' SCHEMA test\"", + "%%SSH%%mclient -d test -s \"GRANT vagrant_role TO vagrant\"", + "%%SSH%%mclient -d test '/home/vagrant/files/create_table.monetdb'", + "%%SSH%%mclient -d test -s \"GRANT ALL ON test.usermetric TO vagrant\""] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"monetdb\" | grep -v \"grep\" | wc -l)-2))'",] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/mysql.py b/vagrant_files/generator/files/databases/mysql.py new file mode 100644 index 0000000..48e4a3e --- /dev/null +++ b/vagrant_files/generator/files/databases/mysql.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/mysql"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=com.mysql.jdbc.Driver -p db.url=jdbc:mysql://%%IP%%:3306/test -p db.user=root -p db.passwd=vagrant" + dbConfig["db_name"]="mysql" + dbConfig["db_desc"]="MySQL DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "mysql -h \"%%IP%%\" -u root --password='vagrant' -e 'create database test'", + "%%SSH%%mysql -u root --password='vagrant' -e 'source /home/vagrant/files/create_table.mysql'" + ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/mysql1.py b/vagrant_files/generator/files/databases/mysql1.py new file mode 100644 index 0000000..4b39df4 --- /dev/null +++ b/vagrant_files/generator/files/databases/mysql1.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/mysql"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=com.mysql.jdbc.Driver -p db.url=jdbc:mysql://%%IP%%:3306/test -p db.user=root -p db.passwd=vagrant" + dbConfig["db_name"]="mysql1" + dbConfig["db_desc"]="MySQL DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "mysql -h \"%%IP%%\" -u root --password='vagrant' -e 'create database test'", + "%%SSH%%mysql -u root --password='vagrant' -e 'source /home/vagrant/files/create_table.mysql'" + ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/mysql_cl1_rf1.py b/vagrant_files/generator/files/databases/mysql_cl1_rf1.py new file mode 100644 index 0000000..41aa095 --- /dev/null +++ b/vagrant_files/generator/files/databases/mysql_cl1_rf1.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/mysql"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=com.mysql.jdbc.Driver -p db.url=jdbc:mysql://%%IP%%:3306/test -p db.user=root -p db.passwd=vagrant" + dbConfig["db_name"]="mysql_cl1_rf1" + dbConfig["db_desc"]="MySQL DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "mysql -h \"%%IP%%\" -u root --password='vagrant' -e 'create database test'", + "%%SSH%%mysql -u root --password='vagrant' -e 'source /home/vagrant/files/create_table.mysql'" + ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/newts1.py b/vagrant_files/generator/files/databases/newts1.py new file mode 100644 index 0000000..73ed236 --- /dev/null +++ b/vagrant_files/generator/files/databases/newts1.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts1" + dbConfig["db_desc"]="NewTS with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/newts2.py b/vagrant_files/generator/files/databases/newts2.py new file mode 100644 index 0000000..9a461b6 --- /dev/null +++ b/vagrant_files/generator/files/databases/newts2.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts2" + dbConfig["db_desc"]="NewTS with Cassandra together on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP0%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/newts3.py b/vagrant_files/generator/files/databases/newts3.py new file mode 100644 index 0000000..a8035c2 --- /dev/null +++ b/vagrant_files/generator/files/databases/newts3.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts3" + dbConfig["db_desc"]="NewTS with Cassandra together on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP0%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/newts4.py b/vagrant_files/generator/files/databases/newts4.py new file mode 100644 index 0000000..8b5c596 --- /dev/null +++ b/vagrant_files/generator/files/databases/newts4.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts4" + dbConfig["db_desc"]="NewTS with Cassandra together on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP0%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/newts_cl1_rf1.py b/vagrant_files/generator/files/databases/newts_cl1_rf1.py new file mode 100644 index 0000000..ea4877f --- /dev/null +++ b/vagrant_files/generator/files/databases/newts_cl1_rf1.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts_cl1_rf1" + dbConfig["db_desc"]="NewTS with Cassandra together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/newts_cl5_rf1.py b/vagrant_files/generator/files/databases/newts_cl5_rf1.py new file mode 100644 index 0000000..4f212f9 --- /dev/null +++ b/vagrant_files/generator/files/databases/newts_cl5_rf1.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts_cl5_rf1" + dbConfig["db_desc"]="NewTS with Cassandra together on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP0%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/newts_cl5_rf2.py b/vagrant_files/generator/files/databases/newts_cl5_rf2.py new file mode 100644 index 0000000..e63e0e2 --- /dev/null +++ b/vagrant_files/generator/files/databases/newts_cl5_rf2.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts_cl5_rf2" + dbConfig["db_desc"]="NewTS with Cassandra together on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP0%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/newts_cl5_rf5.py b/vagrant_files/generator/files/databases/newts_cl5_rf5.py new file mode 100644 index 0000000..1f5d3c1 --- /dev/null +++ b/vagrant_files/generator/files/databases/newts_cl5_rf5.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="newts" + dbConfig["db_args"]="-p ip=%%IP%% -p port=9042" + dbConfig["db_name"]="newts_cl5_rf5" + dbConfig["db_desc"]="NewTS with Cassandra together on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|host: localhost|host: %%IP0%%|g\" /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'", + "%%SSH%%sudo -s bash -c 'cassandra-cli -h %%IP%% -f /home/vagrant/files/newts_cassandra.cli'", + "%%SSH%%sudo -s bash -c 'sleep 5'", + "%%SSH%%sudo -s bash -c '/home/vagrant/newts-1.3.1/bin/init /home/vagrant/newts-1.3.1/etc/config.yaml'", + "%%SSH%%sudo -s bash -c 'systemctl start newts.service'", + "%%SSH%%sudo -s bash -c 'sleep 5'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status newts.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status newts.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/opentsdb.py b/vagrant_files/generator/files/databases/opentsdb.py new file mode 100644 index 0000000..564ad1a --- /dev/null +++ b/vagrant_files/generator/files/databases/opentsdb.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hbase-1.1.2"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb" + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/opentsdb1.py b/vagrant_files/generator/files/databases/opentsdb1.py new file mode 100644 index 0000000..1fe1980 --- /dev/null +++ b/vagrant_files/generator/files/databases/opentsdb1.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hbase-1.1.2"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb1" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-3))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/opentsdb2.py b/vagrant_files/generator/files/databases/opentsdb2.py new file mode 100644 index 0000000..e344146 --- /dev/null +++ b/vagrant_files/generator/files/databases/opentsdb2.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hadoop"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb2" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop on 5 VMs and Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-5))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 1 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + } + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/opentsdb3.py b/vagrant_files/generator/files/databases/opentsdb3.py new file mode 100644 index 0000000..eee2b56 --- /dev/null +++ b/vagrant_files/generator/files/databases/opentsdb3.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hadoop"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb3" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop on 5 VMs and Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-5))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 1 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + } + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/opentsdb4.py b/vagrant_files/generator/files/databases/opentsdb4.py new file mode 100644 index 0000000..99241bc --- /dev/null +++ b/vagrant_files/generator/files/databases/opentsdb4.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hadoop"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb4" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop on 5 VMs and Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-5))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 1 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + } + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/opentsdb_cl1_rf1.py b/vagrant_files/generator/files/databases/opentsdb_cl1_rf1.py new file mode 100644 index 0000000..b4bd51e --- /dev/null +++ b/vagrant_files/generator/files/databases/opentsdb_cl1_rf1.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hbase-1.1.2"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb_cl1_rf1" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop together on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-3))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-1))'"] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/opentsdb_cl5_rf1.py b/vagrant_files/generator/files/databases/opentsdb_cl5_rf1.py new file mode 100644 index 0000000..c91cdec --- /dev/null +++ b/vagrant_files/generator/files/databases/opentsdb_cl5_rf1.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hadoop"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb_cl5_rf1" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop on 5 VMs and Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-5))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 1 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + } + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/opentsdb_cl5_rf2.py b/vagrant_files/generator/files/databases/opentsdb_cl5_rf2.py new file mode 100644 index 0000000..99241bc --- /dev/null +++ b/vagrant_files/generator/files/databases/opentsdb_cl5_rf2.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hadoop"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb4" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop on 5 VMs and Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-5))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 1 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + } + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/opentsdb_cl5_rf5.py b/vagrant_files/generator/files/databases/opentsdb_cl5_rf5.py new file mode 100644 index 0000000..92812f4 --- /dev/null +++ b/vagrant_files/generator/files/databases/opentsdb_cl5_rf5.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/home/vagrant/hadoop"] + dbConfig["db_client"]="opentsdb" + dbConfig["db_args"]="-p ip=%%IP%% -p port=4242" + dbConfig["db_name"]="opentsdb_cl5_rf5" + dbConfig["db_desc"]="OpenTSDB with HBase and Hadoop on 5 VMs and Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% vm0\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% vm1\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% vm2\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% vm3\" >> /etc/hosts'", + "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% vm4\" >> /etc/hosts'"] + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP0%% $(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP1%% $(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP2%% $(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP3%% $(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'echo -e \"%%IP4%% $(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /etc/hosts'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave0/$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave1/$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave2/$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'sed -i \"s/slave3/$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/core-site.xml'", + #"%%SSH%%sudo -s bash -c 'sed -i \"s/master0/$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )/g\" /home/vagrant/hadoop-2.7.1/etc/hadoop/yarn-site.xml'"] + # ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= []#"%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP1%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP2%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP3%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP4%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/slaves'", + # "%%SSH%%sudo -s bash -c 'echo \"$(dig -x %%IP0%% | grep -A1 \"ANSWER SECTION\" | tail -n1 | awk \"{print $ 5}\" | sed \"s/\.$//g\" )\" >> /home/vagrant/hadoop-2.7.1/etc/hadoop/masters'", + # "%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'"] + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= { + 0 : ["%%SSH%%sudo -s bash -c '/home/vagrant/hadoop-2.7.1/bin/hdfs namenode -format test'", + "%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-dfs.sh", + #"%%SSH%%sudo -s bash /home/vagrant/hadoop-2.7.1/sbin/start-yarn.sh" + "%%SSH%%sudo -s bash /home/vagrant/hbase-1.1.2/bin/start-hbase.sh", + "%%SSH%%sudo -s bash -c 'sleep 10'", + "%%SSH%%sudo -s bash -c \"COMPRESSION=LZO HBASE_HOME=/home/vagrant/hbase-1.1.2 /usr/share/opentsdb/tools/create_table.sh\"", + "%%SSH%%sudo -s bash -c 'systemctl start opentsdb.service'", + "%%SSH%%sudo -s bash -c '/usr/share/opentsdb/bin/tsdb mkmetric usermetric'" + ], + } + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status opentsdb.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status opentsdb.service | grep -c \"active (running)\")-1))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-5))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= { + 1 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 2 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-6))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-4))'"], + 3 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + 4 : ["%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hbase\" | grep -v \"grep hbase\" | wc -l)-4))'", + "%%SSH%%sudo -s bash -c 'exit $(($(ps ax | grep \"hadoop\" | grep -v \"grep hadoop\" | wc -l)-3))'"], + } + dbConfig["basic"]= False + dbConfig["sequence"]=[1,2,3,4,0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/postgres.py b/vagrant_files/generator/files/databases/postgres.py new file mode 100644 index 0000000..2dfdf4c --- /dev/null +++ b/vagrant_files/generator/files/databases/postgres.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/postgresql/9.4/main"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=org.postgresql.Driver -p db.url=jdbc:postgresql://%%IP%%/test -p db.user=vagrant -p db.passwd=vagrant" + dbConfig["db_name"]="postgres" + dbConfig["db_desc"]="Postgres DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "PGPASSWORD=vagrant psql -h \"%%IP%%\" -U postgres -c 'create database test'", + "PGPASSWORD=vagrant psql test -h \"%%IP%%\" -U postgres -c \"create user vagrant password 'vagrant';\"", + "PGPASSWORD=vagrant psql test -h \"%%IP%%\" -U postgres -c \"GRANT ALL PRIVILEGES ON DATABASE test TO vagrant;\"", + "%%SSH%%PGPASSWORD=vagrant psql -U vagrant test -f '/home/vagrant/files/create_table.psql'" + ] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/postgres1.py b/vagrant_files/generator/files/databases/postgres1.py new file mode 100644 index 0000000..6547e6c --- /dev/null +++ b/vagrant_files/generator/files/databases/postgres1.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/postgresql/9.4/main"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=org.postgresql.Driver -p db.url=jdbc:postgresql://%%IP%%/test -p db.user=vagrant -p db.passwd=vagrant" + dbConfig["db_name"]="postgres1" + dbConfig["db_desc"]="Postgres DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "PGPASSWORD=vagrant psql -h \"%%IP%%\" -U postgres -c 'create database test'", + "PGPASSWORD=vagrant psql test -h \"%%IP%%\" -U postgres -c \"create user vagrant password 'vagrant';\"", + "PGPASSWORD=vagrant psql test -h \"%%IP%%\" -U postgres -c \"GRANT ALL PRIVILEGES ON DATABASE test TO vagrant;\"", + "%%SSH%%PGPASSWORD=vagrant psql -U vagrant test -f '/home/vagrant/files/create_table.psql'", + "%%SSH%%sudo -s bash -c 'echo -e \"host all all %%IPgen%% md5\" >> /etc/postgresql/9.4/main/pg_hba.conf'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/postgres_cl1_rf1.py b/vagrant_files/generator/files/databases/postgres_cl1_rf1.py new file mode 100644 index 0000000..66b612e --- /dev/null +++ b/vagrant_files/generator/files/databases/postgres_cl1_rf1.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/postgresql/9.4/main"] + dbConfig["db_client"]="jdbc" + dbConfig["db_args"]="-p jdbc.driver=org.postgresql.Driver -p db.url=jdbc:postgresql://%%IP%%/test -p db.user=vagrant -p db.passwd=vagrant" + dbConfig["db_name"]="postgres_cl1_rf1" + dbConfig["db_desc"]="Postgres DB on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= [ + "PGPASSWORD=vagrant psql -h \"%%IP%%\" -U postgres -c 'create database test'", + "PGPASSWORD=vagrant psql test -h \"%%IP%%\" -U postgres -c \"create user vagrant password 'vagrant';\"", + "PGPASSWORD=vagrant psql test -h \"%%IP%%\" -U postgres -c \"GRANT ALL PRIVILEGES ON DATABASE test TO vagrant;\"", + "%%SSH%%PGPASSWORD=vagrant psql -U vagrant test -f '/home/vagrant/files/create_table.psql'", + "%%SSH%%sudo -s bash -c 'echo -e \"host all all %%IPgen%% md5\" >> /etc/postgresql/9.4/main/pg_hba.conf'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= [] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= [] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/rhombus1.py b/vagrant_files/generator/files/databases/rhombus1.py new file mode 100644 index 0000000..9239516 --- /dev/null +++ b/vagrant_files/generator/files/databases/rhombus1.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=%%IP%% -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl1.json\"" + dbConfig["db_name"]="rhombus1" + dbConfig["db_desc"]="Rhombus with Cassandra on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/rhombus2.py b/vagrant_files/generator/files/databases/rhombus2.py new file mode 100644 index 0000000..7f0a1bc --- /dev/null +++ b/vagrant_files/generator/files/databases/rhombus2.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\" -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl5.json\"" + dbConfig["db_name"]="rhombus2" + dbConfig["db_desc"]="Rhombus with Cassandra on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/rhombus3.py b/vagrant_files/generator/files/databases/rhombus3.py new file mode 100644 index 0000000..f0f5f5e --- /dev/null +++ b/vagrant_files/generator/files/databases/rhombus3.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\" -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl1.json\"" + dbConfig["db_name"]="rhombus3" + dbConfig["db_desc"]="Rhombus with Cassandra on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/rhombus4.py b/vagrant_files/generator/files/databases/rhombus4.py new file mode 100644 index 0000000..fefe37c --- /dev/null +++ b/vagrant_files/generator/files/databases/rhombus4.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\" -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl2.json\"" + dbConfig["db_name"]="rhombus4" + dbConfig["db_desc"]="Rhombus with Cassandra on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/rhombus_cl1_rf1.py b/vagrant_files/generator/files/databases/rhombus_cl1_rf1.py new file mode 100644 index 0000000..9179d35 --- /dev/null +++ b/vagrant_files/generator/files/databases/rhombus_cl1_rf1.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=%%IP%% -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl1.json\"" + dbConfig["db_name"]="rhombus_cl1_rf1" + dbConfig["db_desc"]="Rhombus with Cassandra on 1 VM." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + dbConfig["prerun_slaves"]= [] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + dbConfig["check"]= [] + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/rhombus_cl5_rf1.py b/vagrant_files/generator/files/databases/rhombus_cl5_rf1.py new file mode 100644 index 0000000..b90a8cd --- /dev/null +++ b/vagrant_files/generator/files/databases/rhombus_cl5_rf1.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\" -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl1.json\"" + dbConfig["db_name"]="rhombus_cl5_rf1" + dbConfig["db_desc"]="Rhombus with Cassandra on 5 VMs with Replication Factor 1." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/rhombus_cl5_rf2.py b/vagrant_files/generator/files/databases/rhombus_cl5_rf2.py new file mode 100644 index 0000000..0bae134 --- /dev/null +++ b/vagrant_files/generator/files/databases/rhombus_cl5_rf2.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\" -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl2.json\"" + dbConfig["db_name"]="rhombus4" + dbConfig["db_desc"]="Rhombus with Cassandra on 5 VMs with Replication Factor 2." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/databases/rhombus_cl5_rf5.py b/vagrant_files/generator/files/databases/rhombus_cl5_rf5.py new file mode 100644 index 0000000..6f883e8 --- /dev/null +++ b/vagrant_files/generator/files/databases/rhombus_cl5_rf5.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +__author__ = 'Andreas Bader' +__version__ = "0.01" + +# db_folders -> List of DB Folder (for space check) +# db_client -> name of ycsb client +# db_args -> special ycsb arguments for this db +# db_name -> name of this db (e.g. for workload file) +# db_desc -> more detailed name/description +# jvm_args -> special jvm_args for this db and ycsb +# prerun_once -> list of commands to run local once before ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# postrun_once -> list of commands to run local once after ycsb (%%IP%% uses first db vm) (without ycsb, sync or space diff or poweroff commands!) +# prerun -> list of commands to run before ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# postrun -> list of commands to run after ycsb (all vms or local) (without ycsb, sync or space diff or poweroff commands!) +# prerun_master -> list of commands to run before ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_master -> list of commands to run after ycsb (only on master(first=ID 0) vm or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_slaves -> list of commands to run before ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# postrun_slaves -> list of commands to run after ycsb (only on slave (all without master(=ID 0)) vms or local)) (without ycsb, sync or space diff or poweroff commands!) +# prerun_dict -> list of commands to run before ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# postrun_dict -> list of commands to run after ycsb for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# check -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (systemctl start xyz oftern returns true even if start failed somehow. Check that here!) +# check_master -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (only on master(first=ID 0) vm or local)) +# check_slaves -> list of commands to run after prerun (all vms or local) for checking if everything runs correctly (all without master(=ID 0)) vms or local)) +# check_dict -> list of commands to run after prerun for each db vm (key=number of vm) (without ycsb, sync or space diff or poweroff commands!) (%%SSH%% not needed) +# basic -> True/False, if True this is a basic database, so no need to ssh for space checking +# sequence -> which vm should be provisioned first? (for all postrun/prerun dicts/lists. First number is considered master db vm, rest are slaves.) +# the following variables are possible in prerun_once, postrun_once, prerun, prerun_master, prerun_slaves, check, check_master, check_slaves, postrun, postrun_master, postrun_slaves, prerun_dict, postrun_dict, check_dict, db_args: +# %%IP%% -> IP of (actual) db vm +# %%IPgen%% -> IP of (actual) generator vm (on which this script runs) +# %%IPn%% -> IP of db vm number n (e.g. %%IP2%%) +# %%IPall%% -> give String with IP of all vms) +# %%SSH%% -> if SSH should be used (set at the beginning) +# Order of Preruns/Postruns: +# 1. prerun/postrun/check, 2. prerun_master/postrun_master/check_master, 3. preun_skaves/postrun_slaves/check_slaves, 4.prerun_dict/postrun_dict/check_dict +# General Order: +# prerun -> check -> ycsb -> postrun + +def getDict(): + dbConfig={} + dbConfig["db_folders"]=["/var/lib/cassandra"] + dbConfig["db_client"]="rhombus" + dbConfig["db_args"]="-p ip=\"%%IP0%%,%%IP1%%,%%IP2%%,%%IP3%%,%%IP4%%\" -p keySpacedefinitionfile=\"/home/vagrant/files/rhombus_repl5.json\"" + dbConfig["db_name"]="rhombus_cl5_rf5" + dbConfig["db_desc"]="Rhombus with Cassandra on 5 VMs with Replication Factor 5." + dbConfig["jvm_args"]="-jvm-args='-Xmx4096m'" + dbConfig["prerun_once"]= [] + dbConfig["postrun_once"]= [] + dbConfig["prerun"]= ["%%SSH%%sudo -s bash -c 'sed -i \"s|- seeds: \\\\\"127.0.0.1\\\\\"|- seeds: \\\\\"%%IP0%%\\\\\"|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|listen_address: localhost|listen_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'", + "%%SSH%%sudo -s bash -c 'sed -i \"s|rpc_address: localhost|rpc_address: %%IP%%|g\" /etc/cassandra/cassandra.yaml'"] + dbConfig["postrun"]= [] + dbConfig["prerun_master"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service'", + "%%SSH%%sudo -s bash -c 'sleep 60'"] + dbConfig["postrun_master"]= [] + # Sleep is needed for slaves, otherwise all slaves would connect at the same time which + # leads to an error. systemctl start for cassandra is non-blocking, delay is added by hand + dbConfig["prerun_slaves"]= ["%%SSH%%sudo -s bash -c 'systemctl start cassandra.service && sleep 60'"] + dbConfig["postrun_slaves"]= [] + dbConfig["prerun_dict"]= {} + dbConfig["postrun_dict"]= {} + # check if cassandra runs but has not exited (active+exited = error/not running anymore) + dbConfig["check"]= ["%%SSH%%sudo -s bash -c 'exit $(systemctl status cassandra.service | grep -c \"active (exited)\")'", + "%%SSH%%sudo -s bash -c 'exit $(($(systemctl status cassandra.service | grep -c \"active (running)\")-1))'"] + # check the same for newts but only on master + dbConfig["check_master"]= ["%%SSH%%sudo -s bash -c 'exit $(($(nodetool status | grep -c \"UN\")-5))'"] + dbConfig["check_slaves"]= [] + dbConfig["check_dict"]= {} + dbConfig["basic"]= False + dbConfig["sequence"]=[0,1,2,3,4] + return dbConfig \ No newline at end of file diff --git a/vagrant_files/generator/files/rhombus_repl1.json b/vagrant_files/generator/files/rhombus_repl1.json new file mode 100644 index 0000000..2da862a --- /dev/null +++ b/vagrant_files/generator/files/rhombus_repl1.json @@ -0,0 +1,46 @@ +{ + "name" : "rhombus", + "replicationClass" : "SimpleStrategy", + "replicationFactors" : { + "replication_factor" : 1 + }, + "definitions" : [ + { + "name": "usermetric", + "fields": [ + {"name": "value", "type": "double"}, + {"name": "TAG0", "type": "varchar"}, + {"name": "TAG1", "type": "varchar"}, + {"name": "TAG2", "type": "varchar"}, + {"name": "TAGALWAYSSET1", "type": "bigint"} + ], + "indexes" : [ + { + "key": "TAGALWAYSSET1", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG0", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG0:TAG1", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG0:TAG1:TAG2", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG1", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG2", + "shardingStrategy": {"type": "ShardingStrategyNone"} + } + ] + } + + ] +} \ No newline at end of file diff --git a/vagrant_files/generator/files/rhombus_repl2.json b/vagrant_files/generator/files/rhombus_repl2.json new file mode 100644 index 0000000..1c01a4b --- /dev/null +++ b/vagrant_files/generator/files/rhombus_repl2.json @@ -0,0 +1,46 @@ +{ + "name" : "rhombus", + "replicationClass" : "SimpleStrategy", + "replicationFactors" : { + "replication_factor" : 2 + }, + "definitions" : [ + { + "name": "usermetric", + "fields": [ + {"name": "value", "type": "double"}, + {"name": "TAG0", "type": "varchar"}, + {"name": "TAG1", "type": "varchar"}, + {"name": "TAG2", "type": "varchar"}, + {"name": "TAGALWAYSSET1", "type": "bigint"} + ], + "indexes" : [ + { + "key": "TAGALWAYSSET1", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG0", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG0:TAG1", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG0:TAG1:TAG2", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG1", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG2", + "shardingStrategy": {"type": "ShardingStrategyNone"} + } + ] + } + + ] +} \ No newline at end of file diff --git a/vagrant_files/generator/files/rhombus_repl5.json b/vagrant_files/generator/files/rhombus_repl5.json new file mode 100644 index 0000000..6d395d1 --- /dev/null +++ b/vagrant_files/generator/files/rhombus_repl5.json @@ -0,0 +1,46 @@ +{ + "name" : "rhombus", + "replicationClass" : "SimpleStrategy", + "replicationFactors" : { + "replication_factor" : 5 + }, + "definitions" : [ + { + "name": "usermetric", + "fields": [ + {"name": "value", "type": "double"}, + {"name": "TAG0", "type": "varchar"}, + {"name": "TAG1", "type": "varchar"}, + {"name": "TAG2", "type": "varchar"}, + {"name": "TAGALWAYSSET1", "type": "bigint"} + ], + "indexes" : [ + { + "key": "TAGALWAYSSET1", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG0", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG0:TAG1", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG0:TAG1:TAG2", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG1", + "shardingStrategy": {"type": "ShardingStrategyNone"} + }, + { + "key": "TAG2", + "shardingStrategy": {"type": "ShardingStrategyNone"} + } + ] + } + + ] +} \ No newline at end of file diff --git a/vagrant_files/generator/generator_0.vagrant b/vagrant_files/generator/generator_0.vagrant new file mode 100644 index 0000000..ab71622 --- /dev/null +++ b/vagrant_files/generator/generator_0.vagrant @@ -0,0 +1,27 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "gen0" + +load 'vagrantconf.rb' +load 'vagrantconf_gen.rb' + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + + config.vm.provision "shell", inline: "/root/change_hostname.sh gen0" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y update" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install postgresql-client mysql-client libmysql-java libpostgresql-jdbc-java libcsv-java" + config.vm.provision "shell", privileged: false, inline: "if [ \\( -f /vagrant/files/ycsb.tar.gz -a -r /vagrant/files/ycsb.tar.gz \\) -o \\( -f /vagrant/files/ycsb-0.4.0.tar.gz -a -r /vagrant/files/ycsb-0.4.0.tar.gz \\) ]; then if [ -f /vagrant/files/ycsb-0.4.0.tar.gz ]; then mv /vagrant/files/ycsb-0.4.0.tar.gz ycsb.tar.gz; else mv /vagrant/files/ycsb.tar.gz .; fi; else wget -O ycsb.tar.gz -t 10 --retry-connrefused -nv \"#{$links_ycsbts}\" ; fi" + config.vm.provision "shell", privileged: false, inline: "tar xfvz ycsb.tar.gz" + config.vm.provision "shell", privileged: false, inline: "rm ycsb.tar.gz" + config.vm.provision "shell", privileged: false, inline: "mv ycsb-0.4.0 ycsb" + config.vm.provision "shell", privileged: false, inline: "if [ -d ~/ycsb/jdbc-binding/lib/ ]; then ln -s /usr/share/java/mysql-connector-java.jar ~/ycsb/jdbc-binding/lib/; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d ~/ycsb/jdbc-binding/lib/ ]; then ln -s /usr/share/java/postgresql-jdbc4.jar ~/ycsb/jdbc-binding/lib/; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d /vagrant/files ]; then cp -r /vagrant/files ~/; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d ~/files ]; then chmod +x -f ~/files/*.sh; exit 0; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d /vagrant/files/workloads ]; then mv ~/files/workloads ~/; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d /vagrant/files/libs ]; then mv ~/files/libs ~/; fi" + +end diff --git a/vagrant_files/influxdb_cl1_rf1/influxdb_cl1_rf1_0.vagrant b/vagrant_files/influxdb_cl1_rf1/influxdb_cl1_rf1_0.vagrant new file mode 100644 index 0000000..0535b0c --- /dev/null +++ b/vagrant_files/influxdb_cl1_rf1/influxdb_cl1_rf1_0.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 1 VM + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_0.vagrant b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_0.vagrant new file mode 100644 index 0000000..f4f04f5 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_0.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 1 +# First VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" +INFLUXDBHOSTNAMES = "" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_1.vagrant b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_1.vagrant new file mode 100644 index 0000000..639ea46 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_1.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 1 +# Second VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" +INFLUXDBHOSTNAMES = "vm0:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_2.vagrant b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_2.vagrant new file mode 100644 index 0000000..a73b4df --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_2.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 1 +# Third VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" +INFLUXDBHOSTNAMES = "vm0:8088,vm1:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_3.vagrant b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_3.vagrant new file mode 100644 index 0000000..a8752a5 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_3.vagrant @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 1 +# Third VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" +# you only need 2 vms in INFLUXDBHOSTNAMES, but we use all 3 raft hosts +INFLUXDBHOSTNAMES = "vm0:8088,vm1:8088,vm2:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_4.vagrant b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_4.vagrant new file mode 100644 index 0000000..7499895 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf1/influxdb_cl5_rf1_4.vagrant @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 1 +# Third VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" +# you only need 2 vms in INFLUXDBHOSTNAMES, but we use all 3 raft hosts +INFLUXDBHOSTNAMES = "vm0:8088,vm1:8088,vm2:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_0.vagrant b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_0.vagrant new file mode 100644 index 0000000..2573d4b --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_0.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 2 +# First VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" +INFLUXDBHOSTNAMES = "" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_1.vagrant b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_1.vagrant new file mode 100644 index 0000000..ff26977 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_1.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 2 +# Second VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" +INFLUXDBHOSTNAMES = "vm0:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_2.vagrant b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_2.vagrant new file mode 100644 index 0000000..0211b2f --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_2.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 2 +# Third VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" +INFLUXDBHOSTNAMES = "vm0:8088,vm1:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_3.vagrant b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_3.vagrant new file mode 100644 index 0000000..74061af --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_3.vagrant @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 2 +# Third VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" +# you only need 2 vms in INFLUXDBHOSTNAMES, but we use all 3 raft hosts +INFLUXDBHOSTNAMES = "vm0:8088,vm1:8088,vm2:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_4.vagrant b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_4.vagrant new file mode 100644 index 0000000..b7d00a7 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf2/influxdb_cl5_rf2_4.vagrant @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 2 +# Third VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" +# you only need 2 vms in INFLUXDBHOSTNAMES, but we use all 3 raft hosts +INFLUXDBHOSTNAMES = "vm0:8088,vm1:8088,vm2:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_0.vagrant b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_0.vagrant new file mode 100644 index 0000000..e23e3d9 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_0.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 5 +# First VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" +INFLUXDBHOSTNAMES = "" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_1.vagrant b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_1.vagrant new file mode 100644 index 0000000..2009586 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_1.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 5 +# Second VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" +INFLUXDBHOSTNAMES = "vm0:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_2.vagrant b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_2.vagrant new file mode 100644 index 0000000..a394378 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_2.vagrant @@ -0,0 +1,18 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 5 +# Third VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" +INFLUXDBHOSTNAMES = "vm0:8088,vm1:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_3.vagrant b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_3.vagrant new file mode 100644 index 0000000..cef5d21 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_3.vagrant @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 5 +# Third VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" +# you only need 2 vms in INFLUXDBHOSTNAMES, but we use all 3 raft hosts +INFLUXDBHOSTNAMES = "vm0:8088,vm1:8088,vm2:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_4.vagrant b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_4.vagrant new file mode 100644 index 0000000..d2152b1 --- /dev/null +++ b/vagrant_files/influxdb_cl5_rf5/influxdb_cl5_rf5_4.vagrant @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# InfluxDB on 5 VMs, Replication = 5 +# Third VM of Raft Cluster + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" +# you only need 2 vms in INFLUXDBHOSTNAMES, but we use all 3 raft hosts +INFLUXDBHOSTNAMES = "vm0:8088,vm1:8088,vm2:8088" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/influxdb.rb' +load 'basic/influxdb_cluster.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/kairosdb_cl1_rf1/files/kairos_cassandra.cli b/vagrant_files/kairosdb_cl1_rf1/files/kairos_cassandra.cli new file mode 100644 index 0000000..f0039ff --- /dev/null +++ b/vagrant_files/kairosdb_cl1_rf1/files/kairos_cassandra.cli @@ -0,0 +1,4 @@ +use kairosdb; +update column family data_points with read_repair_chance = 0.1; +update column family row_key_index with read_repair_chance = 0.1; +update column family string_index with read_repair_chance = 0.1; \ No newline at end of file diff --git a/vagrant_files/kairosdb_cl1_rf1/kairosdb_cl1_rf1_0.vagrant b/vagrant_files/kairosdb_cl1_rf1/kairosdb_cl1_rf1_0.vagrant new file mode 100644 index 0000000..3d117f0 --- /dev/null +++ b/vagrant_files/kairosdb_cl1_rf1/kairosdb_cl1_rf1_0.vagrant @@ -0,0 +1,34 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 1 VM + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + + config.vm.provision "shell", inline: "/root/change_hostname.sh vm0" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y update" + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"https://github.com/kairosdb/kairosdb/releases/download/v1.0.0/kairosdb_1.0.0-1_all.deb\"" + config.vm.provision "shell", inline: "dpkg -i kairosdb_1.0.0-1_all.deb" + config.vm.provision "shell", privileged: false, inline: "rm kairosdb_1.0.0-1_all.deb" + config.vm.provision "shell", inline: "echo \"deb http://www.apache.org/dist/cassandra/debian 21x main\" >> /etc/apt/sources.list" + config.vm.provision "shell", inline: "echo \"deb-src http://www.apache.org/dist/cassandra/debian 21x main\" >> /etc/apt/sources.list" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y update" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install cassandra" + config.vm.provision "shell", inline: "systemctl stop kairosdb.service" + config.vm.provision "shell", inline: "systemctl stop cassandra.service" + config.vm.provision "shell", inline: "systemctl start cassandra.service" + config.vm.provision "shell", privileged: false, inline: "sleep 60" + config.vm.provision "shell", inline: "sed -i \"s/kairosdb.service.datastore=org.kairosdb.datastore.h2.H2Module/#kairosdb.service.datastore=org.kairosdb.datastore.h2.H2Module/g\" /opt/kairosdb/conf/kairosdb.properties" + config.vm.provision "shell", inline: "sed -i \"s/#kairosdb.service.datastore=org.kairosdb.datastore.cassandra.CassandraModule/kairosdb.service.datastore=org.kairosdb.datastore.cassandra.CassandraModule/g\" /opt/kairosdb/conf/kairosdb.properties " + config.vm.provision "shell", inline: "systemctl start kairosdb.service" + config.vm.provision "shell", privileged: false, inline: "if [ -d /vagrant/files ]; then cp -r /vagrant/files ~/; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d ~/files ]; then chmod +x -f ~/files/*.sh; exit 0; fi" + config.vm.provision "shell", privileged: false, inline: "sleep 5" +end diff --git a/vagrant_files/kairosdb_cl5_rf1/files/kairos_cassandra.cli b/vagrant_files/kairosdb_cl5_rf1/files/kairos_cassandra.cli new file mode 100644 index 0000000..f0039ff --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf1/files/kairos_cassandra.cli @@ -0,0 +1,4 @@ +use kairosdb; +update column family data_points with read_repair_chance = 0.1; +update column family row_key_index with read_repair_chance = 0.1; +update column family string_index with read_repair_chance = 0.1; \ No newline at end of file diff --git a/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_0.vagrant b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_0.vagrant new file mode 100644 index 0000000..36cc9ed --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_0.vagrant @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/kairosdb.rb' +load 'basic/kairosdb_repl1.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_1.vagrant b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_1.vagrant new file mode 100644 index 0000000..9b44219 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_1.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_2.vagrant b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_2.vagrant new file mode 100644 index 0000000..ae2df28 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_2.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_3.vagrant b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_3.vagrant new file mode 100644 index 0000000..2dd791b --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_3.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_4.vagrant b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_4.vagrant new file mode 100644 index 0000000..fba8c93 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf1/kairosdb_cl5_rf1_4.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf2/files/kairos_cassandra.cli b/vagrant_files/kairosdb_cl5_rf2/files/kairos_cassandra.cli new file mode 100644 index 0000000..f0039ff --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf2/files/kairos_cassandra.cli @@ -0,0 +1,4 @@ +use kairosdb; +update column family data_points with read_repair_chance = 0.1; +update column family row_key_index with read_repair_chance = 0.1; +update column family string_index with read_repair_chance = 0.1; \ No newline at end of file diff --git a/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_0.vagrant b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_0.vagrant new file mode 100644 index 0000000..310d6ac --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_0.vagrant @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/kairosdb.rb' +load 'basic/kairosdb_repl2.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_1.vagrant b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_1.vagrant new file mode 100644 index 0000000..7258e03 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_1.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_2.vagrant b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_2.vagrant new file mode 100644 index 0000000..114e013 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_2.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_3.vagrant b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_3.vagrant new file mode 100644 index 0000000..08b2f8d --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_3.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_4.vagrant b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_4.vagrant new file mode 100644 index 0000000..fcdcd66 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf2/kairosdb_cl5_rf2_4.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf5/files/kairos_cassandra.cli b/vagrant_files/kairosdb_cl5_rf5/files/kairos_cassandra.cli new file mode 100644 index 0000000..f0039ff --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf5/files/kairos_cassandra.cli @@ -0,0 +1,4 @@ +use kairosdb; +update column family data_points with read_repair_chance = 0.1; +update column family row_key_index with read_repair_chance = 0.1; +update column family string_index with read_repair_chance = 0.1; \ No newline at end of file diff --git a/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_0.vagrant b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_0.vagrant new file mode 100644 index 0000000..064bf13 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_0.vagrant @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/kairosdb.rb' +load 'basic/kairosdb_repl5.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_1.vagrant b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_1.vagrant new file mode 100644 index 0000000..f10ac33 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_1.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_2.vagrant b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_2.vagrant new file mode 100644 index 0000000..07657a9 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_2.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_3.vagrant b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_3.vagrant new file mode 100644 index 0000000..a4af1af --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_3.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_4.vagrant b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_4.vagrant new file mode 100644 index 0000000..b960f80 --- /dev/null +++ b/vagrant_files/kairosdb_cl5_rf5/kairosdb_cl5_rf5_4.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' + diff --git a/vagrant_files/kairosdb_h2_cl1_rf1/kairosdb_h2_cl1_rf1_0.vagrant b/vagrant_files/kairosdb_h2_cl1_rf1/kairosdb_h2_cl1_rf1_0.vagrant new file mode 100644 index 0000000..fde9b59 --- /dev/null +++ b/vagrant_files/kairosdb_h2_cl1_rf1/kairosdb_h2_cl1_rf1_0.vagrant @@ -0,0 +1,25 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Kairos with H2 on 1 VM + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + + config.vm.provision "shell", inline: "/root/change_hostname.sh vm0" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y update" + config.vm.provision "shell", privileged: false, inline: "wget -t 10 --retry-connrefused -nv \"https://github.com/kairosdb/kairosdb/releases/download/v1.0.0/kairosdb_1.0.0-1_all.deb\"" + config.vm.provision "shell", inline: "dpkg -i kairosdb_1.0.0-1_all.deb" + config.vm.provision "shell", privileged: false, inline: "rm kairosdb_1.0.0-1_all.deb" + config.vm.provision "shell", inline: "systemctl restart kairosdb.service" + config.vm.provision "shell", privileged: false, inline: "if [ -d /vagrant/files ]; then cp -r /vagrant/files ~/; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d ~/files ]; then chmod +x -f ~/files/*.sh; exit 0; fi" + config.vm.provision "shell", privileged: false, inline: "sleep 5" + +end diff --git a/vagrant_files/monetdb_cl1_rf1/files/create_table.monetdb b/vagrant_files/monetdb_cl1_rf1/files/create_table.monetdb new file mode 100644 index 0000000..1eab9c9 --- /dev/null +++ b/vagrant_files/monetdb_cl1_rf1/files/create_table.monetdb @@ -0,0 +1,25 @@ +-- Copyright (c) 2015 YCSB contributors. All rights reserved. +-- +-- Licensed 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. See accompanying +-- LICENSE file. + +-- Create the usermetric table with 10 fields and 1 double value and Timestamp as key +CREATE TABLE test.usermetric( + ID INT AUTO_INCREMENT PRIMARY KEY, + YCSB_KEY TIMESTAMP, + VALUE DOUBLE, + TAG0 TEXT, TAG1 TEXT, + TAG2 TEXT, TAG3 TEXT, + TAG4 TEXT, TAG5 TEXT, + TAG6 TEXT, TAG7 TEXT, + TAG8 TEXT, TAG9 TEXT); diff --git a/vagrant_files/monetdb_cl1_rf1/monetdb_cl1_rf1_0.vagrant b/vagrant_files/monetdb_cl1_rf1/monetdb_cl1_rf1_0.vagrant new file mode 100644 index 0000000..9cb13b1 --- /dev/null +++ b/vagrant_files/monetdb_cl1_rf1/monetdb_cl1_rf1_0.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# MonetDB on 1 VM + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/monetdb.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/mysql_cl1_rf1/files/create_table.mysql b/vagrant_files/mysql_cl1_rf1/files/create_table.mysql new file mode 100644 index 0000000..8c073bb --- /dev/null +++ b/vagrant_files/mysql_cl1_rf1/files/create_table.mysql @@ -0,0 +1,16 @@ +-- Creates a Table. +-- see https://github.com/brianfrankcooper/YCSB/blob/master/jdbc/src/main/resources/sql/create_table.mysql + +-- Drop the table if it exists; +DROP TABLE IF EXISTS test.usermetric; + +-- Create the usermetric table with 10 fields and 1 double value and Timestamp as key +CREATE TABLE test.usermetric( + ID INT AUTO_INCREMENT PRIMARY KEY, + YCSB_KEY TIMESTAMP, + VALUE DOUBLE, + TAG0 TEXT, TAG1 TEXT, + TAG2 TEXT, TAG3 TEXT, + TAG4 TEXT, TAG5 TEXT, + TAG6 TEXT, TAG7 TEXT, + TAG8 TEXT, TAG9 TEXT); diff --git a/vagrant_files/mysql_cl1_rf1/mysql_cl1_rf1_0.vagrant b/vagrant_files/mysql_cl1_rf1/mysql_cl1_rf1_0.vagrant new file mode 100644 index 0000000..f0f4828 --- /dev/null +++ b/vagrant_files/mysql_cl1_rf1/mysql_cl1_rf1_0.vagrant @@ -0,0 +1,23 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + + config.vm.provision "shell", inline: "/root/change_hostname.sh vm0" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y update" + config.vm.provision "shell", inline: "apt-get --allow-unauthenticated -q -y install mysql-server" + config.vm.provision "shell", inline: "mysqladmin -u root password vagrant" + config.vm.provision "shell", privileged: false, inline: "if [ -d /vagrant/files ]; then cp -r /vagrant/files ~/; fi" + config.vm.provision "shell", privileged: false, inline: "if [ -d ~/files ]; then chmod +x -f ~/files/*.sh; exit 0; fi" + config.vm.provision "shell", inline: "sed -i \"s/bind-address[[:space:]]*\= 127\.0\.0\.1/bind-address \= \*/g\" /etc/mysql/my.cnf" + config.vm.provision "shell", privileged: false, inline: "mysql -u root --password='vagrant' -e \"GRANT ALL ON *.* to root@'%' IDENTIFIED BY 'vagrant'\""; + config.vm.provision "shell", inline: "systemctl restart mysql.service" + +end diff --git a/vagrant_files/newts_cl1_rf1/files/newts.service b/vagrant_files/newts_cl1_rf1/files/newts.service new file mode 100644 index 0000000..ceae9a1 --- /dev/null +++ b/vagrant_files/newts_cl1_rf1/files/newts.service @@ -0,0 +1,10 @@ +[Unit] +Description=NewTS + +[Service] +Type=forking +ExecStart=/usr/bin/java -cp /home/vagrant/newts-1.3.1/lib/*: org.opennms.newts.rest.NewtsDaemon -D -p /var/run/newts.pid -c /home/vagrant/newts-1.3.1/etc/config.yaml +PIDFile=/var/run/newts.pid + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/newts_cl1_rf1/files/newts_cassandra.cli b/vagrant_files/newts_cl1_rf1/files/newts_cassandra.cli new file mode 100644 index 0000000..6f9f2cf --- /dev/null +++ b/vagrant_files/newts_cl1_rf1/files/newts_cassandra.cli @@ -0,0 +1 @@ +create keyspace newts with placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' and strategy_options = {replication_factor:1}; \ No newline at end of file diff --git a/vagrant_files/newts_cl1_rf1/newts_cl1_rf1_0.vagrant b/vagrant_files/newts_cl1_rf1/newts_cl1_rf1_0.vagrant new file mode 100644 index 0000000..0902d91 --- /dev/null +++ b/vagrant_files/newts_cl1_rf1/newts_cl1_rf1_0.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 1 VM + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/newts.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf1/files/newts.service b/vagrant_files/newts_cl5_rf1/files/newts.service new file mode 100644 index 0000000..ceae9a1 --- /dev/null +++ b/vagrant_files/newts_cl5_rf1/files/newts.service @@ -0,0 +1,10 @@ +[Unit] +Description=NewTS + +[Service] +Type=forking +ExecStart=/usr/bin/java -cp /home/vagrant/newts-1.3.1/lib/*: org.opennms.newts.rest.NewtsDaemon -D -p /var/run/newts.pid -c /home/vagrant/newts-1.3.1/etc/config.yaml +PIDFile=/var/run/newts.pid + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/newts_cl5_rf1/files/newts_cassandra.cli b/vagrant_files/newts_cl5_rf1/files/newts_cassandra.cli new file mode 100644 index 0000000..6f9f2cf --- /dev/null +++ b/vagrant_files/newts_cl5_rf1/files/newts_cassandra.cli @@ -0,0 +1 @@ +create keyspace newts with placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' and strategy_options = {replication_factor:1}; \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_0.vagrant b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_0.vagrant new file mode 100644 index 0000000..84dc43f --- /dev/null +++ b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_0.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/newts.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_1.vagrant b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_1.vagrant new file mode 100644 index 0000000..3d7d644 --- /dev/null +++ b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_1.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_2.vagrant b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_2.vagrant new file mode 100644 index 0000000..05a4b3c --- /dev/null +++ b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_2.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_3.vagrant b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_3.vagrant new file mode 100644 index 0000000..6f1203b --- /dev/null +++ b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_3.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_4.vagrant b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_4.vagrant new file mode 100644 index 0000000..5c9274b --- /dev/null +++ b/vagrant_files/newts_cl5_rf1/newts_cl5_rf1_4.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf2/files/newts.service b/vagrant_files/newts_cl5_rf2/files/newts.service new file mode 100644 index 0000000..ceae9a1 --- /dev/null +++ b/vagrant_files/newts_cl5_rf2/files/newts.service @@ -0,0 +1,10 @@ +[Unit] +Description=NewTS + +[Service] +Type=forking +ExecStart=/usr/bin/java -cp /home/vagrant/newts-1.3.1/lib/*: org.opennms.newts.rest.NewtsDaemon -D -p /var/run/newts.pid -c /home/vagrant/newts-1.3.1/etc/config.yaml +PIDFile=/var/run/newts.pid + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/newts_cl5_rf2/files/newts_cassandra.cli b/vagrant_files/newts_cl5_rf2/files/newts_cassandra.cli new file mode 100644 index 0000000..10b6c07 --- /dev/null +++ b/vagrant_files/newts_cl5_rf2/files/newts_cassandra.cli @@ -0,0 +1 @@ +create keyspace newts with placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' and strategy_options = {replication_factor:2}; \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_0.vagrant b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_0.vagrant new file mode 100644 index 0000000..b4a73e0 --- /dev/null +++ b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_0.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/newts.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_1.vagrant b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_1.vagrant new file mode 100644 index 0000000..7919c9b --- /dev/null +++ b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_1.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_2.vagrant b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_2.vagrant new file mode 100644 index 0000000..65f7034 --- /dev/null +++ b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_2.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_3.vagrant b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_3.vagrant new file mode 100644 index 0000000..b85b92d --- /dev/null +++ b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_3.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_4.vagrant b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_4.vagrant new file mode 100644 index 0000000..ecfa7e5 --- /dev/null +++ b/vagrant_files/newts_cl5_rf2/newts_cl5_rf2_4.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf5/files/newts.service b/vagrant_files/newts_cl5_rf5/files/newts.service new file mode 100644 index 0000000..ceae9a1 --- /dev/null +++ b/vagrant_files/newts_cl5_rf5/files/newts.service @@ -0,0 +1,10 @@ +[Unit] +Description=NewTS + +[Service] +Type=forking +ExecStart=/usr/bin/java -cp /home/vagrant/newts-1.3.1/lib/*: org.opennms.newts.rest.NewtsDaemon -D -p /var/run/newts.pid -c /home/vagrant/newts-1.3.1/etc/config.yaml +PIDFile=/var/run/newts.pid + +[Install] +WantedBy=multi-user.target diff --git a/vagrant_files/newts_cl5_rf5/files/newts_cassandra.cli b/vagrant_files/newts_cl5_rf5/files/newts_cassandra.cli new file mode 100644 index 0000000..47d9d78 --- /dev/null +++ b/vagrant_files/newts_cl5_rf5/files/newts_cassandra.cli @@ -0,0 +1 @@ +create keyspace newts with placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' and strategy_options = {replication_factor:5}; \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_0.vagrant b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_0.vagrant new file mode 100644 index 0000000..fea33fc --- /dev/null +++ b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_0.vagrant @@ -0,0 +1,17 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/newts.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_1.vagrant b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_1.vagrant new file mode 100644 index 0000000..1912e3d --- /dev/null +++ b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_1.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_2.vagrant b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_2.vagrant new file mode 100644 index 0000000..7620c1d --- /dev/null +++ b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_2.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_3.vagrant b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_3.vagrant new file mode 100644 index 0000000..5f7d0fa --- /dev/null +++ b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_3.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_4.vagrant b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_4.vagrant new file mode 100644 index 0000000..1335639 --- /dev/null +++ b/vagrant_files/newts_cl5_rf5/newts_cl5_rf5_4.vagrant @@ -0,0 +1,16 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# NewTS with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/sleep_5.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/opentsdb_cl1_rf1/files/lzo/hadoop-lzo-0.4.15.tar.gz b/vagrant_files/opentsdb_cl1_rf1/files/lzo/hadoop-lzo-0.4.15.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5fc59673b686807ab82e366c6b005725f13c6575 GIT binary patch literal 156334 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 z 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

<0CA;po?>t>ai#b72~Xz%7|#a_ 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 z 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

<0CA;po?>t>ai#b72~Xz%7|#a_ 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 z zqA~$=sJw1xxGl8qDIn7ihOxv%*}(Q7b@FgfGgSgwwx?cW4^n$+^6=iYDoGyVWN*YE z+y_s@=-X45mZW~^GIan&yhM9{kEwbCJf?OWm}3Hf8Mz1HOYno!<*Y<(`hukEiio8l z9w{qP!3W+PD8MsWoII}=5{6-c9Oy{tDRD9iA}O_fwG03jM_j&IhMd|`1Qi}h(J;}5 zf^>$A>e47Ki+Gt%Rlo!@U7p;VyF;sUEv-(b;S(CoGQ2`CJI4Z!&ap7(P+Qj&K~Ls# zyD($38)LqYHB(Bh?J~|(5%6uisUiSQ$kDq7E$5j)piX4Eko%f|U)eRRPM$06XX6x^Rny#n4>e)|gT6Z}X>(O$#*zg7sBP()^88 zV{)7|W2K~;riQf2P-9bbprxfQ6ilzh7ARX0DrUG)b9yBnGSL#QstQyC8JaD;yeZHE zMVR4$)w&QAA%iC_Zmnwwr_}|?GIM>f&evE4lqgcB1+Z8d3Zj;1qLGVMHB?syX%VoX zla_%!YZ+yRF-+mdcDpiVHA6k?oV)Y#N4r|T!qeHJ)G)cY;?#$*;A)#eF0tuPKIc|k zdn6@K4o^}O^I98~ukLZJP`j@{;pgyAX{~GF=4X|mi54q^Xu;*1 z;TooTx3uKnIJ0h{dQchBa}DKti1NiNLuJC){D&24je4_s)91xxmsHLg=iJq^~+=s)H=PR4A!( zBr(bn3!+wz@jVR1aY~k~r1VtpQ$|4!eS%Ap(hZ$i<(ySh0+s(4qat#i! zEt=u-(tKGc=F4~?@VnXqKTGFO#zAb?hZffdD#LRE)fLcn(wsm;z~2%mZ?0>s!ze9m zZuT!PZiaHDzd>qk2{ezE&I~L)JK$e3y&<&N-vEMAvA?0AXn8m=D-f;?RS~W%X?h?$ zts&$O6Ae=v0*!$ngeTIni9m6!znKaYO1_rbP;+>3D^+!7DA-ol9B%bncp|10##R+i zsxp!dB(~GWEIYbb@C_EqX#22crZV7}jgndSC{Gu@+L%dxp9DeW3OfpF@MBqW#!=5OFBqZ!h!kS>fKtjX{ z4ns28NM>SY5*8Iv!4iRr)`hlOaV=JDsilfLxMJPVy4Gs3S_SKZ3yK^0&bjxVx7_yz z)b{)R|G)3cD0%lR_nvdlJ@?$@y?0+NGDJBDVym#E+4Z5uYGq}lWd+a!O`)bp%WBN1 zl!Kijt;-vE%P$PoLf^-%ScbhROQI#=Xe=163Y}h~%na4kheI=%wzFFzP2d)dV6;#* z7t~N=xB^pgC3sYbDJdMT938-3KAN*WTptV6w1%q!%`x5>jM4C$n#N#lREe%`S{`Y% zR4@{OLc?4%%f!%?k@{-UiVe~FH6g4kr(oqQ+@^?1jAEcjo)TyZwyX$&85@>^`FKr0 z;B*2EwXL=i<}+2W6)m}BQFS#oztYeaY-}}pqNOnm5oUR!reqJSkYPw6JZw5;s5*ek zN0p{%ZJ;p}c6fJ@X%a4%8^theX(U|BQBYi{r7cvQYZ7@8B{L0Lp5&)?NwdPy)|OCd z1mcR(8Rtcyy(2BN!ZGN2hAKRt**?~Cm=#OHF-IGivB%K}SPM&Uc2}@cX;=wC&XNtJ z7=G6ri7IpFmz0E|t?H{Oct&F_@IQ0#Xs|6rozSX(Q6mH!j<8Qr1EMd^V_gwEf_WEj zUPtA4w_a2+yEGK8jnyelK`hp^7^}Q#Fv&|AShSVuZi#8Y(Fi8uK5pxUF*IbPEz|93J+}2DFYQqU&-Sk=w1RkMRH+tXk3943}ugW^IQj87@)Ds#Mbw3h`)V z)XW(+&1U7o(M-V@bOjuL%-(DED-gmt12y%~X(LKST}x!8G}@TWV>DO{B6Lxd6^}g` zg0d2-YUBp7gu?1bpt=zvsN{}~R!FG{mw{tr(1c4Y%XxYYTj7YjiHtnP}g1+7(>^rVROo`)1%BzW7wHT z6nXTp>J8&;IJ7FJGz6)Sw}h_v3REgMJws6eK0yjt zmK^AV0lQA<*d;TgN*KEuT9ZP*`xwh?*4z@QWo;tb!0MWL0JH7{MM>2lPYyIiV14A$ z+i*rwPSM@k#}%Md*VoiQ+2z(SgTBgV5z4GpRiS3=uBTU3wYIc`s!c~WCOT#$r^bRN zXX7Qcwi#_PmKp(r8Gwr{YmL^iEVEmJO)Qu(JPgut<`D6t04Q6^ocj2~R%s~g8gj*` z!yAj-+w5bONNRT$d$((dvc|yz%Ms=+E6&uQeOpN zu%)VQ3M`jLA+a`N)ak%jQ&uv=G8Ls*UrGa?ZL(!mLMe*Hf>m`hu-U>fa2{y1qUg*Z z7$B^Ks9gj2bRTB5Og4;p0Tb3xWds5m1>Ht_S649oX9nbG5$3Q43tY>XGe=`W#4QGX z#3Q#TZDq>}SOH)ji!&<~5n~c>nJt+iT8=B$i1XumbuHL^O{BDbc}uWmbtO!)u?Ep_ zGc4#Mn}UGn&448P>_OM!bxDN<~8 zVLd`xG{g^gXkzNYN|*wZ*>kCL&T$PZ<@O07jereJH1RH%rWS#=7!LikJ{4}}bn$ZM z%Fw<-uXLR~7b&xYv0&pYHsoTfw(+K8Ar!=D?5|l>hZ=D$XqfT3nDh1HY2=P7RXZ>OGLIT^;y(p@!c-b zy-ApotWdEsfN{!P{8h7YoGtU`xGWXQ-B+&GxMM_)5?rFy1gk;;EQ8n1Kdj!CHyUhz_P#n-iRdYD-LXvv(1jgwuRq zQmoptSTD!@16t_jC}J0l7hGfP2oVF@Gc($o0oLhJ7{}&vm*LxRD$$zphsGjuawDTl zsIYfx`#udd@Q>=HM8&E_`7F^gG}VQwT-VPE+i+7FVmR@_0L2y-F`B=+R}dC67D@(vjr zlxe?%w$Q}+VjcdUrUZ)m18UuaSc%Jx)}@Ao)vCWVs-UVqbc0# zE;YaC6^?zrc*<7(5G_%GIQKcEVXsJPdCM*p*Au%J*30Hy23G)_w>~WPz>Pj??zA7T zOBdM|B{bz@+uri_s&g;c>RSO=XF|MgY;6kLXVK8n-J_Lr+k=hoBC?_zj?D*01mm_w zakH0hJ@C~HA8F&>sW8V``JSTNz5_bc4;Yzj#n4s((yBw!+TGYGvr?i?RoKqakG+v2 z-66G#_#u^b*BHa2oY|NuIk;IgwU-l!Ir2B!;U8^c*LB-ZX(xwf?j82W7HwAEIze%8 z$OY<&CFDZzJOZN){TZC6u)4vB1z{gULwAt89z}-DEOS z@_>y|)++Ods`6h;_$lomH?zBiof3Yy$Nd0Dl1-#3ISy+ej?z1fqRJ>~mcB$Tohn{v zu#{1<#6VS2a=yt$DqL%#C~1nTl*QdIu6xW}lr(cKRiqzz`U*1_B~90K$f5#2HCPr= za*sx+a!NiXuDo3cI@Mz^QgW<;T13fl9&6rsdVFc)VP(jH= zqpT%~E(%u|3WrR_kVD}LH-#$5GWgIrx=VU)}w-wgN)+K2f64`Vdyc(WSrxoM}?usoqmInk}vzMj0Bkq zJH~8M_%=h~1(c**?)~R^!S$lqx|D49@vEj>V5AF#&K{+0_u2xa57F<5uM6_!VgoWi^`>X?A+ZGlqu*%!)j)mVj!bJ<2HAVC5sgY`3zA z)Dsw=tQ`63W>Yyzh7FGkERa+K6nR|0@VJ0n_N}6z+sv|Wb5?wZTgA7nb0#u`ZQJ}UnVt4or9T59R^ zQ)-BFOtF;AH}nrgq;Lo*Y8$gkjyAee6!g8g;vh!pE=J*oFI{1}7bUMYP>Wv>@{T5( zg;Dx@!%xa6IU~hnqqM22W8nOiQ0F#NElS>RpcdXQwJcb4tHYv$gwDBUbtpN*KrN)C z#V?&jT_~B|10lo_0yYTZem~WCrICKwz@4{D&PPMsU8bIQIhxrqzR4vKpcYb++}m9%LHv_h z6eVAXKS;hHd8=#Gpe@Q zy6jlxnmbmxE!j43xtgcM8%oX2Fy!H@6chdA7N)Mah6|JCUFZ&AgPn#>`8}ZMM7w z-C*XWf|B{>_FcY*I&yUeZX3liiiIA#uwf;-~WH{#TH-*NRl&URS4C~LE+?`ElZw)f!T8_pdCs^MSE z!YKK$xfe)%;&T&4O?rW84>FC}qz)62PaHGFQF5)gqEl4|!K#{C?9Ss5Gm0NgT}}~!neMXE4PW{9&5z`NP~bbHdv$4E zcm5x%|9GL#c4_%>vov+4<$(MfAoN-&-Gp2gr#?z{bahiKxE!vr7JjXxR5%g~W!HvV zv)Snbqw1>_2Gs?lbxL;i>M*`g$*!>$PN8Srtv~>1EuqFBGKy4lV@%0rk3?n1@D0Ok ze8vlCk?LS9sAPxg0yX$3YM`#V#e{f{0Dl>g<)Cy!6|iAeEFDT=It82Rt3Z!PjQ!yv zdGX7mQ6;-7(!^dj$*vA9Z^bu!gW=jxl)(CMO~fEAU)~aGBdD=H9HKOK1C@!*$v-C**MG%f0DAz6`!hX8|j7zB}cj8K^Zy_-iAL}@w?)?DQT|w?n??4?_f!tM;(IBJ$GYLum1VB@-VPkc_lbk=8wcMn4!(aJ{D3(4fpPE| z4jj6-SNXI<#&=;fr~R>}nv4Hr3;a3>UnKDRCHxtzeAAxP&1zWM=?_~(IceSO<@}2A zJN;^RoOeB|n=tX|#I5o`6%h}(P!@I>qx>n%V z=^UOU0?n_z?)vW({PMR5j(FYc<@IrX`9m#}eeUI##lcsLa^x>w{K|)RNLSLw*`@zh z;AMOM-si68L!x~7I|<$dcm4qh?t11XxNP#lZyw`!&O^%Mlv5iAe_jIDbB}08V|rB8 z5{t%KYihEqlt5tajD>;HlJbf`K&cMV*&u;fQ=qCb5{3z%3n~z(js$Ai>uG`NSfnKy z2)3?buU6w*XVuwb$BxZ)X9}3}+W<^cTUIN4MqJ(6)P(P)SfGG8Ef%cuF_!m{4b7qIKlZv@>{<0kuc6TW!zuCiTl>e z4|$j72fkeN!`?qR;hQ5Tdcnr|#!(9c2-&#DMi6iqLk6;SYGl)}O}r6tp61oE=;vI~?zNyWT? z*)gF2?1L5T&D%hTt^9u4DJ*f%yuN0Df};n?A6c8WO9=||h;L}!cq*T24EETnA*+OMGNP>EmOhQRgNmmM7u z%1`?mbX_L!v@<1dKj610QY`Xm|07-6BJ&C!%AYQ-g`#XjzSn;JTG~&Mw_WggjSh?c zw4XxP@sj?Ubj3U3$1M42--WJ)io5>wtG3YaNBc8$Ei?8_`A@EYSmd8BVA{u_>tT!j z$u9ZvYdUBXF|9S`S#*_m8szqmO8IGDh^{*&{xs>jR?1K7f4a`;;hvv<>!tiOf2V8G z3G}~I$ED=lAe0RWbd; z*ssWO=a=ET;a^uve%c@L|G@l@2>mHPts~QZVE!ki{IuRL6#2JFTiS(E{+ATq_QXc( z&)3Fq_^@awvOCEqKYCM=Py2cM#1}bfYhTu%uK$wq(|Y!>$X|DY{Qr^i)4F=`SUaDb zpMIYT9Ob8V+cJ@V_X+ZUDdgu!c*-yD5USF(LvhAb{GBiIFN>3(eyOT^{x?PbKI@O4 zzfYX}U)?9J33j~9n;9qn$9ws8<_YrWtM2y8+sCh2k^yD=O^YM{tbgN~%dz7iH z?;G<&fzRw~@)W{sJpuj>RR%F$-*L*{HQIiq-AZFFNsVmGr}%Z5h)3y(_I#SiNAnJI z9>T9Q51}i?L9h5Hue;>+*H8;T{>uIxtH!iE-<0Q_)l$9%kWUJ!$NkYf3G?Gr9AovI z`HPgZhAjU5-EaK!Uhj^>n-9Kxde#Nsf55)Ej&z()qCL<=7iDZqN>jX9$=(e0(xFNr z(r`;2@Aplg_40??W{AdCSGe5$HGgjRtN*UL?+4>HaE1%MU3I@dfYSlDa@08G{5cN)eR1$- z#VIE*4t`~va!M8Vee{ds*dY?9oQE{``zn7`-0yqbsJh>;ctLZ&&v3rtet)J=b-&;8 zPu2ZC#^aj%{faX+_xloGDem_Z(iHdmKRq<}`!?SzaqcHbdux0H@wgk8ad)5WTTQMT zV02D6-~0b*o1fxvQgQUYaa!$9*s}Z|Y-s)WTdm^T1#!1@f9h^0JE;37ZDsx+IgQGF zs}m+r4Q)+0Yl2jDBP6o(Fjne<(n8Jjs>Gw3uv8|!-!)cg{jo);;U`NcQF%Ov~&fnO%! zM+m+=cz;BI%-yR3QQ^E%XevgE27Wn-V{z8F2AmOhN_`?$ZCV^LS?f6{+ zpC;iS7x)Yb|BArpNci^!zEHv+CHqVGWU&FWOv3jU_~tnHb#d@pCHzQ%-!9>&2>eb7 zKVRVYNce!j@0ak+0)IflUnua0CHxh%;gn~`-z4y95`LG!XGr+R1wKc@zbf#B68-~$ zFO%@!lKmxoYL=*m+=xz;BiCGX#FSgkL1^J0*Ob!0(aps|9|)gx@Ui2PFLU z0#DD+82%tWVeXgklLbCa!p{@svEcnezV+T9{?aUX>%EM03*Nf!&amLE zdS+Vi)>|w&7QA(@db|anV!;<$@K*hcE%=ix_%aJV)yjYIhyLPCzD2__l;RD0V!nf? zG2~)NtU^$RFhE>Dgt^*4pg)rOQKXjl2e#3r-FivL{CkgiirWtt?>#uJSbd`Sg=4XFC@fbL)`b_w^ULL}o6-(!O6!Q?i>D-F zY7vwd>r%XFN&`R#`-92{i{a1GCw$8Qp?>bv=j;9;=i+HfYs#Usfs^YE@^2f$-q;(G!aNSDbx*(s5j$96t>Qb zXe?q2pfH+uAE%rz(Id@OTi|xL>fJVQ26ywap2O(q}eCyke4)Beb!>KrkqKY@IL(j7GU*3Pdfc{hU_u{?p zc#GS=FK+*P@s|EK^~vDDQvF-$rc)2DXA%o^Ubk0KvGz|6uKkWxs_S~Zi`9_R;4iut zBUOVRQtZhL2HuA$+-OoBUI!7OV?Xql4Cu(^#hYef-wv)Qz5baEg*ov zJG(FA*x@pDG`M3WI{KL$8f$Wv198-FShq%C7Tj}crGKpRoebl z$JV175+3J-pIHbQpltgFjH^fk18vgB3`8r4Oi+5Em6%FIo-yA_`_}*qZAx!w;r0!s zz|eI)`Zt&ThXJxuPjbSY7DA?n3C`q&gMArx9}IQiF&l>P!XV%=G#(+wt456b1!D_@ zws{*q>bib`DstEh`k6;)^%tz7QJ7g}xj=jiulV8zkqVLXTgA21^&WvfW>N1+m(t$w zpn71PyU;tTm@O}S5DkW=E3LW(TLqLUV)8*0F0N%@(7!1w^$VHa6zk8?@Y7g@Vv))&vuzKH~;#TkT4O!(W za=p`kV!aQ1=W73CuE)u)dK~$J^msa1)+6xUPt#)r{A4bFh^zb~pBwd0vdD)h-gP|=LZ*BkKe%8^IAIcZeT!|+#~I%5q0@^%!25pj zCKgXS_8;D4L!?Rxrz{GZG#1>7sO+3np=% z6blc{I}M(bc=z!;c@Fg=9(;Qrc)m+;&N~gB$GICmB;JJsF^R$yEWbi!9c{V0H z=C7-Ju{qxR2{eDr1jNC29P`(bUXJyhvuvUAIN&bKu@jasv!6`lgnTM(mqt6y9MHR60y{8*2U10|MA~tLLks&4ac=nn4^aPP2Dhx2H~AjX?eotqz8xn+ozWOD z6D_LbJ-VZu&pLOonYDL6lzgEcXWEH#(h6NnBRXh?_XH=5u@Ly|v6Kb2L_T}$qGRPc zEOS-N^l=Y4Q?WJElRZQxF=gZvw?r1FI?OrQ0XEG^WK+ft%aqYzq&e9*nlkpJ9QJ}P z(**iUOF>V#6!bAG=*zC_pXHM~HkYgVODUU??Gf=6)*5Ww-~+`brhUhLXw`Gg$%5|X zlZ6XE#N9NUFDPD`FWmbPH^r8M%h&?1!!}4QG~VUlc;_>8enYeA4CC!ZeBPHsEsW!B4zp8-G2Z4-3wM~~ z?c8Iw@%9)G9ynWf%HQxI$v?{>|Ml;Gn*1BSx5;12<&SZd?=$4Tp<3j#@&0L>eC|>- z-WwifNOagefy=#3b(6d0KP0zGmFs=VPptQ65QO+r-`oaOW(33GNGzi<60FV;@5S+( z$it!;nZu%4gOt*SU|Vo>V=!Dhnmwg3N#Sq5{Y()r9Gb7aG0t#(WHjEQ=5L=(QrzEI zD{;r;D{qdM*XAnrR|MT&3Uqr7(D~w@`6*Z>5HP++-N6wn7$rsdp<##9jtE* zRcFK^8Tg^djA2m=rZr4B<52~cTFp{m&X!QDwIv*?o|rL=eRwq2xaZFy%cBhp5tKoh zVYv+E%7{D}F-At@%ZLIQF;+&5lM&-(ghNlK<`ZO8l?>*}h&&lFMn>ezhyocgRz{4I z5#wcqLr^=?+SfRFR>?eoaANWtm;xE&D0#J9@@gl~8V4#bXh-p%*)JA_qrq5x zw5C2(U0NSr!MletBhuPfoq-_)yHY)SvMB>f!(f7sy9}~M1rZVCmrqNbFQevKo_7)6 zFCms64-tq4YeJ%NB(|y(vITl*3Ss)N z1D39<@cKnZ2Oep*8?Fb$%~pEtOi8~{iHPZ`X5F2V9H_Ih4dlT*`+ zSdLjKS{0=mf%O^qxAXmu4)(05n;wf(a~e~}Pfsl@PA#6ETDB}TN1F>;6j}6|lcFt< zP$eld?Fh2lWRSBC+Q52W8TGFK{3^h+XG%f6OSBm$B}~7}bJj1sTYQ@nE>85U*OI}` zr=^tPg?$DA?YJ5B{^WmW$A3V1TcNyXR2Msz*z8!Jnm&`IQ4f3;H4}X2h(h^_F<%kp zi>78yPt7T2R$P{vvDzqPZc5NdFG(q)B-*K3y88}0)P*w5h65`C&fFEd~b-w(FI*lbo9 zZ@LF8Fy?QT;0q=A3JJbRf_F*q;}ZOe1ivrAN2U7Eb9DIT6~g^9O@6GO6~_8mVXWUs z3yk@vNbr0K4oGmb1Yan@S4i+p61+=-A2(oLKYFeWPb5e91Bw4ziB8Y25uKh}!xu{s zrsvg^bsU~y@Ov4&$bb_WTql*cTB2{3;OnLG6zNCLq0w_^^qd(zS4Pi~(Q{+;oESY9 zM$duKb6@nF7d_WS&vDUnTlAb3J(oq#VbOC}^qdtvS4GcJ(Q{MuoD@A5MbAOeb5Hb~ z6Fu*Hy=I4RlVE!9nV!*kMZolo4?Vw6&-T!B`^JfR;<;8j5s#iFqW9V9x!`^h{m8Kn z_C^_HS9ey

<0CA;po?>t>ai#b72~Xz%7|#a_ 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 z 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

<0CA;po?>t>ai#b72~Xz%7|#a_ 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 jq> /etc/postgresql/9.4/main/pg_hba.conf" + config.vm.provision "shell", inline: "echo \"host all all 10.0.0.0/24 md5\" >> /etc/postgresql/9.4/main/pg_hba.conf" + config.vm.provision "shell", inline: "systemctl restart postgresql.service" + +end diff --git a/vagrant_files/rhombus_cl1_rf1/rhombus_cl1_rf1_0.vagrant b/vagrant_files/rhombus_cl1_rf1/rhombus_cl1_rf1_0.vagrant new file mode 100644 index 0000000..b1aa058 --- /dev/null +++ b/vagrant_files/rhombus_cl1_rf1/rhombus_cl1_rf1_0.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 1 VM + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_0.vagrant b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_0.vagrant new file mode 100644 index 0000000..fe4c483 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_0.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_1.vagrant b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_1.vagrant new file mode 100644 index 0000000..56b0702 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_1.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_2.vagrant b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_2.vagrant new file mode 100644 index 0000000..1dde733 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_2.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_3.vagrant b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_3.vagrant new file mode 100644 index 0000000..2eedb3b --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_3.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_4.vagrant b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_4.vagrant new file mode 100644 index 0000000..716e14f --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf1/rhombus_cl5_rf1_4.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 1 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_0.vagrant b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_0.vagrant new file mode 100644 index 0000000..fbede16 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_0.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_1.vagrant b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_1.vagrant new file mode 100644 index 0000000..21a68f4 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_1.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_2.vagrant b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_2.vagrant new file mode 100644 index 0000000..3fcf76b --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_2.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_3.vagrant b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_3.vagrant new file mode 100644 index 0000000..158e105 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_3.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_4.vagrant b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_4.vagrant new file mode 100644 index 0000000..cb33364 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf2/rhombus_cl5_rf2_4.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 2 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_0.vagrant b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_0.vagrant new file mode 100644 index 0000000..7a56a48 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_0.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm0" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_1.vagrant b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_1.vagrant new file mode 100644 index 0000000..5b3f560 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_1.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm1" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_2.vagrant b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_2.vagrant new file mode 100644 index 0000000..4a5890b --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_2.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm2" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_3.vagrant b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_3.vagrant new file mode 100644 index 0000000..fc917f4 --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_3.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm3" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_4.vagrant b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_4.vagrant new file mode 100644 index 0000000..4c63def --- /dev/null +++ b/vagrant_files/rhombus_cl5_rf5/rhombus_cl5_rf5_4.vagrant @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Rhombus with Cassandra on 5 VMs with Replication Factor 5 + +VAGRANTFILE_API_VERSION = "2" + +HOSTNAME = "vm4" + +load 'vagrantconf.rb' +load 'vagrantconf_db.rb' +load 'basic/change_hostname.rb' +load 'basic/update.rb' +load 'basic/cassandra.rb' +load 'basic/copy_files.rb' \ No newline at end of file diff --git a/vagrant_files/vagrantconf.rb b/vagrant_files/vagrantconf.rb new file mode 100644 index 0000000..4438c62 --- /dev/null +++ b/vagrant_files/vagrantconf.rb @@ -0,0 +1,30 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.box = 'dummy' + config.vm.box_url = 'dummy.box' + config.ssh.username = 'vagrant' + + config.vm.provider :vsphere do |vsphere| + vsphere.host = '' + vsphere.compute_resource_name = '' + vsphere.resource_pool_name = '' + vm_base_path = '' + vsphere.data_store_name = '' + vsphere.user = '' + vsphere.password = '' + vsphere.insecure = true + end + config.vm.provider :openstack do |openstack| + openstack.openstack_auth_url = '' + openstack.username = '' + openstack.password = '' + openstack.tenant_name = '' + openstack.image = '' + openstack.floating_ip_pool = '' + openstack.openstack_image_url = '' + end +end + +# links to prepackaged/precompiled stuff +$links_ycsbts = 'http://nemarcontrolvm.iaas.uni-stuttgart.de/bin/ycsb-0.4.0.tar.gz' +$links_blueflood = 'http://nemarcontrolvm.iaas.uni-stuttgart.de/bin/blueflood-all-2.0.0-SNAPSHOT-jar-with-dependencies.jar' + \ No newline at end of file diff --git a/vagrant_files/vagrantconf_db.rb b/vagrant_files/vagrantconf_db.rb new file mode 100644 index 0000000..311610e --- /dev/null +++ b/vagrant_files/vagrantconf_db.rb @@ -0,0 +1,8 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.provider :vsphere do |vsphere| + vsphere.template_name = '' + end + config.vm.provider :openstack do |openstack| + openstack.flavor = '' + end +end \ No newline at end of file diff --git a/vagrant_files/vagrantconf_gen.rb b/vagrant_files/vagrantconf_gen.rb new file mode 100644 index 0000000..bf01a7b --- /dev/null +++ b/vagrant_files/vagrantconf_gen.rb @@ -0,0 +1,8 @@ +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.provider :vsphere do |vsphere| + vsphere.template_name = '' + end + config.vm.provider :openstack do |openstack| + openstack.flavor = '' + end +end \ No newline at end of file