You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

424 rivejä
20 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2010-2016 Mir Calculate. http://www.calculate-linux.org
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import sys
  16. from calculate.core.server.func import Action, Tasks, AllTasks
  17. from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
  18. from calculate.lib.cl_template import TemplatesError
  19. from calculate.lib.utils.binhosts import BinhostError
  20. from calculate.lib.utils.files import FilesError, readFile
  21. from calculate.update.update import UpdateError
  22. from calculate.update.emerge_parser import EmergeError
  23. from calculate.lib.utils.git import GitError
  24. from calculate.lib.utils.portage import (EmergeLog, isPkgInstalled,
  25. EmergeLogNamedTask, PackageList)
  26. from calculate.update.update_tasks import EmergeMark
  27. _ = lambda x: x
  28. setLocalTranslate('cl_update3', sys.modules[__name__])
  29. __ = getLazyLocalTranslate(_)
  30. def get_synchronization_tasks(object_name):
  31. Object = lambda s: "%s.%s"%(object_name, s)
  32. return [
  33. {'name': 'reps_synchronization',
  34. 'group': __("Repositories synchronization"),
  35. 'tasks': [
  36. # создать объект проверки PGP
  37. {'name': 'prepare_gpg',
  38. 'method': Object("prepare_gpg()"),
  39. },
  40. # создать объект хранилище серверов обновлений
  41. {'name': 'create_binhost_data',
  42. 'method': Object('create_binhost_data()')
  43. },
  44. # проверить валиден ли текущий хост
  45. {'name': 'check_current_binhost',
  46. 'message': __("Checking current binhost"),
  47. 'essential': False,
  48. 'method': Object('check_current_binhost(update.cl_update_binhost)'),
  49. 'condition': lambda GetBool, Get: (
  50. not GetBool('update.cl_update_binhost_recheck_set') and
  51. Get('update.cl_update_sync_rep') and
  52. Get('update.cl_update_binhost'))
  53. },
  54. {'name': 'not_use_search:failed_base_binhost',
  55. 'error': __("Failed to use base binhost"),
  56. 'depend': AllTasks.failed_all("check_current_binhost")
  57. },
  58. {'name': 'group_find_binhost',
  59. 'group': '',
  60. 'while': (~AllTasks.has_any("detect_best_binhost") &
  61. ((AllTasks.failed_all("update_packages_cache")
  62. & ~AllTasks.has_any("not_use_search")) |
  63. ~AllTasks.has_any("sync_reps"))) & Tasks.success(),
  64. 'condition': lambda GetBool, Get: (GetBool('update.cl_update_usetag_set') and
  65. Get('update.cl_update_sync_rep')),
  66. 'tasks': [
  67. # найти лучший сервер обновлений
  68. {'name': 'detect_best_binhost',
  69. 'method': Object('detect_best_binhost()'),
  70. 'essential': False,
  71. 'depend': (Tasks.success() & ~AllTasks.has_any("not_use_search") &
  72. (~AllTasks.success_one_of("check_current_binhost") |
  73. AllTasks.success_all("sync_reps"))),
  74. },
  75. # запасная синхронизация, в ходе которой ветки обновляются до
  76. # master
  77. {'name': 'sync_reps_fallback',
  78. 'foreach': 'update.cl_update_sync_rep',
  79. 'message':
  80. __("Fallback syncing the {eachvar:capitalize} repository"),
  81. 'method': Object('syncRepositories(eachvar,True)'),
  82. 'depend': Tasks.success() & AllTasks.failed_one_of("detect_best_binhost"),
  83. },
  84. # обновление переменных информации из binhost
  85. {'name': 'sync_reps_fallback:update_binhost_list',
  86. 'method': Object('update_binhost_list()'),
  87. 'depend': Tasks.success() & AllTasks.failed_one_of("detect_best_binhost"),
  88. },
  89. # найти лучший сервер обновлений
  90. {'name': 'sync_reps_fallback:detect_best_binhost',
  91. 'method': Object('detect_best_binhost()'),
  92. 'depend': Tasks.success() & AllTasks.failed_one_of("detect_best_binhost"),
  93. },
  94. {'name': 'sync_reps',
  95. 'foreach': 'update.cl_update_sync_rep',
  96. 'message': __("Checking {eachvar:capitalize} updates"),
  97. 'method': Object('syncRepositories(eachvar)'),
  98. 'condition': lambda Get: Get('update.cl_update_sync_rep'),
  99. 'depend': Tasks.success() & ~AllTasks.success_all("update_packages_cache")
  100. },
  101. {'name': 'sync_reps:update_local_info_binhost',
  102. 'method': Object('update_local_info_binhost()'),
  103. },
  104. {'name': 'sync_reps:update_binhost_list',
  105. 'essential': False,
  106. 'method': Object('update_binhost_list()'),
  107. 'condition': lambda GetBool: GetBool('update.cl_update_outdate_set')
  108. },
  109. {'name': 'sync_reps:update_packages_cache',
  110. 'message': __("Update packages index"),
  111. 'method': Object('download_packages(update.cl_update_portage_binhost,'
  112. 'update.cl_update_package_cache,update.cl_update_package_cache_sign,'
  113. 'update.cl_update_gpg)'),
  114. 'essential': False,
  115. 'condition': lambda Get, GetBool: (
  116. Get('update.cl_update_package_cache') and (
  117. Get('update.cl_update_outdate_set') == 'on' or
  118. Get('update.cl_update_package_cache_set') == 'on'))
  119. },
  120. ],
  121. },
  122. {'name': 'no_server',
  123. 'error': __("Failed to find the binary updates server"),
  124. 'method': Object("delete_binhost()"),
  125. # method: который должен удалить текущую информацию о сервере обновлений
  126. 'depend': (Tasks.failed() |
  127. Tasks.success() & AllTasks.failed_one_of("update_packages_cache")),
  128. 'condition': lambda GetBool, Get: (GetBool('update.cl_update_usetag_set') and
  129. Get('update.cl_update_sync_rep')),
  130. },
  131. {'name': 'sync_reps',
  132. 'foreach': 'update.cl_update_sync_rep',
  133. 'message': __("Checking {eachvar:capitalize} updates"),
  134. 'method': Object('syncRepositories(eachvar)'),
  135. 'condition': lambda Get, GetBool: (Get('update.cl_update_sync_rep') and
  136. not GetBool('update.cl_update_usetag_set')),
  137. },
  138. {'name': 'update_layman',
  139. 'message': __("Layman cache update"),
  140. 'method': Object('update_layman()'),
  141. 'condition': lambda Get: isPkgInstalled(
  142. "app-portage/layman", prefix=Get('cl_chroot_path')),
  143. 'essential': False,
  144. },
  145. {'name': 'sync_other_reps',
  146. 'foreach': 'update.cl_update_other_rep_name',
  147. 'message': __("Syncing the {eachvar:capitalize} repository"),
  148. 'method': Object('syncLaymanRepository(eachvar)'),
  149. 'condition': lambda Get: Get('update.cl_update_other_set') == 'on'
  150. },
  151. {'name': 'trim_reps',
  152. 'foreach': 'update.cl_update_sync_rep',
  153. 'message': __("Cleaning the history of the "
  154. "{eachvar:capitalize} repository"),
  155. 'method': Object('trimRepositories(eachvar)'),
  156. 'condition': lambda Get: (Get('update.cl_update_sync_rep') and
  157. Get('update.cl_update_onedepth_set') == 'on')
  158. },
  159. {'name': 'sync_reps:regen_cache',
  160. 'foreach': 'update.cl_update_sync_overlay_rep',
  161. 'essential': False,
  162. 'method': Object('regenCache(eachvar)'),
  163. 'condition': (
  164. lambda Get: (Get('update.cl_update_outdate_set') == 'on' and
  165. Get('update.cl_update_egencache_force') != 'skip' or
  166. Get('update.cl_update_egencache_force') == 'force'))
  167. },
  168. {'name': 'sync_other_reps:regen_other_cache',
  169. 'foreach': 'update.cl_update_other_rep_name',
  170. 'method': Object('regenCache(eachvar)'),
  171. 'essential': False,
  172. },
  173. {'name': 'eix_update',
  174. 'message': __("Updating the eix cache for "
  175. "{update.cl_update_eix_repositories}"),
  176. 'method': Object('eixUpdate(cl_repository_name)'),
  177. 'condition': (
  178. lambda Get: (Get('update.cl_update_outdate_set') == 'on' and
  179. Get('update.cl_update_eixupdate_force') != 'skip' or
  180. Get('update.cl_update_eixupdate_force') == 'force'))
  181. },
  182. {'name': 'update_setup_cache',
  183. 'message': __("Updating the cache of configurable packages"),
  184. 'method': Object('updateSetupCache()'),
  185. 'essential': False,
  186. 'condition': lambda Get: Get('update.cl_update_outdate_set') == 'on'
  187. },
  188. {'name': 'sync_reps:cleanpkg',
  189. 'message': __("Removing obsolete distfiles and binary packages"),
  190. 'method': Object('Update.cleanpkg()'),
  191. 'condition': (
  192. lambda Get: Get('update.cl_update_cleanpkg_set') == 'on' and
  193. Get('update.cl_update_outdate_set') == 'on'),
  194. 'essential': False
  195. },
  196. # сообщение удачного завершения при обновлении репозиториев
  197. {'name': 'success_syncrep',
  198. 'message': __("Synchronization finished"),
  199. 'depend': (Tasks.success() & Tasks.has_any("sync_reps",
  200. "sync_other_reps",
  201. "emerge_metadata",
  202. "eix_update")),
  203. }
  204. ]
  205. },
  206. ]
  207. class UpdateConditions(object):
  208. @staticmethod
  209. def was_installed(pkg, task_name):
  210. def func():
  211. task = EmergeLog(EmergeLogNamedTask(task_name))
  212. return bool(PackageList(task.list)[pkg])
  213. return func
  214. @staticmethod
  215. def need_depclean(pkg, task_name):
  216. def func(Get):
  217. task = EmergeLog(EmergeLogNamedTask(task_name))
  218. return (bool(PackageList(task.list)[pkg])
  219. or Get('cl_update_force_depclean_set') == 'on'
  220. or Get('cl_update_outdated_kernel_set') == 'on')
  221. return func
  222. @staticmethod
  223. def force_preserved(Get):
  224. pfile = "/var/lib/portage/preserved_libs_registry"
  225. content = readFile(pfile).strip()
  226. if not content or content[1:-1].strip() == '':
  227. return False
  228. else:
  229. return True
  230. class ClUpdateAction(Action):
  231. """
  232. Действие обновление конфигурационных файлов
  233. """
  234. # ошибки, которые отображаются без подробностей
  235. native_error = (FilesError, UpdateError,
  236. TemplatesError, BinhostError,
  237. GitError, EmergeError)
  238. successMessage = None
  239. failedMessage = None
  240. interruptMessage = __("Update manually interrupted")
  241. emerge_tasks = [
  242. {'name': 'save_bdeps_val',
  243. 'method': 'Update.save_with_bdeps()',
  244. 'essential': False
  245. },
  246. {'name': 'premerge_group',
  247. 'group': __("Checking for updates"),
  248. 'tasks': [
  249. {'name': 'premerge',
  250. 'message': __("Calculating dependencies"),
  251. 'method': 'Update.premerge("-uDN","@world")',
  252. 'condition': lambda Get: (
  253. Get('cl_update_sync_only_set') == 'off' and
  254. Get('cl_update_pretend_set') == 'on')
  255. }],
  256. },
  257. {'name': 'update',
  258. 'condition': lambda Get:Get('cl_update_pretend_set') == 'off',
  259. },
  260. {'name': 'update_other',
  261. 'condition': lambda Get: ( Get('cl_update_pretend_set') == 'off' and
  262. Get('cl_update_sync_only_set') == 'off')
  263. },
  264. {'name': 'update:update_world',
  265. 'group': __("Updating packages"),
  266. 'tasks': [
  267. {'name': 'update_world',
  268. 'message': __("Calculating dependencies"),
  269. 'method': 'Update.emerge_ask(cl_update_pretend_set,'
  270. '"-uDN","@world")',
  271. }
  272. ],
  273. 'condition': lambda Get: Get('cl_update_sync_only_set') == 'off'
  274. },
  275. {'name': 'update_other:update_perl',
  276. 'group': __("Updating Perl"),
  277. 'tasks': [
  278. {'name': 'update_other:perl_cleaner',
  279. 'message': __('Find & rebuild packages and Perl header files '
  280. 'broken due to a perl upgrade'),
  281. 'method': 'Update.emergelike("perl-cleaner", "all")',
  282. 'condition': UpdateConditions.was_installed(
  283. 'dev-lang/perl$', EmergeMark.PerlCleaner),
  284. 'decoration': 'Update.update_task("%s")' % EmergeMark.PerlCleaner
  285. },
  286. ]
  287. },
  288. {'name': 'update_other:depclean',
  289. 'group': __("Cleaning the system from needless packages"),
  290. 'tasks': [
  291. {'name': 'update_other:update_depclean',
  292. 'message': __("Calculating dependencies"),
  293. 'method': 'Update.depclean()',
  294. 'condition': UpdateConditions.need_depclean(
  295. '.*', EmergeMark.Depclean),
  296. 'decoration': 'Update.update_task("%s")' % EmergeMark.Depclean
  297. },
  298. ]
  299. },
  300. {'name': 'update_other:update_modules',
  301. 'group': __("Rebuilding dependent modules"),
  302. 'tasks': [
  303. {'name': 'update_other:module_rebuild',
  304. 'message': __('Updating Kernel modules'),
  305. 'method': 'Update.emerge("","@module-rebuild")',
  306. 'condition': UpdateConditions.was_installed(
  307. 'sys-kernel/.*source', EmergeMark.KernelModules),
  308. 'decoration': 'Update.update_task("%s")' %
  309. EmergeMark.KernelModules
  310. },
  311. {'name': 'update_other:x11_module_rebuild',
  312. 'message': __('Updating X.Org server modules'),
  313. 'method': 'Update.emerge("","@x11-module-rebuild")',
  314. 'condition': UpdateConditions.was_installed(
  315. 'x11-base/xorg-server', EmergeMark.XorgModules),
  316. 'decoration': 'Update.update_task("%s")' %
  317. EmergeMark.XorgModules
  318. },
  319. {'name': 'update_other:preserved_rebuild',
  320. 'message': __('Updating preserved libraries'),
  321. 'method': 'Update.emerge("","@preserved-rebuild")',
  322. 'condition': lambda Get: (UpdateConditions.was_installed(
  323. '.*', EmergeMark.PreservedLibs)() or
  324. UpdateConditions.force_preserved(Get)),
  325. 'decoration': 'Update.update_task("%s")' %
  326. EmergeMark.PreservedLibs
  327. },
  328. {'name': 'update_other:revdev_rebuild',
  329. 'message': __('Checking reverse dependencies'),
  330. 'method': 'Update.revdep_rebuild("revdep-rebuild")',
  331. 'condition': lambda Get: (Get(
  332. 'cl_update_skip_rb_set') == 'off' and
  333. UpdateConditions.was_installed(
  334. '.*', EmergeMark.RevdepRebuild)()),
  335. 'decoration': 'Update.update_task("%s")' %
  336. EmergeMark.RevdepRebuild
  337. },
  338. {'name': 'update_other:dispatch_conf_end',
  339. 'message': __("Updating configuration files"),
  340. 'method': 'Update.dispatchConf()',
  341. 'condition': lambda Get: (Get('cl_dispatch_conf') != 'skip' and
  342. Get('cl_update_pretend_set') == 'off')
  343. },
  344. ]
  345. },
  346. {'name': 'update:set_upto_date_cache',
  347. 'method': 'Update.setUpToDateCache()'
  348. }
  349. ]
  350. # список задач для действия
  351. tasks = [
  352. {'name': 'check_schedule',
  353. 'method': 'Update.checkSchedule(cl_update_autocheck_interval,'
  354. 'cl_update_autocheck_set)',
  355. 'condition': lambda Get: (
  356. Get('cl_update_autocheck_schedule_set') == 'on'),
  357. },
  358. {'name': 'check_run',
  359. 'method': 'Update.checkRun(cl_update_wait_another_set)'
  360. },
  361. ] + get_synchronization_tasks("Update") + [
  362. {'name': 'system_configuration',
  363. 'group': __("System configuration"),
  364. 'tasks': [
  365. {'name': 'revision',
  366. 'message': __("Fixing the settings"),
  367. 'method': 'Update.applyTemplates(install.cl_source,'
  368. 'cl_template_clt_set,True,None,False)',
  369. 'condition': lambda Get: (Get('cl_templates_locate') and
  370. (Get('cl_update_world') != "update" or
  371. Get('cl_update_outdate_set') == 'on' or
  372. Get('cl_update_binhost_recheck_set') == 'on' or
  373. Get('cl_update_force_fix_set') == 'on'))
  374. },
  375. {'name': 'dispatch_conf',
  376. 'message': __("Updating configuration files"),
  377. 'method': 'Update.dispatchConf()',
  378. 'condition': lambda Get: (Get('cl_dispatch_conf') != 'skip' and
  379. Get('cl_update_pretend_set') == 'off' and
  380. (Get('cl_update_binhost_recheck_set') == 'on' or
  381. Get('cl_update_outdate_set') == 'on' or
  382. Get('cl_update_force_fix_set') == 'on'))
  383. },
  384. {'name': 'binhost_changed',
  385. 'method': 'Update.message_binhost_changed()'
  386. },
  387. ]
  388. }
  389. ] + emerge_tasks + [
  390. {'name': 'failed',
  391. 'error': __("Update failed"),
  392. 'depend': (Tasks.failed() & Tasks.hasnot("interrupt") &
  393. (Tasks.hasnot("check_schedule") |
  394. Tasks.success_all("check_schedule")))},
  395. {'name': 'failed',
  396. 'depend': Tasks.failed_all("check_schedule")
  397. },
  398. # сообщение удачного завершения при обновлении ревизии
  399. {'name': 'success_rev',
  400. 'message': __("System update finished!"),
  401. 'condition': lambda Get: (Get('cl_update_rev_set') == 'on' and
  402. Get('cl_update_pretend_set') == 'off')
  403. },
  404. # сообщение удачного завершения при пересоздании world
  405. {'name': 'success_world',
  406. 'message': __("World rebuild finished!"),
  407. 'condition': lambda Get: Get('cl_rebuild_world_set') == 'on'
  408. },
  409. ]