示例#1
0
    def uninstall_package(self, pkg_type, id):
        """ Uninstall a package
            For the moment, we will only delete the package Json file for 
            plugins and external
            @param pkg_type : package type
            @param id : package id
        """
        if PACKAGE_MODE != True:
            raise PackageException("Package mode not activated")
        self.log("Start uninstall for package '%s-%s'" % (pkg_type, id))
        self.log(
            "Only Json description file will be deleted in this Domogik version"
        )

        try:
            if pkg_type in ('plugin'):
                os.unlink("%s/domogik_packages/plugins/%s.json" %
                          (INSTALL_PATH, id))
            elif pkg_type in ('external'):
                os.unlink("%s/domogik_packages/externals/%s.json" %
                          (INSTALL_PATH, id))
            else:
                raise PackageException("Package type '%s' not uninstallable" %
                                       pkg_type)
        except:
            msg = "Error while unstalling package : %s" % (
                traceback.format_exc())
            self.log(msg)
            raise PackageException(msg)
        self.log("Package successfully uninstalled.")

        return True
示例#2
0
    def get_available_updates(self, pkg_type, pkg_id, version):
        """ List all available updates for a package
            @param pkg_type : package type
            @param id : package id
            @param version : package version
        """
        if PACKAGE_MODE != True:
            raise PackageException("Package mode not activated")

        pkg_list = []
        for root, dirs, files in os.walk(REPO_CACHE_DIR):
            for fic in files:
                if fic[-5:] != ".json":
                    continue
                my_json = json.load(open("%s/%s" % (root, fic)))
                for my_pkg in my_json["packages"]:
                    if pkg_type == my_pkg["type"] and \
                       pkg_id == my_pkg["id"] and \
                       version < my_pkg["version"]:
                        pkg_list.append({
                            "type": pkg_type,
                            "id": pkg_id,
                            "version": my_pkg["version"],
                            "priority": my_pkg["priority"],
                            "changelog": my_pkg["changelog"]
                        })
        return pkg_list
示例#3
0
    def cache_package(self, cache_dir, pkg_type, id, version, pkg_path=None):
        """ Download package to put it in cache
            @param cache_dir : folder in which we want to cache the file
            @param pkg_type : package type
            @param id : package id
            @param version : package version
            @param pkg_path : path of the package to cache on local host
        """
        if PACKAGE_MODE != True:
            raise PackageException("Package mode not activated")
        dl_path = "%s/%s-%s-%s.tgz" % (cache_dir, pkg_type, id, version)

        ### cache from the web
        if pkg_path == None:
            package = "%s-%s" % (pkg_type, id)
            pkg, status = self._find_package(package, version)
            if status != True:
                return False
            # download package
            path = pkg["archive_url"]
            self.log("Caching package : '%s' to '%s'" % (path, dl_path))
            urllib.urlretrieve(path, dl_path)
        ### cache from a local file
        else:
            self.log("Caching package : '%s' to '%s'" % (pkg_path, dl_path))
            shutil.copyfile(pkg_path, dl_path)
        self.log("OK")
        return True
示例#4
0
    def _create_tar_gz(self,
                       name,
                       output_dir,
                       files,
                       info_file=None,
                       icon_file=None,
                       doc_path=None):
        """ Create a .tar.gz file anmmed <name.tgz> which contains <files>
            @param name : file name
            @param output_dir : if != None, the path to put .tar.gz
            @param files : table of file names to add in tar.gz
            @param info_file : path for info.json file
            @param icon_file : path for icon.png file
            @param doc_path : path for doc
        """
        if output_dir == None:
            my_tar = "%s/%s.tgz" % (tempfile.gettempdir(), name)
        else:
            my_tar = "%s/%s.tgz" % (output_dir, name)
        self.log("Generating package : '%s'" % my_tar)
        try:
            tar = tarfile.open(my_tar, "w:gz")
            for my_file in files:
                path = str(my_file)
                self.log("- %s" % path)
                if os.path.isfile(SRC_PATH + path):
                    tar.add(SRC_PATH + path, arcname=path)
                elif os.path.isdir(SRC_PATH + path):
                    self.log("  (directory)")
                    tar.add(SRC_PATH + path, arcname=path)
                else:
                    self.log("  WARNING : file doesn't exists : %s" %
                             SRC_PATH + path)
            if info_file != None:
                self.log("- info.json")
                tar.add(info_file, arcname="info.json")
            if icon_file != None:
                if os.path.isfile(icon_file):
                    self.log("- icon.png")
                    tar.add(icon_file, arcname="icon.png")
            if doc_path != None:
                self.log("- package documentation")
                tar.add(doc_path, arcname="docs")
            tar.close()

            # delete temporary Json file
            if info_file != None:
                os.unlink(info_file)
        except:
            msg = "Error generating package : %s : %s" % (
                my_tar, traceback.format_exc())
            self.log(msg)
            # delete temporary Json file
            if info_file != None:
                os.unlink(info_file)
            raise PackageException(msg)
        self.log("OK")
示例#5
0
 def _create_folder(self, folder):
     """ Try to create a folder (does nothing if it already exists)
         @param folder : folder path
     """
     try:
         if os.path.isdir(folder) == False:
             self.log("Creating directory : %s" % folder)
             os.makedirs(folder)
     except:
         msg = "Error while creating temporary folder '%s' : %s" % (
             folder, traceback.format_exc())
         self.log(msg)
         raise PackageException(msg)
示例#6
0
 def _extract_package(self, pkg_path, extract_path):
     """ Extract package <pkg_path> in <extract_path>
         @param pkg_path : path to package
         @param extract_path : path for extraction
     """
     tar = tarfile.open(pkg_path)
     # check if there is no .. or / in files path
     for fic in tar.getnames():
         if fic[0:1] == "/" or fic[0:2] == "..":
             msg = "Error while extracting package '%s' : filename '%s' in tgz not allowed" % (
                 pkg_path, fic)
             self.log(msg)
             raise PackageException(msg)
     tar.extractall(path=extract_path)
     tar.close()
示例#7
0
 def get_installed_packages_list(self):
     """ List all packages in install folder 
         and return a detailed list
     """
     if PACKAGE_MODE != True:
         raise PackageException("Package mode not activated")
     pkg_list = []
     for rep in [PLUGIN_JSON_PATH, EXTERNAL_JSON_PATH]:
         for root, dirs, files in os.walk(rep):
             for fic in files:
                 if fic[-5:] == ".json":
                     pkg_json = PackageJson(path="%s/%s" % (root, fic)).json
                     # TODO : replace by identity and repo informations
                     #   from the json ???
                     pkg_list.append(pkg_json["identity"])
     return sorted(pkg_list, key=lambda k: (k['fullname'], k['version']))
示例#8
0
 def _clean_folder(self, folder):
     """ Delete the content of a folder
         @param folder: folder to clean
     """
     # Clean folder
     try:
         for root, dirs, files in os.walk(folder):
             for fic in files:
                 os.unlink(os.path.join(root, fic))
             for dir in dirs:
                 shutil.rmtree(os.path.join(root, dir))
     except:
         msg = "Error while cleaning cache folder '%s' : %s" % (
             folder, traceback.format_exc())
         self.log(msg)
         raise PackageException(msg)
示例#9
0
 def get_repositories_list(self):
     """ Read repository source file and return list
     """
     try:
         repo_list = []
         src_file = open(REPO_SRC_FILE, "r")
         for line in src_file.readlines():
             # if the line is not a comment
             if line.strip()[0] != "#":
                 url = line.split()[1]
                 # remove all useless final "/"
                 while url[-1] == "/":
                     url = url[0:-1]
                 repo_list.append({"priority": line.split()[0], "url": url})
         src_file.close()
     except:
         msg = "Error reading source file : %s : %s" % (
             REPO_SRC_FILE, str(traceback.format_exc()))
         self.log(msg)
         raise PackageException(msg)
     # return sorted list
     return sorted(repo_list, key=lambda k: k['priority'], reverse=True)
示例#10
0
    def get_packages_list(self, fullname=None, version=None, pkg_type=None):
        """ List all packages in cache folder 
            and return a detailed list
            @param fullname (optionnal) : fullname of a package
            @param version (optionnal) : version of a package (to use with name)
            @param pkg_type (optionnal) : package type
            Used by Rest
        """
        if PACKAGE_MODE != True:
            raise PackageException("Package mode not activated")

        pkg_list = []
        for root, dirs, files in os.walk(REPO_CACHE_DIR):
            for fic in files:
                if fic[-5:] != ".json":
                    continue
                my_json = json.load(open("%s/%s" % (root, fic)))
                for my_pkg in my_json["packages"]:
                    if fullname == None or (fullname == my_pkg["fullname"]
                                            and version == my_pkg["version"]):
                        if pkg_type == None or pkg_type == my_pkg["type"]:
                            pkg_list.append(my_pkg)
        return sorted(pkg_list, key=lambda k: (k['id']))
示例#11
0
    def _install_plugin_or_external(self, pkg_dir, install_path, pkg_type,
                                    package_part):
        """ Install plugin
            @param pkg_dir : directory where package is extracted
            @param install_path : path where we install packages
            @param pkg_type : plugin, external
            @param pkg_id : package id
            @param package_part : PKG_PART_XPL (for manager), PKG_PART_RINOR (for RINOR)
            @param repo_source : path from which the package comes
        """

        ### create needed directories
        # create install directory
        self.log("Creating directories for %s..." % pkg_type)
        plg_path = "%s/domogik_packages/" % (install_path)
        self._create_folder(plg_path)

        ### copy files
        self.log("Copying files for %s..." % pkg_type)
        try:
            # xpl/* and plugins/*.json are installed on target host
            if package_part == PKG_PART_XPL:
                if pkg_type == "plugin":
                    copytree("%s/src/domogik_packages/xpl" % pkg_dir,
                             "%s/xpl" % plg_path, self.log)
                    copytree("%s/src/domogik_packages/tests" % pkg_dir,
                             "%s/tests" % plg_path, self.log)
                    self._create_init_py("%s/" % plg_path)
                    self._create_init_py("%s/xpl/" % plg_path)
                    self._create_init_py("%s/xpl/bin/" % plg_path)
                    self._create_init_py("%s/xpl/lib/" % plg_path)
                    self._create_init_py("%s/xpl/helpers/" % plg_path)
                    self._create_init_py("%s/tests/" % plg_path)
                    self._create_init_py("%s/tests/plugin/" % plg_path)
                    type_path = "plugins"
                if pkg_type == "external":
                    type_path = "externals"
                print("%s => %s" %
                      ("%s/src/share/domogik/%ss" %
                       (pkg_dir, pkg_type), "%s/%s" % (plg_path, type_path)))
                copytree("%s/src/share/domogik/%ss" % (pkg_dir, pkg_type),
                         "%s/%s" % (plg_path, type_path), self.log)
                copytree("%s/src/share/domogik/data/" % pkg_dir,
                         "%s/data/" % plg_path, self.log)

            # design/*
            # stats/*
            # url2xpl/*
            # exernal/* are installed on rinor host
            if package_part == PKG_PART_RINOR:
                copytree("%s/src/share/domogik/design/" % pkg_dir,
                         "%s/design/" % plg_path, self.log)
                #copytree("%s/src/share/domogik/url2xpl/" % pkg_dir, "%s/url2xpl/" % plg_path, self.log)
                #copytree("%s/src/share/domogik/stats/" % pkg_dir, "%s/stats/" % plg_path, self.log)
                copytree("%s/src/external/" % pkg_dir,
                         "%s/external" % plg_path, self.log)
                copytree("%s/src/domogik_packages/conversions" % pkg_dir,
                         "%s/conversions" % plg_path, self.log)
        except:
            msg = "Error while copying %s files : %s" % (
                pkg_type, traceback.format_exc())
            self.log(msg)
            raise PackageException(msg)
示例#12
0
    def install_package(self, path, version=None, package_part=PKG_PART_XPL):
        """ Install a package
            0. Eventually download package
            1. Extract tar.gz
            2. Install package
            3. Insert data in database
            @param path : path for tar.gz
            @param version : version to install (default : highest)
            @param package_part : PKG_PART_XPL (for manager), PKG_PART_RINOR (for RINOR)
        """
        if PACKAGE_MODE != True:
            raise PackageException("Package mode not activated")
        self.log("Start install for part '%s' of '%s'" % (package_part, path))
        if path[0:6] == "cache:":
            path = "%s/package/download/%s" % (REST_URL, path[6:])

        if path[0:5] == "repo:":
            pkg, status = self._find_package(path[5:], version)
            if status != True:
                return status
            path = pkg.archive_url

        # get package name
        if path[0:4] == "http":  # special process for a http path
            id = full_name = '-'.join(path.split("/")[-3:])
            print("id=%s" % full_name)
        else:
            full_name = os.path.basename(path)
            # twice to remove first .gz and then .tar
            id = os.path.splitext(full_name)[0]
            id = os.path.splitext(id)[0]

        self.log("Ask for installing package id : %s" % id)

        # get temp dir to extract data
        my_tmp_dir_dl = TMP_EXTRACT_DIR
        my_tmp_dir = "%s/%s" % (my_tmp_dir_dl, id)
        self._create_folder(my_tmp_dir)

        # Check if we need to download package
        if path[0:4] == "http":
            dl_path = "%s/%s.tgz" % (my_tmp_dir_dl, full_name)
            self.log("Downloading package : '%s' to '%s'" % (path, dl_path))
            urllib.urlretrieve(path, dl_path)
            path = dl_path
            self.log("Package downloaded : %s" % path)

        # extract in tmp directory
        self.log("Extracting package...")
        try:
            self._extract_package(path, my_tmp_dir)
        except:
            msg = "Error while extracting package '%s' : %s" % (
                path, traceback.format_exc())
            self.log(msg)
            raise PackageException(msg)
        self.log("Package successfully extracted.")

        # get Json informations
        pkg_json = PackageJson(path="%s/info.json" % my_tmp_dir).json

        # check compatibility with domogik installed version
        __import__("domogik")
        dmg = sys.modules["domogik"]
        self.log("Domogik version = %s" % dmg.__version__)
        self.log("Minimum Domogik version required for package = %s" %
                 pkg_json["identity"]["domogik_min_version"])
        print("%s < %s" %
              (pkg_json["identity"]["domogik_min_version"], dmg.__version__))
        if pkg_json["identity"]["domogik_min_version"] > dmg.__version__:
            msg = "This package needs a Domogik version >= %s. Actual is %s. Installation ABORTED!" % (
                pkg_json["identity"]["domogik_min_version"], dmg.__version__)
            self.log(msg)
            raise PackageException(msg)

        # check the json_version file
        self.log("Required json version = %s" % MIN_JSON_VERSION)
        self.log("Package json version = %s" % pkg_json["json_version"])
        if pkg_json["json_version"] < MIN_JSON_VERSION:
            msg = "This package has json_version set to %s, but Domogik needs at least %s" % (
                pkg_json["json_version"], MIN_JSON_VERSION)
            self.log(msg)
            raise PackageException(msg)

        # create install directory
        self._create_folder(INSTALL_PATH)

        # install plugin in $HOME
        self.log("Installing package (%s)..." % pkg_json["identity"]["type"])
        try:
            if pkg_json["identity"]["type"] in ('plugin', 'external'):
                self._install_plugin_or_external(my_tmp_dir, INSTALL_PATH,
                                                 pkg_json["identity"]["type"],
                                                 package_part)
            else:
                raise "Package type '%s' not installable" % pkg_json[
                    "identity"]["type"]
        except:
            msg = "Error while installing package : %s" % (
                traceback.format_exc())
            self.log(msg)
            raise PackageException(msg)
        self.log("Package successfully extracted.")

        # insert data in database
        if pkg_json["identity"]["type"] in ('plugin', 'external'):
            if package_part == PKG_PART_RINOR:
                self.log("Insert data in database...")
                pkg_data = PackageData("%s/info.json" % my_tmp_dir)
                pkg_data.insert()

        self.log("Package installation finished")
        return True
示例#13
0
        """ Create __init__.py file in path
            param path : path where we wan to create the file
        """
        try:
            self.log("Create __init__.py file in %s" % path)
            open("%s/__init__.py" % path, "a").close()
        except IOError as (errno, strerror):
            if errno == 2:
                self.log("No directory '%s'" % path)
                return
            raise
        except:
            msg = "Error while creating __init__.py file in %s : %s" % (
                path, traceback.format_exc())
            self.log(msg)
            raise PackageException(msg)

    def update_cache(self):
        """ update local package cache
        """
        if PACKAGE_MODE != True:
            self.log("Update cache not possible : Package mode not activated")
            return
        # Get repositories list
        try:
            # Read repository source file and generate repositories list
            repo_list = self.get_repositories_list()
        except:
            self.log(str(traceback.format_exc()))
            return False