ruby_nsx_cli 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.idea/.rakeTasks +7 -0
- data/.idea/dictionaries/dancole.xml +3 -0
- data/.idea/inspectionProfiles/Project_Default.xml +6 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/ruby_nsx_cli.iml +23 -0
- data/.idea/vcs.xml +6 -0
- data/.idea/workspace.xml +719 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +33 -0
- data/LICENSE.txt +21 -0
- data/README.md +130 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/ruby_nsx_cli/nsx_objects/nsx_edge.rb +184 -0
- data/lib/ruby_nsx_cli/nsx_objects/nsx_virtualwire.rb +87 -0
- data/lib/ruby_nsx_cli/nsx_objects/nsxobject.rb +189 -0
- data/lib/ruby_nsx_cli/nsx_objects/templates/dhcp/relayagent.xml.erb +4 -0
- data/lib/ruby_nsx_cli/nsx_objects/templates/dhcp/simple-dhcp-pool.xml.erb +9 -0
- data/lib/ruby_nsx_cli/nsx_objects/templates/interface/interfaces.xml.erb +15 -0
- data/lib/ruby_nsx_cli/nsx_objects/templates/virtualwire/virtualwire.xml.erb +6 -0
- data/lib/ruby_nsx_cli/version.rb +3 -0
- data/lib/ruby_nsx_cli.rb +6 -0
- data/ruby_nsx_cli.gemspec +28 -0
- metadata +141 -0
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at daniel.cole@superchoice.com.au. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in ruby_nsx_cli.gemspec
|
6
|
+
|
7
|
+
gem 'rake', "~> 12.0.0"
|
8
|
+
gem 'rest-client', '2.0.2'
|
9
|
+
gem 'nokogiri', '1.8.1'
|
10
|
+
gem 'minitest', '5.10.1'
|
11
|
+
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
domain_name (0.5.20170404)
|
5
|
+
unf (>= 0.0.5, < 1.0.0)
|
6
|
+
http-cookie (1.0.3)
|
7
|
+
domain_name (~> 0.5)
|
8
|
+
mime-types (2.99.3)
|
9
|
+
mini_portile2 (2.3.0)
|
10
|
+
minitest (5.10.1)
|
11
|
+
netrc (0.11.0)
|
12
|
+
nokogiri (1.8.1)
|
13
|
+
mini_portile2 (~> 2.3.0)
|
14
|
+
rake (12.0.0)
|
15
|
+
rest-client (2.0.2)
|
16
|
+
http-cookie (>= 1.0.2, < 2.0)
|
17
|
+
mime-types (>= 1.16, < 4.0)
|
18
|
+
netrc (~> 0.8)
|
19
|
+
unf (0.1.4)
|
20
|
+
unf_ext
|
21
|
+
unf_ext (0.0.7.4)
|
22
|
+
|
23
|
+
PLATFORMS
|
24
|
+
ruby
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
minitest (= 5.10.1)
|
28
|
+
nokogiri (= 1.8.1)
|
29
|
+
rake (~> 12.0.0)
|
30
|
+
rest-client (= 2.0.2)
|
31
|
+
|
32
|
+
BUNDLED WITH
|
33
|
+
1.16.0
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Daniel Cole
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
# RubyNsxCli
|
2
|
+
|
3
|
+
This gem is in early stages of development and has only a small set of VMWare's NSX
|
4
|
+
API currently implemented.
|
5
|
+
|
6
|
+
The main focus for developing this gem was to provide a simple way to automate network creation using the NSX API.
|
7
|
+
|
8
|
+
## Features
|
9
|
+
|
10
|
+
1. Creation and deletion of virtual wires
|
11
|
+
2. Attaching interfaces an edge
|
12
|
+
3. Adding DHCP relay agents to an edge
|
13
|
+
4. Creating a DHCP IP pool on an edge (This is limited in that it only provides a subset of the available options)
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem 'ruby_nsx_cli'
|
21
|
+
```
|
22
|
+
|
23
|
+
And then execute:
|
24
|
+
|
25
|
+
$ bundle
|
26
|
+
|
27
|
+
Or install it yourself as:
|
28
|
+
|
29
|
+
$ gem install ruby_nsx_cli
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
Create a new virtual wire:
|
34
|
+
```ruby
|
35
|
+
virtualwire = RubyNsxCli::NSXVirtualWire.new
|
36
|
+
|
37
|
+
virtualwire_args = {
|
38
|
+
:name => 'api-test-wire-1',
|
39
|
+
:scope_id => 'vdnscope-1',
|
40
|
+
:description => 'virtual wire for api testing',
|
41
|
+
:tenant_id => nil,
|
42
|
+
:control_plane_mode => nil
|
43
|
+
}
|
44
|
+
|
45
|
+
virtualwire.create(virtualwire_args)
|
46
|
+
```
|
47
|
+
|
48
|
+
Attach an interface to an edge:
|
49
|
+
```ruby
|
50
|
+
edge = RubyNsxCli::NSXEdge.new
|
51
|
+
|
52
|
+
|
53
|
+
interface_args = {
|
54
|
+
:edge_id => 'edge-5',
|
55
|
+
:name => 'api-test-lif-1',
|
56
|
+
:primary_address => '10.250.30.1',
|
57
|
+
:subnet_mask => '255.255.255.0',
|
58
|
+
:mtu => '1500',
|
59
|
+
:connected_to_id => virtualwire_id,
|
60
|
+
:type => 'internal'
|
61
|
+
}
|
62
|
+
|
63
|
+
edge.attach_interface(interface_args)
|
64
|
+
```
|
65
|
+
|
66
|
+
Chain commands together to create a new virtualwire, attach the interface and create a DHCP pool:
|
67
|
+
```ruby
|
68
|
+
# First, create the virtual wire
|
69
|
+
virtualwire = RubyNsxCli::NSXVirtualWire.new
|
70
|
+
virtualwire_args = {
|
71
|
+
:name => 'api-test-wire-attach-dhcp-1',
|
72
|
+
:scope_id => 'vdnscope-1',
|
73
|
+
:description => 'virtual wire for api testing',
|
74
|
+
:tenant_id => nil,
|
75
|
+
:control_plane_mode => nil
|
76
|
+
}
|
77
|
+
virtualwire_id = virtualwire.create(virtualwire_args)
|
78
|
+
|
79
|
+
# Second, attach the interface to the specified edge
|
80
|
+
edge = RubyNsxCli::NSXEdge.new
|
81
|
+
gateway_address = '10.250.31.1'
|
82
|
+
|
83
|
+
interface_args = {
|
84
|
+
:edge_id => 'edge-5',
|
85
|
+
:name => 'api-test-lif-dhcp-1',
|
86
|
+
:primary_address => gateway_address,
|
87
|
+
:subnet_mask => '255.255.255.0',
|
88
|
+
:mtu => '1500',
|
89
|
+
:connected_to_id => virtualwire_id,
|
90
|
+
:type => 'internal'
|
91
|
+
}
|
92
|
+
|
93
|
+
# The response from attaching the interface will contain the vnic index required for adding a DHCP relay
|
94
|
+
response = edge.attach_interface(interface_args)
|
95
|
+
|
96
|
+
# Parse the vNIC index from the response given when attaching the interface
|
97
|
+
vnic_index = edge.get_attr_text_from_xml(response, 'index')
|
98
|
+
|
99
|
+
# Finally, add the dhcp agent to the edge
|
100
|
+
edge.add_dhcp_agent(edge_id, vnic_index, gateway_address)
|
101
|
+
```
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
## Development
|
106
|
+
|
107
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
108
|
+
|
109
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
110
|
+
|
111
|
+
Please note that you will need to set the following environment variables before running `rake test`:
|
112
|
+
1. NSX_USERNAME
|
113
|
+
2. NSX_PASSWORD
|
114
|
+
3. NSX_MANAGER_URL
|
115
|
+
4. NSX_TEST_ESG_ID
|
116
|
+
5. NSX_TEST_DLR_ID
|
117
|
+
|
118
|
+
How to run a single test using rake:
|
119
|
+
```
|
120
|
+
rake test TEST=test/nsx_edge_test.rb TESTOPTS="--name=test_add_dhcp_relay -v"
|
121
|
+
```
|
122
|
+
|
123
|
+
|
124
|
+
## Contributing
|
125
|
+
|
126
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/daniel-cole/ruby_nsx_cli. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
127
|
+
|
128
|
+
## License
|
129
|
+
|
130
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "ruby_nsx_cli"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
require_relative 'nsxobject'
|
2
|
+
|
3
|
+
module RubyNsxCli
|
4
|
+
class NSXEdge < NSXObject
|
5
|
+
|
6
|
+
INTERFACE_TYPES = %w[internal uplink]
|
7
|
+
|
8
|
+
|
9
|
+
# Attaches an interface to the specified edge
|
10
|
+
#
|
11
|
+
# @param edge_id [String] Edge ID to
|
12
|
+
# @param name [String] Name of the interface
|
13
|
+
# @param primary_address [Integer] Primary IP address for the interface
|
14
|
+
# @param subnet_mask [String] Subnet mask for the network that the interface is attached to
|
15
|
+
# @param mtu [Integer] Maximum transmission unit for the interface
|
16
|
+
# @param connected_to_id [String] ID of the virtualwire or port group to attach the interface to
|
17
|
+
# @param type [Type] Network link type; either 'internal' or 'uplink'
|
18
|
+
# @return [String] Interface XML configuration from the NSX API
|
19
|
+
def attach_interface(edge_id:, name:, primary_address:, subnet_mask:, mtu:, connected_to_id:, type:)
|
20
|
+
api_endpoint = "/api/4.0/edges/#{edge_id}/interfaces/?action=patch"
|
21
|
+
|
22
|
+
interface_hash = {
|
23
|
+
:name => name,
|
24
|
+
:primary_address => primary_address,
|
25
|
+
:subnet_mask => subnet_mask,
|
26
|
+
:mtu => mtu || 1500,
|
27
|
+
:connected_to_id => connected_to_id,
|
28
|
+
:type => type
|
29
|
+
}
|
30
|
+
|
31
|
+
validate_edge_args(interface_hash, edge_id)
|
32
|
+
raise "The interface type must be one of: #{INTERFACE_TYPES.to_s}" if !INTERFACE_TYPES.include?(interface_hash[:type])
|
33
|
+
|
34
|
+
@logger.info("Checking if interface already exists on edge: #{edge_id}")
|
35
|
+
if (interface = check_interface_exists(edge_id, connected_to_id))
|
36
|
+
@logger.info("Skipping interface - interface already exists (edgeId: #{edge_id} connectedToId: #{connected_to_id})")
|
37
|
+
return interface
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
interface_obj = OpenStruct.new(interface_hash)
|
42
|
+
payload = render_template('/templates/interface/interfaces.xml.erb', interface_obj)
|
43
|
+
|
44
|
+
post(:api_endpoint => api_endpoint, :payload => payload)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Adds a DHCP relay agent to the specified edge for the specified vNIC
|
48
|
+
# This method is not safe to run concurrently
|
49
|
+
#
|
50
|
+
# @param edge_id [String] Edge Id to add the DHCP agent to
|
51
|
+
# @param gi_address [String] Gateway IP address
|
52
|
+
# @param vnic_index [Integer] vNIC index of the interface on the specified edge to add the DHCP relay agent
|
53
|
+
# @return [RestClient::Response] Response from the NSX API
|
54
|
+
def add_dhcp_agent(edge_id, vnic_index, gi_address)
|
55
|
+
|
56
|
+
api_endpoint = "/api/4.0/edges/#{edge_id}/dhcp/config/relay"
|
57
|
+
|
58
|
+
dhcp_agent_hash = {
|
59
|
+
:vnic_index => vnic_index,
|
60
|
+
:gi_address => gi_address
|
61
|
+
}
|
62
|
+
|
63
|
+
validate_edge_args(dhcp_agent_hash, edge_id)
|
64
|
+
|
65
|
+
dhcp_agent_obj = OpenStruct.new(dhcp_agent_hash)
|
66
|
+
dhcp_agent_xml = render_template('/templates/dhcp/relayagent.xml.erb', dhcp_agent_obj)
|
67
|
+
|
68
|
+
# The DHCP configuration must be retrieved as the put operation overrides the current config
|
69
|
+
# There does not seem to be an alternative way of doing this
|
70
|
+
current_dhcp_config = get("/api/4.0/edges/#{edge_id}/dhcp/config/relay")
|
71
|
+
|
72
|
+
@logger.info("Checking if DHCP agent already exists on edge: #{edge_id}")
|
73
|
+
if check_dhcp_agent_exists(current_dhcp_config, vnic_index, gi_address)
|
74
|
+
@logger.info("Skipping Agent - DHCP agent already exists (vnicIndex: #{vnic_index} giAddress #{gi_address})")
|
75
|
+
return
|
76
|
+
end
|
77
|
+
|
78
|
+
@logger.info("Adding Agent (vnicIndex: #{vnic_index} giAddress #{gi_address})")
|
79
|
+
|
80
|
+
# Grandparent xml node must be provided in the case that the parent node does not exist
|
81
|
+
# i.e. <relayAgents /> does not exist if there are no current relay agents on the edge
|
82
|
+
payload = inject_xml(current_dhcp_config, 'relay', 'relayAgents', dhcp_agent_xml)
|
83
|
+
|
84
|
+
# Strip out XML pi at top of response to prevent 500 errors due to bad formatting of XML payload
|
85
|
+
payload = strip_xml_root_pi(payload)
|
86
|
+
|
87
|
+
put(:api_endpoint => api_endpoint, :payload => payload)
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
# Adds a DHCP IP pool agent to the specified edge
|
92
|
+
# This creates a simple dhcp pool as it only allows a small number of the available options to be specified
|
93
|
+
#
|
94
|
+
# @param edge_id [String] Edge ID to add the DHCP pool
|
95
|
+
# @param ip_range [String] Range of IP addresses to include in the DHCP pool. i.e. 192.168.10.2-192.168.10.62
|
96
|
+
# @param default_gateway [String] Default gateway for the network that the agent is providing DHCP to
|
97
|
+
# @param primary_name_server [String] Primary DNS
|
98
|
+
# @param secondary_name_server [String] Secondary DNS
|
99
|
+
# @param lease_time [Integer] DHCP lease time. Defaults to 3600
|
100
|
+
# @return [RestClient::Response] Response from the NSX API
|
101
|
+
def add_simple_dhcp_pool(edge_id:, ip_range:, default_gateway:, domain_name:, primary_name_server:, secondary_name_server:, lease_time:)
|
102
|
+
|
103
|
+
api_endpoint = "/api/4.0/edges/#{edge_id}/dhcp/config/ippools"
|
104
|
+
|
105
|
+
simple_dhcp_pool_hash = {
|
106
|
+
:ip_range => ip_range,
|
107
|
+
:default_gateway => default_gateway,
|
108
|
+
:domain_name => domain_name,
|
109
|
+
:primary_name_server => primary_name_server,
|
110
|
+
:secondary_name_server => secondary_name_server,
|
111
|
+
:lease_time => lease_time || 3600
|
112
|
+
}
|
113
|
+
|
114
|
+
validate_edge_args(simple_dhcp_pool_hash, edge_id)
|
115
|
+
@logger.info("Checking if DHCP IP pool already exists on edge: #{edge_id}")
|
116
|
+
if (ip_pool_id = check_simple_dhcp_pool_exists(edge_id, ip_range))
|
117
|
+
@logger.info("Skipping DHCP IP Pool - already exists (edgeId: #{edge_id} ipRange: #{ip_range})")
|
118
|
+
return ip_pool_id
|
119
|
+
end
|
120
|
+
|
121
|
+
simple_dhcp_pool_obj = OpenStruct.new(simple_dhcp_pool_hash)
|
122
|
+
payload = render_template('/templates/dhcp/simple-dhcp-pool.xml.erb', simple_dhcp_pool_obj)
|
123
|
+
|
124
|
+
post(:api_endpoint => api_endpoint, :payload => payload)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Checks if the specified edge already has the DHCP IP pool by checking if the ip_range has already been specified
|
128
|
+
#
|
129
|
+
# @param edge_id [String] Edge ID to check if the IP pool already exists
|
130
|
+
# @param ip_range [String] IP range of the DHCP IP pool
|
131
|
+
# @return [String] the ID of the DHCP pool if it exists; otherwise nil
|
132
|
+
def check_simple_dhcp_pool_exists(edge_id, ip_range)
|
133
|
+
api_endpoint = "/api/4.0/edges/#{edge_id}/dhcp/config"
|
134
|
+
doc = Nokogiri::XML(get(api_endpoint))
|
135
|
+
ip_pools = doc.css('ipPool')
|
136
|
+
ip_pools.map {|ip_pool| return ip_pool.at('poolId').text if ip_pool.at('ipRange').text == ip_range}
|
137
|
+
return nil
|
138
|
+
end
|
139
|
+
|
140
|
+
# Checks if the specified edge already has the port group or virtualwire attached
|
141
|
+
#
|
142
|
+
# @param edge_id [String] Edge ID to check if the interface is attached to
|
143
|
+
# @param connected_to_id [String] ID of the virtualwire or port group of the interface
|
144
|
+
# @return [String] XML string containing the configuration for the interface if it exists; otherwise nil
|
145
|
+
def check_interface_exists(edge_id, connected_to_id)
|
146
|
+
api_endpoint = "/api/4.0/edges/#{edge_id}/interfaces"
|
147
|
+
doc = Nokogiri::XML(get(api_endpoint))
|
148
|
+
interfaces = doc.css('interface')
|
149
|
+
interfaces.map {|interface| return strip_xml_root_pi(interface) if interface.at('connectedToId').text == connected_to_id}
|
150
|
+
return nil
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
# Checks if a DHCP relay agent already exists within the specified XML document
|
155
|
+
#
|
156
|
+
# @param xml [String] XML document to check for the DHCP agent
|
157
|
+
# @param vnic_index [String] vNIC index of the DHCP agent on the edge it is attached to
|
158
|
+
# @param gi_address [String] Gateway IP address for the DHCP agent
|
159
|
+
# @return [Boolean] True if the agent exists; otherwise false
|
160
|
+
def check_dhcp_agent_exists(xml, vnic_index, gi_address)
|
161
|
+
doc = Nokogiri::XML(xml)
|
162
|
+
agents = doc.css('relayAgent')
|
163
|
+
|
164
|
+
agents.each do |agent|
|
165
|
+
agent_vnic_index = agent.css('vnicIndex').text
|
166
|
+
agent_gi_address = agent.css('giAddress').text
|
167
|
+
if vnic_index == agent_vnic_index && gi_address == agent_gi_address
|
168
|
+
return true
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
return false
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
def validate_edge_args(arg_hash, edge_id)
|
177
|
+
errors = []
|
178
|
+
errors << 'Error: Edge ID must be specified' if edge_id.nil?
|
179
|
+
arg_hash.map {|k, v| errors << "Error: Argument: #{arg.to_s} must be specified" if v.nil?}
|
180
|
+
raise errors.to_s if errors.length > 0
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require_relative 'nsxobject'
|
2
|
+
|
3
|
+
module RubyNsxCli
|
4
|
+
|
5
|
+
class NSXVirtualWire < NSXObject
|
6
|
+
|
7
|
+
CONTROL_PLANE_MODES = %w[
|
8
|
+
UNICAST_MODE
|
9
|
+
MULTICAST_MODE
|
10
|
+
HYBRID_MODE
|
11
|
+
]
|
12
|
+
|
13
|
+
|
14
|
+
# Creates an NSX virtualwire with the provided arguments
|
15
|
+
#
|
16
|
+
# @param name [String] Name of the virtualwire
|
17
|
+
# @param scope_id [String] vdnscope on which the virtualwire will be added to
|
18
|
+
# @param description [String] Optional description for the virtualwire
|
19
|
+
# @param tenant_id [String]
|
20
|
+
# @param control_plane_mode [String] one of 'UNICAST_MODE', 'MULTICAST_MODE', 'HYBRID_MODE'. Defaults to 'UNICAST_MODE'
|
21
|
+
# @return [String] virtualwire ID.
|
22
|
+
def create(name:, scope_id:, description:, tenant_id:, control_plane_mode:)
|
23
|
+
|
24
|
+
@logger.info("Attempting to create new virtualwire (name: #{name}, scopeId: #{scope_id})")
|
25
|
+
|
26
|
+
virtual_wire_hash = {
|
27
|
+
:name => name,
|
28
|
+
:description => description,
|
29
|
+
:tenant_id => tenant_id || 'virtual wire tenant',
|
30
|
+
:control_plane_mode => control_plane_mode || 'UNICAST_MODE'
|
31
|
+
}
|
32
|
+
|
33
|
+
validate_create_args(virtual_wire_hash, scope_id)
|
34
|
+
|
35
|
+
@logger.info("Checking if virtualwire already exists (name: #{name}, scopeId: #{scope_id})")
|
36
|
+
if (vwire_id = check_virtual_wire_exists(name, scope_id))
|
37
|
+
@logger.info("Skipping virtualwire creation - virtual wire already exists (name: #{name}, scopeId: #{scope_id})")
|
38
|
+
return vwire_id
|
39
|
+
end
|
40
|
+
|
41
|
+
@logger.info("Adding virtual wire (name: #{name}, scopeId: #{scope_id})")
|
42
|
+
|
43
|
+
virtual_wire_obj = OpenStruct.new(virtual_wire_hash)
|
44
|
+
api_endpoint = "/api/2.0/vdn/scopes/#{scope_id}/virtualwires"
|
45
|
+
payload = render_template('/templates/virtualwire/virtualwire.xml.erb', virtual_wire_obj)
|
46
|
+
|
47
|
+
post(:api_endpoint => api_endpoint, :payload => payload)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Deletes a virtualwire
|
51
|
+
#
|
52
|
+
# @param virtualwire_id [String] ID of the virtualwire
|
53
|
+
# @return [String] virtualwire ID if it exists; otherwise nil
|
54
|
+
def delete(virtualwire_id)
|
55
|
+
raise 'You must specify the virtual wire id to be deleted' if !virtualwire_id
|
56
|
+
api_endpoint = "/api/2.0/vdn/virtualwires/#{virtualwire_id}"
|
57
|
+
super(:api_endpoint => api_endpoint)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Checks if a virtaul wire exists by querying the API for a list of virtual wires for the specified scope
|
61
|
+
#
|
62
|
+
# @param name [String] Name of the virtualwire
|
63
|
+
# @param scope_id [String] vdnscope to check for the virtualwire
|
64
|
+
# @return [String] virtualwire id if it exists; otherwise nil
|
65
|
+
def check_virtual_wire_exists(name, scope_id)
|
66
|
+
api_endpoint = "/api/2.0/vdn/scopes/#{scope_id}/virtualwires?startindex=0&pagesize=1000"
|
67
|
+
xml = get(api_endpoint)
|
68
|
+
doc = Nokogiri::XML(xml)
|
69
|
+
virtualwires = doc.css('virtualWire')
|
70
|
+
virtualwires.map {|vwire| return vwire.at('objectId').text if vwire.at('name').text == name}
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def validate_create_args(virtual_wire_hash, scope_id)
|
76
|
+
errors = []
|
77
|
+
if !NSXVirtualWire::CONTROL_PLANE_MODES.include?(virtual_wire_hash[:control_plane_mode])
|
78
|
+
errors << "Error: Control Plane Mode must be one of [#{NSXVirtualWire::CONTROL_PLANE_MODES.to_s}]"
|
79
|
+
end
|
80
|
+
|
81
|
+
errors << 'Error: Scope ID must be specified' if scope_id.nil?
|
82
|
+
virtual_wire_hash.map {|k, v| errors << "Error: Argument: #{arg.to_s} must be specified" if v.nil?}
|
83
|
+
raise errors.to_s if errors.length > 0
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|