Ability to install only new patch versions of firmware updates.

More logs detalization.
Some fixes and improvements
Fixed issue - https://github.com/beeyev/Mikrotik-Firmware-Auto-Updater/issues/1
This commit is contained in:
Alexander Beeyev 2019-01-26 17:20:49 +03:00
parent d716e87d55
commit 207090873a

View file

@ -3,7 +3,7 @@
########## Set variables
## Notification e-mail
:local emailEnabled true;
:local emailAddress "email@example.com";
:local emailAddress "yourmail@example.com";
:local sendBackupToEmail true;
## Backup encryption password, no encryption if no password.
@ -12,33 +12,168 @@
:local sensetiveDataInConfig false;
## Update channel. Possible values: current, bugfix
## Temporarily disabled
##:local updateChannel "current";
:local updateChannel "stable";
## Install only patch versions of firmware updates.
## Means that new update will be installed only if major and minor version numbers are same as currently installed firmware.
## Example: v6.43.6 => major.minor.PATCH
:local onlyPatchUpdates false;
##########
## !!!! DO NOT CHANGE ANYTHING BELOW THIS LINE, IF YOU ARE NOT SURE WHAT YOU ARE DOING !!!! ##
############### vvvvvvvvv GLOBAL FUNCTIONS vvvvvvvvv ###############
# Function converts standard mikrotik build versions to the number.
# Possible arguments: osVer
# Example:
# :put [$getOsVerNum osVer=[/system routerboard get current-firmware]];
# result will be: 64301, because current-firmware value is: 6.43.1
:global getOsVerNum do={
:local osVerNum;
:local osVerMicroPart;
:local zro 0;
:local tmp;
:local dotPos1 [:find $osVer "." 0];
:if ($dotPos1 > 0) do={
# AA
:set osVerNum [:pick $osVer 0 $dotPos1];
:local dotPos2 [:find $osVer "." $dotPos1];
#Taking minor version, everything after first dot
:if ([:len $dotPos2] = 0) do={:set tmp [:pick $osVer ($dotPos1+1) [:len $osVer]];}
#Taking minor version, everything between first and second dots
:if ($dotPos2 > 0) do={:set tmp [:pick $osVer ($dotPos1+1) $dotPos2];}
# AA 0B
:if ([:len $tmp] = 1) do={:set osVerNum "$osVerNum$zro$tmp";}
# AA BB
:if ([:len $tmp] = 2) do={:set osVerNum "$osVerNum$tmp";}
:if ($dotPos2 > 0) do={
:set tmp [:pick $osVer ($dotPos2+1) [:len $osVer]];
# AA BB 0C
:if ([:len $tmp] = 1) do={:set osVerNum "$osVerNum$zro$tmp";}
# AA BB CC
:if ([:len $tmp] = 2) do={:set osVerNum "$osVerNum$tmp";}
} else={
# AA BB 00
:set osVerNum "$osVerNum$zro$zro";
}
} else={
# AA 00 00
:set osVerNum "$osVer$zro$zro$zro$zro";
}
:return $osVerNum;
}
############### ^^^^^^^^^ GLOBAL FUNCTIONS ^^^^^^^^^ ###############
#Check proper email config
:if ($emailEnabled = true and ([:len $emailAddress] = 0 or [:len [/tool e-mail get address]] = 0 or [:len [/tool e-mail get from]] = 0)) do={
:log warning ("Email notifications switched off, you need to check your e-mail configuration. Tools -> Email");
:set emailEnabled false;
}
:log info ("Firmware checking and upgrade process has started");
#load global var
:global beePatchUpdateInapplicable;
## Set global var to the local one, then delete it form the global environment
:global beeGlobalUpdateStep;
:local updateStep $beeGlobalUpdateStep;
/system script environment remove beeGlobalUpdateStep
/system script environment remove beeGlobalUpdateStep;
:log info ("Update step: $updateStep");
## if it is a very first step
:if ([:len $updateStep] = 0) do={
## Check for update
##/system package update set channel=$updateChannel;
# Convert current version to numeric (6.43.8 => 64308)
:local osVerCurrent [/system package update get installed-version];
:local osVerCurrentNum [$getOsVerNum osVer=$osVerCurrent];
## We need this part to keep compatibility with firmware older than 6.43.7
:if ($osVerCurrentNum < 64307 and [:len [:find "bugfix current release-candidate" $updateChannel 0]] = 0) do={
:if ($updateChannel = "stable") do={
:set updateChannel "current";
} else={
:if ($updateChannel = "long-term") do={
:set updateChannel "bugfix";
} else={
:if ($updateChannel = "testing") do={
:set updateChannel "release-candidate";
}
}
}
}
log info ("Checking for new firmware version. Current version is: $osVerCurrent");
/system package update check-for-updates;
:delay 5s;
# Getting info about new available firmware version
:local osVerNew [/system package update get latest-version];
:delay 5s;
# If there is a problem getting information about available firmware from server
:if ([:len $osVerNew] = 0) do={
:log info ("There is a problem getting information about available firmware from server. No internet connection \?");
:error "Error during firmware-updater script execution, please see log.";
}
# Convert new version to numeric (6.43.8 => 64308)
:local osVerNewNum [$getOsVerNum osVer=$osVerNew];
# Remove function getOsVerNum from global environment to keep it fresh and clean.
:set getOsVerNum;
# Compare new and current versions
:local isUpdateAvailable false;
:if ($osVerNewNum > $osVerCurrentNum) do={
:set isUpdateAvailable true;
:log info ("New firmware version found: $osVerNew");
} else={
:log info ("New firmware version not found.")
}
# If only patch updates are allowed
:if ($onlyPatchUpdates = true and $isUpdateAvailable = true) do={
#Check if Major and Minor builds are the same.
:if ([:pick $osVerCurrentNum 0 ([:len $osVerCurrentNum]-2)] = [:pick $osVerNewNum 0 ([:len $osVerNewNum]-2)]) do={
:log info ("New patch version of RouterOS firmware is available.");
} else={
:log info ("New major version of RouterOS firmware is available. You have to update it manually.");
:set isUpdateAvailable false;
#Send email just once
:if ($beePatchUpdateInapplicable != true and $emailEnabled = true) do={
:log info ("Email was sent just once.");
/tool e-mail send to="$emailAddress" subject="Router: $[/system identity get name], new major version of RouterOS firmware is available: v$osVerNew" body="New major version of RouterOS firmware is available. You have to update it manually.. \r\n\r\nRouter name: $[/system identity get name]\r\nCurrent RouterOS version: $osVerCurrent; Routerboard firmware: $[/system routerboard get current-firmware]; Update channel: $[/system package update get channel]; \r\nBoard name: $[/system resource get board-name]; Serial number: $[/system routerboard get serial-number]; \r\n\r\n Changelog: https://mikrotik.com/download/changelogs/current-release-tree";
:delay 5s;
# If notification was sent, we no longer bother with it.
:if ([/tool e-mail get last-status] = "succeeded") do={
:global beePatchUpdateInapplicable true;
}
}
}
}
#Keep environment clean
:if ($isUpdateAvailable = true and $beePatchUpdateInapplicable = true) do={
/system script environment remove beePatchUpdateInapplicable;
}
# If we found some updates
:if ([/system package update get installed-version] != [/system package update get latest-version]) do={
:if ($isUpdateAvailable = true) do={
## New version of RouterOS available, let's upgrade
:log info ("Upgrading RouterOS on router $[/system identity get name], board name: $[/system resource get board-name], serial number: $[/system routerboard get serial-number] | From $[/system package update get installed-version] to $[/system package update get latest-version] (channel:$[/system package update get channel])");
:log info ("Going to update RouterOS firmware from $osVerCurrent to $osVerNew (channel:$updateChannel)");
:if ($emailEnabled = true) do={
:local attachments;
#M# acking system backups to attach them in email.
:if ($sendBackupToEmail = true) do={
:log info ("Making system backups.");
## date and time in format: 2018aug06-215139
:local dtame ([:pick [/system clock get date] 7 11] . [:pick [/system clock get date] 0 3] . [:pick [/system clock get date] 4 6] . "-" . [:pick [/system clock get time] 0 2] . [:pick [/system clock get time] 3 5] . [:pick [/system clock get time] 6 8]);
## unified backup file name without extension
@ -51,7 +186,7 @@
:if ([:len $backupPassword] = 0) do={
/system backup save dont-encrypt=yes name=$bname;
} else={
/system backup save encryption=aes-sha256 password=$backupPassword name=$bname;
/system backup save password=$backupPassword name=$bname;
}
## Export config file
@ -60,24 +195,22 @@
} else={
/export compact hide-sensitive file=$bname;
}
## Wait until bakup is done
:delay 15s;
:delay 5s;
}
/tool e-mail send to=$emailAddress subject="Upgrade router: $[/system identity get name] FW has been started" body="Upgrading RouterOS on router $[/system identity get name] from $[/system package update get installed-version] to $[/system package update get latest-version] \r\nYou will recieve final report with detailed information when upgrade process is finished. If you have not got second email in next 5 minutes, then probably something went wrong." file=$attachments;
## Wait for mail to be send & upgrade
:delay 15s;
:log info ("Sending email");
/tool e-mail send to=$emailAddress subject="Upgrade router: $[/system identity get name] FW has been started" body="Upgrading RouterOS on router $[/system identity get name] from $osVerCurrent to $osVerNew \r\nYou will recieve final report with detailed information when upgrade process is finished. If you have not got second email in next 5 minutes, then probably something went wrong." file=$attachments;
:delay 5s;
## Remove backups which we have already sent
:if ($sendBackupToEmail = true && [/tool e-mail get last-status] = "succeeded") do={
/file remove $attachments;
}
}
## Set scheduled task to upgrade routerboard firmware on the next boot, task will be deleted when upgrade is done. (That is why you should keep original script name)
/system schedule add name=BEE-UPGRADE-NEXT-BOOT on-event="/system scheduler remove BEE-UPGRADE-NEXT-BOOT; :global beeGlobalUpdateStep \"routerboardUpgrade\"; :delay 5s; /system script run firmware-updater;" start-time=startup interval=0;
/system schedule add name=BEE-UPGRADE-NEXT-BOOT on-event="/system scheduler remove BEE-UPGRADE-NEXT-BOOT; :global beeGlobalUpdateStep \"routerboardUpgrade\"; :delay 15s; /system script run firmware-updater;" start-time=startup interval=0;
## command is reincarnation of the "upgrade" command - doing exactly the same but under a different name
/system package update install;
@ -98,10 +231,10 @@
/system routerboard upgrade;
## Wait until the upgrade is finished
:delay 30s;
:delay 5s;
## Set scheduled task to send final report on the next boot, task will be deleted when is is done. (That is why you should keep original script name)
/system schedule add name=BEE-FINAL-REPORT-NEXT-BOOT on-event="/system scheduler remove BEE-FINAL-REPORT-NEXT-BOOT; :global beeGlobalUpdateStep \"finalReport\"; :delay 10s; /system script run firmware-updater;" start-time=startup interval=0;
/system schedule add name=BEE-FINAL-REPORT-NEXT-BOOT on-event="/system scheduler remove BEE-FINAL-REPORT-NEXT-BOOT; :global beeGlobalUpdateStep \"finalReport\"; :delay 15s; /system script run firmware-updater;" start-time=startup interval=0;
## Reboot system to boot with new firmware
/system reboot;