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