blob: b673837719adb62e2bc947ca77fd75627bcfe966 [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright (c) 2015-2017 Nest Labs, Inc.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# @file
# Implements WeavePing class that tests Weave Echo among Weave Nodes.
#
import os
import sys
from happy.ReturnMsg import ReturnMsg
from happy.Utils import *
from happy.HappyNode import HappyNode
from happy.HappyNetwork import HappyNetwork
from plugin.WeaveTest import WeaveTest
options = {"count": None,
"udp": False,
"tcp": False,
"wrmp": False,
"quiet": False,
"no_service": False,
"interval": None,
"tap": None,
"case": False,
"case_shared": False,
"timeout": None,
"client_process_tag": "WEAVE-ECHO-CLIENT",
"server_process_tag": "WEAVE-ECHO-SERVER",
"endpoint": "Echo",
"clients_info": [],
"server_node_id": None,
"strace": True,
"case_cert_path": None,
"case_key_path": None,
"use_persistent_storage": True,
"plaid_server_env": {},
"plaid_client_env": {}
}
def option():
return options.copy()
class WeavePing(HappyNode, HappyNetwork, WeaveTest):
"""
weave-ping [-h --help] [-q --quiet] [-o --origin <NAME>] [-s --server <NAME>]
[-c --count <NUMBER>] [-u --udp] [-t --tcp] [-w --wrmp] [-i --interval <ms>] [-p --tap <TAP_INTERFACE>]
[-C --case] [--case-shared] [-E --case_cert_path <path>] [-T --case_key_path <path>]
command to test weave ping over UDP:
$ weave-ping -o node01 -s node02 -u -i 100 -c 5
command to test weave ping over TCP:
$ weave-ping -o node01 -s node02 -t
command to test weave ping over WRMP:
$ weave-ping -o node01 -s node02 -w
command to test weave ping over WRMP and CASE:
$ weave-ping -o node01 -s node02 -w --case --case_cert_path path --case_key_path path
command to test weave ping over WRMP with shared CASE session to the Nest Core Router:
$ weave-ping -o node01 -s node02 -w --case-shared --case_cert_path path --case_key_path path
return:
0-100 percentage of the lost packets
"""
def __init__(self, opts = options):
HappyNode.__init__(self)
HappyNetwork.__init__(self)
WeaveTest.__init__(self)
self.__dict__.update(opts)
def __pre_check(self):
# clear network info
self.clients_info = []
# Make sure that fabric was created
if self.getFabricId() == None:
emsg = "Weave Fabric has not been created yet."
self.logger.error("[localhost] WeavePing: %s" % (emsg))
sys.exit(1)
if self.count != None and self.count.isdigit():
self.count = int(float(self.count))
else:
self.count = 1
for client in self.clients:
client_node_id = None
# Check if Weave Ping client node is given.
if client == None:
emsg = "Missing name or address of the Weave Ping client node."
self.logger.error("[localhost] WeavePing: %s" % (emsg))
sys.exit(1)
# Check if Weave Ping client node exists.
if self._nodeExists(client):
client_node_id = client
# Check if client is provided in a form of IP address
if self.isIpAddress(client):
client_node_id = self.getNodeIdFromAddress(client)
if client_node_id == None:
emsg = "Unknown identity of the client node."
self.logger.error("[localhost] WeavePing: %s" % (emsg))
sys.exit(1)
if self.getNodeType(client_node_id) == "service":
client_ip = self.getServiceWeaveIPAddress(self.endpoint, client_node_id)
client_weave_id = self.getServiceWeaveID(self.endpoint, client_node_id)
else:
client_ip = self.getNodeWeaveIPAddress(client_node_id)
client_weave_id = self.getWeaveNodeID(client_node_id)
if client_ip == None:
emsg = "Could not find IP address of the client node."
self.logger.error("[localhost] WeavePing: %s" % (emsg))
sys.exit(1)
if client_weave_id == None:
emsg = "Could not find Weave node ID of the client node."
self.logger.error("[localhost] WeavePing: %s" % (emsg))
sys.exit(1)
self.clients_info.append({'client': client, 'client_node_id': client_node_id, 'client_ip': client_ip,
'client_weave_id': client_weave_id, 'client_process_tag': client + "_" + self.client_process_tag + client})
# Check if Weave Ping server node is given.
if self.server == None:
emsg = "Missing name or address of the Weave Ping server node."
self.logger.error("[localhost] WeavePing: %s" % (emsg))
sys.exit(1)
# Check if Weave Ping server node exists.
if self._nodeExists(self.server):
self.server_node_id = self.server
# Check if server is provided in a form of IP address
if self.isIpAddress(self.server):
self.no_service = True
self.server_ip = self.server
self.server_weave_id = self.IPv6toWeaveId(self.server)
elif self.isDomainName(self.server) or self.server == "service":
self.no_service = True
self.server_ip = self.getServiceWeaveIPAddress(self.endpoint)
self.server_weave_id = self.IPv6toWeaveId(self.server_ip)
else:
# Check if server is a true clound service instance
if self.getNodeType(self.server) == self.node_type_service:
self.no_service = True
if not self.no_service and self.server_node_id == None:
emsg = "Unknown identity of the server node."
self.logger.error("[localhost] WeavePing: %s" % (emsg))
sys.exit(1)
if self.getNodeType(self.server_node_id) == "service":
self.server_ip = self.getServiceWeaveIPAddress(self.endpoint, self.server_node_id)
self.server_weave_id = self.getServiceWeaveID(self.endpoint, self.server_node_id)
else:
if not self.no_service:
self.server_ip = self.getNodeWeaveIPAddress(self.server_node_id)
self.server_weave_id = self.getWeaveNodeID(self.server_node_id)
# Check if all unknowns were found
if self.server_ip == None:
emsg = "Could not find IP address of the server node."
self.logger.error("[localhost] WeavePing: %s" % (emsg))
sys.exit(1)
if not self.no_service and self.server_weave_id == None:
emsg = "Could not find Weave node ID of the server node."
self.logger.error("[localhost] WeavePing: %s" % (emsg))
sys.exit(1)
def __process_results(self, client_info, output):
# search for '%' e.g. 1/1(100.00%)
loss_percentage = None
for line in output.split("\n"):
if not "%" in line:
continue
for token in line.split():
if "%" in token:
loss_percentage = token.strip().split("(")[1]
loss_percentage = loss_percentage.translate(None, "()%")
if loss_percentage == None:
# hmmm, we haven't found our line
loss_percentage = 100
else:
loss_percentage = float(loss_percentage)
loss_percentage = 100 - loss_percentage
if self.quiet == False:
print "weave-ping from node %s (%s) to node %s (%s) : " % \
(client_info['client_node_id'], client_info['client_ip'],
self.server_node_id, self.server_ip),
if loss_percentage == 0:
print hgreen("%f%% packet loss" % (loss_percentage))
else:
print hred("%f%% packet loss" % (loss_percentage))
return loss_percentage # indicate the loss for each client
def __start_server_side(self):
if self.no_service:
return
cmd = self.getWeavePingPath()
if not cmd:
return
if self.tcp:
cmd += " --tcp"
elif self.udp:
# default is UDP
cmd += " --udp"
elif self.wrmp:
cmd += " --wrmp"
if self.tap:
cmd += " --interface " + self.tap
self.start_simple_weave_server(cmd, self.server_ip,
self.server_node_id, self.server_process_tag, use_persistent_storage = self.use_persistent_storage, env=self.plaid_server_env)
def __start_client_side(self, client_info):
cmd = self.getWeavePingPath()
if not cmd:
return
if self.tcp:
cmd += " --tcp"
elif self.udp:
# default is UDP
cmd += " --udp"
elif self.wrmp:
cmd += " --wrmp"
if self.interval != None:
cmd += " --interval " + self.interval
cmd += " --count " + str(self.count)
if self.tap:
cmd += " --interface " + self.tap
if self.case:
if self.case_shared:
cmd += " --case-shared"
else:
cmd += " --case"
if not self.case_cert_path == 'default':
self.cert_file = self.case_cert_path if self.case_cert_path else os.path.join(self.main_conf['log_directory'], client_info["client_weave_id"].upper() + '-cert.weave-b64')
self.key_file = self.case_key_path if self.case_key_path else os.path.join(self.main_conf['log_directory'], client_info["client_weave_id"].upper() + '-key.weave-b64')
cmd += ' --node-cert ' + self.cert_file + ' --node-key ' + self.key_file
self.start_simple_weave_client(cmd, client_info['client_ip'],
self.server_ip, self.server_weave_id,
client_info['client_node_id'], client_info['client_process_tag'], use_persistent_storage=self.use_persistent_storage, env=self.plaid_client_env)
def __wait_for_client(self, client_info):
self.wait_for_test_to_end(client_info["client_node_id"], client_info["client_process_tag"], timeout=self.timeout)
def __stop_server_side(self):
if self.no_service:
return
self.stop_weave_process(self.server_node_id, self.server_process_tag)
def run(self):
all_data = []
self.logger.debug("[localhost] WeavePing: Run.")
self.__pre_check()
self.__start_server_side()
emsg = "WeavePing %s should be running." % (self.server_process_tag)
self.logger.debug("[%s] WeavePing: %s" % (self.server_node_id, emsg))
for client_info in self.clients_info:
self.__start_client_side(client_info)
for client_info in self.clients_info:
self.__wait_for_client(client_info)
for client_info in self.clients_info:
client_output_value, client_output_data = \
self.get_test_output(client_info['client_node_id'], client_info['client_process_tag'], True)
client_strace_value, client_strace_data = \
self.get_test_strace(client_info['client_node_id'], client_info['client_process_tag'], True)
if self.no_service:
server_output_data = ""
server_strace_data = ""
else:
self.__stop_server_side()
server_output_value, server_output_data = \
self.get_test_output(self.server_node_id, self.server_process_tag, True)
server_strace_value, server_strace_data = \
self.get_test_strace(self.server_node_id, self.server_process_tag, True)
loss_percentage = self.__process_results(client_info, client_output_data)
data = {}
data.update(client_info)
data["client_output"] = client_output_data
data["server_output"] = server_output_data
if self.strace:
data["client_strace"] = client_strace_data
data["server_strace"] = server_strace_data
all_data.append(data)
self.logger.debug("[localhost] WeavePing: Done.")
return ReturnMsg(loss_percentage, all_data)