d00200d91e10016f1d80a47af824a8e129cb73e5
[vswitchperf.git] / tools / functions.py
1 # Copyright 2016-2017 Intel Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #   http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """Various helper functions
16 """
17
18 import os
19 import logging
20 import glob
21 import shutil
22 from conf import settings as S
23
24 #
25 # Support functions
26 #
27 # pylint: disable=too-many-branches
28 def settings_update_paths():
29     """ Configure paths to OVS, DPDK and QEMU sources and binaries based on
30         selected vswitch type and src/binary switch. Data are taken from
31         PATHS dictionary and after their processing they are stored inside TOOLS.
32         PATHS dictionary has specific section for 'vswitch', 'qemu' and 'dpdk'
33         Following processing is done for every item:
34             item 'type' - string, which defines the type of paths ('src' or 'bin') to be selected
35                   for a given section:
36                       'src' means, that VSPERF will use OVS, DPDK or QEMU built from sources
37                           e.g. by execution of systems/build_base_machine.sh script during VSPERF
38                           installation
39                       'bin' means, that VSPERF will use OVS, DPDK or QEMU binaries installed
40                           in the OS, e.g. via OS specific packaging system
41             item 'path' - string with valid path; Its content is checked for existence, prefixed
42                   with section name and stored into TOOLS for later use
43                   e.g. TOOLS['dpdk_src'] or TOOLS['vswitch_src']
44             item 'modules' - list of strings; Every value from given list is checked for '.ko'
45                   suffix. In case it matches and it is not an absolute path to the module, then
46                   module name is prefixed with 'path' defined for the same section
47                   e.g. TOOLS['vswitch_modules'] = [
48                       '/tmp/vsperf/src_vanilla/ovs/ovs/datapath/linux/openvswitch.ko']
49             all other items - string - if given string is a relative path and item 'path'
50                   is defined for a given section, then item content will be prefixed with
51                   content of the 'path'. Otherwise tool name will be searched within
52                   standard system directories. Also any OS filename wildcards will be
53                   expanded to the real path. At the end of processing, every absolute
54                   path is checked for its existence. In case that temporary path (i.e. path
55                   with '_tmp' suffix) doesn't exist, then log will be written and vsperf will
56                   continue. If any other path will not exist, then vsperf execution will
57                   be terminated with runtime error.
58
59         Note: In case that 'bin' type is set for DPDK, then TOOLS['dpdk_src'] will be set to
60         the value of PATHS['dpdk']['src']['path']. The reason is, that VSPERF uses downloaded
61         DPDK sources to copy DPDK and testpmd into the GUEST, where testpmd is built. In case,
62         that DPDK sources are not available, then vsperf will continue with test execution,
63         but testpmd can't be used as a guest loopback. This is useful in case, that other guest
64         loopback applications (e.g. buildin) are used by CI jobs, etc.
65     """
66     # set dpdk and ovs paths accorfing to VNF and VSWITCH
67     paths = {}
68     vswitch_type = S.getValue('PATHS')['vswitch'][S.getValue('VSWITCH')]['type']
69     paths['vswitch'] = S.getValue('PATHS')['vswitch'][S.getValue('VSWITCH')][vswitch_type]
70     paths['dpdk'] = S.getValue('PATHS')['dpdk'][S.getValue('PATHS')['dpdk']['type']]
71     paths['qemu'] = S.getValue('PATHS')['qemu'][S.getValue('PATHS')['qemu']['type']]
72     paths['paths'] = {}
73     paths['paths']['ovs_var_tmp'] = S.getValue('PATHS')['vswitch']['ovs_var_tmp']
74     paths['paths']['ovs_etc_tmp'] = S.getValue('PATHS')['vswitch']['ovs_etc_tmp']
75
76     tools = {}
77     # pylint: disable=too-many-nested-blocks
78     for path_class in paths:
79         for tool in paths[path_class]:
80             tmp_tool = paths[path_class][tool]
81
82             # store valid path of given class into tools dict
83             if tool == 'path':
84                 if os.path.isdir(tmp_tool):
85                     tools['{}_src'.format(path_class)] = tmp_tool
86                     continue
87                 else:
88                     raise RuntimeError('Path {} does not exist.'.format(tmp_tool))
89
90             # store list of modules of given class into tools dict
91             if tool == 'modules':
92                 tmp_modules = []
93                 for module in tmp_tool:
94                     # add path to the .ko modules and check it for existence
95                     if module.endswith('.ko') and not os.path.isabs(module):
96                         module = os.path.join(paths[path_class]['path'], module)
97                         if not os.path.exists(module):
98                             raise RuntimeError('Cannot locate modlue {}'.format(module))
99
100                     tmp_modules.append(module)
101
102                 tools['{}_modules'.format(path_class)] = tmp_modules
103                 continue
104
105             # if path to the tool is relative, then 'path' will be prefixed
106             # in case that 'path' is not defined, then tool will be searched
107             # within standard system paths
108             if not os.path.isabs(tmp_tool):
109                 if 'path' in paths[path_class]:
110                     tmp_tool = os.path.join(paths[path_class]['path'], tmp_tool)
111                 elif shutil.which(tmp_tool):
112                     tmp_tool = shutil.which(tmp_tool)
113                 else:
114                     raise RuntimeError('Cannot locate tool {}'.format(tmp_tool))
115
116             # expand OS wildcards in paths if needed
117             if glob.has_magic(tmp_tool):
118                 tmp_glob = glob.glob(tmp_tool)
119                 if len(tmp_glob) == 0:
120                     raise RuntimeError('Path to the {} is not valid: {}.'.format(tool, tmp_tool))
121                 elif len(tmp_glob) > 1:
122                     raise RuntimeError('Path to the {} is ambiguous {}'.format(tool, tmp_glob))
123                 elif len(tmp_glob) == 1:
124                     tmp_tool = tmp_glob[0]
125             elif not os.path.exists(tmp_tool):
126                 if tool.endswith('_tmp'):
127                     logging.getLogger().debug('Temporary path to the %s does not '
128                                               'exist: %s', tool, tmp_tool)
129                 else:
130                     raise RuntimeError('Path to the {} is not valid: {}'.format(tool, tmp_tool))
131
132             tools[tool] = tmp_tool
133
134     # ensure, that dpkg_src for bin will be set to downloaded DPDK sources, so it can
135     # be copied to the guest share dir and used by GUEST to build and run testpmd
136     # Validity of the path is not checked by purpose, so user can use VSPERF without
137     # downloading DPDK sources. In that case guest loopback can't be set to 'testpmd'
138     if S.getValue('PATHS')['dpdk']['type'] == 'bin':
139         tools['dpdk_src'] = S.getValue('PATHS')['dpdk']['src']['path']
140
141     S.setValue('TOOLS', tools)