platform-upgrade 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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 uses a wildcard certificate based on the
  6. # Thawte Primary Root CA.
  7. # SHA-1=91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81
  8. # SHA-256=8D:72:2F:81:A9:C1:13:C0:79:1D:F1:36:A2:96:6D:B2:6C:95:0A:97:1D:B4:6B:41:99:F4:EA:54:B7:8B:FB:9F
  9. cert_file=$(mktemp)
  10. function cleanup {
  11. rm "$cert_file"
  12. }
  13. trap cleanup EXIT
  14. cat >"$cert_file" <<EOF
  15. -----BEGIN CERTIFICATE-----
  16. MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
  17. qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
  18. Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
  19. MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
  20. BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
  21. NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
  22. LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
  23. A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
  24. IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
  25. SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
  26. W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
  27. 3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
  28. 6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
  29. Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
  30. NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
  31. MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
  32. r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
  33. DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
  34. YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
  35. xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
  36. /qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
  37. LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
  38. jVaMaA==
  39. -----END CERTIFICATE-----
  40. -----BEGIN CERTIFICATE-----
  41. MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
  42. MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
  43. d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
  44. QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
  45. MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
  46. b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
  47. 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
  48. CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
  49. nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
  50. 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
  51. T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
  52. gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
  53. BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
  54. TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
  55. DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
  56. hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
  57. 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
  58. PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
  59. YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
  60. CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
  61. -----END CERTIFICATE-----
  62. EOF
  63. function _curl {
  64. curl -s --cacert "$cert_file" $@
  65. }
  66. function usage() {
  67. cat <<- "USAGE"
  68. $ platform-upgrade [-u URL -s MD5SUM_URL] [-f]
  69. OPTIONS:
  70. -u URL : Remote/local url of platform-version.tgz file
  71. -s MD5SUM_URL : Remote/local url of md5 checksum file
  72. -f : Force installation if version is already present
  73. EXAMPLE:
  74. # Use default Joyent URL for latest platform image
  75. platform-upgrade
  76. # Use local platform and checksum file
  77. platform-upgrade -u file:///tmp/platform-20180510T153535Z.tgz -s file:///tmp/md5sum.txt
  78. USAGE
  79. }
  80. force="false"
  81. while getopts :fu:s: option; do
  82. case "$option" in
  83. u)
  84. platform_url="$OPTARG"
  85. ;;
  86. s)
  87. md5sums_url="$OPTARG"
  88. ;;
  89. f)
  90. force="true"
  91. ;;
  92. \?)
  93. usage
  94. exit -1
  95. ;;
  96. esac
  97. done
  98. shift $((OPTIND-1))
  99. if [[ -n $platform_url ]] && [[ ! -n $md5sums_url ]]; then
  100. usage
  101. exit -1
  102. fi
  103. if [[ ! -n $platform_url ]]; then
  104. host=https://us-east.manta.joyent.com
  105. latest_path="${host}$(_curl "$host/Joyent_Dev/public/SmartOS/latest")"
  106. version="$(expr "$latest_path" : '.*\([0-9]\{8\}T[0-9]\{6\}Z\).*')
  107. latest_spec_path="$(_curl "$host/Joyent_Dev/public/SmartOS/$version")"
  108. header="$(expr "$latest_spec_path" : '.*platform-release-\([0-9]\{8\}\)-.*')"
  109. platform_url="$latest_path/platform-release-$header-$version.tgz"
  110. if [[ ! -n $md5sums_url ]]; then
  111. md5sums_url="$latest_path/md5sums.txt"
  112. fi
  113. else
  114. version="$(expr "$platform_url" : '.*\([0-9]\{8\}T[0-9]\{6\}Z\).*')"
  115. fi
  116. platform_file="platform-release-$header-$version.tgz"
  117. platform_dir="platform-$version"
  118. IFS=_ read brand kernel < <(uname -v)
  119. if [[ $kernel == $version ]]; then
  120. echo "Already on latest version ($kernel)."
  121. $force || exit -1
  122. fi
  123. tmp=$(mktemp -d)
  124. cd "$tmp" || exit -1
  125. echo -n "Downloading latest platform ($platform_file)..."
  126. if ! _curl -o "$platform_file" "$platform_url" ; then
  127. echo " failed"
  128. exit -1
  129. else
  130. echo " OK"
  131. fi
  132. echo -n "Verifying checksum..."
  133. _curl "$md5sums_url" \
  134. | grep "$platform_file" \
  135. | awk '{print $1}' > expected.md5
  136. openssl md5 "$platform_file" | awk '{print $2}' > actual.md5
  137. if ! cmp -s actual.md5 expected.md5 ; then
  138. echo " failed"
  139. exit -1
  140. else
  141. echo " OK"
  142. fi
  143. echo -n "Extracting latest platform..."
  144. if ! gtar zxf "$platform_file" ; then
  145. echo " failed"
  146. exit -1
  147. else
  148. echo " OK"
  149. fi
  150. echo -n "Marking release version..."
  151. if ! echo $version > $platform_dir/VERSION ; then
  152. echo " failed"
  153. exit -1
  154. else
  155. echo " OK"
  156. fi
  157. echo -n "Checking current boot device..."
  158. if [[ -z $1 ]] ; then
  159. removables=($(diskinfo -cH | \
  160. awk 'BEGIN { FS="\t" } $7~/\?\?R./ { print $2 }'))
  161. echo -n " detected ${removables[@]}"
  162. if [[ ${#removables[@]} -eq 0 ]]; then
  163. echo
  164. echo "Error: Unable to detect removable device."
  165. diskinfo
  166. echo "Specify correct device on the command line."
  167. exit -1
  168. elif [[ ${#removables[@]} -gt 1 ]]; then
  169. echo
  170. echo "Error: more than one removable device detected."
  171. diskinfo -cH | awk 'BEGIN { FS="\t" } $7~/\?\?R./ { print }'
  172. echo "Specify correct device on the command line."
  173. exit -1
  174. fi
  175. # Look for a GPT/EFI VTOC; if there isn't one, then this is almost
  176. # certainly an MBR-partitioned device. If it's a GPT label, then we
  177. # want the slice that's of type 2 (ROOT).
  178. if [[ -e "/dev/dsk/${removables[0]}" ]]; then
  179. partition=$(/usr/sbin/prtvtoc -h "/dev/dsk/${removables[0]}" | \
  180. awk ' $2 == 2 { print $1 }')
  181. if [[ $? -eq 0 && -n "$partition" ]]; then
  182. echo -n ", GPT label"
  183. usb="/dev/dsk/${removables[0]}s${partition}"
  184. fi
  185. fi
  186. if [[ -z "$usb" ]]; then
  187. echo -n ", MBR label"
  188. usb="/dev/dsk/${removables[0]}p1"
  189. fi
  190. else
  191. usb="$1"
  192. echo -n " using $usb"
  193. fi
  194. umount "$usb" 2>/dev/null
  195. mkdir usb
  196. if ! mount -F pcfs -o foldcase "$usb" "$tmp/usb" ; then
  197. echo ", mount failed"
  198. exit -1
  199. else
  200. echo -n ", mounted"
  201. fi
  202. if [[ ! -d usb/platform ]] ; then
  203. echo ", missing platform dir"
  204. exit -1
  205. else
  206. echo ", OK"
  207. fi
  208. echo -n "Updating platform on boot device..."
  209. if ! rsync -rltD "$platform_dir/" usb/platform.new/ ; then
  210. echo " failed"
  211. exit -1
  212. else
  213. echo " OK"
  214. fi
  215. echo -n "Remounting boot device..."
  216. umount "$usb" 2>/dev/null
  217. if ! mount -F pcfs -o foldcase "$usb" "$tmp/usb" ; then
  218. echo " failed"
  219. exit -1
  220. else
  221. echo " OK"
  222. fi
  223. echo -n "Verifying kernel checksum on boot device..."
  224. openssl dgst -sha1 "$platform_dir"/i86pc/kernel/amd64/unix | cut -d ' ' -f 2 > kernel.expected
  225. openssl dgst -sha1 usb/platform.new/i86pc/kernel/amd64/unix | cut -d ' ' -f 2 > kernel.actual
  226. if ! cmp -s kernel.actual kernel.expected ; then
  227. echo " failed"
  228. exit -1
  229. else
  230. echo " OK"
  231. fi
  232. echo -n "Verifying boot_archive checksum on boot device..."
  233. openssl dgst -sha1 usb/platform.new/i86pc/amd64/boot_archive | cut -d ' ' -f 2 > boot_archive.actual
  234. if ! cmp -s boot_archive.actual usb/platform.new/i86pc/amd64/boot_archive.hash ; then
  235. echo " failed"
  236. exit -1
  237. else
  238. echo " OK"
  239. fi
  240. echo -n "Activating new platform on $usb..."
  241. rm -rf usb/old
  242. mkdir usb/old
  243. if ! ( mv usb/platform usb/old && mv usb/platform.new usb/platform ) ; then
  244. echo " failed"
  245. exit -1
  246. else
  247. echo " OK"
  248. fi
  249. echo
  250. echo "Boot device upgraded. To do:"
  251. echo
  252. echo " 1) Sanity check the contents of $tmp/usb"
  253. echo " 2) umount $usb"
  254. echo " 3) reboot"