Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ Changelog
### New Cisco Resources

### Added
* Extend nxapi client for https support
* `use_ssl` will be true when `transport` is `https`
* now makes use of `port` for custom nxapi ports
* Extend router_ospf_vrf with attribute:
* `redistribute`
* `reset_instance` method to node. Allows a single instance of nodeutils to reset the environment cache.
Expand Down
46 changes: 40 additions & 6 deletions lib/cisco_node_utils/client/nxapi/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# November 2014, Glenn F. Matthews
#
# Copyright (c) 2014-2016 Cisco and/or its affiliates.
# Copyright (c) 2014-2019 Cisco and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -60,7 +60,11 @@ def initialize(**kwargs)
else
# Remote connection. This is primarily expected
# when running e.g. from a Unix server as part of Minitest.
@http = Net::HTTP.new(@host)
@transport = kwargs[:transport] || 'http'
@verify_mode = kwargs[:verify_mode] || 'none'
@port.nil? ? @port = '' : @port = ":#{@port}"
uri = URI.parse("#{@transport}://#{@host}#{@port}")
@http = Net::HTTP.new(uri.host, uri.port)
end
# The default read time out is 60 seconds, which may be too short for
# scaled configuration to apply. Change it to 300 seconds, which is
Expand Down Expand Up @@ -205,14 +209,18 @@ def req(type, command_or_list)
request = build_http_request(type, command)

# send the request and get the response
debug("Sending HTTP request to NX-API at #{@http.address}:\n" \
debug("Sending #{@transport} request to NX-API at #{@http.address}:\n" \
"#{request.to_hash}\n#{request.body}")
read_timeout_check(request)
tries = 2
begin
# Explicitly use http to avoid EOFError
# http://stackoverflow.com/a/23080693
@http.use_ssl = false
if @transport == 'https'
debug('Setting use_ssl to true')
@http.use_ssl = true
@http.verify_mode = handle_verify_mode(@verify_mode)
else
@http.use_ssl = false
end
response = @http.request(request)
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
emsg = 'Connection refused or reset. Is the NX-API feature enabled?'
Expand Down Expand Up @@ -268,6 +276,32 @@ def build_http_request(type, command_string)
end
private :build_http_request

# Returns the OpenSSL verify mode based on the verify_mode arguments
#
# @raise if verify_mode param is not `peer`, `client-once`, `fail-no-peer`
# or `none`
#
# @param String verify mode to use
#
# @return OpenSSL::SSL verification mode
def handle_verify_mode(verify_mode)
case verify_mode
when 'peer'
OpenSSL::SSL::VERIFY_PEER
when 'client-once'
OpenSSL::SSL::VERIFY_CLIENT_ONCE
when 'fail-no-peer'
OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
when 'none'
OpenSSL::SSL::VERIFY_NONE
else
fail "#{verify_mode} is not a valid mode, " \
'valid modes are: "none", "peer", ' \
'"client-once", "fail-no-peer"'
end
end
private :handle_verify_mode

def handle_http_response(response)
debug("HTTP Response: #{response.message}\n#{response.body}")
case response
Expand Down
44 changes: 40 additions & 4 deletions tests/basetest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,56 @@ def password
self.class.password
end

def self.telnet_port
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you exposing a telnet port? Are you using a non-default port in your test environment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I am using non-default in my local test environment

Cisco::Environment.environment[:telnet_port] || 23
end

def telnet_port
self.class.telnet_port
end

def self.port
Cisco::Environment.environment[:port] || address.split(':')[1]
end

def port
self.class.port
end

def self.transport
Cisco::Environment.environment[:transport] || 'http'
end

def transport
self.class.transport
end

def self.verify_mode
Cisco::Environment.environment[:verify_mode] || 'none'
end

def verify_mode
self.class.verify_mode
end

def setup
# Hack - populate environment from user-entered values from basetest.rb
if Cisco::Environment.environments.empty?
class << Cisco::Environment
attr_writer :environments
end
Cisco::Environment.environments['default'] = {
host: address.split(':')[0],
port: address.split(':')[1],
username: username,
password: password,
host: address.split(':')[0],
port: port,
telnet_port: telnet_port,
transport: transport,
verify_mode: verify_mode,
username: username,
password: password,
}
end
@device = Net::Telnet.new('Host' => address.split(':')[0],
'Port' => telnet_port,
'Timeout' => 240,
# NX-OS has a space after '#', IOS XR does not
'Prompt' => /[$%#>] *\z/n,
Expand Down