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