wadebug/wa_actions/implementations/check_network.py (78 lines of code) (raw):
# Copyright (c) Facebook, Inc. and its affiliates.
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from __future__ import absolute_import, division, print_function, unicode_literals
from enum import Enum
from wadebug import results
from wadebug.wa_actions import docker_utils, network_utils
from wadebug.wa_actions.base import WAAction
class WA_SERVER_TYPE(Enum):
WA_SERVER = "WhatsApp Server"
WA_REPOSITORY = "WhatsApp Docker Repository"
DEFAULT_PORT = 5222
HTTPS_PORT = 443
WHATSAPP_SERVERS = [
("g.whatsapp.net", WA_SERVER_TYPE.WA_SERVER, DEFAULT_PORT, HTTPS_PORT),
("v.whatsapp.net", WA_SERVER_TYPE.WA_SERVER, HTTPS_PORT, DEFAULT_PORT),
("mmg.whatsapp.net", WA_SERVER_TYPE.WA_SERVER, HTTPS_PORT, DEFAULT_PORT),
("graph.facebook.com", WA_SERVER_TYPE.WA_SERVER, HTTPS_PORT, DEFAULT_PORT),
("docker.whatsapp.biz", WA_SERVER_TYPE.WA_REPOSITORY, HTTPS_PORT, DEFAULT_PORT),
("dt.bintray.com", WA_SERVER_TYPE.WA_REPOSITORY, HTTPS_PORT, DEFAULT_PORT),
("akamai.bintray.com", WA_SERVER_TYPE.WA_REPOSITORY, HTTPS_PORT, DEFAULT_PORT),
]
CONNECTION_TIMEOUT = 1
class CheckNetworkAction(WAAction):
user_facing_name = "check_network"
short_description = (
"Test if required hosts can be reached on specific port "
"from the first running coreapp container."
)
@classmethod
def _run(cls, config, *args, **kwargs):
wacore_containers = docker_utils.get_running_wacore_containers()
if not wacore_containers:
return results.Skipped(
cls,
"Network connectivity check was skipped",
"There is no wacore container running. Action skipped.",
"If this is unexpected, check results from other actions to diagnose. "
"If this is expected (e.g.: an HA/MC setup "
"across multiple hosts is under test), no actions are required.",
)
container = wacore_containers[0]
hosts_not_reachable = get_hosts_not_reachable_from_container(
container, WHATSAPP_SERVERS
)
TROUBLESHOOTING_URL = (
"https://developers.facebook.com/docs/whatsapp/network-debugging"
)
if hosts_not_reachable:
error_message = format_error_message(hosts_not_reachable)
return results.Problem(
cls,
"Network connectivity check fails",
error_message,
"Please refer to {} for network requirements details.".format(
TROUBLESHOOTING_URL
),
)
return results.OK(cls)
def get_hosts_not_reachable_from_container(container, hosts):
hosts_not_reachable = []
for host in hosts:
hostname, server_type, primary_port, secondary_port = host
if not is_host_reachable_from_container(
container, hostname, primary_port, secondary_port
):
hosts_not_reachable.append((hostname, server_type))
return hosts_not_reachable
def is_host_reachable_from_container(container, hostname, primary_port, secondary_port):
return network_utils.hostname_reachable_from_container(
container, hostname, primary_port, CONNECTION_TIMEOUT
) or network_utils.hostname_reachable_from_container(
container, hostname, secondary_port, CONNECTION_TIMEOUT
)
def format_error_message(hosts):
message = ""
for hostname, server_type in hosts:
# error message to users doesn't need to differentiate primary/secondary
# ports for different hosts
message += "Cannot reach {} {} on port {} or {}.\n".format(
server_type.value, hostname, DEFAULT_PORT, HTTPS_PORT
)
return message