Executing multiple JUNOS router commands with ruby - ruby

Has anyone tried to execute multiple commands in a JUNOS router using ruby with the net/ssh and net/ssh/telnet gems where you have to go into configure mode? It never wants to accept the configure commands and I don't know why.
Here is my code:
def exec_router(host_type, commands)
puts "commands: #{commands}"
output = ""
ssh = Net::SSH.start(HOST_MAP[host_type], QA_USER, :password => QA_USER_PASSWORD)
t = Net::SSH::Telnet.new("Session" => ssh, "Prompt" => /.+#.+>/, "Output_log" => "/tmp/test.outputi")
commands.each { |command| output << t.cmd(command) }
puts output
t.close
ssh.close
end
And here is the output that it produces:
commands: ["configure", "show policy-options prefix-list greautomation-676872"]
configure
^
unknown command.
{master:member0-re0}
qa#c1.lab5> show policy-options
^
syntax error, expecting <command>.
qa#c1.lab5> show policy-optionsprefix-list
^
syntax error, expecting .
qa#c1.lab5> show policy-optionsprefix-listgreautomation-676872
^
syntax error, expecting .
I know my ssh/telnet stuff is working because I can replace the block that iterates through the command array with t.cmd('?') and I get the expected output with no errors.
My Junos version is 15.1F6-S3.8 and I am using ruby 2.3.0.
Thanks in advance
Craig

Have you checked https://github.com/Juniper/net-netconf? It is a Ruby Gem for doing NETCONF based interactions with Junos devices.

You should use RubyEZ.
Refer: https://github.com/Juniper/ruby-junos-ez-stdlib
to get the configuration of the device, we have get-configuration rpc.
data = ndev.rpc.get_configuration # Junos specific RPC
puts "Showing 'policy-options' hierarchy ..."
puts cfgall.xpath('policy-options')
To call operational rpc (for ex "show chassis hardware" corresponds to get-chassis-inventory rpc), hence
data = ndev.rpc.get_chassis_inventory

Although I would recommend you to use RubyEZ libraries, your problem is related to the fact that you are trying to execute a configuration syntax command in the operational mode.
Here is your problem:
commands: ["configure", "show policy-options prefix-list greautomation-676872"]
Make the following changes:
remove the "configure" command
replace "show policy-options prefix-list greautomation-676872" with "show configuration policy-options prefix-list greautomation-676872"
This should solve your problem.
I highly recommend you to look into RubyEZ libraries from Juniper.

Related

Handle Commander errors manually in Ruby

I'm writing a simple Commander CLI as part of a project I'm working on.
Commander has its own method of handling errors. For example, if the user enters an invalid command, then Commander will print a user-friendly message:
$ my-commander-program some-invalid-command
invalid command. Use --help for more information.
I would like to replace this message with my own, so that the output is more consistent with the rest of my program. For example:
$ my-commander-program some-invalid-command
[ERR ] 'some-invalid-command' is not a known command.
Use --help to see a list of valid commands.
I've looked at Commander's README.md, which contains plenty of examples of how to use Commander, but I can't find how to do this from there.
My program is written using Commander's 'classic' style, where one imports commander/import and uses methods like program and command from the top-level, rather than creating a class which includes Commander::Methods. For example:
require 'commander/import'
program :name, 'my-commander-program'
program :version, '1.0.0'
program :description, 'Example'
command :example do |c|
c.action do |args, options|
puts "Invoked!"
end
end
How can I go about replacing this error message? I'm using Commander 4.4.5.

Enabling a console for a Ruby app

I'm trying to add a console to my Ruby cli application (much like the Rails console), but I can't seem to find a solution that does what I need:
Colorization & syntax highlighting
Ability to pass in variables or use the current context
I'd like to use pry, but I can't figure out how to disable the code context from being printed out at the start of the session. I'd like it to immediately start the session without printing anything out besides the prompt.
Here's what currently gets printed when the pry session starts:
Frame number: 0/8
From: <file_path> # line <#> <Class>#<method>:
71: def console
72: client_setup
73: puts "Console Connected to #{#client.url}"
74: puts 'HINT: The #client object is available to you'
75: rescue StandardError => e
76: puts "WARNING: Couldn't connect to #{#client.url}"
77: ensure
78: Pry.config.prompt = proc { "> " }
79: binding.pry
=> 80: end
>
Here's what I want:
>
I've also tried a few other solutions, but here's my problems with each:
IRB: No colorization, doesn't seem customizable
ripl: No colorization or syntax highlighting
Any help here would be greatly appreciated!
We usually create a separate executable file like bin/console in our project and put there content similar to this:
#!/usr/bin/env ruby
require_relative "../application"
require "pry"
Pry.start
Where application.rb is a file which loads gems via Bundler and includes all necessary application-related files, so it will be possible to use application classes in the console.
It's easy to start your console with just ./bin/console command from your terminal.
If you need to customise the look of console then official wiki at github has enough information about this: https://github.com/pry/pry/wiki/Customization-and-configuration
What I ended up doing is defining a pretty simple/empty class to bind to:
class Console
def initialize(client)
#client = client
end
end
Then in my console method:
Pry.config.prompt = proc { '> ' }
Pry.plugins['stack_explorer'] && Pry.plugins['stack_explorer'].disable!
Pry.start(Console.new(#client))
Disabling the stack_explorer prevented it from printing the Frame number info, and inside the Pry session, I can access #client as expected.

puppet ruby wrong number of arguments (1 for 0)

First off, I know there are a lot of questions regarding this error and I have checked them all, mine is not solved using any of their solutions however.
I am working for the first time with Puppet / Ruby and am having the following issue.
I created this function:
module Puppet::Parser::Functions
newfunction(:phpversion, :type => :rvalue) do
%x["/usr/bin/php -r 'echo PHP_MAJOR_VERSION . \".\" . PHP_MINOR_VERSION;'"]
end
end
And when I call it in my manifest file using:
$phpversion = phpversion()
It throws, when I execute the agent, the error "Error: Could not retrieve catalog from remote server: Error 400 on SERVER: wrong number of arguments (1 for 0) at /etc/puppetlabs/puppet/modules/x/manifests/somefile.pp:123 on node foo.example.bar"
I tried adding |args| after the do statement and removing :type but it keeps throwing the same error. when I use $phpversion = phpversion it just thinks its a text string instead of a function (which I expected, but tried anyway).
Any help would be greatly appreciated.
If you're trying to get the version of php, it'd probably be easier to do it as a fact:
Facter.add(:phpversion) do
setcode do
if Facter::Util::Resolution.which('php')
Facter::Util::Resolution.exec('/usr/bin/php -r 'echo PHP_MAJOR_VERSION . \".\" . PHP_MINOR_VERSION;'"').lines.first.split(/"/)[1].strip
end
end
end
Put this a directory lib/facter/ in your module, then reference it in your manifest as $::phpversion

ruby running commands on a remote machine

I'm trying to run commands remotely with ruby's net ssh. I need the output as well as the exit code. There are other stackoverflow threads on this topic but the accepted solutions do not work. Some people suggested using net-ssh-shell gem but as I tried it, I got an error saying that this package is in conflict with the version of my net-ssh package...
Here is what I have:
Net::SSH.start(remote_ip, username,:keys => [ssh_key_path], :verbose => :debug) do |ssh|
cmd = "blah bla"
result = ssh.exec!(cmd)
puts result
end
It works but it does not raise an exception if it fails. I've also tried using the channel to retrieve the exit code but it always returns 0:
channel.on_request("exit-status") do |ch,data|
exit_code = data.read_long
end
Please help me out. I've already tried several things based on wrong info on the internet.
If you are using Ruby 1.9+ I would suggest Open3.popen3:
i, o, e, t = Open3.popen3("ssh ... remote_user#remote_host remote_command")
i.write ... # if your command needs input
output = o.read
error = e.read
status = t.value.exitstatus

Mercurial HG_NODE hook variable on windows

I'm currently testing mercurial hooks on windows and it seems like I cannot access hook variables....
here's hgrc content :
[hooks] prechangegroup = ruby prechangegroup.rb test1 test2 $HG_NODE
I also tried with %HG_NODE%
Here's prechangegroup.rb content
ARGV.each do|a|
puts "Argument: #{a}"
end
It prints out:
Argument: test1
Argument: test2
Argument: $HG_NODE$
Followed by the normal push output...
Any idea? (probably something stupid but, I can't seem to find it)
Thanks
HG_NODE is an environmental variable. You don't have to use it as arguments on the command line. Instead, you should be able to use it as puts ENV['HG_NODE'] (found through search engine as I'm not a ruby guy)
OK, I found a good documentation right on mercurial's website.
http://www.selenic.com/mercurial/hgrc.5.html#hooks
I tried with a variable other than %HG_NODE% like %HG_URL% and the variable worked.
So it probably means that the variable is inaccessible from that hook.

Resources