wzcloud-nova 0.9.29

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f33e8d10aeedcb3d952e33b2c367df563673eb03
4
+ data.tar.gz: c75f0790e5ae5f63d0492f7bb26030346b7237ed
5
+ SHA512:
6
+ metadata.gz: b1bcc1d8237979126046fe956bbe4174f3fe7f590c8c06a5e3f09bd7cf15dc3825b1895563d652ae5be2103188040d90eaf22aaaaa382d0ef3645d694225545f
7
+ data.tar.gz: 4ed8363b41c024f45c8617583d98b0eede25fc695c97d63429a7f9946109cbae52b856e1c398cbff29a77bc724d1e1e5ccf9f673376ff274f82ca36dd57c10ea
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.editorconfig ADDED
@@ -0,0 +1,6 @@
1
+ [*.rb]
2
+ charset=utf-8
3
+ end_of_line=lf
4
+ insert_final_newline=true
5
+ indent_style=space
6
+ indent_size=2
data/.gitattributes ADDED
@@ -0,0 +1 @@
1
+ spec/cassettes/** -diff
data/.gitignore ADDED
@@ -0,0 +1,54 @@
1
+ # rcov generated
2
+ coverage
3
+ coverage.data
4
+
5
+ # rdoc generated
6
+ rdoc
7
+
8
+ # yard generated
9
+ doc
10
+ .yardoc
11
+
12
+ # bundler
13
+ .bundle
14
+
15
+ # jeweler generated
16
+ pkg
17
+
18
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
19
+ #
20
+ # * Create a file at ~/.gitignore
21
+ # * Include files you want ignored
22
+ # * Run: git config --global core.excludesfile ~/.gitignore
23
+ #
24
+ # After doing this, these files will be ignored in all your git projects,
25
+ # saving you from having to 'pollute' every project you touch with them
26
+ #
27
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
28
+ #
29
+ # For MacOS:
30
+ #
31
+ #.DS_Store
32
+
33
+ # For TextMate
34
+ #*.tmproj
35
+ #tmtags
36
+
37
+ # For emacs:
38
+ #*~
39
+ #\#*
40
+ #.\#*
41
+
42
+ # For vim:
43
+ #*.swp
44
+
45
+ # For redcar:
46
+ #.redcar
47
+
48
+ # For rubinius:
49
+ #*.rbc
50
+
51
+ # <3 Idea
52
+ .idea
53
+ wzcloud-nova.iml
54
+ *.gem
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,34 @@
1
+ image: "nexus.servers.com/ruby:2.3.4"
2
+
3
+ variables:
4
+ RACK_ENV: test
5
+ CI: 'gitlab'
6
+
7
+ test:
8
+ cache:
9
+ key: root
10
+ paths:
11
+ - vendor
12
+ script:
13
+ - bundle install -j $(nproc) --path vendor --clean
14
+ - STAGING=serverscom ENABLE_VCR=true bundle exec rspec
15
+
16
+ rubocop:
17
+ services: []
18
+ cache:
19
+ key: root
20
+ paths:
21
+ - vendor
22
+ script:
23
+ - bundle install -j $(nproc) --path vendor --clean
24
+ - bundle exec rubocop -D
25
+
26
+ production:
27
+ type: deploy
28
+ script:
29
+ - bundle install -j $(nproc) --path vendor --clean
30
+ - gem install geminabox
31
+ - gem install nexus
32
+ - make release
33
+ only:
34
+ - tags
data/.overcommit.yml ADDED
@@ -0,0 +1,22 @@
1
+ CommitMsg:
2
+ HardTabs:
3
+ enabled: true
4
+ CapitalizedSubject:
5
+ enabled: true
6
+ on_warn: fail
7
+
8
+ PreCommit:
9
+ ALL:
10
+ exclude:
11
+ - 'spec/cassettes/**/*'
12
+ - 'Makefile'
13
+ RuboCop:
14
+ enabled: true
15
+ on_warn: fail
16
+ command: ['bundle', 'exec', 'rubocop']
17
+ HardTabs:
18
+ enabled: true
19
+ TrailingWhitespace:
20
+ enabled: true
21
+ BundleCheck:
22
+ enabled: true
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,54 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ # This is the configuration used to check the rubocop source code.
4
+
5
+ AllCops:
6
+ TargetRubyVersion: 2.3
7
+ Exclude:
8
+ - 'Gemfile'
9
+ - 'Makefile'
10
+ - 'bin/*'
11
+ - 'vendor/**/*'
12
+ - '*/vendor/**/*'
13
+
14
+ Documentation:
15
+ Enabled: false
16
+
17
+ Style/AsciiComments:
18
+ Enabled: false
19
+
20
+ Performance/Casecmp:
21
+ Enabled: false
22
+
23
+ Metrics/LineLength:
24
+ Max: 120
25
+
26
+ Metrics/ClassLength:
27
+ Enabled: false
28
+
29
+ Metrics/AbcSize:
30
+ Enabled: false
31
+
32
+ Metrics/MethodLength:
33
+ Enabled: false
34
+
35
+ Metrics/CyclomaticComplexity:
36
+ Enabled: false
37
+
38
+ Metrics/ParameterLists:
39
+ Enabled: false
40
+
41
+ Naming/AccessorMethodName:
42
+ Enabled: false
43
+
44
+ Lint/HandleExceptions:
45
+ Enabled: false
46
+
47
+ Lint/UselessAssignment:
48
+ Enabled: false
49
+
50
+ Metrics/PerceivedComplexity:
51
+ Enabled: false
52
+
53
+ Layout/SpaceInsideHashLiteralBraces:
54
+ EnforcedStyle: no_space
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,117 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2019-04-16 21:20:57 +0300 using RuboCop version 0.67.2.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 2
10
+ # Cop supports --auto-correct.
11
+ # Configuration parameters: TreatCommentsAsGroupSeparators, Include.
12
+ # Include: **/*.gemspec
13
+ Gemspec/OrderedDependencies:
14
+ Exclude:
15
+ - 'wzcloud-nova.gemspec'
16
+
17
+ # Offense count: 11
18
+ # Cop supports --auto-correct.
19
+ Layout/EmptyLineAfterGuardClause:
20
+ Exclude:
21
+ - 'lib/wzcloud/nova.rb'
22
+
23
+ # Offense count: 5
24
+ # Configuration parameters: CountComments, ExcludedMethods.
25
+ # ExcludedMethods: refine
26
+ Metrics/BlockLength:
27
+ Max: 538
28
+
29
+ # Offense count: 1
30
+ # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
31
+ # AllowedNames: io, id, to, by, on, in, at, ip, db
32
+ Naming/UncommunicativeMethodParamName:
33
+ Exclude:
34
+ - 'lib/wzcloud/nova.rb'
35
+
36
+ # Offense count: 1
37
+ # Cop supports --auto-correct.
38
+ Performance/CompareWithBlock:
39
+ Exclude:
40
+ - 'lib/wzcloud/nova.rb'
41
+
42
+ # Offense count: 1
43
+ # Cop supports --auto-correct.
44
+ Style/Encoding:
45
+ Exclude:
46
+ - 'Rakefile'
47
+
48
+ # Offense count: 1
49
+ # Cop supports --auto-correct.
50
+ Style/ExpandPathArguments:
51
+ Exclude:
52
+ - 'wzcloud-nova.gemspec'
53
+
54
+ # Offense count: 7
55
+ # Cop supports --auto-correct.
56
+ # Configuration parameters: EnforcedStyle.
57
+ # SupportedStyles: when_needed, always, never
58
+ Style/FrozenStringLiteralComment:
59
+ Exclude:
60
+ - 'Rakefile'
61
+ - 'lib/wzcloud/nova.rb'
62
+ - 'spec/spec_helper.rb'
63
+ - 'spec/support/staging.rb'
64
+ - 'spec/support/vcr.rb'
65
+ - 'spec/wzcloud/nova_spec.rb'
66
+ - 'wzcloud-nova.gemspec'
67
+
68
+ # Offense count: 2
69
+ # Cop supports --auto-correct.
70
+ # Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
71
+ # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
72
+ Style/HashSyntax:
73
+ Exclude:
74
+ - 'lib/wzcloud/nova.rb'
75
+
76
+ # Offense count: 2
77
+ # Cop supports --auto-correct.
78
+ # Configuration parameters: InverseMethods, InverseBlocks.
79
+ Style/InverseMethods:
80
+ Exclude:
81
+ - 'lib/wzcloud/nova.rb'
82
+
83
+ # Offense count: 1
84
+ # Cop supports --auto-correct.
85
+ # Configuration parameters: PreferredDelimiters.
86
+ Style/PercentLiteralDelimiters:
87
+ Exclude:
88
+ - 'lib/wzcloud/nova.rb'
89
+
90
+ # Offense count: 2
91
+ # Cop supports --auto-correct.
92
+ # Configuration parameters: EnforcedStyle.
93
+ # SupportedStyles: implicit, explicit
94
+ Style/RescueStandardError:
95
+ Exclude:
96
+ - 'spec/wzcloud/nova_spec.rb'
97
+
98
+ # Offense count: 2
99
+ # Cop supports --auto-correct.
100
+ Style/StderrPuts:
101
+ Exclude:
102
+ - 'Rakefile'
103
+
104
+ # Offense count: 1
105
+ # Cop supports --auto-correct.
106
+ # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
107
+ # SupportedStyles: single_quotes, double_quotes
108
+ Style/StringLiterals:
109
+ Exclude:
110
+ - 'wzcloud-nova.gemspec'
111
+
112
+ # Offense count: 2
113
+ # Cop supports --auto-correct.
114
+ # Configuration parameters: MinSize.
115
+ # SupportedStyles: percent, brackets
116
+ Style/SymbolArray:
117
+ EnforcedStyle: brackets
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.4
data/Dockerfile.dev ADDED
@@ -0,0 +1,16 @@
1
+ FROM dev2-nl.servers.com:4567/serverscom/docker/ruby:2.3.4
2
+ RUN apt-get update && \
3
+ apt-get install --no-install-recommends -y gcc make clang curl build-essential git tzdata && \
4
+ rm -rf /var/lib/apt/lists/* && \
5
+ mkdir /app && \
6
+ bundle config git.allow_insecure true && \
7
+ bundle config --global silence_root_warning 1
8
+
9
+ WORKDIR /app
10
+
11
+ ENV RACK_ENV=development \
12
+ BUNDLE_PATH=vendor \
13
+ BUNDLE_BIN=vendor/bin \
14
+ PATH="${BUNDLE_BIN}:${PATH}"
15
+
16
+ CMD ["/bin/bash"]
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,113 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ wzcloud-nova (0.9.29)
5
+ multi_json
6
+ wzcloud-transport (~> 0.6.8)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ addressable (2.3.8)
12
+ ast (2.4.0)
13
+ childprocess (0.5.9)
14
+ ffi (~> 1.0, >= 1.0.11)
15
+ coderay (1.1.0)
16
+ cookiejar (0.3.2)
17
+ diff-lcs (1.3)
18
+ docile (1.1.5)
19
+ em-http-request (1.1.2)
20
+ addressable (>= 2.3.4)
21
+ cookiejar
22
+ em-socksify (>= 0.3)
23
+ eventmachine (>= 1.0.3)
24
+ http_parser.rb (>= 0.6.0)
25
+ em-socksify (0.3.1)
26
+ eventmachine (>= 1.0.0.beta.4)
27
+ em-synchrony (1.0.4)
28
+ eventmachine (>= 1.0.0.beta.1)
29
+ eventmachine (1.0.6)
30
+ faraday (0.9.2)
31
+ multipart-post (>= 1.2, < 3)
32
+ faraday_middleware (0.10.0)
33
+ faraday (>= 0.7.4, < 0.10)
34
+ ffi (1.9.18)
35
+ http_parser.rb (0.6.0)
36
+ iniparse (1.4.3)
37
+ jaro_winkler (1.5.2)
38
+ method_source (0.8.2)
39
+ multi_json (1.10.1)
40
+ multipart-post (2.0.0)
41
+ overcommit (0.34.2)
42
+ childprocess (~> 0.5.8)
43
+ iniparse (~> 1.4)
44
+ parallel (1.17.0)
45
+ parser (2.6.2.1)
46
+ ast (~> 2.4.0)
47
+ powerpack (0.1.2)
48
+ pry (0.10.0)
49
+ coderay (~> 1.1.0)
50
+ method_source (~> 0.8.1)
51
+ slop (~> 3.4)
52
+ rainbow (3.0.0)
53
+ rake (10.5.0)
54
+ rspec (3.6.0)
55
+ rspec-core (~> 3.6.0)
56
+ rspec-expectations (~> 3.6.0)
57
+ rspec-mocks (~> 3.6.0)
58
+ rspec-core (3.6.0)
59
+ rspec-support (~> 3.6.0)
60
+ rspec-expectations (3.6.0)
61
+ diff-lcs (>= 1.2.0, < 2.0)
62
+ rspec-support (~> 3.6.0)
63
+ rspec-mocks (3.6.0)
64
+ diff-lcs (>= 1.2.0, < 2.0)
65
+ rspec-support (~> 3.6.0)
66
+ rspec-support (3.6.0)
67
+ rubocop (0.61.1)
68
+ jaro_winkler (~> 1.5.1)
69
+ parallel (~> 1.10)
70
+ parser (>= 2.5, != 2.5.1.1)
71
+ powerpack (~> 0.1)
72
+ rainbow (>= 2.2.2, < 4.0)
73
+ ruby-progressbar (~> 1.7)
74
+ unicode-display_width (~> 1.4.0)
75
+ ruby-progressbar (1.10.0)
76
+ simplecov (0.9.0)
77
+ docile (~> 1.1.0)
78
+ multi_json
79
+ simplecov-html (~> 0.8.0)
80
+ simplecov-html (0.8.0)
81
+ slop (3.6.0)
82
+ unicode-display_width (1.4.1)
83
+ vcr (3.0.1)
84
+ wzcloud-cinder (0.1.7)
85
+ wzcloud-transport (~> 0.6.5)
86
+ wzcloud-keystone (0.4.15)
87
+ wzcloud-transport (~> 0.6.1)
88
+ yajl-ruby
89
+ wzcloud-transport (0.6.8)
90
+ em-http-request
91
+ em-synchrony
92
+ faraday
93
+ faraday_middleware
94
+ yajl-ruby
95
+ yajl-ruby (1.2.1)
96
+
97
+ PLATFORMS
98
+ ruby
99
+
100
+ DEPENDENCIES
101
+ overcommit
102
+ pry
103
+ rake (~> 10.0)
104
+ rspec
105
+ rubocop (= 0.61.1)
106
+ simplecov
107
+ vcr
108
+ wzcloud-cinder (~> 0.1.7)
109
+ wzcloud-keystone (~> 0.4.15)
110
+ wzcloud-nova!
111
+
112
+ BUNDLED WITH
113
+ 1.17.1
data/Makefile ADDED
@@ -0,0 +1,5 @@
1
+ release:
2
+ gem build wzcloud-nova.gemspec
3
+ gem inabox -o wzcloud-nova-*.gem -g http://exaspark:CevEckigaid3@gems.mgm.servers.com
4
+ gem nexus --url https://nexus.servers.com/repository/rubygems-registry/ --credential "${NEXUS_USER}:${NEXUS_PASSWORD}" --ignore-ssl-errors wzcloud-nova-*.gem
5
+ rm wzcloud-nova-*.gem
data/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # wzcloud-nova
2
+
3
+ Description goes here.
4
+
5
+ ## Releasing a new version
6
+
7
+ gem install geminabox
8
+ gem install nexus
9
+ gem inabox -c # setup Host, e.g. http://login:password@gems.mgm.servers.com
10
+
11
+ NEXUS_USER=login NEXUS_PASSWORD=password make release
12
+
13
+ ## Releasing a new version via CI
14
+
15
+ git commit
16
+ git tag -a v0.0.1 -m 'Version 0.0.1'
17
+ git push origin v0.0.1
18
+
19
+ ## Contributing to wzcloud-nova
20
+
21
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
22
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
23
+ * Fork the project.
24
+ * Start a feature/bugfix branch.
25
+ * Commit and push until you are happy with your contribution.
26
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
27
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,30 @@
1
+ version: '3.4'
2
+
3
+ x-logging: &logging
4
+ options:
5
+ max-size: '200k'
6
+ max-file: '5'
7
+ labels: "{{.Name}}"
8
+ driver: json-file
9
+
10
+ x-app: &base
11
+ build:
12
+ context: .
13
+ dockerfile: Dockerfile.dev
14
+ environment: &app_env
15
+ - RACK_ENV=development
16
+ - APP_ENV=development
17
+ - BUNDLE_PATH=vendor
18
+ - BUNDLE_BIN=vendor/bin
19
+ volumes:
20
+ - .:/app
21
+ - bundled_gems:/app/vendor
22
+ logging: *logging
23
+
24
+ volumes:
25
+ bundled_gems:
26
+
27
+ services:
28
+ app:
29
+ <<: *base
30
+ working_dir: /app
@@ -0,0 +1,503 @@
1
+ require 'wzcloud/transport'
2
+ require 'multi_json'
3
+ require 'ostruct'
4
+ require 'yaml'
5
+ require 'base64'
6
+
7
+ module WZCloud
8
+ class Nova
9
+ KEYPAIR_PREFIX = 'os-keypairs'.freeze
10
+ ERROR_STATUS = 'ERROR'.freeze
11
+
12
+ attr_reader :transport, :default_headers
13
+
14
+ def initialize(access, transport, custom_headers = {})
15
+ @access = access
16
+ @transport = transport
17
+ @base_url = @access.endpoints('nova')
18
+ @transport.middleware.unshift(ErrorHandler)
19
+ @default_headers = {'X-Auth-Token' => @access.token,
20
+ 'Content-Type' => 'application/json',
21
+ 'Accept' => 'application/json'}.merge(custom_headers)
22
+ end
23
+
24
+ def get_flavors(is_public = true)
25
+ params = {}
26
+ params[:is_public] = false unless is_public
27
+ make_request(:get, 'flavors', nil, params)
28
+ .body[:flavors].map(&OpenStruct.method(:new))
29
+ end
30
+
31
+ def get_flavor(id)
32
+ make_request(:get, "flavors/#{id}").body[:flavor]
33
+ end
34
+
35
+ def get_flavors_detail(is_public = true)
36
+ params = {}
37
+ params[:is_public] = false unless is_public
38
+ sort_flavors(make_request(:get, 'flavors/detail', nil, params).body[:flavors])
39
+ end
40
+
41
+ def get_flavor_extra_specs(flavor_id)
42
+ make_request(:get, "flavors/#{flavor_id}/os-extra_specs", nil, {}).body[:extra_specs]
43
+ end
44
+
45
+ def get_flavor_access(flavor_id, options = {})
46
+ make_request(:get, "flavors/#{flavor_id}/os-flavor-access", nil, options).body[:flavor_access]
47
+ rescue WZCloud::Transport::NotFoundError => _e
48
+ []
49
+ end
50
+
51
+ def get_images
52
+ make_request(:get, 'images').body[:images].map(&OpenStruct.method(:new))
53
+ end
54
+
55
+ def get_images_detail(options = {})
56
+ make_request(:get, 'images/detail', nil, options).body[:images]
57
+ end
58
+
59
+ def get_servers_detail(options = {})
60
+ make_request(:get, 'servers/detail', nil, options).body[:servers]
61
+ end
62
+
63
+ def get_server(id)
64
+ make_request(:get, "servers/#{id}").body[:server]
65
+ end
66
+
67
+ def get_servers(options = {})
68
+ make_request(:get, 'servers', nil, options).body[:servers]
69
+ end
70
+
71
+ def create_server(name, flavor_ref, image_ref, network_id = nil,
72
+ av_zone = nil, key_name = nil, password = nil,
73
+ server_group = nil, count = 1, return_reservation_id = false)
74
+ options = {server: {name: name, flavorRef: flavor_ref, imageRef: image_ref}}
75
+
76
+ options['os:scheduler_hints'] = {group: server_group} if server_group
77
+ options[:server][:availability_zone] = av_zone if av_zone
78
+ options[:server][:key_name] = key_name if key_name
79
+ options[:server][:networks] = Array(network_id).map { |nid| {uuid: nid} } if network_id
80
+ options[:server][:min_count] = count if count.to_i > 1
81
+ options[:server][:return_reservation_id] = 'True' if return_reservation_id
82
+ unless password.to_s.empty?
83
+ user_data = generate_user_data(password)
84
+ options[:server][:user_data] = Base64.encode64(user_data)
85
+ end
86
+
87
+ result = make_request(:post, 'servers', options)
88
+
89
+ return_reservation_id ? result.body : result.body[:server]
90
+ end
91
+
92
+ def rename_server(server_uuid, new_name)
93
+ make_request(:put, "servers/#{server_uuid}", server: {name: new_name}).body[:server]
94
+ end
95
+
96
+ def rebuild_server(server_uuid, image_ref, name = nil)
97
+ opts = {imageRef: image_ref}
98
+ opts[:name] = name if name
99
+ make_request(:post, "servers/#{server_uuid}/action", rebuild: opts).body[:server]
100
+ end
101
+
102
+ def delete_server(uuid)
103
+ make_request(:delete, "servers/#{uuid}")
104
+ end
105
+
106
+ def resize_server(server_uuid, flavor_ref)
107
+ server = get_server(server_uuid)
108
+ raise InstanceError if server[:status] != 'ACTIVE'
109
+ data = {resize: {flavorRef: flavor_ref}}
110
+ make_request :post, "servers/#{server_uuid}/action", data
111
+ end
112
+
113
+ def confirm_resize_server(server_uuid)
114
+ server = get_server(server_uuid)
115
+ raise InstanceError if server[:status] != 'VERIFY_RESIZE'
116
+ make_request :post, "servers/#{server_uuid}/action", confirmResize: nil
117
+ end
118
+
119
+ def revert_resize_server(server_uuid)
120
+ server = get_server(server_uuid)
121
+ raise InstanceError if server[:status] != 'VERIFY_RESIZE' # XXX Maybe delete all this checks?
122
+ make_request :post, "servers/#{server_uuid}/action", revertResize: nil
123
+ end
124
+
125
+ def start_server(server_uuid)
126
+ make_request :post, "servers/#{server_uuid}/action", 'os-start' => nil
127
+ end
128
+
129
+ def stop_server(server_uuid)
130
+ make_request :post, "servers/#{server_uuid}/action", 'os-stop' => nil
131
+ rescue Transport::ConflictError => e
132
+ raise unless e.message['vm_state stopped']
133
+ end
134
+
135
+ def reboot_server(server_uuid, type = 'SOFT')
136
+ data = {reboot: {type: type}}
137
+ make_request :post, "servers/#{server_uuid}/action", data
138
+ end
139
+
140
+ def reset_server(server_uuid, type = 'error')
141
+ data = {'os-resetState' => {state: type}}
142
+ make_request :post, "servers/#{server_uuid}/action", data
143
+ end
144
+
145
+ def get_server_groups(options = {})
146
+ make_request(:get, 'os-server-groups', options).body[:server_groups]
147
+ end
148
+
149
+ def create_server_group(name, policy)
150
+ options = {name: name, policies: [policy]}
151
+ make_request(:post, 'os-server-groups', server_group: options).body[:server_group]
152
+ end
153
+
154
+ def get_server_group(server_group_uuid)
155
+ make_request(:get, "os-server-groups/#{server_group_uuid}").body[:server_group]
156
+ end
157
+
158
+ def delete_server_group(server_group_uuid)
159
+ make_request(:delete, "os-server-groups/#{server_group_uuid}")
160
+ end
161
+
162
+ def vnc_url(server_uuid)
163
+ data = {:'os-getVNCConsole' => {type: 'novnc'}}
164
+ make_request(:post, "servers/#{server_uuid}/action", data).body
165
+ end
166
+
167
+ def get_actions(server_uuid)
168
+ make_request(:get, "/servers/#{server_uuid}/os-instance-actions")
169
+ .body[:instanceActions]
170
+ end
171
+
172
+ def get_action_detail(server_uuid, request_id)
173
+ make_request(:get, "/servers/#{server_uuid}/os-instance-actions/#{request_id}")
174
+ .body[:instanceAction]
175
+ end
176
+
177
+ def attach_interface(server_id, network_id)
178
+ wait_for_servers
179
+
180
+ make_request(
181
+ :post,
182
+ "servers/#{server_id}/os-interface",
183
+ interfaceAttachment: {net_id: network_id}
184
+ ).body[:interfaceAttachment]
185
+ end
186
+
187
+ def detach_interface(server_id, network_id, neutron)
188
+ ifaces = make_request(:get, "servers/#{server_id}/os-interface").body[:interfaceAttachments]
189
+ iface = ifaces.find { |i| i[:net_id] == network_id }
190
+ raise "Interface for network #{network_id} not found on #{server_id}" unless iface
191
+ neutron.delete_port(iface[:port_id])
192
+ end
193
+
194
+ def get_keypairs
195
+ make_request(:get, KEYPAIR_PREFIX).body[:keypairs]
196
+ end
197
+
198
+ def get_keypair_by_fingerprint(fp)
199
+ get_keypairs.find { |kp| kp[:keypair][:fingerprint] == fp } ||
200
+ raise(ArgumentError, "Keypair with fingerprint #{fp} not found")
201
+ end
202
+
203
+ def create_keypair(name, public_key = nil)
204
+ body = {keypair: {name: name}}
205
+ body[:keypair][:public_key] = public_key if public_key
206
+ begin
207
+ make_request(:post, KEYPAIR_PREFIX, body).body[:keypair]
208
+ rescue Transport::BadRequestError => e
209
+ # Can't reproduce message
210
+ if e.message['malformed or otherwise incorrect'] || e.message['Keypair data is invalid:']
211
+ raise ArgumentError, 'Invalid public key'
212
+ end
213
+ raise e
214
+ end
215
+ end
216
+
217
+ def delete_keypair(name)
218
+ make_request :delete, "#{KEYPAIR_PREFIX}/#{name}"
219
+ end
220
+
221
+ def get_hosts
222
+ hosts = make_request(:get, 'os-hosts').body[:hosts]
223
+ # Filtering via query parameter doesn't work.
224
+ hosts.select { |host| host[:service] == 'compute' }
225
+ end
226
+
227
+ def get_av_zones
228
+ info = make_request(:get, 'os-availability-zone').body[:availabilityZoneInfo]
229
+ info.delete_if { |zone| !zone[:zoneState][:available] }.map { |zone| zone[:zoneName] }
230
+ end
231
+
232
+ def get_snapshots(instance_id = nil)
233
+ params = if instance_id
234
+ {server: "#{@base_url}/servers/#{instance_id}"}
235
+ else
236
+ {}
237
+ end
238
+ images = get_images_detail(params)
239
+ if instance_id
240
+ images
241
+ else
242
+ images.select { |i| i[:server] }
243
+ end
244
+ end
245
+
246
+ def create_snapshot(instance_id, options = {})
247
+ name = options[:name] || "#{instance_id}-snap-#{Time.new.to_i}"
248
+ metadata = options[:metadata] || {}
249
+ begin
250
+ r = make_request(
251
+ :post,
252
+ "servers/#{instance_id}/action",
253
+ createImage: {name: name, metadata: metadata}
254
+ )
255
+ {id: r.headers['Location'][%r{\/([-a-f0-9]+)\z}, 1]}
256
+ rescue Transport::RequestError => e
257
+ case e
258
+ when Transport::NotFoundError
259
+ raise ArgumentError, "Instance #{instance_id} not found"
260
+ when Transport::ConflictError
261
+ raise ArgumentError, "Instance #{instance_id} is in conflicting state"
262
+ else
263
+ raise e
264
+ end
265
+ end
266
+ end
267
+
268
+ def delete_image(id)
269
+ make_request(:delete, "images/#{id}")
270
+ end
271
+
272
+ def fetch_local_ip(server_details)
273
+ local_ip = nil
274
+ server_details[:addresses].each do |addr_name, ips|
275
+ next unless addr_name['local-network']
276
+ ips.each do |ip|
277
+ local_ip = ip[:addr] if ip[:"OS-EXT-IPS:type"] == 'fixed'
278
+ end
279
+ end
280
+ local_ip
281
+ end
282
+
283
+ def fetch_internal_and_external_ips(server_details)
284
+ internal_ip = nil
285
+ external_ip = nil
286
+ server_details[:addresses].each do |addr_name, ips|
287
+ next unless addr_name['network-for']
288
+ ips.each do |ip|
289
+ case ip[:"OS-EXT-IPS:type"]
290
+ when 'fixed' then internal_ip = ip[:addr]
291
+ when 'floating' then external_ip = ip[:addr]
292
+ end
293
+ end
294
+ end
295
+ {internal_ip: internal_ip, external_ip: external_ip}
296
+ end
297
+
298
+ def quotas(tenant_id)
299
+ make_request(:get, "os-quota-sets/#{tenant_id}").body[:quota_set]
300
+ end
301
+
302
+ def update_quotas(tenant_id, new_quotas)
303
+ data = {quota_set: new_quotas}
304
+ make_request(:put, "os-quota-sets/#{tenant_id}", data).body[:quota_set]
305
+ end
306
+
307
+ # Requires admin privileges by default, but that can be changed via
308
+ # +compute_extension:os-server-external-events:create+ policy.
309
+ def refresh_network(server_id)
310
+ data = {events: [{name: 'network-changed', server_uuid: server_id}]}
311
+ make_request(:post, 'os-server-external-events', data)
312
+ rescue WZCloud::Transport::NotFoundError
313
+ # Network not available yet? Nothing to reset, then.
314
+ end
315
+
316
+ def get_console_output(instance_id)
317
+ make_request(:post, "servers/#{instance_id}/action",
318
+ :"os-getConsoleOutput" => {length: nil})
319
+ .body[:output]
320
+ end
321
+
322
+ def migrate_server(instance_id)
323
+ make_request(:post, "servers/#{instance_id}/action", migrate: nil)
324
+ end
325
+
326
+ def get_volumes(server_id)
327
+ make_request(:get, "servers/#{server_id}/os-volume_attachments").body[:volumeAttachments]
328
+ end
329
+
330
+ def attach_volume(server_id, volume_id)
331
+ data = {volumeAttachment: {volumeId: volume_id}}
332
+ make_request(
333
+ :post,
334
+ "servers/#{server_id}/os-volume_attachments",
335
+ data
336
+ ).body[:volumeAttachment]
337
+ end
338
+
339
+ def rescue_server(server_uuid, admin_password = nil, rescue_image_ref = nil)
340
+ data = {rescue: {}}
341
+ data[:rescue][:adminPass] = admin_password if admin_password
342
+ data[:rescue][:rescue_image_ref] = rescue_image_ref if rescue_image_ref
343
+ make_request(:post, "servers/#{server_uuid}/action", data).body
344
+ end
345
+
346
+ def unrescue_server(server_uuid)
347
+ data = {unrescue: nil}
348
+ make_request(:post, "servers/#{server_uuid}/action", data).body
349
+ end
350
+
351
+ def detach_volume(server_id, attachment_id)
352
+ make_request(:delete, "servers/#{server_id}/os-volume_attachments/#{attachment_id}")
353
+ end
354
+
355
+ def lock(server_uuid)
356
+ make_request :post, "servers/#{server_uuid}/action", lock: nil
357
+ end
358
+
359
+ def unlock(server_uuid)
360
+ make_request :post, "servers/#{server_uuid}/action", unlock: nil
361
+ end
362
+
363
+ def show_attachment(server_id, attachment_id)
364
+ make_request(
365
+ :get,
366
+ "servers/#{server_id}/os-volume_attachments/#{attachment_id}"
367
+ ).body[:volumeAttachment]
368
+ end
369
+
370
+ def wait_for_servers
371
+ loop do
372
+ servers = get_servers_detail
373
+ break if !servers.any? { |serv| %w(BUILD RESIZE).include? serv[:status] } &&
374
+ !servers.any? { |serv| ['deleting'].include? serv[:"OS-EXT-STS:task_state"] }
375
+ sleep 1
376
+ end
377
+ end
378
+
379
+ def wait_status(server, status, seconds = 120)
380
+ server_status = get_server(server[:id])[:status]
381
+ seconds.times do
382
+ server_status = get_server(server[:id])[:status]
383
+ break if server_status == status || server_status == ERROR_STATUS
384
+ sleep 1
385
+ end
386
+ raise InstanceError, server_status if server_status != status
387
+ end
388
+
389
+ def wait_for_snapshots
390
+ loop do
391
+ images = get_images_detail
392
+ break unless images.any? { |image| ['SAVING'].include? image[:status] }
393
+ sleep 1
394
+ end
395
+ end
396
+
397
+ def clear_db(servers = get_servers)
398
+ servers.each do |server|
399
+ begin
400
+ delete_server(server[:id])
401
+ rescue Transport::RequestError => e
402
+ # that happens sometimes
403
+ raise e unless e.status == 404
404
+ end
405
+ end
406
+
407
+ get_snapshots.each do |snap|
408
+ begin
409
+ delete_image(snap[:id])
410
+ rescue Transport::RequestError => e
411
+ # that happens too
412
+ raise e unless e.status == 404
413
+ end
414
+ end
415
+
416
+ # If we don't wait until all instances are terminated,
417
+ # the next cleanup action is likely to remove the current tenant,
418
+ # and then the remaining instances won't get deleted automatically.
419
+ while servers.any?
420
+ servers.each do |server|
421
+ begin
422
+ get_server(server[:id])
423
+ rescue Transport::NotFoundError
424
+ servers.delete(server)
425
+ end
426
+ end
427
+
428
+ sleep 0.1
429
+ end
430
+
431
+ get_keypairs.each do |keypair|
432
+ delete_keypair keypair[:keypair][:name]
433
+ end
434
+ end
435
+
436
+ def make_request(method, url_path, body = nil, params = nil)
437
+ json_body = MultiJson.dump(body) if body
438
+
439
+ @transport.http_call("#{@base_url}/#{url_path}", method,
440
+ default_headers, json_body, params)
441
+ end
442
+
443
+ private
444
+
445
+ def generate_user_data(password)
446
+ %(
447
+ #cloud-config
448
+ disable_root: False
449
+ ssh_pwauth: True
450
+ users: root
451
+ chpasswd:
452
+ list: |
453
+ root:#{password}
454
+ expire: True
455
+ ).strip
456
+ end
457
+
458
+ def sort_flavors(flavors)
459
+ flavors.sort { |f1, f2| f1[:disk] <=> f2[:disk] }
460
+ end
461
+
462
+ class InstanceError < StandardError; end
463
+
464
+ class ErrorHandler
465
+ def initialize(app)
466
+ @app = app
467
+ end
468
+
469
+ def call(envir)
470
+ @app.call(envir)
471
+ rescue Faraday::Error::TimeoutError => e
472
+ raise Transport::TimeoutError.new(envir[:url].to_s, 'Timeout error', 504)
473
+ rescue Faraday::Error::ClientError => e
474
+ raise unless e.response
475
+ case e.response[:status]
476
+ when 400
477
+ message = e.response[:body][:badRequest][:message]
478
+ raise Transport::BadRequestError.new(envir[:url].to_s, message, 400)
479
+ when 403
480
+ raise Transport::UnauthorizedError.new(
481
+ envir[:url].to_s,
482
+ e.response[:body].values.first[:message],
483
+ 403
484
+ )
485
+ when 404
486
+ message = if e.response[:body].class == String
487
+ e.response[:body]
488
+ else
489
+ e.response[:body][:itemNotFound][:message]
490
+ end
491
+ raise Transport::NotFoundError.new(envir[:url].to_s, message, 404)
492
+ when 409
493
+ message = e.response[:body][:conflictingRequest][:message]
494
+ raise Transport::ConflictError.new(envir[:url].to_s, message, 409)
495
+ else
496
+ body = e.response[:body]
497
+ message = body.values.first[:message] if body && body.class == Hash
498
+ raise Transport::RequestError.new(envir[:url].to_s, message, e.response[:status])
499
+ end
500
+ end
501
+ end
502
+ end
503
+ end
@@ -0,0 +1,35 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'wzcloud-nova'
6
+ s.version = '0.9.29'
7
+
8
+ s.require_paths = ['lib']
9
+ s.authors = ['Sokolov Ilya', 'Dmitry Gutov']
10
+ s.date = '2015-12-23'
11
+ s.description = 'longer description of your gem'
12
+ s.email = 'Falconmain@gmail.com'
13
+ s.extra_rdoc_files = [
14
+ 'README.md'
15
+ ]
16
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ s.homepage = 'http://github.com/Flcn/wzcloud-nova'
20
+ s.licenses = ['MIT']
21
+ s.summary = 'one-line summary of your gem'
22
+
23
+ s.add_runtime_dependency 'wzcloud-transport', '~> 0.6.8'
24
+ s.add_runtime_dependency 'multi_json'
25
+
26
+ s.add_development_dependency 'wzcloud-keystone', '~> 0.4.15'
27
+ s.add_development_dependency 'wzcloud-cinder', '~> 0.1.7'
28
+ s.add_development_dependency 'rake', '~> 10.0'
29
+ s.add_development_dependency 'pry'
30
+ s.add_development_dependency 'rspec'
31
+ s.add_development_dependency 'vcr'
32
+ s.add_development_dependency 'simplecov'
33
+ s.add_development_dependency 'rubocop', '0.61.1'
34
+ s.add_development_dependency 'overcommit'
35
+ end
metadata ADDED
@@ -0,0 +1,218 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wzcloud-nova
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.29
5
+ platform: ruby
6
+ authors:
7
+ - Sokolov Ilya
8
+ - Dmitry Gutov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-12-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: wzcloud-transport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 0.6.8
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 0.6.8
28
+ - !ruby/object:Gem::Dependency
29
+ name: multi_json
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: wzcloud-keystone
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 0.4.15
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 0.4.15
56
+ - !ruby/object:Gem::Dependency
57
+ name: wzcloud-cinder
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: 0.1.7
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 0.1.7
70
+ - !ruby/object:Gem::Dependency
71
+ name: rake
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '10.0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '10.0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: pry
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rspec
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: vcr
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: simplecov
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: rubocop
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - '='
145
+ - !ruby/object:Gem::Version
146
+ version: 0.61.1
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - '='
152
+ - !ruby/object:Gem::Version
153
+ version: 0.61.1
154
+ - !ruby/object:Gem::Dependency
155
+ name: overcommit
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ description: longer description of your gem
169
+ email: Falconmain@gmail.com
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files:
173
+ - README.md
174
+ files:
175
+ - ".document"
176
+ - ".editorconfig"
177
+ - ".gitattributes"
178
+ - ".gitignore"
179
+ - ".gitlab-ci.yml"
180
+ - ".overcommit.yml"
181
+ - ".rspec"
182
+ - ".rubocop.yml"
183
+ - ".rubocop_todo.yml"
184
+ - ".ruby-version"
185
+ - Dockerfile.dev
186
+ - Gemfile
187
+ - Gemfile.lock
188
+ - Makefile
189
+ - README.md
190
+ - Rakefile
191
+ - docker-compose.yml
192
+ - lib/wzcloud/nova.rb
193
+ - wzcloud-nova.gemspec
194
+ homepage: http://github.com/Flcn/wzcloud-nova
195
+ licenses:
196
+ - MIT
197
+ metadata: {}
198
+ post_install_message:
199
+ rdoc_options: []
200
+ require_paths:
201
+ - lib
202
+ required_ruby_version: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
207
+ required_rubygems_version: !ruby/object:Gem::Requirement
208
+ requirements:
209
+ - - ">="
210
+ - !ruby/object:Gem::Version
211
+ version: '0'
212
+ requirements: []
213
+ rubyforge_project:
214
+ rubygems_version: 2.5.2
215
+ signing_key:
216
+ specification_version: 4
217
+ summary: one-line summary of your gem
218
+ test_files: []