PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/overlay/generic/lib/svc/method/manifest-import

http://github.com/joyent/smartos-live
Korn Shell | 517 lines | 312 code | 67 blank | 138 comment | 67 complexity | 4490812f9aadfa9b7cf678d7110a6608 MD5 | raw file
Possible License(s): BSD-3-Clause, CC-BY-SA-3.0, MPL-2.0-no-copyleft-exception, GPL-2.0, 0BSD, MIT, Apache-2.0
  1. #!/bin/ksh
  2. #
  3. # CDDL HEADER START
  4. #
  5. # The contents of this file are subject to the terms of the
  6. # Common Development and Distribution License (the "License").
  7. # You may not use this file except in compliance with the License.
  8. #
  9. # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10. # or http://www.opensolaris.org/os/licensing.
  11. # See the License for the specific language governing permissions
  12. # and limitations under the License.
  13. #
  14. # When distributing Covered Code, include this CDDL HEADER in each
  15. # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16. # If applicable, add the following below this CDDL HEADER, with the
  17. # fields enclosed by brackets "[]" replaced with your own identifying
  18. # information: Portions Copyright [yyyy] [name of copyright owner]
  19. #
  20. # CDDL HEADER END
  21. #
  22. # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  23. #
  24. # 0a Initialization.
  25. [ -f /lib/svc/share/smf_include.sh ] || exit 1
  26. . /lib/svc/share/smf_include.sh
  27. activity=false
  28. EMI_SERVICE="svc:/system/early-manifest-import:default"
  29. PROFILE_DIR_SITE="/etc/svc/profile/site"
  30. X=
  31. ALT_REPOSITORY=
  32. ALT_MFST_DIR=
  33. early=false
  34. [ "$SMF_FMRI" == "$EMI_SERVICE" ] && early=true
  35. usage()
  36. {
  37. echo "Usage: /lib/svc/method/manifest-import [-n]" \
  38. "[-f repository-file -d manifest-directory]"
  39. echo "\nOptions:"
  40. echo "-n dryrun"
  41. echo "-f and -d specify alternate repository and" \
  42. "manifest directory for import\n"
  43. exit 2
  44. }
  45. while getopts "nd:f:" opt; do
  46. case $opt in
  47. n) X=echo;;
  48. d) ALT_MFST_DIR=$OPTARG;;
  49. f) ALT_REPOSITORY=$OPTARG;;
  50. ?) usage;;
  51. esac
  52. done
  53. #
  54. # Both -f and -d options must be specified together or not specified at all
  55. #
  56. [ -n "$ALT_REPOSITORY" -a -z "$ALT_MFST_DIR" ] && usage
  57. [ -n "$ALT_MFST_DIR" -a -z "$ALT_REPOSITORY" ] && usage
  58. function svccfg_apply {
  59. $X /usr/sbin/svccfg apply $1
  60. if [ $? -ne 0 ]; then
  61. echo "WARNING: svccfg apply $1 failed" | tee /dev/msglog
  62. fi
  63. }
  64. #
  65. # If the smf/manifest table has file entries that are missing
  66. # then there is work to be done by the cleanup process.
  67. #
  68. function cleanup_needwork {
  69. if [ "$early" == true ]; then
  70. smfmfiles=`/usr/bin/svcprop smf/manifest | \
  71. awk '(/^lib_/ && /\/manifestfile /) {print $3}'`
  72. else
  73. smfmfiles=`/usr/bin/svcprop smf/manifest | \
  74. awk '/\/manifestfile / {print $3}'`
  75. fi
  76. nw=`/lib/svc/bin/mfstscan $smfmfiles 2>&1 1>/dev/null`
  77. [ "$nw" ] && return 1
  78. return 0
  79. }
  80. #
  81. # Upon upgrading to early manifest import code, preserve hashes of system
  82. # profiles which lived under /var/svc/profile so that svccfg apply would
  83. # not re-apply the profiles and overwrite user customizations. Simply
  84. # migrate manifestfile and hash values to new property groups named after
  85. # profiles under /etc/svc/profile. If the profiles don't really exist,
  86. # svccfg cleanup will remove the property groups in a later step.
  87. #
  88. # Existing generic.xml, inetd_services.xml, and name_service.xml symlinks
  89. # need to be preserved.
  90. #
  91. # Don't process site.xml profile since it is still supported under
  92. # /var/svc/profile directory.
  93. #
  94. function preserve_system_profiles {
  95. #
  96. # If /var is a separate fs, return and let Late Import
  97. # preserves the hashes.
  98. #
  99. [ -d "/var/svc/profile" ] || return 1
  100. #
  101. # Preserve hashes for the following profiles: generic (two
  102. # cases) and platform (uname -i, uname -m outputs).
  103. #
  104. gn="var_svc_profile_generic_open_xml"
  105. gh=`/usr/bin/svcprop -p ${gn}/md5sum smf/manifest 2>/dev/null`
  106. [ $? = 0 ] || gh=""
  107. gn="etc_svc_profile_generic_open_xml"
  108. gln="var_svc_profile_generic_limited_net_xml"
  109. glh=`/usr/bin/svcprop -p ${gln}/md5sum smf/manifest 2>/dev/null`
  110. [ $? = 0 ] || glh=""
  111. gln="etc_svc_profile_generic_limited_net_xml"
  112. LC_ALL=C pl=`/usr/bin/uname -i | /usr/bin/tr , _`
  113. pln="var_svc_profile_platform_${pl}_xml"
  114. plh=`/usr/bin/svcprop -p ${pln}/md5sum smf/manifest 2>/dev/null`
  115. [ $? = 0 ] || plh=""
  116. pln="etc_svc_profile_platform_${pl}_xml"
  117. LC_ALL=C plm=`/usr/bin/uname -m | /usr/bin/tr , _`
  118. if [ $plm != $pl ]; then
  119. plmn="var_svc_profile_platform_${plm}_xml"
  120. plmh=`/usr/bin/svcprop -p ${plmn}/md5sum smf/manifest \
  121. 2>/dev/null`
  122. [ $? = 0 ] || plmh=""
  123. plmn="etc_svc_profile_platform_${plm}_xml"
  124. else
  125. plmh=""
  126. fi
  127. [ -n "$gh" ] && {
  128. echo "Preserving generic hash ($gh)."
  129. /usr/sbin/svccfg -s smf/manifest addpg ${gn} framework
  130. /usr/sbin/svccfg -s smf/manifest setprop ${gn}/md5sum = \
  131. opaque: $gh
  132. /usr/sbin/svccfg -s smf/manifest setprop ${gn}/manifestfile = \
  133. astring: "/etc/svc/profile/generic.xml"
  134. }
  135. [ -n "$glh" ] && {
  136. echo "Preserving generic_limited hash ($glh)."
  137. /usr/sbin/svccfg -s smf/manifest addpg ${gln} framework
  138. /usr/sbin/svccfg -s smf/manifest setprop ${gln}/md5sum = \
  139. opaque: $glh
  140. /usr/sbin/svccfg -s smf/manifest setprop ${gln}/manifestfile = \
  141. astring: "/etc/svc/profile/generic.xml"
  142. }
  143. [ -n "$plh" ] && {
  144. echo "Preserving platform hash ($plh)."
  145. /usr/sbin/svccfg -s smf/manifest addpg $pln framework
  146. /usr/sbin/svccfg -s smf/manifest setprop $pln/md5sum = \
  147. opaque: $plh
  148. /usr/sbin/svccfg -s smf/manifest setprop ${pln}/manifestfile = \
  149. astring: "/etc/svc/profile/platform_${pl}_xml"
  150. }
  151. [ -n "$plmh" ] && {
  152. echo "Preserving platform hash ($plmh)."
  153. /usr/sbin/svccfg -s smf/manifest addpg $plmn framework
  154. /usr/sbin/svccfg -s smf/manifest setprop $plmn/md5sum = \
  155. opaque: $plmh
  156. /usr/sbin/svccfg -s smf/manifest setprop \
  157. ${plmn}/manifestfile = \
  158. astring: "/etc/svc/profile/platform_${plm}_xml"
  159. }
  160. #
  161. # Move symlinks from /var/svc/profile to /etc/svc/profile
  162. #
  163. generic_prof="/var/svc/profile/generic.xml"
  164. ns_prof="/var/svc/profile/name_service.xml"
  165. inetd_prof="/var/svc/profile/inetd_services.xml"
  166. platform_prof="/var/svc/profile/platform.xml"
  167. [ -L "$generic_prof" ] && mv $generic_prof /etc/svc/profile/
  168. [ -L "$ns_prof" ] && mv $ns_prof /etc/svc/profile/
  169. [ -L "$inetd_prof" ] && mv $inetd_prof /etc/svc/profile/
  170. [ -L "$platform_prof" ] && mv $platform_prof /etc/svc/profile/
  171. return 0
  172. }
  173. #
  174. # 2. Manifest import. Application directories first, then
  175. # site-specific manifests.
  176. #
  177. function import_manifests {
  178. typeset basedir=$1
  179. typeset console_print=$2
  180. typeset logf="/etc/svc/volatile/manifest_import.$$"
  181. rm -f $logf
  182. if [ "${basedir}" == "/opt/custom/smf" ]; then
  183. # Special case where we will just import from the root, not subdirs
  184. nonsite_dirs=${basedir}
  185. else
  186. nonsite_dirs=`/usr/bin/find $basedir/* -name site \
  187. -prune -o -type d -print -prune`
  188. fi
  189. if [ -n "$_MFST_DEBUG" ]; then
  190. nonsite_manifests=`/lib/svc/bin/mfstscan $nonsite_dirs`
  191. site_manifests=`/lib/svc/bin/mfstscan $basedir/site`
  192. manifests="$nonsite_manifests $site_manifests"
  193. echo "Changed manifests to import:"
  194. for m in $manifests; do echo " $m"; done
  195. fi
  196. #
  197. # Upon boot, attempt to move the repository to tmpfs.
  198. #
  199. if [ -z "$ALT_REPOSITORY" -a -z "$ALT_MFST_DIR" ]; then
  200. /usr/sbin/svcadm _smf_repository_switch fast
  201. fi
  202. #
  203. # Import the manifests while giving a running display of imports on
  204. # console, and a final count in the logfile.
  205. #
  206. dirs="$nonsite_dirs"
  207. [ -d "$basedir/site" ] && dirs="$dirs $basedir/site"
  208. if [ "$console_print" = "true" ]; then
  209. $X /usr/sbin/svccfg import -p /dev/msglog $dirs > $logf 2>&1
  210. else
  211. $X /usr/sbin/svccfg import $dirs > $logf 2>&1
  212. fi
  213. grep "Loaded .*. smf(5) service descriptions" $logf > /dev/null 2>&1
  214. if [ $? -eq 0 ]; then
  215. activity=true
  216. fi
  217. if [ -s $logf ]; then
  218. grep "smf(5) service descriptions failed to load" $logf > /dev/null 2>&1
  219. failures=$?
  220. if [ $failures -eq 0 ]; then
  221. echo "svccfg warnings:"
  222. fi
  223. cat $logf
  224. if [ $failures -eq 0 -a "$console_print" = "true" ]; then
  225. msg="svccfg import warnings. See"
  226. msg="$msg /var/svc/log/system-manifest-import:default.log ."
  227. echo $msg > /dev/msglog
  228. fi
  229. fi
  230. rm -f $logf
  231. }
  232. #
  233. # 3. Profile application. We must create the platform profile upon
  234. # first boot, as we may be a diskless client of a platform or
  235. # architecture distinct from our NFS server.
  236. #
  237. # Generic and platform profiles are only supported in /etc.
  238. #
  239. function apply_profile {
  240. #
  241. # If smf/manifest doesn't have any profile under /etc/var/profile,
  242. # this is very likely an import after upgrade so call
  243. # preserve_system_profiles in that case.
  244. #
  245. LC_ALL=C pl=`/usr/bin/uname -i | /usr/bin/tr , _`
  246. pln="etc_svc_profile_platform_${pl}_xml"
  247. LC_ALL=C plm=`/usr/bin/uname -m | /usr/bin/tr , _`
  248. [ $plm != $pl ] && plmn="etc_svc_profile_platform_${plm}_xml"
  249. preserve_profiles=1
  250. for prof in $pln $plmn etc_svc_profile_platform_none_xml \
  251. etc_svc_profile_generic_limited_net_xml \
  252. etc_svc_profile_generic_open_xml; do
  253. if /usr/bin/svcprop -p $prof smf/manifest >/dev/null 2>&1
  254. then
  255. preserve_profiles=0
  256. break
  257. fi
  258. done
  259. if [ $preserve_profiles -eq 1 ]; then
  260. echo "/etc/svc system profiles not found: upgrade system profiles"
  261. preserve_system_profiles || return
  262. fi
  263. typeset prefix="/etc/svc/profile"
  264. svccfg_apply $prefix/generic.xml
  265. if [ ! -f $prefix/platform.xml ]; then
  266. this_karch=`uname -m`
  267. this_plat=`uname -i`
  268. if [ -f $prefix/platform_$this_plat.xml ]; then
  269. platform_profile=platform_$this_plat.xml
  270. elif [ -f $prefix/platform_$this_karch.xml ]; then
  271. platform_profile=platform_$this_karch.xml
  272. else
  273. platform_profile=platform_none.xml
  274. fi
  275. ln -s $platform_profile $prefix/platform.xml
  276. fi
  277. svccfg_apply $prefix/platform.xml
  278. }
  279. #
  280. # 4. Upgrade handling. The upgrade file generally consists of a series
  281. # of svcadm(1M) and svccfg(1M) commands.
  282. #
  283. function handle_upgrade {
  284. [ -f /var/svc/profile/upgrade ] && activity=true
  285. (
  286. unset SVCCFG_CHECKHASH
  287. if [ -f /var/svc/profile/upgrade ]; then
  288. . /var/svc/profile/upgrade
  289. /usr/bin/mv /var/svc/profile/upgrade \
  290. /var/svc/profile/upgrade.app.`date +\%Y\%m\%d\%H\%M\%S`
  291. fi
  292. #
  293. # Rename the datalink upgrade script file. This script is used in the
  294. # network/physical service to upgrade datalink configuration, but
  295. # the file cannot be renamed until now (when the file system becomes
  296. # read-write).
  297. #
  298. datalink_script=/var/svc/profile/upgrade_datalink
  299. if [ -f "${datalink_script}" ]; then
  300. /usr/bin/mv "${datalink_script}" \
  301. "${datalink_script}".app.`date +\%Y\%m\%d\%H\%M\%S`
  302. fi
  303. )
  304. }
  305. #
  306. # 5. Giving administrator the final say, apply site.xml profile and profiles
  307. # under /etc/svc/profile/site directory.
  308. #
  309. function apply_site_profile {
  310. typeset prefix="$1"
  311. [ -f $prefix/site.xml ] && svccfg_apply $prefix/site.xml
  312. if [ -d $PROFILE_DIR_SITE -a "$1" = "/etc/svc/profile" ]; then
  313. svccfg_apply $PROFILE_DIR_SITE
  314. fi
  315. }
  316. #
  317. # 0b Cleanup deathrow
  318. #
  319. if [ "$early" = "false" ];then
  320. deathrow=/etc/svc/deathrow
  321. if [ -s $deathrow ];then
  322. #
  323. # svc.startd has unconfigured the services found in deathrow,
  324. # clean them now.
  325. #
  326. while read fmri mfst pkgname; do
  327. # Delete services and instances from the deathrow file.
  328. /usr/sbin/svccfg delete -f $fmri >/dev/null 2>&1
  329. # Remove deathrow manifest hash.
  330. /usr/sbin/svccfg delhash -d $mfst >/dev/null 2>&1
  331. done < $deathrow
  332. /usr/bin/mv $deathrow $deathrow.old
  333. fi
  334. fi
  335. SVCCFG_CHECKHASH=1 export SVCCFG_CHECKHASH
  336. #
  337. # 0c Clean up repository
  338. #
  339. if [ "$early" = "false" ]; then
  340. if [ -z "$X" ] && /usr/bin/svcprop smf/manifest 2>/dev/null |
  341. /usr/bin/grep '^ar_svc_[^/]*/md5sum opaque ' >/dev/null
  342. then
  343. set -- `
  344. /usr/bin/svcprop smf/manifest 2>/dev/null |
  345. /usr/bin/grep '^ar_svc[^/]*/md5sum opaque ' |
  346. /usr/bin/tr '/' ' ' |
  347. while read pg prop type value; do
  348. echo "$pg/$value"
  349. done
  350. `
  351. backup=`echo "$#/$#" | sed 's/.//g'`
  352. fwidth=`echo "$#\c" | wc -c`
  353. echo "Converting obsolete repository entries: \c" > /dev/msglog
  354. i=1; n=$#
  355. while [ $# -gt 0 ]; do
  356. printf "%${fwidth}s/%${fwidth}s" $i $n > /dev/msglog
  357. echo $1 | sed 's:/: :' | (
  358. read pg value
  359. (echo "select /smf/manifest"; echo "delpg v$pg") |
  360. /usr/sbin/svccfg 2>/dev/null >/dev/null
  361. (echo "select /smf/manifest"; echo "delpg $pg") |
  362. /usr/sbin/svccfg 2>/dev/null >/dev/null
  363. (echo "select /smf/manifest";
  364. echo "addpg v$pg framework") |
  365. /usr/sbin/svccfg 2>/dev/null >/dev/null
  366. (echo "select /smf/manifest";
  367. echo "setprop v$pg/md5sum = opaque: $value") |
  368. /usr/sbin/svccfg 2>/dev/null >/dev/null
  369. )
  370. i=`expr $i + 1`
  371. shift
  372. echo "$backup\c" > /dev/msglog
  373. done
  374. echo > /dev/msglog
  375. echo "Converted $n obsolete repository entries"
  376. activity=true
  377. fi
  378. fi
  379. #
  380. # If the alternate repository and directory are specified, simply set
  381. # SVCCFG_REPOSITORY env, run svccfg import on the given directory, and
  382. # exit.
  383. #
  384. if [ -n "$ALT_REPOSITORY" -a -n "$ALT_MFST_DIR" ]; then
  385. SVCCFG_REPOSITORY=$ALT_REPOSITORY export SVCCFG_REPOSITORY
  386. import_manifests "$ALT_MFST_DIR" false
  387. unset SVCCFG_REPOSITORY
  388. exit 0
  389. fi
  390. #
  391. # Call import and apply profiles here
  392. #
  393. if [ "$early" = "true" ]; then
  394. import_manifests "/lib/svc/manifest" true
  395. apply_profile
  396. apply_site_profile "/etc/svc/profile"
  397. else
  398. #
  399. # Process both /lib/svc/manifest and /var/svc/manifest
  400. # during late manifest-import
  401. #
  402. # First import the manifests
  403. #
  404. import_manifests "/lib/svc/manifest" true
  405. import_manifests "/var/svc/manifest" true
  406. if [ -d "/opt/custom/smf" ]; then
  407. import_manifests "/opt/custom/smf" true
  408. fi
  409. #
  410. # Apply profiles
  411. #
  412. apply_profile
  413. apply_site_profile "/etc/svc/profile"
  414. #
  415. # Run the upgrade script
  416. #
  417. handle_upgrade
  418. apply_site_profile "/var/svc/profile"
  419. fi
  420. #
  421. # 6. Final actions.
  422. #
  423. #if $activity; then
  424. # /usr/sbin/svcadm _smf_backup "manifest_import" || true
  425. #fi
  426. #
  427. # If the filesystem is NOT read only then move the repo back to perm
  428. # There is no care wether the switch was made or not, but just want
  429. # to move it. If it is already perm this does not affect anything
  430. # at least on the surface. REALLY want to improve on this...
  431. #
  432. touch /etc/svc/smf_rwtest.$$ > /dev/null 2>&1
  433. if [ $? -eq 0 ]; then
  434. rm -f /etc/svc/smf_rwtest.$$
  435. /usr/sbin/svcadm _smf_repository_switch perm || { \
  436. echo "Repository switch back operation failed, \c"
  437. echo "please check the system log for the"
  438. echo "possible fatal error messages."
  439. exit $SMF_EXIT_ERR_FATAL
  440. }
  441. fi
  442. if $activity; then
  443. /usr/sbin/svccfg cleanup | /usr/bin/tee /dev/msglog
  444. else
  445. cleanup_needwork
  446. if [ $? -ne 0 ]; then
  447. /usr/sbin/svccfg cleanup -a | /usr/bin/tee /dev/msglog
  448. fi
  449. fi
  450. exit 0