def findAPILocation(domain_url):

	(status, briefing, message, output) = domainNameLookup(domain_url)
	if ( status != 0 ):
		return (status, briefing, message, None)

	status, briefing, message, data = apiLookup(domain_url)
	if ( status != 0 ):
		status = 2
		briefing = "This test was skipped because previous test <strong>api_server_lookup</strong> has failed.<br/>"
		new_message = briefing
		new_message += "Reason:<br/>"
		new_message += "<br/>" + message
		return (status, briefing, new_message, None)

	status, briefing, message, output = apiConnection(domain_url)
	if ( status != 0 ):
		status = 2
		briefing = "This test was skipped because previous test <strong>api_server_connection</strong> has failed.<br/>"
		new_message = briefing
		new_message = "Reason:<br/>"
		new_message += "<br/>" + message
		return (status, briefing, new_message, None)

	api_location = "%(protocol)s://%(domain)s%(path)s/" % data
	
	status = 0
	briefing = "HTTP API location for buddycloud domain at %s found: %s" % (domain_url, api_location)
	message = briefing
	return (status, briefing, message, api_location)
def performSRVLookup(domain_url, srv_name, srv_description, srv_port):

	(status, briefing, message, output) = domainNameLookup(domain_url)
	if ( status != 0 ):
		return (status, briefing, message, None)

	answers = []
	query_for_SRV_record = None

	try:

		resolver = dns.resolver.Resolver()
		resolver.nameservers = [ getAuthoritativeNameserver(domain_url) ]
		resolver.lifetime = 5
		query_for_SRV_record = resolver.query(srv_name+domain_url, dns.rdatatype.SRV)

	except (NXDOMAIN, NoAnswer, Timeout):

		return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

	except Exception, e:

		if ( str(e) == "" or str(e) == ("%s. does not exist." % domain_url) ):
			return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

		status = 2
		briefing = "A problem happened while searching for the %s:" % srv_description
		briefing += " <strong>" + srv_name + domain_url + "</strong>!"
		message = "Something odd happened while we were searching for the %s:" % srv_description
		message += " <strong>" + srv_name + domain_url + "</strong>!"
		message += "<br/>This is the exception we got: {"+str(e)+"}"
		message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
		message += "<br/>But it could also be a bug in our Inspector."
		message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so." 
		return (status, briefing, message, None)
Esempio n. 3
0
def findAPILocation(domain_url):

    (status, briefing, message, output) = domainNameLookup(domain_url)
    if (status != 0):
        return (status, briefing, message, None)

    status, briefing, message, data = apiLookup(domain_url)
    if (status != 0):
        status = 2
        briefing = "This test was skipped because previous test <strong>api_server_lookup</strong> has failed.<br/>"
        new_message = briefing
        new_message += "Reason:<br/>"
        new_message += "<br/>" + message
        return (status, briefing, new_message, None)

    status, briefing, message, output = apiConnection(domain_url)
    if (status != 0):
        status = 2
        briefing = "This test was skipped because previous test <strong>api_server_connection</strong> has failed.<br/>"
        new_message = briefing
        new_message = "Reason:<br/>"
        new_message += "<br/>" + message
        return (status, briefing, new_message, None)

    api_location = "%(protocol)s://%(domain)s%(path)s/" % data

    status = 0
    briefing = "HTTP API location for buddycloud domain at %s found: %s" % (
        domain_url, api_location)
    message = briefing
    return (status, briefing, message, api_location)
def testFunction(domain_url):

    view = {"domain_url":domain_url}

    if ( domainNameLookup(domain_url)[0] != 0 ):
        view["warning"] = "%s not found!" % (domain_url)
        return warning(view)

    try:
        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        if ( nameserver ):
            resolver.nameservers = [ nameserver ]
        answer = resolver.query("_buddycloud-api._tcp."+domain_url,
            dns.rdatatype.TXT)
    except Exception as e:
        return no_record(view)

    else:

        txt_answer = answer[0].to_text()
        view["record"] = txt_answer

        for test in record_well_formedness_tests:
            if ( not test[0](txt_answer) ):
                view["error"] = code("TXT record") + " is malformed! " + test[1]
                return record_error(view)

        domain =  txt_answer[txt_answer.find("host=")+5:
            txt_answer.find(" ", txt_answer.find("host=")+5)]
        port = txt_answer[txt_answer.find("port=")+5:
            txt_answer.find(" ", txt_answer.find("port=")+5)]
        path = txt_answer[txt_answer.find("path=")+5:
            txt_answer.find(" ", txt_answer.find("path=")+5)]
        protocol = txt_answer[txt_answer.find("protocol=")+9:
            txt_answer.find(" ", txt_answer.find("protocol=")+9)]

        if ( protocol.lower() != "https" ):
            view["error"] = code("TXT record") + "\'s " + bold("protocol") + "\
                attribute must have value set to " + code("https") + "!"
            return record_error(view)

        output = {
            'protocol' : protocol,
            'domain' : domain,
            'port' : port,
            'path' : path
        }
        return record_correct(view, output)
def testFunction(domain_url):

    (status, briefing, message, output) = domainNameLookup(domain_url)
    if status != 0:
        return (status, briefing, message, None)

    classified_as = checkMediaServerPresence(domain_url)

    description = descriptions[classified_as] % ("<strong>" + domain_url + "</strong>")
    briefing = description.split("<br/>")[0]
    message = description

    if classified_as == "MEDIASERVER_UP":
        status = 0
    elif classified_as == "SERVER_ERROR" or classified_as == "NOT_MEDIASERVER_UP":
        status = 1
    else:
        status = 2

    return (status, briefing, message, None)
def testFunction(domain_url):

    (status, briefing, message, output) = domainNameLookup(domain_url)
    if (status != 0):
        return (status, briefing, message, None)

    classified_as = checkPusherServerPresence(domain_url)

    description = descriptions[classified_as] % ("<strong>" + domain_url +
                                                 "</strong>")
    briefing = description.split("<br/>")[0]
    message = description

    if (classified_as == "PUSHERSERVER_UP"):
        status = 0
    elif (classified_as == "SERVER_ERROR"
          or classified_as == "NOT_PUSHERSERVER_UP"):
        status = 1
    else:
        status = 2

    return (status, briefing, message, None)
Esempio n. 7
0
def performSRVLookup(domain_url, srv_name, srv_description, srv_port):

    (status, briefing, message, output) = domainNameLookup(domain_url)
    if (status != 0):
        return (status, briefing, message, None)

    answers = []
    query_for_SRV_record = None

    try:

        resolver = dns.resolver.Resolver()
        resolver.nameservers = [getAuthoritativeNameserver(domain_url)]
        resolver.lifetime = 5
        query_for_SRV_record = resolver.query(srv_name + domain_url,
                                              dns.rdatatype.SRV)

    except (NXDOMAIN, NoAnswer, Timeout):

        return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

    except Exception, e:

        if (str(e) == "" or str(e) == ("%s. does not exist." % domain_url)):
            return no_SRV_record(domain_url, srv_name, srv_description,
                                 srv_port)

        status = 2
        briefing = "A problem happened while searching for the %s:" % srv_description
        briefing += " <strong>" + srv_name + domain_url + "</strong>!"
        message = "Something odd happened while we were searching for the %s:" % srv_description
        message += " <strong>" + srv_name + domain_url + "</strong>!"
        message += "<br/>This is the exception we got: {" + str(e) + "}"
        message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
        message += "<br/>But it could also be a bug in our Inspector."
        message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so."
        return (status, briefing, message, None)
Esempio n. 8
0
def testFunction(domain_url):

    (status, briefing, message, output) = domainNameLookup(domain_url)
    if (status != 0):
        return (status, briefing, message, None)

    query_for_TXT_record = None

    try:

        resolver = dns.resolver.Resolver()
        resolver.nameservers = [getAuthoritativeNameserver(domain_url)]
        resolver.lifetime = 5
        query_for_TXT_record = resolver.query(
            "_buddycloud-api._tcp." + domain_url, dns.rdatatype.TXT)

    except (NXDOMAIN, NoAnswer):

        return noTXTRecord(domain_url)

    except Exception as e:

        if (str(e) == "" or str(e) == ("%s. does not exist." % domain_url)):
            return noTXTRecord(domain_url)

        status = 2
        briefing = "A problem happened while searching for the API server TXT record:"
        briefing += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
        message = "Something odd happened while we were searching for the API server TXT record:"
        message += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
        message += "<br/>This is the exception we got: {" + str(e) + "}"
        message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
        message += "<br/>But it could also be a bug in our Inspector."
        message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so."
        return (status, briefing, message, None)

    classified_records = {}

    for answer in query_for_TXT_record:

        classified = classifyTXTRecord(str(answer))

        if not classified['type'] in classified_records:
            classified_records[classified['type']] = []
        classified_records[classified['type']].append(classified)

    if (len(classified_records.get('INFO_MISSING', [])) != 0
            or len(classified_records.get('MALFORMED', [])) != 0
            or len(classified_records.get('NOT_HTTPS', [])) != 0):

        status = 1
        briefing = "We detected incorrect API server TXT records at domain"
        briefing += " <strong>%s</strong>." % domain_url
        message = "We detected you set up the following incorrect API"
        message += " server TXT records.<br/>"
        message += "You must have just one correct API server SRV record.<br/>"
        message += "These are the SRV records we found and their problems: <br/><br/>"

        for record in classified_records.get('INFO_MISSING', []):

            message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>" %
                        (record['description'], record['record']))

        for record in classified_records.get('MALFORMED', []):

            message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>" %
                        (record['description'], record['record']))

        if (len(classified_records.get('MALFORMED', [])) != 0):

            message += "The API server TXT record must always have a <em>version</em>, <em>host</em>,"
            message += " <em>protocol</em>, <em>path</em> and <em>port</em>.<br/>"
            message += "<strong>Each of these properties must be defined within double quotes and separated by spaces only</strong>.<br/>"
            message += "For example, assuming that the server running buddycloud will be named: <strong><em>buddycloud."
            message += domain_url + "</em></strong>,"
            message += "<br/>here you are a TXT record that should work:<br/>"
            message += "<strong>_buddycloud-api._tcp." + domain_url + "\tIN TXT \"v=1.0\" \"host=buddycloud."
            message += domain_url + "\" \"protocol=https\" \"path=/api\" \"port=433\"</strong><br/>"
            message += "<br/>Please not that your API server TXT record won't be correct until it contains proper"
            message += " information regarding the <em>version</em>, <em>host</em>, <em>protocol<em/>, <em>path</em> and <em>port</em>.<br/>"

        for record in classified_records.get('NOT_HTTPS', []):

            message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>" %
                        (record['description'], record['record']))

        if (len(classified_records.get('NOT_HTTPS', [])) != 0):

            message += "Please ensure your API server will run with HTTPS enabled.<br/>"

        message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
        message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
        return (status, briefing, message, None)

    elif len(classified_records.get('CORRECT', [])) == 0:

        status = 1
        briefing = "No correct API server TXT record found at "
        briefing += "domain <strong>%s</strong>!<br/>" % domain_url
        message = briefing + "<br/>"
        message += "You must have one correct API server SRV record.<br/>"
        message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
        message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
        return (status, briefing, message, None)

    elif len(classified_records.get('CORRECT', [])) > 1:

        status = 1
        briefing = "We found multiple correct API server TXT records!"
        message = briefing + "<br/>"
        message += "But really, you should have just one.<br/>"
        message += "These are the records we found: <br/><br/>"

    else:

        status = 0
        briefing = "API server TXT record found: "
        briefing += "<strong>%s</strong>" % classified_records['CORRECT'][0][
            'record']
        message = "Congratulations! You have set up your API server "
        message += "TXT record correctly.<br/><br/>"

    for record in classified_records.get('CORRECT', []):

        message += ("<strong>%s://%s:%s%s</strong><br/><em>%s</em><br/><br/>" %
                    (record['protocol'], record['domain'], record['port'],
                     record['path'], record['record']))

    r = classified_records['CORRECT'][0]

    return (status, briefing, message, {
        'protocol': r['protocol'],
        'domain': r['domain'],
        'port': r['port'],
        'path': r['path']
    })
def testFunction(domain_url):

	(status, briefing, message, output) = domainNameLookup(domain_url)
	if ( status != 0 ):
		return (status, briefing, message, None)

	query_for_TXT_record = None

	try:

		resolver = dns.resolver.Resolver()
		resolver.nameservers = [ getAuthoritativeNameserver(domain_url) ]
		resolver.lifetime = 5
		query_for_TXT_record = resolver.query("_buddycloud-api._tcp."+domain_url, dns.rdatatype.TXT)

	except (NXDOMAIN, NoAnswer):

		return noTXTRecord(domain_url)

	except Exception as e:

		if ( str(e) == "" or str(e) == ("%s. does not exist." % domain_url) ):
			return noTXTRecord(domain_url)

		status = 2
		briefing = "A problem happened while searching for the API server TXT record:"
		briefing += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
		message = "Something odd happened while we were searching for the API server TXT record:"
		message += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
		message += "<br/>This is the exception we got: {"+str(e)+"}"
		message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
		message += "<br/>But it could also be a bug in our Inspector."
		message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so." 
		return (status, briefing, message, None)

	classified_records = {}

	for answer in query_for_TXT_record:

		classified = classifyTXTRecord(str(answer))

		if not classified['type'] in classified_records:
			classified_records[classified['type']] = []
		classified_records[classified['type']].append(classified)

	if ( len(classified_records.get('INFO_MISSING', [])) != 0
	  or len(classified_records.get('MALFORMED', [])) != 0
	  or len(classified_records.get('NOT_HTTPS', [])) != 0 ):

		status = 1
		briefing = "We detected incorrect API server TXT records at domain"
		briefing += " <strong>%s</strong>." % domain_url
		message = "We detected you set up the following incorrect API"
		message += " server TXT records.<br/>"
		message += "You must have just one correct API server SRV record.<br/>"
		message += "These are the SRV records we found and their problems: <br/><br/>"

		for record in classified_records.get('INFO_MISSING', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		for record in classified_records.get('MALFORMED', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		if ( len(classified_records.get('MALFORMED', [])) != 0 ):

			message += "The API server TXT record must always have a <em>version</em>, <em>host</em>,"
			message += " <em>protocol</em>, <em>path</em> and <em>port</em>.<br/>"
			message += "<strong>Each of these properties must be defined within double quotes and separated by spaces only</strong>.<br/>"
			message += "For example, assuming that the server running buddycloud will be named: <strong><em>buddycloud."
			message += domain_url + "</em></strong>," 
			message += "<br/>here you are a TXT record that should work:<br/>"
			message += "<strong>_buddycloud-api._tcp." + domain_url + "\tIN TXT \"v=1.0\" \"host=buddycloud."
			message += domain_url + "\" \"protocol=https\" \"path=/api\" \"port=433\"</strong><br/>"
			message += "<br/>Please not that your API server TXT record won't be correct until it contains proper"
			message += " information regarding the <em>version</em>, <em>host</em>, <em>protocol<em/>, <em>path</em> and <em>port</em>.<br/>"

		for record in classified_records.get('NOT_HTTPS', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		if ( len(classified_records.get('NOT_HTTPS', [])) != 0 ):

			message += "Please ensure your API server will run with HTTPS enabled.<br/>"

		message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
		message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
		return (status, briefing, message, None)

	elif len(classified_records.get('CORRECT', [])) == 0:

		status = 1
		briefing = "No correct API server TXT record found at "
		briefing += "domain <strong>%s</strong>!<br/>" % domain_url
		message = briefing + "<br/>"
		message += "You must have one correct API server SRV record.<br/>"
		message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
		message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
		return (status, briefing, message, None)

	elif len(classified_records.get('CORRECT', [])) > 1:

		status = 1
		briefing = "We found multiple correct API server TXT records!"
		message = briefing + "<br/>"
		message += "But really, you should have just one.<br/>"
		message += "These are the records we found: <br/><br/>"

	else:

		status = 0
		briefing = "API server TXT record found: "
		briefing += "<strong>%s</strong>" % classified_records['CORRECT'][0]['record']
		message = "Congratulations! You have set up your API server "
		message += "TXT record correctly.<br/><br/>"

	for record in classified_records.get('CORRECT', []):

		message += ("<strong>%s://%s:%s%s</strong><br/><em>%s</em><br/><br/>"
				% (record['protocol'],
				   record['domain'],
				   record['port'],
				   record['path'],
				   record['record']))

	r = classified_records['CORRECT'][0]

	return (status, briefing, message, {
			'protocol' : r['protocol'],
			'domain' : r['domain'],
			'port' : r['port'],
			'path' : r['path']
		})
def testFunction(domain_url):

    view = {"domain_url":domain_url}

    if ( domainNameLookup(domain_url)[0] != 0 ):
        view["warning"] = "%s not found!" % (domain_url)
        return warning(view)

    (status, b, m, answers) = xmppServerServiceRecordLookup(domain_url)
    if ( status != 0 ):
        wiew["warning"] = "XMPP Server of domain %s not found!" % (domain_url)
        return warning(view)

    xmpp = sleekxmpp.ClientXMPP("*****@*****.**", "ei3tseq")

    situation = {}

    for answer in answers:

        conn_address = answer["domain"], answer["port"]
        view["xmpp_server"] = conn_address[0]

        if ( not xmpp.connect(conn_address, reattempt=False, use_ssl=False, use_tls=False) ):
             situation[conn_address] = make_output_builder(view,
                 xmpp_connection_problem)
             continue

        xmpp.process(block=False)

        try:
            DISCO_ITEMS_NS = 'http://jabber.org/protocol/disco#items'
            iq = xmpp.make_iq_get(queryxmlns=DISCO_ITEMS_NS,
                ito=domain_url, ifrom=xmpp.boundjid)

            try:
                view["disco_type"] = "disco#items"
                response = iq.send(block=True, timeout=5)
            except Exception as e:
                if ( str(e) != "" ):
                    view["error"] = str(e)
                situation[conn_address] = make_output_builder(view,
                    xmpp_disco_query_send_error)
                continue

            if ( len(response.xml.findall("iq[@type='error']")) != 0 ):
                view["error"] = response.xml.findall("iq[@type='error']")[0]
                situation[conn_address] = make_output_builder(view,
                    xmpp_server_error)
                continue

            its = response.xml.findall(
                "{%s}query/{%s}item" % ((DISCO_ITEMS_NS,)*2))
            for item in its:
                item_jid = item.attrib['jid']

                DISCO_INFO_NS = 'http://jabber.org/protocol/disco#info'
                iq = xmpp.make_iq_get(queryxmlns=DISCO_INFO_NS,
                    ito=item_jid, ifrom=xmpp.boundjid)

                try:
                    view["disco_type"] = "disco#info"
                    response = iq.send(block=True, timeout=5)
                except Exception as e:
                    if ( str(e) != "" ):
                        view["error"] = str(e)
                    situation[conn_address] = make_output_builder(view,
                        xmpp_disco_query_send_error)
                    continue

                if ( len(response.xml.findall("iq[@type='error']")) != 0 ):
                    view["error"] = response.xml.findall("iq[@type='error']")[0]
                    situation[conn_address] = make_output_builder(view,
                        xmpp_server_error)
                    continue

                ids = response.xml.findall(
                    "{%s}query/{%s}identity" % ((DISCO_INFO_NS,)*2))
                for identity in ids:
                    identity_category = identity.attrib['category']
                    identity_type = identity.attrib['type']

                    view["discovery"] = True
                    view["channel_server"] = item_jid
                    if ( identity_category == 'pubsub'
                        and identity_type == 'channels' ):

                        try:
                            resolver = dns.resolver.Resolver()
                            nameserver = getAuthoritativeNameserver(domain_url)
                            resolver.nameservers = [nameserver]
                            resolver.lifetime = 5
                            PTR_name = "_buddycloud-server._tcp." + domain_url
                            answer = resolver.query(PTR_name, dns.rdatatype.PTR)
                        except Exception:
                            pass
                        else:
                            #TODO check if PTR record and DISCO are pointing
                            # to the same place -- they must!
                            view["ptr_record"] = True
                        return is_buddycloud_enabled(view)

            if not conn_address in situation:
                situation[conn_address] = make_output_builder(view,
                    not_buddycloud_enabled)

        finally:
            xmpp.disconnect()

    try:
        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        resolver.nameservers = [nameserver]
        resolver.lifetime = 5
        PTR_name = "_buddycloud-server._tcp." + domain_url
        answer = resolver.query(PTR_name, dns.rdatatype.PTR)
    except (NXDOMAIN, NoAnswer, Timeout):
        pass
    except Exception:
        pass
    else:
        view["ptr_record"] = True
        #view["channel_server"] = answer
        return is_buddycloud_enabled(view)

    if ( len(situation) == 1 ):
       return situation[situation.keys()[0]]() 

    view["xmpp_servers"] = []

    status = 2
    for xmpp_server in situation:
        output = situation[xmpp_server]()
        if ( output[0] == 1 ):
            status = 1
        view["xmpp_servers"].append({
            "name" : "%s through port %s" %(xmpp_server),
            "error" : output[2]
        })

    view["status"] = status

    return multiple_problems(view)
def performSRVLookup(domain_url, srv_name, srv_description, srv_port):

    (status, briefing, message, output) = domainNameLookup(domain_url)
    if status != 0:
        return (status, briefing, message, None)

    answers = []
    query_for_SRV_record = None

    try:

        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        if nameserver:
            resolver.nameservers = [nameserver]
        query_for_SRV_record = resolver.query(srv_name + domain_url, dns.rdatatype.SRV)

    except (NXDOMAIN, NoAnswer, Timeout):

        return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

    except Exception as e:

        if str(e) == "" or str(e) == ("%s. does not exist." % domain_url):
            return no_SRV_record(domain_url, srv_name, srv_description, srv_port)

        status = 2
        briefing = "A problem happened while searching for the %s:" % srv_description
        briefing += " <strong>" + srv_name + domain_url + "</strong>!"
        message = "Something odd happened while we were searching for the %s:" % srv_description
        message += " <strong>" + srv_name + domain_url + "</strong>!"
        message += "<br/>This is the exception we got: {" + str(e) + "}"
        message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
        message += "<br/>But it could also be a bug in our Inspector."
        message += " Let us know at <a href='https://github.com/buddycloud/buddycloud-tests-framework/issues'>our issue tracker</a> if you think so."
        return (status, briefing, message, None)

    for answer in query_for_SRV_record:

        try:

            domain = answer.target.to_text()[:-1]
            port = str(answer.port)

            answers.append({"domain": domain, "port": port, "priority": answer.priority, "weight": answer.weight})

        except Exception:
            continue

    SRV_records = []
    for i in range(len(answers)):
        SRV_record = srv_name + domain_url + " IN SRV "
        SRV_record += answers[i]["port"] + " " + str(answers[i]["domain"])
        SRV_records.append(SRV_record)

    status = 0
    briefing = srv_description + "s found: <strong>" + string.join(SRV_records, " | ") + "</strong>"
    message = "Congratulations! You have set up your SRV records correctly."
    message += "<br/>These were the %ss we found:<br/>" % srv_description
    message += "<strong><br/>" + string.join(SRV_records, "<br/>") + "<br/></strong>"
    message += "<br/>Now, we expect that at least one of them is pointing to an A record"
    message += " that will ultimately guide us to your buddycloud server."
    return (status, briefing, message, answers)
def testFunction(domain_url):

	(status, briefing, message, output) = domainNameLookup(domain_url)
	if ( status != 0 ):
		return (status, briefing, message, None)

	classified_as = checkBuddycloudCompatibility(domain_url)

	description =  descriptions[classified_as] % ("<strong>"+domain_url+"</strong>")
	briefing = description.split("<br/>")[0]
	message = description

	if ( classified_as == "BUDDYCLOUD_ENABLED" ):
		status = 0
	elif ( classified_as == "SERVER_ERROR"
	    or classified_as == "NOT_BUDDYCLOUD_ENABLED" ):
		status = 1

		(sts, brf, mes, out) = buddycloudChannelSRVLookup(domain_url)
		if ( sts != 0 ):

			message += "<br/>You need to set up a SRV record "
			
			(sts2, brf2, mes2, xmpp_server_names) = xmppServerServiceRecordLookup(domain_url)
			if ( sts2 != 0 ):

				message += "similar to the following:"
				message += "<br/><br/><em>(assuming your XMPP server is called"
				message += " <strong>bc.%s</strong>)</em><br/>" % domain_url
				message += "<strong>_xmpp-server._tcp.channels." + domain_url + "."
				message += "\tSRV\t5\t0\t5269\tbc.%s.</strong>" % domain_url

			else:
				message += "exactly like the following:"
				
				if ( len(xmpp_server_names) > 1 ):
					message += " (only one of them)"

				message += "<br/><br/>"

				for xmpp_server in xmpp_server_names:

					xmpp_server = xmpp_server['domain']
					message += "<strong>_xmpp-server._tcp.channels.%s." %domain_url
					message += "\tSRV\t5\t0\t5269\t%s.<br/><br/></strong>" %xmpp_server

		else:

			message += "<br/>Please ensure your buddycloud channel server is running "
			message += "at <strong>%s</strong> and if that's not the case, run:<br/>" % domain_url
			message += "<br/><strong>sudo /etc/init.d/buddycloud-server"
			message += " start</strong><br/><br/>...to start your buddycloud channel server.<br/>"
			message += "See more information at <a href='https://buddycloud.org/wiki/Install"
			message += "#buddycloud_Channel_Server' target='_blank'>"
			message += "https://buddycloud.org/wiki/Install#buddycloud_Channel_Server</a>."
	else:
		status = 2

		(sts, brf, mes, out) = xmppServerConnection(domain_url)
		if ( sts != 0 ):

			status = 1
			message = briefing + "<br/>"
			message += "Reason: <br/>"
			message += mes
			return (status, briefing, message, None)

	return (status, briefing, message, None)
def testFunction(domain_url):

    view = {"domain_url":domain_url}

    if ( domainNameLookup(domain_url)[0] != 0 ):
        view["warning"] = "%s not found!" % (domain_url)
        return warning(view)

    xmpp = create_xmpp_client()
    conn_address = 'crater.buddycloud.org', 5222

    disco_situation = None

    if ( not xmpp.connect(conn_address) ):
        disco_situation = make_output_builder(view, xmpp_connection_problem)

    else:
        xmpp.process(block=False)

        try:
            DISCO_ITEMS_NS = 'http://jabber.org/protocol/disco#items'
            iq = xmpp.make_iq_get(queryxmlns=DISCO_ITEMS_NS,
                ito=domain_url, ifrom=xmpp.boundjid)

            class DiscoItemsFailedException(Exception):
                pass

            try:
                view["disco_type"] = "disco#items"
                response = iq.send(block=True, timeout=config.IQ_TIMEOUT)
            except Exception as e:
                if ( str(e) != "" ):
                    view["error"] = str(e)
                disco_situation = make_output_builder(view,
                    xmpp_disco_query_send_error)
                raise DiscoItemsFailedException()

            if ( len(response.xml.findall("iq[@type='error']")) != 0 ):
                view["error"] = response.xml.findall("iq[@type='error']")[0]
                disco_situation = make_output_builder(view,
                    xmpp_server_error)
                raise DiscoItemsFailedException()

            its = response.xml.findall(
                "{%s}query/{%s}item" % ((DISCO_ITEMS_NS,)*2))
            for item in its:
                item_jid = item.attrib['jid']

                DISCO_INFO_NS = 'http://jabber.org/protocol/disco#info'
                iq = xmpp.make_iq_get(queryxmlns=DISCO_INFO_NS,
                    ito=item_jid, ifrom=xmpp.boundjid)

                try:
                    view["disco_type"] = "disco#info"
                    view["xmpp_server"] = item_jid
                    response = iq.send(block=True, timeout=config.IQ_TIMEOUT)
                except Exception as e:
                    if ( str(e) != "" ):
                        view["error"] = str(e)
                    disco_situation = make_output_builder(view,
                        xmpp_disco_query_send_error)
                    continue

                if ( len(response.xml.findall("iq[@type='error']")) != 0 ):
                    view["error"] = response.xml.findall("iq[@type='error']")[0]
                    disco_situation = make_output_builder(view,
                        xmpp_server_error)
                    continue

                ids = response.xml.findall(
                    "{%s}query/{%s}identity" % ((DISCO_INFO_NS,)*2))
                for identity in ids:
                    identity_category = identity.attrib['category']
                    identity_type = identity.attrib['type']

                    if ( identity_category == 'pubsub'
                        and identity_type == 'channels' ):

                        view["discovery"] = True
                        view["channel_server"] = item_jid

                        try:
                            resolver = dns.resolver.Resolver()
                            nameserver = getAuthoritativeNameserver(domain_url)
                            if ( nameserver ):
                                resolver.nameservers = [nameserver]
                            TXT_name = "_bcloud-server._tcp." + domain_url
                            answer = resolver.query(TXT_name, dns.rdatatype.TXT)
                        except Exception:
                            pass
                        else:
                            view["txt_record"] = True
                            txt_answer = answer[0].to_text()
                            if ( len(txt_answer) == 0 ):
                                txt_answer = "(Blank record)"
                            view["record"] = txt_answer

                            for test in record_well_formedness_tests:
                                if ( not test[0](txt_answer) ):
                                    view["error"] = code("TXT record") + " is malformed! " + test[1]
                                    return record_error(view)

                            answer_jid =  txt_answer[txt_answer.find("server=")+7:txt_answer.find(" ", txt_answer.find("server=")+7)]

                            if ( item_jid != answer_jid ):
                                view["channel_server2"] = answer_jid
                                return buddycloud_enabled_with_conflict(view)

                        return is_buddycloud_enabled(view)

            if disco_situation == None:
                disco_situation = make_output_builder(view,
                    not_buddycloud_enabled)

        except DiscoItemsFailedException:
            pass
        finally:
            xmpp.disconnect()

    try:
        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        if ( nameserver ):
            resolver.nameservers = [nameserver]
        TXT_name = "_bcloud-server._tcp." + domain_url
        answer = resolver.query(TXT_name, dns.rdatatype.TXT)
    except Exception:
        return disco_situation() 
    else:
        view["txt_record"] = True
        txt_answer = answer[0].to_text()
        if ( len(txt_answer) == 0 ):
            txt_answer = "(Blank record)"
        view["record"] = txt_answer

        for test in record_well_formedness_tests:
            if ( not test[0](txt_answer) ):
                view["error"] = code("TXT record") + " is malformed! " + test[1]
                return record_error(view)

        answer_jid =  txt_answer[txt_answer.find("server=")+7:txt_answer.find(" ", txt_answer.find("server=")+7)]

        view["channel_server"] = answer_jid
        return is_buddycloud_enabled(view)
def testFunction(domain_url):

	(status, briefing, message, output) = domainNameLookup(domain_url)
	if ( status != 0 ):
		return (status, briefing, message, None)

	query_for_TXT_record = None

	try:

		resolver = dns.resolver.Resolver()
		resolver.nameservers = [ getAuthoritativeNameserver(domain_url) ]
		resolver.lifetime = 5
		query_for_TXT_record = resolver.query("_buddycloud-api._tcp."+domain_url, dns.rdatatype.TXT)

	except (NXDOMAIN, NoAnswer):

		return noTXTRecord(domain_url)

	except Exception as e:

		if ( str(e) == "" or str(e) == ("%s. does not exist." % domain_url) ):
			return noTXTRecord(domain_url)

		status = 2
		briefing = "A problem happened while searching for the API server TXT record:"
		briefing += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
		message = "Something odd happened while we were searching for the API server TXT record:"
		message += " <strong>_buddycloud-api._tcp." + domain_url + "</strong>!"
		message += "<br/>This is the exception we got: {"+str(e)+"}"
		message += "<br/>It is probably a temporary issue with domain " + domain_url + "."
		message += "<br/>But it could also be a bug in our Inspector."
		message += " Let us know at <email> if you think so." 
		return (status, briefing, message, None)

	classified_records = {}

	for answer in query_for_TXT_record:

		classified = classifyTXTRecord(str(answer))

		if not classified['type'] in classified_records:
			classified_records[classified['type']] = []
		classified_records[classified['type']].append(classified)


	if ( len(classified_records.get('INFO_MISSING', [])) != 0
	  or len(classified_records.get('MALFORMED', [])) != 0
	  or len(classified_records.get('NOT_HTTPS', [])) != 0 ):

		status = 1
		briefing = "We detected incorrect API server TXT records at domain"
		briefing += " <strong>%s</strong>." % domain_url
		message = "We detected you set up the following incorrect API"
		message += " server TXT records.<br/>"
		message += "Really you must have just one correct API server SRV record.<br/>"
		message += "These are the SRV records we found and their problems: <br/><br/>"

		for record in classified_records.get('INFO_MISSING', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		for record in classified_records.get('MALFORMED', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		for record in classified_records.get('NOT_HTTPS', []):

			message += ("<strong>%s</strong><br/><em>%s</em><br/><br/>"
					% (record['description'], record['record']))

		if ( len(classified_records.get('NOT_HTTPS', [])) != 0 ):

			message += "Please ensure your API server will run with HTTPS enabled.<br/>"

		message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
		message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
		return (status, briefing, message, None)

	elif len(classified_records.get('CORRECT', [])) == 0:

		status = 1
		briefing = "No correct API server TXT record found at "
		briefing += "domain <strong>%s</strong>!<br/>" % domain_url
		message = briefing + "<br/>"
		message += "You must have one correct API server SRV record.<br/>"
		message += "See <a href='https://buddycloud.org/wiki/Install#buddycloud_DNS' target='_blank'"
		message += " >https://buddycloud.org/wiki/Install#buddycloud_DNS</a> for more information.<br/>"
		return (status, briefing, message, None)

	elif len(classified_records.get('CORRECT', [])) > 1:

		status = 1
		briefing = "We found multiple correct API server TXT records!"
		message = briefing + "<br/>"
		message += "But really, you should have just one.<br/>"
		message += "These are the records we found: <br/><br/>"

	else:

		status = 0
		briefing = "API server TXT record found: "
		briefing += "<strong>%s</strong>" % classified_records['CORRECT'][0]['record']
		message = "Congratulations! You have set up your API server "
		message += "TXT record correctly.<br/><br/>"

	for record in classified_records.get('CORRECT', []):

		message += ("<strong>%s://%s:%s%s</strong><br/><em>%s</em><br/><br/>"
				% (record['protocol'],
				   record['domain'],
				   record['port'],
				   record['path'],
				   record['record']))

	r = classified_records['CORRECT'][0]

	return (status, briefing, message, {
			'protocol' : r['protocol'],
			'domain' : r['domain'],
			'port' : r['port'],
			'path' : r['path']
		})
def testFunction(domain_url):

    view = {"domain_url": domain_url}

    if (domainNameLookup(domain_url)[0] != 0):
        view["warning"] = "%s not found!" % (domain_url)
        return warning(view)

    (status, b, m, answers) = xmppServerServiceRecordLookup(domain_url)
    if (status != 0):
        wiew["warning"] = "XMPP Server of domain %s not found!" % (domain_url)
        return warning(view)

    xmpp = sleekxmpp.ClientXMPP("*****@*****.**", "ei3tseq")

    situation = {}

    for answer in answers:

        conn_address = answer["domain"], answer["port"]
        view["xmpp_server"] = conn_address[0]

        if (not xmpp.connect(
                conn_address, reattempt=False, use_ssl=False, use_tls=False)):
            situation[conn_address] = make_output_builder(
                view, xmpp_connection_problem)
            continue

        xmpp.process(block=False)

        try:
            DISCO_ITEMS_NS = 'http://jabber.org/protocol/disco#items'
            iq = xmpp.make_iq_get(queryxmlns=DISCO_ITEMS_NS,
                                  ito=domain_url,
                                  ifrom=xmpp.boundjid)

            try:
                view["disco_type"] = "disco#items"
                response = iq.send(block=True, timeout=5)
            except Exception as e:
                if (str(e) != ""):
                    view["error"] = str(e)
                situation[conn_address] = make_output_builder(
                    view, xmpp_disco_query_send_error)
                continue

            if (len(response.xml.findall("iq[@type='error']")) != 0):
                view["error"] = response.xml.findall("iq[@type='error']")[0]
                situation[conn_address] = make_output_builder(
                    view, xmpp_server_error)
                continue

            its = response.xml.findall("{%s}query/{%s}item" %
                                       ((DISCO_ITEMS_NS, ) * 2))
            for item in its:
                item_jid = item.attrib['jid']

                DISCO_INFO_NS = 'http://jabber.org/protocol/disco#info'
                iq = xmpp.make_iq_get(queryxmlns=DISCO_INFO_NS,
                                      ito=item_jid,
                                      ifrom=xmpp.boundjid)

                try:
                    view["disco_type"] = "disco#info"
                    response = iq.send(block=True, timeout=5)
                except Exception as e:
                    if (str(e) != ""):
                        view["error"] = str(e)
                    situation[conn_address] = make_output_builder(
                        view, xmpp_disco_query_send_error)
                    continue

                if (len(response.xml.findall("iq[@type='error']")) != 0):
                    view["error"] = response.xml.findall(
                        "iq[@type='error']")[0]
                    situation[conn_address] = make_output_builder(
                        view, xmpp_server_error)
                    continue

                ids = response.xml.findall("{%s}query/{%s}identity" %
                                           ((DISCO_INFO_NS, ) * 2))
                for identity in ids:
                    identity_category = identity.attrib['category']
                    identity_type = identity.attrib['type']

                    view["discovery"] = True
                    view["channel_server"] = item_jid
                    if (identity_category == 'pubsub'
                            and identity_type == 'channels'):

                        try:
                            resolver = dns.resolver.Resolver()
                            nameserver = getAuthoritativeNameserver(domain_url)
                            resolver.nameservers = [nameserver]
                            resolver.lifetime = 5
                            PTR_name = "_buddycloud-server._tcp." + domain_url
                            answer = resolver.query(PTR_name,
                                                    dns.rdatatype.PTR)
                        except Exception:
                            pass
                        else:
                            #TODO check if PTR record and DISCO are pointing
                            # to the same place -- they must!
                            view["ptr_record"] = True
                        return is_buddycloud_enabled(view)

            if not conn_address in situation:
                situation[conn_address] = make_output_builder(
                    view, not_buddycloud_enabled)

        finally:
            xmpp.disconnect()

    try:
        resolver = dns.resolver.Resolver()
        nameserver = getAuthoritativeNameserver(domain_url)
        resolver.nameservers = [nameserver]
        resolver.lifetime = 5
        PTR_name = "_buddycloud-server._tcp." + domain_url
        answer = resolver.query(PTR_name, dns.rdatatype.PTR)
    except (NXDOMAIN, NoAnswer, Timeout):
        pass
    except Exception:
        pass
    else:
        view["ptr_record"] = True
        #view["channel_server"] = answer
        return is_buddycloud_enabled(view)

    if (len(situation) == 1):
        return situation[situation.keys()[0]]()

    view["xmpp_servers"] = []

    status = 2
    for xmpp_server in situation:
        output = situation[xmpp_server]()
        if (output[0] == 1):
            status = 1
        view["xmpp_servers"].append({
            "name":
            "%s through port %s" % (xmpp_server),
            "error":
            output[2]
        })

    view["status"] = status

    return multiple_problems(view)