def __init__(self, aiqueue, name, default=False): ''' Reads manifest from database Args: aiqueue = database request queue name = name of the manifest default = boolean whether this manifest is default or not ''' # Save manifest name self.name = name # Manifest itself don't know whether it is default for its service so # this information should be passed in constructor self.default = default # Each manifest can have several sets of criteria - put them into list self.criteria = list() # Length of the longest criteria self.max_crit_len = 0 # One manifest can have associated more sets of criteria instances = AIdb.numInstances(name, aiqueue) for instance in range(0, instances): self.criteria.append( CriteriaPrintObject(aiqueue, name, instance, AIdb.MANIFESTS_TABLE)) # Check whether this manifest has at least one active criteria # and find the longest one self.has_crit = False for crit in self.criteria: self.has_crit = crit.get_has_crit() if crit.get_max_crit_len() > self.max_crit_len: self.max_crit_len = crit.get_max_crit_len() # Set status if self.default: self.status = DEFAULT else: if not self.has_crit: # It is not default and doesn't have criteria - it is Inactive self.status = INACTIVE else: self.status = ''
def delete_manifest_from_db(db, manifest_instance, service_name, data_loc): """ Remove manifest from DB """ instance = manifest_instance[1] # check to see that the manifest is found in the database (as entered) if manifest_instance[0] not in AIdb.getManNames(db.getQueue()): # since all manifest names have to have .xml appended try adding that if manifest_instance[0] + '.xml' in AIdb.getManNames(db.getQueue()): man_name = manifest_instance[0] + '.xml' else: raise SystemExit(_("Error:\tManifest %s not found in database!" % manifest_instance[0])) else: man_name = manifest_instance[0] service = AIService(service_name) # Do not delete if this manifest is set up as the default. if man_name == service.get_default_manifest(): raise ValueError(_("Error:\tCannot delete default manifest %s.") % man_name) # if we do not have an instance remove the entire manifest if instance is None: # remove manifest from database query = AIdb.DBrequest("DELETE FROM manifests WHERE name = '%s'" % AIdb.sanitizeSQL(man_name), commit=True) db.getQueue().put(query) query.waitAns() # run getResponse to handle and errors query.getResponse() # clean up file on file system try: os.remove(os.path.join(service.manifest_dir, man_name)) except OSError: print >> sys.stderr, _("Warning:\tUnable to find file %s for " + "removal!") % man_name # we are removing a specific instance else: # check that the instance number is within bounds for that manifest # (0..numInstances) if instance > AIdb.numInstances(man_name, db.getQueue()) or \ instance < 0: raise SystemExit(_("Error:\tManifest %(name)s has %(num)i " "instances" % {'name': man_name, 'num': AIdb.numInstances(man_name, db.getQueue())})) # remove instance from database query = ("DELETE FROM manifests WHERE name = '%s' AND " "instance = '%i'") % (AIdb.sanitizeSQL(man_name), instance) query = AIdb.DBrequest(query, commit=True) db.getQueue().put(query) query.waitAns() # run getResponse to handle and errors query.getResponse() # We may need to reshuffle manifests to prevent gaps in instance # numbering as the DB routines expect instances to be contiguous and # increasing. We may have removed an instance with instances numbered # above thus leaving a gap. # get the number of instances with a larger instance for num in range(instance, AIdb.numInstances(man_name, db.getQueue()) + 1): # now decrement the instance number query = ("UPDATE manifests SET instance = '%i' WHERE " "name = '%s' ") % (num - 1, AIdb.sanitizeSQL(man_name)) query += "AND instance = '%i'" % num query = AIdb.DBrequest(query, commit=True) db.getQueue().put(query) query.waitAns() # run getResponse to handle and errors query.getResponse() # remove file if manifest is no longer in database if man_name not in AIdb.getManNames(db.getQueue()): try: os.remove(os.path.join(service.manifest_dir, man_name)) except OSError: print >> sys.stderr, _("Warning: Unable to find file %s for " + "removal!") % man_name
def list_manifests(service): '''Replies to the client with criteria list for a service. The output should be similar to installadm list. Args service - the name of the service being listed Returns None Raises None ''' print 'Content-Type: text/html' # HTML is following print # blank line, end of headers print '<html>' print '<head>' sys.stdout.write('<title>%s %s</title>' % (_('Manifest list for'), service)) print '</head><body>' port = 0 try: smf.AISCF(FMRI="system/install/server") except KeyError: # report the internal error to error_log and requesting client sys.stderr.write( _("error:The system does not have the " "system/install/server SMF service.")) sys.stdout.write( _("error:The system does not have the " "system/install/server SMF service.")) return services = config.get_all_service_names() if not services: # report the error to the requesting client only sys.stdout.write(_('error:no services on this server.\n')) return found = False if config.is_service(service): service_ctrl = AIService(service) found = True # assume new service setup path = service_ctrl.database_path if os.path.exists(path): try: aisql = AIdb.DB(path) aisql.verifyDBStructure() except StandardError as err: # report the internal error to error_log and # requesting client sys.stderr.write( _('error:AI database access ' 'error\n%s\n') % err) sys.stdout.write( _('error:AI database access ' 'error\n%s\n') % err) return # generate the list of criteria for the criteria table header criteria_header = E.TR() for crit in AIdb.getCriteria(aisql.getQueue(), strip=False): criteria_header.append(E.TH(crit)) # generate the manifest rows for the criteria table body names = AIdb.getManNames(aisql.getQueue()) table_body = E.TR() allcrit = AIdb.getCriteria(aisql.getQueue(), strip=False) colspan = str(max(len(list(allcrit)), 1)) for manifest in names: # iterate through each manifest (and instance) for instance in range( 0, AIdb.numInstances(manifest, aisql.getQueue())): table_body.append(E.TR()) # print the manifest name only once (from instance 0) if instance == 0: href = '../' + service + '/' + manifest row = str(AIdb.numInstances(manifest, aisql.getQueue())) table_body.append( E.TD(E.A(manifest, href=href, rowspan=row))) else: table_body.append(E.TD()) crit_pairs = AIdb.getManifestCriteria(manifest, instance, aisql.getQueue(), onlyUsed=True, humanOutput=True) # crit_pairs is an SQLite3 row object which doesn't # support iteritems(), etc. for crit in crit_pairs.keys(): formatted_val = AIdb.formatValue( crit, crit_pairs[crit]) # if we do not get back a valid value ensure a # hyphen is printed (prevents "" from printing) if formatted_val and crit_pairs[crit]: table_body.append( E.TD(formatted_val, align="center")) else: table_body.append( E.TD(lxml.etree.Entity("nbsp"), align="center")) # print the default manifest at the end of the table, # which has the same colspan as the Criteria List label else: href = '../' + service + '/default.xml' table_body.append( E.TR( E.TD(E.A("Default", href=href)), E.TD(lxml.etree.Entity("nbsp"), colspan=colspan, align="center"))) web_page = E.HTML( E.HEAD(E.TITLE(_("OmniOS Automated " "Installation Webserver"))), E.BODY( E.H1( _("Welcome to the OmniOS " "Automated Installation webserver!")), E.P( _("Service '%s' has the following " "manifests available, served to clients " "matching required criteria.") % service), E.TABLE(E.TR(E.TH(_("Manifest"), rowspan="2"), E.TH(_("Criteria List"), colspan=colspan)), criteria_header, table_body, border="1", align="center"), )) print lxml.etree.tostring(web_page, pretty_print=True) # service is not found, provide available services on host if not found: sys.stdout.write(_('Service <i>%s</i> not found. ') % service) sys.stdout.write(_('Available services are:<p><ol><i>')) host = socket.gethostname() for service_name in config.get_all_service_names(): # assume new service setup port = config.get_service_port(service_name) sys.stdout.write( '<a href="http://%s:%d/cgi-bin/' 'cgi_get_manifest.py?version=%s&service=%s">%s</a><br>\n' % (host, port, VERSION, service_name, service_name)) sys.stdout.write('</i></ol>%s' % _('Please select a service ' 'from the above list.')) print '</body></html>'
def get_service_manifests(sname, linst): """ Iterate through all the manifests for the named service (sname) pointed to by the SCF service. Args sname = service name inst = smf.AISCF() Returns a dictionary of the criteria for the named service within a list: { servicename1:[ { 'arch':arch1, 'mem':memory1, 'ipv4':ipaddress1, 'mac':macaddr1, 'platform':platform1, 'network':network1 'cpu':cpu1 }, ... ] } * Note1: platform, network and cpu are currently not-implemented upstream. * Note2: could simply use a list of dictionaries but implemented as a dictionary of a list of dictionary which will allow for multiple services to be listed at the same time. width of longest manifest name width of longest criteria Raises None """ sdict = {} width = 0 cwidth = 0 # ensure the named service is in our service dictionary. lservices = linst.services.keys() if sname in lservices: serv = smf.AIservice(linst, sname) if not has_key(serv, 'txt_record'): sys.stderr.write(_('%s: error: SMF service key ' 'property does not exist\n') % \ os.path.basename(sys.argv[0])) sys.exit(1) port = serv['txt_record'].split(':')[-1] path = os.path.join('/var/ai', str(port), 'AI.db') if os.path.exists(path): try: maisql = AIdb.DB(path) maisql.verifyDBStructure() aiqueue = maisql.getQueue() for name in AIdb.getManNames(aiqueue): sdict[name] = [] instances = AIdb.numInstances(name, aiqueue) for instance in range(0, instances): criteria = AIdb.getManifestCriteria(name, instance, aiqueue, humanOutput = True, onlyUsed = True) width = max(len(name), width) tdict, twidth = get_criteria_info(criteria) cwidth = max(twidth, cwidth) sdict[name].extend([tdict]) except Exception, err: sys.stderr.write(_('%s: error: AI database access ' 'error\n%s\n') % \ (os.path.basename(sys.argv[0]), err)) sys.exit(1) else: sys.stderr.write(_('%s: error: unable to locate ' 'AI database on server for %s\n') % \ (os.path.basename(sys.argv[0]), sname)) sys.exit(1)
def insert_SQL(files): """ Ensures all data is properly sanitized and formatted, then inserts it into the database Args: None Returns: None """ query = "INSERT INTO manifests VALUES(" # add the manifest name to the query string query += "'" + AIdb.sanitizeSQL(files.manifest_name) + "'," # check to see if manifest name is already in database (affects instance # number) if AIdb.sanitizeSQL(files.manifest_name) in \ AIdb.getManNames(files.database.getQueue()): # database already has this manifest name get the number of # instances instance = AIdb.numInstances(AIdb.sanitizeSQL(files.manifest_name), files.database.getQueue()) # this a new manifest else: instance = 0 # actually add the instance to the query string query += str(instance) + "," # we need to fill in the criteria or NULLs for each criteria the database # supports (so iterate over each criteria) for crit in AIdb.getCriteria(files.database.getQueue(), onlyUsed=False, strip=False): # for range values trigger on the MAX criteria (skip the MIN's # arbitrary as we handle rows in one pass) if crit.startswith('MIN'): continue # get the values from the manifest values = files.criteria[crit.replace('MAX', '', 1)] # If the critera manifest didn't specify this criteria, fill in NULLs if values is None: # use the criteria name to determine if this is a range if crit.startswith('MAX'): query += "NULL,NULL," # this is a single value else: query += "NULL," # Else if this is a value criteria (not a range), insert the value # as a space-separated list of values which will account for the case # where a list of values have been given. elif not crit.startswith('MAX'): # Join the values of the list with a space separator. query += "'" + AIdb.sanitizeSQL(" ".join(values)) + "'," # else values is a range else: for value in values: # translate "unbounded" to a database NULL if value == "unbounded": query += "NULL," # we need to deal with mac addresses specially being # hexadecimal elif crit.endswith("mac"): # need to insert with hex operand x'<val>' # use an upper case string for hex values query += "x'" + AIdb.sanitizeSQL(str(value).upper()) + \ "'," else: query += AIdb.sanitizeSQL(str(value).upper()) + "," # strip trailing comma and close parentheses query = query[:-1] + ")" # update the database query = AIdb.DBrequest(query, commit=True) files.database.getQueue().put(query) query.waitAns() # in case there's an error call the response function (which will print the # error) query.getResponse()
def get_mfest_or_profile_criteria(sname, services, dbtable): """ Iterate through all the manifests or profiles for the named service (sname) pointed to by the SCF service. Args sname = service name services = config.get_all_service_props() dbtable = database table, distinguishing manifests from profiles Assumed to be one of AIdb.MANIFESTS_TABLE or AIdb.PROFILES_TABLE Returns a dictionary of the criteria for the named service within a list: { servicename1:[ { 'arch':arch1, 'mem':memory1, 'ipv4':ipaddress1, 'mac':macaddr1, 'platform':platform1, 'network':network1, 'cpu':cpu1, 'zonename':z1 }, ... ] } * Note1: platform, network and cpu are currently not-implemented upstream. * Note2: could simply use a list of dictionaries but implemented as a dictionary of a list of dictionary which will allow for multiple services to be listed at the same time. width of longest manifest or profile name width of longest criteria Raises None """ sdict = dict() width = 0 cwidth = 0 # ensure the named service is in our service dictionary. lservices = services.keys() if sname in lservices: try: path = AIService(sname).database_path except VersionError as version_err: warn_version(version_err) return sdict, width, cwidth if os.path.exists(path): try: maisql = AIdb.DB(path) maisql.verifyDBStructure() aiqueue = maisql.getQueue() if dbtable == AIdb.MANIFESTS_TABLE: for name in AIdb.getNames(aiqueue, dbtable): sdict[name] = list() instances = AIdb.numInstances(name, aiqueue) for instance in range(0, instances): width = max(len(name), width) criteria = AIdb.getManifestCriteria(name, instance, aiqueue, humanOutput=True, onlyUsed=True) if criteria: tdict, twidth = get_criteria_info(criteria) cwidth = max(twidth, cwidth) sdict[name].append(tdict) elif dbtable == AIdb.PROFILES_TABLE: for name in AIdb.getNames(aiqueue, dbtable): sdict[name] = list() criteria = AIdb.getProfileCriteria(name, aiqueue, humanOutput=True, onlyUsed=True) width = max(len(name), width) tdict, twidth = get_criteria_info(criteria) cwidth = max(twidth, cwidth) sdict[name].append(tdict) else: raise ValueError("Invalid value for dbtable: %s" % dbtable) except StandardError as err: sys.stderr.write(_('Error: AI database access error\n%s\n') % err) sys.exit(1) else: sys.stderr.write(_('Error: unable to locate AI database on server ' 'for %s\n') % sname) sys.exit(1) return sdict, width, cwidth
def get_manifest_or_profile_names(services, dbtable): """ Iterate through the services retrieving all the stored manifest or profile names. Args services = dictionary of service properties dbtable = database table, distinguishing manifests from profiles Returns a dictionary of service manifests or profiles within a list: { servicename1: [ [name, has_criteria (boolean), {crit:value, ... }], ... ], ... } the width of the longest service name (swidth) the width of the longest manifest name (mwidth) the width of the longest criteria (cwidth) Raises None """ swidth = 0 mwidth = 0 cwidth = 0 sdict = dict() for sname in sorted(services.keys()): try: service = AIService(sname) except VersionError as err: warn_version(err) continue path = service.database_path if os.path.exists(path): try: maisql = AIdb.DB(path) maisql.verifyDBStructure() aiqueue = maisql.getQueue() swidth = max(len(sname), swidth) if not AIdb.tableExists(aiqueue, dbtable): continue for name in AIdb.getNames(aiqueue, dbtable): mwidth = max(len(name), mwidth) tdict = dict() if dbtable == 'manifests': instances = AIdb.numInstances(name, aiqueue) for instance in range(0, instances): criteria = AIdb.getTableCriteria(name, instance, aiqueue, dbtable, humanOutput=False, onlyUsed=True) has_criteria = False if criteria is not None: for key in criteria.keys(): if criteria[key] is not None: has_criteria = True break if has_criteria: # We need criteria in human readable form hrcrit = AIdb.getTableCriteria(name, instance, aiqueue, dbtable, humanOutput=True, onlyUsed=True) tdict, twidth = get_criteria_info(hrcrit) cwidth = max(twidth, cwidth) else: criteria = AIdb.getTableCriteria(name, None, aiqueue, dbtable, humanOutput=False, onlyUsed=True) has_criteria = False if criteria is not None: for key in criteria.keys(): if criteria[key] is not None: has_criteria = True break if sname in sdict: slist = sdict[sname] slist.append([name, has_criteria, tdict]) sdict[sname] = slist else: sdict[sname] = [[name, has_criteria, tdict]] except StandardError as err: sys.stderr.write(_('Error: AI database access error\n%s\n') % err) continue else: sys.stderr.write(_('Error: unable to locate AI database for "%s" ' 'on server\n') % sname) continue return sdict, swidth, mwidth, cwidth
def get_mfest_or_profile_criteria(sname, services, dbtable): """ Iterate through all the manifests or profiles for the named service (sname) pointed to by the SCF service. Args sname = service name services = config.get_all_service_props() dbtable = database table, distinguishing manifests from profiles Assumed to be one of AIdb.MANIFESTS_TABLE or AIdb.PROFILES_TABLE Returns a dictionary of the criteria for the named service within a list: { servicename1:[ { 'arch':arch1, 'mem':memory1, 'ipv4':ipaddress1, 'mac':macaddr1, 'platform':platform1, 'network':network1, 'cpu':cpu1, 'zonename':z1 }, ... ] } * Note1: platform, network and cpu are currently not-implemented upstream. * Note2: could simply use a list of dictionaries but implemented as a dictionary of a list of dictionary which will allow for multiple services to be listed at the same time. width of longest manifest or profile name width of longest criteria Raises None """ sdict = dict() width = 0 cwidth = 0 # ensure the named service is in our service dictionary. lservices = services.keys() if sname in lservices: try: path = AIService(sname).database_path except VersionError as version_err: warn_version(version_err) return sdict, width, cwidth if os.path.exists(path): try: maisql = AIdb.DB(path) maisql.verifyDBStructure() aiqueue = maisql.getQueue() if dbtable == AIdb.MANIFESTS_TABLE: for name in AIdb.getNames(aiqueue, dbtable): sdict[name] = list() instances = AIdb.numInstances(name, aiqueue) for instance in range(0, instances): width = max(len(name), width) criteria = AIdb.getManifestCriteria( name, instance, aiqueue, humanOutput=True, onlyUsed=True) if criteria: tdict, twidth = get_criteria_info(criteria) cwidth = max(twidth, cwidth) sdict[name].append(tdict) elif dbtable == AIdb.PROFILES_TABLE: for name in AIdb.getNames(aiqueue, dbtable): sdict[name] = list() criteria = AIdb.getProfileCriteria(name, aiqueue, humanOutput=True, onlyUsed=True) width = max(len(name), width) tdict, twidth = get_criteria_info(criteria) cwidth = max(twidth, cwidth) sdict[name].append(tdict) else: raise ValueError("Invalid value for dbtable: %s" % dbtable) except StandardError as err: sys.stderr.write( _('Error: AI database access error\n%s\n') % err) sys.exit(1) else: sys.stderr.write( _('Error: unable to locate AI database on server ' 'for %s\n') % sname) sys.exit(1) return sdict, width, cwidth
def get_manifest_or_profile_names(services, dbtable): """ Iterate through the services retrieving all the stored manifest or profile names. Args services = dictionary of service properties dbtable = database table, distinguishing manifests from profiles Returns a dictionary of service manifests or profiles within a list: { servicename1: [ [name, has_criteria (boolean), {crit:value, ... }], ... ], ... } the width of the longest service name (swidth) the width of the longest manifest name (mwidth) the width of the longest criteria (cwidth) Raises None """ swidth = 0 mwidth = 0 cwidth = 0 sdict = dict() for sname in sorted(services.keys()): try: service = AIService(sname) except VersionError as err: warn_version(err) continue path = service.database_path if os.path.exists(path): try: maisql = AIdb.DB(path) maisql.verifyDBStructure() aiqueue = maisql.getQueue() swidth = max(len(sname), swidth) if not AIdb.tableExists(aiqueue, dbtable): continue for name in AIdb.getNames(aiqueue, dbtable): mwidth = max(len(name), mwidth) tdict = dict() if dbtable == 'manifests': instances = AIdb.numInstances(name, aiqueue) for instance in range(0, instances): criteria = AIdb.getTableCriteria(name, instance, aiqueue, dbtable, humanOutput=False, onlyUsed=True) has_criteria = False if criteria is not None: for key in criteria.keys(): if criteria[key] is not None: has_criteria = True break if has_criteria: # We need criteria in human readable form hrcrit = AIdb.getTableCriteria( name, instance, aiqueue, dbtable, humanOutput=True, onlyUsed=True) tdict, twidth = get_criteria_info(hrcrit) cwidth = max(twidth, cwidth) else: criteria = AIdb.getTableCriteria(name, None, aiqueue, dbtable, humanOutput=False, onlyUsed=True) has_criteria = False if criteria is not None: for key in criteria.keys(): if criteria[key] is not None: has_criteria = True break if sname in sdict: slist = sdict[sname] slist.append([name, has_criteria, tdict]) sdict[sname] = slist else: sdict[sname] = [[name, has_criteria, tdict]] except StandardError as err: sys.stderr.write( _('Error: AI database access error\n%s\n') % err) continue else: sys.stderr.write( _('Error: unable to locate AI database for "%s" ' 'on server\n') % sname) continue return sdict, swidth, mwidth, cwidth
def index(self): """ The server's main page """ # generate the list of criteria for the criteria table header criteriaHeader = E.TR() for crit in AIdb.getCriteria(self.AISQL.getQueue(), strip=False): criteriaHeader.append(E.TH(crit)) # generate the manifest rows for the criteria table body names = AIdb.getManNames(self.AISQL.getQueue()) tableBody = E.TR() for manifest in names: # iterate through each manifest (and instance) for instance in range(0, AIdb.numInstances(manifest, self.AISQL.getQueue())): tableBody.append(E.TR()) # print the manifest name only once (key off instance 0) if instance == 0: tableBody.append( E.TD(E.A(manifest, href="/manifests/" + manifest, rowspan=str(AIdb.numInstances(manifest, self.AISQL.getQueue()))) ) ) else: tableBody.append(E.TD()) critPairs = AIdb.getManifestCriteria(manifest, instance, self.AISQL.getQueue(), onlyUsed=True, humanOutput=True) # critPairs is an SQLite3 row object which doesn't support # iteritems(), etc. for crit in critPairs.keys(): formatted_val = AIdb.formatValue(crit, critPairs[crit]) # if we do not get back a valid value ensure a hyphen is # printed (this prevents "" from printing) if formatted_val and critPairs[crit]: tableBody.append(E.TD(formatted_val, align="center")) else: tableBody.append(E.TD(lxml.etree.Entity("nbsp"), align="center")) # print the default manifest at the end of the table else: tableBody.append( E.TR( E.TD( E.A("Default", href="/manifests/default.xml")), E.TD(lxml.etree.Entity("nbsp"), colspan=str(max(len(list( AIdb.getCriteria(self.AISQL.getQueue(), strip=False))), 1)), align="center") ) ) web_page = \ E.HTML( E.HEAD( E.TITLE(_("%s A/I Webserver") % _DISTRIBUTION) ), E.BODY( E.H1(_("Welcome to the %s A/I " "webserver!") % _DISTRIBUTION), E.P(_("This server has the following " "manifests available, served to clients " "matching required criteria.")), E.TABLE( E.TR( E.TH(_("Manifest"), rowspan="2"), E.TH(_("Criteria List"), colspan=str(max(len(list( AIdb.getCriteria(self.AISQL.\ getQueue(), strip=False))), 1))) ), criteriaHeader, tableBody, border="1", align="center" ), ) ) return lxml.etree.tostring(web_page, pretty_print=True)
def insert_SQL(files): """ Ensures all data is properly sanitized and formatted, then inserts it into the database Args: None Returns: None """ query = "INSERT INTO manifests VALUES(" # add the manifest name to the query string query += "'" + AIdb.sanitizeSQL(files.manifest_name) + "'," # check to see if manifest name is already in database (affects instance # number) if AIdb.sanitizeSQL(files.manifest_name) in \ AIdb.getManNames(files.database.getQueue()): # database already has this manifest name get the number of # instances instance = AIdb.numInstances(AIdb.sanitizeSQL(files.manifest_name), files.database.getQueue()) # this a new manifest else: instance = 0 # actually add the instance to the query string query += str(instance) + "," # we need to fill in the criteria or NULLs for each criteria the database # supports (so iterate over each criteria) for crit in AIdb.getCriteria(files.database.getQueue(), onlyUsed=False, strip=False): # for range values trigger on the MAX criteria (skip the MIN's # arbitrary as we handle rows in one pass) if crit.startswith('MIN'): continue # get the values from the manifest values = files.criteria[crit.replace('MAX', '', 1)] # If the critera manifest didn't specify this criteria, fill in NULLs if values is None: # use the criteria name to determine if this is a range if crit.startswith('MAX'): query += "NULL,NULL," # this is a single value else: query += "NULL," # Else if this is a value criteria (not a range), insert the value # as a space-separated list of values which will account for the case # where a list of values have been given. elif not crit.startswith('MAX'): # Join the values of the list with a space separator. query += "'" + AIdb.sanitizeSQL(" ".join(values)) + "'," # else values is a range else: for value in values: # translate "unbounded" to a database NULL if value == "unbounded": query += "NULL," # we need to deal with mac addresses specially being # hexadecimal elif crit.endswith("mac"): # need to insert with hex operand x'<val>' # use an upper case string for hex values query += "x'" + AIdb.sanitizeSQL(str(value).upper()) + \ "'," else: query += AIdb.sanitizeSQL(str(value).upper()) + "," # strip trailing comma and close parentheses query = query[:-1] + ")" # update the database query = AIdb.DBrequest(query, commit=True) files.database.getQueue().put(query) query.waitAns() # in case there's an error call the response function (which will print the # error) query.getResponse()
def list_manifests(service): '''Replies to the client with criteria list for a service. The output should be similar to installadm list. Args service - the name of the service being listed Returns None Raises None ''' print 'Content-Type: text/html' # HTML is following print # blank line, end of headers print '<html>' print '<head>' sys.stdout.write('<title>%s %s</title>' % (_('Manifest list for'), service)) print '</head><body>' port = 0 try: smf.AISCF(FMRI="system/install/server") except KeyError: # report the internal error to error_log and requesting client sys.stderr.write(_("error:The system does not have the " "system/install/server SMF service.")) sys.stdout.write(_("error:The system does not have the " "system/install/server SMF service.")) return services = config.get_all_service_names() if not services: # report the error to the requesting client only sys.stdout.write(_('error:no services on this server.\n')) return found = False if config.is_service(service): service_ctrl = AIService(service) found = True # assume new service setup path = service_ctrl.database_path if os.path.exists(path): try: aisql = AIdb.DB(path) aisql.verifyDBStructure() except StandardError as err: # report the internal error to error_log and # requesting client sys.stderr.write(_('error:AI database access ' 'error\n%s\n') % err) sys.stdout.write(_('error:AI database access ' 'error\n%s\n') % err) return # generate the list of criteria for the criteria table header criteria_header = E.TR() for crit in AIdb.getCriteria(aisql.getQueue(), strip=False): criteria_header.append(E.TH(crit)) # generate the manifest rows for the criteria table body names = AIdb.getManNames(aisql.getQueue()) table_body = E.TR() allcrit = AIdb.getCriteria(aisql.getQueue(), strip=False) colspan = str(max(len(list(allcrit)), 1)) for manifest in names: # iterate through each manifest (and instance) for instance in range(0, AIdb.numInstances(manifest, aisql.getQueue())): table_body.append(E.TR()) # print the manifest name only once (from instance 0) if instance == 0: href = '../' + service + '/' + manifest row = str(AIdb.numInstances(manifest, aisql.getQueue())) table_body.append(E.TD( E.A(manifest, href=href, rowspan=row))) else: table_body.append(E.TD()) crit_pairs = AIdb.getManifestCriteria(manifest, instance, aisql.getQueue(), onlyUsed=True, humanOutput=True) # crit_pairs is an SQLite3 row object which doesn't # support iteritems(), etc. for crit in crit_pairs.keys(): formatted_val = AIdb.formatValue(crit, crit_pairs[crit]) # if we do not get back a valid value ensure a # hyphen is printed (prevents "" from printing) if formatted_val and crit_pairs[crit]: table_body.append(E.TD(formatted_val, align="center")) else: table_body.append(E.TD(lxml.etree.Entity("nbsp"), align="center")) # print the default manifest at the end of the table, # which has the same colspan as the Criteria List label else: href = '../' + service + '/default.xml' table_body.append(E.TR(E.TD(E.A("Default", href=href)), E.TD(lxml.etree.Entity("nbsp"), colspan=colspan, align="center"))) web_page = E.HTML( E.HEAD( E.TITLE(_("OmniOS Automated " "Installation Webserver")) ), E.BODY( E.H1(_("Welcome to the OmniOS " "Automated Installation webserver!")), E.P(_("Service '%s' has the following " "manifests available, served to clients " "matching required criteria.") % service), E.TABLE( E.TR( E.TH(_("Manifest"), rowspan="2"), E.TH(_("Criteria List"), colspan=colspan)), criteria_header, table_body, border="1", align="center"), ) ) print lxml.etree.tostring(web_page, pretty_print=True) # service is not found, provide available services on host if not found: sys.stdout.write(_('Service <i>%s</i> not found. ') % service) sys.stdout.write(_('Available services are:<p><ol><i>')) host = socket.gethostname() for service_name in config.get_all_service_names(): # assume new service setup port = config.get_service_port(service_name) sys.stdout.write('<a href="http://%s:%d/cgi-bin/' 'cgi_get_manifest.py?version=%s&service=%s">%s</a><br>\n' % (host, port, VERSION, service_name, service_name)) sys.stdout.write('</i></ol>%s' % _('Please select a service ' 'from the above list.')) print '</body></html>'