API utility in Ruby 1.9

I’ve been doing some stuff with the API in Ruby 1.9 for InfoWest, Inc. – Anyone interested can take a look at it on my personal web site (BSD licensed):

http://www.aarongifford.com/computers/mtik.rb_latest.txt

Download it and rename it as mtik.rb or something before using, and check the ruby command path on the first line of the script.

This script relies on some Ruby 1.9 behavior–while it wouldn’t take much to port to 1.8, I suppose, I doubt I will bother. I haven’t yet implemented timeouts like I hope to someday.

Improvements/bugs/comments are welcome.

In the mtik.rb file, if one were to uncomment the interactive client line:

### Interactive client example:
MTik::interactive_client(ARGV)

One could then do:

myhost# ./mtik.rb 10.0.0.1 admin weakpassword
<<< '/login' (6)
<<< END-OF-SENTENCE

>>> '!done' (5)
>>> '=ret=5eaf1a82ade0e68fbdcd412fd8aa582f' (37)
>>> END-OF SENTENCE

<<< '/login' (6)
<<< '=name=admin' (11)
<<< '=response=00a5a1f2e65b1aa9131be149671c4fe015' (44)
<<< END-OF-SENTENCE

>>> '!done' (5)
>>> END-OF SENTENCE


Command (/quit to end): /interface/print
=== COMMAND: /interface/print
<<< '/interface/print' (16)
<<< END-OF-SENTENCE

>>> '!re' (3)
>>> '=.id=*1' (7)
>>> '=comment=' (9)
>>> '=name=ether1' (12)
>>> '=type=ether' (11)
>>> '=mtu=1500' (9)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> '=.id=*2' (7)
>>> '=comment=' (9)
>>> '=name=wlan1' (11)
>>> '=type=wlan' (10)
>>> '=mtu=1500' (9)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> '=.id=*3' (7)
>>> '=comment=' (9)
>>> '=name=bridge' (12)
>>> '=type=bridge' (12)
>>> '=mtu=1500' (9)
>>> END-OF SENTENCE

[{"!re"=>nil, "=.id"=>"*1", "=comment"=>"", "=name"=>"ether1", "=type"=>"ether", "=mtu"=>"1500"}, {"!re"=>nil, "=.id"=>"*2", "=comment"=>"", "=name"=>"wlan1", "=type"=>"wlan", "=mtu"=>"1500"}, {"!re"=>nil, "=.id"=>"*3", "=comment"=>"", "=name"=>"bridge1", "=type"=>"bridge", "=mtu"=>"1500"}]

Command (/quit to end): /quit
<<< '/quit' (5)
<<< END-OF-SENTENCE

>>> '!fatal' (6)
>>> 'session terminated on request' (29)
>>> END-OF SENTENCE

=== Disconnected ===
myhost%

All the verbose printing of the exchange between device and script only occurs if $VERBOSE or $DEBUG is set, or if the MTik::interactive_client() method is used.

The other bottom-of-file example uses the script’s MTik::command() function – an all-in-one that accepts named parameters for host/user/port/pass/command, connects, logs in, executes the command, gets the result, closes the connection, then returns the result. Useful if you don’t want to bother keeping a connection open.

If you instead choose to instantiate an MTik object, you’ll most likely use the MTik#request_reply() call. Or you could use MTik#send_request() and MTik#get_reply() individually (the request_reply() method just encapsulates both). For MTik#send_request(), pass the command and args, command first, and args formatted in the ‘=argmane=argvalue’ API style.

The response/rely is an array with each sentence of the response as a separate array item. Each array item is a hash (associative array) with key/value pairs already split up. So if the API word ‘=responsekey=responsevalue’ appeared as a word in the 2nd response sentence, one would access the value ‘responsevalue’ thus:

response[1]['=responsekey']

(Notice that the leading ‘=’ character is NOT stripped from the key, but the ‘=’ separating key and value does NOT appear in either the key, nor in the value.)

Here’s an example of how I’m using this utility in another Ruby 1.9 script:

def get_info(ip, user, pass)
  tk = MTik.new(:host => ip, :user => user, :pass => pass)
  rbinfo  = tk.request_reply('/system/routerboard/print')
  ethinfo = tk.request_reply('/interface/ethernet/print')
  winfo   = tk.request_reply('/interface/wireless/print')

  ... additional work with the routerboard, ethernet info, and wireless info done here...

  tk.request_reply('/quit')
  tk.close
end

That snippet lets me grab routerboard, ethernet interface, and wireless interface info.

Have fun!

I will.

Aaron out.

wow, nice and thanks a lot! I will add this thread to the wiki, or you can make a new wiki article yourself

I’ve finally GEM-ified the Ruby MikroTik API stuff. Check it out on the MikroTik wiki at http://wiki.mikrotik.com/wiki/API_Ruby_class or on my own site at http://www.aarongifford.com/computers/mtik/.

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.)

Aaron out.

Updates have been released for the Ruby MikroTik API Gem:

A bug-fix to versions 3.0.x is available, version 3.0.5 at:
http://www.aarongifford.com/computers/mtik/latest/pkg/mtik-3.0.5.gem

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

Docs/etc are visible at http://www.aarongifford.com/computers/mtik/index.html and http://www.aarongifford.com/computers/mtik/latest/doc/index.html

And don’t forget MikroTik’s Wiki: http://wiki.mikrotik.com/wiki/API_Ruby_class

Thanks to Allan Eising and Søren Daugaard for bug reports and patches!

Enjoy!

Aaron out.