1 #Requires -Version 5.0
2 Set-StrictMode -Version Latest
3
4 <#
5 .SYNOPSIS
6 Updates openHAB to the latest version.
7 .DESCRIPTION
8 The Update-openHAB function performs the necessary tasks to update openHAB.
9 .PARAMETER OHDirectory
10 The directory where openHAB is installed (default: current directory).
11 .PARAMETER OHVersion
12 The version to upgrade to.
13 .PARAMETER Snapshot
14 DEPRECATED - Upgrade to a snapshot version ($true) or a release version ($false) (default: $false)
15 DEPRECATED - Please specify "-snapshot" in the OHVersion instead (ex: "3.0.0-SNAPSHOT")
16 .PARAMETER AutoConfirm
17 Automatically confirm update (used for headless mode)
18 .EXAMPLE
19 Update the openHAB distribution in the current directory to the current stable version
20 Update-openHAB
21 .EXAMPLE
22 Update the openHAB distribution in the C:\oh-snapshot directory to the next snapshot version
23 Update-openHAB -OHDirectory C:\oh-snapshot -OHVersion 3.0.0-SNAPSHOT
24 #>
25
26 ###########################################################################
27 # NOTE: changes in this script should be reflected in update.sh as well
28 ###########################################################################
29
Update-openHAB()30 Function Update-openHAB() {
31 [CmdletBinding()]
32 param(
33 [Parameter(ValueFromPipeline = $True)]
34 [string]$OHDirectory = ".",
35 [Parameter(ValueFromPipeline = $True)]
36 [string]$OHVersion,
37 [Parameter(ValueFromPipeline = $True)]
38 [boolean]$Snapshot = $false,
39 [Parameter(ValueFromPipeline = $True)]
40 [boolean]$AutoConfirm = $false,
41 [Parameter(ValueFromPipeline = $True)]
42 [boolean]$SkipNew = $false, # sssh - secret switch ;)
43 [Parameter(ValueFromPipeline = $True)]
44 [boolean]$KeepUpdateScript = $false # sssh - secret switch ;)
45 )
46
47 # Downloads the URL into a file showing a progress meter. Any error will be thrown to the caller
48
49 function DownloadFiles() {
50 param(
51 [Parameter(Mandatory = $True)]
52 [string] $URL,
53 [Parameter(Mandatory = $True)]
54 [string] $OutputFile
55 )
56
57 # Create the request
58 [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
59 $uri = New-Object "System.Uri" "$URL"
60 $request = [System.Net.HttpWebRequest]::Create($uri)
61 $request.set_Timeout(15000)
62
63 #Get the response (along with the total size)
64 $response = $request.GetResponse()
65 $totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)
66
67 try {
68 # Gets the response stream and setup the buffer
69 $responseStream = $response.GetResponseStream()
70 $targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $Outputfile, Create
71 $buffer = new-object byte[] 10KB
72
73 # Save console settings
74 $startTop = [System.Console]::CursorTop
75 $startVisibility = [System.Console]::CursorVisible
76 $startColor = [System.Console]::ForegroundColor
77
78 # Process each chunk into the output file (updating the progress meter along the way)
79 try {
80 [System.Console]::CursorVisible = $False
81 [System.Console]::ForegroundColor = "Blue"
82 $count = $responseStream.Read($buffer,0,$buffer.length)
83 $downloadedBytes = $count
84 while ($count -gt 0)
85 {
86 $bytes = [System.Math]::Floor($downloadedBytes/1024)
87 $perc = [System.Math]::Floor(($bytes / $totalLength) * 100)
88 [System.Console]::CursorLeft = 0
89 [System.Console]::CursorTop = $startTop
90 [System.Console]::Write("Downloaded {0}K of {1}K [{2}%]", $bytes, $totalLength, $perc)
91 $targetStream.Write($buffer, 0, $count)
92 $count = $responseStream.Read($buffer,0,$buffer.length)
93 $downloadedBytes = $downloadedBytes + $count
94 }
95 Write-Host "`nFinished Download"
96 } finally {
97 # Set the console settings back
98 [System.Console]::CursorVisible = $startVisibility
99 [System.Console]::ForegroundColor = $startColor
100 }
101 } finally {
102 # Cleanup resources
103 if ($targetStream) {
104 $targetStream.Flush()
105 $targetStream.Close()
106 $targetStream.Dispose()
107 }
108 if ($responseStream) {
109 $responseStream.Dispose()
110 }
111 }
112 }
113
114 # This function 'normalizes' the version number - creates left 0 padded segments "0000.0000.0000" that can be compared against
115 function NormalizeVersionNumber() {
116 param(
117 [Parameter(Mandatory = $True)]
118 [string] $VersionNumber
119 )
120
121 $parts = $VersionNumber.Split(".")
122 if ($parts.Length -eq 2) {
123 $parts += "0"
124 }
125 if ($parts.Length -ne 3) {
126 throw "$VersionNumber is not formatted correctly (d.d.d)"
127 }
128
129 $rc = "";
130 $parts | ForEach-Object {
131 $rc += $_.PadLeft(5 - $_.Length, '0')
132 $rc += "."
133 }
134 return $rc.Substring(0, $rc.Length - 1)
135 }
136
137 # This function will process a command from the upgrade.lst file (called from ProcessVersionChange)
138 function ProcessCommand() {
139 param(
140 [Parameter(Mandatory = $True)]
141 [string] $Line
142 )
143
144 # Use of global variables (not passed in)
145 $Line = $Line.Replace("`$OPENHAB_USERDATA", $OHUserData)
146 $Line = $Line.Replace("`$OPENHAB_CONF", $OHConf)
147 $Line = $Line.Replace("`$OPENHAB_HOME", $OHDirectory)
148 $Line = $Line.Replace("`$OPENHAB_RUNTIME", $OHRuntime)
149
150 # Split the line into it's distinct parts
151 $parts = $Line.Split(";")
152
153 # blank line - simply return
154 if ($parts.length -eq 0) {
155 return;
156 }
157
158 # If default - rename an item to "x.bak" (assumes a new version of this file will be added by the upgrade process)
159 if ($parts[0] -eq "DEFAULT") {
160 if ($parts.length -le 1) {
161 Write-Host -ForegroundColor Red "Badly formatted: $Line"
162 }
163 else {
164 try {
165 Rename-Item -Path $parts[1] "$parts[1].bak" -ErrorAction Stop
166 Write-Host -ForegroundColor Cyan "$($parts[1]) renamed to $($parts[1]).bak"
167 }
168 catch {
169 Write-Host -ForegroundColor Yellow "Could not rename $($parts[1]) to $($parts[1]).bak"
170 }
171 }
172 }
173
174 # Deletes an item
175 ElseIf ($parts[0] -eq "DELETEDIR" -or $parts[0] -eq "DELETE") {
176 if ($parts.length -le 1) {
177 Write-Host -ForegroundColor Red "Badly formatted: $Line"
178 }
179 else {
180 try {
181 if ($parts[0] -eq "DELETEDIR") {
182 DeleteIfExists $parts[1] $True
183 } else {
184 DeleteIfExists $parts[1]
185 }
186 Write-Host -ForegroundColor Cyan "Deleted $($parts[1])"
187 }
188 catch {
189 Write-Host -ForegroundColor Yellow "Could not delete $($parts[1])"
190
191 }
192 }
193 }
194
195 # Moves an item
196 ElseIf ($parts[0] -eq "MOVE") {
197 if ($parts.length -le 2) {
198 Write-Host -ForegroundColor Red "Badly formatted: $Line"
199 }
200 else {
201 try {
202 Move-Item -Path $parts[1] -Destination $parts[2] -ErrorAction Stop
203 Write-Host -ForegroundColor Cyan "Moved $($parts[1]) to $($parts[2])"
204 }
205 catch {
206 Write-Host -ForegroundColor Yellow "Could not move $($parts[1]) to $($parts[2])"
207 }
208 }
209 }
210
211 # Replaces text in a file
212 ElseIf ($parts[0] -eq "REPLACE") {
213 if ($parts.length -le 3) {
214 Write-Host -ForegroundColor Red "Badly formatted: $Line"
215 }
216 else {
217 try {
218 (Get-Content $parts[3]).replace($parts[1], $parts[2]) | Set-Content $parts[3]
219 Write-Host -ForegroundColor Cyan "Replaced string $($parts[1]) to $($parts[2]) in file $($parts[3])"
220 }
221 catch {
222 Write-Host -ForegroundColor Yellow "Could not replace string $($parts[1]) to $($parts[2]) in file $($parts[3])"
223 }
224 }
225 }
226
227 # Shows a note (console message with a green label)
228 ElseIf ($parts[0] -eq "NOTE") {
229 if ($parts.length -le 1) {
230 Write-Host -ForegroundColor Red "Badly formatted: $Line"
231 }
232 else {
233 Write-Host -ForegroundColor Green "Note: " -NoNewLine
234 Write-Host $parts[1]
235 }
236 }
237 # Shows a note (console message with a red label)
238 ElseIf ($parts[0] -eq "ALERT") {
239 if ($parts.length -le 1) {
240 Write-Host -ForegroundColor Red "Badly formatted: $Line"
241 }
242 else {
243 Write-Host -ForegroundColor Red "Warning: " -NoNewLine
244 Write-Host $parts[1]
245 }
246 }
247 Else {
248 Write-Host -ForegroundColor Red "Unknown command: $Line"
249 }
250 }
251
252 # Processes the update.lst file for the specific section, and version (going from x.x.x to x.x.x).
253 # A boolean is returned indicating whether we found any commands or not
254 function ProcessVersionChange() {
255 param(
256 [Parameter(Mandatory = $True)]
257 [string] $FileName,
258 [Parameter(Mandatory = $True)]
259 [string] $Section,
260 [Parameter(Mandatory = $True)]
261 [string] $VersionMsg,
262 [Parameter(Mandatory = $True)]
263 [string] $OldVersion,
264 [Parameter(Mandatory = $True)]
265 [string] $NewVersion
266 )
267
268 # Flags used
269 $InSection = $false
270 $InNewVersion = $false
271
272 # Normalize our lower/upper versions
273 $NormalizedOldVersion = NormalizeVersionNumber $OldVersion
274 $NormalizedNewVersion = NormalizeVersionNumber $NewVersion
275
276 # FoundSomething is true if we did some action (and is returned to caller)
277 $FoundSomething = $False
278
279 # Loops through the content of the file...
280 Get-Content $FileName -ErrorAction Stop | ForEach-Object {
281 # Skip blank lines
282 if ($_ -ne "") {
283 # If it's OUR section - flip the switch
284 if ($_ -match "\[\[$Section\]\]") {
285 $InSection = $True
286 }
287 # If it's not OUR section - flip it false
288 ElseIf ($_ -match "\[\[.*\]\]") {
289 $InSection = $false
290 $InNewVersion = $false
291 }
292 # If its a version number section
293 ElseIf ($_ -match "\[\d\.*\d\.*\d\]") {
294 # Determine if we are in a section and the version number is greater than our lower bound but less than or equal to our upper bound
295 if ($InSection) {
296 $NormalizedSectionVersion = NormalizeVersionNumber $_.Substring(1, $_.length - 2)
297 $InNewVersion = ($NormalizedSectionVersion -gt $NormalizedOldVersion) -and ($NormalizedSectionVersion -le $NormalizedNewVersion)
298 if ($InNewVersion -and $InSection) {
299 # If so, show that we are processing this section
300 Write-Host ""
301 Write-Host -ForegroundColor Cyan "$VersionMsg $_ :"
302 }
303 }
304 }
305 else {
306 if ($InSection -and $InNewVersion) {
307 # Woohoo - found a command to process
308 $FoundSomething = $True
309 ProcessCommand $_
310 }
311 }
312 }
313 }
314
315 return $FoundSomething
316 }
317
318 # Force reimport of common functions (in case of upgrading the script)
319 Import-Module $PSScriptRoot\common.psm1 -Force
320
321 # Write out startup message
322 Write-Host ""
323 BoxMessage "openHAB update script" Magenta
324 Write-Host ""
325
326 # Check for admin (commented out - don't think we need it)
327 # CheckForAdmin
328
329 # Check for openhab running
330 CheckOpenHABRunning
331
332 # Check if service is installed, stop and delete it
333 Write-Host -ForegroundColor Cyan "Checking whether a service exists"
334 try {
335 $service = Get-Service 'openHAB%' -ErrorAction Ignore
336 if ($service) {
337 # Stop and delete the service
338 Write-Host -ForegroundColor Cyan "Stopping the service"
339 Stop-Service $service.Name -Force -ErrorAction Stop
340 Write-Host -ForegroundColor Cyan "Deleting the service"
341 Remove-Service $service.Name -ErrorAction Stop
342 }
343 }
344 catch {
345 exit PrintAndReturn "Could not stop/delete the openHAB windows server - please do that manually and try again" $_
346 }
347
348
349 # Find the proper directory root directory
350 Write-Host -ForegroundColor Cyan "Checking the specified openHAB directory"
351 $OHDirectory = GetOpenHABRoot $OHDirectory
352 if ($OHDirectory -eq "") {
353 exit PrintAndReturn "Could not find the openHAB directory! Make sure you are in the openHAB directory or specify the -OHDirectory parameter!"
354 }
355
356 # Get the various 'other' directories
357 $OHConf = GetOpenHABDirectory "OPENHAB_CONF" "$OHDirectory\conf"
358 $OHUserData = GetOpenHABDirectory "OPENHAB_USERDATA" "$OHDirectory\userdata"
359 $OHRuntime = GetOpenHABDirectory "OPENHAB_RUNTIME" "$OHDirectory\runtime"
360 $OHAddons = GetOpenHABDirectory "OPENHAB_ADDONS" "$OHDirectory\addons"
361
362 # Validate that all the directories exist (and are directories)
363 if (-NOT (Test-Path -Path $OHConf -PathType Container)) {
364 exit PrintAndReturn "Configuration directory does not exist: $OHConf"
365 }
366
367 if (-NOT (Test-Path -Path $OHUserData -PathType Container)) {
368 exit PrintAndReturn "Userdata directory does not exist: $OHUserData"
369 }
370
371 if (-NOT (Test-Path -Path $OHRuntime -PathType Container)) {
372 exit PrintAndReturn "Runtime directory does not exist: $OHRuntime"
373 }
374
375 if (-NOT (Test-Path -Path $OHAddons -PathType Container)) {
376 exit PrintAndReturn "Addons directory does not exist: $OHAddons"
377 }
378
379 # Tell the user what we are processing
380 Write-Host -ForegroundColor Yellow "Using $OHConf as conf folder"
381 Write-Host -ForegroundColor Yellow "Using $OHUserData as userdata folder"
382 Write-Host -ForegroundColor Yellow "Using $OHRuntime as runtime folder"
383 Write-Host -ForegroundColor Yellow "Using $OHAddons as addons folder"
384
385 # Get current openHAB version
386 $CurrentVersion = GetOpenHABVersion $OHUserData
387 if ($CurrentVersion -eq "") {
388 exit PrintAndReturn "Can't get the current openhab version from $OHUserData\etc\version.properties"
389 }
390
391 # Get the current version (d.d.d)
392 # If stable, simply use d.d.d
393 # If snapshot, strip the "-snapshot" part (d.d.d-snapshort)
394 # If milestone, strip the milestone part (d.d.d.milestone)
395 $parts = $CurrentVersion.Split(".")
396 if (($parts.Length -lt 3) -or ($parts.Length -gt 4)) {
397 exit PrintAndReturn "Current openhab version from $OHUserData\etc\version.properties is malformed. Should be either d.d.d (for stable) or d.d.d-snapshot (for snapshot) or d.d.d.d (for milestones) - malformed version: $CurrentVersion"
398 }
399
400 if ($parts[2].EndsWith("-SNAPSHOT", "CurrentCultureIgnoreCase")) {
401 $CurrentVersion = $parts[0] + "." + $parts[1] + "." + $parts[2].Substring(0, $parts[2].Length - "-SNAPSHOT".Length);
402 }
403 else {
404 $CurrentVersion = $parts[0] + "." + $parts[1] + "." + $parts[2]
405 }
406 Write-Host -ForegroundColor Yellow "The current version is $CurrentVersion"
407
408 # If the OHVersion parameter was not specified,
409 # If the current version is snapshot - make OHVersion the same snapshot
410 # If the current version is stable - make OHVersion the next minor upgrade (current version 3.0.0 would make our OHversion 3.1.0)
411 # If the current version is milestone - make OHVersion the stable version (3.1.0.M6 becomes 3.1.0)
412 if (-Not $OHVersion) {
413 if ($parts.Length -eq 3) {
414 if ($parts[2].EndsWith("-SNAPSHOT", "CurrentCultureIgnoreCase")) {
415 $OHVersion = $parts[0] + "." + $parts[1] + "." + $parts[2]
416 } else {
417 $OHVersion = $parts[0] + "." + ([int]$parts[1] + 1) + "." + $parts[2]
418 }
419 } elseif ($parts.Length -eq 4) {
420 $OHVersion = $parts[0] + "." + $parts[1] + "." + $parts[2]
421 }
422 else {
423 exit PrintAndReturn "The current version $CurrentVersion was not formatted correctly (d.d.d)"
424 }
425 }
426
427 # If snapshot was defined, add "-snapshot" to the OHVersion if not already present
428 if ($Snapshot -eq $true) {
429 BoxMessage "-SNAPSHOT is deprecated - please put '-snapshot' in OHVersion instead (ex: 3.1.0-snapshot)" Magenta
430 if (-Not $OHVersion.EndsWith("-SNAPSHOT", "CurrentCultureIgnoreCase")) {
431 $OHVersion = $OHVersion + "-SNAPSHOT"
432 }
433 }
434
435 # Split up the OHVersion to validate
436 $parts = $OHVersion.Split(".")
437
438 # If only "x.y" - make "x.y.0"
439 if ($parts.Length -eq 2) {
440 $parts += "0"
441 }
442
443 # Valid versions:
444 # Stable: "3.x.y"
445 # Snapshot: "3.x.y-SNAPSHOT"
446 # Milestone: "3.x.y.Mz"
447 if (($parts.Length -lt 3) -or ($parts.Length -gt 4)) {
448 exit PrintAndReturn "The specified OH version $OHVersion was not formatted correctly (d.d.d[.d])"
449 }
450
451 $Snapshot = $False
452 $Milestone = ""
453 if ($parts[2].EndsWith("-SNAPSHOT", "CurrentCultureIgnoreCase")) {
454 $Snapshot = $True
455 $parts[2] = $parts[2].Substring(0, $parts[2].Length - "-SNAPSHOT".Length);
456 } elseif ($parts.Length -eq 4) {
457 $Milestone = $parts[3]
458 }
459 $OHVersion = $parts[0] + "." + $parts[1] + "." + $parts[2]
460
461 # Recreate the name - should be standardized now and is used for messages and downloads
462 if ($Snapshot -eq $True) {
463 $OHVersionName = "$OHVersion-SNAPSHOT"
464 } elseif ($Milestone -ne "") {
465 $OHVersionName = $OHVersion + "." + $Milestone
466 } else {
467 $OHVersionName = $OHVersion
468 }
469
470 # Get the current directory (so we can switch back to it at the end)
471 try {
472 $StartDir = Get-Location -ErrorAction Stop
473 }
474 catch {
475 exit PrintAndReturn "Can't retrieve the current location - exiting" $_
476 }
477
478 # Set the current directory to our OH root directory
479 Write-Host -ForegroundColor Cyan "Changing location to $OHDirectory"
480 try {
481 Set-Location -Path $OHDirectory
482 }
483 catch {
484 exit PrintAndReturn "Could not change location to $OHDirectory - exiting" $_
485 }
486
487 # Setup where our temporary locations will be
488 $TempDir = "$(GetOpenHABTempDirectory)"
489 $TempDistributionZip = "$TempDir\openhab-$OHVersion.zip";
490 $TempDistribution = "$TempDir\update"
491
492 # Create the proper download URLs
493 if ($Snapshot) {
494 $DownloadLocation="https://ci.openhab.org/job/openHAB3-Distribution/lastSuccessfulBuild/artifact/distributions/openhab/target/openhab-$OHVersionName.zip"
495 $AddonsDownloadLocation="https://ci.openhab.org/job/openHAB3-Distribution/lastSuccessfulBuild/artifact/distributions/openhab-addons/target/openhab-addons-$OHVersionName.kar"
496 }
497 elseif ($Milestone -ne "") {
498 $DownloadLocation="https://www.openhab.org/download/milestones/org/openhab/distro/openhab/$OHVersionName/openhab-$OHVersionName.zip"
499 $AddonsDownloadLocation="https://www.openhab.org/download/milestones/org/openhab/distro/openhab-addons/$OHVersionName/openhab-addons-$OHVersionName.kar"
500 }
501 else {
502 $DownloadLocation = "https://www.openhab.org/download/releases/org/openhab/distro/openhab/$OHVersionName/openhab-$OHVersionName.zip"
503 $AddonsDownloadLocation = "https://www.openhab.org/download/releases/org/openhab/distro/openhab-addons/$OHVersionName/openhab-addons-$OHVersionName.kar"
504 }
505
506 # If we are not in SkipNew (or SkipNew and the temporary distribution file/folders have not been created yet):
507 # 1. Delete and recreate the temporary distribution directory if it exists
508 # 2. Download the distribution to the temp directory
509 # 3. Expand the distribution to the temp directory
510 # 4. Copy the update.ps1/common.psm1 files to the temp distribution if KeepUpdateScript is true (dev purposes only)
511 if (($SkipNew -eq $False) -or
512 (($SkipNew -eq $True) -and -NOT
513 ((Test-Path -Path $TempDistributionZip -PathType Leaf) -and (Test-Path -Path $TempDistribution -PathType Container))
514 )
515 ) {
516 ########### STEP 1 - Delete and recreate the temporary distribution directory if it exists
517 try {
518 DeleteIfExists $TempDir $True
519 }
520 catch {
521 # Do nothing here - probably a file lock issue
522 }
523
524 try {
525 Write-Host -ForegroundColor Cyan "Creating temporary update directory $TempDir"
526 CreateDirectory $TempDir
527 }
528 catch {
529 exit PrintAndReturn "Error creating temporary update directory $TempDir - exiting" $_
530 }
531
532 ########### STEP 2 - download the distribution
533 try {
534 Write-Host -ForegroundColor Cyan "Downloading the openHAB $OHVersionName distribution to $TempDistributionZip"
535 DownloadFiles $DownloadLocation $TempDistributionZip
536 }
537 catch {
538 if ([int]$_.Exception.InnerException.Response.StatusCode -eq 404) {
539 exit PrintAndReturn "Download of $OHVersionName failed because it's not a valid version" $_
540 } else {
541 exit PrintAndReturn "Download of $DownloadLocation failed" $_
542 }
543 }
544
545 ########### STEP 3 - Expand the archive
546 try {
547 Write-Host -ForegroundColor Cyan "Extracting the archive ($TempDistributionZip) to $TempDistribution"
548 Expand-Archive -Path $TempDistributionZip -DestinationPath $TempDistribution -Force -ErrorAction Stop
549 } catch {
550 exit PrintAndReturn "Unzipping of $TempDistributionZip to $TempDistribution failed." $_
551 }
552
553 ########### STEP 4 - Copy the update/common over if we are keeping the update scripts
554 if ($KeepUpdateScript) {
555 try {
556 Write-Host -ForegroundColor Cyan "Keeping commons.psm1 and update.ps1 by copying to $TempDistribution\runtime\bin"
557 Copy-Item -Path "$OHRuntime\bin\common.psm1" -Destination "$TempDistribution\runtime\bin\common.psm1" -Force
558 Copy-Item -Path "$OHRuntime\bin\update.ps1" -Destination "$TempDistribution\runtime\bin\update.ps1" -Force
559 } catch {
560 Write-Error $_
561 Write-Host -ForegroundColor Magenta "Could not copy the common.psm1 and update.ps1 to $TempDistribution\runtime\bin"
562 # Don't bother with AutoConfirm here since this is special debugging logic to begin with
563 $confirmation = Read-Host "Okay to Continue? [y/N]"
564 if ($confirmation -ne 'y') {
565 exit PrintAndReturn "Cancelling update"
566 }
567 }
568 }
569 }
570
571 # If not SkipNew - check to see if the new distribution has an update.ps1 (which is likely)
572 # and then execute it (exiting with it's result)
573 if ($SkipNew -eq $False) {
574 $newUpdate = Join-Path $TempDistribution "\runtime\bin\update.ps1"
575
576 If (Test-Path $newUpdate) {
577 Write-Host ""
578 BoxMessage "New update.ps1 was found - executing it instead (found in $newUpdate)" Magenta
579 Write-Host ""
580 try {
581 # go back to our original directory so the new update script does it as well
582 Set-Location -Path $StartDir -ErrorAction Continue
583 . $newUpdate
584 exit Update-openHAB -OHDirectory $OHDirectory -OHVersion $OHVersionName -AutoConfirm $AutoConfirm -SkipNew $true -KeepUpdateScript $KeepUpdateScript
585 } catch {
586 exit PrintAndReturn "Execution of new update.ps1 failed - please execute it yourself (found in $newUpdate)" $_
587 }
588 }
589 }
590
591 # Do the following questions after the update.ps1 check to make sure this question isn't asked twice!
592
593 # Are we resinstalling the current version (as long as it's not a snapshot)
594 if ($OHVersion -eq $CurrentVersion -and $Snapshot -eq $False) {
595 if ($AutoConfirm) {
596 Write-Host -ForegroundColor Magenta "Current version is equal to specified version ($OHVersionName). ***REINSTALLING*** $OHVersionName instead (rather than upgrading)."
597 } else {
598 Write-Host -ForegroundColor Magenta "Current version is equal to specified version ($OHVersionName). If you continue, you will REINSTALL $OHVersionName rather than upgrade."
599 $confirmation = Read-Host "Okay to Continue? [y/N]"
600 if ($confirmation -ne 'y') {
601 exit PrintAndReturn "Cancelling update"
602 }
603 }
604 Write-Host -ForegroundColor Yellow "REINSTALLING" -NoNewline -BackgroundColor Blue
605 Write-Host -ForegroundColor Yellow " version $OHVersionName"
606 } else {
607
608 # Are we trying to downgrade the distribution (yikes!)
609 if ((NormalizeVersionNumber $OHVersion) -lt (NormalizeVersionNumber $CurrentVersion)) {
610 # Don't use autoconfirm on a downgrade warning
611 BoxMessage "You are attempting to downgrade from $CurrentVersion to $OHVersionName !!!" Red
612 Write-Host -ForegroundColor Magenta "This script is not meant to downgrade and the results will be unpredictable"
613 $confirmation = Read-Host "Okay to Continue? [y/N]"
614 if ($confirmation -ne 'y') {
615 exit PrintAndReturn "Cancelling update"
616 }
617 Write-Host -ForegroundColor Yellow "DOWNGRADING" -NoNewline -BackgroundColor Red
618 Write-Host -ForegroundColor Yellow " to version $OHVersionName"
619 } else {
620 Write-Host -ForegroundColor Yellow "Upgrading to version $OHVersionName"
621 }
622 }
623
624
625 # Crete the temporary backup locations to the current distribution
626 $TempBackupDir = "$TempDir\backup-$CurrentVersion"
627 $TempBackupDirHome = $TempBackupDir + "\home"
628 $TempBackupDirRuntime = $TempBackupDir + "\runtime"
629 $TempBackupDirUserData = $TempBackupDir + "\userdata"
630 $TempBackupDirConf = $TempBackupDir + "\conf"
631
632 # Backup the current distribution to those locations
633 Write-Host ""
634 Write-Host -ForegroundColor Cyan "Making a backup of your distribution to $TempBackupDir"
635 try {
636 Write-Host -ForegroundColor Cyan "Creating backup directories in $TempBackupDir"
637 DeleteIfExists $TempBackupDir $True
638
639 Write-Host -ForegroundColor Cyan "Copying directory conf, userdata and runtime to $TempBackupDirConf"
640 Copy-Item -Path $OHConf, $OHUserData, $OHRuntime -Destination $TempBackupDir -Recurse -Force -ErrorAction Stop
641
642 Write-Host -ForegroundColor Cyan "Copying files from $OHDirectory to $TempBackupDirHome"
643 Get-ChildItem $OHDirectory -File -ErrorAction Stop | Copy-Item -Destination $TempBackupDirHome -Force -ErrorAction Stop
644
645 } catch {
646 exit PrintAndReturn "Could not backup existing distribution to $TempBackupDir" $_
647 }
648
649 # Alright - we are ready to being the update process. This will be wrapped in a
650 # try/catch/finally to restore our current distribution on error and to cleanup
651 # the temporary files when finished
652 try {
653
654 # If our update.lst exists, process the notes (ie MSG section) and the PRE section
655 $updateLst = Join-Path $TempDistribution "\runtime\bin\update.lst"
656
657 if (Test-Path $updateLst) {
658 Write-Host ""
659 Write-Host -ForegroundColor Cyan "The script will attempt to update openHAB to version $OHVersionName"
660 Write-Host -ForegroundColor Cyan "Please read the following " -NoNewLine
661 Write-Host -ForegroundColor Green "notes" -NoNewLine
662 Write-Host -ForegroundColor Cyan " and " -NoNewLine
663 Write-Host -ForegroundColor Red "warnings"
664 $NotesFound = $False
665 try {
666 $NotesFound = ProcessVersionChange $updateLst "MSG" "Important notes for version" $CurrentVersion $OHVersion
667 } catch {
668 # PrintAndReturn since there have been no file changes yet
669 exit PrintAndReturn "Could not process 'MSG' of $updateLst" $_
670 }
671
672 if ($NotesFound) {
673 if (-Not $AutoConfirm) {
674 $confirmation = Read-Host "Okay to Continue? [y/N]"
675 if ($confirmation -ne 'y') {
676 exit PrintAndReturn "Cancelling update"
677 }
678 }
679 } else {
680 Write-Host -ForegroundColor Blue "No notes found for version $OHVersionName"
681 }
682
683 try {
684 Write-Host ""
685 Write-Host -ForegroundColor Cyan "Execute 'PRE' instructions for version $OHVersionName"
686 if (-NOT (ProcessVersionChange $updateLst "PRE" "Performing pre-update tasks for version" $CurrentVersion $OHVersion)) {
687 Write-Host -ForegroundColor Blue "No 'PRE' instructions found for version $OHVersionName"
688 }
689 } catch {
690 return PrintAndThrow "Could not process 'PRE' of $updateLst" $_
691 }
692 Write-Host ""
693 }
694
695
696 # Delete current userdata files
697 # Update openHAB
698 # 1. First remove all file in runtime (they will all be replaced)
699 # 2. Remove all the userdata\etc files listed in userdata_sysfiles.lst (they may be replaced)
700 # 3. Remove the cache/tmp directories
701 # 4. Then copy all files from our new distribution WITHOUT overwriting anything
702 # (by removals in 1 & 2 - that means we will replace those)
703 #
704
705 ############## STEP 1 - remove runtime
706 try {
707 Write-Host -ForegroundColor Cyan "Deleting current runtime ($OHRuntime)"
708 DeleteIfExists $OHRuntime $True
709 } catch {
710 return PrintAndThrow "Could not delete current runtime ($OHRuntime)" $_
711 }
712
713 ############## STEP 2 - remove userdata\etc files in userdata_sysfiles.lst
714 $updateSysFilesLst = "$TempDistribution\runtime\bin\userdata_sysfiles.lst"
715 if (Test-Path $updateSysFilesLst) {
716 Write-Host -ForegroundColor Cyan "Deleting current files in userdata that should not persist"
717 foreach ($FileName in Get-Content $updateSysFilesLst) {
718 $fileToDelete = "$OHUserData\etc\$FileName"
719 try {
720 if (Test-Path -Path $fileToDelete) {
721 DeleteIfExists $fileToDelete
722 Write-Host -ForegroundColor Cyan "Deleted $FileName from $OHUserData\etc"
723 }
724 } catch {
725 Write-Error $_
726 Write-Host "Could not delete $fileToDelete. File is no longer needed and should be manually deleted."
727 }
728 }
729 }
730
731 ############## STEP 3 - remove cache/tmp directories
732 try {
733 Write-Host -ForegroundColor Cyan "Removing $OHUserData\cache"
734 DeleteIfExists "$OHUserData\cache" $True
735 } catch {
736 return PrintAndThrow "Could not delete the $OHUserData\cache directory" $_
737 }
738
739 try {
740 Write-Host -ForegroundColor Cyan "Removing $OHUserData\tmp"
741 DeleteIfExists "$OHUserData\tmp" $True
742 } catch {
743 return PrintAndThrow "Could not delete the $OHUserData\tmp directory" $_
744 }
745
746 ############## STEP 4 - copy files from temporary to distribution WITHOUT replacement
747 Write-Host -ForegroundColor Cyan "Copying $TempDistribution to $OHDirectory without overwriting existing ones"
748 try {
749 Get-ChildItem -Path $TempDistribution -Recurse -ErrorAction Stop | ForEach-Object {
750 $relPath = GetRelativePath $TempDistribution $_.FullName
751
752 if ($relPath.StartsWith(".\addons")) {
753 $localPath = Join-Path $OHAddons $relPath.Substring(".\addons".Length)
754 } elseif ($relPath.StartsWith(".\conf")) {
755 $localPath = Join-Path $OHConf $relPath.Substring(".\conf".Length)
756 } elseif ($relPath.StartsWith(".\userdata")) {
757 $localPath = Join-Path $OHUserData $relPath.Substring(".\userdata".Length)
758 } elseif ($relPath.StartsWith(".\runtime")) {
759 $localPath = Join-Path $OHRuntime $relPath.Substring(".\runtime".Length)
760 } else {
761 $localPath = Join-Path $OHDirectory $relPath
762 }
763 if (-Not (Test-Path $localPath)) {
764 if (Test-Path $localPath -PathType Container) {
765 CreateDirectory $localPath
766 } else {
767 Copy-Item -Path $_.FullName -Destination $localPath -ErrorAction Stop
768 }
769 }
770 }
771 } catch {
772 return PrintAndThrow "Error occurred copying $TempDistribution to $OHDirectory" $_
773 }
774
775 # If we have an update.lst - process the "POST" section
776 if (Test-Path $updateLst) {
777 Write-Host ""
778 try {
779 Write-Host -ForegroundColor Cyan "Execute 'POST' instructions for version $OHVersionName"
780 if (-NOT (ProcessVersionChange $updateLst "POST" "Performing post-update tasks for version" $CurrentVersion $OHVersion)) {
781 Write-Host -ForegroundColor Blue "No 'POST' instructions found for version $OHVersionName"
782 }
783 } catch {
784 return PrintAndThrow "Could not process 'POST' of $updateLst" $_
785 }
786 }
787 Write-Host ""
788
789
790 # If there's an existing addons file, we need to replace it with the correct version.
791 try {
792 $AddonsFile = "$OHAddons\openhab-addons-$OHVersionName.kar"
793 if (Test-Path -Path $AddonsFile) {
794 Write-Host "Found an openHAB addons file, replacing with new version"
795 DeleteIfExists $AddonsFile
796 DownloadFiles $AddonsDownloadLocation "$OHAddons\openhab-addons-$OHVersionName.kar"
797 }
798 } catch {
799 return PrintAndThrow "Could not replace the $AddonsFile" $_
800 }
801
802
803 # Hop for joy - we did it!
804 Write-Host -ForegroundColor Green "openHAB updated to version $OHVersionName!"
805 Write-Host -ForegroundColor Green "Run start.bat to launch it."
806 Write-Host -ForegroundColor Green "Check https://www.openhab.org/docs/installation/windows.html"
807 Write-Host -ForegroundColor Green "for instructions on re-installing the Windows Service if desired"
808 }
809 catch {
810
811 # Some issue happened - we need to copy the old distribution back
812 BoxMessage "Restoring your distribution from $TempBackupDir" Yellow
813 try {
814 Write-Host -ForegroundColor Cyan "Removing existing files in $OHDirectory"
815 Get-ChildItem $OHDirectory -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue
816 Write-Host -ForegroundColor Cyan "Copying backup files from $TempBackupDirHome to $OHDirectory"
817 Get-ChildItem $TempBackupDirHome -file -ErrorAction Stop | Copy-Item -Destination $OHDirectory -Force -ErrorAction Stop
818
819 Write-Host -ForegroundColor Cyan "Removing the directory $OHConf"
820 Remove-Item "$OHConf\*" -Recurse -Force -ErrorAction SilentlyContinue
821 Write-Host -ForegroundColor Cyan "Copying backup directory $TempBackupDirConf to $OHConf"
822 Copy-Item -Path "$TempBackupDirConf\*" -Destination $OHConf -Recurse -Force -ErrorAction Stop
823
824 Write-Host -ForegroundColor Cyan "Removing the directory $OHUserData"
825 Remove-Item "$OHUserData\*" -Recurse -Force -ErrorAction SilentlyContinue
826 Write-Host -ForegroundColor Cyan "Copying backup directory $TempBackupDirUserData to $OHUserData"
827 Copy-Item -Path "$TempBackupDirUserData\*" -Destination $OHUserData -Recurse -Force -ErrorAction Stop
828
829 Write-Host -ForegroundColor Cyan "Removing the directory $OHRuntime"
830 Remove-Item "$OHRuntime\*" -Recurse -Force -ErrorAction SilentlyContinue
831 Write-Host -ForegroundColor Cyan "Copying backup directory $TempBackupDirRuntime to $OHRuntime"
832 Copy-Item -Path "$TempBackupDirRuntime\*" -Destination $OHRuntime -Recurse -Force -ErrorAction Stop
833 } catch {
834 Write-Host -ForegroundColor Cyan "Restoration was unsuccessful - you may want to restore from $TempBackupDir yourself"
835 Write-Error $_
836 }
837 exit -1
838 }
839 finally {
840 # And we are done...
841 Write-Host ""
842
843 # If our temp backup directory exists - ask if we should remove it
844 # TODO - maybe only do this if an error occurred
845 try {
846 if (Test-Path $TempBackupDir) {
847 if ($AutoConfirm) {
848 Write-Host -ForegroundColor Cyan "Removing temporary distribution backup $TempBackupDir"
849 DeleteIfExists $TempBackupDir $True
850 } else {
851 Write-Host -ForegroundColor Cyan "Your prior distribution is in $TempBackupDir"
852 $confirmation = Read-Host "Should it be deleted? [y/N]"
853 if ($confirmation -eq 'y') {
854 Write-Host -ForegroundColor Cyan "Removing temporary distribution backup $TempBackupDir"
855 DeleteIfExists $TempBackupDir $True
856 }
857 }
858 }
859 }
860 catch {
861 Write-Host -ForegroundColor Red "Could not delete $TempBackupDir - delete it manually"
862 }
863
864 try {
865 # If the backup directory doesn't exist - delete the tempdir directory (and it's parent)
866 # (may exist if they answer "N" to the above question)
867 if (-NOT (Test-Path $TempBackupDir)) {
868 try {
869 Write-Host -ForegroundColor Cyan "Removing temporary directory $TempDir"
870 DeleteIfExists $TempDir $True
871 }
872 catch {
873 Write-Host -ForegroundColor Red "Could not delete $TempDir - delete it manually"
874 }
875 }
876 }
877 catch {
878 Write-Host -ForegroundColor Red "Could not delete $parent - delete it manually"
879 }
880
881 # FINALLY - set our location back to where we began
882 Write-Host -ForegroundColor Cyan "Setting location back to $StartDir"
883 Set-Location -Path $StartDir -ErrorAction Continue
884 }
885 }
886