当前位置: 首页>>代码示例>>Python>>正文


Python utils.blender函数代码示例

本文整理汇总了Python中utils.blender函数的典型用法代码示例。如果您正苦于以下问题:Python blender函数的具体用法?Python blender怎么用?Python blender使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。


在下文中一共展示了blender函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。

示例1: generate_kickstart_for_profile

    def generate_kickstart_for_profile(self,g):

        g = self.api.find_profile(name=g)
        if g is None:
           return "# profile not found"

        distro = g.get_conceptual_parent()
        meta = utils.blender(self.api, False, g)
        if distro is None:
           raise CX(_("profile %(profile)s references missing distro %(distro)s") % { "profile" : g.name, "distro" : g.distro })
        kickstart_path = utils.find_kickstart(meta["kickstart"])
        if kickstart_path is not None and os.path.exists(kickstart_path):
            # the input is an *actual* file, hence we have to copy it
            try:
                meta = utils.blender(self.api, False, g)
                ksmeta = meta["ks_meta"]
                del meta["ks_meta"]
                meta.update(ksmeta) # make available at top level
                meta["yum_repo_stanza"] = self.generate_repo_stanza(g,True)
                meta["yum_config_stanza"] = self.generate_config_stanza(g,True)
                meta["kickstart_done"]  = self.generate_kickstart_signal(0, g, None)
                meta["kickstart_start"] = self.generate_kickstart_signal(1, g, None)
                meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])
                kfile = open(kickstart_path)
                data = self.templar.render(kfile, meta, None, g)
                kfile.close()
                return data
            except:
                utils.log_exc(self.api.logger)
                raise

        elif kickstart_path is not None and not os.path.exists(kickstart_path):
            if kickstart_path.find("http://") == -1 and kickstart_path.find("ftp://") == -1 and kickstart_path.find("nfs:") == -1:
                return "# Error, cannot find %s" % kickstart_path
        return "# kickstart is sourced externally, or is missing, and cannot be displayed here: %s" % meta["kickstart"]
开发者ID:icontender,项目名称:cobbler,代码行数:35,代码来源:kickgen.py

示例2: run

def run(api,args,logger):
    # FIXME: make everything use the logger, no prints, use util.subprocess_call, etc

    objtype = args[0] # "system" or "profile"
    name    = args[1] # name of system or profile
    ip      = args[2] # ip or "?"

    if objtype == "system":
        target = api.find_system(name)
    else:
        target = api.find_profile(name)

    # collapse the object down to a rendered datastructure
    target = utils.blender(api, False, target)

    if target == {}:
        logger.info("unable to locate %s " % name)
        raise CX("failure looking up target")

    if target['ks_meta']['vms']:
        for vm in target['ks_meta']['vms'].split(','):
            try:
                arglist = ["/usr/local/bin/createvm",target['ip_address_vmnic1'],vm,target['server']]
                logger.info("creating virtual guest %s" % vm)
                rc = utils.subprocess_call(logger, arglist, shell=False)
            except Exception, reason:
                logger.error("unable to create %s: %s" % (name,reason))
            if rc != 0:
                raise CX("cobbler trigger failed: %(file)s returns ")
开发者ID:optionalg,项目名称:vmware_misc,代码行数:29,代码来源:install_firstboot_createvms.py

示例3: generate_kickstart

    def generate_kickstart(self, profile=None, system=None):

        obj = system
        if system is None:
            obj = profile

        meta = utils.blender(self.api, False, obj)
        kickstart_path = utils.find_kickstart(meta["kickstart"])

        if not kickstart_path:
            return "# kickstart is missing or invalid: %s" % meta["kickstart"]

        ksmeta = meta["ks_meta"]
        del meta["ks_meta"]
        meta.update(ksmeta) # make available at top level
        meta["yum_repo_stanza"] = self.generate_repo_stanza(obj, (system is None))
        meta["yum_config_stanza"] = self.generate_config_stanza(obj, (system is None))
        meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])
        # meta["config_template_files"] = self.generate_template_files_stanza(g, False)

        try:
            raw_data = utils.read_file_contents(kickstart_path, self.api.logger,
                    self.settings.template_remote_kickstarts)
            if raw_data is None:
                return "# kickstart is sourced externally: %s" % meta["kickstart"]
            data = self.templar.render(raw_data, meta, None, obj)
            return data
        except FileNotFoundException:
            self.api.logger.warning("kickstart not found: %s" % meta["kickstart"])
            return "# kickstart not found: %s" % meta["kickstart"]
开发者ID:colloquium,项目名称:cobbler,代码行数:30,代码来源:kickgen.py

示例4: generate_autoyast

    def generate_autoyast(self, profile=None, system=None, raw_data=None):
        self.api.logger.info("autoyast XML file found. Checkpoint: profile=%s system=%s" % (profile, system))
        nopxe = '\nwget "http://%s/cblr/svc/op/nopxe/system/%s" -O /dev/null'
        runpost = '\ncurl "http://%s/cblr/svc/op/trig/mode/post/%s/%s" > /dev/null'
        runpre = '\nwget "http://%s/cblr/svc/op/trig/mode/pre/%s/%s" -O /dev/null'

        what = "profile"
        blend_this = profile
        if system:
            what = "system"
            blend_this = system
        blended = utils.blender(self.api, False, blend_this)
        srv = blended["http_server"]

        document = xml.dom.minidom.parseString(raw_data)

        # do we already have the #raw comment in the XML? (addComment = 0 means, don't add #raw comment)
        addComment = 1
        for node in document.childNodes[1].childNodes:
            if node.nodeType == node.ELEMENT_NODE and node.tagName == "cobbler":
                addComment = 0
                break

        # add some cobbler information to the XML file
        # maybe that should be configureable
        if addComment == 1:
            # startComment = document.createComment("\ncobbler_system_name=$system_name\ncobbler_server=$server\n#raw\n")
            # endComment = document.createComment("\n#end raw\n")
            cobblerElement = document.createElement("cobbler")
            cobblerElementSystem = xml.dom.minidom.Element("system_name")
            cobblerElementProfile = xml.dom.minidom.Element("profile_name")
            if system is not None:
                cobblerTextSystem = document.createTextNode(system.name)
                cobblerElementSystem.appendChild(cobblerTextSystem)
            if profile is not None:
                cobblerTextProfile = document.createTextNode(profile.name)
                cobblerElementProfile.appendChild(cobblerTextProfile)

            cobblerElementServer = document.createElement("server")
            cobblerTextServer = document.createTextNode(blended["http_server"])
            cobblerElementServer.appendChild(cobblerTextServer)

            cobblerElement.appendChild(cobblerElementServer)
            cobblerElement.appendChild(cobblerElementSystem)
            cobblerElement.appendChild(cobblerElementProfile)

            document.childNodes[1].insertBefore(cobblerElement, document.childNodes[1].childNodes[1])

        name = profile.name
        if system is not None:
            name = system.name

        if str(self.settings.pxe_just_once).upper() in ["1", "Y", "YES", "TRUE"]:
            self.addAutoYaSTScript(document, "chroot-scripts", nopxe % (srv, name))
        if self.settings.run_install_triggers:
            # notify cobblerd when we start/finished the installation
            self.addAutoYaSTScript(document, "pre-scripts", runpre % (srv, what, name))
            self.addAutoYaSTScript(document, "init-scripts", runpost % (srv, what, name))

        return document.toxml()
开发者ID:pandasasa,项目名称:cobbler,代码行数:60,代码来源:kickgen.py

示例5: checkfile

    def checkfile(self,obj,is_profile):
        blended = utils.blender(self.config.api, False, obj)

        os_version = blended["os_version"]

        ks = blended["kickstart"]
        if ks is None or ks == "":
            print "%s has no kickstart, skipping" % obj.name
            return True

        breed = blended["breed"]
        if breed != "redhat":
            print "%s has a breed of %s, skipping" % (obj.name, breed)
            return True

        server = blended["server"] 
        if not ks.startswith("/"):
            url = self.kickstart
        elif is_profile:
            url = "http://%s/cblr/svc/op/ks/profile/%s" % (server,obj.name)
        else:
            url = "http://%s/cblr/svc/op/ks/system/%s" % (server,obj.name)

        print "----------------------------"
        print "checking url: %s" % url


        rc = os.system("/usr/bin/ksvalidator \"%s\"" % url)
        if rc != 0:
            return False
       
        return True
开发者ID:icontender,项目名称:cobbler,代码行数:32,代码来源:action_validate.py

示例6: write_boot_files_distro

    def write_boot_files_distro(self,distro):
        # collapse the object down to a rendered datastructure
        # the second argument set to false means we don't collapse
        # hashes/arrays into a flat string
        target      = utils.blender(self.config.api, False, distro)

        # Create metadata for the templar function
        # Right now, just using img_path, but adding more
        # cobbler variables here would probably be good
        metadata = {}
        metadata["img_path"] = os.path.join(
                                    utils.tftpboot_location(),
                                    "images",distro.name)
	# Create the templar instance.  Used to template the target directory
	templater = templar.Templar()

        # Loop through the hash of boot files,
        # executing a cp for each one
        for file in target["boot_files"].keys():
            file_dst = templater.render(file,metadata,None)
            try:
                shutil.copyfile(target["boot_files"][file], file_dst)
                self.config.api.log("copied file %s to %s for %s" % (
                        target["boot_files"][file],
                        file_dst,
                        distro.name))
            except:
                self.logger.error("failed to copy file %s to %s for %s" % (
                        target["boot_files"][file],
                        file_dst,
                    distro.name))
                # Continue on to sync what you can

        return 0
开发者ID:SEJeff,项目名称:cobbler,代码行数:34,代码来源:manage_in_tftpd.py

示例7: run

def run(api, args, logger):
    objtype = args[0] # "system" or "profile"
    name    = args[1] # name of system or profile
    ip      = args[2] # ip or "?"

    if objtype != "system":
        return 0

    settings = api.settings()

    if not str(settings.puppet_auto_setup).lower() in [ "1", "yes", "y", "true"]:
        return 0

    if not str(settings.sign_puppet_certs_automatically).lower() in [ "1", "yes", "y", "true"]:
        return 0

    system = api.find_system(name)
    system = utils.blender(api, False, system)
    hostname = system[ "hostname" ]
    puppetca_path = settings.puppetca_path
    cmd = [puppetca_path, '--sign', hostname]

    rc = 0

    try:
        rc = utils.subprocess_call(logger, cmd, shell=False)
    except:
        if logger is not None:
            logger.warning("failed to execute %s", puppetca_path)

    if rc != 0:
        if logger is not None:
            logger.warning("signing of puppet cert for %s failed", name)

    return 0
开发者ID:SEJeff,项目名称:cobbler,代码行数:35,代码来源:install_post_puppet.py

示例8: power

    def power(self, desired_state):
        """
        state is either "on" or "off".  Rebooting is implemented at the api.py
        level.

        The user and password need not be supplied.  If not supplied they
        will be taken from the environment, COBBLER_POWER_USER and COBBLER_POWER_PASS.
        If provided, these will override any other data and be used instead.  Users
        interested in maximum security should take that route.
        """

        template = self.get_command_template()
        template_file = open(template, "r")

        meta = utils.blender(self.api, False, self.system)
        meta["power_mode"] = desired_state

        # allow command line overrides of the username/password 
        if self.force_user is not None:
           meta["power_user"] = self.force_user
        if self.force_pass is not None:
           meta["power_pass"] = self.force_pass

        tmp = templar.Templar(self.api._config)
        cmd = tmp.render(template_file, meta, None, self.system)
        template_file.close()

        cmd = cmd.strip()

        self.logger.info("cobbler power configuration is:")

        self.logger.info("      type   : %s" % self.system.power_type)
        self.logger.info("      address: %s" % self.system.power_address)
        self.logger.info("      user   : %s" % self.system.power_user)
        self.logger.info("      id     : %s" % self.system.power_id)

        # if no username/password data, check the environment

        if meta.get("power_user","") == "":
            meta["power_user"] = os.environ.get("COBBLER_POWER_USER","")
        if meta.get("power_pass","") == "":
            meta["power_pass"] = os.environ.get("COBBLER_POWER_PASS","")

        # now reprocess the command so we don't feed it through the shell
        cmd = cmd.split(" ")

        # Try the power command 5 times before giving up.
        # Some power switches are flakey
        for x in range(0,5):
            rc = utils.subprocess_call(self.logger, cmd, shell=False)
            if rc == 0:
                break
            else:
                time.sleep(2)

        if not rc == 0:
           utils.die(self.logger,"command failed (rc=%s), please validate the physical setup and cobbler config" % rc)

        return rc
开发者ID:imeyer,项目名称:cobbler,代码行数:59,代码来源:action_power.py

示例9: generate_repo_stanza

    def generate_repo_stanza(self, obj, is_profile=True):

        """
        Automatically attaches yum repos to profiles/systems in kickstart files
        that contain the magic $yum_repo_stanza variable.  This includes repo
        objects as well as the yum repos that are part of split tree installs,
        whose data is stored with the distro (example: RHEL5 imports)
        """

        buf = ""
        blended = utils.blender(self.api, False, obj)
        repos = blended["repos"]

        # keep track of URLs and be sure to not include any duplicates
        included = {}

        for repo in repos:
            # see if this is a source_repo or not
            repo_obj = self.api.find_repo(repo)
            if repo_obj is not None:
                yumopts = ""
                for opt in repo_obj.yumopts:
                    yumopts = yumopts + " %s=%s" % (opt, repo_obj.yumopts[opt])
                if not repo_obj.yumopts.has_key("enabled") or repo_obj.yumopts["enabled"] == "1":
                    if repo_obj.mirror_locally:
                        baseurl = "http://%s/cobbler/repo_mirror/%s" % (blended["http_server"], repo_obj.name)
                        if not included.has_key(baseurl):
                            buf = buf + "repo --name=%s --baseurl=%s\n" % (repo_obj.name, baseurl)
                        included[baseurl] = 1
                    else:
                        if not included.has_key(repo_obj.mirror):
                            buf = buf + "repo --name=%s --baseurl=%s %s\n" % (repo_obj.name, repo_obj.mirror, yumopts)
                        included[repo_obj.mirror] = 1
            else:
                # FIXME: what to do if we can't find the repo object that is listed?
                # this should be a warning at another point, probably not here
                # so we'll just not list it so the kickstart will still work
                # as nothing will be here to read the output noise.  Logging might
                # be useful.
                pass

        if is_profile:
            distro = obj.get_conceptual_parent()
        else:
            distro = obj.get_conceptual_parent().get_conceptual_parent()

        source_repos = distro.source_repos
        count = 0
        for x in source_repos:
            count = count + 1
            if not included.has_key(x[1]):
                buf = buf + "repo --name=source-%s --baseurl=%s\n" % (count, x[1])
                included[x[1]] = 1

        return buf
开发者ID:pandasasa,项目名称:cobbler,代码行数:55,代码来源:kickgen.py

示例10: generate_bootcfg

    def generate_bootcfg(self, what, name):
        if what.lower() not in ("profile", "system"):
            return "# bootcfg is only valid for profiles and systems"

        distro = None
        if what == "profile":
            obj = self.api.find_profile(name=name)
            distro = obj.get_conceptual_parent()
        else:
            obj = self.api.find_system(name=name)
            distro = obj.get_conceptual_parent().get_conceptual_parent()

        # For multi-arch distros, the distro name in ks_mirror
        # may not contain the arch string, so we need to figure out
        # the path based on where the kernel is stored. We do this
        # because some distros base future downloads on the initial
        # URL passed in, so all of the files need to be at this location
        # (which is why we can't use the images link, which just contains
        # the kernel and initrd).
        ks_mirror_name = string.join(distro.kernel.split("/")[-2:-1], "")

        blended = utils.blender(self.api, False, obj)

        ksmeta = blended.get("ks_meta", {})
        try:
            del blended["ks_meta"]
        except:
            pass
        blended.update(ksmeta)  # make available at top level

        blended["distro"] = ks_mirror_name

        # FIXME: img_path should probably be moved up into the
        #        blender function to ensure they're consistently
        #        available to templates across the board
        if obj.enable_gpxe:
            blended["img_path"] = "http://%s:%s/cobbler/links/%s" % (
                self.settings.server,
                self.settings.http_port,
                distro.name,
            )
        else:
            blended["img_path"] = os.path.join("/images", distro.name)

        template = os.path.join(
            self.settings.pxe_template_dir, "bootcfg_%s_%s.template" % (what.lower(), distro.os_version)
        )
        if not os.path.exists(template):
            return "# boot.cfg template not found for the %s named %s (filename=%s)" % (what, name, template)

        template_fh = open(template)
        template_data = template_fh.read()
        template_fh.close()

        return self.templar.render(template_data, blended, None)
开发者ID:TechForks,项目名称:cobbler,代码行数:55,代码来源:pxegen.py

示例11: get_yum_config

    def get_yum_config(self,obj,is_profile):
        """
        Return one large yum repo config blob suitable for use by any target system that requests it.
        """

        totalbuf = ""

        blended  = utils.blender(self.api, False, obj)

        input_files = []

        # chance old versions from upgrade do not have a source_repos
        # workaround for user bug
        if not blended.has_key("source_repos"):
            blended["source_repos"] = []

        # tack on all the install source repos IF there is more than one.
        # this is basically to support things like RHEL5 split trees
        # if there is only one, then there is no need to do this.

        included = {}
        for r in blended["source_repos"]:
            filename = self.settings.webdir + "/" + "/".join(r[0].split("/")[4:])
            if not included.has_key(filename):
                input_files.append(filename)
            included[filename] = 1

        for repo in blended["repos"]:
            path = os.path.join(self.settings.webdir, "repo_mirror", repo, "config.repo")
            if not included.has_key(path):
                input_files.append(path)
            included[path] = 1

        for infile in input_files:
            if infile.find("ks_mirror") == -1:
                dispname = infile.split("/")[-2]
            else:
                dispname = infile.split("/")[-1].replace(".repo","")
            try:
                infile_h = open(infile)
            except:
                # file does not exist and the user needs to run reposync
                # before we will use this, cobbler check will mention
                # this problem
                totalbuf = totalbuf +  "\n# error: could not read repo source: %s\n\n" % infile
                continue

            infile_data = infile_h.read()
            infile_h.close()
            outfile = None # disk output only
            totalbuf = totalbuf + self.templar.render(infile_data, blended, outfile, None)
            totalbuf = totalbuf + "\n\n"

        return totalbuf
开发者ID:akesling,项目名称:cobbler,代码行数:54,代码来源:yumgen.py

示例12: generate_kickstart_signal

    def generate_kickstart_signal(self, is_pre=0, profile=None, system=None):
        """
        Do things that we do at the start/end of kickstarts...
        * start: signal the status watcher we're starting
        * end:   signal the status watcher we're done
        * end:   disable PXE if needed
        * end:   save the original kickstart file for debug
        """

        nopxe = "\nwget \"http://%s/cblr/svc/op/nopxe/system/%s\" -O /dev/null"
        saveks = "\nwget \"http://%s/cblr/svc/op/ks/%s/%s\" -O /root/cobbler.ks"
        runpost = "\nwget \"http://%s/cblr/svc/op/trig/mode/post/%s/%s\" -O /dev/null"
        runpre  = "\nwget \"http://%s/cblr/svc/op/trig/mode/pre/%s/%s\" -O /dev/null"

        what = "profile"
        blend_this = profile
        if system:
            what = "system"
            blend_this = system

        blended = utils.blender(self.api, False, blend_this)
        kickstart = blended.get("kickstart",None)

        buf = ""
        srv = blended["http_server"]
        if system is not None:
            if not is_pre:
                if str(self.settings.pxe_just_once).upper() in [ "1", "Y", "YES", "TRUE" ]:
                    buf = buf + nopxe % (srv, system.name)
                if kickstart and os.path.exists(kickstart):
                    buf = buf + saveks % (srv, "system", system.name)
                if self.settings.run_install_triggers:
                    buf = buf + runpost % (srv, what, system.name)
            else:
                if self.settings.run_install_triggers:
                    buf = buf + runpre % (srv, what, system.name)

        else:
            if not is_pre:
                if kickstart and os.path.exists(kickstart):
                    buf = buf + saveks % (srv, "profile", profile.name)
                if self.settings.run_install_triggers:
                    buf = buf + runpost % (srv, what, profile.name) 
            else:
                if self.settings.run_install_triggers:
                    buf = buf + runpre % (srv, what, profile.name) 

        return buf
开发者ID:icontender,项目名称:cobbler,代码行数:48,代码来源:kickgen.py

示例13: generate_config_stanza

    def generate_config_stanza(self, obj, is_profile=True):

        """
        Add in automatic to configure /etc/yum.repos.d on the remote system
        if the kickstart file contains the magic $yum_config_stanza.
        """

        if not self.settings.yum_post_install_mirror:
            return ""

        blended = utils.blender(self.api, False, obj)
        if is_profile:
            url = "http://%s/cblr/svc/op/yum/profile/%s" % (blended["http_server"], obj.name)
        else:
            url = "http://%s/cblr/svc/op/yum/system/%s" % (blended["http_server"], obj.name)

        return 'wget "%s" --output-document=/etc/yum.repos.d/cobbler-config.repo\n' % (url)
开发者ID:pandasasa,项目名称:cobbler,代码行数:17,代码来源:kickgen.py

示例14: generate_kickstart

    def generate_kickstart(self, profile=None, system=None):

        obj = system
        if system is None:
            obj = profile

        meta = utils.blender(self.api, False, obj)
        kickstart_path = utils.find_kickstart(meta["kickstart"])

        if not kickstart_path:
            return "# kickstart is missing or invalid: %s" % meta["kickstart"]

        ksmeta = meta["ks_meta"]
        del meta["ks_meta"]
        meta.update(ksmeta)     # make available at top level
        meta["yum_repo_stanza"] = self.generate_repo_stanza(obj, (system is None))
        meta["yum_config_stanza"] = self.generate_config_stanza(obj, (system is None))
        meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])

        # add extra variables for other distro types
        if "tree" in meta:
            urlparts = urlparse.urlsplit(meta["tree"])
            meta["install_source_directory"] = urlparts[2]

        try:
            raw_data = utils.read_file_contents(
                kickstart_path, self.api.logger,
                self.settings.template_remote_kickstarts)
            if raw_data is None:
                return "# kickstart is sourced externally: %s" % meta["kickstart"]
            distro = profile.get_conceptual_parent()
            if system is not None:
                distro = system.get_conceptual_parent().get_conceptual_parent()

            data = self.templar.render(raw_data, meta, None, obj)

            if distro.breed == "suse":
                # AutoYaST profile
                data = self.generate_autoyast(profile, system, data)

            return data
        except FileNotFoundException:
            self.api.logger.warning("kickstart not found: %s" % meta["kickstart"])
            return "# kickstart not found: %s" % meta["kickstart"]
开发者ID:adelekks,项目名称:cobbler,代码行数:44,代码来源:kickgen.py

示例15: generate_script

    def generate_script(self, what, objname, script_name):
        if what == "profile":
            obj = self.api.find_profile(name=objname)
        else:
            obj = self.api.find_system(name=objname)

        if not obj:
            return "# %s named %s not found" % (what, objname)

        distro = obj.get_conceptual_parent()
        while distro.get_conceptual_parent():
            distro = distro.get_conceptual_parent()

        blended = utils.blender(self.api, False, obj)

        ksmeta = blended.get("ks_meta", {})
        try:
            del blended["ks_meta"]
        except:
            pass
        blended.update(ksmeta)  # make available at top level

        # FIXME: img_path should probably be moved up into the
        #        blender function to ensure they're consistently
        #        available to templates across the board
        if obj.enable_gpxe:
            blended["img_path"] = "http://%s:%s/cobbler/links/%s" % (
                self.settings.server,
                self.settings.http_port,
                distro.name,
            )
        else:
            blended["img_path"] = os.path.join("/images", distro.name)

        template = os.path.normpath(os.path.join("/var/lib/cobbler/scripts", script_name))
        if not os.path.exists(template):
            return "# script template %s not found" % script_name

        template_fh = open(template)
        template_data = template_fh.read()
        template_fh.close()

        return self.templar.render(template_data, blended, None, obj)
开发者ID:TechForks,项目名称:cobbler,代码行数:43,代码来源:pxegen.py


注:本文中的utils.blender函数示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。