blob: c4cd76cf443effe9ddee4c2a08d7379d267b3cc4 [file] [log] [blame]
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001# Copyright (C) 2016 Intel Corporation
2# Released under the MIT license (see COPYING.MIT)
3
4import os
5
6from oeqa.core.context import OETestContext, OETestContextExecutor
7from oeqa.core.target.ssh import OESSHTarget
8from oeqa.core.target.qemu import OEQemuTarget
9from oeqa.utils.dump import HostDumper
10
11from oeqa.runtime.loader import OERuntimeTestLoader
12
13class OERuntimeTestContext(OETestContext):
14 loaderClass = OERuntimeTestLoader
15 runtime_files_dir = os.path.join(
16 os.path.dirname(os.path.abspath(__file__)), "files")
17
18 def __init__(self, td, logger, target,
19 host_dumper, image_packages, extract_dir):
20 super(OERuntimeTestContext, self).__init__(td, logger)
21
22 self.target = target
23 self.image_packages = image_packages
24 self.host_dumper = host_dumper
25 self.extract_dir = extract_dir
26 self._set_target_cmds()
27
28 def _set_target_cmds(self):
29 self.target_cmds = {}
30
31 self.target_cmds['ps'] = 'ps'
32 if 'procps' in self.image_packages:
33 self.target_cmds['ps'] = self.target_cmds['ps'] + ' -ef'
34
35class OERuntimeTestContextExecutor(OETestContextExecutor):
36 _context_class = OERuntimeTestContext
37
38 name = 'runtime'
39 help = 'runtime test component'
40 description = 'executes runtime tests over targets'
41
42 default_cases = os.path.join(os.path.abspath(os.path.dirname(__file__)),
43 'cases')
44 default_data = None
45 default_test_data = 'data/testdata.json'
46 default_tests = ''
47
48 default_target_type = 'simpleremote'
49 default_manifest = 'data/manifest'
50 default_server_ip = '192.168.7.1'
51 default_target_ip = '192.168.7.2'
52 default_host_dumper_dir = '/tmp/oe-saved-tests'
53 default_extract_dir = 'packages/extracted'
54
55 def register_commands(self, logger, subparsers):
56 super(OERuntimeTestContextExecutor, self).register_commands(logger, subparsers)
57
58 runtime_group = self.parser.add_argument_group('runtime options')
59
60 runtime_group.add_argument('--target-type', action='store',
61 default=self.default_target_type, choices=['simpleremote', 'qemu'],
62 help="Target type of device under test, default: %s" \
63 % self.default_target_type)
64 runtime_group.add_argument('--target-ip', action='store',
65 default=self.default_target_ip,
66 help="IP address of device under test, default: %s" \
67 % self.default_target_ip)
68 runtime_group.add_argument('--server-ip', action='store',
69 default=self.default_target_ip,
70 help="IP address of device under test, default: %s" \
71 % self.default_server_ip)
72
73 runtime_group.add_argument('--host-dumper-dir', action='store',
74 default=self.default_host_dumper_dir,
75 help="Directory where host status is dumped, if tests fails, default: %s" \
76 % self.default_host_dumper_dir)
77
78 runtime_group.add_argument('--packages-manifest', action='store',
79 default=self.default_manifest,
80 help="Package manifest of the image under testi, default: %s" \
81 % self.default_manifest)
82
83 runtime_group.add_argument('--extract-dir', action='store',
84 default=self.default_extract_dir,
85 help='Directory where extracted packages reside, default: %s' \
86 % self.default_extract_dir)
87
88 runtime_group.add_argument('--qemu-boot', action='store',
89 help="Qemu boot configuration, only needed when target_type is QEMU.")
90
91 @staticmethod
92 def getTarget(target_type, logger, target_ip, server_ip, **kwargs):
93 target = None
94
95 if target_type == 'simpleremote':
96 target = OESSHTarget(logger, target_ip, server_ip, **kwargs)
97 elif target_type == 'qemu':
98 target = OEQemuTarget(logger, target_ip, server_ip, **kwargs)
99 else:
100 # XXX: This code uses the old naming convention for controllers and
101 # targets, the idea it is to leave just targets as the controller
102 # most of the time was just a wrapper.
103 # XXX: This code tries to import modules from lib/oeqa/controllers
104 # directory and treat them as controllers, it will less error prone
105 # to use introspection to load such modules.
106 # XXX: Don't base your targets on this code it will be refactored
107 # in the near future.
108 # Custom target module loading
109 try:
110 target_modules_path = kwargs.get('target_modules_path', '')
111 controller = OERuntimeTestContextExecutor.getControllerModule(target_type, target_modules_path)
112 target = controller(logger, target_ip, server_ip, **kwargs)
113 except ImportError as e:
114 raise TypeError("Failed to import %s from available controller modules" % target_type)
115
116 return target
117
118 # Search oeqa.controllers module directory for and return a controller
119 # corresponding to the given target name.
120 # AttributeError raised if not found.
121 # ImportError raised if a provided module can not be imported.
122 @staticmethod
123 def getControllerModule(target, target_modules_path):
124 controllerslist = OERuntimeTestContextExecutor._getControllerModulenames(target_modules_path)
125 controller = OERuntimeTestContextExecutor._loadControllerFromName(target, controllerslist)
126 return controller
127
128 # Return a list of all python modules in lib/oeqa/controllers for each
129 # layer in bbpath
130 @staticmethod
131 def _getControllerModulenames(target_modules_path):
132
133 controllerslist = []
134
135 def add_controller_list(path):
136 if not os.path.exists(os.path.join(path, '__init__.py')):
137 raise OSError('Controllers directory %s exists but is missing __init__.py' % path)
138 files = sorted([f for f in os.listdir(path) if f.endswith('.py') and not f.startswith('_')])
139 for f in files:
140 module = 'oeqa.controllers.' + f[:-3]
141 if module not in controllerslist:
142 controllerslist.append(module)
143 else:
144 raise RuntimeError("Duplicate controller module found for %s. Layers should create unique controller module names" % module)
145
146 extpath = target_modules_path.split(':')
147 for p in extpath:
148 controllerpath = os.path.join(p, 'lib', 'oeqa', 'controllers')
149 if os.path.exists(controllerpath):
150 add_controller_list(controllerpath)
151 return controllerslist
152
153 # Search for and return a controller from given target name and
154 # set of module names.
155 # Raise AttributeError if not found.
156 # Raise ImportError if a provided module can not be imported
157 @staticmethod
158 def _loadControllerFromName(target, modulenames):
159 for name in modulenames:
160 obj = OERuntimeTestContextExecutor._loadControllerFromModule(target, name)
161 if obj:
162 return obj
163 raise AttributeError("Unable to load {0} from available modules: {1}".format(target, str(modulenames)))
164
165 # Search for and return a controller or None from given module name
166 @staticmethod
167 def _loadControllerFromModule(target, modulename):
168 obj = None
169 # import module, allowing it to raise import exception
170 try:
171 module = __import__(modulename, globals(), locals(), [target])
172 except Exception as e:
173 return obj
174 # look for target class in the module, catching any exceptions as it
175 # is valid that a module may not have the target class.
176 try:
177 obj = getattr(module, target)
178 except:
179 obj = None
180 return obj
181
182 @staticmethod
183 def readPackagesManifest(manifest):
184 if not manifest or not os.path.exists(manifest):
185 raise OSError("Manifest file not exists: %s" % manifest)
186
187 image_packages = set()
188 with open(manifest, 'r') as f:
189 for line in f.readlines():
190 line = line.strip()
191 if line and not line.startswith("#"):
192 image_packages.add(line.split()[0])
193
194 return image_packages
195
196 @staticmethod
197 def getHostDumper(cmds, directory):
198 return HostDumper(cmds, directory)
199
200 def _process_args(self, logger, args):
201 if not args.packages_manifest:
202 raise TypeError('Manifest file not provided')
203
204 super(OERuntimeTestContextExecutor, self)._process_args(logger, args)
205
206 target_kwargs = {}
207 target_kwargs['qemuboot'] = args.qemu_boot
208
209 self.tc_kwargs['init']['target'] = \
210 OERuntimeTestContextExecutor.getTarget(args.target_type,
211 None, args.target_ip, args.server_ip, **target_kwargs)
212 self.tc_kwargs['init']['host_dumper'] = \
213 OERuntimeTestContextExecutor.getHostDumper(None,
214 args.host_dumper_dir)
215 self.tc_kwargs['init']['image_packages'] = \
216 OERuntimeTestContextExecutor.readPackagesManifest(
217 args.packages_manifest)
218 self.tc_kwargs['init']['extract_dir'] = args.extract_dir
219
220_executor_class = OERuntimeTestContextExecutor