Class: Controller

Inherits:
Object
  • Object
show all
Defined in:
lib/controller/controller.rb

Overview

Class that represents a Controller device.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ip_addr: nil, port_number: 8181, admin_name: nil, admin_password: nil, timeout_in_s: 5) ⇒ Controller

Parameters

  • ip_addr

    String : IP address of the BVC. e.g. 192.168.56.101

  • port_number

    String : Port number of the BVC RESTCONF API. e.g. 8181

  • admin_name

    String : Admin userid for logon to BVC RESTCONF API. e.g. admin

  • admin_password

    String : Admin password for logon to BVC RESTCONF API. e.g. admin

  • timeout_in_s

    Integer : Number of seconds to wait for a response from BVC to RESTCONF request. e.g. 5

Raises:

  • (ArgumentError)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/controller/controller.rb', line 62

def initialize(ip_addr: nil, port_number: 8181, admin_name: nil,
    admin_password: nil, timeout_in_s: 5) 
  raise ArgumentError, "IP Address (ip_addr) required" unless ip_addr
  raise ArgumentError, "Admin Username (admin_name) required" unless admin_name
  raise ArgumentError, "Admin Password (admin_password) required" unless admin_password
  @ip = ip_addr
  @port = port_number
  @username = admin_name
  @password = admin_password
  @timeout = timeout_in_s
  
  @rest_agent = RestAgent.new("http://#{@ip}:#{@port}", username: @username,
    password: @password, open_timeout: @timeout)
end

Instance Attribute Details

#ipObject (readonly)

String : IP address of the BVC. e.g. 192.168.56.101



43
44
45
# File 'lib/controller/controller.rb', line 43

def ip
  @ip
end

#passwordObject (readonly)

String : Admin password for logon to BVC RESTCONF API. e.g. admin



49
50
51
# File 'lib/controller/controller.rb', line 49

def password
  @password
end

#portObject (readonly)

String : Port number of the BVC RESTCONF API. e.g. 8181



45
46
47
# File 'lib/controller/controller.rb', line 45

def port
  @port
end

#rest_agentObject (readonly)

RestAgent : The REST agent connected to controller.



53
54
55
# File 'lib/controller/controller.rb', line 53

def rest_agent
  @rest_agent
end

#timeoutObject (readonly)

Integer : Number of seconds to wait for a response from BVC to RESTCONF request. e.g. 5



51
52
53
# File 'lib/controller/controller.rb', line 51

def timeout
  @timeout
end

#usernameObject (readonly)

String : Admin userid for logon to BVC RESTCONF API. e.g. admin



47
48
49
# File 'lib/controller/controller.rb', line 47

def username
  @username
end

Instance Method Details

#add_netconf_node(node) ⇒ Object

Connect a netconf device to the controller (for example connect vrouter to controller via NetConf)

Parameters

  • node

    NetconfNode : A netconf node.

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and JSON providing response from adding the node.



498
499
500
501
502
503
504
505
506
507
508
# File 'lib/controller/controller.rb', line 498

def add_netconf_node(node)
  post_uri = "/restconf/config/opendaylight-inventory:nodes/node/"\
    "controller-config/yang-ext:mount/config:modules"
  post_body = generate_node_xml(node)    
  response = @rest_agent.post_request(post_uri, post_body,
    headers: {'Content-Type' => "application/xml",
      'Accept' => "application/xml"})
  check_response_for_success(response) do
      NetconfResponse.new(NetconfResponseStatus::OK)
  end
end

#check_node_config_status(node_name) ⇒ Object

Return the configuration status of the node.

Parameters

  • node_name

    String : name of the node from the #get_all_nodes_in_config

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and configuration status of requested node.



416
417
418
419
420
421
422
423
# File 'lib/controller/controller.rb', line 416

def check_node_config_status(node_name)
  get_uri = "/restconf/config/opendaylight-inventory:nodes/node/#{node_name}"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do
    NetconfResponse.new(NetconfResponseStatus::NODE_CONFIGURED,
      JSON.parse(response.body))
  end
end

#check_node_conn_status(node_name) ⇒ Object

Return the connection status of the node to the controller.

Parameters

  • node_name

    String : name of the node from the #get_nodes_operational_list

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and Status of the node’s connection to the controller. Note: currently OpenFlow nodes are always shown disconnected..



433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
# File 'lib/controller/controller.rb', line 433

def check_node_conn_status(node_name)
  get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
    "#{node_name}"
  response = @rest_agent.get_request(get_uri)
  if response.code.to_i == 404
    NetconfResponse.new(NetconfResponseStatus::NODE_NOT_FOUND)
  else
    check_response_for_success(response) do |body|
      connected = false
      if body.has_key?('node') && body['node'][0] && body['node'][0].has_key?('id')
        if body['node'][0].has_key?('netconf-node-inventory:connected')
          if body['node'][0]['netconf-node-inventory:connected']
            connected = true
          end
        end
      end
      if connected
        NetconfResponse.new(NetconfResponseStatus::NODE_CONNECTED)
      else
        NetconfResponse.new(NetconfResponseStatus::NODE_DISCONNECTED)
      end
    end
  end
end

#delete_netconf_node(node) ⇒ Object

Disconnect a netconf device from the controller.

Parameters

  • node

    NetconfNode : node to disconnect from the controller.

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and response if error.



518
519
520
521
522
523
524
525
526
527
528
529
530
# File 'lib/controller/controller.rb', line 518

def delete_netconf_node(node)
  delete_uri = "/restconf/config/opendaylight-inventory:nodes/node/"\
    "controller-config/yang-ext:mount/config:modules/module/"\
    "odl-sal-netconf-connector-cfg:sal-netconf-connector/#{node.name}"
  response = @rest_agent.delete_request(delete_uri)
  # need to do the check here because there is no response body and the code
  # is a 200 instead of 204
  if response.code.to_i == 200
    NetconfResponse.new(NetconfResponseStatus::OK)
  else
    handle_error_response(response)
  end
end

#get_all_modules_operational_stateObject

Return a list of modules and their operational state.

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and JSON listing modules and their operational state



194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/controller/controller.rb', line 194

def get_all_modules_operational_state
  get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
    "controller-config/yang-ext:mount/config:modules"
  response = @rest_agent.get_request(get_uri)
  response.body.gsub!("\\\n", "")
  check_response_for_success(response) do |body|
    if body.has_key?('modules') && body['modules'].has_key?('module')
      NetconfResponse.new(NetconfResponseStatus::OK, body['modules']['module'])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_all_nodes_conn_statusObject

Return a list of nodes and the status of their connection to the controller.

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and list of nodes and their connection to the controller.



464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'lib/controller/controller.rb', line 464

def get_all_nodes_conn_status
  get_uri = "/restconf/operational/opendaylight-inventory:nodes"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('nodes') && body['nodes'].has_key?('node')
      conn_list = []
      body['nodes']['node'].each do |node|
        is_connected = false
        if node['id'].include?('openflow')
          # OpenFlow devices connect to controller (unlike NETCONF nodes),
          # so if we see one, then it is 'connected'
          is_connected = true
        elsif node.has_key?('netconf-node-inventory:connected')
          is_connected = node['netconf-node-inventory:connected']
        end
        conn_status = {:node => node['id'],
          :connected => is_connected}
        conn_list << conn_status
      end
      NetconfResponse.new(NetconfResponseStatus::OK, conn_list)
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_all_nodes_in_configObject

Return a list of nodes in the controller’s config data store

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and list of nodes in the config data store of the controller



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/controller/controller.rb', line 279

def get_all_nodes_in_config
  get_uri = "/restconf/config/opendaylight-inventory:nodes"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('nodes') && body['nodes'].has_key?('node')
      devices = []
      body['nodes']['node'].each do |node|
        devices << node['id']
      end
      NetconfResponse.new(NetconfResponseStatus::OK, devices)
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_ext_mount_config_uri(node) ⇒ Object

Return the netconf mountpoint url to the configured node.

Parameters

  • node

    NetconfNode : node for which to return the url.

Return Value

  • String: Url

Raises:

  • (ArgumentError)


570
571
572
573
574
# File 'lib/controller/controller.rb', line 570

def get_ext_mount_config_uri(node)
  raise ArgumentError, "Node (node) must be a 'Node' object or a 'Node' "\
    "subclass object" unless node.is_a?(Node)
  "/restconf/config/opendaylight-inventory:nodes/node/#{node.name}/yang-ext:mount"
end

#get_module_operational_state(type: nil, name: nil) ⇒ Object

Return operational state for specified module.

Parameters

  • type

    String : module type

  • name

    String : module name

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and JSON providing operational state

Raises:

  • (ArgumentError)


217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/controller/controller.rb', line 217

def get_module_operational_state(type: nil, name: nil)
  raise ArgumentError, "Type (type) required" unless type
  raise ArgumentError, "Name (name) required" unless name
  get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
    "controller-config/yang-ext:mount/config:modules/module/"\
    "#{type}/#{name}"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('module')
      NetconfResponse.new(NetconfResponseStatus::OK, body["module"])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_netconf_nodes_conn_statusObject

Return a list of NETCONF nodes in the operational data store of controller and the status of their connection to the controller.

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and list of nodes the status of their connection to the controller.



323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/controller/controller.rb', line 323

def get_netconf_nodes_conn_status
  get_uri = "/restconf/operational/opendaylight-inventory:nodes"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('nodes') && body['nodes'].has_key?('node')
      conn_list = []
      body['nodes']['node'].each do |node|
        unless node['id'].include?('openflow')
          conn_status = {:node => node['id'],
            :connected => node['netconf-node-inventory:connected']}
          conn_list << conn_status
        end
      end
      NetconfResponse.new(NetconfResponseStatus::OK, conn_list)
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_netconf_nodes_in_configObject

Return a list of NETCONF nodes in the controller’s configuration data store

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and list of nodes in the config data store of the controller



301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/controller/controller.rb', line 301

def get_netconf_nodes_in_config 
  get_uri = "/restconf/config/opendaylight-inventory:nodes"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('nodes') && body['nodes'].has_key?('node')
      devices = []
      body['nodes']['node'].each do |node|
        devices << node['id'] unless node['id'].include?('openflow')
      end
      NetconfResponse.new(NetconfResponseStatus::OK, devices)
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_netconf_operations(node_name) ⇒ Object

Return a list of operations supported by the indicated node.

Parameters

  • node_name

    String : name of the node from the #get_all_nodes_in_config

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and operations supported by indicated node.



175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/controller/controller.rb', line 175

def get_netconf_operations(node_name)
  get_uri = "/restconf/operations/opendaylight-inventory:nodes/node/"\
    "#{node_name}/yang-ext:mount"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('operations')
      NetconfResponse.new(NetconfResponseStatus::OK, body['operations'])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_node_config_uri(node) ⇒ Object

Return the url to the configured node.

Parameters

  • node

    NetconfNode : node for which to return the url.

Return Value

  • String: Url

Raises:

  • (ArgumentError)


555
556
557
558
559
560
# File 'lib/controller/controller.rb', line 555

def get_node_config_uri(node)
  raise ArgumentError, "Node (node) must be a 'Node' object or a 'Node' "\
    "subclass object" unless node.is_a?(Node) ||
    (node.methods.include?(:ancestors) && node.ancestors.include?(Node))
  "/restconf/config/opendaylight-inventory:nodes/node/#{node.name}"
end

#get_node_info(node_name) ⇒ Object

Return information about a node in the operational data store.

Parameters

  • node_name

    String : name of the node in operational data store from the #get_nodes_operational_list

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and JSON data about the requested node.



395
396
397
398
399
400
401
402
403
404
405
406
# File 'lib/controller/controller.rb', line 395

def get_node_info(node_name)
  get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
    "#{node_name}"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('node')
      NetconfResponse.new(NetconfResponseStatus::OK, body['node'])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_node_operational_uri(node) ⇒ Object

Return the url to the operational node.

Parameters

  • node

    NetconfNode : node for which to return the url.

Return Value

  • String: Url

Raises:

  • (ArgumentError)


540
541
542
543
544
545
# File 'lib/controller/controller.rb', line 540

def get_node_operational_uri(node)
  raise ArgumentError, "Node (node) must be a 'Node' object or a 'Node' "\
    "subclass object" unless node.is_a?(Node) ||
    (node.methods.include?(:ancestors) && node.ancestors.include?(Node))
  "/restconf/operational/opendaylight-inventory:nodes/node/#{node.name}"
end

#get_nodes_operational_listObject

Return a list of nodes in the controllers operational data store.

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and list of nodes in controller’s operational data store.



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/controller/controller.rb', line 349

def get_nodes_operational_list
  get_uri = "/restconf/operational/opendaylight-inventory:nodes"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('nodes') && body['nodes'].has_key?('node')
      list = []
      body['nodes']['node'].each do |node|
        list << node['id'] if node['id']
      end
      NetconfResponse.new(NetconfResponseStatus::OK, list)
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_openflow_nodes_operational_listObject

Return a list of nodes that support OpenFlow in the Controller’s operational data store.

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and list of OpenFlow-capable nodes in the Controller’s operational database.



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
# File 'lib/controller/controller.rb', line 371

def get_openflow_nodes_operational_list
  get_uri = "/restconf/operational/opendaylight-inventory:nodes"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('nodes') && body['nodes'].has_key?('node')
      filtered_list = []
      body['nodes']['node'].each do |node|
        filtered_list << node['id'] if node['id'].start_with?('openflow')
      end
      NetconfResponse.new(NetconfResponseStatus::OK, filtered_list)
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_schema(node_name, id: nil, version: nil) ⇒ Object

Return a YANG schema for the indicated schema on the indicated node.

Parameters

  • node_name

    String : name of the node from the #get_all_nodes_in_config

  • id

    String : Identifier for schema

  • version

    String : Version/date for schema

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and YANG schema.

Raises:

  • (ArgumentError)


108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/controller/controller.rb', line 108

def get_schema(node_name, id: nil, version: nil)
  raise ArgumentError, "Identifier (id) required" unless id
  raise ArgumentError, "Version (version) required" unless version
  post_uri = "/restconf/operations/opendaylight-inventory:nodes/node/"\
    "#{node_name}/yang-ext:mount/ietf-netconf-monitoring:get-schema"
  post_body = {:input => {:identifier => id, :version => version,
      :format => 'yang'}}
  response = @rest_agent.post_request(post_uri, post_body)
  check_response_for_success(response) do |body|
    if body.has_key?('get-schema') && body['get-schema'].has_key?('output') &&
        body['get-schema']['output'].has_key?('data')
      NetconfResponse.new(NetconfResponseStatus::OK,
        body['get-schema']['output']['data'])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_schemas(node_name) ⇒ Object

Return a list of YANG schemas for the node.

Parameters

  • node_name

    String : name of the node from the #get_all_nodes_in_config

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and list of YANG schemas for the node.



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/controller/controller.rb', line 85

def get_schemas(node_name)
  get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
    "#{node_name}/yang-ext:mount/ietf-netconf-monitoring:netconf-state/schemas"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('schemas') && body['schemas'].has_key?('schema')
      NetconfResponse.new(NetconfResponseStatus::OK, body['schemas']['schema'])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_service_provider_info(provider_name) ⇒ Object

Return info about a single service provider.

Parameters

  • provider_name

    name of the service provider from get_service_providers_info

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and JSON providing info about the service provider.



154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/controller/controller.rb', line 154

def get_service_provider_info(provider_name)
  get_uri = "/restconf/config/opendaylight-inventory:nodes/node/"\
    "controller-config/yang-ext:mount/config:services/service/#{provider_name}"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('service')
      NetconfResponse.new(NetconfResponseStatus::OK, body['service'])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_service_providers_infoObject

Return a list of service providers available.

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and JSON providing a list of service providers.



133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/controller/controller.rb', line 133

def get_service_providers_info
  get_uri = "/restconf/config/opendaylight-inventory:nodes/node/"\
    "controller-config/yang-ext:mount/config:services"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('services') && body['services'].has_key?('service')
      NetconfResponse.new(NetconfResponseStatus::OK, body['services']['service'])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_sessions_info(node_name) ⇒ Object

Return sessions for indicated node.

Parameters

  • node_name

    String : name of the node from the #get_all_nodes_in_config

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and JSON providing list of sessions.



241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/controller/controller.rb', line 241

def get_sessions_info(node_name)
  get_uri = "/restconf/operational/opendaylight-inventory:nodes/node/"\
    "#{node_name}/yang-ext:mount/ietf-netconf-monitoring:netconf-state/"\
    "sessions"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('sessions')
      NetconfResponse.new(NetconfResponseStatus::OK, body["sessions"])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#get_streams_infoObject

Return streams available for subscription.

Return Value

  • NetconfResponse : Status ( NetconfResponseStatus ) and JSON providing list of streams.



261
262
263
264
265
266
267
268
269
270
271
# File 'lib/controller/controller.rb', line 261

def get_streams_info
  get_uri = "restconf/streams"
  response = @rest_agent.get_request(get_uri)
  check_response_for_success(response) do |body|
    if body.has_key?('streams')
      NetconfResponse.new(NetconfResponseStatus::OK, body['streams'])
    else
      NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
    end
  end
end

#to_hashObject

:nodoc:



577
578
579
580
# File 'lib/controller/controller.rb', line 577

def to_hash #:nodoc:
  {:ip_addr => @ip, :port_num => @port, :admin_name => @username,
    :admin_password => @password}
end