aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries/python/CpuUtils.py
blob: 85c2e843e4053c565890bbb865fd37e80d701096 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Copyright (c) 2016 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""CPU utilities library"""

from resources.libraries.python.ssh import SSH

__all__ = ["CpuUtils"]

class CpuUtils(object):
    """CPU utilities"""

    @staticmethod
    def __str2int(string):
        """Conversion from string to integer, 0 in case of empty string.

        :param string: Input string.
        :type string: str
        :return: Integer converted from string, 0 in case of ValueError.
        :rtype: int
        """
        try:
            return int(string)
        except ValueError:
            return 0

    @staticmethod
    def get_cpu_layout_from_all_nodes(nodes):
        """Retrieve cpu layout from all nodes, assuming all nodes
           are Linux nodes.

        :param nodes: DICT__nodes from Topology.DICT__nodes.
        :type nodes: dict
        """
        ssh = SSH()
        for node in nodes.values():
            ssh.connect(node)
            cmd = "lscpu -p"
            ret, stdout, stderr = ssh.exec_command(cmd)
#           parsing of "lscpu -p" output:
#           # CPU,Core,Socket,Node,,L1d,L1i,L2,L3
#           0,0,0,0,,0,0,0,0
#           1,1,0,0,,1,1,1,0
            if ret != 0:
                raise RuntimeError(
                    "Failed to execute ssh command, ret: {} err: {}".format(
                        ret, stderr))
            node['cpuinfo'] = list()
            for line in stdout.split("\n"):
                if len(line) > 0 and line[0] != "#":
                    node['cpuinfo'].append([CpuUtils.__str2int(x) for x in
                                            line.split(",")])

    @staticmethod
    def cpu_node_count(node):
        """Return count of numa nodes.

        :param node: Targeted node.
        :type node: dict
        :return: Count of numa nodes.
        :rtype: int
        """
        cpuinfo = node.get("cpuinfo")
        if cpuinfo is not None:
            return node["cpuinfo"][-1][3] + 1
        else:
            raise RuntimeError("Node cpuinfo not available.")

    @staticmethod
    def cpu_list_per_node(node, cpu_node):
        """Return node related list of CPU numbers.

        :param node: Node dictionary with cpuinfo.
        :param cpu_node: Numa node number.
        :type node: int
        :type cpu_node: int
        :return: List of cpu numbers related to numa from argument.
        :rtype: list of int
        """
        cpu_node = int(cpu_node)
        cpuinfo = node.get("cpuinfo")
        cpulist = []
        if cpuinfo is not None:
            for cpu in cpuinfo:
                if cpu[3] == cpu_node:
                    cpulist.append(cpu[0])
        else:
            raise RuntimeError("Node cpuinfo not available.")

        return cpulist

    @staticmethod
    def cpu_list_per_node_str(node, cpu_node, skip_cnt=0,
                              cpu_cnt=0, sep=","):
        """Return string of node related list of CPU numbers.

        :param node: Node dictionary with cpuinfo.
        :param cpu_node: Numa node number.
        :param skip_cnt: Skip first "skip_cnt" CPUs.
        :param cpu_cnt: Count of cpus to return, if 0 then return all.
        :param sep: Separator, default: 1,2,3,4,....
        :type node: dict
        :type cpu_node: int
        :type skip_cnt: int
        :type cpu_cnt: int
        :type sep: str
        :return: Cpu numbers related to numa from argument.
        :rtype: str
        """

        cpu_list = CpuUtils.cpu_list_per_node(node, cpu_node)
        cpu_list_len = len(cpu_list)
        cpu_flist = ""
        if cpu_cnt == 0:
            cpu_cnt = cpu_list_len - skip_cnt

        if cpu_cnt + skip_cnt > cpu_list_len:
            raise RuntimeError("cpu_cnt + skip_cnt > length(cpu list).")

        cpu_flist = sep.join(str(a) for a in
                             cpu_list[skip_cnt:skip_cnt+cpu_cnt])

        return cpu_flist
pan> * * @param fib_index * The index of the FIB * * @param prefix * The prefix for the entry to add * * @param source * The ID of the client/source adding the entry. * * @param rpaths * A vector of paths. */ extern void mfib_table_entry_path_remove(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *paths); /** * @brief * Delete a FIB entry. If the entry has no more sources, then it is * removed from the table. * * @param fib_index * The index of the FIB * * @param prefix * The prefix for the entry to remove * * @param source * The ID of the client/source adding the entry. */ extern void mfib_table_entry_delete(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source); /** * @brief * Delete a FIB entry. If the entry has no more sources, then it is * removed from the table. * * @param entry_index * The index of the FIB entry * * @param source * The ID of the client/source adding the entry. */ extern void mfib_table_entry_delete_index(fib_node_index_t entry_index, mfib_source_t source); /** * @brief * Add a 'special' entry to the mFIB that links to the DPO passed * A special entry is an entry that the FIB is not expect to resolve * via the usual mechanisms (i.e. recurisve or neighbour adj DB lookup). * Instead the client/source provides the index of a replicate DPO to link to. * * @param fib_index * The index of the FIB * * @param prefix * The prefix to add * * @param source * The ID of the client/source adding the entry. * * @param flags * Flags for the entry. * * @param rep_dpo * The replicate DPO index to link to. * * @return * the index of the fib_entry_t that is created (or existed already). */ extern fib_node_index_t mfib_table_entry_special_add(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, mfib_entry_flags_t flags, index_t rep_dpo); /** * @brief * Flush all entries from a table for the source * * @param fib_index * The index of the FIB * * @paran proto * The protocol of the entries in the table * * @param source * the source to flush */ extern void mfib_table_flush(u32 fib_index, fib_protocol_t proto, mfib_source_t source); /** * @brief * Get the index of the FIB bound to the interface * * @paran proto * The protocol of the FIB (and thus the entries therein) * * @param sw_if_index * The interface index * * @return fib_index * The index of the FIB */ extern u32 mfib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index); /** * @brief * Get the index of the FIB for a Table-ID. This DOES NOT create the * FIB if it does not exist. * * @paran proto * The protocol of the FIB (and thus the entries therein) * * @param table-id * The Table-ID * * @return fib_index * The index of the FIB, which may be INVALID. */ extern u32 mfib_table_find(fib_protocol_t proto, u32 table_id); /** * @brief * Get the index of the FIB for a Table-ID. This DOES create the * FIB if it does not exist. * * @paran proto * The protocol of the FIB (and thus the entries therein) * * @param table-id * The Table-ID * * @return fib_index * The index of the FIB * * @param source * The ID of the client/source. */ extern u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, mfib_source_t source); /** * @brief * Get the index of the FIB for a Table-ID. This DOES create the * FIB if it does not exist. * * @paran proto * The protocol of the FIB (and thus the entries therein) * * @param table-id * The Table-ID * * @return fib_index * The index of the FIB * * @param source * The ID of the client/source. * * @param name * The client is choosing the name they want the table to have */ extern u32 mfib_table_find_or_create_and_lock_w_name(fib_protocol_t proto, u32 table_id, mfib_source_t source, const u8 *name); /** * @brief * Take a reference counting lock on the table * * @param fib_index * The index of the FIB * * @paran proto * The protocol of the FIB (and thus the entries therein) * * @param source * The ID of the client/source. */ extern void mfib_table_unlock(u32 fib_index, fib_protocol_t proto, mfib_source_t source); /** * @brief * Release a reference counting lock on the table. When the last lock * has gone. the FIB is deleted. * * @param fib_index * The index of the FIB * * @paran proto * The protocol of the FIB (and thus the entries therein) * * @param source * The ID of the client/source. */ extern void mfib_table_lock(u32 fib_index, fib_protocol_t proto, mfib_source_t source); /** * @brief * Return the number of entries in the FIB added by a given source. * * @param fib_index * The index of the FIB * * @paran proto * The protocol of the FIB (and thus the entries therein) * * @return number of sourced entries. */ extern u32 mfib_table_get_num_entries(u32 fib_index, fib_protocol_t proto); /** * @brief * Get a pointer to a FIB table */ extern mfib_table_t *mfib_table_get(fib_node_index_t index, fib_protocol_t proto); /** * @brief Call back function when walking entries in a FIB table */ typedef int (*mfib_table_walk_fn_t)(fib_node_index_t fei, void *ctx); /** * @brief Walk all entries in a FIB table * N.B: This is NOT safe to deletes. If you need to delete, walk the whole * table and store elements in a vector, then delete the elements */ extern void mfib_table_walk(u32 fib_index, fib_protocol_t proto, mfib_table_walk_fn_t fn, void *ctx); #endif