Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
ipsecondary_test.py
1 #!/usr/bin/env python3
2 
3 import logging
4 import argparse
5 
6 from os import getcwd, chdir, path
7 
8 from test_fixtures import with_aktualizr, with_uptane_backend, KeyStore, with_secondary, with_treehub,\
9  with_sysroot, with_director
10 
11 logger = logging.getLogger("IPSecondaryTest")
12 
13 
14 # The following is a test suit intended for IP Secondary integration testing
15 @with_uptane_backend()
16 @with_secondary(start=True)
17 @with_aktualizr(start=False, output_logs=False)
18 def test_secondary_update_if_secondary_starts_first(uptane_repo, secondary, aktualizr, **kwargs):
19  '''Test Secondary update if Secondary is booted before Primary'''
20 
21  # add a new image to the repo in order to update the secondary with it
22  secondary_image_filename = "secondary_image_filename_001.img"
23  secondary_image_hash = uptane_repo.add_image(id=secondary.id, image_filename=secondary_image_filename)
24 
25  logger.debug("Trying to update ECU {} with the image {}".
26  format(secondary.id, (secondary_image_hash, secondary_image_filename)))
27 
28  with aktualizr:
29  # run aktualizr once, secondary has been already running
30  aktualizr.wait_for_completion()
31 
32  test_result = secondary_image_hash == aktualizr.get_current_image_info(secondary.id)
33  logger.debug("Update result: {}".format("success" if test_result else "failed"))
34  return test_result
35 
36 
37 @with_uptane_backend()
38 @with_secondary(start=False)
39 @with_aktualizr(start=True, output_logs=False)
40 def test_secondary_update_if_primary_starts_first(uptane_repo, secondary, aktualizr, **kwargs):
41  '''Test Secondary update if Secondary is booted after Primary'''
42 
43  # add a new image to the repo in order to update the secondary with it
44  secondary_image_filename = "secondary_image_filename_001.img"
45  secondary_image_hash = uptane_repo.add_image(id=secondary.id, image_filename=secondary_image_filename)
46 
47  logger.debug("Trying to update ECU {} with the image {}".
48  format(secondary.id, (secondary_image_hash, secondary_image_filename)))
49  with secondary:
50  # start secondary, aktualizr has been already started in 'once' mode
51  aktualizr.wait_for_completion()
52 
53  test_result = secondary_image_hash == aktualizr.get_current_image_info(secondary.id)
54  logger.debug("Update result: {}".format("success" if test_result else "failed"))
55  return test_result
56 
57 
58 @with_uptane_backend()
59 @with_secondary(start=False)
60 @with_aktualizr(start=False, output_logs=False)
61 def test_secondary_update(uptane_repo, secondary, aktualizr, **kwargs):
62  '''Test Secondary update if a boot order of Secondary and Primary is undefined'''
63 
64  test_result = True
65  number_of_updates = 1
66  ii = 0
67  while ii < number_of_updates and test_result:
68  # add a new image to the repo in order to update the secondary with it
69  secondary_image_filename = "secondary_image_filename_{}.img".format(ii)
70  secondary_image_hash = uptane_repo.add_image(id=secondary.id, image_filename=secondary_image_filename)
71 
72  logger.debug("Trying to update ECU {} with the image {}".
73  format(secondary.id, (secondary_image_hash, secondary_image_filename)))
74 
75  # start Secondary and Aktualizr processes, aktualizr is started in 'once' mode
76  with secondary, aktualizr:
77  aktualizr.wait_for_completion()
78 
79  test_result = secondary_image_hash == aktualizr.get_current_image_info(secondary.id)
80  logger.debug("Update result: {}".format("success" if test_result else "failed"))
81  ii += 1
82 
83  return test_result
84 
85 @with_treehub()
86 @with_uptane_backend()
87 @with_director()
88 @with_sysroot()
89 @with_secondary(start=False)
90 @with_aktualizr(start=False, run_mode='once', output_logs=True)
91 def test_secondary_ostree_update(uptane_repo, secondary, aktualizr, treehub, sysroot, director, **kwargs):
92  """Test Secondary ostree update if a boot order of Secondary and Primary is undefined"""
93 
94  test_result = True
95  target_rev = treehub.revision
96  uptane_repo.add_ostree_target(secondary.id, target_rev)
97 
98  with secondary:
99  with aktualizr:
100  aktualizr.wait_for_completion()
101 
102  pending_rev = aktualizr.get_current_pending_image_info(secondary.id)
103 
104  if pending_rev != target_rev:
105  logger.error("Pending version {} != the target one {}".format(pending_rev, target_rev))
106  return False
107 
108  sysroot.update_revision(pending_rev)
109  secondary.emulate_reboot()
110 
111  with secondary:
112  with aktualizr:
113  aktualizr.wait_for_completion()
114 
115  installed_rev = aktualizr.get_current_image_info(secondary.id)
116 
117  if installed_rev != target_rev:
118  logger.error("Installed version {} != the target one {}".format(installed_rev, target_rev))
119  return False
120 
121  return director.get_install_result()
122 
123 
124 @with_uptane_backend()
125 @with_secondary(start=False)
126 @with_aktualizr(start=False, output_logs=False, wait_timeout=0.1)
127 def test_primary_timeout_during_first_run(uptane_repo, secondary, aktualizr, **kwargs):
128  """Test Aktualizr's timeout of waiting for Secondaries during initial boot"""
129 
130  secondary_image_filename = "secondary_image_filename_001.img"
131  secondary_image_hash = uptane_repo.add_image(id=secondary.id, image_filename=secondary_image_filename)
132 
133  logger.debug("Checking Aktualizr behaviour if it timeouts while waiting for a connection from the secondary")
134 
135  # just start the aktualizr and expect that it timeouts on waiting for a connection from the secondary
136  # so the secondary is not registered at the device and backend
137  with aktualizr:
138  aktualizr.wait_for_completion()
139 
140  info = aktualizr.get_info()
141  if info is None:
142  return False
143  not_provisioned = 'Provisioned on server: no' in info
144 
145  return not_provisioned and not aktualizr.is_ecu_registered(secondary.id)
146 
147 
148 @with_uptane_backend()
149 @with_secondary(start=False)
150 @with_aktualizr(start=False, output_logs=False)
151 def test_primary_timeout_after_device_is_registered(uptane_repo, secondary, aktualizr, **kwargs):
152  '''Test Aktualizr's timeout of waiting for Secondaries after the device/aktualizr was registered at the backend'''
153 
154  # run aktualizr and secondary and wait until the device/aktualizr is registered
155  with aktualizr, secondary:
156  aktualizr.wait_for_completion()
157 
158  # the secondary must be registered
159  if not aktualizr.is_ecu_registered(secondary.id):
160  return False
161 
162  # make sure that the secondary is not running
163  if secondary.is_running():
164  return False
165 
166  # run just aktualizr, the previously registered secondary is off
167  # and check if the primary ECU is updatable if the secondary is not connected
168  primary_image_filename = "primary_image_filename_001.img"
169  primary_image_hash = uptane_repo.add_image(id=aktualizr.id, image_filename=primary_image_filename)
170 
171  # if a new image for the not-connected secondary is specified in the target
172  # then nothing is going to be updated, including the image intended for
173  # healthy primary ECU
174  # secondary_image_filename = "secondary_image_filename_001.img"
175  # secondary_image_hash = uptane_repo.add_image(id=secondary.id, image_filename=secondary_image_filename)
176 
177  aktualizr.update_wait_timeout(0.1)
178  with aktualizr:
179  aktualizr.wait_for_completion()
180 
181  return (aktualizr.get_current_primary_image_info() == primary_image_hash)\
182  and not aktualizr.is_ecu_registered(secondary.id)
183 
184 
185 # test suit runner
186 if __name__ == '__main__':
187  logging.basicConfig(level=logging.INFO)
188 
189  parser = argparse.ArgumentParser(description='Test IP Secondary')
190  parser.add_argument('-b', '--build-dir', help='build directory', default='build')
191  parser.add_argument('-s', '--src-dir', help='source directory', default='.')
192  parser.add_argument('-o', '--ostree', help='ostree support', default='OFF')
193 
194  input_params = parser.parse_args()
195 
196  KeyStore.base_dir = path.abspath(input_params.src_dir)
197  initial_cwd = getcwd()
198  chdir(input_params.build_dir)
199 
200  test_suite = [
201  test_secondary_update,
202  test_secondary_update_if_secondary_starts_first,
203  test_secondary_update_if_primary_starts_first,
204  test_primary_timeout_during_first_run,
205  test_primary_timeout_after_device_is_registered
206  ]
207 
208  if input_params.ostree == 'ON':
209  test_suite.append(test_secondary_ostree_update)
210 
211  test_suite_run_result = True
212  for test in test_suite:
213  logger.info('>>> Running {}...'.format(test.__name__))
214  test_run_result = test()
215  logger.info('>>> {}: {}\n'.format('OK' if test_run_result else 'FAILED', test.__name__))
216  test_suite_run_result = test_suite_run_result and test_run_result
217 
218  chdir(initial_cwd)
219  exit(0 if test_suite_run_result else 1)