platform-upgrade 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #!/bin/bash
  2. # https://github.com/calmh/smartos-platform-upgrade
  3. # Copyright (c) 2012-2016 Jakob Borg & Contributors
  4. # Distributed under the MIT License
  5. # us-east.manta.joyent.com currently use Let's Encrypt
  6. # https://letsencrypt.org/certs/isrgrootx1.txt
  7. # https://letsencrypt.org/certs/lets-encrypt-r3.txt
  8. cert_file=$(mktemp)
  9. function cleanup {
  10. rm "$cert_file"
  11. }
  12. trap cleanup EXIT
  13. cat >"$cert_file" <<EOF
  14. -----BEGIN CERTIFICATE-----
  15. MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
  16. TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
  17. cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
  18. WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
  19. ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
  20. MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
  21. h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
  22. 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
  23. A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
  24. T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
  25. B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
  26. B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
  27. KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
  28. OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
  29. jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
  30. qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
  31. rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
  32. HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
  33. hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
  34. ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
  35. 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
  36. NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
  37. ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
  38. TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
  39. jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
  40. oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
  41. 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
  42. mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
  43. emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
  44. -----END CERTIFICATE-----
  45. -----BEGIN CERTIFICATE-----
  46. MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
  47. TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
  48. cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
  49. WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
  50. RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
  51. AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
  52. R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
  53. sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
  54. NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
  55. Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
  56. /kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
  57. AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
  58. Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
  59. FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
  60. AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
  61. Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
  62. gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
  63. PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
  64. ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
  65. CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
  66. lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
  67. avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
  68. yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
  69. yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
  70. hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
  71. HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
  72. MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
  73. nLRbwHOoq7hHwg==
  74. -----END CERTIFICATE-----
  75. EOF
  76. function _curl {
  77. curl -s --cacert "$cert_file" $@
  78. }
  79. function usage() {
  80. cat <<- "USAGE"
  81. $ platform-upgrade [-u URL -s MD5SUM_URL] [-f]
  82. OPTIONS:
  83. -u URL : Remote/local url of platform-version.tgz file
  84. -s MD5SUM_URL : Remote/local url of md5 checksum file
  85. -f : Force installation if version is already present
  86. EXAMPLE:
  87. # Use default Joyent URL for latest platform image
  88. platform-upgrade
  89. # Use local platform and checksum file
  90. platform-upgrade -u file:///tmp/platform-20180510T153535Z.tgz -s file:///tmp/md5sum.txt
  91. USAGE
  92. }
  93. force="false"
  94. while getopts :fu:s: option; do
  95. case "$option" in
  96. u)
  97. platform_url="$OPTARG"
  98. ;;
  99. s)
  100. md5sums_url="$OPTARG"
  101. ;;
  102. f)
  103. force="true"
  104. ;;
  105. \?)
  106. usage
  107. exit -1
  108. ;;
  109. esac
  110. done
  111. shift $((OPTIND-1))
  112. if [[ -n $platform_url ]] && [[ ! -n $md5sums_url ]]; then
  113. usage
  114. exit -1
  115. fi
  116. if [[ ! -n $platform_url ]]; then
  117. host=https://us-east.manta.joyent.com
  118. latest_path="${host}$(_curl "$host/Joyent_Dev/public/SmartOS/latest")"
  119. version="$(expr "$latest_path" : '.*\([0-9]\{8\}T[0-9]\{6\}Z\).*')"
  120. latest_spec_path="$(_curl "$host/Joyent_Dev/public/SmartOS/$version")"
  121. header="$(expr "$latest_spec_path" : '.*platform-release-\([0-9]\{8\}\)-.*')"
  122. platform_url="$latest_path/platform-release-$header-$version.tgz"
  123. if [[ ! -n $md5sums_url ]]; then
  124. md5sums_url="$latest_path/md5sums.txt"
  125. fi
  126. else
  127. header="$(expr "$platform_url" : '.*platform-release-\([0-9]\{8\}\)-.*')"
  128. version="$(expr "$platform_url" : '.*\([0-9]\{8\}T[0-9]\{6\}Z\).*')"
  129. fi
  130. platform_file="platform-release-$header-$version.tgz"
  131. platform_dir="platform-$version"
  132. IFS=_ read brand kernel < <(uname -v)
  133. if [[ $kernel == $version ]]; then
  134. echo "Already on latest version ($kernel)."
  135. $force || exit -1
  136. fi
  137. tmp=$(mktemp -d)
  138. cd "$tmp" || exit -1
  139. echo -n "Downloading $platform_file..."
  140. if ! _curl -o "$platform_file" "$platform_url" ; then
  141. echo " failed"
  142. exit -1
  143. else
  144. echo " OK"
  145. fi
  146. echo -n "Verifying checksum..."
  147. _curl "$md5sums_url" \
  148. | grep "$platform_file" \
  149. | awk '{print $1}' > expected.md5
  150. openssl md5 "$platform_file" | awk '{print $2}' > actual.md5
  151. if ! cmp -s actual.md5 expected.md5 ; then
  152. echo " failed"
  153. exit -1
  154. else
  155. echo " OK"
  156. fi
  157. echo -n "Extracting latest platform..."
  158. if ! gtar zxf "$platform_file" ; then
  159. echo " failed"
  160. exit -1
  161. else
  162. echo " OK"
  163. fi
  164. echo -n "Marking release version..."
  165. if ! echo $version > $platform_dir/VERSION ; then
  166. echo " failed"
  167. exit -1
  168. else
  169. echo " OK"
  170. fi
  171. echo -n "Checking current boot device..."
  172. if [[ -z $1 ]] ; then
  173. removables=($(diskinfo -cH | \
  174. awk 'BEGIN { FS="\t" } $7~/\?\?R./ { print $2 }'))
  175. echo -n " detected ${removables[@]}"
  176. if [[ ${#removables[@]} -eq 0 ]]; then
  177. echo
  178. echo "Error: Unable to detect removable device."
  179. diskinfo
  180. echo "Specify correct device on the command line."
  181. exit -1
  182. elif [[ ${#removables[@]} -gt 1 ]]; then
  183. echo
  184. echo "Error: more than one removable device detected."
  185. diskinfo -cH | awk 'BEGIN { FS="\t" } $7~/\?\?R./ { print }'
  186. echo "Specify correct device on the command line."
  187. exit -1
  188. fi
  189. # Look for a GPT/EFI VTOC; if there isn't one, then this is almost
  190. # certainly an MBR-partitioned device. If it's a GPT label, then we
  191. # want the slice that's of type 2 (ROOT).
  192. if [[ -e "/dev/dsk/${removables[0]}" ]]; then
  193. partition=$(/usr/sbin/prtvtoc -h "/dev/dsk/${removables[0]}" | \
  194. awk ' $2 == 2 { print $1 }')
  195. if [[ $? -eq 0 && -n "$partition" ]]; then
  196. echo -n ", GPT label"
  197. usb="/dev/dsk/${removables[0]}s${partition}"
  198. fi
  199. fi
  200. if [[ -z "$usb" ]]; then
  201. echo -n ", MBR label"
  202. usb="/dev/dsk/${removables[0]}p1"
  203. fi
  204. else
  205. usb="$1"
  206. echo -n " using $usb"
  207. fi
  208. umount "$usb" 2>/dev/null
  209. mkdir usb
  210. if ! mount -F pcfs -o foldcase "$usb" "$tmp/usb" ; then
  211. echo ", mount failed"
  212. exit -1
  213. else
  214. echo -n ", mounted"
  215. fi
  216. if [[ ! -d usb/platform ]] ; then
  217. echo ", missing platform dir"
  218. exit -1
  219. else
  220. echo ", OK"
  221. fi
  222. echo -n "Updating platform on boot device..."
  223. if ! rsync -rltD "$platform_dir/" usb/platform.new/ ; then
  224. echo " failed"
  225. exit -1
  226. else
  227. echo " OK"
  228. fi
  229. echo -n "Remounting boot device..."
  230. umount "$usb" 2>/dev/null
  231. if ! mount -F pcfs -o foldcase "$usb" "$tmp/usb" ; then
  232. echo " failed"
  233. exit -1
  234. else
  235. echo " OK"
  236. fi
  237. echo -n "Verifying kernel checksum on boot device..."
  238. openssl dgst -sha1 "$platform_dir"/i86pc/kernel/amd64/unix | cut -d ' ' -f 2 > kernel.expected
  239. openssl dgst -sha1 usb/platform.new/i86pc/kernel/amd64/unix | cut -d ' ' -f 2 > kernel.actual
  240. if ! cmp -s kernel.actual kernel.expected ; then
  241. echo " failed"
  242. exit -1
  243. else
  244. echo " OK"
  245. fi
  246. echo -n "Verifying boot_archive checksum on boot device..."
  247. openssl dgst -sha1 usb/platform.new/i86pc/amd64/boot_archive | cut -d ' ' -f 2 > boot_archive.actual
  248. if ! cmp -s boot_archive.actual usb/platform.new/i86pc/amd64/boot_archive.hash ; then
  249. echo " failed"
  250. exit -1
  251. else
  252. echo " OK"
  253. fi
  254. echo -n "Activating new platform on $usb..."
  255. rm -rf usb/old
  256. mkdir usb/old
  257. if ! ( mv usb/platform usb/old && mv usb/platform.new usb/platform ) ; then
  258. echo " failed"
  259. exit -1
  260. else
  261. echo " OK"
  262. fi
  263. echo
  264. echo "Boot device upgraded. To do:"
  265. echo
  266. echo " 1) Sanity check the contents of $tmp/usb"
  267. echo " 2) umount $usb"
  268. echo " 3) reboot"