Automating MikroTik RouterOS updates

Share your Config Push presets or discuss automation in general
SpiderMattX
Posts: 2
Joined: Fri Jan 29, 2021 11:53 am

Fri Jan 29, 2021 11:59 am

I want to add to what Unimus provided as a starting point. It's helpful but it doesn't really solve the problem of handling software rollbacks when things really hit the fan. I have a script here that you simply define the target version you wish to change to and it handles the rest as part of a 2-step execution.

Here is the raw script:

Code: Select all

:global TargetVer "6.47.4"
:global Architecture
:global PkgVer
:global PkgVer1
:global PkgVer2
:global PkgVer3
:global RbVer
:global RbVer1
:global RbVer2
:global RbVer3
:global TargetVer1
:global TargetVer2
:global TargetVer3
:global PackageURL
:set Architecture [/system resource get architecture-name]
:set PkgVer "$[/system package get system version]"
:set PkgVer1 [:pick $PkgVer 0 1]
:set PkgVer2 [:pick $PkgVer 2 4]
:set PkgVer3 [:pick $PkgVer 5 6]
:set RbVer "$[/system routerboard get current-firmware]"
:set RbVer1 [:pick $RbVer 0 1]
:set RbVer2 [:pick $RbVer 2 4]
:set RbVer3 [:pick $RbVer 5 6]
:set PkgVer1 [:tonum $PkgVer1]
:set PkgVer2 [:tonum $PkgVer2]
:set PkgVer3 [:tonum $PkgVer3]
:set RbVer1 [:tonum $RbVer1]
:set RbVer2 [:tonum $RbVer2]
:set RbVer3 [:tonum $RbVer3]
:set TargetVer1 [:pick $TargetVer 0 1]
:set TargetVer2 [:pick $TargetVer 2 4]
:set TargetVer3 [:pick $TargetVer 5 6]
:set TargetVer1 [:tonum $TargetVer1]
:set TargetVer2 [:tonum $TargetVer2]
:set TargetVer3 [:tonum $TargetVer3]
:set PackageURL "https://download.mikrotik.com/routeros/$TargetVer/routeros-$Architecture-$TargetVer.npk"
if ($PkgVer != $TargetVer) do={
	:log info "Package version does not match target version. Downloading package file from $PackageURL.";
	/tool fetch url=$PackageURL;
	if ($PkgVer1 > $TargetVer1 || $PkgVer2 > $TargetVer2 || $PkgVer3 > $TargetVer3) do={ :log info "Target package version is older than current package version. Executing downgrade..."; /system package downgrade; } else={ :log info "Target package version is newer than current package version. Executing upgrade..."; /system reboot; }
} else={
	if ($RbVer != $PkgVer) do={ :log info "RouterBoard firmware ($RbVer) does not match target version ($TargetVer). Executing upgrade..."; /system routerboard upgrade; /system reboot; } else={ :log info "Software and firmware currently match target version ($TargetVer). No changes being made."; }
}
Here is the packaged script for automated deployment using Unimus:

Code: Select all

/system script remove update-software
/system script add name="update-software" policy="read,write,reboot,test,ftp,sensitive,policy" comment="Updates system software to declared target version." source=":global TargetVer \"6.47.4\"\r\n:global Architecture\r\n:global PkgVer\r\n:global PkgVer1\r\n:global PkgVer2\r\n:global PkgVer3\r\n:global RbVer\r\n:global RbVer1\r\n:global RbVer2\r\n:global RbVer3\r\n:global TargetVer1\r\n:global TargetVer2\r\n:global TargetVer3\r\n:global PackageURL\r\n:set Architecture [/system resource get architecture-name]\r\n:set PkgVer \"\$[/system package get system version]\"\r\n:set PkgVer1 [:pick \$PkgVer 0 1]\r\n:set PkgVer2 [:pick \$PkgVer 2 4]\r\n:set PkgVer3 [:pick \$PkgVer 5 6]\r\n:set RbVer \"\$[/system routerboard get current-firmware]\"\r\n:set RbVer1 [:pick \$RbVer 0 1]\r\n:set RbVer2 [:pick \$RbVer 2 4]\r\n:set RbVer3 [:pick \$RbVer 5 6]\r\n:set PkgVer1 [:tonum \$PkgVer1]\r\n:set PkgVer2 [:tonum \$PkgVer2]\r\n:set PkgVer3 [:tonum \$PkgVer3]\r\n:set RbVer1 [:tonum \$RbVer1]\r\n:set RbVer2 [:tonum \$RbVer2]\r\n:set RbVer3 [:tonum \$RbVer3]\r\n:set TargetVer1 [:pick \$TargetVer 0 1]\r\n:set TargetVer2 [:pick \$TargetVer 2 4]\r\n:set TargetVer3 [:pick \$TargetVer 5 6]\r\n:set TargetVer1 [:tonum \$TargetVer1]\r\n:set TargetVer2 [:tonum \$TargetVer2]\r\n:set TargetVer3 [:tonum \$TargetVer3]\r\n:set PackageURL \"https://download.mikrotik.com/routeros/\$TargetVer/routeros-\$Architecture-\$TargetVer.npk\"\r\nif (\$PkgVer != \$TargetVer) do={\r\n	:log info \"Package version does not match target version. Downloading package file from \$PackageURL.\";\r\n	/tool fetch url=\$PackageURL;\r\n	if (\$PkgVer1 > \$TargetVer1 || \$PkgVer2 > \$TargetVer2 || \$PkgVer3 > \$TargetVer3) do={ :log info \"Target package version is older than current package version. Executing downgrade...\"; /system package downgrade; } else={ :log info \"Target package version is newer than current package version. Executing upgrade...\"; /system reboot; }\r\n} else={\r\n	if (\$RbVer != \$PkgVer) do={ :log info \"RouterBoard firmware (\$RbVer) does not match target version (\$TargetVer). Executing upgrade...\"; /system routerboard upgrade; /system reboot; } else={ :log info \"Software and firmware currently match target version (\$TargetVer). No changes being made.\"; }\r\n}"
Here is a script for Unimus to deploy scheduler configurations to execute the script automatically:

Code: Select all

/system scheduler remove update-software
/system scheduler remove update-firmware
/system scheduler add name="update-software" comment="Executes update-software script at 3am." start-date="jan/29/2021" start-time="03:00:00" policy="read,write,reboot,test,ftp,sensitive,policy" on-event=update-software
/system scheduler add name="update-firmware" comment="Executes update-software script at 3:10am." start-date="jan/29/2021" start-time="03:10:00" policy="read,write,reboot,test,ftp,sensitive,policy" on-event=update-software
This code completed a production test successfully last night but no warranty is provided so know what you're doing before you do it!

Enjoy!
User avatar
ementat
Posts: 8
Joined: Wed Jun 08, 2022 12:30 pm

Wed Jun 08, 2022 12:37 pm

I am trying to do Mass Config Push with the code example provided by SpiderMattX, but all I get is "no such item" in Output. And this is strange, because if I paste this code directly in the Mikrotik terminal inside Winbox everything is working as expected. Any ideas what could be wrong?
SpiderMattX wrote:
Fri Jan 29, 2021 11:59 am
Here is the packaged script for automated deployment using Unimus:

Code: Select all

/system script remove update-software
/system script add name="update-software" policy="read,write,reboot,test,ftp,sensitive,policy" comment="Updates system software to declared target version." source=":global TargetVer \"6.47.4\"\r\n:global Architecture\r\n:global PkgVer\r\n:global PkgVer1\r\n:global PkgVer2\r\n:global PkgVer3\r\n:global RbVer\r\n:global RbVer1\r\n:global RbVer2\r\n:global RbVer3\r\n:global TargetVer1\r\n:global TargetVer2\r\n:global TargetVer3\r\n:global PackageURL\r\n:set Architecture [/system resource get architecture-name]\r\n:set PkgVer \"\$[/system package get system version]\"\r\n:set PkgVer1 [:pick \$PkgVer 0 1]\r\n:set PkgVer2 [:pick \$PkgVer 2 4]\r\n:set PkgVer3 [:pick \$PkgVer 5 6]\r\n:set RbVer \"\$[/system routerboard get current-firmware]\"\r\n:set RbVer1 [:pick \$RbVer 0 1]\r\n:set RbVer2 [:pick \$RbVer 2 4]\r\n:set RbVer3 [:pick \$RbVer 5 6]\r\n:set PkgVer1 [:tonum \$PkgVer1]\r\n:set PkgVer2 [:tonum \$PkgVer2]\r\n:set PkgVer3 [:tonum \$PkgVer3]\r\n:set RbVer1 [:tonum \$RbVer1]\r\n:set RbVer2 [:tonum \$RbVer2]\r\n:set RbVer3 [:tonum \$RbVer3]\r\n:set TargetVer1 [:pick \$TargetVer 0 1]\r\n:set TargetVer2 [:pick \$TargetVer 2 4]\r\n:set TargetVer3 [:pick \$TargetVer 5 6]\r\n:set TargetVer1 [:tonum \$TargetVer1]\r\n:set TargetVer2 [:tonum \$TargetVer2]\r\n:set TargetVer3 [:tonum \$TargetVer3]\r\n:set PackageURL \"https://download.mikrotik.com/routeros/\$TargetVer/routeros-\$Architecture-\$TargetVer.npk\"\r\nif (\$PkgVer != \$TargetVer) do={\r\n	:log info \"Package version does not match target version. Downloading package file from \$PackageURL.\";\r\n	/tool fetch url=\$PackageURL;\r\n	if (\$PkgVer1 > \$TargetVer1 || \$PkgVer2 > \$TargetVer2 || \$PkgVer3 > \$TargetVer3) do={ :log info \"Target package version is older than current package version. Executing downgrade...\"; /system package downgrade; } else={ :log info \"Target package version is newer than current package version. Executing upgrade...\"; /system reboot; }\r\n} else={\r\n	if (\$RbVer != \$PkgVer) do={ :log info \"RouterBoard firmware (\$RbVer) does not match target version (\$TargetVer). Executing upgrade...\"; /system routerboard upgrade; /system reboot; } else={ :log info \"Software and firmware currently match target version (\$TargetVer). No changes being made.\"; }\r\n}"
Use your mentality. Wake up to reality.
SpiderMattX
Posts: 2
Joined: Fri Jan 29, 2021 11:53 am

Wed Jun 08, 2022 12:48 pm

Without really digging into it, the first thought that comes to mind on the surface is possibly an issue with the scripts being copied and pasted into unimus. Have you verified that the text isn't being escaped or mutated in any way when copied in to Unimus?

What exactly is the output or error that you are receiving?
User avatar
Tomas
Posts: 1206
Joined: Sat Jun 25, 2016 12:33 pm

Wed Jun 08, 2022 12:52 pm

As another note, I would also recommend testing with 2.2.3-Beta3. We fixed an edge-case where the "$" would need to be escaped even when it was not a part of an Unimus variable - which could break Tik scripts in specific scenarios. You might be running into that issue.
User avatar
ementat
Posts: 8
Joined: Wed Jun 08, 2022 12:30 pm

Wed Jun 08, 2022 1:01 pm

As I can see all $ are escaped in initial script and I really don't see any "mutations". Mikrotik responds with "no such item" for the second command. Here is the output:

Code: Select all

<prompt> /system script remove update-software

no such item



[admin@RB4011] >
<prompt> /system script add name="update-software" policy="read,write,reboot,test,ftp,sensitive,policy" comment="Updates system software to declared target version." source=":global TargetV
er \"7.3\"\r\n:global Architecture\r\n:global PkgVer\r\n:global PkgVer1\r\n:global PkgVer2\r\n:global PkgVer3\r\n:global RbVer\r\n:global RbVer1\r\n:global RbVer2\r\n:global RbVer3\r\n:global TargetVe
r1\r\n:global TargetVer2\r\n:global TargetVer3\r\n:global PackageURL\r\n:set Architecture [/system resource get architecture-name]\r\n:set PkgVer \"$[/system package get system version]\"\r\n:set PkgV
er1 [:pick $PkgVer 0 1]\r\n:set PkgVer2 [:pick $PkgVer 2 4]\r\n:set PkgVer3 [:pick $PkgVer 5 6]\r\n:set RbVer \"$[/system routerboard get current-firmware]\"\r\n:set RbVer1 [:pick $RbVer 0 1]\r\n:set
RbVer2 [:pick $RbVer 2 4]\r\n:set RbVer3 [:pick $RbVer 5 6]\r\n:set PkgVer1 [:tonum $PkgVer1]\r\n:set PkgVer2 [:tonum $PkgVer2]\r\n:set PkgVer3 [:tonum $PkgVer3]\r\n:set RbVer1 [:tonum $RbVer1]\r\n:se
t RbVer2 [:tonum $RbVer2]\r\n:set RbVer3 [:tonum $RbVer3]\r\n:set TargetVer1 [:pick $TargetVer 0 1]\r\n:set TargetVer2 [:pick $TargetVer 2 4]\r\n:set TargetVer3 [:pick $TargetVer 5 6]\r\n:set TargetVe
r1 [:tonum $TargetVer1]\r\n:set TargetVer2 [:tonum $TargetVer2]\r\n:set TargetVer3 [:tonum $TargetVer3]\r\n:set PackageURL \"https://download.mikrotik.com/routeros/$TargetVer/routeros-$Architecture-$T
argetVer.npk\"\r\nif ($PkgVer != $TargetVer) do={\r\n  :log info \"Package version does not match target version. Downloading package file from $PackageURL.\";\r\n  /tool fetch url=$PackageURL;\r\n  i
f ($PkgVer1 > $TargetVer1 || $PkgVer2 > $TargetVer2 || $PkgVer3 > $TargetVer3) do={ :log info \"Target package version is older than current package version. Executing downgrade...\"; /system package
downgrade; } else={ :log info \"Target package version is newer than current package version. Executing upgrade...\"; /system reboot; }\r\n} else={\r\n  if ($RbVer != $PkgVer) do={ :log info \"RouterB
oard firmware ($RbVer) does not match target version ($TargetVer). Executing upgrade...\"; /system routerboard upgrade; /system reboot; } else={ :log info \"Software and firmware currently match targe
t version ($TargetVer). No changes being made.\"; }\r\n}"
[tikadmin@RB4011] > /system script add name="update-software" policy="read,write,reboot,test,ftp,sensitive,policy" comment="Updates system software to declared target version." source=":global TargetVe
r \"7.3\"\r\n:global Architecture\r\n:global PkgVer\r\n:global PkgVer1\r\n:global PkgVer2\r\n:global PkgVer3\r\n:global RbVer\r\n:global RbVer1\r\n:global RbVer2\r\n:global RbVer3\r\n:global TargetVer
1\r\n:global TargetVer2\r\n:global TargetVer3\r\n:global PackageURL\r\n:set Architecture [/system resource get architecture-name]\r\n:set PkgVer \"$[/system package get system version]\"\r\n:set PkgVe
r1 [:pick $PkgVer 0 1]\r\n:set PkgVer2 [:pick $PkgVer 2 4]\r\n:set PkgVer3 [:pick $PkgVer 5 6]\r\n:set RbVer \"$[/system routerboard get current-firmware]\"\r\n:set RbVer1 [:pick $RbVer 0 1]\r\n:set R
bVer2 [:pick $RbVer 2 4]\r\n:set RbVer3 [:pick $RbVer 5 6]\r\n:set PkgVer1 [:tonum $PkgVer1]\r\n:set PkgVer2 [:tonum $PkgVer2]\r\n:set PkgVer3 [:tonum $PkgVer3]\r\n:set RbVer1 [:tonum $RbVer1]\r\n:set
 RbVer2 [:tonum $RbVer2]\r\n:set RbVer3 [:tonum $RbVer3]\r\n:set TargetVer1 [:pick $TargetVer 0 1]\r\n:set TargetVer2 [:pick $TargetVer 2 4]\r\n:set TargetVer3 [:pick $TargetVer 5 6]\r\n:set TargetVer
1 [:tonum $TargetVer1]\r\n:set TargetVer2 [:tonum $TargetVer2]\r\n:set TargetVer3 [:tonum $TargetVer3]\r\n:set PackageURL \"https://download.mikrotik.com/routeros/$TargetVer/routeros-$Architecture-$Ta
rgetVer.npk\"\r\nif ($PkgVer != $TargetVer) do={\r\n  :log info \"Package version does not match target version. Downloading package file from $PackageURL.\";\r\n  /tool fetch url=$PackageURL;\r\n  if
 ($PkgVer1 > $TargetVer1 || $PkgVer2 > $TargetVer2 || $PkgVer3 > $TargetVer3) do={ :log info \"Target package version is older than current package version. Executing downgrade...\"; /system package d
owngrade; } else={ :log info \"Target package version is newer than current package version. Executing upgrade...\"; /system reboot; }\r\n} else={\r\n  if ($RbVer != $PkgVer) do={ :log info \"RouterBo
ard firmware ($RbVer) does not match target version ($TargetVer). Executing upgrade...\"; /system routerboard upgrade; /system reboot; } else={ :log info \"Software and firmware currently match target
 version ($TargetVer). No changes being made.\"; }\r\n}"

no such item



[admin@RB4011] >
<prompt>
Use your mentality. Wake up to reality.
User avatar
ementat
Posts: 8
Joined: Wed Jun 08, 2022 12:30 pm

Wed Jun 08, 2022 1:22 pm

The problem is definitly with the:

Code: Select all

:set PkgVer \"\$[/system package get system version]\"\r\n
How I can correctly escape $ here in Unimus 2.2.2? Using %24 is not working :(
Use your mentality. Wake up to reality.
User avatar
Tomas
Posts: 1206
Joined: Sat Jun 25, 2016 12:33 pm

Wed Jun 08, 2022 1:35 pm

ementat wrote:
Wed Jun 08, 2022 1:22 pm
The problem is definitly with the:

Code: Select all

:set PkgVer \"\$[/system package get system version]\"\r\n
How I can correctly escape $ here in Unimus 2.2.2? Using %24 is not working :(
Adding an additional "\" should work. Alternatively, update to 2.2.3-Beta3 and it should work without any modification.
User avatar
ementat
Posts: 8
Joined: Wed Jun 08, 2022 12:30 pm

Wed Jun 08, 2022 2:14 pm

ementat wrote:
Wed Jun 08, 2022 1:22 pm
Adding an additional "\" should work. Alternatively, update to 2.2.3-Beta3 and it should work without any modification.
Thanks! Now the script is working as expected. Waiting for 2.2.3 release.
Use your mentality. Wake up to reality.
User avatar
ementat
Posts: 8
Joined: Wed Jun 08, 2022 12:30 pm

Fri Jun 17, 2022 5:37 am

I am still experiencing problems with "$" character shielding in 2.2.3 release. The command line that works in Mikrotik terminal gives me weird results if pushed from Unimus. With "$" double shielding anything is working fine as in 2.2.2.
Use your mentality. Wake up to reality.
Vik@Unimus
Posts: 198
Joined: Thu Aug 05, 2021 6:35 pm

Fri Jun 17, 2022 12:23 pm

The fix for this should be present since 2.2.3-Beta3. Was it consistently working on Beta3 and stopped working on 2.2.3?
Post Reply