The Ruby API client has been updated and now works with Ruby 1.8 as well as Ruby 1.9. Version 2.0.1 does make some significant changes, moving to an event-driven-with-callback model for handling replies to API commands.
All I/O is still synchronous, but the new design should make it easier to migrate to a truly asynchronous I/O model to improve I/O throughput (and allow single-threaded handling of multiple simultaneous commands without blocking while waiting for one to complete) in the future.
This is a big step closer to that design goal.
A page has been added to the MikroTik wiki for the Ruby API client:
With careful application/use design, the 2.0 Ruby client can now handle commands that do not complete, but instead output a continual periodic response.
Example: Connect to a device and retrieve the list of current DHCP leases.
require 'mtik.rb'
begin
tik = MTik.new(:host => '10.20.30.1', :user => 'admin', :pass => 'mypassword')
rescue MTikError, Errno::ETIMEDOUT, Errno::EHOSTUNREACH, Errno::ECONNREFUSED => e
print "ERROR CONNECTING OR LOGGING IN: #{e}\n"
exit
end
begin
tik.send_request(true, '/ip/dhcp-server/lease/getall') do |req, sentence|
## This code block ONLY gets called (it's a callback) when the command
## output completes with a '!done'...
## Iterate over each reply sentence:
req.reply.each do |reply|
if reply.key?('!re')
## Look at the DHCP lease info...
print "LEASE: mac=#{reply['mac-address']} IP=#{reply['address']} status=#{reply['status']}\n"
end
end
end
while tik.outstanding > 0
## Main "event loop"
tik.wait_for_reply
end
rescue MTikError, Errno::ETIMEDOUT, Errno::EHOSTUNREACH, Errno::ECONNREFUSED => e
print "ERROR during DHCP lease API request: #{e}\n"
exit
end
tik.close
I had to bump the version waaaay up to 3.0.0 due to the structural changes that break scripts using the older Ruby APIs. (I’m following the suggested Ruby GEM versioning scheme.) 2.x implemented an event model which broke 1.x scripts 3.x builds on 2.x’s design, but with the modularization changes to be more namespace friendly in preparation to become a Ruby GEM, the name changes were too significant NOT to result in a major version change.
I expect to bump a few minor versions in the next little bit with new features that should NOT break existing scripts. (I have the scripts working, but want to move some of their functionality into the GEM so other scripts can make use of the same code.)
With the 3.x changes, the script example I mentioned above would now become:
#!/usr/local/bin/ruby
require 'rubygems'
require 'mtik'
begin
tik = MTik::Connection.new(:host => '10.20.30.40', :user => 'admin', :pass => 'adminpassword')
rescue MTik::Error, Errno::ETIMEDOUT, Errno::EHOSTUNREACH, Errno::ECONNREFUSED => e
print "ERROR CONNECTING OR LOGGING IN: #{e}\n"
exit
end
begin
## MTik::Connection#get_request() has a build-in event loop so we don't have
## to execute one ourselves.
tik.get_reply_each('/ip/dhcp-server/lease/getall') do |req, sentence|
## This code block gets called for EACH sentence received in reply:
if sentence.key?('!re')
## Look at the DHCP lease info...
print "LEASE: mac=#{sentence['mac-address']} IP=#{sentence['address']} status=#{sentence['status']}\n"
end
end
rescue MTik::Error, Errno::ETIMEDOUT, Errno::EHOSTUNREACH, Errno::ECONNREFUSED => e
print "ERROR during DHCP lease API request: #{e}\n"
exit
end
tik.close
The output would be identical. The changes mostly are thinks like MTikError becoming MTik::Error. Also the new MTik::Connection#get_reply_each() method simplifies things by building in the event loop. One can still directly call send_request() and implement an event loop one’s self–desirable when one may have other events besides MTik stuff to handle.
I just wanted to thank you for your API implementation. I haven’t tested the 3.0 rewrite, but the 2.x stuff works great, and I’m happy that it’s finally available as a gem.
This version is mostly just tiny typo fixes, with a little bit of functionality to the tikcommand.rb example and the interactive CLI function.
Example use of the tikfetch.rb script in the GEM’s examples subdirectory, from a shell prompt on a host with Ruby and the mtik gem installed:
user@host:/home/tikexamples$ ./tikfetch.rb 10.0.0.55 adminuser adminpass http://download.mikrotik.com/routeros-mipsbe-4.5.npk routeros-mipsbe-4.5.npk
>>> OK: Fetching file 'routeros-mipsbe-4.5.npk' from URL 'http://download.mikrotik.com/routeros-mipsbe-4.5.npk'...
>>> OK: Connecting to 'http://download.mikrotik.com/routeros-mipsbe-4.5.npk' to download file 'routeros-mipsbe-4.5.npk'
>>> OK: Downloaded 318 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 2.85%
>>> OK: Downloaded 730 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 6.54%
>>> OK: Downloaded 1157 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 10.37%
>>> OK: Downloaded 1456 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 13.05%
>>> OK: Downloaded 1976 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 17.71%
>>> OK: Downloaded 2254 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 20.20%
>>> OK: Downloaded 2636 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 23.63%
>>> OK: Downloaded 3116 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 27.93%
>>> OK: Downloaded 3532 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 31.66%
>>> OK: Downloaded 3868 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 34.67%
>>> OK: Downloaded 4342 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 38.92%
>>> OK: Downloaded 4611 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 41.33%
>>> OK: Downloaded 5022 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 45.02%
>>> OK: Downloaded 5404 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 48.44%
>>> OK: Downloaded 5740 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 51.45%
>>> OK: Downloaded 6057 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 54.29%
>>> OK: Downloaded 6544 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 58.66%
>>> OK: Downloaded 7129 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 63.90%
>>> OK: Downloaded 7713 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 69.14%
>>> OK: Downloaded 8302 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 74.42%
>>> OK: Downloaded 8896 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 79.74%
>>> OK: Downloaded 9480 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 84.98%
>>> OK: Downloaded 10047 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 90.06%
>>> OK: Downloaded 10612 bytes of 11156 of file 'routeros-mipsbe-4.5.npk' 95.12%
>>> OK: File 'routeros-mipsbe-4.5.npk' download finished.
SIZE CREATED FILENAME
====================================================================
11424494 feb/05/2010 14:58:27 routeros-mipsbe-4.5.npk
user@host:/home/tikexamples$
Anyone who has used the API /tool/fetch command is aware that the command has multiple states, and API responses (sentences) will keep coming informing the API user of the command’s state. However, even once the command is in the finished state, responses do not stop. They will continue indefinitely until the API user cancels the command, or terminates the connection.
The Ruby GEM in 3.0.2 automates command canceling when the /tool/fetch command is issued using the GEM’s interactive_client feature, or one can use a new GEM method MTik#fetch(url, filename) – see the tikfetch.rb example script to see the latter in use (the output of which is shown in the example above).
Incorporating the bug fix AND adding a tiny bit of functionality (and a small library method change to the MTik::Connection.fetch() method–see the CHANGELOG.txt file at my web site) is also now available: http://www.aarongifford.com/computers/mtik/latest/pkg/mtik-3.1.0.gem
See the CHANGELOG.txt file for details about what has changed, or the commit messages on github.
Anyone whose code accessed the MTik::Request.state instance variable directly will need to watch out for the change of type (it was a String, now it’s a Symbol) and a spelling change to the canceled state (was cancelled, now canceled).
You can report BUGS or other issues via github, or contact the author (me) via his (my) web site.