acos_client 0.1.0.pre.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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