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 Nping done: 1 IP address pinged in 0.43 seconds 80 81 Example of data returned by this function: 82 83 nping_result: 84 [max_rtt]: 193.010ms 85 [min_rtt]: 193.010ms 86 [avg_rtt]: 193.010ms 87 [raw_packets_sent]: 2 (80B) 88 [rcvd]: 1 (46B) 89 [lost]: 1 (50.00%) 90 [percent_lost]: 50.00 91 92 Description of argument(s): 93 output The output obtained by running an nping 94 command. 95 """ 96 97 lines = output.split("\n") 98 # Obtain only the lines of interest. 99 lines = list(filter(lambda x: re.match(r"(Max rtt|Raw packets)", x), 100 lines)) 101 102 key_value_list = [] 103 for line in lines: 104 key_value_list += line.split("|") 105 nping_result = vf.key_value_list_to_dict(key_value_list) 106 # Extract percent_lost value from lost field. 107 nping_result['percent_lost'] = \ 108 float(nping_result['lost'].split(" ")[-1].strip("()%")) 109 return nping_result 110 111 112openbmc_host = BuiltIn().get_variable_value("${OPENBMC_HOST}") 113 114 115def nping(host=openbmc_host, parse_results=1, **options): 116 r""" 117 Run the nping command and return the results either as a string or as a dictionary. 118 119 Do a 'man nping' for a complete description of the nping utility. 120 121 Note that any valid nping argument may be specified as a function argument. 122 123 Example robot code: 124 125 ${nping_result}= Nping delay=${delay} count=${count} icmp=${None} icmp-type=echo 126 Rprint Vars nping_result 127 128 Resulting output: 129 130 nping_result: 131 [max_rtt]: 0.534ms 132 [min_rtt]: 0.441ms 133 [avg_rtt]: 0.487ms 134 [raw_packets_sent]: 4 (112B) 135 [rcvd]: 2 (92B) 136 [lost]: 2 (50.00%) 137 [percent_lost]: 50.0 138 139 Description of argument(s): 140 host The host name or IP of the target of the 141 nping command. 142 parse_results 1 or True indicates that this function 143 should parse the nping results and return 144 a dictionary rather than the raw nping 145 output. See the parse_nping_output() 146 function for details on the dictionary 147 structure. 148 options Zero or more options accepted by the nping 149 command. Do a 'man nping' for details. 150 """ 151 152 command_string = gc.create_command_string('nping', host, options) 153 rc, output = gc.shell_cmd(command_string, print_output=0, ignore_err=0) 154 if parse_results: 155 return parse_nping_output(output) 156 157 return output 158 159 160def get_channel_config(): 161 r""" 162 Get the channel config data and return as a dictionary. 163 164 Example: 165 channel_config = get_channel_config() 166 print_vars(channel_config) 167 168 channel_config: 169 [0]: 170 [name]: IPMB 171 [is_valid]: True 172 [active_sessions]: 0 173 [channel_info]: 174 [medium_type]: ipmb 175 [protocol_type]: ipmb-1.0 176 [session_supported]: session-less 177 [is_ipmi]: True 178 [1]: 179 [name]: eth0 180 [is_valid]: True 181 [active_sessions]: 0 182 [channel_info]: 183 [medium_type]: other-lan 184 [protocol_type]: ipmb-1.0 185 [session_supported]: multi-session 186 [is_ipmi]: True 187 [2]: 188 [name]: eth1 189 [is_valid]: True 190 [active_sessions]: 0 191 [channel_info]: 192 [medium_type]: lan-802.3 193 [protocol_type]: ipmb-1.0 194 [session_supported]: multi-session 195 [is_ipmi]: True 196 (etc.) 197 """ 198 199 stdout, stderr, rc = bsu.bmc_execute_command("cat /usr/share/ipmi-providers/channel_config.json") 200 return json.loads(stdout) 201 202 203def get_active_channel_config(): 204 r""" 205 Channel configs which medium_type are 'other-lan' or 'lan-802.3' returned by 206 this function. 207 """ 208 209 return vf.filter_struct(get_channel_config(), "[('medium_type', 'other-lan|lan-802.3')]", regex=1) 210 211 212def get_channel_access_config(file_name): 213 r""" 214 Get the channel access config data and return as a dictionary. 215 216 Description of argument: 217 file_name File name for channel access settings (e.g. '/run/ipmi/channel_access_volatile.json', 218 '/var/lib/ipmi/channel_access_nv.json'.). 219 220 Example: 221 222 channel_access_config = get_channel_access_config() 223 print_vars(channel_access_config) 224 225 channel_access_config: 226 [1]: 227 [priv_limit]: priv-admin 228 [per_msg_auth_disabled]: False 229 [access_mode]: always_available 230 [alerting_disabled]: False 231 [user_auth_disabled]: False 232 [2]: 233 [priv_limit]: priv-admin 234 [per_msg_auth_disabled]: False 235 [access_mode]: always_available 236 [alerting_disabled]: False 237 [user_auth_disabled]: False 238 """ 239 stdout, stderr, rc = bsu.bmc_execute_command("cat " + file_name) 240 241 return json.loads(stdout) 242