aboutsummaryrefslogtreecommitdiff
path: root/lava_dispatcher/test/test_lxc.py
blob: 68867a6b4f2d28e8edb52dcc64b40ec52c52d97c (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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# Copyright (C) 2016 Linaro Limited
#
# Author: Senthil Kumaran S <senthil.kumaran@linaro.org>
#
# This file is part of LAVA Dispatcher.
#
# LAVA Dispatcher is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LAVA Dispatcher is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along
# with this program; if not, see <http://www.gnu.org/licenses>.

import os
import yaml
import unittest
from lava_dispatcher.device import NewDevice
from lava_dispatcher.parser import JobParser
from lava_dispatcher.action import JobError
from lava_dispatcher.test.test_basic import Factory, StdoutTestCase
from lava_dispatcher.test.utils import DummyLogger, infrastructure_error
from lava_dispatcher.actions.deploy import DeployAction
from lava_dispatcher.actions.deploy.lxc import LxcCreateAction
from lava_dispatcher.actions.boot.lxc import BootAction


class LxcFactory(Factory):  # pylint: disable=too-few-public-methods
    """
    Not Model based, this is not a Django factory.
    Factory objects are dispatcher based classes, independent
    of any database objects.
    """

    def create_lxc_job(self, filename):
        return self.create_job('lxc-01.jinja2', filename)

    def create_bbb_lxc_job(self, filename):  # pylint: disable=no-self-use
        return self.create_job('bbb-01.jinja2', filename)

    def create_adb_nuc_job(self, filename):  # pylint: disable=no-self-use
        device = NewDevice(os.path.join(os.path.dirname(__file__),
                                        '../devices/adb-nuc-01.yaml'))
        job_yaml = os.path.join(os.path.dirname(__file__), filename)
        with open(job_yaml) as sample_job_data:
            parser = JobParser()
            job = parser.parse(sample_job_data, device, 4577, None, "")
        job.logger = DummyLogger()
        return job

    def create_hikey_aep_job(self, filename):  # pylint: disable=no-self-use
        device = NewDevice(os.path.join(os.path.dirname(__file__),
                                        '../devices/hi6220-hikey-01.yaml'))
        job_yaml = os.path.join(os.path.dirname(__file__), filename)
        with open(job_yaml) as sample_job_data:
            parser = JobParser()
            job = parser.parse(sample_job_data, device, 4577, None, "")
        job.logger = DummyLogger()
        return job


class TestLxcDeploy(StdoutTestCase):  # pylint: disable=too-many-public-methods

    def setUp(self):
        super().setUp()
        factory = LxcFactory()
        self.job = factory.create_lxc_job('sample_jobs/lxc.yaml')

    def test_deploy_job(self):
        self.assertEqual(self.job.pipeline.job, self.job)
        for action in self.job.pipeline.actions:
            if isinstance(action, DeployAction):
                self.assertEqual(action.job, self.job)

    def test_pipeline(self):
        description_ref = self.pipeline_reference('lxc.yaml')
        self.assertEqual(description_ref, self.job.pipeline.describe(False))

    @unittest.skipIf(infrastructure_error('lxc-create'),
                     'lxc-create not installed')
    def test_validate(self):
        try:
            self.job.pipeline.validate_actions()
        except JobError as exc:
            self.fail(exc)
        for action in self.job.pipeline.actions:
            self.assertEqual([], action.errors)

    @unittest.skipIf(infrastructure_error('lxc-create'),
                     'lxc-create not installed')
    def test_create(self):
        for action in self.job.pipeline.actions:
            if isinstance(action, LxcCreateAction):
                self.assertEqual(action.lxc_data['lxc_name'],
                                 'pipeline-lxc-test-4577')
                self.assertEqual(action.lxc_data['lxc_distribution'], 'debian')
                self.assertEqual(action.lxc_data['lxc_release'], 'sid')
                self.assertEqual(action.lxc_data['lxc_arch'], 'amd64')
                self.assertEqual(action.lxc_data['lxc_template'], 'debian')
                self.assertEqual(action.lxc_data['lxc_mirror'],
                                 'http://ftp.us.debian.org/debian/')
                self.assertEqual(action.lxc_data['lxc_security_mirror'],
                                 'http://mirror.csclub.uwaterloo.ca/debian-security/')

    @unittest.skipIf(infrastructure_error('lxc-start'),
                     'lxc-start not installed')
    def test_boot(self):
        for action in self.job.pipeline.actions:
            if isinstance(action, BootAction):
                # get the action & populate it
                self.assertEqual(action.parameters['method'], 'lxc')
                self.assertEqual(action.parameters['prompts'], ['root@(.*):/#'])

    def test_testdefinitions(self):
        for action in self.job.pipeline.actions:
            if action.name == 'test':
                # get the action & populate it
                self.assertEqual(len(action.parameters['definitions']), 2)


class TestLxcWithDevices(StdoutTestCase):

    def setUp(self):
        super().setUp()
        self.factory = LxcFactory()
        self.job = self.factory.create_bbb_lxc_job('sample_jobs/bbb-lxc.yaml')

    def test_lxc_feedback(self):  # pylint: disable=too-many-locals
        self.assertIsNotNone(self.job)
        # validate with two test actions, lxc and device
        self.job.validate()
        drone_test = [action for action in self.job.pipeline.actions if action.name == 'lava-test-retry'][0]
        self.assertNotEqual(10, drone_test.connection_timeout.duration)
        drone_shell = [action for action in drone_test.internal_pipeline.actions if action.name == 'lava-test-shell'][0]
        self.assertEqual(10, drone_shell.connection_timeout.duration)

    def test_lxc_with_device(self):  # pylint: disable=too-many-locals
        self.assertIsNotNone(self.job)
        # validate with two test actions, lxc and device
        self.job.validate()
        lxc_yaml = os.path.join(os.path.dirname(__file__), 'sample_jobs/bbb-lxc.yaml')
        with open(lxc_yaml) as sample_job_data:
            data = yaml.load(sample_job_data)
        lxc_deploy = [action for action in self.job.pipeline.actions if action.name == 'lxc-deploy'][0]
        overlay = [action for action in lxc_deploy.internal_pipeline.actions if action.name == 'lava-overlay'][0]
        test_def = [action for action in overlay.internal_pipeline.actions if action.name == 'test-definition'][0]
        self.assertIsNotNone(test_def.level, test_def.test_list)
        runner = [action for action in test_def.internal_pipeline.actions if action.name == 'test-runscript-overlay'][0]
        self.assertIsNotNone(runner.testdef_levels)
        tftp_deploy = [action for action in self.job.pipeline.actions if action.name == 'tftp-deploy'][0]
        prepare = [action for action in tftp_deploy.internal_pipeline.actions if action.name == 'prepare-tftp-overlay'][0]
        overlay = [action for action in prepare.internal_pipeline.actions if action.name == 'lava-overlay'][0]
        test_def = [action for action in overlay.internal_pipeline.actions if action.name == 'test-definition'][0]
        namespace = test_def.parameters.get('namespace')
        self.assertIsNotNone(namespace)
        test_actions = [action for action in self.job.parameters['actions'] if 'test' in action]
        for action in test_actions:
            if 'namespace' in action['test']:
                if action['test']['namespace'] == namespace:
                    self.assertEqual(action['test']['definitions'][0]['name'], 'smoke-tests-bbb')
        namespace_tests = [action['test']['definitions'] for action in test_actions
                           if 'namespace' in action['test'] and action['test']['namespace'] == namespace]
        self.assertEqual(len(namespace_tests), 1)
        self.assertEqual(len(test_actions), 2)
        self.assertEqual('smoke-tests-bbb', namespace_tests[0][0]['name'])
        self.assertEqual(
            'smoke-tests-bbb',
            test_def.test_list[0][0]['name'])
        self.assertIsNotNone(test_def.level, test_def.test_list)
        runner = [action for action in test_def.internal_pipeline.actions if action.name == 'test-runscript-overlay'][0]
        self.assertIsNotNone(runner.testdef_levels)
        # remove the second test action
        data['actions'].pop()
        test_actions = [action for action in data['actions'] if 'test' in action]
        self.assertEqual(len(test_actions), 1)
        self.assertEqual(test_actions[0]['test']['namespace'], 'probe')
        parser = JobParser()
        (rendered, _) = self.factory.create_device('bbb-01.jinja2')
        device = NewDevice(yaml.load(rendered))
        job = parser.parse(yaml.dump(data), device, 4577, None, "")
        job.logger = DummyLogger()
        job.validate()
        lxc_deploy = [action for action in self.job.pipeline.actions if action.name == 'lxc-deploy'][0]
        overlay = [action for action in lxc_deploy.internal_pipeline.actions if action.name == 'lava-overlay'][0]
        test_def = [action for action in overlay.internal_pipeline.actions if action.name == 'test-definition'][0]
        self.assertIsNotNone(test_def.level, test_def.test_list)
        runner = [action for action in test_def.internal_pipeline.actions if action.name == 'test-runscript-overlay'][0]
        self.assertIsNotNone(runner.testdef_levels)

    def test_lxc_with_static_device(self):  # pylint: disable=too-many-locals
        self.job = self.factory.create_hikey_aep_job('sample_jobs/hi6220-hikey.yaml')
        self.job.validate()
        lxc_boot = [action for action in self.job.pipeline.actions if action.name == 'lxc-boot'][0]
        lxc_static = [action for action in lxc_boot.internal_pipeline.actions if action.name == 'lxc-add-static'][0]
        self.assertIsNotNone(lxc_static)
        self.assertIsInstance(self.job.device.get('static_info'), list)
        self.assertEqual(len(self.job.device.get('static_info')), 1)
        for board in self.job.device.get('static_info'):
            self.assertIsInstance(board, dict)
            self.assertIn('board_id', board)
            self.assertEqual(board['board_id'], 'S/NO62200001')
        description_ref = self.pipeline_reference('hi6220-hikey.yaml', job=self.job)
        self.assertEqual(description_ref, self.job.pipeline.describe(False))

    def test_lxc_without_lxctest(self):  # pylint: disable=too-many-locals
        lxc_yaml = os.path.join(os.path.dirname(__file__), 'sample_jobs/bbb-lxc-notest.yaml')
        with open(lxc_yaml) as sample_job_data:
            data = yaml.load(sample_job_data)
        parser = JobParser()
        (rendered, _) = self.factory.create_device('bbb-01.jinja2')
        device = NewDevice(yaml.load(rendered))
        job = parser.parse(yaml.dump(data), device, 4577, None, "")
        job.logger = DummyLogger()
        job.validate()
        lxc_deploy = [action for action in job.pipeline.actions if action.name == 'lxc-deploy'][0]
        names = [action.name for action in lxc_deploy.internal_pipeline.actions]
        self.assertNotIn('prepare-tftp-overlay', names)
        namespace1 = lxc_deploy.parameters.get('namespace')
        tftp_deploy = [action for action in job.pipeline.actions if action.name == 'tftp-deploy'][0]
        prepare = [action for action in tftp_deploy.internal_pipeline.actions if action.name == 'prepare-tftp-overlay'][0]
        overlay = [action for action in prepare.internal_pipeline.actions if action.name == 'lava-overlay'][0]
        test_def = [action for action in overlay.internal_pipeline.actions if action.name == 'test-definition'][0]
        namespace = test_def.parameters.get('namespace')
        self.assertIsNotNone(namespace)
        self.assertIsNotNone(namespace1)
        self.assertNotEqual(namespace, namespace1)
        self.assertNotEqual(self.job.pipeline.describe(False), job.pipeline.describe(False))
        test_actions = [action for action in job.parameters['actions'] if 'test' in action]
        for action in test_actions:
            if 'namespace' in action['test']:
                if action['test']['namespace'] == namespace:
                    self.assertEqual(action['test']['definitions'][0]['name'], 'smoke-tests-bbb')
            else:
                self.fail("Found a test action not from the tftp boot")
        namespace_tests = [action['test']['definitions'] for action in test_actions
                           if 'namespace' in action['test'] and action['test']['namespace'] == namespace]
        self.assertEqual(len(namespace_tests), 1)
        self.assertEqual(len(test_actions), 1)
        description_ref = self.pipeline_reference('bbb-lxc-notest.yaml', job=job)
        self.assertEqual(description_ref, job.pipeline.describe(False))

    def test_adb_nuc_job(self):
        self.factory = LxcFactory()
        job = self.factory.create_adb_nuc_job('sample_jobs/adb-nuc.yaml')
        description_ref = self.pipeline_reference('adb-nuc.yaml', job=job)
        self.assertEqual(description_ref, job.pipeline.describe(False))

    def test_iot_lxc(self):
        self.factory = Factory()
        job = self.factory.create_job('frdm-k64f-01.jinja2', 'sample_jobs/frdm-k64f-lxc.yaml')
        job.validate()
        self.assertIsNotNone([action for action in job.pipeline.actions if action.name == 'lxc-deploy'])
        self.assertIsNotNone([action for action in job.pipeline.actions if action.name == 'lxc-boot'])
        description_ref = self.pipeline_reference('frdm-k64f-lxc.yaml', job=job)
        self.assertEqual(description_ref, job.pipeline.describe(False))