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))
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
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
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)
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
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