1#!/usr/bin/env python3 2 3r""" 4Network generic functions. 5 6""" 7 8import gen_print as gp 9import gen_cmd as gc 10import gen_misc as gm 11import var_funcs as vf 12import collections 13import re 14import ipaddress 15import subprocess 16import socket 17from robot.libraries.BuiltIn import BuiltIn 18import json 19import bmc_ssh_utils as bsu 20 21ip_regex = r"\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}" 22 23 24def get_running_system_ip(): 25 r""" 26 Get the IP address of server from which robot code is running. 27 28 """ 29 30 ip_list = list() 31 stdout = subprocess.check_output(['hostname', '--all-fqdns'], shell=True) 32 host_fqdns = stdout.decode("utf-8").strip() 33 ip_address = socket.gethostbyname(str(host_fqdns)) 34 ip_list.append(ip_address) 35 36 return ip_list 37 38 39def netmask_prefix_length(netmask): 40 r""" 41 Return the netmask prefix length. 42 43 Description of argument(s): 44 netmask Netmask value (e.g. "255.255.0.0", "255.255.255.0", 45 "255.252.0.0", etc.). 46 """ 47 48 # IP address netmask format: '0.0.0.0/255.255.252.0' 49 return ipaddress.ip_network('0.0.0.0/' + netmask).prefixlen 50 51 52def get_netmask_address(prefix_len): 53 r""" 54 Return the netmask address. 55 56 Description of argument(s): 57 prefix_len Prefix length value (e.g. "24", "23", "22", etc.). 58 """ 59 60 # IP address netmask format: '0.0.0.0/24' 61 return ipaddress.ip_network('0.0.0.0/' + prefix_len).netmask 62 63 64def parse_nping_output(output): 65 r""" 66 Parse the output from the nping command and return as a dictionary. 67 68 Example of output value: 69 70 Starting Nping 0.6.47 ( http://nmap.org/nping ) at 2019-08-07 22:05 IST 71 SENT (0.0181s) TCP Source IP:37577 > 72 Destination IP:80 S ttl=64 id=39113 iplen=40 seq=629782493 win=1480 73 SENT (0.2189s) TCP Source IP:37577 > 74 Destination IP:80 S ttl=64 id=39113 iplen=40 seq=629782493 win=1480 75 RCVD (0.4120s) TCP Destination IP:80 > 76 Source IP:37577 SA ttl=49 id=0 iplen=44 seq=1078301364 win=5840 <mss 1380> 77 Max rtt: 193.010ms | Min rtt: 193.010ms | Avg rtt: 193.010ms 78 Raw packets sent: 2 (80B) | Rcvd: 1 (46B) | Lost: 1 (50.00%) 79 TCP connection attempts: 5 | Successful connections: 5 | Failed: 0 (0.00%) 80 Nping done: 1 IP address pinged in 0.43 seconds 81 82 Example of data returned by this function: 83 84 nping_result: 85 [max_rtt]: 193.010ms 86 [min_rtt]: 193.010ms 87 [avg_rtt]: 193.010ms 88 [raw_packets_sent]: 2 (80B) 89 [rcvd]: 1 (46B) 90 [lost]: 1 (50.00%) 91 [percent_lost]: 50.00 92 [tcp_connection_attempts]: 5 93 [successful_connections]: 5 94 [failed]: 0 (0.00%) 95 [percent_failed]: 0.00 96 97 Description of argument(s): 98 output The output obtained by running an nping 99 command. 100 """ 101 102 lines = output.split("\n") 103 # Obtain only the lines of interest. 104 lines = list(filter(lambda x: re.match(r"(Max rtt|Raw packets|TCP connection)", x), 105 lines)) 106 107 key_value_list = [] 108 for line in lines: 109 key_value_list += line.split("|") 110 nping_result = vf.key_value_list_to_dict(key_value_list) 111 # Extract percent_lost/percent_failed value from lost/failed field. 112 if 'lost' in nping_result: 113 nping_result['percent_lost'] = \ 114 float(nping_result['lost'].split(" ")[-1].strip("()%")) 115 else: 116 nping_result['percent_failed'] = \ 117 float(nping_result['failed'].split(" ")[-1].strip("()%")) 118 return nping_result 119 120 121openbmc_host = BuiltIn().get_variable_value("${OPENBMC_HOST}") 122 123 124def nping(host=openbmc_host, parse_results=1, **options): 125 r""" 126 Run the nping command and return the results either as a string or as a dictionary. 127 128 Do a 'man nping' for a complete description of the nping utility. 129 130 Note that any valid nping argument may be specified as a function argument. 131 132 Example robot code: 133 134 ${nping_result}= Nping delay=${delay} count=${count} icmp=${None} icmp-type=echo 135 Rprint Vars nping_result 136 137 Resulting output: 138 139 nping_result: 140 [max_rtt]: 0.534ms 141 [min_rtt]: 0.441ms 142 [avg_rtt]: 0.487ms 143 [raw_packets_sent]: 4 (112B) 144 [rcvd]: 2 (92B) 145 [lost]: 2 (50.00%) 146 [percent_lost]: 50.0 147 148 Description of argument(s): 149 host The host name or IP of the target of the 150 nping command. 151 parse_results 1 or True indicates that this function 152 should parse the nping results and return 153 a dictionary rather than the raw nping 154 output. See the parse_nping_output() 155 function for details on the dictionary 156 structure. 157 options Zero or more options accepted by the nping 158 command. Do a 'man nping' for details. 159 """ 160 161 command_string = gc.create_command_string('nping', host, options) 162 rc, output = gc.shell_cmd(command_string, print_output=0, ignore_err=0) 163 if parse_results: 164 return parse_nping_output(output) 165 166 return output 167 168 169def get_channel_config(): 170 r""" 171 Get the channel config data and return as a dictionary. 172 173 Example: 174 channel_config = get_channel_config() 175 print_vars(channel_config) 176 177 channel_config: 178 [0]: 179 [name]: IPMB 180 [is_valid]: True 181 [active_sessions]: 0 182 [channel_info]: 183 [medium_type]: ipmb 184 [protocol_type]: ipmb-1.0 185 [session_supported]: session-less 186 [is_ipmi]: True 187 [1]: 188 [name]: eth0 189 [is_valid]: True 190 [active_sessions]: 0 191 [channel_info]: 192 [medium_type]: other-lan 193 [protocol_type]: ipmb-1.0 194 [session_supported]: multi-session 195 [is_ipmi]: True 196 [2]: 197 [name]: eth1 198 [is_valid]: True 199 [active_sessions]: 0 200 [channel_info]: 201 [medium_type]: lan-802.3 202 [protocol_type]: ipmb-1.0 203 [session_supported]: multi-session 204 [is_ipmi]: True 205 (etc.) 206 """ 207 208 stdout, stderr, rc = bsu.bmc_execute_command("cat /usr/share/ipmi-providers/channel_config.json") 209 return json.loads(stdout) 210 211 212def get_active_channel_config(): 213 r""" 214 Channel configs which medium_type are 'other-lan' or 'lan-802.3' returned by 215 this function. 216 """ 217 218 return vf.filter_struct(get_channel_config(), "[('medium_type', 'other-lan|lan-802.3')]", regex=1) 219 220 221def get_channel_access_config(file_name): 222 r""" 223 Get the channel access config data and return as a dictionary. 224 225 Description of argument: 226 file_name File name for channel access settings (e.g. '/run/ipmi/channel_access_volatile.json', 227 '/var/lib/ipmi/channel_access_nv.json'.). 228 229 Example: 230 231 channel_access_config = get_channel_access_config() 232 print_vars(channel_access_config) 233 234 channel_access_config: 235 [1]: 236 [priv_limit]: priv-admin 237 [per_msg_auth_disabled]: False 238 [access_mode]: always_available 239 [alerting_disabled]: False 240 [user_auth_disabled]: False 241 [2]: 242 [priv_limit]: priv-admin 243 [per_msg_auth_disabled]: False 244 [access_mode]: always_available 245 [alerting_disabled]: False 246 [user_auth_disabled]: False 247 """ 248 stdout, stderr, rc = bsu.bmc_execute_command("cat " + file_name) 249 250 return json.loads(stdout) 251