"""
 *
 * This file is part of rasdaman community.
 *
 * Rasdaman community is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Rasdaman community is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU  General Public License for more details.
 *
 * You should have received a copy of the GNU  General Public License
 * along with rasdaman community.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright 2003 - 2016 Peter Baumann / rasdaman GmbH.
 *
 * For more information please see <http://www.rasdaman.org>
 * or contact Peter Baumann via <baumann@rasdaman.com>.
 *
"""
from abc import abstractmethod, ABCMeta
import os
import sys
from time import sleep
from config_manager import ConfigManager
from util.distrowrapper import InitDTypes, DistroWrapper
from util.file_util import replace_in_file, find_line_containing_token_in_file, \
    fix_trailing_slash, write_to_file, read_file, replace_in_file_matching_lines_re, \
    get_values_for_property_keys
from util.log import log
from util.commands import chmod, copy, make_directory, sudo_remove, sudo_copy, \
    sudo_chown, sudo_chmod, add_user_to_group
from util.servicemgr import RasdamanLocalService
from services import executor, postgres_service, linux_distro, rasdaman_service, \
    tomcat_service, rasdaman_system_service


class Preparer:
    __metaclass__ = ABCMeta

    # All rasdaman configuration files
    CONFIG_FILES = ["rasmgr.conf", "rmankey", "petascope.properties",
                    "secore.properties", "rasfed.properties",
                    "log-client.conf", "log-server.conf", "log-rasmgr.conf"]

    @abstractmethod
    def prepare(self):
        """
        Prepares the system for a run of the installation and testing phases. For example
        if rasdaman was configured with postgres as a based db a preparer would create
        the database for it.
        """
        pass


class PreparerBasis(Preparer):
    def __init__(self):
        """
        The basis class to build the preparer hierarchy
        """
        Preparer.__init__(self)

    def prepare(self):
        pass


class PreparerDecorator(Preparer):
    def __init__(self, preparer):
        """
        The preparer decorator allows you to compose several preparer into one.
        :param Preparer preparer: the preparer that this decorator wraps
        """
        self.preparer = preparer

    def prepare(self):
        """
        This method should be overridden to add new configure parameters
        However a call to super will always be required
        """
        self.preparer.prepare()


class PostgresPreparer(PreparerDecorator):
    def __init__(self, preparer, install_path, user, update):
        """
        Prepares the postgres database engine for rasdaman
        :param str install_path: the installation path of rasdaman
        :param str user: the local rasdaman user
        :param str update: updating an existing installation
        """
        PreparerDecorator.__init__(self, preparer)
        self.install_path = install_path
        self.user = user
        self.update = update

    def __execute_cmd(self, cmd):
        executor.execute(cmd, user="postgres", throw_on_error=False, warn_on_error=True)

    def prepare(self):
        PreparerDecorator.prepare(self)
        log.info("Preparing rasdaman postgresql database...")
        postgres_service.start()
        if not postgres_service.user_exists(self.user):
            self.__execute_cmd(["createuser", "-s", self.user])
        dbscript = "update_db.sh" if postgres_service.database_exists("RASBASE") else "create_db.sh"
        executor.execute([self.install_path + "bin/" + dbscript],
                         throw_on_error=False, warn_on_error=True)
        log.info("Rasdaman postgresql database was prepared.")


class SqlitePreparer(PreparerDecorator):
    def __init__(self, preparer, install_path, data_dir):
        """
        Prepares the sqlite database engine for rasdaman
        :param str install_path: the path to the installation
        :param str data_dir: the installation path of rasdaman
        """
        PreparerDecorator.__init__(self, preparer)
        self.data_dir = data_dir
        self.install_path = install_path

    def prepare(self):
        PreparerDecorator.prepare(self)
        log.info("Preparing rasdaman SQLite database...")
        rasbase = self.data_dir + "RASBASE"
        rasbase_exists = os.path.exists(rasbase)
        log.debug("  RASBASE exists at " + rasbase + ": " + str(rasbase_exists))
        dbscript = "update_db.sh" if rasbase_exists else "create_db.sh"
        executor.execute([self.install_path + "bin/" + dbscript],
                         throw_on_error=False, warn_on_error=True)
        log.info("Rasdaman SQLite database was prepared.")


class PetascopePreparer(PreparerDecorator):
    def __init__(self, preparer, profile):
        """
        Prepares the postgres database engine for petascope
        :param str install_path: the installation path of rasdaman
        :param str username: the postgres user
        :param str password: the password for the above user
        :param str url: the connection string to postgres
        """
        PreparerDecorator.__init__(self, preparer)
        self.profile = profile
        self.install_path = profile.install_path
        self.username = self.profile.petascopedb_username
        self.password = self.profile.petascopedb_password
        self.password_updated = False
        self.url = self.profile.petascopedb_url
        self.petascopedb = self.url
        if '/' in self.url:
            self.petascopedb = self.url.split('/')[-1]
        self.props_path = self.install_path + "etc/petascope.properties"

    def __execute_cmd(self, cmd):
        executor.execute(cmd, user="postgres", throw_on_error=False, warn_on_error=True)

    def __create_postgres_user(self):
        """
        Makes sure a valid petascope user exists and changes the password to something we know.
        Not to orthodox but only way to be backwards compatible
        """
        if not postgres_service.user_exists(self.username):
            self.__execute_cmd(["createuser", "-s", self.username])
            self.__execute_cmd(["psql", "-c", "ALTER USER \"" + self.username +
                                "\" WITH PASSWORD '" + self.password + "'"])
            return True
        elif not postgres_service.user_can_login(self.username, self.password,
                                                 self.petascopedb):
            self.__execute_cmd(["psql", "-c", "ALTER USER \"" + self.username +
                                "\" WITH PASSWORD '" + self.password + "'"])
            return True
        else:
            return False

    def __update_options(self, options, new_value):
        for option in options:
            lines_matching_pattern = "^" + option
            pattern = "^" + option + ".*"
            replacement = option + new_value
            replace_in_file_matching_lines_re(
                self.props_path, lines_matching_pattern, {pattern: replacement})

    def __update_postgres_config(self):
        """
        Update the petascopedb url, username and password if it is a first time
        installation.
        """
        self.__update_options(["metadata_url=", "spring.datasource.url="], self.url)
        self.__update_options(["metadata_user=", "petascope_admin_user=",
                               "spring.datasource.username="], self.username)
        self.__update_options(["metadata_pass=", "petascope_admin_pass=",
                               "spring.datasource.password="], self.password)

    def __check_standalone_port_free(self):
        """
        Print warning if petascope standalone port (embedded deployment) is busy
        """
        if self.profile.generate_package or self.profile.update \
           or self.profile.webapps_deployment != "standalone":
            return

        from util.url_util import is_port_in_use
        port = self.profile.petascope_standalone_port
        if is_port_in_use(port):
            ConfigManager.petascope_available = False
            log.warn("""
Warning: Petascope will be deployed in 'embedded' mode (java_server=embedded and
server.port={0} in petascope.properties), however, the configured port {0} is
currently in use (possibly by the system Tomcat, or another application), so
petascope will likely fail to start when rasdaman is started. There are several
alternative ways to handle this situation:

 1. Check if the application occupying port {0} is needed, and stop/uninstall if not;
 2. Change server.port in petascope.properties to a port that is available on
    your system and restart rasdaman;
 3. Deploy petascope in a system Tomcat by copying {1}
    to the Tomcat webapps directory. This is generally not recommended as it will
    require management separate from the rasdaman service start/stop.

Please consult the rasdaman documentation on "petascope Standalone Deployment" at
https://doc.rasdaman.com/testing/05_geo-services-guide.html#petascope-standalone-deployment
as well as the comments of relevant options in {2}.
""".format(port, self.install_path + "share/rasdaman/war/rasdaman.war", self.props_path))

    def prepare(self):
        PreparerDecorator.prepare(self)
        log.info("Preparing petascope...")
        # Configure postgres
        postgres_service.start()
        if self.__create_postgres_user():
            self.__update_postgres_config()
        self.__check_standalone_port_free()
        log.info("Petascope was prepared.")


class TomcatServerPreparer(PreparerDecorator):
    def __init__(self, preparer, install_path, standalone, petascope_port):
        """
        Modifies the petascope properties to adjust the standalone server port
        :param str install_path: the installation path
        :param bool standalone: deploy standalone Tomcat or embedded
        :param int petascope_port: the port of embedded Tomcat
        :return:
        """
        PreparerDecorator.__init__(self, preparer)
        self.install_path = install_path
        self.standalone = standalone
        self.petascope_port = petascope_port

    def __update_options(self, component, options, new_value):
        props = self.install_path + "etc/" + component + ".properties"
        for option in options:
            line = find_line_containing_token_in_file(props, option)
            if line is not None:
                replace_in_file(props, {line: option + new_value})

    def prepare(self):
        PreparerDecorator.prepare(self)
        deploy = "embedded" if self.standalone else "external"
        log.info("Preparing for " + deploy + " server deployment...")
        self.__update_options("petascope", ["java_server="], deploy)
        self.__update_options("petascope", ["server.port="], str(self.petascope_port))
        self.__update_options("secore", ["java_server="], deploy)
        log.info("Config updated for " + deploy + " server deployment.")


class UpdateWebappsLogPathsPreparer(PreparerDecorator):
    def __init__(self, preparer, install_path, webapps_logs):
        """
        Update the log file paths of petascope and secore to point to a location
        where Tomcat has access.
        :param str install_path: the installation path of rasdaman
        """
        PreparerDecorator.__init__(self, preparer)
        self.install_path = install_path
        self.webapps_logs = fix_trailing_slash(webapps_logs)

    def __update_log_file_path(self, svc):
        """
        Set the path to petascope.log and secore.log to a file that Tomcat can
        write to (e.g. /var/log/tomcat/petascope.log).
        """
        install_path = self.install_path
        prop_file = install_path + "etc/" + svc + ".properties"
        if not os.path.exists(prop_file):
            return
        bad_log_file = install_path + "log/" + svc + ".log"
        good_log_file = self.webapps_logs + svc + ".log"
        replace_in_file(prop_file, {bad_log_file: good_log_file})
        log.info("Updated path of " + svc + ".log to " + good_log_file + ".")

    def prepare(self):
        PreparerDecorator.prepare(self)
        self.__update_log_file_path("petascope")
        self.__update_log_file_path("secore")


class EnableDebugLoggingPreparer(PreparerDecorator):
    def __init__(self, preparer, install_path, config_file):
        """
        Enable Debug logging in the rasmgr/server/client config_file.
        """
        PreparerDecorator.__init__(self, preparer)
        self.config_file = install_path + "etc/" + config_file

    def prepare(self):
        PreparerDecorator.prepare(self)
        f = read_file(self.config_file)
        if f is None:
            return
        lines = f.split("\n")
        in_debug_section = False
        modified = False
        for i in range(len(lines)):
            if lines[i].startswith("* Debug"):
                in_debug_section = True
            elif lines[i].startswith("* "):
                in_debug_section = False
            elif in_debug_section:
                if lines[i].startswith("  Enabled = false"):
                    lines[i] = "  Enabled = true"
                    modified = True
        if modified:
            f = "\n".join(lines)
            write_to_file(self.config_file, f)
            log.info(self.config_file + " updated to enable debug logging.")


class AddTomcatToRasdamanGroup(PreparerDecorator):
    def __init__(self, preparer, tomcat_user, rasdaman_group):
        """
        Add tomcat user to the rasdaman group, so it can read files in
        /opt/rasdaman/etc (petascope.properties and secore.properties)
        """
        PreparerDecorator.__init__(self, preparer)
        self.tomcat_user = tomcat_user
        self.rasdaman_group = rasdaman_group

    def prepare(self):
        PreparerDecorator.prepare(self)
        add_user_to_group(self.tomcat_user, self.rasdaman_group)


class CopyInstallerPreparer(PreparerDecorator):
    def __init__(self, Preparer, install_path):
        """
        Copies the installer directory to the rasdaman install path.
        :param str install_path: the install path to rasdaman
        """
        PreparerDecorator.__init__(self, Preparer)
        self.install_path = install_path

    def prepare(self):
        PreparerDecorator.prepare(self)
        installer_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
        installer_new_path = self.install_path + "share/rasdaman/installer"
        log.info("Copying install.sh to '{}'...".format(installer_new_path))
        make_directory(installer_new_path)
        # copy install.sh script to /opt/rasdaman/installer
        copy(installer_dir + "/install.sh", installer_new_path, False)
        sudo_chown(self.install_path, ConfigManager.default_user)
        log.info("install.sh copied successfully.")


class ServiceInitDPreparer(PreparerDecorator):
    def __init__(self, Preparer, install_path, profile, automatic_start=True):
        """
        Creates a init.d script to be used to stop and start rasdaman
        :param str install_path: the rasdaman installation path
        :param str user: the user that needs to execute rasdaman services
        :param Profile profile: the whole profile object
        :param bool automatic_start: set to false if rasdaman should not start
        at startup
        """
        PreparerDecorator.__init__(self, Preparer)
        self.install_path = install_path
        self.profile = profile
        self.user = profile.user
        self.automatic_start = automatic_start
        self.currdir = os.path.dirname(os.path.realpath(__file__))

    def __install_sysv_script(self):
        src = self.currdir + "/rasdaman.sh"
        dst = "/etc/init.d/rasdaman"
        contents = read_file(src)
        if contents is None:
            return
        tmp = "/tmp/rasdaman.sh"
        write_to_file(tmp, contents)
        sudo_copy(tmp, dst)
        sudo_chmod(dst, "755")
        sudo_remove(tmp)
        log.debug("Installed SysV init script at " + dst)

    def __install_systemd_script(self):
        if linux_distro.get_initd_type() == InitDTypes.SYSTEMD:
            src = self.currdir + "/rasdaman.service"
            dst = "/etc/systemd/system/rasdaman.service"
            sudo_copy(src, dst)
            sudo_chmod(dst, "644")
            log.debug("Installed systemd init script at " + dst)
        if self.automatic_start:
            rasdaman_system_service.enable()

    def __install_service_config(self):
        src = self.currdir + "/rasdaman.cfg"
        config_dir = "/etc/default"
        dst = config_dir + "/rasdaman"
        if not os.path.exists(dst) and os.path.exists(config_dir):
            contents = read_file(src)
            if contents is None:
                return
            contents = contents.format(self.install_path, self.user,
                                       DistroWrapper().get_runuser_cmd(),
                                       self.profile.rasmgr_port)
            write_to_file(dst, contents)
            log.debug("Installed service config script at " + dst)

    def prepare(self):
        PreparerDecorator.prepare(self)
        log.info("Installing service scripts...")
        self.__install_sysv_script()
        self.__install_systemd_script()
        self.__install_service_config()
        log.info("Service scripts installed successfully.")


class UpdateRasdamanScriptPreparer(PreparerDecorator):
    def __init__(self, Preparer, source_path, profile_path, install_path):
        """
        Saves the installation profile in the rasdaman main path and adds any
        needed extra information
        :param str source_path: path to the rasdaman source
        :param str profile_path: the path to the installation profile
        :param str install_path: the main path of rasdaman
        :return:
        """
        PreparerDecorator.__init__(self, Preparer)
        self.profile_path = profile_path
        self.source_path = source_path
        self.install_path = install_path
        self.installer_path = self.install_path + "share/rasdaman/installer"

    def __generate_update_rasdaman(self, profile_path):
        update_rasdaman_contents = """
#!/usr/bin/env bash
{}/install.sh -j {}
""".format(self.installer_path, profile_path)
        # NOTE: the update_rasdaman.sh is generated in /opt/rasdaman/bin by
        # default, it is not in the installer folder
        updater_path = self.install_path + "bin/update_rasdaman.sh"
        log.info("Installing update script at '" + updater_path + "'...")
        write_to_file(updater_path, update_rasdaman_contents)
        sudo_chown(updater_path, ConfigManager.default_user)
        chmod(updater_path, "+x")
        log.info("Update script installed successfully.")

    def __create_rasdaman_log_dir(self):
        log_dir = self.install_path + "log/"
        make_directory(log_dir)
        sudo_chmod(log_dir, "750")

    def prepare(self):
        PreparerDecorator.prepare(self)
        installer_path = self.install_path + "share/rasdaman/installer"
        dst = installer_path + "/install_profile.toml"
        if dst != self.profile_path:
            log.info("Updating the installation profile file at '" + dst + "'...")
            make_directory(installer_path)
            copy(self.profile_path, dst)
            sudo_chown(dst, ConfigManager.default_user)
            chmod(dst, "644")
            log.info("Installation profile updated successfully.")
        self.__generate_update_rasdaman(dst)
        self.__create_rasdaman_log_dir()


class MigratePreviousVersionConfigsPreparer(PreparerDecorator):
    def __init__(self, Preparer, install_path):
        """
        Updates properties files.
        :param str install_path: the installation path
        """
        PreparerDecorator.__init__(self, Preparer)
        self.install_path = install_path

    def __update_properties(self, src, dst):
        """
        Run `update_properties.sh src dst` to merge user configured properties in
        src (old properties file) and dst (new properties file in package)
        into an updated src file.
        """
        log.debug("  Merging '" + src + "' with '" + dst + "'...")
        # Run the update_properties.sh to update the changes between user's old
        # file and source's new file. The output is a combined PROPERTIES_FILE
        # file which will be copied back to installation path
        update_script = self.install_path + "bin/update_properties.sh"
        executor.executeSudo([update_script, src, dst],
                             throw_on_error=False, warn_on_error=True)
        sudo_chown(dst, ConfigManager.default_user)

    def update_secore_urls(self, props_path):
        """
        Update secore_urls to replace localhost:<port> entries with internal;
        See http://kahlua.eecs.jacobs-university.de/trac/wiki/ticket/352
        """
        log.info("  Migrating secore_urls from localhost to internal...")
        lines_matching_pattern = "^secore_urls="
        pattern = "https?://localhost(:[0-9]+)?/(rasdaman/)?def"
        replacement = "internal"
        replace_in_file_matching_lines_re(
            props_path, lines_matching_pattern, {pattern: replacement})

    def prepare(self):
        PreparerDecorator.prepare(self)
        log.info("Migrating configuration files to latest version...")
        etc_path = self.install_path + "etc/"
        copied = False
        for path in Preparer.CONFIG_FILES:
            dst = etc_path + path
            # This directory is populated by the package preinst script
            src = "/tmp/rasdaman-backup/etc/" + path
            if not os.path.exists(src):
                src = dst
                if not os.path.exists(src):
                    continue

            # Migrate secore_urls from localhost to internal
            if path == "petascope.properties":
                self.update_secore_urls(src)

            # Run update_properties.sh after determining the properties file of
            # the new version (new_dst)
            if path in ["petascope.properties", "secore.properties", "rasfed.properties"]:
                new_dst = dst
                for ext in [".rpmnew", ".dpkg-dist"]:
                    if os.path.exists(dst + ext):
                        new_dst = dst + ext
                        break
                if src != new_dst:
                    self.__update_properties(src, new_dst)

            # Restore the newly updated properties file from
            # /tmp/rasdaman-backup/etc to $RMANHOME/etc
            if src != dst:
                sudo_copy(src, dst, throw_on_error=False)
                sudo_chown(dst, ConfigManager.default_user)
                copied = True
                log.debug("  Restored '" + src + "' to '" + dst + "'")
        if copied:
            log.info("All previous configuration files migrated successfully.")
        else:
            log.info("No previous configuration files found to migrate.")


class PermissionFixPreparer(PreparerDecorator):
    def __init__(self, Preparer, install_path, update):
        """
        Make sure the install_path is owned by the rasdaman user
        :param str install_path: the installation path of rasdaman
        :param bool update: True if updating an existing rasdaman installation
        """
        PreparerDecorator.__init__(self, Preparer)
        self.install_path = install_path
        self.update = update

    def prepare(self):
        PreparerDecorator.prepare(self)
        if self.update:
            # collect paths for which to fix permissions (skip data/ and log/)
            paths = []
            for p in ["bin", "etc", "include", "lib", "share"]:
                path = self.install_path + p
                if os.path.exists(path):
                    paths.append(path)
            # set owner to rasdaman for the collected paths in /opt/rasdaman;
            # this is mostly done to avoid changing ownership of /opt/rasdaman/data,
            # which may have many blob files for which ownership does not change anyway
            executor.executeSudo(["chown", "-R", ConfigManager.default_user + ":"] + paths,
                                 throw_on_error=False, warn_on_error=True)
        else:
            # set owner to rasdaman for everything in /opt/rasdaman
            sudo_chown(self.install_path, ConfigManager.default_user)


class StartServicesPreparer(PreparerDecorator):
    def __init__(self, preparer, install_path, webapps_enabled, external_deployment, port):
        """
        Start rasdaman/tomcat services.
        :param Preparer preparer: the preparer to decorate
        :param str install_path: the installation path
        :param bool start_tomcat: true if external Tomcat should be started or not
        """
        PreparerDecorator.__init__(self, preparer)
        self.install_path = fix_trailing_slash(install_path)
        self.webapps_enabled = webapps_enabled
        self.external_deployment = external_deployment
        self.log_dir = self.install_path + "log"
        self.props_path = self.install_path + "etc/petascope.properties"
        self.tomcat_port = port

    def __test_url(self, url, component, credentials=[]):
        _,_,rc = executor.execute(["wget", "-q", url, "-O", "/dev/null"] + credentials,
                                  throw_on_error=False, warn_on_error=True,
                                  timeout_sec=30)
        if rc != 0:
            log.warn("Test request to {} failed: {}".format(component, url))
        return rc == 0

    def __test_secore(self):
        req = "http://localhost:{}/rasdaman/def/crs/EPSG/0/4326".format(self.tomcat_port)
        return self.__test_url(req, "secore (CRS resolver)")

    def __test_petascope(self):
        # get the authentication_type, we need to know if it's basic_header
        values = get_values_for_property_keys(self.props_path, ["authentication_type"])
        auth_type = ""
        if len(values) == 1:
            auth_type = values[0]

        # credentials for wget, needed if basic_header is enabled
        credentials = []
        if auth_type == "basic_header":
            user, passwd = RasdamanLocalService.get_rasadmin_user(self.props_path)
            if user is None or passwd is None:
                log.warn("Failed retrieving rasdaman_admin_user from " + self.props_path +
                         ", will skip testing whether petascope is running.")
                return False
            else:
                credentials = ["--user=" + user, "--password=" + passwd, "--auth-no-challenge"]

        # execute request
        req = "http://localhost:{}/rasdaman/ows?service=WCS&version=2.0.1&" \
              "request=GetCapabilities".format(self.tomcat_port)
        return self.__test_url(req, "petascope (OGC OWS component)", credentials)

    def __ensure_log_dir(self):
        if not os.path.exists(self.log_dir):
            make_directory(self.log_dir, throw_on_error=False)
            sudo_chmod(self.log_dir, "750")

    def __start_petascope(self):
        if self.webapps_enabled:
            if self.external_deployment:
                tomcat_service.restart()
            # wait for petascope to initialize
            sleep(60)
            return self.__test_secore() and self.__test_petascope()
        else:
            return False

    def prepare(self):
        PreparerDecorator.prepare(self)
        tomcat_type = "external" if self.external_deployment else "standalone"
        start_petascope = self.webapps_enabled and ConfigManager.petascope_available

        if start_petascope:
            log.info("Starting rasdaman and " + tomcat_type + " Tomcat...")
        else:
            log.info("Starting rasdaman...")

        self.__ensure_log_dir()

        # a bit longer way to restart rasdaman, but:
        # - we need to make sure rasdaman is _really_ stopped, and doing it via
        #   service rasdaman stop (i.e. rasdaman_system_service) doesn't work always
        # - at the same time, we should not start rasdaman via start_rasdaman.sh,
        #   as afterwards the service script is broken as it thinks rasdaman is down.
        rasdaman_system_service.stop()
        rasdaman_service.stop()
        rasdaman_system_service.start()

        if start_petascope:
            petascope_started = self.__start_petascope()

        if rasdaman_system_service.running():
            if rasdaman_system_service.running():
                if start_petascope:
                    if petascope_started:
                        log.info("Rasdaman and petascope successfully started.")
                    else:
                        log.warn("Rasdaman successfully started, but petascope "
                                 "failed to respond to requests.")
                        log_dir = self.log_dir
                        if self.external_deployment:
                            log_dir = linux_distro.get_tomcat_logs()
                        log.warn("Please check petascope.log / secore.log in " + log_dir)
                else:
                    log.info("Rasdaman successfully started.")
            else:
                log.warn("Rasdaman is running, but is not operationally available.")
                log.warn("Please check the server logs in " + self.log_dir +
                         " (rasserver.* and rasmgr.*)")
        else:
            log.error("Rasdaman failed to start.")
            log.error("Please check the server logs in " + self.log_dir +
                      " (rasserver.* and rasmgr.*)")

def test():
    #
    # test __update_secore_urls
    #
    install_path = "/tmp/installer_test/"
    etc_path = install_path + "etc/"
    props_path = etc_path + "petascope.properties"
    # mkdir -p returns -1 for some reason.. so set throw_on_error=False
    make_directory(etc_path, throw_on_error=False)

    props_contents = """
#---------------------- General Petascope configuration ------------------------

# Prefix for controller in web application URL routing, e.g the /rasdaman in
# http://localhost:8080/rasdaman/ows
server.contextPath=/rasdaman

# SECORE endpoints to be used by petascope. Multiple endpoints (for fail safety)
# can be specified as comma-separated list, attempted in order as listed.
secore_urls=http://localhost:8081/def
secore_urls=http://localhost/def
secore_urls=https://localhost/rasdaman/def
secore_urls=http://localhost/xyz/def
secore_urls=http://localhost/def,http://opengis.net/def
secore_urls=http://opengis.net/def
secore_urls=http://opengis.net/def,https://ows.rasdaman.org/def
secore_urls=http://opengis.net/def,http://localhost:8080/def
secore_urls=http://opengis.net/def,http://localhost/def
secore_urls=http://opengis.net/def,  http://localhost:8080/def

# secore_urls=http://localhost:8080/def
"""
    write_to_file(props_path, props_contents)

    # __init__(self, preparer, install_path, username, password, url)
    preparer = MigratePreviousVersionConfigsPreparer(PreparerBasis(), install_path)
    preparer.update_secore_urls(props_path)

    updated_props_contents = read_file(props_path)
    expected_props_contents = """
#---------------------- General Petascope configuration ------------------------

# Prefix for controller in web application URL routing, e.g the /rasdaman in
# http://localhost:8080/rasdaman/ows
server.contextPath=/rasdaman

# SECORE endpoints to be used by petascope. Multiple endpoints (for fail safety)
# can be specified as comma-separated list, attempted in order as listed.
secore_urls=internal
secore_urls=internal
secore_urls=internal
secore_urls=http://localhost/xyz/def
secore_urls=internal,http://opengis.net/def
secore_urls=http://opengis.net/def
secore_urls=http://opengis.net/def,https://ows.rasdaman.org/def
secore_urls=http://opengis.net/def,internal
secore_urls=http://opengis.net/def,internal
secore_urls=http://opengis.net/def,  internal

# secore_urls=http://localhost:8080/def
"""

    return updated_props_contents == expected_props_contents


if __name__== "__main__":
    test()
