Add an all-features template to the cluster deployer.
[integration/test.git] / test / tools / clustering / cluster-deployer / deploy.py
index f9927cc0a165f1f19558f015324751e1ac927299..102742f03512e04da1bfed2790dc4cd4b1c92ef0 100755 (executable)
 #
 # The input that this script will take is as follows,
 #
-# - A comma separated list of ip addresses/hostnames for each host on which the distribution needs to be deployed
+# - A comma separated list of ip addresses/hostnames for each host on which
+#   the distribution needs to be deployed
 # - The replication factor to be used
-# - The ssh username/password of the remote host(s). Note that this should be the same for each host
+# - The ssh username/password of the remote host(s). Note that this should be
+#   the same for each host
 # - The name of the template to be used.
-#   Note that this template name should match the name of a template folder in the templates directory.
+#   Note that this template name should match the name of a template folder in
+#   the templates directory.
 #   The templates directory can be found in the same directory as this script.
 #
 # Here are the things it will do,
 # - Copy over a distribution of opendaylight to the remote host
 # - Create a timestamped directory on the remote host
 # - Unzip the distribution to the timestamped directory
-# - Copy over the template substituted configuration files to the appropriate location on the remote host
+# - Copy over the template substituted configuration files to the appropriate
+#   location on the remote host
 # - Create a symlink to the timestamped directory
 # - Start karaf
 #
-# -------------------------------------------------------------------------------------------------------------
+# ----------------------------------------------------------------------------
 
 import argparse
 import time
@@ -40,22 +44,31 @@ from remote_host import RemoteHost
 
 parser = argparse.ArgumentParser(description='Cluster Deployer')
 parser.add_argument("--distribution", default="",
-                    help="the absolute path of the distribution on the local host that needs to be deployed. "
-                    "(Must contain version in the form: \"<#>.<#>.<#>-<name>\", e.g. 0.2.0-SNAPSHOT)",
+                    help="the absolute path of the distribution on the local "
+                         "host that needs to be deployed. (Must contain "
+                         "version in the form: \"<#>.<#>.<#>-<name>\", e.g. "
+                         "0.2.0-SNAPSHOT)",
                     required=True)
 parser.add_argument("--rootdir", default="/root",
-                    help="the root directory on the remote host where the distribution is to be deployed",
+                    help="the root directory on the remote host where the "
+                         "distribution is to be deployed",
                     required=True)
-parser.add_argument("--hosts", default="", help="a comma separated list of host names or ip addresses",
+parser.add_argument("--hosts", default="", help="a comma separated list of "
+                                                "host names or ip addresses",
                     required=True)
-parser.add_argument("--clean", action="store_true", default=False, help="clean the deployment on the remote host")
+parser.add_argument("--clean", action="store_true", default=False,
+                    help="clean the deployment on the remote host")
 parser.add_argument("--template", default="openflow",
                     help="the name of the template to be used. "
-                    "This name should match a folder in the templates directory.")
+                    "This name should match a folder in the templates "
+                         "directory.")
 parser.add_argument("--rf", default=3, type=int,
-                    help="replication factor. This is the number of replicas that should be created for each shard.")
-parser.add_argument("--user", default="root", help="the SSH username for the remote host(s)")
-parser.add_argument("--password", default="Ecp123", help="the SSH password for the remote host(s)")
+                    help="replication factor. This is the number of replicas "
+                         "that should be created for each shard.")
+parser.add_argument("--user", default="root", help="the SSH username for the "
+                                                   "remote host(s)")
+parser.add_argument("--password", default="Ecp123",
+                    help="the SSH password for the remote host(s)")
 args = parser.parse_args()
 
 
@@ -71,6 +84,9 @@ class TemplateRenderer:
         if variables is None:
             variables = {}
 
+        if os.path.exists(self.template_root + template_path) is False:
+            return
+
         with open(self.template_root + template_path, "r") as myfile:
             data = myfile.read()
 
@@ -85,8 +101,8 @@ class TemplateRenderer:
 
 
 #
-# The array_str method takes an array of strings and formats it into a string such that
-# it can be used in an akka configuration file
+# The array_str method takes an array of strings and formats it into a
+#  string such that it can be used in an akka configuration file
 #
 def array_str(arr):
     s = "["
@@ -102,8 +118,9 @@ def array_str(arr):
 # The Deployer deploys the controller to one host and configures it
 #
 class Deployer:
-    def __init__(self, host, member_no, template, user, password, rootdir, distribution,
-                 dir_name, hosts, ds_seed_nodes, rpc_seed_nodes, replicas, clean=False):
+    def __init__(self, host, member_no, template, user, password, rootdir,
+                 distribution, dir_name, hosts, ds_seed_nodes, rpc_seed_nodes,
+                 replicas, clean=False):
         self.host = host
         self.member_no = member_no
         self.template = template
@@ -118,17 +135,29 @@ class Deployer:
         self.rpc_seed_nodes = rpc_seed_nodes
         self.replicas = replicas
 
-    def kill_controller(self, remote):
-        remote.copy_file("kill_controller.sh",  self.rootdir + "/")
-        remote.exec_cmd(self.rootdir + "/kill_controller.sh")
+        # Connect to the remote host and start doing operations
+        self.remote = RemoteHost(self.host, self.user, self.password,
+                                 self.rootdir)
+
+    def kill_controller(self):
+        self.remote.copy_file("kill_controller.sh",  self.rootdir + "/")
+        self.remote.exec_cmd(self.rootdir + "/kill_controller.sh")
 
     def deploy(self):
         # Determine distribution version
-        distribution_name = os.path.splitext(os.path.basename(self.distribution))[0]
-        distribution_ver = re.search('(\d+\.\d+\.\d+-\w+\Z)|(\d+\.\d+\.\d+-\w+)(-SR\d+\Z)|(\d+\.\d+\.\d+-\w+)(-SR\d+(\.\d+)\Z)', distribution_name)  # noqa
+        distribution_name \
+            = os.path.splitext(os.path.basename(self.distribution))[0]
+        distribution_ver = re.search('(\d+\.\d+\.\d+-\w+\Z)|'
+                                     '(\d+\.\d+\.\d+-\w+)(-SR\d+\Z)|'
+                                     '(\d+\.\d+\.\d+-\w+)(-SR\d+(\.\d+)\Z)',
+                                     distribution_name)  # noqa
 
         if distribution_ver is None:
-            print distribution_name + " is not a valid distribution version. (Must contain version in the form: \"<#>.<#>.<#>-<name>\" or \"<#>.<#>.<#>-<name>-SR<#>\" or \"<#>.<#>.<#>-<name>\", e.g. 0.2.0-SNAPSHOT)"  # noqa
+            print distribution_name + " is not a valid distribution version." \
+                                      " (Must contain version in the form: " \
+                                      "\"<#>.<#>.<#>-<name>\" or \"<#>.<#>." \
+                                      "<#>-<name>-SR<#>\" or \"<#>.<#>.<#>" \
+                                      "-<name>\", e.g. 0.2.0-SNAPSHOT)"  # noqa
             sys.exit(1)
         distribution_ver = distribution_ver.group()
 
@@ -142,54 +171,71 @@ class Deployer:
                 "DS_SEED_NODES": array_str(self.ds_seed_nodes),
                 "RPC_SEED_NODES": array_str(self.rpc_seed_nodes)
             })
-        module_shards_conf = renderer.render("module-shards.conf.template", "module-shards.conf", self.replicas)
-        modules_conf = renderer.render("modules.conf.template", "modules.conf")
-        features_cfg = renderer.render("org.apache.karaf.features.cfg.template",
-                                       "org.apache.karaf.features.cfg",
-                                       {"ODL_DISTRIBUTION": distribution_ver})
+        module_shards_conf = renderer.render("module-shards.conf.template",
+                                             "module-shards.conf",
+                                             self.replicas)
+        modules_conf = renderer.render("modules.conf.template",
+                                       "modules.conf")
+        features_cfg = \
+            renderer.render("org.apache.karaf.features.cfg.template",
+                            "org.apache.karaf.features.cfg",
+                            {"ODL_DISTRIBUTION": distribution_ver})
         jolokia_xml = renderer.render("jolokia.xml.template", "jolokia.xml")
-        management_cfg = renderer.render("org.apache.karaf.management.cfg.template",
-                                         "org.apache.karaf.management.cfg",
-                                         {"HOST": self.host})
-
-        # Connect to the remote host and start doing operations
-        remote = RemoteHost(self.host, self.user, self.password, self.rootdir)
-
-        # Delete all the sub-directories under the deploy directory if the --clean flag is used
+        management_cfg = \
+            renderer.render("org.apache.karaf.management.cfg.template",
+                            "org.apache.karaf.management.cfg",
+                            {"HOST": self.host})
+        datastore_cfg = \
+            renderer.render(
+                "org.opendaylight.controller.cluster.datastore.cfg.template",
+                "org.opendaylight.controller.cluster.datastore.cfg")
+
+        # Delete all the sub-directories under the deploy directory if
+        # the --clean flag is used
         if self.clean is True:
-            remote.exec_cmd("rm -rf " + self.rootdir + "/deploy/*")
+            self.remote.exec_cmd("rm -rf " + self.rootdir + "/deploy/*")
 
         # Create the deployment directory
-        remote.mkdir(self.dir_name)
+        self.remote.mkdir(self.dir_name)
 
         # Clean the m2 repository
-        remote.exec_cmd("rm -rf " + self.rootdir + "/.m2/repository")
-
-        # Kill the controller if it's running
-        self.kill_controller(remote)
+        self.remote.exec_cmd("rm -rf " + self.rootdir + "/.m2/repository")
 
         # Copy the distribution to the host and unzip it
         odl_file_path = self.dir_name + "/odl.zip"
-        remote.copy_file(self.distribution, odl_file_path)
-        remote.exec_cmd("unzip " + odl_file_path + " -d " + self.dir_name + "/")
+        self.remote.copy_file(self.distribution, odl_file_path)
+        self.remote.exec_cmd("unzip " + odl_file_path + " -d " +
+                             self.dir_name + "/")
 
         # Rename the distribution directory to odl
-        remote.exec_cmd("mv " + self.dir_name + "/" + distribution_name + " " + self.dir_name + "/odl")
+        self.remote.exec_cmd("mv " + self.dir_name + "/" +
+                             distribution_name + " " + self.dir_name + "/odl")
 
         # Copy all the generated files to the server
-        remote.mkdir(self.dir_name + "/odl/configuration/initial")
-        remote.copy_file(akka_conf, self.dir_name + "/odl/configuration/initial/")
-        remote.copy_file(module_shards_conf, self.dir_name + "/odl/configuration/initial/")
-        remote.copy_file(modules_conf, self.dir_name + "/odl/configuration/initial/")
-        remote.copy_file(features_cfg, self.dir_name + "/odl/etc/")
-        remote.copy_file(jolokia_xml, self.dir_name + "/odl/deploy/")
-        remote.copy_file(management_cfg, self.dir_name + "/odl/etc/")
+        self.remote.mkdir(self.dir_name
+                          + "/odl/configuration/initial")
+        self.remote.copy_file(akka_conf, self.dir_name
+                              + "/odl/configuration/initial/")
+        self.remote.copy_file(module_shards_conf, self.dir_name
+                              + "/odl/configuration/initial/")
+        self.remote.copy_file(modules_conf, self.dir_name
+                              + "/odl/configuration/initial/")
+        self.remote.copy_file(features_cfg, self.dir_name
+                              + "/odl/etc/")
+        self.remote.copy_file(jolokia_xml, self.dir_name
+                              + "/odl/deploy/")
+        self.remote.copy_file(management_cfg, self.dir_name
+                              + "/odl/etc/")
+
+        if datastore_cfg is not None:
+            self.remote.copy_file(datastore_cfg, self.dir_name + "/odl/etc/")
 
         # Add symlink
-        remote.exec_cmd("ln -sfn " + self.dir_name + " " + args.rootdir + "/deploy/current")
+        self.remote.exec_cmd("ln -sfn " + self.dir_name + " "
+                             + args.rootdir + "/deploy/current")
 
         # Run karaf
-        remote.start_controller(self.dir_name)
+        self.remote.start_controller(self.dir_name)
 
 
 def main():
@@ -212,20 +258,33 @@ def main():
     replicas = {}
 
     for x in range(0, len(hosts)):
-        ds_seed_nodes.append("akka.tcp://opendaylight-cluster-data@" + hosts[x] + ":2550")
-        rpc_seed_nodes.append("akka.tcp://odl-cluster-rpc@" + hosts[x] + ":2551")
+        ds_seed_nodes.append("akka.tcp://opendaylight-cluster-data@"
+                             + hosts[x] + ":2550")
+        rpc_seed_nodes.append("akka.tcp://odl-cluster-rpc@"
+                              + hosts[x] + ":2551")
         all_replicas.append("member-" + str(x + 1))
 
     for x in range(0, 10):
         if len(all_replicas) > args.rf:
-            replicas["REPLICAS_" + str(x+1)] = array_str(random.sample(all_replicas, args.rf))
+            replicas["REPLICAS_" + str(x+1)] \
+                = array_str(random.sample(all_replicas, args.rf))
         else:
             replicas["REPLICAS_" + str(x+1)] = array_str(all_replicas)
 
+    deployers = []
+
+    for x in range(0, len(hosts)):
+        deployers.append(Deployer(hosts[x], x + 1, args.template, args.user,
+                                  args.password, args.rootdir,
+                                  args.distribution, dir_name, hosts,
+                                  ds_seed_nodes, rpc_seed_nodes, replicas,
+                                  args.clean))
+
+    for x in range(0, len(hosts)):
+        deployers[x].kill_controller()
+
     for x in range(0, len(hosts)):
-        Deployer(hosts[x], x + 1, args.template, args.user, args.password,
-                 args.rootdir, args.distribution, dir_name, hosts, ds_seed_nodes,
-                 rpc_seed_nodes, replicas, args.clean).deploy()
+        deployers[x].deploy()
 
 # Run the script
 main()