junos-space-api 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Scott Ware
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,41 @@
1
+ ## junos-ruby-space-api
2
+
3
+ This program is used to interact with the Junos Space REST API, using Ruby. The following additional
4
+ gems are required:
5
+
6
+ - `rest-client`
7
+ - `nokogiri`
8
+ - `ipaddress`
9
+
10
+ These can all be installed by issuing `gem install <gem>` on the command line.
11
+
12
+ ### Web Services Available
13
+
14
+ Here are the current web services available so far in this API:
15
+
16
+ *Platform*
17
+
18
+ - Job Management
19
+ - Device Management
20
+
21
+ *Security Director*
22
+
23
+ - Address Management
24
+ - Service Management
25
+ - Device Management
26
+
27
+ Please see [Juniper's documentation][2] for the full release notes on the Security Director API.
28
+
29
+ I will be adding more functionality/web services soon, so please keep checking back!
30
+
31
+ ### Documentation & Usage
32
+
33
+ Check out the [Wiki][1] for documentation on the different Classes and their respective methods.
34
+
35
+ ### Examples
36
+
37
+ Check out the `examples` directory to browse through some samples of what this API can do!
38
+
39
+
40
+ [1]: https://github.com/scottdware/junos-ruby-space-api/wiki
41
+ [2]: http://www.juniper.net/techpubs/en_US/junos-space13.1/information-products/topic-collections/junos-space-security-designer/security-director-api.pdf
@@ -0,0 +1,19 @@
1
+ require 'junos-space-api/platform'
2
+ require 'pp'
3
+
4
+ user = 'me'
5
+ pass = 'somepass'
6
+ server = 'space.company.com'
7
+
8
+ JunosSpace.open('user', 'pass', 'server')
9
+ devices = JunosSpace::Platform::Device.new
10
+
11
+ data = {
12
+ 'host' => '10.10.10.1',
13
+ 'snmp' => 'false',
14
+ 'user' => 'sshuser',
15
+ 'pass' => 'sshpass'
16
+ }
17
+
18
+ # Will return the job ID (i.e. {"status"=>"9990001"}
19
+ pp devices.add_device(data)
@@ -0,0 +1,29 @@
1
+ require 'junos-space-api/sd'
2
+ require 'pp'
3
+
4
+ user = 'me'
5
+ pass = 'somepass'
6
+ server = 'space.company.com'
7
+
8
+ JunosSpace.open('user', 'pass', 'server')
9
+ addrs = JunosSpace::SD::Address.new
10
+
11
+ data = {
12
+ 'name' => 'my-home-network',
13
+ 'type' => 'network',
14
+ 'ip' => '192.168.1.0/24',
15
+ 'desc' => 'My home network',
16
+ 'version' => 'v4'
17
+ }
18
+
19
+ # Will get a list of all of the address objects.
20
+ pp addrs.addresses
21
+
22
+ # Will add a new address object to Junos Space.
23
+ pp addrs.add_address(data)
24
+
25
+ # Will return information about the address object.
26
+ pp addrs.address_info('my-home-network')
27
+
28
+ # Will delete the address object.
29
+ pp addrs.delete_address('my-home-network')
data/examples/jobs.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'junos-space-api/platform'
2
+ require 'pp'
3
+
4
+ user = 'me'
5
+ pass = 'somepass'
6
+ server = 'space.company.com'
7
+
8
+ JunosSpace.open('user', 'pass', 'server')
9
+ jobs = JunosSpace::Platform::Job.new
10
+
11
+ # Will return all jobs with a status of SUCCESS
12
+ pp jobs.jobs('success')
13
+
14
+ # Will return all jobs with a status of FAILURE
15
+ pp jobs.jobs('failure')
16
+
17
+ # Will return information about the job ID 9990001
18
+ pp jobs.job_info('9990001')
@@ -0,0 +1,12 @@
1
+ require 'junos-space-api/sd'
2
+ require 'pp'
3
+
4
+ user = 'me'
5
+ pass = 'somepass'
6
+ server = 'space.company.com'
7
+
8
+ JunosSpace.open('user', 'pass', 'server')
9
+ secdev = JunosSpace::SD::Device.new
10
+
11
+ # Will return the security device information (i.e. zones, interfaces, etc.)
12
+ pp secdev.device_info('corporate-firewall')
@@ -0,0 +1,26 @@
1
+ require 'junos-space-api/sd'
2
+ require 'pp'
3
+
4
+ user = 'me'
5
+ pass = 'somepass'
6
+ server = 'space.company.com'
7
+
8
+ JunosSpace.open('user', 'pass', 'server')
9
+ services = JunosSpace::SD::Service.new
10
+
11
+ data = {
12
+ 'name' => 'my-custom-service',
13
+ 'port' => '60001'
14
+ }
15
+
16
+ # Will get a list of all of the services.
17
+ pp services.services
18
+
19
+ # Will add a new service object to Junos Space.
20
+ pp services.add_service(data)
21
+
22
+ # Will return information about the service object.
23
+ pp services.service_info('my-custom-service')
24
+
25
+ # Will delete the service object.
26
+ pp services.delete_service('my-custom-service')
@@ -0,0 +1,13 @@
1
+ require 'rake'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.license = 'MIT'
5
+ s.name = 'junos-space-api'
6
+ s.version = '0.2.0'
7
+ s.summary = 'Interact with the Junos Space REST API.'
8
+ s.description = 'This gem is used to interact with Juniper Networks Junos Space management platform using the REST API.'
9
+ s.authors = ["Scott Ware"]
10
+ s.email = 'scottdware@gmail.com'
11
+ s.files = FileList['*', 'lib/**/*.rb', 'examples/*.rb']
12
+ s.homepage = 'https://github.com/scottdware/junos-ruby-space-api'
13
+ end
@@ -0,0 +1,2 @@
1
+ require 'junos-space-api/platform/job'
2
+ require 'junos-space-api/platform/device'
@@ -0,0 +1,106 @@
1
+ require 'rest-client'
2
+ require 'nokogiri'
3
+ require 'ipaddress'
4
+ require 'junos-space-api/space'
5
+
6
+ class JunosSpace::Platform::Device
7
+ @@devices_uri = '/api/space/device-management/devices'
8
+ @@discover_uri = '/api/space/device-management/discover-devices'
9
+ @@device_headers = {
10
+ :content_type => 'application/vnd.net.juniper.space.device-management.discover-devices+xml;version=2;charset=UTF-8'
11
+ }
12
+ @@queue_headers = {
13
+ :content_type => 'application/hornetq.jms.queue+xml'
14
+ }
15
+ @@ucase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
16
+ @@dcase = 'abcdefghijklmnopqrstuvwxyz'
17
+
18
+ # devices
19
+ #
20
+ # Returns a Hash of all of the devices in the Junos Space database. The
21
+ # device name is the key, and value is an array of the following:
22
+ # device id, family, Junos version, platform, serial number,
23
+ # connection status, IP address, and managed status.
24
+ #
25
+ def devices
26
+ result = {}
27
+
28
+ begin
29
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@devices_uri}")
30
+ doc = Nokogiri::XML::Document.parse(res)
31
+
32
+ doc.xpath('//device').each do |device|
33
+ stats = []
34
+ stats << device.xpath('@key').text
35
+ stats << device.xpath('deviceFamily').text
36
+ stats << device.xpath('OSVersion').text
37
+ stats << device.xpath('platform').text
38
+ stats << device.xpath('serialNumber').text
39
+ stats << device.xpath('connectionStatus').text
40
+ stats << device.xpath('ipAddr').text
41
+ stats << device.xpath('managedStatus').text
42
+
43
+ result[device.xpath('name').text] = stats
44
+ end
45
+
46
+ return result
47
+ rescue RestClient::Unauthorized
48
+ result['status'] = '401 Error - Auth failure (bad username/password).'
49
+
50
+ return result
51
+ end
52
+ end
53
+
54
+ # add_device(data)
55
+ #
56
+ # Add a new device to the Junos Space database, with the given information
57
+ # in 'data'. 'data' is a Hash table with the following structure:
58
+ #
59
+ # `host => IP address or hostname of device`,
60
+ # `snmp => Use SNMP during discovery: 'community string' or 'false'`,
61
+ # `user => SSH username for device`,
62
+ # `pass => SSH password for device`
63
+ #
64
+ # Returns a Hash with 'status' as the key, and the job ID as the value.
65
+ #
66
+ def add_device(data)
67
+ result = {}
68
+
69
+ begin
70
+ rand = Random.rand(999999)
71
+ server = JunosSpace.base_uri.split('@')[1]
72
+ queue_xml = "<queue name='d#{rand}'><durable>false</durable></queue>"
73
+ RestClient.post("#{JunosSpace.base_uri}/api/hornet-q/queues", queue_xml, @@queue_headers)
74
+ queue_url = "https://#{server}/api/hornet-q/queues/jms.queue.d#{rand}"
75
+
76
+ xml = "<discover-devices>"
77
+
78
+ if IPAddress.valid?(data['host'])
79
+ xml += "<ipAddressDiscoveryTarget><ipAddress>#{data['host']}</ipAddress></ipAddressDiscoveryTarget>"
80
+ else
81
+ xml += "<hostNameDiscoveryTarget><hostName>#{data['host']}</hostName></hostNameDiscoveryTarget>"
82
+ end
83
+
84
+ if data['snmp'] != 'false'
85
+ xml += "<useSnmp>true</useSnmp><snmpV1Setting><communityName>#{data['snmp']}</communityName></snmpV1Setting>"
86
+ else
87
+ xml += "<manageDiscoveredSystemsFlag>true</manageDiscoveredSystemsFlag><sshCredential>" +
88
+ "<userName>#{data['user']}</userName><password>#{data['pass']}</password></sshCredential>" +
89
+ "</discover-devices>"
90
+ end
91
+
92
+ res = RestClient.post("#{JunosSpace.base_uri}#{@@discover_uri}?queue-url=#{queue_url}", xml, @@device_headers)
93
+ doc = Nokogiri::XML::Document.parse(res)
94
+
95
+ if res.code == 202
96
+ result['status'] = doc.xpath('//task/id').text
97
+ end
98
+
99
+ return result
100
+ rescue RestClient::Unauthorized
101
+ result['status'] = '401 Error - Auth failure (bad username/password).'
102
+
103
+ return result
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,87 @@
1
+ require 'rest-client'
2
+ require 'nokogiri'
3
+ require 'junos-space-api/space'
4
+
5
+ class JunosSpace::Platform::Job
6
+ @@job_uri = '/api/space/job-management/jobs'
7
+ @@ucase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
8
+ @@dcase = 'abcdefghijklmnopqrstuvwxyz'
9
+
10
+ # jobs(status)
11
+ #
12
+ # Returns a Hash of all of the jobs in Space with the status
13
+ # 'status'. Where 'status' can be one of: 'success', 'failure',
14
+ # 'inprogress', or 'cancelled'. If no status is given, then all of the jobs are
15
+ # returned. The name of the job is the key, and the ID is the value.
16
+ #
17
+ def jobs(status)
18
+ result = {}
19
+
20
+ begin
21
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@job_uri}")
22
+ doc = Nokogiri::XML::Document.parse(res)
23
+
24
+ if status
25
+ doc.xpath("//job[contains(translate(status, '#{@@ucase}', '#{@@dcase}'), translate('#{status}', '#{@@ucase}', '#{@@dcase}'))]").each do |job|
26
+ name = job.xpath('name').text
27
+ id = job.xpath('@key').text
28
+
29
+ result[name] = id
30
+ end
31
+
32
+ if result.size == 0
33
+ result['status'] = "No jobs found with status: #{status.downcase}."
34
+ end
35
+ else
36
+ doc.xpath("//job").each do |job|
37
+ name = job.xpath('name').text
38
+ id = job.xpath('@key').text
39
+
40
+ result[name] = id
41
+ end
42
+ end
43
+
44
+ return result
45
+ rescue RestClient::Unauthorized
46
+ result['status'] = '401 Error - Auth failure (bad username/password).'
47
+
48
+ return result
49
+ end
50
+ end
51
+
52
+ # job_info(job)
53
+ #
54
+ # Returns information about the job 'job'. This information is returned in a Hash
55
+ # with the job ID, name, percentage complete, status, job type, summary, user
56
+ # who issued the job, and the time the job was started.
57
+ #
58
+ def job_info(job)
59
+ result = {}
60
+
61
+ begin
62
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@job_uri}/#{job}")
63
+ doc = Nokogiri::XML::Document.parse(res)
64
+
65
+ doc.xpath('//job').each do |job|
66
+ result["id"] = job.xpath('id').text
67
+ result["name"] = job.xpath('name').text
68
+ result["percent"] = job.xpath('percent').text
69
+ result["status"] = job.xpath('status').text
70
+ result["job-type"] = job.xpath('jobType').text
71
+ result["summary"] = job.xpath('summary').text
72
+ result["time"] = job.xpath('scheduledStartTime').text
73
+ result["user"] = job.xpath('user').text
74
+ end
75
+
76
+ return result
77
+ rescue RestClient::Unauthorized
78
+ result['status'] = '401 Error - Auth failure (bad username/password).'
79
+
80
+ return result
81
+ rescue RestClient::ResourceNotFound
82
+ result['status'] = "404 Error - No job found with ID: #{job}."
83
+
84
+ return result
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ require 'junos-space-api/sd/address'
2
+ require 'junos-space-api/sd/service'
3
+ require 'junos-space-api/sd/device'
@@ -0,0 +1,176 @@
1
+ require 'rest-client'
2
+ require 'nokogiri'
3
+ require 'junos-space-api/space'
4
+
5
+ class JunosSpace::SD::Address
6
+ @@address_uri = '/api/juniper/sd/address-management/addresses'
7
+ @@address_headers = {
8
+ :content_type => "application/vnd.juniper.sd.address-management.address+xml;version=1;charset=UTF-8"
9
+ }
10
+ @@ucase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
11
+ @@dcase = 'abcdefghijklmnopqrstuvwxyz'
12
+
13
+ # addresses
14
+ #
15
+ # Returns a Hash of all of the address objects in Space. The name
16
+ # of the object is the key, and the ID is the value.
17
+ #
18
+ def addresses
19
+ result = {}
20
+
21
+ begin
22
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@address_uri}")
23
+ doc = Nokogiri::XML::Document.parse(res)
24
+
25
+ doc.xpath('//address').each do |address|
26
+ name = address.xpath('name').text
27
+ id = address.xpath('id').text
28
+
29
+ result[name] = id
30
+ end
31
+
32
+ return result
33
+ rescue RestClient::Unauthorized
34
+ result['status'] = '401 Error - Auth failure (bad username/password).'
35
+
36
+ return result
37
+ end
38
+ end
39
+
40
+ # address_info(name)
41
+ #
42
+ # Searches for address object 'name' and returns a Hash with the address
43
+ # object(s) name as the key, and the IP address as the value.
44
+ # If the address object(s) are a group, then the value within
45
+ # the Hash is an array of the address object names within the group(s).
46
+ #
47
+ def address_info(name)
48
+ result = {}
49
+
50
+ begin
51
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@address_uri}", :params => {:filter => "(global eq '#{name}')"})
52
+ doc = Nokogiri::XML::Document.parse(res)
53
+ count = doc.xpath('//addresses/@total').text
54
+
55
+ if count == "0"
56
+ result['status'] = 'No address object(s) found.'
57
+ else
58
+ doc.xpath("//address[contains(translate(name, '#{@@ucase}', '#{@@dcase}'), translate('#{name}', '#{@@ucase}', '#{@@dcase}'))]").each do |address|
59
+ name = address.xpath('name').text
60
+ type = address.xpath('address-type').text
61
+ id = address.xpath('id').text
62
+
63
+ if type != 'GROUP'
64
+ address.xpath('//address').each do |info|
65
+ ip = info.xpath('ip-address').text
66
+ result[name] = ip
67
+ end
68
+ elsif type == 'GROUP'
69
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@address_uri}/#{id}")
70
+ doc = Nokogiri::XML::Document.parse(res)
71
+
72
+ group_members = []
73
+ doc.xpath('//member').each do |member|
74
+ member_name = member.xpath('name').text
75
+ member_ip = member.xpath('ip-address').text
76
+ group_members << member_name
77
+ end
78
+ result[name] = group_members
79
+ end
80
+ end
81
+ end
82
+
83
+ return result
84
+ rescue RestClient::Unauthorized
85
+ result['status'] = '401 Error - Auth failure (bad username/password).'
86
+
87
+ return result
88
+ end
89
+ end
90
+
91
+ # add_address(data)
92
+ #
93
+ # This method will add a new address object to Space give the information
94
+ # in 'data'. This information is a Hash with the following structure:
95
+ #
96
+ # `name => Name of the object you want to create`,
97
+ # `type => Either 'address' or 'network'`,
98
+ # `ip => IP address or subnet/mask`,
99
+ # `desc => Description (optional)`,
100
+ # `version => Either 'v4' or 'v6'`
101
+ #
102
+ def add_address(data)
103
+ result = {}
104
+ type = data['type'] == 'address' ? 'IPADDRESS' : 'NETWORK'
105
+ version = data['version'] == 'v4' ? 'IPV4' : 'IPV6'
106
+ if data['desc']
107
+ desc = data['desc']
108
+ else
109
+ desc = ''
110
+ end
111
+
112
+ xml = "<address><name>#{data['name']}</name><address-type>#{type}</address-type>" +
113
+ "<host-name/><edit-version/><members/><address-version>#{version}</address-version>" +
114
+ "<definition-type>CUSTOM</definition-type><ip-address>#{data['ip']}</ip-address>" +
115
+ "<description>#{desc}</description></address>"
116
+
117
+ begin
118
+ res = RestClient.post("#{JunosSpace.base_uri}#{@@address_uri}", xml, @@address_headers)
119
+
120
+ if res.code == 200
121
+ result['status'] = '200 OK - Success'
122
+ end
123
+
124
+ return result
125
+ rescue RestClient::Unauthorized
126
+ result['status'] = '401 Error - Auth failure (bad username/password).'
127
+
128
+ return result
129
+ rescue RestClient::InternalServerError
130
+ result['status'] = '500 Error - Check and see if the device already exists.'
131
+
132
+ return result
133
+ end
134
+ end
135
+
136
+ # delete_address(name)
137
+ #
138
+ # Deletes the object matching the name 'name'. If more than one address object
139
+ # is found during the search, then send a warning to refine the search (i.e.
140
+ # use the exact name if possible).
141
+ #
142
+ def delete_address(name)
143
+ result = {}
144
+
145
+ begin
146
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@address_uri}", :params => {:filter => "(global eq '#{name}')"})
147
+ doc = Nokogiri::XML::Document.parse(res)
148
+ headers = {
149
+ :content_type => 'application/vnd.juniper.sd.address-management.delete-address-response+xml;version=1;q=0.01'
150
+ }
151
+ num_results = doc.xpath('//addresses/@total').text
152
+
153
+ if num_results == "0"
154
+ result['status'] = 'Address object does not exist.'
155
+ elsif num_results.to_i > 1
156
+ result['status'] = 'More than one object was found. Please refine your search (use the exact name if possible).'
157
+ else
158
+ doc.xpath("//address[contains(translate(name, '#{@@ucase}', '#{@@dcase}'), translate('#{name}', '#{@@ucase}', '#{@@dcase}'))]").each do |address|
159
+ id = address.xpath('id').text
160
+
161
+ res = RestClient.delete("#{JunosSpace.base_uri}#{@@address_uri}/#{id}", headers)
162
+
163
+ if res == ''
164
+ result['status'] = '200 OK - Success.'
165
+ end
166
+ end
167
+ end
168
+
169
+ return result
170
+ rescue RestClient::Unauthorized
171
+ result['status'] = '401 Error - Auth failure (bad username/password).'
172
+
173
+ return result
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,114 @@
1
+ require 'rest-client'
2
+ require 'nokogiri'
3
+ require 'junos-space-api/space'
4
+
5
+ class JunosSpace::SD::Device
6
+ @@device_uri = '/api/juniper/sd/device-management/devices'
7
+
8
+ # devices
9
+ #
10
+ # Returns a Hash of all of the device objects in Space. The name
11
+ # of the device is the key, and the ID is the value.
12
+ #
13
+ def devices
14
+ result = {}
15
+
16
+ begin
17
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@device_uri}")
18
+ doc = Nokogiri::XML::Document.parse(res)
19
+
20
+ doc.xpath('//device').each do |device|
21
+ name = device.xpath('name').text
22
+ id = device.xpath('id').text
23
+
24
+ result[name] = id
25
+ end
26
+
27
+ return result
28
+ rescue RestClient::Unauthorized
29
+ result['status'] = '401 Error - Auth failure (bad username/password).'
30
+
31
+ return result
32
+ end
33
+ end
34
+
35
+ # device_info(name)
36
+ #
37
+ # Returns a Hash of resultrmation about the given device 'name'. For zones,
38
+ # it returns Hash where the zone name is the key, and an array of interfaces
39
+ # that are in said zone as the value.
40
+ #
41
+ # For interfaces, it returns a Hash where the interface name is the key, and
42
+ # the IP address of that interface is the value.
43
+ #
44
+ def device_info(name)
45
+ result = {}
46
+ devices = self.devices
47
+
48
+ begin
49
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@device_uri}/#{devices[name]}")
50
+ doc = Nokogiri::XML::Document.parse(res)
51
+
52
+ if !devices[name]
53
+ result['status'] = 'No device(s) found.'
54
+ else
55
+ doc.xpath('//device').each do |device|
56
+ result["management-status"] = device.xpath('management-status').text,
57
+ result["name"] = device.xpath('name').text,
58
+ result["platform"] = device.xpath('platform').text,
59
+ result["ip"] = device.xpath('device-ip').text,
60
+ result["config-status"] = device.xpath('configuration-status').text,
61
+ result["connection-status"] = device.xpath('connection-status').text,
62
+ result["family"] = device.xpath('device-family').text,
63
+ result["version"] = device.xpath('software-release').text,
64
+ result["id"] = device.xpath('id').text
65
+
66
+ zone_uri = device.xpath('Zone/@href').text
67
+ int_uri = device.xpath('Interfaces/@href').text
68
+
69
+ zone_res = RestClient.get("#{JunosSpace.base_uri}#{zone_uri}")
70
+ zone_doc = Nokogiri::XML::Document.parse(zone_res)
71
+ int_res = RestClient.get("#{JunosSpace.base_uri}#{int_uri}")
72
+ int_doc = Nokogiri::XML::Document.parse(int_res)
73
+
74
+ zones = []
75
+ zone_doc.xpath('//zone').each do |zone|
76
+ zone_ints = []
77
+ zone_result = {}
78
+ name = zone.xpath('name').text
79
+
80
+ zone.xpath('./interfaces').each do |int|
81
+ int.xpath('./interface').each do |interface|
82
+ zone_ints << interface.text
83
+ end
84
+ end
85
+
86
+ zone_result[name] = zone_ints
87
+ zones << zone_result
88
+ end
89
+
90
+ result["zones"] = zones
91
+
92
+ interfaces = []
93
+ int_doc.xpath('//interface').each do |int|
94
+ int_result = {}
95
+ name = int.xpath('name').text
96
+ ip = int.xpath('ip-addr').text
97
+ mask = int.xpath('ip-netmask').text
98
+ int_result[name] = "#{ip}/#{mask}"
99
+
100
+ interfaces << int_result
101
+ end
102
+
103
+ result["interfaces"] = interfaces
104
+ end
105
+ end
106
+
107
+ return result
108
+ rescue RestClient::Unauthorized
109
+ result['status'] = '401 Error - Auth failure (bad username/password).'
110
+
111
+ return result
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,175 @@
1
+ require 'rest-client'
2
+ require 'nokogiri'
3
+ require 'junos-space-api/space'
4
+
5
+ class JunosSpace::SD::Service
6
+ @@service_uri = '/api/juniper/sd/service-management/services'
7
+ @@service_headers = {
8
+ :content_type => "application/vnd.juniper.sd.service-management.service+xml;version=1;charset=UTF-8"
9
+ }
10
+ @@ucase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
11
+ @@dcase = 'abcdefghijklmnopqrstuvwxyz'
12
+
13
+ # services
14
+ #
15
+ # Returns a Hash of all of the individual service objects in Space.
16
+ # The name of the service is the key, and the ID is the value.
17
+ #
18
+ def services
19
+ result = {}
20
+
21
+ begin
22
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@service_uri}")
23
+ doc = Nokogiri::XML::Document.parse(res)
24
+
25
+ doc.xpath('//service').each do |service|
26
+ name = service.xpath('name').text
27
+ id = service.xpath('id').text
28
+
29
+ result[name] = id
30
+ end
31
+
32
+ return result
33
+ rescue RestClient::Unauthorized
34
+ result['status'] = '401 Error - Auth failure (bad username/password).'
35
+
36
+ return result
37
+ end
38
+ end
39
+
40
+ # service_info(name)
41
+ #
42
+ # Searches for the service 'name' and returns a Hash with the service
43
+ # object(s) name as the key, and the ID as the value.
44
+ # If the service object(s) are a group, then the value within
45
+ # the Hash is an array of the service object names within the group(s).
46
+ #
47
+ def service_info(name)
48
+ result = {}
49
+
50
+ begin
51
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@service_uri}", :params => {:filter => "(global eq '#{name}')"})
52
+ doc = Nokogiri::XML::Document.parse(res)
53
+ count = doc.xpath('//services/@total').text
54
+
55
+ if count == "0"
56
+ result['status'] = 'No service object(s) found.'
57
+ else
58
+ doc.xpath("//service[contains(translate(name, '#{@@ucase}', '#{@@dcase}'), translate('#{name}', '#{@@ucase}', '#{@@dcase}'))]").each do |service|
59
+ group = service.xpath('is-group').text
60
+ name = service.xpath('name').text
61
+ id = service.xpath('id').text
62
+
63
+ if group == 'false'
64
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@service_uri}/#{id}")
65
+ doc = Nokogiri::XML::Document.parse(res)
66
+
67
+ doc.xpath('//protocol').each do |info|
68
+ dst_port = info.xpath('dst-port').text
69
+ result[name] = dst_port
70
+ end
71
+ elsif group == 'true'
72
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@service_uri}/#{id}")
73
+ doc = Nokogiri::XML::Document.parse(res)
74
+
75
+ group_members = []
76
+ doc.xpath('//member').each do |member|
77
+ member_name = member.xpath('name').text
78
+ group_members << member_name
79
+ end
80
+ result[name] = group_members
81
+ end
82
+ end
83
+ end
84
+
85
+ return result
86
+ rescue RestClient::Unauthorized
87
+ result['status'] = '401 Error - Auth failure (bad username/password).'
88
+
89
+ return result
90
+ end
91
+ end
92
+
93
+ # add_service(data)
94
+ #
95
+ # This method will add a new service object to Space give the information
96
+ # in 'data'. This information is a Hash table, with the following structure:
97
+ #
98
+ # `name => `Name of the object you want to create`
99
+ # `port => Port number`
100
+ # `desc => Description (optional)`
101
+ #
102
+ def add_service(data)
103
+ result = {}
104
+
105
+ if data['desc']
106
+ desc = data['desc']
107
+ else
108
+ desc = ''
109
+ end
110
+
111
+ xml = "<service><name>#{data['name']}</name><is-group>false</is-group><edit-version/>" +
112
+ "<id/><created-by-user-name/><members/><protocols><protocol><description/>" +
113
+ "<sunrpc-protocol-type>6</sunrpc-protocol-type><msrpc-protocol-type>6</msrpc-protocol-type>" +
114
+ "<protocol-number>6</protocol-number><name>#{data['name']}</name><dst-port>#{data['port']}</dst-port>" +
115
+ "<disable-timeout>false</disable-timeout><protocol-type>0</protocol-type><icmp-code>0</icmp-code>" +
116
+ "<icmp-type>0</icmp-type><rpc-program-number>0</rpc-program-number>" +
117
+ "</protocol></protocols><description>#{desc}</description></service>"
118
+
119
+ begin
120
+ res = RestClient.post("#{JunosSpace.base_uri}#{@@service_uri}", xml, @@service_headers)
121
+
122
+ if res.code == 200
123
+ result['status'] = '200 OK - Success'
124
+ end
125
+
126
+ return result
127
+ rescue RestClient::Unauthorized
128
+ result['status'] = '401 Error - Auth failure (bad username/password).'
129
+
130
+ return result
131
+ rescue RestClient::InternalServerError
132
+ result['status'] = '500 Error - Check and see if the device already exists.'
133
+
134
+ return result
135
+ end
136
+ end
137
+
138
+ # delete_service(name)
139
+ #
140
+ # Deletes the object matching the name 'name'. If more than one service object
141
+ # is found during the search, then send a warning to refine the search (i.e.
142
+ # use the exact name if possible).
143
+ #
144
+ def delete_service(name)
145
+ result = {}
146
+
147
+ begin
148
+ res = RestClient.get("#{JunosSpace.base_uri}#{@@service_uri}", :params => {:filter => "(global eq '#{name}')"})
149
+ doc = Nokogiri::XML::Document.parse(res)
150
+ num_results = doc.xpath('//services/@total').text
151
+
152
+ if num_results == "0"
153
+ result['status'] = 'Service object does not exist.'
154
+ elsif num_results.to_i > 1
155
+ result['status'] = 'More than one object was found. Please refine your search (use the exact name if possible).'
156
+ else
157
+ doc.xpath("//service[contains(translate(name, '#{@@ucase}', '#{@@dcase}'), translate('#{name}', '#{@@ucase}', '#{@@dcase}'))]").each do |service|
158
+ id = service.xpath('id').text
159
+
160
+ res = RestClient.delete("#{JunosSpace.base_uri}#{@@service_uri}/#{id}", @@service_headers)
161
+
162
+ if res == ''
163
+ result['status'] = '200 OK - Success.'
164
+ end
165
+ end
166
+ end
167
+
168
+ return result
169
+ rescue RestClient::Unauthorized
170
+ result['status'] = '401 Error - Auth failure (bad username/password).'
171
+
172
+ return result
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,20 @@
1
+ module JunosSpace
2
+ # JunosSpace.open
3
+ #
4
+ # Initiates the connection to the Junos Space server.
5
+ #
6
+ def self.open(user, pass, server)
7
+ @conn_str = "https://#{user}:#{pass}@#{server}"
8
+ end
9
+
10
+ # JunosSpace.base_uri
11
+ #
12
+ # Returns the base URI for the API to use in our classes
13
+ #
14
+ def self.base_uri
15
+ @conn_str
16
+ end
17
+ end
18
+
19
+ module JunosSpace::Platform; end
20
+ module JunosSpace::SD; end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: junos-space-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Scott Ware
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-09 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: This gem is used to interact with Juniper Networks Junos Space management
15
+ platform using the REST API.
16
+ email: scottdware@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - junos-space-api.gemspec
22
+ - LICENSE
23
+ - README.md
24
+ - lib/junos-space-api/platform/device.rb
25
+ - lib/junos-space-api/platform/job.rb
26
+ - lib/junos-space-api/platform.rb
27
+ - lib/junos-space-api/sd/address.rb
28
+ - lib/junos-space-api/sd/device.rb
29
+ - lib/junos-space-api/sd/service.rb
30
+ - lib/junos-space-api/sd.rb
31
+ - lib/junos-space-api/space.rb
32
+ - examples/addresses.rb
33
+ - examples/add_device.rb
34
+ - examples/jobs.rb
35
+ - examples/sec_device.rb
36
+ - examples/services.rb
37
+ homepage: https://github.com/scottdware/junos-ruby-space-api
38
+ licenses:
39
+ - MIT
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 1.8.24
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: Interact with the Junos Space REST API.
62
+ test_files: []