acos_client 0.1.0.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +3 -0
  3. data/Gemfile +4 -0
  4. data/README.md +39 -0
  5. data/Rakefile +1 -0
  6. data/acos_client.gemspec +29 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +7 -0
  9. data/lib/acos_client/application.rb +91 -0
  10. data/lib/acos_client/client.rb +58 -0
  11. data/lib/acos_client/errors.rb +56 -0
  12. data/lib/acos_client/tools.rb +12 -0
  13. data/lib/acos_client/v21/action.rb +36 -0
  14. data/lib/acos_client/v21/axapi_http.rb +142 -0
  15. data/lib/acos_client/v21/base.rb +63 -0
  16. data/lib/acos_client/v21/config_file.rb +26 -0
  17. data/lib/acos_client/v21/device_info.rb +22 -0
  18. data/lib/acos_client/v21/ha.rb +29 -0
  19. data/lib/acos_client/v21/log.rb +117 -0
  20. data/lib/acos_client/v21/monkey_patch_ssl.rb +22 -0
  21. data/lib/acos_client/v21/nat.rb +53 -0
  22. data/lib/acos_client/v21/network.rb +167 -0
  23. data/lib/acos_client/v21/partition.rb +53 -0
  24. data/lib/acos_client/v21/responses.rb +170 -0
  25. data/lib/acos_client/v21/session.rb +61 -0
  26. data/lib/acos_client/v21/slb/aflex.rb +89 -0
  27. data/lib/acos_client/v21/slb/class_list.rb +67 -0
  28. data/lib/acos_client/v21/slb/hm.rb +122 -0
  29. data/lib/acos_client/v21/slb/init.rb +53 -0
  30. data/lib/acos_client/v21/slb/member.rb +36 -0
  31. data/lib/acos_client/v21/slb/port.rb +52 -0
  32. data/lib/acos_client/v21/slb/server.rb +65 -0
  33. data/lib/acos_client/v21/slb/service_group.rb +75 -0
  34. data/lib/acos_client/v21/slb/template/init.rb +28 -0
  35. data/lib/acos_client/v21/slb/template/persistence.rb +79 -0
  36. data/lib/acos_client/v21/slb/template/template_ssl.rb +56 -0
  37. data/lib/acos_client/v21/slb/virtual_port.rb +87 -0
  38. data/lib/acos_client/v21/slb/virtual_server.rb +62 -0
  39. data/lib/acos_client/v21/slb/virtual_service.rb +61 -0
  40. data/lib/acos_client/v21/system.rb +84 -0
  41. data/lib/acos_client/version.rb +3 -0
  42. data/lib/acos_client.rb +13 -0
  43. metadata +154 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ffc04a9a5a06a8c4cf4e82930a95cc24f290921a
4
+ data.tar.gz: 937daca450fc18eb65b1729a8ca927c682fac1cd
5
+ SHA512:
6
+ metadata.gz: ca6365ea55cda8312c062f851e70b31fa5ea9e978d1ea24a903a0b8bc30f9d6b6ec2e5c5ac368577db5a1f04a5de56aab70517c88240caacb9925a44f0be1792
7
+ data.tar.gz: 031b2e132b27b56bdf9a533f831431d29f0e1df1f113d2766aee1afefc6d5f6048ffeb3f60f1ca85b77c19a88112e2c89a336b14bf7e4d41487760682ba9367c
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in acos_client.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # AcosClient
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/acos_client`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'acos_client'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install acos_client
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ 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` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it ( https://github.com/[my-github-username]/acos_client/fork )
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'acos_client/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "acos_client"
8
+ spec.version = AcosClient::VERSION
9
+ spec.authors = ["Amine Benseddik"]
10
+ spec.email = ["amine.benseddik@gmail.com"]
11
+
12
+ spec.summary = %q{A10network AxAPI client}
13
+ spec.description = %q{Port Python A10network AxAPI client to Ruby}
14
+ spec.homepage = "https://gitlab.spiir.me/amine/acos_client"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.required_ruby_version = '>= 2.0'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.9"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency 'httparty'
26
+ spec.add_development_dependency 'addressable'
27
+ spec.add_development_dependency 'activesupport'
28
+
29
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "acos_client"
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
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,91 @@
1
+ require 'optparse'
2
+ require 'pp'
3
+ require 'acos_client/client'
4
+ require 'acos_client/v21/responses'
5
+
6
+ module AcosClient
7
+ module Application
8
+
9
+ def self.run(argv)
10
+
11
+ c = AcosClient::Client.new('admin', 'a10', '192.168.1.10')
12
+
13
+ puts c.session.id
14
+ #c.system.partition.active('shared')
15
+
16
+ # System
17
+ #puts c.system.tech_download
18
+ puts c.system.information
19
+ puts c.system.device_info.get
20
+ puts c.system.device_info.cpu_current_usage
21
+ puts c.system.device_info.cpu_historical_usage
22
+ #puts c.system.action.reboot # Not Implemented
23
+
24
+ # Partition
25
+ if c.system.partition.exists('test')
26
+ puts c.system.partition.exists('test')
27
+ c.system.partition.active('test')
28
+ else
29
+ #c.system.partition.create("test")
30
+ end
31
+ puts c.current_partition
32
+
33
+ # Log
34
+
35
+ # Network
36
+ puts c.network.interface.all
37
+ #puts c.network.interface.get(3) # broken
38
+ puts c.network.acl.ext.all
39
+ puts c.nat.pool.all
40
+
41
+ # HA Sync
42
+ puts c.ha.sync('127.0.0.1', 'admin', 'a10')
43
+
44
+ #####################
45
+ # SLB #
46
+ #####################
47
+
48
+ # Virtual Service
49
+ #
50
+ puts c.slb.virtual_service.all
51
+ begin
52
+ puts c.slb.virtual_service.get('test')
53
+ rescue => e
54
+ puts "#{e.message}"
55
+ end
56
+
57
+ # Virtual Server
58
+ #
59
+ puts c.slb.virtual_server.all
60
+ puts c.slb.virtual_server.get('test') rescue puts 'Not Found'
61
+
62
+ # Server
63
+ #
64
+ puts c.slb.server.all
65
+ puts c.slb.server.get('test') rescue puts 'Server Not Found'
66
+
67
+ # Class List
68
+ #
69
+ puts c.slb.class_list.all
70
+ puts c.slb.class_list.delete('ClassListTest02')
71
+
72
+ # Aflex
73
+ #
74
+ puts c.slb.aflex.all
75
+ puts c.slb.aflex.get('host_switching')
76
+ puts c.slb.aflex.get('redirect1')
77
+
78
+ # Template
79
+ #
80
+ puts c.slb.template.server_ssl.all
81
+ puts c.slb.template.cookie_persistence.all
82
+ puts c.slb.template.src_ip_persistence.all
83
+
84
+
85
+ ####################
86
+
87
+ # Close session
88
+ c.session.close
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,58 @@
1
+ require 'acos_client/v21/axapi_http'
2
+ require 'acos_client/v21/session'
3
+ require 'acos_client/v21/ha'
4
+ require 'acos_client/v21/system'
5
+ require 'acos_client/v21/slb/init'
6
+ require 'acos_client/v21/network'
7
+ require 'acos_client/v21/nat'
8
+
9
+
10
+ module AcosClient
11
+
12
+ class Client
13
+
14
+ # VERSION_IMPORTS = {
15
+ # :21 = {
16
+ # :HA => :v21_HA,
17
+ # :Nat => :v21_Nat,
18
+ # :Network => :v21_Network,
19
+ # :Session => :v21_Session,
20
+ # :SLB => :v21_SLB,
21
+ # :System => :v21_System,
22
+ # }
23
+ # }
24
+
25
+ attr_accessor :http, :session, :system, :current_partition
26
+
27
+ def initialize(username, password, host, protocol: "https", port: nil)
28
+
29
+ @http = AcosClient::V21::HttpClient.new(host, protocol: protocol, port: port)
30
+ @session = AcosClient::V21::Session.new(self, username, password)
31
+ @current_partition = 'shared'
32
+
33
+ end
34
+
35
+ def ha
36
+ AcosClient::V21::HA.new(self)
37
+ end
38
+
39
+ def system
40
+ AcosClient::V21::System.new(self)
41
+ end
42
+
43
+ def slb
44
+ AcosClient::V21::SLB.new(self)
45
+ end
46
+
47
+ def network
48
+ AcosClient::V21::Network.new(self)
49
+ end
50
+
51
+ def nat
52
+ AcosClient::V21::Nat.new(self)
53
+ end
54
+
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,56 @@
1
+ module AcosClient
2
+ module Error
3
+
4
+ class Error < StandardError;
5
+ end
6
+
7
+ class ACOSUnsupportedVersion < Error;
8
+ end
9
+
10
+ class ACOSUnknownError < Error;
11
+ end
12
+
13
+ class AddressSpecifiedIsInUse < Error;
14
+ end
15
+
16
+ class AuthenticationFailure < Error;
17
+ end
18
+
19
+ class InvalidSessionID < Error;
20
+ end
21
+
22
+ class Exists < Error;
23
+ end
24
+
25
+ class NotFound < Error;
26
+ end
27
+
28
+ class NoSuchServiceGroup < Error;
29
+ end
30
+
31
+ class NotImplemented < Error;
32
+ end
33
+
34
+ class InUse < Error;
35
+ end
36
+
37
+ class InvalidPartitionParameter < Error;
38
+ end
39
+
40
+ class MemoryFault < Error;
41
+ end
42
+
43
+ class InvalidParameter < Error;
44
+ end
45
+
46
+ class OutOfPartitions < Error;
47
+ end
48
+
49
+ class PartitionIdExists < Error;
50
+ end
51
+
52
+ class HMMissingHttpPassive < Error;
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,12 @@
1
+ require 'addressable/uri'
2
+
3
+
4
+ module AcosClient
5
+ module Tools
6
+
7
+ def self.extract_method(api_url)
8
+ return Addressable::URI.parse(api_url).query_values()['method']
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ require 'acos_client/errors'
2
+ require 'acos_client/v21/base'
3
+
4
+ module AcosClient
5
+ module V21
6
+
7
+ class Action < AcosClient::V21::BaseV21
8
+
9
+ def write_memory
10
+ begin
11
+ self._get('system.action.write_memory')
12
+ rescue AcosClient::Error::InvalidPartitionParameter
13
+ #pass
14
+ end
15
+ end
16
+
17
+ def reboot(**opts)
18
+ raise NotImplementedError, 'Reboot Action is not implemented'
19
+ # return self._post('system.action.reboot', **opts)
20
+ end
21
+
22
+ def reload(write_memory: false, **opts)
23
+ # write_memory param is required but no matter what value is passed
24
+ # it will ALWAYS save pending changes
25
+
26
+ if write_memory
27
+ write_memory = 1
28
+ else
29
+ write_memory = 0
30
+ end
31
+
32
+ self._post('system.action.reload', params: {:write_memory => write_memory}, **opts)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,142 @@
1
+ require 'httparty'
2
+ require 'json'
3
+ require 'pp'
4
+
5
+ require 'acos_client/v21/monkey_patch_ssl'
6
+ require 'acos_client/tools'
7
+ require 'acos_client/v21/responses'
8
+
9
+ module AcosClient
10
+ module V21
11
+
12
+ # Some were fixed in ACOS 2.7.2-P4
13
+ #
14
+ BROKEN_REPLIES = {
15
+ ('<?xml version="1.0" encoding="utf-8" ?>'\
16
+ '<response status="ok">') => ({:response => {:status => 'OK'}}).to_json,
17
+
18
+ ('<?xml version="1.0" encoding="utf-8" ?><response status="fail">'\
19
+ '<error code="999" msg=" Partition does not exist. (internal error: 520749062)" />'\
20
+ '</response>') => ({:response => {:status => 'fail', :err => {:code => 999,
21
+ :msg => ' Partition does not exist.'}}}).to_json,
22
+
23
+ ('<?xml version="1.0" encoding="utf-8" ?><response status="fail">'\
24
+ '<error code="1076" msg="Invalid partition parameter." /></response>') => ({
25
+ :response => {:status => 'fail', :err => {:code => 1076, :msg => 'Invalid partition parameter.'}}}).to_json,
26
+
27
+ ('<?xml version="1.0" encoding="utf-8" ?><response status="fail">'\
28
+ '<error code="999" msg=" No such aFleX. (internal error: '\
29
+ '17039361)" /></response>') => ({:response => {:status => 'fail', :err => {:code => 17039361,
30
+ :msg => ' No such aFleX.'}}}).to_json,
31
+
32
+ ('<?xml version="1.0" encoding="utf-8" ?><response status="fail">'\
33
+ '<error code="999" msg=" This aFleX is in use. (internal error: '\
34
+ '17039364)" /></response>') => ({:response => {:status => 'fail', :err => {:code => 17039364,
35
+ :msg => ' This aFleX is in use.'}}}).to_json
36
+ }
37
+
38
+ class HttpClient
39
+ include HTTParty
40
+
41
+ #default_options[:ssl_version] = :TLSv1
42
+ ssl_version :TLSv1
43
+ default_options.update(verify: false)
44
+
45
+ HEADERS = {
46
+ "Content-type" => "application/json",
47
+ "User-Agent" => "A10MGMT-Client-AGENT-#{VERSION}",
48
+ }
49
+
50
+ attr_accessor :host, :port, :protocol
51
+
52
+ def initialize(host, protocol: 'https', port: nil)
53
+
54
+ @host = host
55
+ @port = port
56
+ @protocol = protocol
57
+
58
+ if port.nil?
59
+ if protocol == 'http'
60
+ @port = 80
61
+ else
62
+ @port = 443
63
+ end
64
+ end
65
+
66
+ @base_uri = @protocol + '://' + @host + ':' + @port.to_s
67
+ self.class.base_uri(@base_uri)
68
+ end
69
+
70
+ def request(method, api_url, params: {}, ** opts)
71
+ #
72
+ # Todo: Catch http/httparty exceptions
73
+ #
74
+
75
+ if !params.empty?
76
+ params_copy = params.merge(opts)
77
+ end
78
+
79
+ options = {
80
+ :body => params_copy.to_json,
81
+ :headers => HEADERS
82
+ }
83
+
84
+ case method
85
+
86
+ when 'GET'
87
+ r = self.class.get(api_url, params)
88
+ response = r.body
89
+
90
+ begin
91
+ r.inspect
92
+
93
+ rescue JSON::ParserError
94
+ # ToDo: should check broken replies
95
+ end
96
+
97
+ when 'POST'
98
+ r = self.class.post(api_url, options)
99
+ response = r.body
100
+
101
+ begin
102
+ r.inspect
103
+
104
+ rescue JSON::ParserError
105
+ # Extract "<?xml version="1.0" encoding="utf-8" ?><response status="ok">"
106
+ xmlhead = r.body[0..60]
107
+
108
+ if BROKEN_REPLIES.key?(xmlhead)
109
+ response = BROKEN_REPLIES[xmlhead]
110
+ elsif BROKEN_REPLIES.key?(r.body.to_s)
111
+ response = BROKEN_REPLIES[r.body.to_s]
112
+ end
113
+
114
+ end
115
+
116
+ else
117
+ raise RuntimeError
118
+ end
119
+
120
+ r = JSON.load(response).deep_symbolize_keys!
121
+ if r.key?(:response) and r[:response].key?(:status)
122
+ if r[:response][:status] == 'fail'
123
+ AcosClient::V21::Responses.raise_axapi_error(r, action: AcosClient::Tools.extract_method(@base_uri + api_url))
124
+ end
125
+ end
126
+
127
+ r
128
+ end
129
+
130
+ def get(api_url, params: {}, ** opts)
131
+ self.request('GET', api_url, params: params)
132
+ end
133
+
134
+ def post(api_url, params: {}, ** opts)
135
+ self.request('POST', api_url, params: params)
136
+ end
137
+
138
+ end
139
+
140
+ end
141
+
142
+ end
@@ -0,0 +1,63 @@
1
+ require 'acos_client/errors'
2
+
3
+ module AcosClient
4
+ module V21
5
+
6
+ class BaseV21
7
+
8
+ attr_accessor :client
9
+
10
+ def initialize(client)
11
+ @client = client
12
+
13
+ end
14
+
15
+ def url(action)
16
+ "/services/rest/v2.1/?format=json&method=#{action}&session_id=#{@client.session.id}"
17
+ end
18
+
19
+ def _request(method, action, params: params, retry_count: 0, **opts)
20
+
21
+ if retry_count > 6
22
+ raise AcosClient::Error::ACOSUnknownError
23
+ end
24
+
25
+ begin
26
+
27
+ return @client.http.request(method, self.url(action), params: params, **opts)
28
+
29
+ rescue AcosClient::Error::MemoryFault => e
30
+ if retry_count < 5
31
+ sleep(0.5)
32
+ return self._request(method, action, params: params, retry_count: retry_count+1, **opts)
33
+ end
34
+ raise e
35
+
36
+ rescue AcosClient::Error::InvalidSessionID
37
+ if retry_count < 5
38
+ sleep(0.5)
39
+ begin
40
+ p = @client.current_partition
41
+ @client.session.close
42
+ @client.partition.active(p)
43
+ rescue Exception => e
44
+ #pass
45
+ end
46
+ return self._request(method, action, params: params, retry_count: retry_count+1, **opts)
47
+ end
48
+ raise e
49
+ end
50
+
51
+ end
52
+
53
+ def _get(action, params: {}, **opts)
54
+ self._request('GET', action, params: params, **opts)
55
+ end
56
+
57
+ def _post(action, params: {}, **opts)
58
+ self._request('POST', action, params: params, **opts)
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,26 @@
1
+ require 'acos_client/v21/base'
2
+
3
+ module AcosClient
4
+ module V21
5
+ class ConfigFile < AcosClient::V21::BaseV21
6
+
7
+ def upload(cfg_backup, **opts)
8
+ self._post('system.config_file.upload', params: cfg_backup, **opts)
9
+ end
10
+
11
+
12
+ def restore(**opts)
13
+ self._post('system.config_file.restore', **opts)
14
+ end
15
+
16
+
17
+ def write(from_file, to_file, **opts)
18
+ params = {:from => from_file, :to => to_file}
19
+ self._post('system.config_file.write', params: params, **opts)
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,22 @@
1
+ require 'acos_client/v21/base'
2
+
3
+ module AcosClient
4
+ module V21
5
+
6
+ class DeviceInfo < AcosClient::V21::BaseV21
7
+
8
+ def get(**opts)
9
+ return self._get('system.device_info.get', **opts)
10
+ end
11
+
12
+ def cpu_current_usage(**opts)
13
+ return self._get('system.device_info.cpu.current_usage.get', **opts)
14
+ end
15
+
16
+ def cpu_historical_usage(**opts)
17
+ return self._get('system.device_info.cpu.historical_usage.get', *opts)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ require 'acos_client/v21/base'
2
+
3
+ module AcosClient
4
+ module V21
5
+
6
+ class HA < AcosClient::V21::BaseV21
7
+
8
+ def sync(destination_ip, username, password)
9
+
10
+ params = {
11
+ :ha_config_sync => {
12
+ :auto_authentication => 0,
13
+ :user => username,
14
+ :password => password,
15
+ :sync_all_partition => 1,
16
+ :operation => 2, # running config only
17
+ :peer_operation => 0, # running config
18
+ :peer_reload => 0,
19
+ :destination_ip => destination_ip
20
+ }
21
+ }
22
+
23
+ self._post('ha.sync_config', params: params)
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end