def validate_switch():
    """
    If /rest/v1/switches is cached, perform some validations on it.

    -- verify that the announced interfaces names are case insensitive
    -- verify the names only appear once
    """

    def duplicate_port(entry, name):
        dpid = entry['dpid']

        print 'Warning: switch %s duplicate interface names: %s' % (dpid, name)
        if sdnsh.debug_backtrace:
            for port in entry['ports']:
                if port['name'] == name:
                    print 'SWTICH %s:%s PORT %s' %  (entry, name, port)

    def not_case_sensitive(entry, name):
        dpid = entry['dpid']

        ports = {}
        for port in entry['ports']:
            if port['name'].lower() == name:
                ports[port['name']] = port
            
        print 'Warning: switch %s case insentive interface names: %s' % \
               (dpid, ' - '.join(ports.keys()))
        if sdnsh.debug_backtrace:
            for port in ports:
                print 'SWTICH %s PORT %s' % (dpid, port)

    url = "http://%s/rest/v1/switches" % sdnsh.controller
    entries = url_cache.get_cached_url(url)
    if entries:
        for entry in entries:
            dpid = entry['dpid']

            # verify that the port names are unique even when case
            # sensitive
            all_names = [p['name'] for p in entry['ports']]
            one_case_names = utif.unique_list_from_list([x.lower() for x in all_names])
            if len(all_names) != len(one_case_names):
                # Something is rotten, find out what.
                for (i, port_name) in enumerate(all_names):
                    # use enumerate to drive upper-triangle comparison
                    for other_name in all_names[i+1:]:
                        if port_name == other_name:
                            duplicate_port(entry, port_name)
                        elif port_name.lower() == other_name.lower():
                            not_case_sensitive(entry, port_name)
예제 #2
0
def validate_switch():
    """
    If /rest/v1/switches is cached, perform some validations on it.

    -- verify that the announced interfaces names are case insensitive
    -- verify the names only appear once
    """

    def duplicate_port(entry, name):
        dpid = entry['dpid']

        print 'Warning: switch %s duplicate interface names: %s' % (dpid, name)
        if sdnsh.debug_backtrace:
            for port in entry['ports']:
                if port['name'] == name:
                    print 'SWTICH %s:%s PORT %s' %  (entry, name, port)

    def not_case_sensitive(entry, name):
        dpid = entry['dpid']

        ports = {}
        for port in entry['ports']:
            if port['name'].lower() == name:
                ports[port['name']] = port
            
        print 'Warning: switch %s case insentive interface names: %s' % \
               (dpid, ' - '.join(ports.keys()))
        if sdnsh.debug_backtrace:
            for port in ports:
                print 'SWTICH %s PORT %s' % (dpid, port)

    url = "http://%s/rest/v1/switches" % sdnsh.controller
    entries = url_cache.get_cached_url(url)
    if entries:
        for entry in entries:
            dpid = entry['dpid']

            # verify that the port names are unique even when case
            # sensitive
            all_names = [p['name'] for p in entry['ports']]
            one_case_names = utif.unique_list_from_list([x.lower() for x in all_names])
            if len(all_names) != len(one_case_names):
                # Something is rotten, find out what.
                for (i, port_name) in enumerate(all_names):
                    # use enumerate to drive upper-triangle comparison
                    for other_name in all_names[i+1:]:
                        if port_name == other_name:
                            duplicate_port(entry, port_name)
                        elif port_name.lower() == other_name.lower():
                            not_case_sensitive(entry, port_name)
예제 #3
0
def interface_ranges(names):
    """
    Given a list of interfaces (strings), in any order, with a numeric suffix,
    collect together the prefix components, and create ranges with
    adjacent numeric interfaces, so that a large collection of names
    becomes easier to read.  At the worst, the list will be as
    complicated as the original (which would typically be very unlikely)

    Example: names <- ['Eth0', 'Eth1', 'Eth2',  'Eth4', 'Eth5', 'Eth8']
             result <- ['Eth0-2', 'Eth4-5', 'Eth8']

             names <- ['1','2','3']
             result <- ['1-3']

    """
    # collect the interfaces into dictionaries based on prefixes
    # ahead of groups of digits.
    groups = {}

    def is_digit(c):
        c_ord = ord(c)
        if c_ord >= ord('0') and c_ord <= ord('9'):
            return True
        return False

    for name in names:
        if is_digit(name[-1]):
            for index in range(-2, -len(name) - 1, -1):
                if not is_digit(name[index]):
                    index += 1
                    break
            else:
                index = -len(name)

            prefix = name[:index]
            number = int(name[index:])
            if not prefix in groups:
                groups[prefix] = []
            groups[prefix].append(number)
        else:
            groups[name] = []

    for prefix in groups:
        groups[prefix] = sorted(utif.unique_list_from_list(groups[prefix]))

    ranges = []
    for (prefix, value) in groups.items():
        if len(value) == 0:
            ranges.append(prefix)
        else:
            low = value[0]
            prev = low
            for next in value[1:] + [value[-1] + 2]:  # +[] flushes last item
                if next > prev + 1:
                    if prev == low:
                        ranges.append('%s%s' % (prefix, low))
                    else:
                        ranges.append('%s%s-%s' % (prefix, low, prev))
                    low = next
                prev = next

    return ranges
예제 #4
0
    def format_table(self, data_list, display_format = None, field_ordering="default"):
        """
        Takes in list of dicts and generates nice table, e.g.

        id slice_id MAC Address       ip    Switch ID    
        ------------------------------------------------
        1  1        00:00:00:00:01:03 10013 150861407404
        2  2        00:00:00:00:01:01 10011 150861407404
        3  1        00:00:00:00:02:03 10023 150866955514

        @param data_list - a list of dicts
        @param format describes the format of the output table to display
        @param field_ordering is the field_ordering identifier in the model,
          there can be multiple ("default", "brief", "detailed")
       
        """

        #
        # first, determine a list of fields to be printed, then using that list,
        # determine the fields width of each field, including calling any formatting
        # function, then format the result
        #
        # during the format computation, replace the value with the 'formatted value'
        # to prevent multiple calls to the same formatting funcition
        #
        if not data_list or not type(data_list) == list:
            if type(data_list) == dict and "error_type" in data_list:
                return data_list.get("description", "Internal error")
            return "None."

        format_info = self.table_info.get(display_format, None)

        if self.sdnsh.description:
            if format_info == None:
                print 'format_table: missing format %s' % display_format
            else:
                format_from = format_info.get('self', '')
                print 'format_table: %s %s %d entries' % (
                        display_format, format_from, len(data_list))

        field_widths = {}
        field_headers = {}
        fields_to_print = []

        #
        # do the 'figur'n for which fields will get printed.
        #
        # to determine the length, call the formatting function, and replace the
        # value for that field with the updated value; then 'cypher the length.
        #
        # note that field_widths.keys() are all the possible fields
        # check if the headers makes any field wider and set fields_to_print
        #
        if format_info:
            if 'field-orderings' in format_info:
                fields_to_print = format_info['field-orderings'].get(field_ordering, [])
            if len(fields_to_print) == 0: # either no field_orderings or couldn't find specific
                fields_to_print = format_info['fields'].keys()
            for f in fields_to_print:
                header = self.get_header_for_field(format_info, f)
                field_headers[f] = header
                field_widths[f] = max(len(header), field_widths.get(f, 0))
            # LOOK! not done now... add in extra fields discovered in data_list if desired
            # right now, fields_to_print is a projection on the data
        else:
            # get fields_to_print from the field names in data_list,
            # which is (intended to be) a list of dictionaries
            all_fields = utif.unique_list_from_list(sum([x.keys()
                                                        for x in data_list], []))
            fields_to_print = sorted(all_fields)

        if self.sdnsh.description:
            print 'format_table: field order "%s" fields %s' % \
                   (field_ordering, fields_to_print)

        #
        # generate a fields_to_print ordered list with field_widths for each
        # by going through all data and then using field_ordering if avail.
        #
        row_index = 0
        for row in data_list:
            row_index += 1
            if not 'Idx' in row:
                row['Idx'] = row_index
            for key in fields_to_print:
            #for (k,v) in row.items():
                if format_info:
                    # don't worry about header here - do that soon below
                    info = self.get_field_info(format_info, key)
                    if info and info.get('formatter'):
                        row[key] = str(info['formatter'](row.get(key, ''), row))
                        w = len(row[key])
                    else:
                        w = len(str(row.get(key, '')))
                else:
                    field_headers[key] = self.format_as_header(key)
                    w = max(len(str(row[key])), len(field_headers[key]))
                field_widths[key] = max(w, field_widths.get(key, 0))

        #
        # generate the format_str and header lines based on fields_to_print
        #
        format_str_per_field = []
        for f in fields_to_print:
            format_str_per_field.append("%%(%s)-%ds" % (f, field_widths[f]))

        row_format_str = " ".join(format_str_per_field) + "\n"

        #
        # finally print! only caveat is to handle sparse data with a blank_dict
        # let result be a list, and append new strings to generate the final result,
        # (for better python performance)
        #
        result= []
        result.append(" ".join(format_str_per_field) % field_headers + "\n")
        result.append("|".join(["-"*field_widths[f] for f in fields_to_print]) + "\n") # I <3 python too

        blank_dict = dict([(f,"") for f in fields_to_print])
        for row in data_list:
            result.append(row_format_str % dict(blank_dict, **row))
        
        return ''.join(result)
def interface_ranges(names):
    """
    Given a list of interfaces (strings), in any order, with a numeric suffix,
    collect together the prefix components, and create ranges with
    adjacent numeric interfaces, so that a large collection of names
    becomes easier to read.  At the worst, the list will be as
    complicated as the original (which would typically be very unlikely)

    Example: names <- ['Eth0', 'Eth1', 'Eth2',  'Eth4', 'Eth5', 'Eth8']
             result <- ['Eth0-2', 'Eth4-5', 'Eth8']

             names <- ['1','2','3']
             result <- ['1-3']

    """
    # collect the interfaces into dictionaries based on prefixes
    # ahead of groups of digits.
    groups = {}

    def is_digit(c):
        c_ord = ord(c)
        if c_ord >= ord('0') and c_ord <= ord('9'):
            return True
        return False

    for name in names:
        if is_digit(name[-1]):
            for index in range(-2, -len(name)-1, -1):
                if not is_digit(name[index]):
                    index += 1
                    break;
            else:
                index = -len(name)

            prefix = name[:index]
            number = int(name[index:])
            if not prefix in groups:
                groups[prefix] = []
            groups[prefix].append(number)
        else:
            groups[name] = []

    for prefix in groups:
        groups[prefix] = sorted(utif.unique_list_from_list(groups[prefix]))
    
    ranges = []
    for (prefix, value) in groups.items():
        if len(value) == 0:
            ranges.append(prefix)
        else:
            low = value[0]
            prev = low
            for next in value[1:] + [value[-1] + 2]: # +[] flushes last item
                if next > prev + 1:
                    if prev == low:
                        ranges.append('%s%s' % (prefix, low))
                    else:
                        ranges.append('%s%s-%s' % (prefix, low, prev))
                    low = next
                prev = next
 
    return ranges