def _make_display_device_table(builder): ip_width = 10 port_width = 4 rep_ip_width = 14 rep_port_width = 4 ip_ipv6 = rep_ipv6 = False for dev in builder._iter_devs(): if is_valid_ipv6(dev['ip']): ip_ipv6 = True if is_valid_ipv6(dev['replication_ip']): rep_ipv6 = True ip_width = max(len(dev['ip']), ip_width) rep_ip_width = max(len(dev['replication_ip']), rep_ip_width) port_width = max(len(str(dev['port'])), port_width) rep_port_width = max(len(str(dev['replication_port'])), rep_port_width) if ip_ipv6: ip_width += 2 if rep_ipv6: rep_ip_width += 2 header_line = ('Devices:%5s %6s %4s %' + str(ip_width) + 's:%-' + str(port_width) + 's %' + str(rep_ip_width) + 's:%-' + str(rep_port_width) + 's %5s %6s %10s %7s %5s %s') % ( 'id', 'region', 'zone', 'ip address', 'port', 'replication ip', 'port', 'name', 'weight', 'partitions', 'balance', 'flags', 'meta') def print_dev_f(dev, balance_per_dev=0.00, flags=''): def get_formated_ip(key): value = dev[key] if ':' in value: value = '[%s]' % value return value dev_ip = get_formated_ip('ip') dev_replication_ip = get_formated_ip('replication_ip') format_string = ''.join(['%13d %6d %4d ', '%', str(ip_width), 's:%-', str(port_width), 'd ', '%', str(rep_ip_width), 's', ':%-', str(rep_port_width), 'd %5s %6.02f' ' %10s %7.02f %5s %s']) args = (dev['id'], dev['region'], dev['zone'], dev_ip, dev['port'], dev_replication_ip, dev['replication_port'], dev['device'], dev['weight'], dev['parts'], balance_per_dev, flags, dev['meta']) print(format_string % args) return header_line, print_dev_f
def curl_head_command(ip, port, device, part, target, policy_index): """ Provide a string that is a well formatted curl command to HEAD an object on a storage node. :param ip: the ip of the node :param port: the port of the node :param device: the device of the node :param target: the path of the target resource :param policy_index: the policy_index of the target resource (can be None) :returns: a string, a well formatted curl command """ if is_valid_ipv6(ip): formatted_ip = '[%s]' % ip else: formatted_ip = ip cmd = 'curl -g -I -XHEAD "http://%s:%s/%s/%s/%s"' % ( formatted_ip, port, device, part, urllib.parse.quote(target)) if policy_index is not None: cmd += ' -H "%s: %s"' % ('X-Backend-Storage-Policy-Index', policy_index) cmd += ' --path-as-is' return cmd
def validate_and_normalize_ip(ip): """ Return normalized ip if the ip is a valid ip. Otherwise raise ValueError Exception. The hostname is normalized to all lower case. IPv6-addresses are converted to lowercase and fully expanded. """ # first convert to lower case new_ip = ip.lower() if is_valid_ipv4(new_ip): return new_ip elif is_valid_ipv6(new_ip): return expand_ipv6(new_ip) else: raise ValueError('Invalid ip %s' % ip)
def validate_and_normalize_address(address): """ Return normalized address if the address is a valid ip or hostname. Otherwise raise ValueError Exception. The hostname is normalized to all lower case. IPv6-addresses are converted to lowercase and fully expanded. RFC1123 2.1 Host Names and Nubmers DISCUSSION This last requirement is not intended to specify the complete syntactic form for entering a dotted-decimal host number; that is considered to be a user-interface issue. For example, a dotted-decimal number must be enclosed within "[ ]" brackets for SMTP mail (see Section 5.2.17). This notation could be made universal within a host system, simplifying the syntactic checking for a dotted-decimal number. If a dotted-decimal number can be entered without such identifying delimiters, then a full syntactic check must be made, because a segment of a host domain name is now allowed to begin with a digit and could legally be entirely numeric (see Section 6.1.2.4). However, a valid host name can never have the dotted-decimal form #.#.#.#, since at least the highest-level component label will be alphabetic. """ new_address = address.lstrip('[').rstrip(']') if address.startswith('[') and address.endswith(']'): return validate_and_normalize_ip(new_address) new_address = new_address.lower() if is_valid_ipv4(new_address): return new_address elif is_valid_ipv6(new_address): return expand_ipv6(new_address) elif is_valid_hostname(new_address): return new_address else: raise ValueError('Invalid address %s' % address)
def curl_head_command(ip, port, device, part, target, policy_index): """ Provide a string that is a well formatted curl command to HEAD an object on a storage node. :param ip: the ip of the node :param port: the port of the node :param device: the device of the node :param target: the path of the target resource :param policy_index: the policy_index of the target resource (can be None) :returns: a string, a well formatted curl command """ if is_valid_ipv6(ip): formatted_ip = '[%s]' % ip else: formatted_ip = ip cmd = 'curl -g -I -XHEAD "http://%s:%s/%s/%s/%s"' % ( formatted_ip, port, device, part, urllib.parse.quote(target)) if policy_index is not None: cmd += ' -H "%s: %s"' % ('X-Backend-Storage-Policy-Index', policy_index) return cmd
def is_local_device(my_ips, my_port, dev_ip, dev_port): """ Return True if the provided dev_ip and dev_port are among the IP addresses specified in my_ips and my_port respectively. To support accurate locality determination in the server-per-port deployment, when my_port is None, only IP addresses are used for determining locality (dev_port is ignored). If dev_ip is a hostname then it is first translated to an IP address before checking it against my_ips. """ candidate_ips = [] if not is_valid_ip(dev_ip) and is_valid_hostname(dev_ip): try: # get the ip for this host; use getaddrinfo so that # it works for both ipv4 and ipv6 addresses addrinfo = socket.getaddrinfo(dev_ip, dev_port) for addr in addrinfo: family = addr[0] dev_ip = addr[4][0] # get the ip-address if family == socket.AF_INET6: dev_ip = expand_ipv6(dev_ip) candidate_ips.append(dev_ip) except socket.gaierror: return False else: if is_valid_ipv6(dev_ip): dev_ip = expand_ipv6(dev_ip) candidate_ips = [dev_ip] for dev_ip in candidate_ips: if dev_ip in my_ips and (my_port is None or dev_port == my_port): return True return False