preupg.sh.skel 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. #!/bin/bash
  2. #
  3. # preupgrade-assistant testing utilities
  4. #
  5. # This ASRT module contains various functions to support testing of
  6. # preupgrade-assistant and its modules. Refer to specific functions
  7. # for details.
  8. #
  9. shellfu import dist
  10. shellfu import jat_dump
  11. shellfu import preupg_fupath
  12. shellfu import pxpath
  13. #
  14. # Default rule id (XCCDF) to parse data from
  15. #
  16. PREUPG__RULE=${PREUPG__RULE:-}
  17. #
  18. # Regex to filter rules (XCCDF ids) to only run by preupg__run1()
  19. #
  20. PREUPG__RULE_REGEX=${PREUPG__RULE_REGEX:-.}
  21. #
  22. # Upgrade path
  23. #
  24. # This can be one of following:
  25. #
  26. # * To test with packaged upgrade paths, set this to the module
  27. # package suffix, e.g. el6toel7.
  28. #
  29. # * To test with own generated upgrade path, set this to path
  30. # to 'all-xccdf.xml' in the root of the upgrade path tree.
  31. #
  32. # * You can also use '@BUILTIN' alias to test with quick&trivial
  33. # upgrade path, e.g. '@pass' to test with an upgrade path that
  34. # simply passes. For details in built-in paths, see
  35. # `library(preupgrade-assistant/fupath)`
  36. #
  37. PREUPG__UPATH=${PREUPG__UPATH:-el6toel7}
  38. #
  39. # Valid exit statuses from preupg (ES_EX syntax)
  40. #
  41. # preupg__run1() will raise test failure if exit status does not
  42. # match this expression. Format is described in jat documentation.
  43. # (See `sfdoc jat`.)
  44. #
  45. PREUPG__VALID_ES=${PREUPG__VALID_ES:-0-2}
  46. # FIXME: ^^^ Holy mess; see http://post-office.corp.redhat.com/archives/rhel-inplaceupgrades/2016-September/msg00011.html
  47. #
  48. # Override what packages are considered as native
  49. #
  50. # See preupg__run1() for details.
  51. #
  52. PREUPG__DISTNATIVE=${PREUPG__DISTNATIVE:-}
  53. #
  54. # Strip control characters from preupg stdout
  55. #
  56. # When TESTOUT.log et al. are acccessed using browsers, the control
  57. # characters in preupg will make many browsers treat the file as
  58. # binary, i.e. offer download instead of opening it.
  59. #
  60. # Set this variable to 'false' to keep the output verbatim.
  61. #
  62. PREUPG__STRIPCTL=${PREUPG__STRIPCTL:-true}
  63. preupg__assert() {
  64. #
  65. # Assert value of rule (module) result property
  66. #
  67. # Usage:
  68. # preupg__assert [-r RULE] [-N] FLD VALUE [[-N] FLD VALUE]
  69. #
  70. # In order for assert to pass, FLD must match VALUE. If -N is passed,
  71. # the meaning of assert is reversed, i.e. assert will fail if condition
  72. # is satisfied. Passing multiple pairs of FLD and VALUE performs
  73. # multiple independent asserts with the added value of better log
  74. # readability.
  75. #
  76. # For numeric fields, VALUE is matched for numeric equality. For string
  77. # fields, VALUE is matched as Basic Regular Expression.
  78. #
  79. # FLD can be:
  80. #
  81. # risk - risk
  82. # risk.slight - slight risk
  83. # risk.medium - medium risk
  84. # risk.high - high risk
  85. # risk.extreme - extreme risk
  86. # riskn - number of risks
  87. # riskn.slight - number of slight risks
  88. # riskn.medium - number of medium risks
  89. # riskn.high - number of high risks
  90. # riskn.extreme - number of extreme risks
  91. # msg - message
  92. # msg.debug - debug message
  93. # msg.info - info message
  94. # msg.warning - warning message
  95. # msg.error - error message
  96. # msgn - number of messages
  97. # msgn.debug - number of debug messages
  98. # msgn.info - number of info messages
  99. # msgn.warning - number of warning messages
  100. # msgn.error - number of error messages
  101. # solution - solution text
  102. # result - module result
  103. #
  104. # By default, rule $PREUPG__RULE is queried, but you can
  105. # override that using -r argument. (It's mandatory to use at least one
  106. # of these methods.)
  107. #
  108. local code
  109. local usage="usage: preupg__assert [-r RULE] [-N] FLD VALUE [[-N] FLD VALUE].."
  110. local Rule=$PREUPG__RULE
  111. local conds=()
  112. local Ellipsis=false
  113. local cond
  114. while true; do case $1 in
  115. -r|--rule) Rule=$2; shift 2 || { jat__log_error "$usage"; return 2; } ;;
  116. *) break ;;
  117. esac done
  118. test -n "$Rule" || {
  119. jat__log_error "which rule to assert? set \$PREUPG__RULE or use -r|--rule argument"
  120. return 2
  121. }
  122. while true; do case $1 in
  123. "")
  124. break
  125. ;;
  126. -N)
  127. conds+=("neg:${2,,}:$3")
  128. shift 3 || {
  129. jat__log_error "$usage"
  130. return 2
  131. }
  132. ;;
  133. *)
  134. conds+=("pos:${1,,}:$2")
  135. shift 2 || {
  136. jat__log_error "$usage"
  137. return 2
  138. }
  139. ;;
  140. esac done
  141. case ${#conds[@]} in
  142. 0)
  143. jat__log_error "$usage"
  144. return 2
  145. ;;
  146. 1)
  147. __preupg__assert1 "${conds[0]}"
  148. return $?
  149. ;;
  150. *)
  151. jat__log_info "rule $Rule has:"
  152. for cond in "${conds[@]}";
  153. do
  154. Ellipsis=true __preupg__assert1 "$cond"
  155. done
  156. ;;
  157. esac
  158. }
  159. preupg__dump_node() {
  160. #
  161. # Dump node of $PREUPG__RULE
  162. #
  163. preupg__get_node \
  164. | jat_dump__pipe "NODE-${PREUPG__RULE}"
  165. }
  166. preupg__get_fixtext() {
  167. #
  168. # Get solution text (fixtext) of rule id $PREUPG__RULE
  169. #
  170. __preupg__resultxpath \
  171. "//ns0:Rule[@id='$PREUPG__RULE']/ns0:fixtext/text()"
  172. }
  173. preupg__get_node() {
  174. #
  175. # Get whole result node from rule $PREUPG__RULE
  176. #
  177. __preupg__resultxpath \
  178. "//ns0:rule-result[@idref='$PREUPG__RULE']"
  179. }
  180. preupg__get_result() {
  181. #
  182. # Get 'result' field from rule $PREUPG__RULE
  183. #
  184. __preupg__resultxpath \
  185. "//ns0:rule-result[@idref='$PREUPG__RULE']/ns0:result/text()"
  186. }
  187. preupg__get_risks() {
  188. #
  189. # Get risks of severity $1 or all
  190. #
  191. # 'preupg.risk.' prefix is removed. If severity is given, get only those
  192. # risks and also that part of prefix is removed.
  193. #
  194. # For example,
  195. #
  196. # $ PREUPG__RULE=xccdf_blah
  197. # $ preupg__get_risks
  198. # HIGH: foo
  199. # MEDIUM: bar
  200. # MEDIUM: baz
  201. # $ preupg__get_risks HIGH
  202. # foo
  203. # $
  204. #
  205. local sev=${1^^}
  206. local outfn=preupg__get_stderr
  207. $__PREUPG__LOSCAP \
  208. && outfn=preupg__get_stdout
  209. case $sev in
  210. "")
  211. $outfn \
  212. | grep -E '^preupg\.risk\.(SLIGHT|MEDIUM|HIGH|EXTREME): ' \
  213. | cut -d. -f3-
  214. ;;
  215. SLIGHT|MEDIUM|HIGH|EXTREME)
  216. $outfn \
  217. | grep -E "^preupg\.risk\.$sev: " \
  218. | cut -d. -f3-
  219. ;;
  220. *)
  221. jat__log_error "unknown risk severity: $sev"
  222. return 2
  223. ;;
  224. esac
  225. }
  226. preupg__get_messages() {
  227. #
  228. # Get log messages of severity $1 or all
  229. #
  230. # 'preupg.log.' prefix is removed. If severity is given, get only those
  231. # messages and also that part of prefix is removed.
  232. #
  233. # For example,
  234. #
  235. # $ PREUPG__RULE=xccdf_blah
  236. # $ preupg__get_messages
  237. # INFO: hello
  238. # INFO: Joe
  239. # DEBUG: lalala lalalala
  240. # $ preupg__get_messages DEBUG
  241. # lalala lalalala
  242. # $
  243. #
  244. local sev=${1^^}
  245. local outfn=preupg__get_stderr
  246. $__PREUPG__LOSCAP \
  247. && outfn=preupg__get_stdout
  248. case $sev in
  249. "")
  250. $outfn \
  251. | grep -E '^preupg\.log\.(ERROR|WARNING|INFO|DEBUG): ' \
  252. | cut -d. -f3-
  253. ;;
  254. ERROR|WARNING|INFO|DEBUG)
  255. $outfn \
  256. | grep -E "^preupg\.log\.$sev: " \
  257. | cut -d. -f3-
  258. ;;
  259. *)
  260. jat__log_error "unknown log message severity: $sev"
  261. return 2
  262. ;;
  263. esac
  264. }
  265. preupg__get_stdout() {
  266. #
  267. # Get stdout of rule $PREUPG__RULE (eg. for grepping risks)
  268. #
  269. __preupg__resultxpath \
  270. "//ns0:rule-result[@idref='$PREUPG__RULE']/ns0:check/ns0:check-import[@import-name='stdout']/text()"
  271. }
  272. preupg__get_stderr() {
  273. #
  274. # Get stderr of rule $PREUPG__RULE (eg. for grepping risks)
  275. #
  276. preupg__haslim loscap
  277. __preupg__resultxpath \
  278. "//ns0:rule-result[@idref='$PREUPG__RULE']/ns0:check/ns0:check-import[@import-name='stderr']/text()"
  279. }
  280. preupg__collect_stderrs() {
  281. #
  282. # Collect stderrs of all rules, prefix by rule id
  283. #
  284. local ruleid
  285. preupg__haslim loscap
  286. __preupg__lsrules_xml \
  287. | while read -r ruleid;
  288. do
  289. __preupg__resultxpath \
  290. "//ns0:rule-result[@idref='$ruleid']/ns0:check/ns0:check-import[@import-name='stderr']/text()" \
  291. | sed -e "s/^/$ruleid: /"
  292. done
  293. }
  294. preupg__collect_stray() {
  295. #
  296. # Collect stray outputs (ie. not risks or log messages), prefix by rule id
  297. #
  298. local tmp
  299. local ruleid
  300. preupg__haslim loscap && {
  301. __preupg__collect_stray_loscap
  302. return $?
  303. }
  304. tmp=$(mktemp -td preupg__collect_stray.XXXXXXXX)
  305. pushd "$tmp" >/dev/null
  306. __preupg__lsrules_xml \
  307. | while read -r ruleid;
  308. do
  309. __preupg__resultxpath \
  310. "//ns0:rule-result[@idref='$ruleid']/ns0:check/ns0:check-import[@import-name='stdout']/text()" \
  311. >"stdout"
  312. __preupg__resultxpath \
  313. "//ns0:rule-result[@idref='$ruleid']/ns0:check/ns0:check-import[@import-name='stderr']/text()" \
  314. >"stderr"
  315. test -s "stdout" && sed -e "s/^/$ruleid:stdout: /" "stdout"
  316. test -s "stderr" || continue
  317. <"stderr" grep -v -E \
  318. -e '^preupg\.log\.(ERROR|WARNING|INFO|DEBUG): ' \
  319. -e '^preupg\.risk\.(SLIGHT|MEDIUM|HIGH|EXTREME): ' \
  320. > "stderr.stray"
  321. grep -q . "stderr.stray" || continue
  322. sed -e "s/^/$ruleid:stderr: /" <"stderr.stray"
  323. done
  324. popd >/dev/null
  325. rm -r "$tmp"
  326. }
  327. preupg__lsrules_ast() {
  328. #
  329. # List selected rules from last asssessment result
  330. #
  331. __preupg__lsrules_xml
  332. }
  333. preupg__rmresult() {
  334. #
  335. # Remove assessment results
  336. #
  337. # Keeps cache and logs; use preupg__Cleanup() to clean
  338. # up after test.
  339. #
  340. jat__cmd rm -rf /root/preupgrade
  341. jat__cmd rm -rf /root/preupgrade-results
  342. }
  343. preupg__Run1() {
  344. #
  345. # Create phase and just run preupg__run1 $@
  346. #
  347. # Wrapper around preupg__run1() with phase creation.
  348. # Call this before starting case loop such as xcase__run(),
  349. # where you would try out multiple cache-independent cases.
  350. #
  351. jat__pstarts "run preupg once"
  352. preupg__run1 "$@"
  353. jat__pend
  354. }
  355. preupg__Cleanup() {
  356. #
  357. # Create final cleanup phase (submit & full cleanup)
  358. #
  359. # If results (tarball) are found, jat__submit() them (tarball and
  360. # html and xml). Finally clean up results, logs and cache.
  361. #
  362. # Pass -n to skip submitting of the results.
  363. #
  364. local submit=true
  365. test "x$1" == "-n" && submit=false
  366. jat__pstartc
  367. # we assume that if tarball exists, html and xml both exist
  368. # as well.
  369. if $submit \
  370. && test -n "$(preupg__get_latest_tar)";
  371. then
  372. jat__submit "/root/preupgrade/result.html" "result.html"
  373. jat__submit "/root/preupgrade/result.xml" "result.xml"
  374. jat__submit "$(preupg__get_latest_tar)"
  375. fi
  376. preupg__rmresult
  377. jat__pend
  378. }
  379. preupg__run1() {
  380. #
  381. # Run preupg once without interaction; pass $@ down
  382. #
  383. # Runs preupg with --force argument (to suppress questions) and performs
  384. # additional checks on assessment. Any arguments to this function are
  385. # simply passed down to the preupg call (after any arguments needed
  386. # for overrides, see below).
  387. #
  388. # Exit status is normally same as exit status from preupg, but statuses
  389. # defined in $PREUPG__VALID_ES don't cause assert fail
  390. # (these normally represent upgrade risk level so are considered "normal").
  391. # However, if additional checks done by this routine fail, exit status
  392. # is increased by 100.
  393. #
  394. # Several overrides can be specified via following global
  395. # variables:
  396. #
  397. # * If $PREUPG__RULE_REGEX was specified, modules
  398. # are selected using that regular expression and passed down
  399. # using --select-rules parameter.
  400. #
  401. # * If $PREUPG__DISTNATIVE is specified, preupg config
  402. # is altered for this run to override what packages are treated
  403. # as native. The variable may have following values:
  404. #
  405. # * `sign` - packages signed by vendor (default preupg behavior)
  406. # * `all` - all installed packages
  407. # * `-NAME1[,-NAME2,..]` - all currently installed packages
  408. # except NAME1, NAME2 and so on
  409. # * `/path/to/list` - only packages listed in the file (names)
  410. #
  411. # * If $PREUPG__UPATH points to path to all-xccdf.xml,
  412. # or has form of built-in fake path (`@*`) custom upgrade path is
  413. # used. (see `$PREUPG__UPATH` for details`)
  414. #
  415. # Note that these overrides only affect the single run; i.e. runs
  416. # outside this function work normally, and you can change mentioned
  417. # variables between run.
  418. #
  419. jat__log_info "PREUPG__UPATH='$PREUPG__UPATH'"
  420. jat__log_info "PREUPG__RULE_REGEX='$PREUPG__RULE_REGEX'"
  421. jat__log_info "PREUPG__DISTNATIVE='$PREUPG__DISTNATIVE'"
  422. local es=0 # exit status
  423. local run1tmp # our temporary dir
  424. run1tmp="$(mktemp -d -t preupg__run1.XXXXXXXX)"
  425. __preupg__mkfupath_builtin
  426. __preupg__dno_enable
  427. case "$PREUPG__RULE_REGEX" in
  428. .|"") __preupg__preupg "$@"
  429. es=$?
  430. ;;
  431. *) __preupg__preupg \
  432. --select-rules "$(__preupg__lsrules_upath | paste -sd,)" \
  433. "$@"
  434. es=$?
  435. ;;
  436. esac
  437. __preupg__dno_disable
  438. rm -r "$run1tmp"
  439. # Additional checks
  440. if preupg__collect_stray | grep -q .;
  441. then
  442. jat__fail "stray module output found"
  443. preupg__collect_stray \
  444. | jat_dump__pipe -E STRAY_OUTPUT
  445. es=$((100 + es))
  446. fi
  447. return $es
  448. }
  449. preupg__get_latest_tar() {
  450. #
  451. # Print path to latest tarball; false if there was none
  452. #
  453. test -d /root/preupgrade-results || {
  454. warn "no result found; has preupg been run?"
  455. return 3
  456. }
  457. find /root/preupgrade-results \
  458. -name "preupg_results-*.tar.gz" \
  459. | sort -n \
  460. | tail -1 \
  461. | grep . # grep to normalize exit status
  462. }
  463. preupg__tar_extract() {
  464. #
  465. # Extract last tarball and print path to the extracted directory
  466. #
  467. local tarball_path
  468. local dirname
  469. tarball_path=$(preupg__get_latest_tar)
  470. dirname=${tarball_path##*/}
  471. dirname=${dirname%.tar.gz}
  472. {
  473. jat__cmd -h "tarball found" \
  474. test -n "$tarball_path" \
  475. || return 3
  476. jat__cmd -h "tarball extracted" \
  477. tar -xzf "$tarball_path" \
  478. || return 3
  479. jat__cmd -h "directory present" \
  480. test -d "$dirname" \
  481. || return 3
  482. } >&2
  483. echo "$dirname"
  484. }
  485. preupg__tar_list() {
  486. #
  487. # Print contents of latest tarball
  488. #
  489. local tarball_path
  490. local dirname
  491. tarball_path=$(preupg__get_latest_tar) || return 3
  492. {
  493. jat__cmd -h "tarball found" \
  494. test -n "$tarball_path" \
  495. || return 3
  496. jat__cmd -h "tarball listable" \
  497. tar -tzf "$tarball_path" \
  498. || return 3
  499. } >&2
  500. tar -tzf "$tarball_path"
  501. }
  502. __preupg__shellfu_init__() {
  503. #
  504. # Inialization check hook (called by shellfu)
  505. #
  506. dist__test ver vlt '6.9' && {
  507. jat__log_warning \
  508. "=============================================================" \
  509. " : Old buggy version of OpenSCAP is in use: :" \
  510. " : :" \
  511. " : $(rpm -q openscap) :" \
  512. " : :" \
  513. " : This means that capabilities of this test library will :" \
  514. " : be limited, because stderr from module scripts will be :" \
  515. " : always reported as empty, while its content will be :" \
  516. " : into stdout. :" \
  517. " : :" \
  518. " : See https://bugzilla.redhat.com/show_bug.cgi?id=1309491 :" \
  519. "============================================================="
  520. __PREUPG__LOSCAP=true
  521. }
  522. case "$PREUPG__UPATH" in
  523. el5toel7|el6toel7) true ;;
  524. */all-xccdf.xml) true ;;
  525. @*) true ;;
  526. *) jat__log_error \
  527. "unknown upgrade path: $PREUPG__UPATH" ;;
  528. esac
  529. }
  530. preupg__haslim() {
  531. #
  532. # True and emit warn test reader if limitation $1 is in place
  533. #
  534. # Usage:
  535. #
  536. # preupg__haslim LIM [EFFECT]
  537. #
  538. # If limitation LIM is in place, print warning and exit with zero
  539. # otherwise exit with one if LIM is not in place and 2 if LIM is not
  540. # known.
  541. #
  542. # Warning will mention calling function and describe limitation in
  543. # general; you can provide simple EFFECT (few words) to describe
  544. # how the limitation affects the particular test context.
  545. #
  546. # Known LIMs are:
  547. #
  548. # * `loscap` - legacy OpenSCAP: module stderr is merged into its
  549. # stdout.
  550. #
  551. local limitation=$1
  552. local effect=$2
  553. local parent=${FUNCNAME[1]}
  554. case $limitation in
  555. loscap) # legacy openscap
  556. $__PREUPG__LOSCAP || return 1
  557. test -n "$effect" || effect="see bz1309491"
  558. jat__log_warning "$parent(): old openscap is in use; $effect"
  559. return 0
  560. ;;
  561. esac
  562. jat__log_error "invalid limitation: $limitation"
  563. return 2
  564. }
  565. # # there is something wrong with this world #
  566. # INTERNAL # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
  567. # # by crossing this line you are making it stronger #
  568. #
  569. # Have we touched preupg conf already?
  570. #
  571. __PREUPG__CFG_DIRTY=${__PREUPG__CFG_DIRTY:-false}
  572. #
  573. # True if we should work with legacy openscap
  574. #
  575. # Old openscap (pre openscap-1.2.13-2.el6) merges stderr into stdout so we need
  576. # to alter risk filtering.
  577. #
  578. __PREUPG__LOSCAP=false
  579. __preupg__preupg() {
  580. #
  581. # Run preupg with --force, maybe --contents and maybe other args
  582. #
  583. local args=()
  584. local hints=()
  585. local es=0
  586. local valid_es=$PREUPG__VALID_ES
  587. args+=(--force)
  588. case $PREUPG__UPATH in
  589. */*)
  590. args+=(--contents "$PREUPG__UPATH")
  591. hints+=(" (custom content set)")
  592. ;;
  593. @*)
  594. args+=(--contents "$(<"$run1tmp/builtin_path")") \
  595. || return 3
  596. hints+=(" (built-in fake content set $PREUPG__UPATH)")
  597. ;;
  598. esac
  599. test -n "$*" \
  600. && args+=("$@") \
  601. && hints+=(" ($*)")
  602. jat__log_info "PWD='$PWD'" # help to hunt for things like bz1380120
  603. jat__cmd -h "Run preupgrade assistant${hints[*]}" \
  604. -S "$valid_es" \
  605. -o "$run1tmp/out" -e "$run1tmp/err" \
  606. preupg "${args[@]}"
  607. es=$?
  608. case $PREUPG__STRIPCTL in
  609. false)
  610. <"$run1tmp/out" jat_dump__pipe -l 400 -b 30000 PREUPG_OUT
  611. ;;
  612. true)
  613. <"$run1tmp/out" tr -dc '[:graph:]\n\t ' \
  614. | jat_dump__pipe -l 400 -b 30000 PREUPG_OUT_STRIPPED
  615. ;;
  616. esac
  617. < "$run1tmp/err" jat_dump__pipe -E PREUPG_ERR
  618. return $es
  619. }
  620. __preupg__mkfupath_builtin() {
  621. #
  622. # Ad-hoc path using built-in preupg_fupath() template
  623. #
  624. # This whole process is heavily complicated by weird behavior of preupg
  625. # and its tools':
  626. #
  627. # * You can't just come up with any name for an upgrade path; this
  628. # means the directory name is basically prescribed depending on
  629. # source (and destination) distro.
  630. #
  631. # * The build tool will only generate prescribed path (the above,
  632. # suffixed by '-results').
  633. #
  634. # * The same path *won't* work with preupg; you have to manually rename
  635. # it back to the "prescribed"
  636. #
  637. # In the end, `preupg_fupath()` has to use at least three
  638. # different paths and has no way of avoiding path conflict. Its API
  639. # partially avoids the problem by making the name a mandatory (=explicit)
  640. # argument and stating clearly in the docs that these paths would be
  641. # removed before generation.
  642. #
  643. # The point of this function, though, is to be easy on user; this means
  644. # we'll be implicit wherever we can, at the price of being relatively
  645. # fragile.
  646. #
  647. # Hence the unfunny and frustrating checks below.
  648. #
  649. test "${PREUPG__UPATH:0:1}" = @ || return 0
  650. local name
  651. {
  652. dist__test ver.x eq 5 && name=RHEL5_7
  653. dist__test ver.x eq 6 && name=RHEL6_7
  654. test -n "$name" || {
  655. jat__log_error "could not choose fake upath name (this works only on RHEL5/RHEL6)"
  656. return 3
  657. }
  658. test -e "$name" -o -e "$name-results" -o "$name-raw" || {
  659. jat__log_error "these must not exist for '@BUILTIN' form to work: $name, $name-results $name-raw"
  660. return 3
  661. }
  662. preupg_fupath "$name" "$PREUPG__UPATH"
  663. } >&2 #FIXME: remove block andredirect after bz1171881
  664. echo "$name/all-xccdf.xml" > "$run1tmp/builtin_path"
  665. }
  666. __preupg__mknatlist() {
  667. #
  668. # Make list of "native" packages to override and show the path
  669. #
  670. local ex # single expression from PREUPG__DISTNATIVE
  671. tr , '\n' <<<"$PREUPG__DISTNATIVE" \
  672. | grep . \
  673. | while read -r ex;
  674. do
  675. case "$ex" in
  676. -*) echo "${ex:1}" >> "$run1tmp/dno_exclude" ;;
  677. *) jat__log_error "invalid expression in PREUPG__DISTNATIVE: $ex"
  678. echo /dev/null
  679. return 1 ;;
  680. esac
  681. done
  682. rpm -qa --qf '%{N}\n' \
  683. | sort \
  684. | uniq \
  685. | grep -vxFf "$run1tmp/dno_exclude" \
  686. > "$run1tmp/dno_list"
  687. echo "$run1tmp/dno_list"
  688. }
  689. __preupg__dno_enable() {
  690. #
  691. # Enable "dist_native" override, if need be
  692. #
  693. test -n "$PREUPG__DISTNATIVE" || return 0
  694. jat__eval -h "enable devel_mode" \
  695. "mkdir -p /var/cache/preupgrade; touch /var/cache/preupgrade/devel_mode"
  696. __preupg__cfgbak
  697. {
  698. echo "[devel-mode]"
  699. echo -n "dist_mode="
  700. case "$PREUPG__DISTNATIVE" in
  701. all|sign|*/*) echo "$PREUPG__DISTNATIVE" ;;
  702. *) __preupg__mknatlist ;;
  703. esac
  704. } >> /etc/preupgrade-assistant.conf
  705. }
  706. __preupg__dno_disable() {
  707. #
  708. # Disable "dist_native" override, if need be
  709. #
  710. test -n "$PREUPG__DISTNATIVE" || return 0
  711. jat__cmd -h "disable devel_mode" \
  712. rm -f /var/cache/preupgrade/devel_mode
  713. __preupg__cfgrest
  714. }
  715. __preupg__cfgbak() {
  716. #
  717. # Back up preupg conf
  718. #
  719. jat__filebackup -n "preupg__cfgbak" \
  720. /etc/preupgrade-assistant.conf
  721. }
  722. __preupg__cfgrest() {
  723. #
  724. # Restore preupg conf, if needed
  725. #
  726. $__PREUPG__CFG_DIRTY || true
  727. jat__log_info "config before restoring:"
  728. jat_dump__file /etc/preupgrade-assistant.conf
  729. jat__filerestore -n "preupg__cfgbak"
  730. }
  731. __preupg__assert_mkcode() {
  732. #
  733. # Make Bash code for generating field values
  734. #
  735. echo -n "PREUPG__RULE=$Rule "
  736. case $Field in
  737. risk) echo "preupg__get_risks" ;;
  738. risk.slight) echo "preupg__get_risks SLIGHT" ;;
  739. risk.medium) echo "preupg__get_risks MEDIUM" ;;
  740. risk.high) echo "preupg__get_risks HIGH" ;;
  741. risk.extreme) echo "preupg__get_risks EXTREME" ;;
  742. riskn) echo "preupg__get_risks | wc -l" ;;
  743. riskn.slight) echo "preupg__get_risks SLIGHT | wc -l" ;;
  744. riskn.medium) echo "preupg__get_risks MEDIUM | wc -l" ;;
  745. riskn.high) echo "preupg__get_risks HIGH | wc -l" ;;
  746. riskn.extreme) echo "preupg__get_risks EXTREME | wc -l" ;;
  747. msg) echo "preupg__get_messages" ;;
  748. msg.debug) echo "preupg__get_messages DEBUG" ;;
  749. msg.info) echo "preupg__get_messages INFO" ;;
  750. msg.warning) echo "preupg__get_messages WARNING" ;;
  751. msg.error) echo "preupg__get_messages ERROR" ;;
  752. msgn) echo "preupg__get_messages | wc -l" ;;
  753. msgn.debug) echo "preupg__get_messages DEBUG | wc -l" ;;
  754. msgn.info) echo "preupg__get_messages INFO | wc -l" ;;
  755. msgn.warning) echo "preupg__get_messages WARNING | wc -l" ;;
  756. msgn.error) echo "preupg__get_messages ERROR | wc -l" ;;
  757. solution) echo "preupg__get_fixtext" ;;
  758. result) echo "preupg__get_result" ;;
  759. *) jat__log_error "unsupported field: $Field"; return 2 ;;
  760. esac
  761. }
  762. __preupg__assert_mkvalid_code() {
  763. #
  764. # Make Bash code, true if valid
  765. #
  766. local code
  767. code=$(__preupg__assert_mkcode) || return $?
  768. bash -n <<<"$code" && {
  769. echo "$code"
  770. return 0
  771. }
  772. jat__log_error "bug: bad assert code generated: '$code'"
  773. return 3
  774. }
  775. __preupg__assert_mkhint() {
  776. #
  777. # Compose hint for assert
  778. #
  779. local fphrase # English field phrase
  780. local s # 's' if $Value is plural, empty otherwise
  781. local a='a' # 'a' or 'an', based on what's proper
  782. test "$Value" = 1 || s="s"
  783. case $Field in
  784. result) fphrase="result" ;;
  785. risk|riskn) fphrase="risk" ;;
  786. msg|msgn) fphrase="message" ;;
  787. solution) fphrase="solution text" ;;
  788. risk.*|riskn.*) fphrase="${Field#*.} risk" ;;
  789. msg.*|msgn.*) fphrase="${Field#*.} message" ;;
  790. esac
  791. case ${Field#*.} in
  792. error|extreme|info) a='an' ;;
  793. esac
  794. case $Ellipsis in
  795. false) echo -n "rule $Rule has " ;;
  796. true) echo -n " ... " ;;
  797. esac
  798. case $Mode:$Type in
  799. pos:str) echo "$a $fphrase matching '$Value'" ;;
  800. neg:str) echo "no $fphrase matching '$Value'" ;;
  801. pos:int) echo "exactly $Value $fphrase$s" ;;
  802. neg:int) echo "other than $Value $fphrase$s" ;;
  803. esac
  804. }
  805. __preupg__assert1() {
  806. #
  807. # Perform one assertion with condition $1 with rule $Rule
  808. #
  809. # This does one iteration of preupg__assert
  810. #
  811. local Mode
  812. local Field
  813. local Value
  814. local es=0
  815. local code
  816. local hint
  817. local Type
  818. local tmp=$1 # tmp='MODE:FIELD:VA:L:UE'
  819. Mode=${tmp%%:*} # 'MODE'
  820. tmp=${tmp#$Mode:} # tmp='FIELD:VA:L:UE'
  821. Field=${tmp%%:*} # 'FIELD'
  822. Value=${tmp#$Field:} # 'VA:L:UE'
  823. Type=$(__preupg__assert_op4fld) || return $?
  824. code=$(__preupg__assert_mkvalid_code) || return $?
  825. hint=$(__preupg__assert_mkhint)
  826. case $Mode in
  827. pos) es=0 ;;
  828. neg) es=1 ;;
  829. esac
  830. case $Type in
  831. int) jat__eval -S $es -h "$hint" "test $(eval "$code") -eq $Value" ;;
  832. str) jat__eval -S $es -h "$hint" "$code | grep '$Value'" ;;
  833. esac
  834. }
  835. __preupg__collect_stray_loscap() {
  836. #
  837. # Legacy version of preupg__collect_stray()
  838. #
  839. local tmp
  840. local ruleid
  841. tmp=$(mktemp -td preupg__collect_stray.XXXXXXXX)
  842. pushd "$tmp" >/dev/null
  843. __preupg__lsrules_xml \
  844. | while read -r ruleid;
  845. do
  846. __preupg__resultxpath \
  847. "//ns0:rule-result[@idref='$ruleid']/ns0:check/ns0:check-import[@import-name='stdout']/text()" \
  848. >"stdout"
  849. test -s "stdout" || continue
  850. <"stdout" grep -v -E \
  851. -e '^preupg\.log\.(ERROR|WARNING|INFO|DEBUG): ' \
  852. -e '^preupg\.risk\.(SLIGHT|MEDIUM|HIGH|EXTREME): ' \
  853. > "stdout.stray"
  854. grep -q . "stdout.stray" || continue
  855. sed -e "s/^/$ruleid:stdout: /" <"stdout.stray"
  856. done
  857. popd >/dev/null
  858. rm -r "$tmp"
  859. }
  860. __preupg__assert_op4fld() {
  861. #
  862. # Print correct operator for field $Field
  863. #
  864. case $Field in
  865. result|risk|risk.*|msg|msg.*|solution) echo str ;;
  866. riskn|riskn.*|msgn|msgn.*) echo int ;;
  867. *) jat__log_error "unsupported field: $Field"; return 2 ;;
  868. esac
  869. }
  870. __preupg__lsrules_upath() {
  871. #
  872. # List preupg rule ids from upgrade path
  873. #
  874. local upname # upgrade path name
  875. case "$PREUPG__UPATH" in
  876. el6toel7) upname='RHEL6_7' ;;
  877. el5toel7) upname='RHEL5_7' ;;
  878. @*) upname="$(basename "$(dirname "$(<"$run1tmp/builtin_path")")")" ;;
  879. */all-xccdf.xml) upname="$(basename "$(dirname "$PREUPG__UPATH")")" ;;
  880. *) jat__log_error "unsupported upgrade path: $PREUPG__UPATH" ;;
  881. esac
  882. #FIXME: after bz1362708, use proper CLI --list-rules for both
  883. case "$PREUPG__UPATH" in
  884. @*)
  885. cat "$(dirname "$(<"$run1tmp/builtin_path")")/list_rules"
  886. ;;
  887. */all-xccdf.xml)
  888. cat "$(dirname "$PREUPG__UPATH")/list_rules"
  889. ;;
  890. *)
  891. preupg --list-rules
  892. ;;
  893. esac \
  894. | grep "$PREUPG__RULE_REGEX" \
  895. | sed -e "s/^$upname://"
  896. }
  897. __preupg__lsrules_xml() {
  898. #
  899. # List preupg rule ids from result.xml
  900. #
  901. __preupg__resultxpath \
  902. "//ns0:rule-result[./ns0:result/text() != 'notselected']/@idref"
  903. }
  904. __preupg__resultxpath() {
  905. #
  906. # Run XPath query $1 on result.xml inside tarball $2 or latest
  907. #
  908. # Take XPath query $1, run it on result.xml and print output.
  909. #
  910. # Notes: libxml2-python was, as finally turns out, the only usable
  911. # implementation available on RHEL5
  912. #
  913. local xpath=$1
  914. local tarfile=$2
  915. local inpath # path inside tarfile
  916. test -n "$xpath" || {
  917. jat__log_error "empty XPath query"
  918. return 2
  919. }
  920. test -n "$tarfile" || tarfile=$(preupg__get_latest_tar)
  921. test -n "$tarfile" || {
  922. jat__log_error "No tarfile found. Either run preupg or provide tarfile on command line"
  923. return 2
  924. }
  925. inpath=${tarfile##*/}
  926. inpath=${inpath%.tar.gz}
  927. tar -zf "$tarfile" -O -x "$inpath/result.xml" \
  928. | pxpath \
  929. "$xpath" - \
  930. "xhtml:http://www.w3.org/1999/xhtml" \
  931. "html:http://www.w3.org/1999/xhtml" \
  932. "ns0:http://checklists.nist.gov/xccdf/1.2"
  933. }
  934. #shellfu module-version=__MKIT_PROJ_VERSION__