Exemplo n.º 1
0
def test_allocate_non_percent():
    device_count = 100
    weight_list = [2, 4]
    device_list = weight.allocate_weighted_list(device_count, weight_list,
                                                percentage=False)
    assert device_list == [33, 67]

    device_count = 100
    weight_list = [4, 4, 4]
    device_list = weight.allocate_weighted_list(device_count, weight_list,
                                                percentage=False)
    assert device_list == [34, 33, 33]
Exemplo n.º 2
0
def test_allocate_exceed():
    device_count = 99
    percentage_list = [1, 98, 2]
    fail_msg = ''
    try:
        weight.allocate_weighted_list(device_count, percentage_list)
    except:
        exc_info = sys.exc_info()
        fail_list = traceback.format_exception_only(exc_info[0],
                                                    exc_info[1])
        fail_msg = fail_list[0] if len(fail_list) == 1 else '\n'.join(fail_list)
    if fail_msg == '':
        raise AssertionError('function did not fail as expected')
    if 'weights exceeds 100' not in fail_msg:
        raise AssertionError('function failed with unexpected exception: "' +
                             fail_msg + '"')
Exemplo n.º 3
0
def test_allocate_count():
    device_count = 99
    percentage_list = [1, 98, 1]
    device_list = weight.allocate_weighted_list(device_count, percentage_list)
    assert device_list == [1, 97, 1]

    device_count = 11
    percentage_list = [25, 75]
    device_list = weight.allocate_weighted_list(device_count, percentage_list)
    assert device_list == [3, 8]

    device_count = 99
    percentage_list = [25, 50, 25]
    device_list = weight.allocate_weighted_list(device_count, percentage_list)
    assert device_list == [25, 49, 25]

    device_count = 99
    percentage_list = [98, 1, 1]
    device_list = weight.allocate_weighted_list(device_count, percentage_list)
    assert device_list == [97, 1, 1]

    device_count = 100
    percentage_list = [95, 1, 1, 1, 2]
    device_list = weight.allocate_weighted_list(device_count, percentage_list)
    assert device_list == [95, 1, 1, 1, 2]

    device_count = 99
    percentage_list = [1, 1, 95, 1, 2]
    device_list = weight.allocate_weighted_list(device_count, percentage_list)
    assert device_list == [1, 1, 94, 1, 2]

    device_count = 100
    percentage_list = [.1, .2, 99, .3, .4]
    device_list = weight.allocate_weighted_list(device_count, percentage_list)
    assert device_list == [0, 0, 99, 0, 1]

    device_count = 100
    percentage_list = [.1, .1, 99.5, .1, .2]
    device_list = weight.allocate_weighted_list(device_count, percentage_list)
    assert device_list == [0, 0, 100, 0, 0]

    device_count = 100
    percentage_list = [10, 20.5, 30.3, 38.2]
    device_list = weight.allocate_weighted_list(device_count, percentage_list)
    # Note that the sum for this is 99, so we have only 1 extra, originally it
    # was [10, 21, 31, 38]
    assert device_list == [10, 21, 30, 38]
def run(StmTrafficMix, TagName, Load, LoadUnit):
    plLogger = PLLogger.GetLogger("AllocateTrafficMixLoad1Command")
    obj_list = CCommandEx.ProcessInputHandleVec('StmTrafficMix', [StmTrafficMix])
    if TagName:
        obj_list = obj_list + tag_utils.get_tagged_objects_from_string_names([TagName])
    if len(obj_list) == 0:
        plLogger.LogError("Neither StmTrafficMix nor TagName specified " +
                          "a valid StmTrafficMix Object")
        return False
    obj_dict = {obj.GetObjectHandle(): obj for obj in obj_list}
    for traf_mix in obj_dict.values():
        tmi = traf_mix.Get('MixInfo')
        if tmi == '':
            plLogger.LogError("MixInfo is empty")
            return False
        mix_elem = etree.fromstring(tmi)
        val = mix_elem.get('WeightList')
        weight_list = [float(x) for x in val.split()]
        tmpl_list = traf_mix.GetObjects('StmTemplateConfig')
        if len(weight_list) != len(tmpl_list):
            plLogger.LogError("Size of weight list does not match " +
                              "number of templates")
            return False
        # Fractions are not supported only for these settings
        allow = (LoadUnit not in ['FRAMES_PER_SECOND', 'INTER_BURST_GAP'])
        load_list = weight.allocate_weighted_list(Load, weight_list,
                                                  allow_fraction=allow)
        for load, tmpl in zip(load_list, tmpl_list):
            allocate_weighted_load(load, tmpl, LoadUnit)
            config_generator(tmpl, LoadUnit)
        # After finishing, set the appropriate fields in the mix
        mix_elem.set('Load', str(Load))
        mix_elem.set('LoadUnit', LoadUnit)
        mix_elem.set('LoadDist', ' '.join([str(x) for x in load_list]))
        traf_mix.Set('MixInfo', etree.tostring(mix_elem))
    return True
def run(StmTemplateMix, TagName, DeviceCount, PortGroupTagList):
    # MixInfo JSON:
    # {
    #     "deviceCount": 100,
    #     "components": [
    #         {
    #             "weight": 10.0,
    #             "devicesPerBlock": 0,
    #             "baseTemplateFile": "IPv4_NoVlan.xml"
    #             "appliedValue": 0,
    #         }
    #     ]
    # }
    plLogger = PLLogger.GetLogger("methodology")
    ctor = CScriptableCreator()
    obj_list = []
    this_cmd = get_this_cmd()
    if StmTemplateMix:
        obj_list = CCommandEx.ProcessInputHandleVec("StmTemplateMix",
                                                    [StmTemplateMix])
    if TagName:
        obj_list = obj_list + \
            tag_utils.get_tagged_objects_from_string_names(
                [TagName])
    if len(obj_list) == 0:
        err_str = "Neither StmTemplateMix nor TagName specified a " + \
            "valid StmTemplateMix object."
        plLogger.LogError(err_str)
        this_cmd.Set("Status", err_str)
        return False

    if DeviceCount < 1:
        err_str = "DeviceCount must be at least 1."
        plLogger.LogError(err_str)
        this_cmd.Set("Status", err_str)
        return False

    # Process obj_list to remove duplicates by using
    # a dictionary indexed on object handle.
    obj_dict = {obj.GetObjectHandle(): obj for obj in obj_list}
    for mix in obj_dict.values():
        str_mix_info = mix.Get("MixInfo")
        if str_mix_info == "":
            err_str = "MixInfo is empty"
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        '''
        # Validate the MixInfo
        # mi_schema = CreateProtoMixCmd_get_mix_info_schema()
        # res = json_utils.validate_json(str_mix_info, mi_schema)
        # if res != "":
            # err_str = res
            # plLogger.LogError(err_str)
            # this_cmd.Set("Status", err_str)
            # return False
        '''

        plLogger.LogDebug("string mix_info: " + str_mix_info)
        mix_info = json_utils.load_json(str_mix_info)
        plLogger.LogDebug("mix_info: " + str(mix_info))

        if "components" not in mix_info.keys():
            err_str = "components is missing in MixInfo for " + \
                              "StmProtocolMix: " + mix.Get("Name")
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        component_list = mix_info["components"]
        if len(component_list) == 0:
            err_str = "Could not find any objects in components in " + \
                              "the MixInfo in " + mix.Get("Name")
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        template_list = mix.GetObjects("StmTemplateConfig")
        if len(component_list) != len(template_list):
            err_str = "Number of component elements in the " + \
                              "MixInfo for " + mix.Get("Name") + \
                              " does not match " + \
                              "number of StmTemplateConfig objects."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Check the DeviceCount
        if DeviceCount < len(component_list):
            err_str = "Invalid DeviceCount " + str(DeviceCount) + \
                              " specified.  DeviceCount must be at " + \
                              " least " + str(len(component_list))
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Process the weight parameter
        static_list = []
        percent_list = []
        use_percent_list = []

        for component in component_list:
            if "weight" not in component.keys():
                err_str = "Missing required weight parameter in " + \
                                  "Component in StmProtocolMix: " + \
                                  mix.Get("Name")
                plLogger.LogError(err_str)
                this_cmd.Set("Status", err_str)
                return False
            weight = component["weight"]
            is_percent, act_val, err_str = weight_ops.parse_weight_string(
                weight)
            if err_str != "":
                plLogger.LogError(err_str)
                this_cmd.Set("Status", err_str)
                return False

            if is_percent:
                static_list.append(0)
                percent_list.append(act_val)
            else:
                static_list.append(act_val)
                percent_list.append(0)
            use_percent_list.append(is_percent)

        total_static_count = sum(static_list)
        total_percent = sum(percent_list)

        plLogger.LogDebug("total_static_count: " + str(total_static_count))
        plLogger.LogDebug("total_percent: " + str(total_percent))

        # Don't allow the aggregate of static counts to exceed the
        # configured total device count...
        if total_static_count > DeviceCount:
            err_str = "Sum total of the static counts (" + \
                str(int(total_static_count)) + ") exceeds the total " + \
                "configured DeviceCount (" + str(DeviceCount) + ")."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Don't allow the total percent to exceed 100%
        if total_percent > 100:
            err_str = "Sum total of the weights defined as percentages (" + \
                str(total_percent) + "%) exceeds 100%."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Error if there is no DeviceCount left to divide amongst
        # the weighted components (NetworkCount == 0 probably not allowed)
        if total_percent > 0 and total_static_count == DeviceCount:
            err_str = "Not enough total DeviceCount to distribute devices " + \
                "to all components of the mix.  The required total static " + \
                "device count will use up all of the DeviceCount leaving " + \
                "nothing to distribute on the percent-based weighted " + \
                "components."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Calculate how much of the DeviceCount is left for the
        # weighted components...
        total_percent_count = DeviceCount - total_static_count

        # Check that each percent-based weighted component can get
        # at least 1 device
        if total_percent_count < sum(use_percent_list):
            err_str = "Not enough total DeviceCount to distribute devices " + \
                "to all components of the mix.  Once the static counts " + \
                "are handled (if any), there aren't enough devices left (" + \
                str(total_percent_count) + ") such that each " + \
                "percent-based mix component will get at least one device."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Calculate the percent weighted counts from the percents...
        weighted_counts = weight_ops.allocate_weighted_list(
            total_percent_count, percent_list, allow_fraction=False)

        # Apply the counts across each component
        # Assume apply in creation order to map components to templates
        i = 0
        final_device_count = 0
        plLogger.LogInfo("weighted_counts: " + str(weighted_counts))
        plLogger.LogInfo("static_list: " + str(static_list))
        for component, template in zip(component_list, template_list):
            act_value = 0.0
            if use_percent_list[i]:
                act_value = weighted_counts[i]
            else:
                act_value = static_list[i]

            # Note what we chose to apply and then apply it...
            component["appliedValue"] = act_value
            final_device_count += act_value
            i = i + 1

            if "devicesPerBlock" not in component.keys():
                err_str = "Missing required devicesPerBlock parameter in " + \
                                  "Component in StmProtocolMix: " + \
                                  mix.Get("Name")
                plLogger.LogError(err_str)
                this_cmd.Set("Status", err_str)
                return False

            dev_per_block = component["devicesPerBlock"]
            plLogger.LogDebug("Template: " + template.Get("Name"))
            plLogger.LogDebug("dev_count: " + str(act_value))
            plLogger.LogDebug("devicesPerBlock: " + str(dev_per_block))

            last_block_count = 0
            if dev_per_block == 0 or dev_per_block > act_value:
                # All devices into one block
                block_dev_count = act_value
                copies_per_parent = 1
            else:
                # (Greedily) Fill device block with number of devices
                # specified by devicesPerBlock.  Last block will have
                # remainder of devices that does not fill a complete block.
                block_dev_count = dev_per_block
                copies_per_parent = int(act_value // dev_per_block)
                last_block_count = int(act_value % dev_per_block)

            if last_block_count > 0:
                copies_per_parent += 1

            plLogger.LogDebug("block_dev_count: " + str(block_dev_count))
            plLogger.LogDebug("copies_per_parent: " + str(copies_per_parent))
            plLogger.LogDebug("last_block_count: " + str(last_block_count))

            # Call ExpandTemplateConfigCommand
            cmd = ctor.CreateCommand(PKG + ".ExpandTemplateCommand")
            cmd.SetCollection("StmTemplateConfigList", [template.GetObjectHandle()])
            cmd.Set("CopiesPerParent", copies_per_parent)
            cmd.SetCollection("TargetTagList", PortGroupTagList)
            cmd.Execute()
            cmd.MarkDelete()

            emul_dev_list = template.GetObjects("emulateddevice", RelationType("GeneratedObject"))
            for emul_dev in emul_dev_list:
                # Last Block has remainder AND last emulateddevice in list
                if (last_block_count > 0) and (emul_dev == emul_dev_list[-1]):
                    emul_dev.Set("DeviceCount", last_block_count)
                else:
                    emul_dev.Set("DeviceCount", block_dev_count)

    mix_info["deviceCount"] = final_device_count

    # Write the MixInfo back to the StmProtocolMix
    plLogger.LogDebug("dumping back into MixInfo: " + 
                      json.dumps(mix_info))
    mix.Set("MixInfo", json.dumps(mix_info))

    return True
def run(RouteMixList, RouteMixTagList, RouteCount):
    plLogger = PLLogger.GetLogger("methodology")
    obj_list = []
    this_cmd = get_this_cmd()
    if RouteMixList:
        obj_list = CCommandEx.ProcessInputHandleVec("StmTemplateMix",
                                                    RouteMixList)
    if RouteMixTagList:
        obj_list = obj_list + \
            tag_utils.get_tagged_objects_from_string_names(
                RouteMixTagList)
    if len(obj_list) == 0:
        err_str = "Neither RouteMixList nor RouteMixTagList specified a " + \
            "valid StmTemplateMix object."
        this_cmd.Set("Status", err_str)
        plLogger.LogError(err_str)
        return False

    if RouteCount < 1:
        err_str = "RouteCount must be at least 1."
        this_cmd.Set("Status", err_str)
        plLogger.LogError(err_str)
        return False

    obj_dict = {obj.GetObjectHandle(): obj for obj in obj_list}
    for mix in obj_dict.values():
        # Get all of the StmTemplateConfig objects for this mix...
        templates = mix.GetObjects("StmTemplateConfig")

        # Get the MixInfo
        str_mix_info = mix.Get("MixInfo")

        # Validate the input MixInfo against its schema
        # res = json_utils.validate_json(str_mix_info,
        #                                get_this_cmd().Get("MixInfoJsonSchema"))
        # if res != "":
        #     this_cmd.Set("Status", res)
        #     plLogger.LogError(res)
        #     return False

        plLogger.LogInfo("string mix_info: " + str(str_mix_info))
        err_str, mix_info = json_utils.load_json(str_mix_info)
        if err_str != "":
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        plLogger.LogInfo("mix_info: " + str(mix_info))
        component_list = mix_info["components"]
        plLogger.LogInfo("number of components: " + str(len(component_list)))

        # Check the MixInfo component_list length against the
        # number of templates
        if len(templates) != len(component_list):
            err_str = "There are " + str(len(templates)) + " under the " + \
                "StmTemplateMix " + mix.Get("Name") + " (" + \
                str(mix.GetObjectHandle()) + ") but " + \
                str(len(component_list)) + \
                " components in the MixInfo.  " + \
                "These MUST match."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Record what we will use over the whole mix
        mix_info["routeCount"] = RouteCount

        # Process the weight parameter
        static_list = []
        percent_list = []
        use_percent_list = []

        for component in component_list:
            weight = component["weight"]
            is_percent, act_val, err_str = weight_ops.parse_weight_string(
                weight)
            if err_str != "":
                plLogger.LogError(err_str)
                this_cmd.Set("Status", err_str)
                return False

            if is_percent:
                static_list.append(0)
                percent_list.append(act_val)
            else:
                static_list.append(act_val)
                percent_list.append(0)
            use_percent_list.append(is_percent)

        total_static_count = sum(static_list)
        total_percent = sum(percent_list)

        plLogger.LogDebug("total_static_count: " + str(total_static_count))
        plLogger.LogDebug("total_percent: " + str(total_percent))

        # Don't allow the aggregate of static counts to exceed the
        # configured total route count...
        if total_static_count > RouteCount:
            err_str = "Sum total of the static counts (" + \
                str(int(total_static_count)) + ") exceeds the total " + \
                "configured RouteCount (" + str(RouteCount) + ")."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Don't allow the total percent to exceed 100%
        if total_percent > 100:
            err_str = "Sum total of the weights defined as percentages (" + \
                str(total_percent) + "%) exceeds 100%."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Error if there is no RouteCount left to divide amongst
        # the weighted components (NetworkCount == 0 probably not allowed)
        if total_percent > 0 and total_static_count == RouteCount:
            err_str = "Not enough total RouteCount to distribute routes " + \
                "to all components of the mix.  The required total static " + \
                "route count will use up all of the RouteCount leaving " + \
                "nothing to distribute on the percent-based weighted " + \
                "components."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Calculate how much of the RouteCount is left for the
        # weighted components...
        total_percent_count = RouteCount - total_static_count

        # Check that each percent-based weighted component can get
        # at least 1 route
        if total_percent_count < sum(use_percent_list):
            err_str = "Not enough total RouteCount to distribute routes " + \
                "to all components of the mix.  Once the static counts " + \
                "are handled (if any), there aren't enough routes left (" + \
                str(total_percent_count) + ") such that each " + \
                "percent-based mix component will get at least one route."
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Calculate the percent weighted counts from the percents...
        weighted_counts = weight_ops.allocate_weighted_list(
            total_percent_count, percent_list, allow_fraction=False)

        # Apply the counts across each component
        # Assume apply in creation order to map components to templates
        i = 0
        plLogger.LogInfo("weighted_counts: " + str(weighted_counts))
        plLogger.LogInfo("static_list: " + str(static_list))
        for component, template in zip(component_list, templates):
            act_value = 0.0
            if use_percent_list[i]:
                act_value = weighted_counts[i]
            else:
                act_value = static_list[i]

            # Note what we chose to apply and then apply it...
            component["appliedValue"] = act_value

            # Update the NetworkBlocks
            err_str = update_generated_objects(template, act_value)
            if err_str != "":
                plLogger.LogError(err_str)
                this_cmd.Set("Status", err_str)
                return False
            i = i + 1

        # Update the mix with our changes...
        mix.Set("MixInfo", json.dumps(mix_info))
    return True
def run(StmTrafficMix, TrafficMixTagName, Load, LoadUnit):
    plLogger = PLLogger.GetLogger('AllocateTrafficMixLoad2Command')
    obj_list = []
    this_cmd = get_this_cmd()
    if StmTrafficMix:
        obj_list = CCommandEx.ProcessInputHandleVec('StmTrafficMix', [StmTrafficMix])
    if TrafficMixTagName:
        obj_list = obj_list + tag_utils.get_tagged_objects_from_string_names([TrafficMixTagName])
    if len(obj_list) == 0:
        err_str = "Neither StmTrafficMix nor TrafficMixTagName " + \
            "specified a valid StmTrafficMix Object"
        plLogger.LogError(err_str)
        this_cmd.Set("Status", err_str)
        return False

    obj_dict = {obj.GetObjectHandle(): obj for obj in obj_list}
    for mix in obj_dict.values():
        mix_info_s = mix.Get('MixInfo')

        # Validate the input MixInfo against its schema
        res = json_utils.validate_json(mix_info_s,
                                       this_cmd.Get('MixInfoJsonSchema'))
        if res != '':
            plLogger.LogError(res)
            this_cmd.Set("Status", res)
            return False

        err_str, mix_info = json_utils.load_json(mix_info_s)
        if err_str != "":
            plLoger.LogError(err_str)

        component_list = mix_info['components']

        # Record what we will use MIX wide...
        mix_info['load'] = Load
        mix_info['loadUnits'] = LoadUnit

        # Aggregate the individual streamblock information...
        static_list = []
        percent_list = []
        use_percent_list = []

        for component in component_list:
            weight = component["weight"]
            is_percent, act_val, err_str = \
                weight_ops.parse_weight_string(weight)
            if err_str != "":
                err_str = "Total static loads exceed the mix load."
                plLogger.LogError(err_str)
                this_cmd.Set("Status", err_str)
                return False

            if is_percent:
                static_list.append(0)
                percent_list.append(act_val)
            else:
                static_list.append(act_val)
                percent_list.append(0)
            use_percent_list.append(is_percent)

        total_static_load = sum(static_list)
        total_percent = sum(percent_list)

        # Don't allow the aggregate of static loads to exceed the MIX wide load...
        if total_static_load > Load:
            err_str = 'Total static load ({}) exceeds the ' \
                'configured mix load ({}).'.format(total_static_load, Load)
            plLogger.LogError(err_str)
            this_cmd.Set('Status', err_str)
            return False

        # Don't allow an invalid aggregate of streamblock weights...
        if total_percent > 100:
            err_str = "Total weights ({}) exceed 100%.".format(total_percent)
            plLogger.LogError(err_str)
            this_cmd.Set("Status", err_str)
            return False

        # Warn if there is no MIX wide load left to divide amongst the
        # weighted streamblocks...
        if total_percent > 0 and total_static_load == Load:
            err_str = 'No mix load available for weight distribution'
            plLogger.LogWarn(err_str)
            this_cmd.Set("Status", err_str)

        # Fractions are not supported only for these settings
        allow = (LoadUnit not in ['FRAMES_PER_SECOND', 'INTER_BURST_GAP'])

        # Calculate how much of the load is left for the weighted streamblocks...
        total_weighted_load = Load - total_static_load

        # Calculate the weighted loads from the weights...
        weighted_loads = weight_ops.allocate_weighted_list(total_weighted_load,
                                                           percent_list,
                                                           allow_fraction=allow)

        # Get all of the StmTemplateConfig objects for this MIX...
        templates = mix.GetObjects('StmTemplateConfig')

        # Apply the loads across each streamblock according to their individual preferences...
        # Yes, we are ASSUMING creation order to map components to templates...
        for component, template, weight_load in zip(component_list, templates, weighted_loads):
            is_percent, act_val, err_str = \
                weight_ops.parse_weight_string(component['weight'])
            if not is_percent:
                applied_load = act_val
            else:
                applied_load = weight_load

            # Note what we chose to apply and then apply it...
            component['appliedValue'] = applied_load
            allocate_weighted_load(applied_load, template, LoadUnit)
            config_generator(template, LoadUnit)

        # Update the MIX with our changes...
        mix.Set('MixInfo', json.dumps(mix_info))
    return True
Exemplo n.º 8
0
def test_allocate_total_not_100():
    device_count = 50
    weight_list = [20, 40]
    device_list = weight.allocate_weighted_list(device_count, weight_list)
    assert device_list == [10, 20]