Exemple #1
0
class Config(object):
    """
        YAML configuration file reader.
    """

    def __init__(self, path):
        self._cfg = None
        self._log = Logger()
        self._path = path
        self.load_config()

    def load_config(self):
        """
            Loads config file.
        """
        config_file = open(self._path, "r")
        self._cfg = yaml.load(config_file)
        config_file.close()
        self._log.info("config file '%s' loaded" % self._path)

    def __getattr__(self, attr):
        """
            Returns configuration value by attribute.
        """
        value = self._cfg.get(attr)
        if not value:
            self._log.warn(
                "could not find value for key '{0}' in '{1}'"
                .format(attr, self._path)
            )
        return value
    def __init__(self, config_path):
        self._log = Logger()

        # load global adapo configuration
        self._adapo_config = Config(self.ADAPO_CONF)
        self._data_path = self._adapo_config.get("data_src_path")

        self._config = Config(config_path)
        self._root_dir = self._config.get("csgo.root_directory")
        self._fastdl_url = self._config.get("server_config.sv_downloadurl")
        self._maps = self._config.get("csgo.maps")
        self._plugins = self._config.get("sourcemod.plugins")

        self._log.info("csgo config file validation initialized")
Exemple #3
0
    def __init__(self, config_path):
        self._log = Logger()

        # load global adapo configuration
        self._global_config = Config(self.ADAPO_CONF)

        self._steamcmd_url = self._global_config.steamcmd_dl_url
        self._steamcmd_path = self._global_config.steamcmd_path

        if not self._steamcmd_url or not self._steamcmd_path:
            self._log.error(
                "steamcmd config attrs are required to"
                " install a csgo server"
            )
            exit(1)

        if not os.path.exists(self._steamcmd_path):
            os.makedirs(self._steamcmd_path)

        self._metamod_url = self._global_config.metamod_dl_url
        self._sourcemod_url = self._global_config.sourcemod_dl_url
        if not self._steamcmd_url or not self._steamcmd_path:
            self._log.error(
                "source & metamode urls are required to install a csgo server"
            )
            exit(1)

        # load specific cs:go server configuration
        self._config = Config(config_path)
        if not self._config.csgo:
            self._log.error(
                "configuration section 'csgo' not found!"
            )
            exit(1)

        self._root_dir = self._config.csgo.get("root_directory")
        if not self._root_dir:
            self._log.error(
                "root directory not set"
            )
            exit(1)



        self._resourcemanager = ResourceManager()
Exemple #4
0
class AdapoCore(object):
    """
        Provides helper functions to trigger
        installer functions per config file
    """

    CONFIG_PATH = "/etc/adapo/servers.d/"

    def __init__(self):
        self._logger = Logger()
        self._configs = []
        self.get_configs()

    def install(self, _):
        """
            trigger installer for every
            loaded config file
        """
        for config in self._configs:
            Installer(config).install()

    def validate(self, _):
        """
            trigger validator for every
            loaded config file
        """
        for config in self._configs:
            if ConfigValidator(config).validate():
                self._logger.info("config file '%s'is valid" % config)
                continue
            self._logger.error("config file '%s'is invalid!" % config)

    def get_configs(self):
        """
            add all config files in
            /etc/adapo/servers.d/
            to list
        """
        self._logger.info("loading server configuration files ...")
        for config in os.listdir(self.CONFIG_PATH):
            if config.endswith(".cfg") and config != "example.cfg":
                self._configs.append(os.path.join(self.CONFIG_PATH, config))
class ResourceManager(object):
    """
        Provides generic resource functions
    """

    LOG_FILE = "/tmp/adapo_installer.log"

    def __init__(self):
        self._logger = Logger()

    def open_subprocess(self, args, cwd):
        """
            open sub process
            pipe stdout and stderr to log file
        """
        self._logger.info(
            "EXECUTING {0} in {1}".format(" ".join(args), cwd)
        )
        proc = subprocess.Popen(
            ["stdbuf", "-oL"] + args,
            cwd=cwd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            bufsize=1,
            close_fds=True
        )

        # FIXME: Use logger class
        log_file = open(self.LOG_FILE, "a")
        for line in iter(proc.stdout.readline, b""):
            log_file.write(line)
            log_file.flush()

        for line in iter(proc.stderr.readline, b""):
            log_file.write(line)
            log_file.flush()

        log_file.close()
        proc.stdout.close()
        ret = proc.wait()

        if ret != 0:
            return False
        return True

    def download(self, url, dst):
        """
            download file from url to given
            destination directory
        """
        self._logger.info("downloading '%s' ..." % url)

        os.chdir(dst)
        filename = url.split("/")[-1]

        ret = subprocess.call(
            [
                "wget",
                url
            ]
        )

        if ret != 0:
            return ""

        return os.path.join(dst, filename)

    def unpack(self, path, dst):
        """
            unpack tar.gz file
        """
        self._logger.info("unpacking '%s' ..." % path)

        return self.open_subprocess(
            [
                "tar",
                "-xvzf",
                path,
                "-C",
                dst
            ],
            "/"
        )

    def copy_tree(self, src, dst):
        """
            copy all files in src directory
            to dst --> cp -r src/* dst/
        """
        if not src.endswith("/"):
            src += "/"

        src += "*"
        cmd = "cp -r %s %s" % (src, dst)

        proc = subprocess.Popen(
            cmd,
            shell="true"
        )
        ret = proc.wait()

        if ret != 0:
            return False

        return True
 def __init__(self):
     self._logger = Logger()
Exemple #7
0
 def __init__(self, path):
     self._cfg = None
     self._log = Logger()
     self._path = path
     self.load_config()
Exemple #8
0
 def __init__(self):
     self._logger = Logger()
     self._configs = []
     self.get_configs()
class ConfigValidator(object):
    """
        Configuration Validator
    """

    ADAPO_CONF = "/etc/adapo/main.cfg"

    def __init__(self, config_path):
        self._log = Logger()

        # load global adapo configuration
        self._adapo_config = Config(self.ADAPO_CONF)
        self._data_path = self._adapo_config.get("data_src_path")

        self._config = Config(config_path)
        self._root_dir = self._config.get("csgo.root_directory")
        self._fastdl_url = self._config.get("server_config.sv_downloadurl")
        self._maps = self._config.get("csgo.maps")
        self._plugins = self._config.get("sourcemod.plugins")

        self._log.info("csgo config file validation initialized")

    def validate(self):
        """
            validate csgo config
        """
        if not self.validate_maps():
            return False
        if not self.validate_plugins():
            return False

        return True

    def validate_plugins(self):
        """
            check if all listed plugins are
            available in data/plugins directory
        """
        self._log.info("validating plugins ...")

        for plugin in self._plugins:
            path = os.path.join(self._data_path, "plugins", plugin)

            if os.path.exists("%s.smx" % path):
                self._log.info("found simple plugin '%s.smx'" % path)
                continue

            if os.path.isdir(path):
                self._log.info("found complex plugin '%s'" % path)
                continue

            self._log.error("could not find plugin '%s(.smx)'!" % path)
            return False

        return True

    def validate_maps(self):
        """
            check if all listed maps are
            available on the fastdl server
        """
        self._log.info("validating maps ...")

        maps_url = "%s/maps/" % self._fastdl_url
        pattern = r'href=[\'"]?([^\'" >]+)'
        response = None

        try:
            response = urllib2.urlopen(maps_url).read()
        except urllib2.URLError:
            self._log.error(
                "fastdl server '%s' unreachable" % self._fastdl_url
            )
            return False

        # get all present maps from fastdl_url
        maps_present = []
        for map_url in re.findall(pattern, response):
            if 'bz2' in map_url:
                map_name = map_url.split(".")[0]
                maps_present.append(map_name)

        for _map in self._maps:
            if _map not in maps_present:
                self._log.error(
                    "map '%s' not available on fastdl server" % _map
                )
                return False
            self._log.info("map '%s' found on fastdl server" % _map)
Exemple #10
0
class Installer(object):
    """
        CS:GO Server Installer
    """

    LOG_FILE = "/tmp/adapo_installer.log"
    ADAPO_CONF = "/etc/adapo/main.cfg"

    def __init__(self, config_path):
        self._log = Logger()

        # load global adapo configuration
        self._global_config = Config(self.ADAPO_CONF)

        self._steamcmd_url = self._global_config.steamcmd_dl_url
        self._steamcmd_path = self._global_config.steamcmd_path

        if not self._steamcmd_url or not self._steamcmd_path:
            self._log.error(
                "steamcmd config attrs are required to"
                " install a csgo server"
            )
            exit(1)

        if not os.path.exists(self._steamcmd_path):
            os.makedirs(self._steamcmd_path)

        self._metamod_url = self._global_config.metamod_dl_url
        self._sourcemod_url = self._global_config.sourcemod_dl_url
        if not self._steamcmd_url or not self._steamcmd_path:
            self._log.error(
                "source & metamode urls are required to install a csgo server"
            )
            exit(1)

        # load specific cs:go server configuration
        self._config = Config(config_path)
        if not self._config.csgo:
            self._log.error(
                "configuration section 'csgo' not found!"
            )
            exit(1)

        self._root_dir = self._config.csgo.get("root_directory")
        if not self._root_dir:
            self._log.error(
                "root directory not set"
            )
            exit(1)



        self._resourcemanager = ResourceManager()

    def install(self):
        """
            install csgo server
        """
        if not self.install_steamcmd():
            self._log.error(
                "steamcmd installation failed, "
                "check '%s' for errors!" % self.LOG_FILE
            )
            return False
        self._log.info("steamcmd successfully installed")

        if not self.install_csgo():
            self._log.error(
                "csgo installation failed, "
                "check '%s' for errors!" % self.LOG_FILE
            )
            return False
        self._log.info("csgo successfully installed")

        if not self.install_metamod():
            self._log.error(
                "metamod installation failed, "
                "check '%s' for errors!" % self.LOG_FILE
            )
            return False
        self._log.info("metamod successfully installed")

        if not self.install_sourcemod():
            self._log.error(
                "sourcemod installation failed, "
                "check '%s' for errors!" % self.LOG_FILE
            )
            return False
        self._log.info("sourcmod successfully installed")

        if not self.install_plugins():
            self._log.error(
                "plugin installation failed, "
                "check '%s' for errors!" % self.LOG_FILE
            )
            return False
        self._log.info("plugins successfully installed")

        if not self.install_maps():
            self._log.error(
                "map installation failed, "
                "check '%s' for errors!" % self.LOG_FILE
            )
            return False
        self._log.info("maps successfully installed")

        if not self.write_server_config():
            self._log.error(
                "could not install config!, "
                "check '%s' for errors!" % self.LOG_FILE
            )
            return False
        self._log.info("server config successfully installed")

        if not self.create_start_script():
            self._log.error(
                "could not create start script!, "
                "check '%s' for errors!" % self.LOG_FILE
            )
            self._log.info("start script successfully written")

        return True

    def uninstall(self):
        """
            uninstall csgo server
        """
        # FIXME: Implement uninstall
        self._log.info("uninstall not implemented yet")

    def install_csgo(self):
        """
            install csgo server
        """
        self._log.info("installing csgo with steamcmd ...")

        if not os.path.exists(self._root_dir):
            os.makedirs(self._root_dir)

        return self._resourcemanager.open_subprocess(
            [
                "./steamcmd.sh",
                "+login",
                "anonymous",
                "+force_install_dir",
                self._root_dir,
                "+app_update",
                "740",
                "+quit"
            ],
            self._steamcmd_path
        )

    def download_steamcmd(self):
        """
            download steamcmd.tar.gz
        """
        self._log.info("downloading steamcmd ...")

        return self._resourcemanager.download(
            self._steamcmd_url,
            self._steamcmd_path
        )

    def clean_steamcmd(self):
        """
            clean steamcmd directory
        """
        self._log.info("cleaning up steamcmd directory ...")

        steamcmd_tar = self._steamcmd_url.split("/")[-1]
        path = os.path.join(self._steamcmd_path, steamcmd_tar)

        if os.path.exists(path):
            os.remove(path)

        return True

    def install_steamcmd(self):
        """
            installs steamcmd
        """
        self._log.info("installing steamcmd ...")

        if not os.path.exists(self._steamcmd_path):
            os.makedirs(self._steamcmd_path)

        steamcmd_tar = self._steamcmd_url.split("/")[-1]
        steamcmd_tar = os.path.join(
            self._steamcmd_path,
            steamcmd_tar
        )

        if os.path.exists(steamcmd_tar):
            self._log.error("steamcmd_linux.tar.gz already exists!")
            return False

        if not self.download_steamcmd():
            self._log.error("could not download steamcmd!")
            return False
        self._log.info("steamcmd successfully downloaded")

        if not self._resourcemanager.unpack(steamcmd_tar, self._steamcmd_path):
            self._log.error("could not unpack steamcmd!")
            return False
        self._log.info("steamcmd successfully unpacked")

        if not self.clean_steamcmd():
            self._log.error("could not clean steamcmd!")
            return False
        self._log.info("steamcmd successfully cleaned")

        return True

    def download_sourcemod(self):
        """
            download sourcemod
        """
        sourcemod_tar = self._sourcemod_url.split("/")[-1]
        sourcemod_tar_path = os.path.join(self._root_dir, "csgo", sourcemod_tar)

        if os.path.exists(sourcemod_tar_path):
            self._log.info(
                "sourcemod already cached, if you want to redownload it"
                " remove the sourcemod tar file: '{0}' ..."
                .format(sourcemod_tar_path)
            )
            return sourcemod_tar_path

        self._log.info("downloading sourcemod ...")
        return self._resourcemanager.download(
            self._sourcemod_url,
            os.path.join(self._root_dir, "csgo")
        )

    def install_sourcemod(self):
        """
            install sourcemod to csgo root dir
        """
        self._log.info("installing sourcemod ...")
        sourcemod_tar = self.download_sourcemod()
        if not sourcemod_tar:
            self._log.error("could not download sourcemod!")
            return False

        dst = "/".join(sourcemod_tar.split("/")[:-1])
        if not self._resourcemanager.unpack(sourcemod_tar, dst):
            self._log.error("could not unpack sourcemod!")
            return False

        if not self.write_admins_config():
            self._log.error("could not write admins_simple.ini")
            return False
        self._log.info("admins_simple.ini successfully written")

        if not self.write_databases_config():
            self._log.error("could not write databases.cfg")
            return False
        self._log.info("databases.cfg successfully written")

        return True

    def download_metamod(self):
        """
            download metamod
        """
        metamod_tar = self._metamod_url.split("/")[-1]
        metamod_tar_path = os.path.join(self._root_dir, "csgo", metamod_tar)

        if os.path.exists(metamod_tar_path):
            self._log.info(
                "metamod already cached, if you want to redownload it"
                " remove the metamod tar file: '{0}' ..."
                .format(metamod_tar_path)
            )
            return metamod_tar_path

        self._log.info("downloading metamod ...")
        return self._resourcemanager.download(
            self._metamod_url,
            os.path.join(self._root_dir, "csgo")
        )

    def install_metamod(self):
        """
            install metamod to csgo root dir
        """
        self._log.info("installing metamod ...")
        metamod_tar = self.download_metamod()
        if not metamod_tar:
            self._log.error("could not download metamod!")
            return False

        dst = "/".join(metamod_tar.split("/")[:-1])
        if not self._resourcemanager.unpack(metamod_tar, dst):
            self._log.error("could not unpack metamod!")
            return False

        metamod_vdf = os.path.join(self._root_dir, "csgo/addons/metamod.vdf")
        with open(metamod_vdf, "w") as _file:
            _file.write('"Plugin"\n')
            _file.write('{\n')
            _file.write('\t"file"  "../csgo/addons/metamod/bin/server"\n')
            _file.write('}\n')

        return True

    def install_plugins(self):
        """
            install sourcemod plugins
        """
        self._log.info("installing plugins ...")

        sourcemod_cfg = self._config.sourcemod
        plugins = sourcemod_cfg.get("plugins")

        for plugin in plugins:
            self._log.info("installing plugin '%s' ..." % plugin)

            data_path = self._global_config.data_src_path
            if not data_path:
                return False

            plugin_path = os.path.join(data_path, "plugins", plugin)

            if os.path.exists(plugin_path + ".smx"):
                plugin_path = plugin_path + ".smx"

            if not os.path.exists(plugin_path):
                self._log.error(
                    "could not find plugin files for '%s'" % plugin_path
                )
                continue

            src = plugin_path
            dst = self._root_dir

            if plugin_path.endswith(".smx"):
                dst = os.path.join(
                    self._root_dir,
                    "csgo/addons/sourcemod/plugins/"
                )
                shutil.copy2(src, dst)
                continue

            self._resourcemanager.copy_tree(src, dst)

        self._log.info("simple plugins successfully installed")
        return True

    def dowload_map(self, map_name):
        """
            download map from fastdl server
        """
        server_cfg = self._config.server_config
        if not server_cfg:
            return False

        fastdl_url = server_cfg.get("sv_downloadurl")
        url = fastdl_url + "maps/" + map_name + ".bsp.bz2"
        maps_dir = os.path.join(
            self._root_dir,
            "csgo/maps"
        )
        return self._resourcemanager.download(url, maps_dir)

    def unpack_maps(self):
        """
            unpack all maps (*.bz2)
            in csgo/maps
        """
        maps_dir = os.path.join(
            self._root_dir,
            "csgo/maps"
        )

        for map_file in os.listdir(maps_dir):
            if not map_file.endswith(".bsp.bz2"):
                continue

            self._log.info("unpacking map '%s' ..." % map_file)

            ret = self._resourcemanager.open_subprocess(
                [
                    "bzip2",
                    "-d",
                    map_file
                ],
                maps_dir
            )

            if not ret:
                return False

        return True

    def install_maps(self):
        """
            install maps if maps are not
            already in maps dir
        """
        maps_dir = os.path.join(
            self._root_dir,
            "csgo/maps"
        )

        maps_installed = os.listdir(maps_dir)

        csgo_cfg = self._config.csgo

        for _map in csgo_cfg.get("maps"):
            map_name = _map + ".bsp"

            if map_name in maps_installed:
                self._log.info("map '%s' already installed" % map_name)
                continue

            self._log.info("installing map '%s' ..." % map_name)
            ret = self.dowload_map(_map)

            if not ret:
                return ret

        if not self.unpack_maps():
            return False

        self._log.info("writing maps to maplist.txt & mapcycle.txt ...")

        maplist_file = os.path.join(
            self._root_dir,
            "csgo/maplist.txt"
        )

        mapcycle_file = os.path.join(
            self._root_dir,
            "csgo/mapcycle.txt"
        )

        with open(maplist_file, "w") as maplist:
            for _map in csgo_cfg.get("maps"):
                maplist.write(_map)
                maplist.write("\n")

        shutil.copy2(maplist_file, mapcycle_file)

        return True

    def install_config(self):
        """
            install/write specific config files
        """
        if not self.write_server_config():
            self._log.error("could not write server config")
            return False

        return True

    def write_server_config(self):
        """
            write config server.cfg
        """
        server_cfg_file = os.path.join(
            self._root_dir,
            "csgo/cfg/server.cfg"
        )

        self._log.info("generating '%s' ..." % server_cfg_file)

        with open(server_cfg_file, "w") as config_file:
            server_vars = self._config.server_config
            for key, value in server_vars.iteritems():
                config_file.write(
                    '%s "%s"\n' % (key, value)
                )

        return True

    def create_start_script(self):
        """
            create start.sh script in csgo root dir
            example:
            ./srcds_run -game csgo -console -usercon +game_type 0 +game_mode 0
            +map am_must2 -tickrate 128 -maxplayers_override 32 -condebug
        """
        csgo_cfg = self._config.csgo

        gametype = csgo_cfg.get("game_type")
        gamemode = csgo_cfg.get("game_mode")
        start_map = csgo_cfg.get("map")
        tickrate = csgo_cfg.get("tickrate")
        max_players = csgo_cfg.get("max_players")
        ip_addr = csgo_cfg.get("ip")
        port = csgo_cfg.get("port")

        cmd = os.path.join(self._root_dir, "srcds_run")
        args = [
            "-game csgo",
            "-console",
            "-usercon"
        ]

        if gametype is not None:
            arg = "%s %s" % (Parameters.GAME_TYPE, gametype)
            args.append(arg)
        if gamemode is not None:
            arg = "%s %s" % (Parameters.GAME_MODE, gamemode)
            args.append(arg)
        if start_map:
            arg = "%s %s" % (Parameters.MAP, start_map)
            args.append(arg)
        if tickrate:
            arg = "%s %s" % (Parameters.TICKRATE, tickrate)
            args.append(arg)
        if max_players:
            arg = "%s %s" % (Parameters.MAX_PLAYERS, max_players)
            args.append(arg)
        if ip_addr:
            arg = "%s %s" % (Parameters.IP_ADDR, ip_addr)
            args.append(arg)
        if port:
            arg = "%s %s" % (Parameters.PORT, port)
            args.append(arg)

        start_script_path = os.path.join(self._root_dir, "start.sh")
        arg_string = " ".join(args)

        with open(start_script_path, "w") as start_script_file:
            start_script_file.write("%s %s" % (cmd, arg_string))

        # set execute permission
        sta = os.stat(start_script_path)
        os.chmod(start_script_path, sta.st_mode | stat.S_IEXEC)

        return True

    def write_admins_config(self):
        """
            write config admins_simple.ini
        """
        admins_config_file = os.path.join(
            self._root_dir,
            "csgo/addons/sourcemod/configs/admins_simple.ini"
        )

        self._log.info("generating '%s' ..." % admins_config_file)

        sourcemod_cfg = self._config.sourcemod
        users = sourcemod_cfg.get("users")
        if not users:
            self._log.info("No users found to write to admis_simple.ini")
            return True

        with open(admins_config_file, "w") as config_file:
            for user in users:
                config_file.write(
                    '"%s" "%s"\n' % (user["steam_id"], user["flags"])
                )

        return True

    def write_databases_config(self):
        """
            write database config databases.cfg
        """
        sourcemod_cfg = self._config.sourcemod
        configured_dbs = sourcemod_cfg.get("databases")

        if not configured_dbs:
            self._log.info("no databases configured")
            return True

        database_config_path = os.path.join(
            self._root_dir,
            "csgo/addons/sourcemod/configs/databases.cfg"
        )

        db_config_file = open(database_config_path, "r")
        self._log.info(
            "loading databases configuration '%s' ..." % database_config_path
        )
        db_config = vdf.load(db_config_file, mapper=OrderedDict)
        db_config_file.close()

        for database_name, database_config in configured_dbs.iteritems():
            db_config["Databases"][database_name] = database_config

        self._log.info(
            "writing databases config '%s' ..." % database_config_path
        )
        with open(database_config_path, "w") as config_file:
            config_file.write(vdf.dumps(db_config, pretty=True))

        return True