Example #1
0
    def get_rabbitmq_cluster_nodes(self):
        cluster_nodes = None
        if  self.rabbitmq_major_release == '3' and \
            self.rabbitmq_maintenance_release == '8':

            rmq_cluster_status_cmd = '/usr/sbin/rabbitmqctl cluster_status' + \
                                    ' --formatter json'
            output, error, returncode = SimpleProcess(rmq_cluster_status_cmd).run()
            try:
                rabbitmq_cluster_status = json.loads(output)
            except Exception:
                raise SetupError(
                            errno.EINVAL,
                            "RabbitMQ cluster status is not okay! \n, status : %s",
                            output)
            if returncode:
                raise SetupError(returncode, error)
            running_nodes = rabbitmq_cluster_status['running_nodes']
            for i, node in enumerate(running_nodes):
                running_nodes[i] = node.replace('rabbit@', '')
            cluster_nodes = " ".join(running_nodes)
        elif self.rabbitmq_version == '3.3.5':
            rmq_cluster_status_cmd = "rabbitmqctl cluster_status"
            output, error, returncode = SimpleProcess(rmq_cluster_status_cmd).run()
            cluster_nodes = re.search(
                        r"running_nodes,\['rabbit@(?P<cluster_nodes>.+?)'\]",
                        output.decode()).groupdict()["cluster_nodes"]
        else:
            raise SetupError(
                        errno.EINVAL,
                        "This RabbitMQ version : %s is not supported",
                        self.rabbitmq_version)
        return cluster_nodes
    def validate(self):
        self.PRODUCT_NAME = Conf.get(GLOBAL_CONFIG_INDEX, 'release>product')

        # Validate product
        if not self.PRODUCT_NAME:
            raise SetupError(1, "%s - validation failure. %s", self.name,
                             "Product not found in global config copy.")

        if not enabled_products:
            raise SetupError(1, "No enabled products!")

        if self.PRODUCT_NAME not in enabled_products:
            raise SetupError(
                1, "Product '%s' is not in enabled products list: %s",
                self.PRODUCT_NAME, enabled_products)
    def process(self):
        """Configure SSPL logs and service based on config."""

        # Copy and load product specific sspl config
        if not os.path.exists(file_store_config_path):
            shutil.copyfile(
                "%s/conf/sspl.conf.%s.yaml" %
                (SSPL_BASE_DIR, self.PRODUCT_NAME), file_store_config_path)

        # Global config copy path in sspl.conf will be referred by sspl-ll service later.
        Conf.load(SSPL_CONFIG_INDEX, sspl_config_path)
        Conf.set(SSPL_CONFIG_INDEX, "SYSTEM_INFORMATION>global_config_url",
                 self.global_config_url)
        Conf.set(SSPL_CONFIG_INDEX,
                 "SYSTEM_INFORMATION>global_config_copy_url",
                 self.global_config_copy_url)
        Conf.save(SSPL_CONFIG_INDEX)

        environ = Conf.get(SSPL_CONFIG_INDEX, "SYSTEM_INFORMATION>environment")
        if environ == "DEV":
            self.ENVIRONMENT = environ

        # sspl_setup_consul script install consul in dev env and checks if consul process is running
        # on prod. For node replacement scenario consul will not be running on the new node. But,
        # there will be two instance of consul running on healthy node. When new node is configured
        # consul will be brought back on it. We are using VIP to connect to consul. So, if consul
        # is not running on new node, we dont need to error out. So, need to skip this step for
        # node replacement case
        # TODO: Need to avoid LDR in CORTX and check if we can use "CORTXr1"
        # Onward LR2, consul will be abstracted out and it won't exit as hard dependeny of SSPL
        if self.PRODUCT_NAME == "LDR_R1":
            # setup consul if not running already
            if not os.path.exists(REPLACEMENT_NODE_ENV_VAR_FILE):
                sspl_setup_consul = "%s/sspl_setup_consul -e %s" % (
                    self._script_dir, self.ENVIRONMENT)
                output, error, returncode = SimpleProcess(
                    sspl_setup_consul).run()
                if returncode != 0:
                    raise SetupError(returncode, error, sspl_setup_consul)

        # Install packages which are not available in YUM repo, from PIP
        pip_cmd = "python3 -m pip install -r %s/low-level/requirements.txt" % (
            SSPL_BASE_DIR)
        output, error, returncode = SimpleProcess(pip_cmd).run()
        if returncode != 0:
            raise SetupError(returncode, error, pip_cmd)
        # Splitting current function into 2 functions to reduce the complexity of the code.
        self.install_files(self.PRODUCT_NAME)
Example #4
0
 def validate(self):
     """Validate config command arguments"""
     if not self.args.config:
         raise SetupError(1,
                          "%s - Argument validation failure. %s",
                          self.name,
                          "Global config is required.")
Example #5
0
 def validate(self):
     """Validate init command arguments"""
     if not self.args.config:
         raise SetupError(
                 errno.EINVAL,
                 "%s - Argument validation failure. Global config is needed",
                 self.name)
Example #6
0
    def replace_expr(self, filename:str, key, new_str:str):

        """The function helps to replace the expression provided as key
            with new string in the file provided in filename
            OR
            It inserts the new string at given line as a key in the
            provided file.
        """

        with open(filename, 'r+') as f:
            lines = f.readlines()
            if isinstance(key, str):
                for i, line in enumerate(lines):
                    if re.search(key, line):
                        lines[i] = re.sub(key, new_str, lines[i])
            elif isinstance(key, int):
                if not re.search(new_str, lines[key]):
                    lines.insert(key, new_str)
            else:
                raise SetupError(
                            errno.EINVAL,
                            "Key data type : '%s', should be string or int",
                            type(key))
            f.seek(0)
            for line in lines:
                f.write(line)
Example #7
0
 def validate(self):
     """Validate config for supported role and product"""
     # Validate role
     self.role = Conf.get(consts.GLOBAL_CONFIG_INDEX, 'release>setup')
     if not self.role:
         raise SetupError(
             errno.EINVAL,
             "%s - validation failure. %s",
             self.name,
             "Role not found in global config copy.")
     if self.role not in consts.setups:
         raise SetupError(
             errno.EINVAL,
             "%s - validation failure. %s",
             self.name,
             "Role '%s' is not supported. Check Usage" % self.role)
Example #8
0
 def get_cluster_running_nodes(self, msg_broker : str):
     if(msg_broker == 'rabbitmq'):
         return self.get_rabbitmq_cluster_nodes()
     else:
         raise SetupError(errno.EINVAL,
                     "Provided message broker '%s' is not supported",
                     msg_broker)
Example #9
0
    def validate(self):
        """Validate test command arguments"""
        if not self.args.config:
            raise SetupError(errno.EINVAL,
                             "%s - Argument validation failure. %s",
                             self.name,
                             "Global config is required.")

        if not self.args.plan:
            raise SetupError(
                    errno.EINVAL,
                    "%s - Argument validation failure. Test plan is needed",
                    self.name)

        result = PkgV().validate("rpms", "sspl-test")
        if result == -1:
            raise SetupError(1, "'sspl-test' rpm pkg not found.")
def update_sensor_info(config_index):

    key = 'monitor'

    sensors = dict()
    sensors["REALSTORSENSORS"] = "true"
    sensors["NODEHWSENSOR"] = "true"
    sensors["SYSTEMDWATCHDOG"] = "true"
    sensors["RAIDSENSOR"] = "true"
    sensors["SASPORTSENSOR"] = "true"
    sensors["MEMFAULTSENSOR"] = "true"
    sensors["CPUFAULTSENSOR"] = "true"

    try:
        with open("/etc/machine-id") as f:
            machine_id = f.read().strip("\n")
    except Exception as err:
        raise SetupError(1, "Failed to get machine-id. - %s" % (err))

    srvnode = Conf.get(GLOBAL_CONFIG_INDEX,
                       "cluster>server_nodes>%s" % (machine_id))
    enclosure_id = Conf.get(GLOBAL_CONFIG_INDEX,
                            "cluster>%s>storage>enclosure_id" % (srvnode))
    node_key_id = Conf.get(GLOBAL_CONFIG_INDEX,
                           'cluster>server_nodes>%s' % (machine_id))

    storage_type = Conf.get(GLOBAL_CONFIG_INDEX,
                            'storage>%s>type' % enclosure_id)
    if storage_type and storage_type.lower() in ["virtual", "jbod"]:
        sensors["REALSTORSENSORS"] = "false"

    server_type = Conf.get(GLOBAL_CONFIG_INDEX,
                           'cluster>%s>node_type' % (node_key_id))
    if server_type and server_type.lower() in ["virtual"]:
        sensors["NODEHWSENSOR"] = "false"
        sensors["SASPORTSENSOR"] = "false"
        sensors["MEMFAULTSENSOR"] = "false"
        sensors["CPUFAULTSENSOR"] = "false"
        sensors["RAIDSENSOR"] = "false"

    # Onward LDR_R2, consul will be abstracted out and it won't exit as hard dependeny of SSPL
    # Note: SSPL has backward compatibility to LDR_R1 and there consul is a dependency of SSPL.
    if SSPL_STORE_TYPE == "consul":
        host = os.getenv('CONSUL_HOST', CONSUL_HOST)
        port = os.getenv('CONSUL_PORT', CONSUL_PORT)
        try:
            consul_conn = consul.Consul(host=host, port=port)
            for sect, value in sensors.items():
                consul_conn.kv.put("sspl/config/%s/monitor" % sect, value)
        except Exception as cerror:
            print("Error in connecting with consul: {}".format(cerror))

    # Update sensor information in config
    for sect, value in sensors.items():
        Conf.set(config_index, '%s>%s' % (sect, key), value)

    Conf.save(config_index)
Example #11
0
 def process(self):
     args = ' '.join(self._args.args)
     manifest_support_bundle = "%s/%s %s" % (self._script_dir, self.script, args)
     output, error, returncode = SimpleProcess(manifest_support_bundle).run(realtime_output=True)
     if returncode != 0:
         raise SetupError(returncode,
                          "%s - validation failure. %s",
                          self.name,
                          error)
Example #12
0
    def process(self):
        # stop sspl service
        Service('dbus').process('stop', 'sspl-ll.service')

        # Remove sspl_conf
        self.del_file(file_store_config_path)

        # Remove sspl-configured file
        self.del_file(SSPL_CONFIGURED)

        # Remove sspl data
        shutil.rmtree(DATA_PATH, ignore_errors=True)

        # Remove sspl-ll user if preset
        CMD = "id -u sspl-ll"
        output, error, returncode = SimpleProcess(CMD).run()
        if returncode != 0:
            raise SetupError(returncode, "ERROR: %s - CMD %s", error, CMD)
        else:
            self.user_present = True

        if self.user_present:
            CMD = "/usr/sbin/userdel sspl-ll"
            output, error, returncode = SimpleProcess(CMD).run()
            if returncode != 0:
                raise SetupError(returncode, "ERROR: %s - CMD %s", error, CMD)

        # Remove log directories
        shutil.rmtree(f"/var/log/{PRODUCT_FAMILY}/sspl", ignore_errors=True)
        shutil.rmtree(f"/var/log/{PRODUCT_FAMILY}/iem", ignore_errors=True)

        # Remove rsyslog config files
        self.del_file("/etc/rsyslog.d/0-iemfwd.conf")
        self.del_file("/etc/rsyslog.d/1-ssplfwd.conf")

        # Remove logrotate config files
        self.del_file("/etc/logrotate.d/iem_messages")
        self.del_file("/etc/logrotate.d/sspl_logs")

        # Remove SSPL configuration files
        shutil.rmtree("/etc/sspl-ll", ignore_errors=True)
        self.del_file("/etc/sspl.conf.bak")
Example #13
0
 def recursive_chown(self, path: str, user: str, grpid: int = -1):
     uid = self.get_uid(user)
     if uid == -1:
         raise SetupError(errno.EINVAL, "No User Found with name : %s",
                          user)
     os.chown(path, uid, grpid)
     for root, dirs, files in os.walk(path):
         for item in dirs:
             os.chown(os.path.join(root, item), uid, grpid)
         for item in files:
             os.chown(os.path.join(root, item), uid, grpid)
Example #14
0
    def validate(self):
        if not self.args.config:
            raise SetupError(
                errno.EINVAL,
                "%s - Argument validation failure. Global config is required.",
                self.name)

        if not self.args.type:
            raise SetupError(
                errno.EINVAL,
                "%s - Argument validation failure. Reset type is required.",
                self.name)

        reset_type = self.args.type[0]
        if reset_type == "hard":
            self.process_class = "HardReset"
        elif reset_type == "soft":
            self.process_class = "SoftReset"
        else:
            raise SetupError(1, "Invalid reset type specified. Please check usage.")
Example #15
0
    def process(self):
        self.role = Conf.get('global_config', 'release>setup')

        if self.dp:
            # Extract the data path
            sspldp = Conf.get('sspl', 'SYSTEM_INFORMATION>data_path')
            if not sspldp:
                raise SetupError(
                    errno.EINVAL,
                    "Data Path Not set in %s" % file_store_config_path)

            # Crete the directory and assign permissions
            os.makedirs(sspldp, mode=0o766, exist_ok=True)
            self.recursive_chown(sspldp, 'sspl-ll')

        # Create /tmp/dcs/hpi if required. Not needed for '<product>' role
        if self.role != "cortx":
            os.makedirs(HPI_PATH, mode=0o777, exist_ok=True)
            zabbix_uid = self.get_uid('zabbix')
            if zabbix_uid != -1:
                os.chown(HPI_PATH, zabbix_uid, -1)

        # Check for sspl required processes and misc dependencies like
        # installation, etc based on 'role'
        if self.role:
            self.check_dependencies()

        # Create mdadm.conf to set ACL on it.
        with open(MDADM_PATH, 'a'):
            os.utime(MDADM_PATH)

        # TODO : verify for below replacement of setfacl command which
        #        gives rw permission to sspl-ll user for mdadm.conf file.
        os.chmod(MDADM_PATH, mode=0o666)
        sspl_ll_uid = self.get_uid('sspl-ll')
        if sspl_ll_uid == -1:
            raise SetupError(errno.EINVAL, "No User Found with name : %s",
                             'sspl-ll')
        os.chown(MDADM_PATH, sspl_ll_uid, -1)
 def _send_command(self, command, fail_on_error=True):
     """
     Execute command and retrun response
     Parameters:
         command: shell command to execute
         fail_on_error: Set to False will ignore command failure
     """
     print(f"Executing: {command}")
     output, error, returncode = SimpleProcess(command).run()
     if fail_on_error and returncode != 0:
         raise SetupError(returncode,
                          "ERROR: Command '%s' failed with error\n  %s",
                          command,
                          error)
     return output.decode('utf-8')
Example #17
0
    def process(self):
        self.plan = self.args.plan[0]
        self.avoid_rmq = self.args.avoid_rmq

        # Take back up of sspl test config
        sspl_test_backup = '/etc/sspl_tests.conf.back'
        shutil.copyfile(sspl_test_file_path, sspl_test_backup)

        # Add global config in sspl_test config and revert the changes once test completes.
        # Global config path in sspl_tests.conf will be referred by sspl_tests later
        global_config_copy_url = Conf.get(
            SSPL_CONFIG_INDEX, "SYSTEM_INFORMATION>global_config_copy_url")
        Conf.copy(GLOBAL_CONFIG_INDEX, SSPL_TEST_CONFIG_INDEX)
        Conf.set(SSPL_CONFIG_INDEX,
                 "SYSTEM_INFORMATION>global_config_copy_url",
                 sspl_test_config_path)
        Conf.save(SSPL_CONFIG_INDEX)

        # Enable & disable sensors based on environment
        update_sensor_info(SSPL_TEST_CONFIG_INDEX)

        # Get rabbitmq values from sspl.conf and update sspl_tests.conf
        rmq_passwd = Conf.get(SSPL_CONFIG_INDEX,
                              "RABBITMQEGRESSPROCESSOR>password")
        Conf.set(SSPL_TEST_CONFIG_INDEX, "RABBITMQEGRESSPROCESSOR>password",
                 rmq_passwd)
        Conf.save(SSPL_TEST_CONFIG_INDEX)

        # TODO: Convert shell script to python
        # from cortx.sspl.sspl_test.run_qa_test import RunQATest
        # RunQATest(self.plan, self.avoid_rmq).run()
        CMD = "%s/run_qa_test.sh %s %s" % (TEST_DIR, self.plan, self.avoid_rmq)
        output, error, returncode = SimpleProcess(CMD).run(
            realtime_output=True)
        # Restore the original path/file & service, then throw exception
        # if execution is failed.
        Conf.set(SSPL_CONFIG_INDEX,
                 "SYSTEM_INFORMATION>global_config_copy_url",
                 global_config_copy_url)
        Conf.save(SSPL_CONFIG_INDEX)
        shutil.copyfile(sspl_test_backup, sspl_test_file_path)
        Service('dbus').process('restart', 'sspl-ll.service')
        if returncode != 0:
            raise SetupError(returncode, "%s - ERROR: %s - CMD %s", self.name,
                             error, CMD)
Example #18
0
 def validate(self):
     # Common validator classes to check Cortx/system wide validator
     if not os.path.exists(self.SSPL_CONFIGURED):
         error = "SSPL is not configured. Run provisioner scripts in %s" % (self._script_dir)
         syslog.openlog(logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL3)
         syslog.syslog(syslog.LOG_ERR, error)
         raise SetupError(1,
                          "%s - validation failure. %s",
                          self.name,
                          error)
     # Validate required services are running
     retry = 3
     while retry > 0:
         try:
             ServiceV().validate('isrunning', self.services)
         except VError:
             retry -= 1
             time.sleep(5)
         else:
             break
     ServiceV().validate('isrunning', self.services)
Example #19
0
    def process(self):
        cmd = "config"
        if(cmd == "config"):
            self.config_sspl()
        else:
            raise SetupError(errno.EINVAL, "cmd val should be config")

        # Get the version. Output can be 3.3.5 or 3.8.9 or in this format
        rmq_cmd = "rpm -qi rabbitmq-server"
        output, error, returncode = SimpleProcess(rmq_cmd).run()
        if returncode:
            raise SetupError(returncode, error)
        self.rabbitmq_version = re.search(  r'Version     :\s*([\d.]+)',
                                            str(output)).group(1)

        # Get the Major release version parsed. (Eg: 3 from 3.8.9)
        self.rabbitmq_major_release = self.rabbitmq_version[0]

        # Get the Minor release version parsed. (Eg: 3.8 from 3.8.9)
        self.rabbitmq_minor_release = self.rabbitmq_version[:3]

        # Get the Maitenance release version parsed from minor release.
        # (Eg: 8 from 3.8)
        self.rabbitmq_maintenance_release = self.rabbitmq_minor_release[-1]

        # Skip this step if sspl is being configured for node replacement
        # scenario as consul data is already
        # available on healthy node
        # Updating RabbitMQ cluster nodes.
        # In node replacement scenario, avoiding feeding again to avoid
        # over writing already configured values
        # with which rabbitmq cluster may have been created
        if not os.path.exists(consts.REPLACEMENT_NODE_ENV_VAR_FILE):
            message_broker="rabbitmq"
            # Get the running nodes from a cluster
            pout = self.get_cluster_running_nodes(message_broker)

            # Update cluster_nodes key in consul
            if consts.PRODUCT_NAME == 'LDR_R1':
                host = os.getenv('CONSUL_HOST', consts.CONSUL_HOST)
                port = os.getenv('CONSUL_PORT', consts.CONSUL_PORT)
                consul_conn = consul.Consul(host=host, port=port)
                consul_conn.kv.put(
                        "sspl/config/RABBITMQCLUSTER/cluster_nodes", pout)
            else:
                Conf.set(consts.SSPL_CONFIG_INDEX,
                         'RABBITMQCLUSTER>cluster_nodes', pout)
                Conf.save(consts.SSPL_CONFIG_INDEX)

        # Skip this step if sspl is being configured for node replacement
        # scenario as consul data is already
        # available on healthy node
        # Updating build requested log level
        if not os.path.exists(consts.REPLACEMENT_NODE_ENV_VAR_FILE):
            with open(f'{consts.SSPL_BASE_DIR}/low-level/files/opt/seagate' + \
                '/sspl/conf/build-requested-loglevel', 'r') as f:
                log_level = f.readline().strip()

            if not log_level:
                log_level = "INFO"

            if  log_level == "DEBUG" or log_level == "INFO" or \
                log_level == "WARNING" or log_level == "ERROR" or \
                log_level == "CRITICAL":
                if consts.PRODUCT_NAME == "LDR_R1":
                    host = os.getenv('CONSUL_HOST', consts.CONSUL_HOST)
                    port = os.getenv('CONSUL_PORT', consts.CONSUL_PORT)
                    consul_conn = consul.Consul(host=host, port=port)
                    consul_conn.kv.put(
                            "sspl/config/SYSTEM_INFORMATION/log_level",
                            log_level)
                else:
                    Conf.set(consts.SSPL_CONFIG_INDEX,
                             'SYSTEM_INFORMATION>log_level', log_level)
                    Conf.save(consts.SSPL_CONFIG_INDEX)
            else:
                raise SetupError(
                            errno.EINVAL,
                            "Unexpected log level is requested, '%s'",
                            log_level
                            )
    def install_files(self, PRODUCT):
        """Configure required log files."""

        # Copy rsyslog configuration
        if not os.path.exists(self.RSYSLOG_CONF):
            shutil.copyfile(
                "%s/low-level/files/%s" % (SSPL_BASE_DIR, self.RSYSLOG_CONF),
                self.RSYSLOG_CONF)

        if not os.path.exists(self.RSYSLOG_SSPL_CONF):
            shutil.copyfile(
                "%s/low-level/files/%s" %
                (SSPL_BASE_DIR, self.RSYSLOG_SSPL_CONF),
                self.RSYSLOG_SSPL_CONF)

        # Create soft link for SINGLE product name service to existing LDR_R1, LR2 service
        # Instead of keeping separate service file for SINGLE product with same content.
        currentProduct = "%s/conf/sspl-ll.service.%s" % (SSPL_BASE_DIR,
                                                         PRODUCT)
        if (PRODUCT == "SINGLE" and not os.path.exists(currentProduct)) or \
                (PRODUCT == "DUAL" and not os.path.exists(currentProduct)):
            os.symlink("%s/conf/sspl-ll.service.%s" % (SSPL_BASE_DIR, PRODUCT),
                       currentProduct)

        if PRODUCT == "CLUSTER" and not os.path.exists(currentProduct):
            os.symlink("%s/conf/sspl-ll.service.LR2" % (SSPL_BASE_DIR),
                       currentProduct)

        # Copy sspl-ll.service file and enable service
        shutil.copyfile(currentProduct, "/etc/systemd/system/sspl-ll.service")
        Service('dbus').process('enable', 'sspl-ll.service')
        daemon_reload_cmd = "systemctl daemon-reload"
        output, error, returncode = SimpleProcess(daemon_reload_cmd).run()
        if returncode != 0:
            raise SetupError(returncode, error, daemon_reload_cmd)

        # Copy IEC mapping files
        os.makedirs("%s/iem/iec_mapping" % (PRODUCT_BASE_DIR), exist_ok=True)
        distutils.dir_util.copy_tree(
            "%s/low-level/files/iec_mapping/" % (SSPL_BASE_DIR),
            "%s/iem/iec_mapping" % (PRODUCT_BASE_DIR))

        # Skip this step if sspl is being configured for node replacement scenario as sspl configurations are
        # already available in consul on the healthy node
        # Running script for fetching the config using salt and feeding values to consul
        # Onward LR2, consul will be abstracted out and it won't exit as hard dependeny of SSPL
        if PRODUCT == "LDR_R1":
            if not os.path.exists(REPLACEMENT_NODE_ENV_VAR_FILE):
                config_from_salt = "%s/sspl_fetch_config_from_salt.py %s %s" % (
                    self._script_dir, self.ENVIRONMENT, PRODUCT)
                output, error, returncode = SimpleProcess(
                    config_from_salt).run()
                if returncode != 0:
                    raise SetupError(returncode, error, config_from_salt)

        # Skip this step if sspl is being configured for node replacement scenario as rabbitmq cluster is
        # already configured on the healthy node
        # Configure rabbitmq
        if not os.path.exists(REPLACEMENT_NODE_ENV_VAR_FILE):
            setup_rmq = Conf.get(SSPL_CONFIG_INDEX,
                                 "RABBITMQCLUSTER>setup_rmq")
            if setup_rmq:
                Service('dbus').process('start', 'rabbitmq-server.service')
                sspl_rabbitmq_reinit.main(PRODUCT)
Example #21
0
 def validate(self):
     if not self.args.nodes:
         raise SetupError(1,
                          "Validation failure. %s",
                          "join_cluster requires comma separated node names as argument.")
     self.nodes = self.args.nodes[0]
Example #22
0
    def config_sspl(self):
        if(os.geteuid() != 0):
            raise SetupError(
                        errno.EINVAL,
                        "Run this command with root privileges!!")

        if not os.path.isfile(consts.file_store_config_path):
            raise SetupError(
                        errno.EINVAL,
                        "Missing configuration!! Create and rerun.",
                        consts.file_store_config_path)

        # Put minion id, consul_host and consul_port in conf file
        # Onward LDR_R2, salt will be abstracted out and it won't
        # exist as a hard dependeny of SSPL
        if consts.PRODUCT_NAME == "LDR_R1":
            from cortx.sspl.bin.salt_util import SaltInterface
            salt_util = SaltInterface()
            salt_util.update_config_file(consts.file_store_config_path)

        if os.path.isfile(consts.SSPL_CONFIGURED):
            os.remove(consts.SSPL_CONFIGURED)

        # Add sspl-ll user to required groups and sudoers file etc.
        sspl_reinit = [f"{consts.SSPL_BASE_DIR}/bin/sspl_reinit", self.product]
        _ , error, returncode = SimpleProcess(sspl_reinit).run()
        if returncode:
            raise SetupError(returncode,
                    "%s/bin/sspl_reinit failed for product %s with error : %e",
                      consts.SSPL_BASE_DIR, product, error
                    )

        os.makedirs(consts.SSPL_CONFIGURED_DIR, exist_ok=True)
        with open(consts.SSPL_CONFIGURED, 'a'):
            os.utime(consts.SSPL_CONFIGURED)

        # SSPL Log file configuration
        # SSPL_LOG_FILE_PATH = self.getval_from_ssplconf('sspl_log_file_path')
        SSPL_LOG_FILE_PATH = Conf.get(
            consts.SSPL_CONFIG_INDEX, 'SYSTEM_INFORMATION>sspl_log_file_path')
        IEM_LOG_FILE_PATH = Conf.get(
            consts.SSPL_CONFIG_INDEX, 'IEMSENSOR>log_file_path')
        if SSPL_LOG_FILE_PATH:
            self.replace_expr(consts.RSYSLOG_SSPL_CONF,
                        'File.*[=,"]', 'File="%s"' % SSPL_LOG_FILE_PATH)
            self.replace_expr(
                    f"{consts.SSPL_BASE_DIR}/low-level/files/etc/logrotate.d/sspl_logs",
                    0, SSPL_LOG_FILE_PATH)

        # IEM configuration
        # Configure log file path in Rsyslog and logrotate configuration file
        IEM_LOG_FILE_PATH = Conf.get(
            consts.SSPL_CONFIG_INDEX, 'IEMSENSOR>log_file_path')

        if IEM_LOG_FILE_PATH:
            self.replace_expr(consts.RSYSLOG_IEM_CONF,
                    'File.*[=,"]', 'File="%s"' % IEM_LOG_FILE_PATH)
            self.replace_expr(
                    f'{consts.SSPL_BASE_DIR}/low-level/files/etc/logrotate.d/iem_messages',
                    0, IEM_LOG_FILE_PATH)
        else:
            self.replace_expr(consts.RSYSLOG_IEM_CONF,
                    'File.*[=,"]', 'File="/var/log/%s/iem/iem_messages"' % consts.PRODUCT_FAMILY)

        # Create logrotate dir in case it's not present for dev environment
        if not os.path.exists(consts.LOGROTATE_DIR):
            os.makedirs(consts.LOGROTATE_DIR)

        shutil.copy2(
            '%s/low-level/files/etc/logrotate.d/iem_messages' % consts.SSPL_BASE_DIR,
            consts.IEM_LOGROTATE_CONF)

        shutil.copy2(
            '%s/low-level/files/etc/logrotate.d/sspl_logs' % consts.SSPL_BASE_DIR,
            consts.SSPL_LOGROTATE_CONF)

        # This rsyslog restart will happen after successful updation of rsyslog
        # conf file and before sspl starts. If at all this will be removed from
        # here, there will be a chance that SSPL intial logs will not be present in
        # "/var/log/<product>/sspl/sspl.log" file. So, initial logs needs to be collected from
        # "/var/log/messages"

        Service('dbus').process("restart", 'rsyslog.service')

        # For node replacement scenario consul will not be running on the new node. But,
        # there will be two instance of consul running on healthy node. When new node is configured
        # consul will be brought back on it. We are using VIP to connect to consul. So, if consul
        # is not running on new node, we dont need to error out.
        # If consul is not running, exit
        # Onward LDR_R2, consul will be abstracted out and it won't
        # exit as hard dependeny of SSPL

        if consts.PRODUCT_NAME == 'LDR_R1':
            if not os.path.exists(consts.REPLACEMENT_NODE_ENV_VAR_FILE):
                ServiceV().validate('isrunning', ['consul'], is_process=True)

        # Get the types of server and storage we are currently running on and
        # enable/disable sensor groups in the conf file accordingly.
        update_sensor_info(consts.SSPL_CONFIG_INDEX)