def _check_servers(self): """ Returns True or False depending whether the server_list is a valid list of servers. A valid list consists of host[:port] entries separated by commas, e.g. server1.example.com,server2.example.com:2188 """ valid = True for probe in self.enabled_probe_settings: if probe == 'metric': sys.stdout.write(self.metric_probe_deprecation + "\n") self.log(self.metric_probe_deprecation, level=logging.WARNING) server = self.enabled_probe_settings[probe].split(':')[0] if not validation.valid_domain(server, False): err_mesg = "The server specified for probe %s is not " % probe err_mesg += "a valid domain: %s" % server self.log(err_mesg, level=logging.ERROR) valid = False elif not validation.valid_domain(server, True): err_mesg = "The server specified for probe %s does not " % probe err_mesg += "resolve: %s" % server self.log(err_mesg, level=logging.WARNING) if server != self.enabled_probe_settings[probe]: port = self.enabled_probe_settings[probe].split(':')[1] try: temp = int(port) if temp < 0: raise ValueError() except ValueError: self.log("The port specified for probe %s is not valid, either it " "is less than 0 or not an integer" % probe, exception=True, level=logging.ERROR) return valid
def _check_servers(self): """ Returns True or False depending whether the server_list is a valid list of servers. A valid list consists of host[:port] entries separated by commas, e.g. server1.example.com,server2.example.com:2188 """ valid = True for probe in self.enabled_probe_settings: if probe == 'metric': sys.stdout.write(self.metric_probe_deprecation + "\n") self.log(self.metric_probe_deprecation, level=logging.WARNING) server = self.enabled_probe_settings[probe].split(':')[0] if not validation.valid_domain(server, False): err_mesg = "The server specified for probe %s is not " % probe err_mesg += "a valid domain: %s" % server self.log(err_mesg, level=logging.ERROR) valid = False elif not validation.valid_domain(server, True): err_mesg = "The server specified for probe %s does not " % probe err_mesg += "resolve: %s" % server self.log(err_mesg, level=logging.WARNING) if server != self.enabled_probe_settings[probe]: port = self.enabled_probe_settings[probe].split(':')[1] try: temp = int(port) if temp < 0: raise ValueError() except ValueError: self.log( "The port specified for probe %s is not valid, either it " "is less than 0 or not an integer" % probe, exception=True, level=logging.ERROR) return valid
def check_attributes(self, attributes): """Check attributes currently stored and make sure that they are consistent""" self.log('MiscConfiguration.check_attributes started') attributes_ok = True if not self.enabled: self.log('Not enabled, returning True') self.log('MiscConfiguration.check_attributes completed') return True if (self.options['authorization_method'].value not in \ ['gridmap', 'local-gridmap', 'xacml']): self.log("Setting is not xacml, or gridmap", option='authorization_method', section=self.config_section, level=logging.ERROR) attributes_ok = False if self.options['authorization_method'].value == 'xacml': if utilities.blank(self.options['gums_host'].value): self.log("Gums host not given", section=self.config_section, option='gums_host', level=logging.ERROR) attributes_ok = False if not validation.valid_domain(self.options['gums_host'].value, resolve=True): self.log("Gums host not a valid domain name or does not resolve", section=self.config_section, option='gums_host', level=logging.ERROR) attributes_ok = False self.log('MiscConfiguration.check_attributes completed') return attributes_ok
def _check_subscription(self, subscription, dialect): """ Check a subscription and dialect to make sure it's valid, return True if that's the case, otherwise false. subscription must be a uri and dialect must be CLASSAD, RAW, or OLD_CLASSAD """ valid = True # check for valid uri result = urlparse.urlsplit(subscription) if result[1] == '': self.log("Subscription must be a uri, got %s" % subscription, level=logging.ERROR) valid = False # check to see if host resolves server = result[1] if ':' in server: server = server.split(':')[0] if not validation.valid_domain(server, True): self.log("Host in subscription does not resolve: %s" % server, level=logging.WARNING) # check to make sure dialect is correct if dialect not in ('CLASSAD', 'RAW', 'OLD_CLASSAD'): self.log("Dialect for subscription %s is not valid: %s" % (server, dialect), level=logging.ERROR) valid = False return valid
def test_valid_domain(self): """ Check the valid_domain functionality """ test_domain = "testing" self.assertTrue(validation.valid_domain(test_domain), "testing marked as an invalid domain address") test_domain = "34c93F.39f@~#" self.assertFalse(validation.valid_domain(test_domain), "34c93F.39f@~# marked as a valid domain address") test_domain = "t-ea.34.org" self.assertTrue(validation.valid_domain(test_domain), "t-ea.34.org marked as an invalid domain address") test_domain = "uchicago.edu" self.assertTrue( validation.valid_domain(test_domain, resolve=True), "uchicago.edu marked as an invalid domain address" ) test_domain = "invalid.invalid" self.assertFalse( validation.valid_domain(test_domain, resolve=True), "invalid.invalid marked as an valid domain address" )
def test_valid_domain(self): """ Check the valid_domain functionality """ test_domain = "testing" self.assertTrue(validation.valid_domain(test_domain), "testing marked as an invalid domain address") test_domain = "34c93F.39f@~#" self.assertFalse(validation.valid_domain(test_domain), "34c93F.39f@~# marked as a valid domain address") test_domain = "t-ea.34.org" self.assertTrue(validation.valid_domain(test_domain), "t-ea.34.org marked as an invalid domain address") test_domain = "uchicago.edu" self.assertTrue(validation.valid_domain(test_domain, resolve=True), "uchicago.edu marked as an invalid domain address") test_domain = "invalid.invalid" self.assertFalse(validation.valid_domain(test_domain, resolve=True), "invalid.invalid marked as an valid domain address")
def check_attributes(self, attributes): """Check attributes currently stored and make sure that they are consistent""" self.log('MiscConfiguration.check_attributes started') attributes_ok = True if not self.enabled: self.log('Not enabled, returning True') self.log('MiscConfiguration.check_attributes completed') return True if self.authorization_method not in VALID_AUTH_METHODS: self.log("Setting is not one of: " + ", ".join(VALID_AUTH_METHODS), option='authorization_method', section=self.config_section, level=logging.ERROR) attributes_ok = False if self.authorization_method == 'xacml': gums_host = self.options['gums_host'].value if utilities.blank(gums_host): self.log("Gums host not given", section=self.config_section, option='gums_host', level=logging.ERROR) attributes_ok = False elif not validation.valid_domain(gums_host, resolve=True): self.log( "Gums host not a valid domain name or does not resolve", section=self.config_section, option='gums_host', level=logging.ERROR) attributes_ok = False self.log( "Gums is deprecated in OSG 3.4. The replacement is the LCMAPS VOMS plugin; please see" " installation instructions at" " https://opensciencegrid.github.io/docs/security/lcmaps-voms-authentication/", section=self.config_section, option='authorization_method', level=logging.WARNING) if self.using_glexec: msg = "glExec is not supported in OSG 3.4; unset glexec_location" self.log(msg, options='glexec_location', section=self.config_section, level=logging.ERROR) attributes_ok = False self.log('MiscConfiguration.check_attributes completed') return attributes_ok
def _validate_host_list(self, hosts, setting): """ Validate a list of hosts """ ret = True for host in hosts: # Strip off the port hostname, port = utilities.split_host_port(host) if not validation.valid_domain(hostname): self.log("Invalid domain in [%s].%s: %s" % (self.config_section, setting, host), level=logging.ERROR) ret = False if port and re.search('[^0-9]', port): self.log("Invalid port in [%s].%s: %s" % (self.config_section, setting, host), level=logging.ERROR) ret = False return ret
def check_attributes(self, attributes): """Check attributes currently stored and make sure that they are consistent""" self.log('SquidConfiguration.check_attributes started') attributes_ok = True if not (utilities.gateway_installed() and utilities.rpm_installed('frontier-squid')): return attributes_ok if not self.enabled: self.log( "Squid is not enabled, sites must enable this \n" + "section, location can be set to UNAVAILABLE if squid is \n" + "not present", level=logging.WARNING) self.log('squid not enabled') self.log('SquidConfiguration.check_attributes completed') return attributes_ok if self.ignored: self.log('Ignored, returning True') self.log('SquidConfiguration.check_attributes completed') return attributes_ok if (self.options['location'].value == 'None'): self.log( "location setting must be set, if site does not provide " + "squid, please use UNAVAILABLE", section=self.config_section, option='location', level=logging.WARNING) return attributes_ok if (self.options['location'].value.upper() == 'UNAVAILABLE'): self.log( "Squid location is set to UNAVAILABLE. Although this is \n" + "allowed, most jobs function better and use less bandwidth \n" + "when a squid proxy is available", level=logging.WARN) self.options['location'].value = 'None' return attributes_ok if len(self.options['location'].value.split(':')) != 2: self.log("Bad host specification, got %s expected hostname:port " \ "(e.g. localhost:3128)" % self.options['location'].value, section=self.config_section, option='location', level=logging.ERROR) attributes_ok = False return attributes_ok (hostname, port) = self.options['location'].value.split(':') if not validation.valid_domain(hostname, True): self.log("Invalid hostname for squid location: %s" % \ self.options['location'].value, section=self.config_section, option='location', level=logging.ERROR) attributes_ok = False try: int(port) except ValueError: self.log("The port must be a number(e.g. host:3128) for squid " \ "location: %s" % self.options['location'].value, section=self.config_section, option='location', level=logging.ERROR, exception=True) attributes_ok = False self.log('SquidConfiguration.check_attributes completed') return attributes_ok
def check_attributes(self, attributes): """Check attributes currently stored and make sure that they are consistent""" self.log('SiteInformation.check_attributes started') attributes_ok = True if not self.enabled: self.log('Not enabled, returning True') self.log('SiteInformation.check_attributes completed') return attributes_ok # OSG_GROUP must be either OSG or OSG-ITB group = self.opt_val("group") if group not in ('OSG', 'OSG-ITB'): self.log( "The group setting must be either OSG or OSG-ITB, got: %s" % group, option='group', section=self.config_section, level=logging.ERROR) attributes_ok = False host_name = self.opt_val("host_name") if not utilities.blank(host_name): if not validation.valid_domain(host_name, resolve=False): self.log("%s is not a valid domain", host_name, option="host_name", section=self.config_section, level=logging.ERROR) attributes_ok = False elif not validation.valid_domain(host_name, resolve=True): self.log("%s is a valid domain but can't be resolved", host_name, option="host_name", section=self.config_section, level=logging.WARNING) latitude = self.opt_val("latitude") if not utilities.blank(latitude) and not -90 <= latitude <= 90: self.log("Latitude must be between -90 and 90, got %s" % latitude, section=self.config_section, option='latitude', level=logging.ERROR) attributes_ok = False longitude = self.opt_val("longitude") if not utilities.blank(longitude) and not -180 <= longitude <= 180: self.log("Longitude must be between -180 and 180, got %s" % longitude, section=self.config_section, option='longitude', level=logging.ERROR) attributes_ok = False email = self.opt_val("email") # make sure the email address has the correct format if not utilities.blank(email) and not validation.valid_email(email): self.log("Invalid email address in site information: %s" % email, section=self.config_section, option='email', level=logging.ERROR) attributes_ok = False sponsor = self.opt_val("sponsor") if not utilities.blank(sponsor): attributes_ok &= self.check_sponsor(sponsor) self.log('SiteInformation.check_attributes completed') return attributes_ok
def check_attributes(self, attributes): """Check attributes currently stored and make sure that they are consistent""" self.log("SiteAttributes.check_attributes started") attributes_ok = True if not self.enabled: self.log("Not enabled, returning True") self.log("SiteAttributes.check_attributes completed") return attributes_ok # OSG_GROUP must be either OSG or OSG-ITB if self.options["group"].value not in ("OSG", "OSG-ITB"): self.log( "The group setting must be either OSG or OSG-ITB, got: %s" % self.options["group"].value, option="group", section=self.config_section, level=logging.ERROR, ) attributes_ok = False # host_name must be different from the default setting if self.options["host_name"].value == "my.domain.name": self.log( "Setting left at default value: my.domain.name", option="host_name", section=self.config_section, level=logging.ERROR, ) attributes_ok = False # host_name must be a valid dns name, check this by getting it's ip adddress if not validation.valid_domain(self.options["host_name"].value, True): self.log( "hostname %s can't be resolved" % self.options["host_name"].value, option="host_name", section=self.config_section, level=logging.ERROR, ) attributes_ok = False # site_name or resource/resource_group must be specified not both if not utilities.blank(self.options["site_name"].value) and ( not utilities.blank(self.options["resource"].value) or not utilities.blank(self.options["resource_group"].value) ): self.log( "In section '%s', site_name and " % self.config_section + "resource or resource_group given at the same time, " + "you should use just the resource and resource_group settings.", level=logging.WARNING, ) if self.options["latitude"].value > 90 or self.options["latitude"].value < -90: self.log( "Latitude must be between -90 and 90, got %s" % self.options["latitude"].value, section=self.config_section, option="latitude", level=logging.ERROR, ) attributes_ok = False if self.options["longitude"].value > 180 or self.options["longitude"].value < -180: self.log( "Longitude must be between -180 and 180, got %s" % self.options["longitude"].value, section=self.config_section, option="longitude", level=logging.ERROR, ) attributes_ok = False # make sure that the email address is different from the default value if self.options["email"] == "*****@*****.**": self.log( "The email setting must be changed from the default", section=self.config_section, option="email", level=logging.ERROR, ) attributes_ok = False # make sure the email address has the correct format if not validation.valid_email(self.options["email"].value): self.log( "Invalid email address in site information: %s" % self.options["email"].value, section=self.config_section, option="email", level=logging.ERROR, ) attributes_ok = False vo_list = self.options["sponsor"].value percentage = 0 vo_names = utilities.get_vos(None) if vo_names == []: map_file_present = False else: map_file_present = True vo_names.append("usatlas") # usatlas is a valid vo name vo_names.append("uscms") # uscms is a valid vo name vo_names.append("local") # local is a valid vo name cap_vo_names = [vo.upper() for vo in vo_names] for vo in re.split(r"\s*,?\s*", vo_list): vo_name = vo.split(":")[0] if vo_name not in vo_names: if vo_name.upper() in cap_vo_names: self.log( "VO name %s has the wrong capitialization" % vo_name, section=self.config_section, option="sponsor", level=logging.WARNING, ) vo_mesg = "Valid VO names are as follows:\n" for name in vo_names: vo_mesg += name + "\n" self.log(vo_mesg, level=logging.WARNING) else: if map_file_present: self.log("In %s section, problem with sponsor setting" % self.config_section) self.log( "VO name %s not found" % vo_name, section=self.config_section, option="sponsor", level=logging.ERROR, ) vo_mesg = "Valid VO names are as follows:\n" for name in vo_names: vo_mesg += name + "\n" self.log(vo_mesg, level=logging.ERROR) attributes_ok = False else: self.log( "Can't currently check VOs in sponsor setting because " + "the /var/lib/osg/user-vo-map is empty. If you are " + "configuring osg components, this may be resolved when " + "osg-configure runs the appropriate script to generate " + "this file later in the configuration process", section=self.config_section, option="sponsor", level=logging.WARNING, ) if len(vo.split(":")) == 1: percentage += 100 elif len(vo.split(":")) == 2: vo_percentage = vo.split(":")[1] try: percentage += int(vo_percentage) except ValueError: self.log( "VO percentage (%s) in sponsor field (%s) not an integer" % (vo_percentage, vo), section=self.config_section, option="sponsor", level=logging.ERROR, exception=True, ) attributes_ok = False else: self.log( "VO sponsor field is not formated correctly: %s" % vo, section=self.config_section, option="sponsor", level=logging.ERROR, ) self.log("Sponsors should be given as sponsor:percentage " "separated by a space or comma") if percentage != 100: self.log( "VO percentages in sponsor field do not add up to 100, got %s" % percentage, section=self.config_section, option="sponsor", level=logging.ERROR, ) attributes_ok = False self.log("SiteAttributes.check_attributes completed") return attributes_ok
def check_attributes(self, attributes): """Check attributes currently stored and make sure that they are consistent""" self.log('SiteAttributes.check_attributes started') attributes_ok = True if not self.enabled: self.log('Not enabled, returning True') self.log('SiteAttributes.check_attributes completed') return attributes_ok # OSG_GROUP must be either OSG or OSG-ITB if self.options['group'].value not in ('OSG', 'OSG-ITB'): self.log("The group setting must be either OSG or OSG-ITB, got: %s" % self.options['group'].value, option='group', section=self.config_section, level=logging.ERROR) attributes_ok = False # host_name must be different from the default setting if self.options['host_name'].value == 'my.domain.name': self.log("Setting left at default value: my.domain.name", option='host_name', section=self.config_section, level=logging.ERROR) attributes_ok = False # host_name must be a valid dns name, check this by getting it's ip adddress if not validation.valid_domain(self.options['host_name'].value, True): self.log("hostname %s can't be resolved" % self.options['host_name'].value, option='host_name', section=self.config_section, level=logging.ERROR) attributes_ok = False # site_name or resource/resource_group must be specified not both if (not utilities.blank(self.options['site_name'].value) and (not utilities.blank(self.options['resource'].value) or not utilities.blank(self.options['resource_group'].value))): self.log("In section '%s', site_name and " % self.config_section + "resource or resource_group given at the same time, " + "you should use just the resource and resource_group settings.", level=logging.WARNING) if self.options['latitude'].value > 90 or self.options['latitude'].value < -90: self.log("Latitude must be between -90 and 90, got %s" % self.options['latitude'].value, section=self.config_section, option='latitude', level=logging.ERROR) attributes_ok = False if self.options['longitude'].value > 180 or self.options['longitude'].value < -180: self.log("Longitude must be between -180 and 180, got %s" % self.options['longitude'].value, section=self.config_section, option='longitude', level=logging.ERROR) attributes_ok = False # make sure that the email address is different from the default value if self.options['email'] == '*****@*****.**': self.log("The email setting must be changed from the default", section=self.config_section, option='email', level=logging.ERROR) attributes_ok = False # make sure the email address has the correct format and that the domain portion is # resolvable if not validation.valid_email(self.options['email'].value): self.log("Invalid email address in site information: %s" % self.options['email'].value, section=self.config_section, option='email', level=logging.ERROR) attributes_ok = False else: match = re.match(r'(?:[a-zA-Z\-_+0-9.]+)@([a-zA-Z0-9_\-]+(?:\.[a-zA-Z0-9_\-]+)+)', self.options['email'].value) try: socket.gethostbyname(match.group(1)) except socket.herror: self.log("Can't resolve domain in email: %s" % self.options['email'].value, section=self.config_section, option='email', level=logging.WARNING, exception=True) except socket.gaierror: self.log("Can't resolve domain in email: %s" % self.options['email'].value, section=self.config_section, option='email', level=logging.WARNING, exception=True) vo_list = self.options['sponsor'].value percentage = 0 vo_names = utilities.get_vos(None) if vo_names == []: map_file_present = False else: map_file_present = True vo_names.append('usatlas') # usatlas is a valid vo name vo_names.append('uscms') # uscms is a valid vo name vo_names.append('local') # local is a valid vo name cap_vo_names = [vo.upper() for vo in vo_names] for vo in re.split(r'\s*,?\s*', vo_list): vo_name = vo.split(':')[0] if vo_name not in vo_names: if vo_name.upper() in cap_vo_names: self.log("VO name %s has the wrong capitialization" % vo_name, section=self.config_section, option='sponsor', level=logging.WARNING) vo_mesg = "Valid VO names are as follows:\n" for name in vo_names: vo_mesg += name + "\n" self.log(vo_mesg, level=logging.WARNING) else: if map_file_present: self.log("In %s section, problem with sponsor setting" % \ self.config_section) self.log("VO name %s not found" % vo_name, section=self.config_section, option='sponsor', level=logging.ERROR) vo_mesg = "Valid VO names are as follows:\n" for name in vo_names: vo_mesg += name + "\n" self.log(vo_mesg, level=logging.ERROR) attributes_ok = False else: self.log("Can't currently check VOs in sponsor setting because " + "the /var/lib/osg/user-vo-map is empty. If you are " + "configuring osg components, this may be resolved when " + "osg-configure runs the appropriate script to generate " + "this file later in the configuration process", section=self.config_section, option='sponsor', level=logging.WARNING) if len(vo.split(':')) == 1: percentage += 100 elif len(vo.split(':')) == 2: vo_percentage = vo.split(':')[1] try: percentage += int(vo_percentage) except ValueError: self.log("VO percentage (%s) in sponsor field (%s) not an integer" \ % (vo_percentage, vo), section=self.config_section, option='sponsor', level=logging.ERROR, exception=True) attributes_ok = False else: self.log("VO sponsor field is not formated correctly: %s" % vo, section=self.config_section, option='sponsor', level=logging.ERROR) self.log("Sponsors should be given as sponsor:percentage " "separated by a space or comma") if percentage != 100: self.log("VO percentages in sponsor field do not add up to 100, got %s" \ % percentage, section=self.config_section, option='sponsor', level=logging.ERROR) attributes_ok = False self.log('SiteAttributes.check_attributes completed') return attributes_ok
def check_attributes(self, attributes): """Check attributes currently stored and make sure that they are consistent""" self.log("SquidConfiguration.check_attributes started") attributes_ok = True if not (utilities.gateway_installed() and utilities.rpm_installed("frontier-squid")): return attributes_ok if not self.enabled: self.log( "Squid is not enabled, sites must enable this \n" + "section, location can be set to UNAVAILABLE if squid is \n" + "not present", level=logging.WARNING, ) self.log("squid not enabled") self.log("SquidConfiguration.check_attributes completed") return attributes_ok if self.ignored: self.log("Ignored, returning True") self.log("SquidConfiguration.check_attributes completed") return attributes_ok if self.options["location"].value == "None": self.log( "location setting must be set, if site does not provide " + "squid, please use UNAVAILABLE", section=self.config_section, option="location", level=logging.WARNING, ) return attributes_ok if self.options["location"].value.upper() == "UNAVAILABLE": self.log( "Squid location is set to UNAVAILABLE. Although this is \n" + "allowed, most jobs function better and use less bandwidth \n" + "when a squid proxy is available", level=logging.WARN, ) self.options["location"].value = "None" return attributes_ok if len(self.options["location"].value.split(":")) != 2: self.log( "Bad host specification, got %s expected hostname:port " "(e.g. localhost:3128)" % self.options["location"].value, section=self.config_section, option="location", level=logging.ERROR, ) attributes_ok = False return attributes_ok (hostname, port) = self.options["location"].value.split(":") if not validation.valid_domain(hostname, True): self.log( "Invalid hostname for squid location: %s" % self.options["location"].value, section=self.config_section, option="location", level=logging.ERROR, ) attributes_ok = False try: int(port) except ValueError: self.log( "The port must be a number(e.g. host:3128) for squid " "location: %s" % self.options["location"].value, section=self.config_section, option="location", level=logging.ERROR, exception=True, ) attributes_ok = False self.log("SquidConfiguration.check_attributes completed") return attributes_ok
def check_attributes(self, attributes): """Check attributes currently stored and make sure that they are consistent""" self.log('SiteInformation.check_attributes started') attributes_ok = True if not self.enabled: self.log('Not enabled, returning True') self.log('SiteInformation.check_attributes completed') return attributes_ok # OSG_GROUP must be either OSG or OSG-ITB group = self.opt_val("group") if group not in ('OSG', 'OSG-ITB'): self.log("The group setting must be either OSG or OSG-ITB, got: %s" % group, option='group', section=self.config_section, level=logging.ERROR) attributes_ok = False host_name = self.opt_val("host_name") # host_name must be a valid dns name, check this by getting it's ip adddress if not utilities.blank(host_name) and not validation.valid_domain(host_name, True): self.log("hostname %s can't be resolved" % host_name, option='host_name', section=self.config_section, level=logging.ERROR) attributes_ok = False if not utilities.blank(self.opt_val("site_name")): self.log("The site_name setting has been deprecated in favor of the" " resource and resource_group settings and will be removed", section=self.config_section, option="site_name", level=logging.WARNING) latitude = self.opt_val("latitude") if not utilities.blank(latitude) and not -90 < latitude < 90: self.log("Latitude must be between -90 and 90, got %s" % latitude, section=self.config_section, option='latitude', level=logging.ERROR) attributes_ok = False longitude = self.opt_val("longitude") if not utilities.blank(longitude) and not -180 < longitude < 180: self.log("Longitude must be between -180 and 180, got %s" % longitude, section=self.config_section, option='longitude', level=logging.ERROR) attributes_ok = False email = self.opt_val("email") # make sure the email address has the correct format if not utilities.blank(email) and not validation.valid_email(email): self.log("Invalid email address in site information: %s" % email, section=self.config_section, option='email', level=logging.ERROR) attributes_ok = False sponsor = self.opt_val("sponsor") if not utilities.blank(sponsor): attributes_ok &= self.check_sponsor(sponsor) self.log('SiteInformation.check_attributes completed') return attributes_ok