def test_default_set_get(self):
        '''Set up service rudiments so default handling can be tested'''

        try:
            self.smf_instance = smf.AISCF(FMRI="system/install/server")
        except KeyError:
            raise SystemExit(
                _("Error:\tThe system/install/server SMF "
                  "service is not running."))

        # If the service exists, exit.  We don't want to romp on it.
        if self.service_name in self.smf_instance.services.keys():
            raise SystemExit(
                _("Error: The service %s already exists!!!") %
                self.service_name)

        service_data = {
            aismf.PROP_SERVICE_NAME: self.service_name,
            aismf.PROP_IMAGE_PATH: self.image_path,
            aismf.PROP_BOOT_FILE: "dummy_boot",
            aismf.PROP_TXT_RECORD:
            com.AIWEBSERVER + "=hostname:" + self.dummy_service_dir,
            aismf.PROP_STATUS: aismf.STATUS_OFF
        }

        aismf.create_pg(self.service_name, service_data)

        manifest_name = "temp_mfest_name_%d" % os.getpid()

        properties.set_default(self.service_name, manifest_name,
                               properties.SKIP_MANIFEST_CHECK)
        self.assertEqual(manifest_name,
                         properties.get_default(self.service_name))
Example #2
0
def verifyDTDManifest(xml_dtd, data):
    """
    Use this for verifying a generic DTD based XML whose DOCTYPE points to its
    available DTD (absolute path needed). Will return the etree to walk the
    XML tree or the validation error
    """
    result = list()
    # Explanation of options: Here we don't want to load the DTD since it is
    # passed in; don't use the network in case someone passes in an HTTP
    # reference in the XML as that could be unexpected; we do DTD validation
    # separate from the XML file's validation; we want to leave comments
    # for now, since the embedded SC manifest can be stored as a comment
    # in some places
    parser = lxml.etree.XMLParser(load_dtd=False,
                                  no_network=True,
                                  dtd_validation=False,
                                  remove_comments=False)
    dtd = lxml.etree.DTD(os.path.abspath(xml_dtd))
    try:
        root = lxml.etree.parse(data, parser)
    except IOError:
        raise SystemExit(_("Error:\tCan not open: %s" % data))
    except lxml.etree.XMLSyntaxError, err:
        for error in err.error_log:
            result.append(error.message)
        return None, result
Example #3
0
def usage():
    """ Print usage message and exit
    """
    sys.stderr.write(_("Usage:\n"
                       "    %s -s service_list -o destination"
                       " -p profile_destination_dir"
                       " [-c criteria=value ... ]"
                       " [-d debug_level] [-l] [-h] [-e]\n") %
                       os.path.basename(sys.argv[0]))
    sys.exit(1)
def verifyRelaxNGManifest(schema_f, data):
    """
    Use this to verify a RelaxNG based document using the pointed to RelaxNG
    schema and receive the validation error or the etree to walk the XML tree
    """
    import logging
    logging.debug('schema')
    try:
        relaxng_schema_doc = lxml.etree.parse(schema_f)
    except IOError:
        raise SystemExit(_("Error:\tCan not open: %s" % schema_f))
    logging.debug('RelaxNG doc=%s' % relaxng_schema_doc)
    relaxng = lxml.etree.RelaxNG(relaxng_schema_doc)
    logging.debug('RelaxNG parse data=%s' % data)
    try:
        root = lxml.etree.parse(data)
    except IOError:
        raise SystemExit(_("Error:\tCan not open: %s" % data))
    except lxml.etree.XMLSyntaxError, err:
        return None, err.error_log.last_error
Example #5
0
def verifyRelaxNGManifest(schema_f, data):
    """
    Use this to verify a RelaxNG based document using the pointed to RelaxNG
    schema and receive the validation error or the etree to walk the XML tree
    """
    import logging
    logging.debug('schema')
    try:
        relaxng_schema_doc = lxml.etree.parse(schema_f)
    except IOError:
        raise SystemExit(_("Error:\tCan not open: %s" % schema_f))
    logging.debug('RelaxNG doc=%s' % relaxng_schema_doc)
    relaxng = lxml.etree.RelaxNG(relaxng_schema_doc)
    logging.debug('RelaxNG parse data=%s' % data)
    try:
        root = lxml.etree.parse(data)
    except IOError:
        raise SystemExit(_("Error:\tCan not open: %s" % data))
    except lxml.etree.XMLSyntaxError, err:
        return None, err.error_log.last_error
def checkCPU(value):
# =============================================================================
    """
    Private function that checks whether cpu value is one of the known values

    Args:
      value: the string being checked

    Returns:
      None

    Raises:
      ValueError: Warning: CPU class is not listed in list of know CPU classes
    """

    if value not in com.KNOWN_CPUS:
        cpu_err_msg = _("Warning: CPU class '%s' is not listed in list of " \
            "known CPU classes: %s") % (value, com.KNOWN_CPUS)
        raise ValueError(cpu_err_msg)
Example #7
0
def checkCPU(value):
    # =============================================================================
    """
    Private function that checks whether cpu value is one of the known values

    Args:
      value: the string being checked

    Returns:
      None

    Raises:
      ValueError: Warning: CPU class is not listed in list of know CPU classes
    """

    if value not in com.KNOWN_CPUS:
        cpu_err_msg = _("Warning: CPU class '%s' is not listed in list of " \
            "known CPU classes: %s") % (value, com.KNOWN_CPUS)
        raise ValueError(cpu_err_msg)
def checkArch(value):
# =============================================================================
    """
    Private function that checks whether arch value is one of the known values

    Args:
      value: the string being checked

    Returns:
      None

    Raises:
      ValueError: Warning: Architecture is not listed in list of known
                  architectures
    """

    if value not in com.KNOWN_ARCHS:
        arch_err_msg = _("Warning: Architecture '%s' is not listed in list " \
            "of known architectures: %s") % (value, com.KNOWN_ARCHS)
        raise ValueError(arch_err_msg)
Example #9
0
def checkArch(value):
    # =============================================================================
    """
    Private function that checks whether arch value is one of the known values

    Args:
      value: the string being checked

    Returns:
      None

    Raises:
      ValueError: Warning: Architecture is not listed in list of known
                  architectures
    """

    if value not in com.KNOWN_ARCHS:
        arch_err_msg = _("Warning: Architecture '%s' is not listed in list " \
            "of known architectures: %s") % (value, com.KNOWN_ARCHS)
        raise ValueError(arch_err_msg)
def verifyDTDManifest(xml_dtd, data):
    """
    Use this for verifying a generic DTD based XML whose DOCTYPE points to its
    available DTD (absolute path needed). Will return the etree to walk the
    XML tree or the validation error
    """
    result = list()
    # Explanation of options: Here we don't want to load the DTD since it is
    # passed in; don't use the network in case someone passes in an HTTP
    # reference in the XML as that could be unexpected; we do DTD validation
    # separate from the XML file's validation; we want to leave comments
    # for now, since the embedded SC manifest can be stored as a comment
    # in some places
    parser = lxml.etree.XMLParser(load_dtd=False, no_network=True,
                                  dtd_validation=False, remove_comments=False)
    dtd = lxml.etree.DTD(os.path.abspath(xml_dtd))
    try:
        root = lxml.etree.parse(data, parser)
    except IOError:
        raise SystemExit(_("Error:\tCan not open: %s" % data))
    except lxml.etree.XMLSyntaxError, err:
        for error in err.error_log:
            result.append(error.message)
        return None, result
Example #11
0
def parse_cli(cli_opts_args):
    """ main application
    """

    if len(cli_opts_args) == 0:
        usage()

    opts_args = cli_opts_args[1:]

    try:
        opts = getopt.getopt(opts_args, "c:d:ehlo:p:s:")[0]
    except getopt.GetoptError:
        AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
                      "Invalid options or arguments provided")
        usage()

    criteria_list = list()
    service_list = None
    manifest_file = None
    profile_dir = None
    list_criteria_only = False
    no_default = False

    for option, argument in opts:
        if option == "-c":
            criteria_list.append(argument)
        elif option == "-s":
            service_list = argument
        elif option == "-o":
            manifest_file = argument
        elif option == "-d":
            AIGM_LOG.set_debug_level(int(argument))
        elif option == "-l":
            list_criteria_only = True
        elif option == "-p":
            profile_dir = argument
        elif option == "-e":
            no_default = True
        elif option == "-h":
            usage()

    if service_list is None or manifest_file is None or profile_dir is None:
        AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
                      "Invalid options or arguments provided")
        usage()

    AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "Service list: %s", service_list)

    AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "Manifest file: " + manifest_file)

    AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "Profile directory: " + profile_dir)

    if len(criteria_list) > 0:
        AIGM_LOG.post(AILog.AI_DBGLVL_INFO,
                      "Criteria list: " + str(criteria_list))

    ai_criteria_known = {}

    # If criteria specified on the command line, use that as
    # our known criteria, otherwise get criteria from system.
    if len(criteria_list) > 0:
        for entry in criteria_list:
            entries = entry.partition("=")

            if entries[1]:
                if not entries[0]:
                    raise ValueError(
                        _("Missing criteria name in '%s'\n") % entry)
                elif entries[0].lower() in ai_criteria_known:
                    raise ValueError(
                        _("Duplicate criteria: '%s'\n") % entries[0])
                elif not entries[2]:
                    raise ValueError(
                        _("Missing value for criteria '%s'\n") % entries[0])

                if entries[0] not in AI_CRITERIA_SUPPORTED:
                    raise ValueError(
                        _("Unsupported criteria: '%s'\n") % entries[0])

                ai_criteria_known[entries[0].lower()] = entries[2]
            else:
                raise ValueError(
                    _("Criteria must be of the form "
                      "<criteria>=<value>\n"))
    else:
        # Obtain all available information about client
        for key in AI_CRITERIA_SUPPORTED.keys():
            if AI_CRITERIA_SUPPORTED[key][0] is not None:
                ai_crit = AI_CRITERIA_SUPPORTED[key][0]()
                if ai_crit.is_known():
                    ai_criteria_known[key] = ai_crit.get()

    # List all criteria which client can understand and provide
    AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "Client can supply following criteria")
    for key in ai_criteria_known.keys():
        AIGM_LOG.post(AILog.AI_DBGLVL_INFO, " %s=%s, '%s'", key,
                      ai_criteria_known[key], AI_CRITERIA_SUPPORTED[key][1])

    # if "-l" option was provided, list known criteria and exit
    if list_criteria_only:
        print "Client can supply the following criteria"
        print "----------------------------------------"
        index = 0
        for key in ai_criteria_known.keys():
            index += 1
            print " [%d] %s=%s (%s)" % (index, key, ai_criteria_known[key],
                                        AI_CRITERIA_SUPPORTED[key][1])
        return 0

    #
    # Go through the list of services.
    # Contact each of them and try to obtain valid manifest.
    #

    AIGM_LOG.post(AILog.AI_DBGLVL_INFO,
                  "Starting to contact AI services provided by %s",
                  service_list)

    ai_manifest_obtained = False
    try:
        service_list_fh = open(service_list, 'r')
    except IOError:
        AIGM_LOG.post(AILog.AI_DBGLVL_ERR, "Could not open %s file",
                      service_list)
        return 2

    for ai_service in service_list_fh.readlines():
        service = ai_service.strip()
        (ai_service, ai_port, ai_name) = service.split(':')
        ai_service += ':' + str(ai_port)
        AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "AI service: %s", ai_service)
        AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "AI service name: %s", ai_name)

        AIGM_LOG.post(AILog.AI_DBGLVL_INFO,
                      " HTTP POST cgi-bin/cgi_get_manifest.py?service=%s",
                      ai_service)

        # invoke CGI script to get manifest, profiles
        http_resp, ret, content_type = \
                ai_get_http_file(ai_service, ai_name,
                                 "/cgi-bin/cgi_get_manifest.py",
                                 'POST', ai_criteria_known,
                                 no_default=no_default)
        #
        # If valid manifest was provided, it is not necessary
        # to connect next AI service,
        #
        if ret == httplib.OK:
            if content_type == 'text/xml':  # old format
                ai_manifest = http_resp
                ai_manifest_obtained = True
                AIGM_LOG.post(
                    AILog.AI_DBGLVL_INFO,
                    "%s AI service provided single XML file - "
                    "assumed to be AI manifest." % ai_service)
                break
            AIGM_LOG.post(AILog.AI_DBGLVL_INFO,
                          "%s AI service provided valid manifest", ai_service)
            # prepend content type header for MIME boundary
            #   Content-Type: multipart/mixed; boundary= ...
            mime_response = "Content-Type: %s\n%s" % (content_type, http_resp)
            # by design, response is MIME-encoded, multipart
            if mime_response is not None:
                # delete any profiles from previous runs
                cleanup_earlier_run(profile_dir)
                # parse the MIME response
                parse = Parser()
                msg = parse.parsestr(mime_response)
                # handle each self-identifying part
                for imsg in msg.walk():
                    # write out manifest, any profiles, console messages
                    if handle_mime_payload(imsg, manifest_file, profile_dir):
                        ai_manifest_obtained = True
            if ai_manifest_obtained:  # manifest written by MIME handler
                service_list_fh.close()
                return 0
        else:
            AIGM_LOG.post(AILog.AI_DBGLVL_WARN,
                          "%s AI service did not provide a valid manifest, " \
                          "ret=%d", ai_service, ret)
            AIGM_LOG.post(AILog.AI_DBGLVL_WARN,
                          "Checking compatibility mechanism.")
            ai_manifest, ret = ai_do_compatibility(ai_service,
                                                   ai_criteria_known)

            if ret == httplib.OK:
                AIGM_LOG.post(AILog.AI_DBGLVL_WARN,
                              "Compatibility mechanism provided a valid " \
                              "manifest.")
                ai_manifest_obtained = True
                break
            else:
                AIGM_LOG.post(AILog.AI_DBGLVL_WARN,
                              "Compatibility mechanism did not provide valid" \
                              " manifest, ret=%d", ret)

    service_list_fh.close()

    if not ai_manifest_obtained:
        AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
                      "None of contacted AI services provided valid manifest")
        if no_default:
            # If a default manifest is not requested, its OK if we didn't
            # obtain a manifest, return 0.
            return 0
        else:
            return 2

    # Save the manifest
    AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "Saving manifest to %s", manifest_file)

    try:
        with open(manifest_file, 'w') as fh_manifest:
            fh_manifest.write(ai_manifest)
    except IOError:
        AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
                      "Could not open %s for saving obtained manifest",
                      manifest_file)
        return 2

    return 0
Example #12
0
                AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
                              'failure writing manifest: ' + str(err))
            return wrote_manifest

        # not manifest, assume the attachment is a profile, and output it
        pname = write_profile_file(msg.get_filename(), payload, profile_dir,
                                   SC_EXTENSION, SC_PREFIX)
        if pname:
            AIGM_LOG.post(AILog.AI_DBGLVL_INFO, 'Wrote profile %s.' % pname)

    elif not msg.is_multipart():
        # log and display text messages from the locator CGI
        # assuming any text not within an attachment goes to the console
        AIGM_LOG.post(
            AILog.AI_DBGLVL_WARN,
            _("Messages from AI server while locating manifest and profiles:")
            + "\n" + payload)
    return wrote_manifest


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def cleanup_earlier_run(profile_dir):
    """
    From the designated profile output directory,
    purge any profiles left over from a previous run.
    """
    try:
        cleanlist = os.listdir(profile_dir)
    except OSError, err:
        if err.errno == ENOENT:  # exists
            return