ops_manager_cli 0.5.4 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -1
- data/Dockerfile +1 -1
- data/lib/ops_manager/api/base.rb +3 -0
- data/lib/ops_manager/api/opsman.rb +38 -1
- data/lib/ops_manager/appliance/aws.rb +89 -0
- data/lib/ops_manager/appliance/base.rb +23 -0
- data/lib/ops_manager/appliance/vsphere.rb +47 -0
- data/lib/ops_manager/appliance_deployment.rb +48 -28
- data/lib/ops_manager/cli.rb +7 -0
- data/lib/ops_manager/config/base.rb +42 -0
- data/lib/ops_manager/{configs → config}/opsman_deployment.rb +2 -2
- data/lib/ops_manager/config/product_deployment.rb +13 -0
- data/lib/ops_manager/configs/base.rb +1 -1
- data/lib/ops_manager/installation_runner.rb +8 -19
- data/lib/ops_manager/product_deployment.rb +16 -14
- data/lib/ops_manager/version.rb +1 -1
- data/lib/ops_manager.rb +4 -3
- data/ops_manager.gemspec +1 -0
- metadata +22 -5
- data/lib/ops_manager/configs/product_deployment.rb +0 -16
- data/lib/ops_manager/deployments/vsphere.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8992b156cebae9e672d078b6da9b8657a650b093
|
4
|
+
data.tar.gz: 70fab26214ffab2248756aa0e281fb287acd0e5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2e769b03f59448e5e415f141d2dac8d6009ae272c748c20aabb98b8c6ea6b70d38ada89d20c335e13daafe79fbb9ec9a44be775a7ca3750d69396a20459606e
|
7
|
+
data.tar.gz: 3ef3595a66344221983bdde63e1c770a3422453286656bdf572f2d8b4f66c6e8a4e01ed8549e2bd4672246c4f508e3d789fcee5542fd5f67acc69f138f07d201
|
data/CHANGELOG.md
CHANGED
@@ -1,17 +1,28 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v0.5.4](https://github.com/compozed/ops_manager_cli/tree/v0.5.4) (2017-06-27)
|
4
|
+
[Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.5.3...v0.5.4)
|
5
|
+
|
6
|
+
## [v0.5.3](https://github.com/compozed/ops_manager_cli/tree/v0.5.3) (2017-06-27)
|
7
|
+
[Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.5.2...v0.5.3)
|
8
|
+
|
3
9
|
## [v0.5.2](https://github.com/compozed/ops_manager_cli/tree/v0.5.2) (2017-06-27)
|
4
10
|
[Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.5.1...v0.5.2)
|
5
11
|
|
6
12
|
**Closed issues:**
|
7
13
|
|
14
|
+
- CLI should check that UAA is available after Ops Manager upgrades [\#29](https://github.com/compozed/ops_manager_cli/issues/29)
|
15
|
+
- When upgrading opsman the token does not reset [\#27](https://github.com/compozed/ops_manager_cli/issues/27)
|
8
16
|
- Support refresh tokens for re-authentication with UAA [\#24](https://github.com/compozed/ops_manager_cli/issues/24)
|
9
|
-
- Upgrading product does not work with opsman\_cli 0.5.0 on opsman 1.9 [\#23](https://github.com/compozed/ops_manager_cli/issues/23)
|
10
17
|
- Allow toggling ops\_manager.log [\#21](https://github.com/compozed/ops_manager_cli/issues/21)
|
11
18
|
|
12
19
|
## [v0.5.1](https://github.com/compozed/ops_manager_cli/tree/v0.5.1) (2017-01-25)
|
13
20
|
[Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.5.0...v0.5.1)
|
14
21
|
|
22
|
+
**Closed issues:**
|
23
|
+
|
24
|
+
- Upgrading product does not work with opsman\_cli 0.5.0 on opsman 1.9 [\#23](https://github.com/compozed/ops_manager_cli/issues/23)
|
25
|
+
|
15
26
|
## [v0.5.0](https://github.com/compozed/ops_manager_cli/tree/v0.5.0) (2017-01-24)
|
16
27
|
[Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.4.1...v0.5.0)
|
17
28
|
|
@@ -21,6 +32,7 @@
|
|
21
32
|
|
22
33
|
**Closed issues:**
|
23
34
|
|
35
|
+
- Upgrade does not merge product installation settings [\#22](https://github.com/compozed/ops_manager_cli/issues/22)
|
24
36
|
- ops\_manager curl -x PUT not working [\#17](https://github.com/compozed/ops_manager_cli/issues/17)
|
25
37
|
- When uploading stemcell it does not show the correct output [\#15](https://github.com/compozed/ops_manager_cli/issues/15)
|
26
38
|
|
@@ -30,6 +42,7 @@
|
|
30
42
|
**Fixed bugs:**
|
31
43
|
|
32
44
|
- Director template generator does not delete UAA sensitive data [\#13](https://github.com/compozed/ops_manager_cli/issues/13)
|
45
|
+
- Product template generator does not delete stemcell metadata properties [\#12](https://github.com/compozed/ops_manager_cli/issues/12)
|
33
46
|
|
34
47
|
## [v0.4.0](https://github.com/compozed/ops_manager_cli/tree/v0.4.0) (2016-10-20)
|
35
48
|
[Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.3.0...v0.4.0)
|
@@ -37,12 +50,14 @@
|
|
37
50
|
**Implemented enhancements:**
|
38
51
|
|
39
52
|
- Improve output for appliance deploy/upgrade [\#11](https://github.com/compozed/ops_manager_cli/issues/11)
|
53
|
+
- Improve output for product deploy/upgrade [\#10](https://github.com/compozed/ops_manager_cli/issues/10)
|
40
54
|
- Run errands when applying changes [\#9](https://github.com/compozed/ops_manager_cli/issues/9)
|
41
55
|
- 1.8 support [\#5](https://github.com/compozed/ops_manager_cli/pull/5) ([bonzofenix](https://github.com/bonzofenix))
|
42
56
|
|
43
57
|
**Fixed bugs:**
|
44
58
|
|
45
59
|
- delete-unused-products command not working [\#8](https://github.com/compozed/ops_manager_cli/issues/8)
|
60
|
+
- Hardcoded user name admin when logging agains ops\_manager [\#2](https://github.com/compozed/ops_manager_cli/issues/2)
|
46
61
|
|
47
62
|
**Closed issues:**
|
48
63
|
|
data/Dockerfile
CHANGED
data/lib/ops_manager/api/base.rb
CHANGED
@@ -25,6 +25,10 @@ class OpsManager
|
|
25
25
|
authenticated_get("/api/v0/staged/products", opts)
|
26
26
|
end
|
27
27
|
|
28
|
+
def get_pending_changes(opts = {})
|
29
|
+
authenticated_get("/api/v0/staged/pending_changes", opts)
|
30
|
+
end
|
31
|
+
|
28
32
|
def get_installation_settings(opts = {})
|
29
33
|
print_green '====> Downloading installation settings ...'
|
30
34
|
res = authenticated_get("/api/installation_settings", opts)
|
@@ -117,7 +121,7 @@ class OpsManager
|
|
117
121
|
|
118
122
|
def get_diagnostic_report
|
119
123
|
authenticated_get("/api/v0/diagnostic_report")
|
120
|
-
rescue Errno::ETIMEDOUT , Errno::EHOSTUNREACH, Net::HTTPFatalError, Net::OpenTimeout
|
124
|
+
rescue Errno::ETIMEDOUT , Errno::EHOSTUNREACH, Net::HTTPFatalError, Net::OpenTimeout, HTTPClient::ConnectTimeoutError
|
121
125
|
nil
|
122
126
|
end
|
123
127
|
|
@@ -153,6 +157,23 @@ class OpsManager
|
|
153
157
|
nil
|
154
158
|
end
|
155
159
|
|
160
|
+
def pending_changes(opts = {})
|
161
|
+
print_green '====> Getting pending changes ...'
|
162
|
+
res = authenticated_get('/api/v0/staged/pending_changes')
|
163
|
+
pendingChanges = JSON.parse(res.body)
|
164
|
+
|
165
|
+
if pendingChanges['product_changes'].count == 0
|
166
|
+
puts "\nNo pending changes"
|
167
|
+
else
|
168
|
+
pendingChanges['product_changes'].each do |product|
|
169
|
+
puts "\n#{product['guid']}"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
say_green 'done'
|
174
|
+
res
|
175
|
+
end
|
176
|
+
|
156
177
|
def username
|
157
178
|
@username ||= OpsManager.get_conf(:username)
|
158
179
|
end
|
@@ -174,7 +195,23 @@ class OpsManager
|
|
174
195
|
@access_token ||= get_token.info['access_token']
|
175
196
|
end
|
176
197
|
|
198
|
+
def wait_for_https_alive(limit)
|
199
|
+
@retry_counter = 0
|
200
|
+
res = nil
|
201
|
+
until(@retry_counter >= limit or (res = check_alive).code.to_i < 400) do
|
202
|
+
sleep 1
|
203
|
+
@retry_counter += 1
|
204
|
+
end
|
205
|
+
res
|
206
|
+
end
|
207
|
+
|
177
208
|
private
|
209
|
+
def check_alive
|
210
|
+
get("/")
|
211
|
+
rescue Net::OpenTimeout, Net::HTTPError, Net::HTTPFatalError, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET => e
|
212
|
+
Net::HTTPInternalServerError.new(1.0, 500, e.inspect)
|
213
|
+
end
|
214
|
+
|
178
215
|
def token_issuer
|
179
216
|
@token_issuer ||= CF::UAA::TokenIssuer.new(
|
180
217
|
"https://#{target}/uaa", 'opsman', nil, skip_ssl_validation: true )
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'fog/aws'
|
2
|
+
require 'ops_manager/appliance/base'
|
3
|
+
|
4
|
+
class OpsManager
|
5
|
+
module Appliance
|
6
|
+
class AWS < Base
|
7
|
+
|
8
|
+
def deploy_vm
|
9
|
+
image_id = ::YAML.load_file(ami_mapping_file)[config[:opts][:region]]
|
10
|
+
|
11
|
+
server = connection.servers.create(
|
12
|
+
block_device_mapping: [{
|
13
|
+
'DeviceName' => '/dev/xvda',
|
14
|
+
'Ebs.VolumeSize' => config[:opts][:disk_size_in_gb],
|
15
|
+
}],
|
16
|
+
key_name: config[:opts][:ssh_keypair_name],
|
17
|
+
flavor_id: config[:opts][:instance_type],
|
18
|
+
subnet_id: config[:opts][:subnet_id],
|
19
|
+
image_id: image_id,
|
20
|
+
private_ip_address: config[:ip],
|
21
|
+
security_group_ids: security_group_ids,
|
22
|
+
availability_zone: config[:opts][:availability_zone],
|
23
|
+
iam_instance_profile_name: config[:opts][:instance_profile_name],
|
24
|
+
tags: {
|
25
|
+
'Name' => vm_name,
|
26
|
+
}
|
27
|
+
)
|
28
|
+
server.wait_for { ready? }
|
29
|
+
return server
|
30
|
+
end
|
31
|
+
|
32
|
+
def stop_current_vm(name)
|
33
|
+
server = connection.servers.all("private-ip-address" => config[:ip], "tag:Name" => name).first
|
34
|
+
if ! server
|
35
|
+
fail "VM not found matching IP '#{config[:ip]}', named '#{name}'"
|
36
|
+
end
|
37
|
+
server.stop
|
38
|
+
server.wait_for { server.state == "stopped" }
|
39
|
+
|
40
|
+
# Create ami of stopped server
|
41
|
+
response = connection.create_image(server.id, "#{name}-backup", "Backup of #{name}")
|
42
|
+
image = connection.images.get( response.data[:body]['imageId'])
|
43
|
+
image.wait_for { image.state == "available" }
|
44
|
+
if image.state != "available"
|
45
|
+
fail "Error creating backup AMI, bailing out before destroying the VM"
|
46
|
+
end
|
47
|
+
|
48
|
+
puts "Saved #{name} to AMI #{image.id} (#{name}-backup) for safe-keeping"
|
49
|
+
|
50
|
+
server.destroy
|
51
|
+
if !Fog.mocking?
|
52
|
+
server.wait_for { server.state == 'terminated' }
|
53
|
+
else
|
54
|
+
# Fog's mock doesn't support transitioning state from terminating -> terminated
|
55
|
+
# so we have to hack this here
|
56
|
+
server.wait_for { server.state == 'terminating' }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def ami_mapping_file
|
62
|
+
Dir.glob(config[:opts][:ami_mapping_file]).first
|
63
|
+
end
|
64
|
+
|
65
|
+
def security_group_ids
|
66
|
+
config[:opts][:security_groups].collect do |sg|
|
67
|
+
connection.security_groups.get(sg).group_id
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def connection
|
72
|
+
if config[:opts][:use_iam_profile]
|
73
|
+
@connection ||= Fog::Compute.new({
|
74
|
+
provider: config[:provider],
|
75
|
+
use_iam_profile: config[:opts][:use_iam_profile],
|
76
|
+
aws_access_key_id: "",
|
77
|
+
aws_secret_access_key: "",
|
78
|
+
})
|
79
|
+
else
|
80
|
+
@connection ||= Fog::Compute.new({
|
81
|
+
provider: config[:provider],
|
82
|
+
aws_access_key_id: config[:opts][:access_key],
|
83
|
+
aws_secret_access_key: config[:opts][:secret_key],
|
84
|
+
})
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
class OpsManager
|
3
|
+
module Appliance
|
4
|
+
class Base
|
5
|
+
attr_reader :config
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
end
|
10
|
+
def deploy_vm
|
11
|
+
raise NotImplementedError.new("You must implement deploy_vm.")
|
12
|
+
end
|
13
|
+
def stop_current_vm(name)
|
14
|
+
raise NotImplementedError.new("You must implement stop_current_vm.")
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def vm_name
|
19
|
+
@vm_name ||= "#{config[:name]}-#{config[:desired_version]}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rbvmomi'
|
2
|
+
require "uri"
|
3
|
+
require 'shellwords'
|
4
|
+
require "ops_manager/logging"
|
5
|
+
require 'ops_manager/appliance/base'
|
6
|
+
|
7
|
+
class OpsManager
|
8
|
+
module Appliance
|
9
|
+
class Vsphere < Base
|
10
|
+
include OpsManager::Logging
|
11
|
+
attr_reader :config
|
12
|
+
|
13
|
+
def deploy_vm
|
14
|
+
print '====> Deploying ova ...'.green
|
15
|
+
vcenter_target= "vi://#{vcenter_username}:#{vcenter_password}@#{config[:opts][:vcenter][:host]}/#{config[:opts][:vcenter][:datacenter]}/host/#{config[:opts][:vcenter][:cluster]}"
|
16
|
+
cmd = "echo yes | ovftool --acceptAllEulas --noSSLVerify --powerOn --X:waitForIp --net:\"Network 1=#{config[:opts][:portgroup]}\" --name=#{vm_name} -ds=#{config[:opts][:datastore]} --prop:ip0=#{config[:ip]} --prop:netmask0=#{config[:opts][:netmask]} --prop:gateway=#{config[:opts][:gateway]} --prop:DNS=#{config[:opts][:dns]} --prop:ntp_servers=#{config[:opts][:ntp_servers].join(',')} --prop:admin_password=#{config[:password]} #{config[:opts][:ova_path]} #{vcenter_target}"
|
17
|
+
logger.info "Running: #{cmd}"
|
18
|
+
logger.info `#{cmd}`
|
19
|
+
puts 'done'.green
|
20
|
+
end
|
21
|
+
|
22
|
+
def stop_current_vm(name)
|
23
|
+
print "====> Stopping vm #{name} ...".green
|
24
|
+
dc = vim.serviceInstance.find_datacenter(config[:opts][:vcenter][:datacenter])
|
25
|
+
logger.info "finding vm: #{name}"
|
26
|
+
vm = dc.find_vm(name) or fail "VM not found"
|
27
|
+
vm.PowerOffVM_Task.wait_for_completion
|
28
|
+
puts 'done'.green
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def vim
|
33
|
+
RbVmomi::VIM.connect host: config[:opts][:vcenter][:host], user: URI.unescape(config[:opts][:vcenter][:username]), password: URI.unescape(config[:opts][:vcenter][:password]), insecure: true
|
34
|
+
end
|
35
|
+
|
36
|
+
def vcenter_username
|
37
|
+
Shellwords.escape(URI.encode(config[:opts][:vcenter][:username]))
|
38
|
+
end
|
39
|
+
|
40
|
+
def vcenter_password
|
41
|
+
Shellwords.escape(URI.encode(config[:opts][:vcenter][:password]))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
@@ -1,15 +1,18 @@
|
|
1
1
|
require "ops_manager/api/opsman"
|
2
2
|
require "ops_manager/api/pivnet"
|
3
|
-
require 'ops_manager/
|
3
|
+
require 'ops_manager/config/opsman_deployment'
|
4
4
|
require 'fileutils'
|
5
5
|
|
6
6
|
class OpsManager::ApplianceDeployment
|
7
7
|
extend Forwardable
|
8
|
+
attr_reader :config
|
9
|
+
|
8
10
|
def_delegators :pivnet_api, :get_product_releases, :accept_product_release_eula,
|
9
11
|
:get_product_release_files, :download_product_release_file
|
10
|
-
def_delegators :opsman_api, :create_user, :
|
12
|
+
def_delegators :opsman_api, :create_user, :get_installation_assets,
|
11
13
|
:get_installation_settings, :get_diagnostic_report, :upload_installation_assets, :get_ensure_availability,
|
12
|
-
:import_stemcell, :target, :password, :username, :ops_manager_version= , :reset_access_token
|
14
|
+
:import_stemcell, :target, :password, :username, :ops_manager_version= , :reset_access_token, :get_pending_changes,
|
15
|
+
:wait_for_https_alive
|
13
16
|
|
14
17
|
attr_reader :config_file
|
15
18
|
|
@@ -18,35 +21,37 @@ class OpsManager::ApplianceDeployment
|
|
18
21
|
end
|
19
22
|
|
20
23
|
def run
|
21
|
-
OpsManager.set_conf(:target, config
|
22
|
-
OpsManager.set_conf(:username, config
|
23
|
-
OpsManager.set_conf(:password, config
|
24
|
-
OpsManager.set_conf(:pivnet_token, config
|
24
|
+
OpsManager.set_conf(:target, config[:ip])
|
25
|
+
OpsManager.set_conf(:username, config[:username])
|
26
|
+
OpsManager.set_conf(:password, config[:password])
|
27
|
+
OpsManager.set_conf(:pivnet_token, config[:pivnet_token])
|
25
28
|
|
26
|
-
self.extend(OpsManager::Deployments::Vsphere)
|
27
29
|
|
28
30
|
case
|
29
31
|
when current_version.empty?
|
30
|
-
puts "No OpsManager deployed at #{config
|
32
|
+
puts "No OpsManager deployed at #{config[:ip]}. Deploying ...".green
|
31
33
|
deploy
|
32
34
|
create_first_user
|
33
35
|
when current_version < desired_version then
|
34
|
-
puts "OpsManager at #{config
|
36
|
+
puts "OpsManager at #{config[:ip]} version is #{current_version}. Upgrading to #{desired_version} .../".green
|
35
37
|
upgrade
|
36
38
|
when current_version == desired_version then
|
37
|
-
|
39
|
+
if pending_changes?
|
40
|
+
puts "OpsManager at #{config[:ip]} version has pending changes. Applying changes...".green
|
41
|
+
OpsManager::InstallationRunner.trigger!.wait_for_result
|
42
|
+
else
|
43
|
+
puts "OpsManager at #{config[:ip]} version is already #{config[:desired_version]}. Skiping ...".green
|
44
|
+
end
|
38
45
|
end
|
39
46
|
|
40
47
|
puts '====> Finish!'.green
|
41
48
|
end
|
42
49
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
define_method(m) do
|
49
|
-
raise NotImplementedError
|
50
|
+
def appliance
|
51
|
+
@appliance ||= if config[:provider] =~/vsphere/i
|
52
|
+
OpsManager::Appliance::Vsphere.new(config)
|
53
|
+
else
|
54
|
+
OpsManager::Appliance::AWS.new(config)
|
50
55
|
end
|
51
56
|
end
|
52
57
|
|
@@ -57,10 +62,15 @@ class OpsManager::ApplianceDeployment
|
|
57
62
|
end
|
58
63
|
end
|
59
64
|
|
65
|
+
def deploy
|
66
|
+
appliance.deploy_vm
|
67
|
+
wait_for_https_alive 300
|
68
|
+
end
|
69
|
+
|
60
70
|
def upgrade
|
61
71
|
get_installation_assets
|
62
72
|
download_current_stemcells
|
63
|
-
stop_current_vm(
|
73
|
+
appliance.stop_current_vm(current_name)
|
64
74
|
deploy
|
65
75
|
upload_installation_assets
|
66
76
|
wait_for_uaa
|
@@ -113,21 +123,30 @@ class OpsManager::ApplianceDeployment
|
|
113
123
|
list_current_stemcells.each do |stemcell_version|
|
114
124
|
release_id = find_stemcell_release(stemcell_version)
|
115
125
|
accept_product_release_eula('stemcells', release_id )
|
116
|
-
|
126
|
+
stemcell_regex = /vsphere/
|
127
|
+
if config[:provider] == "AWS"
|
128
|
+
stemcell_regex = /aws/
|
129
|
+
end
|
130
|
+
|
131
|
+
file_id, file_name = find_stemcell_file(release_id, stemcell_regex)
|
117
132
|
download_product_release_file('stemcells', release_id, file_id, write_to: "#{current_stemcell_dir}/#{file_name}")
|
118
133
|
end
|
119
134
|
end
|
120
135
|
|
121
136
|
def new_vm_name
|
122
|
-
@new_vm_name ||= "#{config
|
137
|
+
@new_vm_name ||= "#{config[:name]}-#{config[:desired_version]}"
|
123
138
|
end
|
124
139
|
|
125
140
|
def current_version
|
126
141
|
@current_version ||= OpsManager::Semver.new(version_from_diagnostic_report)
|
127
142
|
end
|
128
143
|
|
144
|
+
def current_name
|
145
|
+
@current_name ||= "#{config[:name]}-#{current_version}"
|
146
|
+
end
|
147
|
+
|
129
148
|
def desired_version
|
130
|
-
@desired_version ||= OpsManager::Semver.new(config
|
149
|
+
@desired_version ||= OpsManager::Semver.new(config[:desired_version])
|
131
150
|
end
|
132
151
|
|
133
152
|
def provision_stemcells
|
@@ -167,12 +186,9 @@ class OpsManager::ApplianceDeployment
|
|
167
186
|
end
|
168
187
|
|
169
188
|
def current_vm_name
|
170
|
-
@current_vm_name ||= "#{config
|
189
|
+
@current_vm_name ||= "#{config[:name]}-#{current_version}"
|
171
190
|
end
|
172
191
|
|
173
|
-
def desired_vm_name
|
174
|
-
@desired_vm_name ||= "#{config.name}-#{config.desired_version}"
|
175
|
-
end
|
176
192
|
|
177
193
|
def pivnet_api
|
178
194
|
@pivnet_api ||= OpsManager::Api::Pivnet.new
|
@@ -183,10 +199,10 @@ class OpsManager::ApplianceDeployment
|
|
183
199
|
end
|
184
200
|
|
185
201
|
def config
|
186
|
-
|
187
|
-
@config ||= OpsManager::Configs::OpsmanDeployment.new(parsed_yml)
|
202
|
+
@config ||= OpsManager::Config::OpsmanDeployment.new(YAML.load_file(@config_file))
|
188
203
|
end
|
189
204
|
|
205
|
+
|
190
206
|
def desired_version?(version)
|
191
207
|
!!(desired_version.to_s =~/#{version}/)
|
192
208
|
end
|
@@ -206,4 +222,8 @@ class OpsManager::ApplianceDeployment
|
|
206
222
|
def current_stemcell_dir
|
207
223
|
"/tmp/current_stemcells"
|
208
224
|
end
|
225
|
+
|
226
|
+
def pending_changes?
|
227
|
+
!JSON.parse(get_pending_changes.body).fetch('product_changes').empty?
|
228
|
+
end
|
209
229
|
end
|
data/lib/ops_manager/cli.rb
CHANGED
@@ -72,6 +72,12 @@ class OpsManager
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
+
class PendingChanges < Clamp::Command
|
76
|
+
def execute
|
77
|
+
OpsManager::Api::Opsman.new.pending_changes
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
75
81
|
class DeleteUnusedProducts < Clamp::Command
|
76
82
|
|
77
83
|
def execute
|
@@ -158,6 +164,7 @@ class OpsManager
|
|
158
164
|
subcommand "get-installation-settings", "Gets installation settings", GetInstallationSettings
|
159
165
|
subcommand "get-installation-logs", "Gets installation logs", GetInstallationLogs
|
160
166
|
subcommand "import-stemcell", "Uploads stemcell to OpsManager", ImportStemcell
|
167
|
+
subcommand "pending-changes", "View pending changes in OpsManager", PendingChanges
|
161
168
|
|
162
169
|
end
|
163
170
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
class OpsManager
|
4
|
+
module Config
|
5
|
+
class Base < OpenStruct
|
6
|
+
def initialize(config)
|
7
|
+
super(config.to_symbolize)
|
8
|
+
end
|
9
|
+
|
10
|
+
def validate_presence_of!(*attrs)
|
11
|
+
attrs.each do |attr|
|
12
|
+
raise "missing #{attr} on config" unless self.to_h.has_key?(attr)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def expand_path_for!(*attrs)
|
17
|
+
attrs.each do |attr|
|
18
|
+
path = self[attr]
|
19
|
+
self[attr] = if path =~ %r{^file://}
|
20
|
+
path = Dir.glob(path.gsub!('file://','')).first
|
21
|
+
"file://#{path}"
|
22
|
+
else
|
23
|
+
Dir.glob(path).first
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Hash
|
32
|
+
def to_symbolize
|
33
|
+
Hash[self.map do |k, v|
|
34
|
+
if v.kind_of?(Hash)
|
35
|
+
[k.to_sym, v.to_symbolize]
|
36
|
+
else
|
37
|
+
[k.to_sym, v]
|
38
|
+
end
|
39
|
+
end]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -6,7 +6,7 @@ class OpsManager
|
|
6
6
|
attr_reader :id
|
7
7
|
|
8
8
|
def trigger!
|
9
|
-
res = trigger_installation(
|
9
|
+
res = trigger_installation( :headers => {"Content-Type"=>"application/json"}, :body => body )
|
10
10
|
@id = JSON.parse(res.body).fetch('install').fetch('id').to_i
|
11
11
|
self
|
12
12
|
end
|
@@ -25,27 +25,19 @@ class OpsManager
|
|
25
25
|
|
26
26
|
private
|
27
27
|
def body
|
28
|
-
@body ||=
|
29
|
-
@body << errands_body
|
30
|
-
@body.join('&')
|
28
|
+
@body ||= {'errands' => errands, 'ignore_warnings' => true }.to_json
|
31
29
|
end
|
32
|
-
|
33
30
|
def opsman_api
|
34
31
|
@opsman_api ||= OpsManager::Api::Opsman.new
|
35
32
|
end
|
36
33
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
post_deploy_errands = post_deploy_errands_for(product_guid)
|
43
|
-
|
44
|
-
if post_deploy_errands.empty?
|
45
|
-
"enabled_errands[#{product_guid}]{}"
|
46
|
-
else
|
47
|
-
post_deploy_errands.collect{ |e| "enabled_errands[#{product_guid}][post_deploy_errands][]=#{e}" }
|
34
|
+
def errands
|
35
|
+
res = { }
|
36
|
+
staged_products_guids.each do |product_guid|
|
37
|
+
errands = errands_for(product_guid).keep_if { |an_errand| an_errand['post_deploy'] }
|
38
|
+
errands.each { |e| res[product_guid] = {'run_post_deploy' => { e['name'] => true}}}
|
48
39
|
end
|
40
|
+
res
|
49
41
|
end
|
50
42
|
|
51
43
|
def staged_products_guids
|
@@ -56,9 +48,6 @@ class OpsManager
|
|
56
48
|
JSON.parse(get_staged_products.body)
|
57
49
|
end
|
58
50
|
|
59
|
-
def post_deploy_errands_for(product_guid)
|
60
|
-
errands_for(product_guid).keep_if{ |errand| errand['post_deploy'] }.map{ |o| o['name']}
|
61
|
-
end
|
62
51
|
|
63
52
|
def errands_for(product_guid)
|
64
53
|
res = get_staged_products_errands(product_guid)
|
@@ -7,6 +7,8 @@ require "ops_manager/semver"
|
|
7
7
|
class OpsManager
|
8
8
|
class ProductDeployment
|
9
9
|
extend Forwardable
|
10
|
+
attr_reader :config
|
11
|
+
|
10
12
|
def_delegators :opsman_api, :current_version, :upload_product, :get_installation_settings,
|
11
13
|
:upgrade_product_installation, :get_installation, :get_available_products, :upload_installation_settings,
|
12
14
|
:trigger_installation, :import_stemcell, :add_staged_products
|
@@ -19,12 +21,12 @@ class OpsManager
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def installation
|
22
|
-
OpsManager::ProductInstallation.find(config
|
24
|
+
OpsManager::ProductInstallation.find(config[:name])
|
23
25
|
end
|
24
26
|
|
25
27
|
def run
|
26
|
-
OpsManager.target_and_login(config
|
27
|
-
import_stemcell(config
|
28
|
+
OpsManager.target_and_login(config[:target], config[:username], config[:password])
|
29
|
+
import_stemcell(config[:stemcell])
|
28
30
|
|
29
31
|
case
|
30
32
|
when installation.nil? || forced_deployment?
|
@@ -37,15 +39,15 @@ class OpsManager
|
|
37
39
|
end
|
38
40
|
|
39
41
|
def desired_version
|
40
|
-
Semver.new(config
|
42
|
+
Semver.new(config[:desired_version])
|
41
43
|
end
|
42
44
|
|
43
45
|
def upload
|
44
46
|
print "====> Uploading product ...".green
|
45
|
-
if ProductDeployment.exists?(config
|
47
|
+
if ProductDeployment.exists?(config[:name], config[:desired_version])
|
46
48
|
puts "product already exists".green
|
47
|
-
elsif config
|
48
|
-
upload_product(config
|
49
|
+
elsif config[:filepath]
|
50
|
+
upload_product(config[:filepath])
|
49
51
|
puts "done".green
|
50
52
|
else
|
51
53
|
puts "no filepath provided, skipping product upload.".green
|
@@ -57,9 +59,9 @@ class OpsManager
|
|
57
59
|
puts "====> Skipping as this product has a pending installation!".red
|
58
60
|
return
|
59
61
|
end
|
60
|
-
puts "====> Upgrading #{config
|
62
|
+
puts "====> Upgrading #{config[:name]} version from #{installation.current_version.to_s} to #{config[:desired_version]}...".green
|
61
63
|
upload
|
62
|
-
upgrade_product_installation(installation.guid, config
|
64
|
+
upgrade_product_installation(installation.guid, config[:desired_version])
|
63
65
|
merge_product_installation_settings
|
64
66
|
OpsManager::InstallationRunner.trigger!.wait_for_result
|
65
67
|
|
@@ -68,12 +70,12 @@ class OpsManager
|
|
68
70
|
|
69
71
|
def add_to_installation
|
70
72
|
unless installation
|
71
|
-
add_staged_products(config
|
73
|
+
add_staged_products(config[:name], config[:desired_version])
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
75
77
|
def deploy
|
76
|
-
puts "====> Deploying #{config
|
78
|
+
puts "====> Deploying #{config[:name]} version #{config[:desired_version]}...".green
|
77
79
|
upload
|
78
80
|
add_to_installation
|
79
81
|
merge_product_installation_settings
|
@@ -85,7 +87,7 @@ class OpsManager
|
|
85
87
|
|
86
88
|
def merge_product_installation_settings
|
87
89
|
get_installation_settings({write_to: '/tmp/is.yml'})
|
88
|
-
puts `DEBUG=false spruce merge /tmp/is.yml #{config
|
90
|
+
puts `DEBUG=false spruce merge /tmp/is.yml #{config[:installation_settings_file]} > /tmp/new_is.yml`
|
89
91
|
upload_installation_settings('/tmp/new_is.yml')
|
90
92
|
end
|
91
93
|
|
@@ -96,7 +98,7 @@ class OpsManager
|
|
96
98
|
|
97
99
|
private
|
98
100
|
def desired_version
|
99
|
-
@desired_version ||= OpsManager::Semver.new(config
|
101
|
+
@desired_version ||= OpsManager::Semver.new(config[:desired_version])
|
100
102
|
end
|
101
103
|
|
102
104
|
def forced_deployment?
|
@@ -108,7 +110,7 @@ class OpsManager
|
|
108
110
|
end
|
109
111
|
|
110
112
|
def config
|
111
|
-
OpsManager::
|
113
|
+
OpsManager::Config::ProductDeployment.new(::YAML.load_file(@config_file))
|
112
114
|
end
|
113
115
|
end
|
114
116
|
end
|
data/lib/ops_manager/version.rb
CHANGED
data/lib/ops_manager.rb
CHANGED
@@ -83,9 +83,10 @@ end
|
|
83
83
|
|
84
84
|
require "ops_manager/version"
|
85
85
|
require "ops_manager/semver"
|
86
|
-
require "ops_manager/
|
87
|
-
require
|
88
|
-
require 'ops_manager/
|
86
|
+
require "ops_manager/appliance/vsphere"
|
87
|
+
require "ops_manager/appliance/aws"
|
88
|
+
require 'ops_manager/config/product_deployment'
|
89
|
+
require 'ops_manager/config/opsman_deployment'
|
89
90
|
require "ops_manager/cli"
|
90
91
|
require "ops_manager/errors"
|
91
92
|
require "net/https"
|
data/ops_manager.gemspec
CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_dependency "rbvmomi"
|
27
27
|
spec.add_dependency "multipart-post"
|
28
28
|
spec.add_dependency "clamp"
|
29
|
+
spec.add_dependency "fog-aws"
|
29
30
|
spec.add_dependency "net-ping"
|
30
31
|
spec.add_dependency "cf-uaa-lib"
|
31
32
|
spec.add_dependency "session_config"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ops_manager_cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- CompoZed
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: fog-aws
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: net-ping
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -218,12 +232,15 @@ files:
|
|
218
232
|
- lib/ops_manager/api/base.rb
|
219
233
|
- lib/ops_manager/api/opsman.rb
|
220
234
|
- lib/ops_manager/api/pivnet.rb
|
235
|
+
- lib/ops_manager/appliance/aws.rb
|
236
|
+
- lib/ops_manager/appliance/base.rb
|
237
|
+
- lib/ops_manager/appliance/vsphere.rb
|
221
238
|
- lib/ops_manager/appliance_deployment.rb
|
222
239
|
- lib/ops_manager/cli.rb
|
240
|
+
- lib/ops_manager/config/base.rb
|
241
|
+
- lib/ops_manager/config/opsman_deployment.rb
|
242
|
+
- lib/ops_manager/config/product_deployment.rb
|
223
243
|
- lib/ops_manager/configs/base.rb
|
224
|
-
- lib/ops_manager/configs/opsman_deployment.rb
|
225
|
-
- lib/ops_manager/configs/product_deployment.rb
|
226
|
-
- lib/ops_manager/deployments/vsphere.rb
|
227
244
|
- lib/ops_manager/director_template_generator.rb
|
228
245
|
- lib/ops_manager/errors.rb
|
229
246
|
- lib/ops_manager/installation.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'ops_manager/configs/base'
|
2
|
-
|
3
|
-
class OpsManager
|
4
|
-
class Configs
|
5
|
-
class ProductDeployment < Base
|
6
|
-
def initialize(config)
|
7
|
-
super(config)
|
8
|
-
validate_presence_of!(:name, :desired_version)
|
9
|
-
end
|
10
|
-
|
11
|
-
def stemcell
|
12
|
-
find_full_path(@config['stemcell'])
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'rbvmomi'
|
2
|
-
require "uri"
|
3
|
-
require 'shellwords'
|
4
|
-
require "ops_manager/logging"
|
5
|
-
|
6
|
-
class OpsManager
|
7
|
-
module Deployments
|
8
|
-
module Vsphere
|
9
|
-
include OpsManager::Logging
|
10
|
-
|
11
|
-
def deploy_vm(name, ip)
|
12
|
-
print '====> Deploying ova ...'.green
|
13
|
-
vcenter_target= "vi://#{vcenter_username}:#{vcenter_password}@#{config.opts['vcenter']['host']}/#{config.opts['vcenter']['datacenter']}/host/#{config.opts['vcenter']['cluster']}"
|
14
|
-
cmd = "echo yes | ovftool --acceptAllEulas --noSSLVerify --powerOn --X:waitForIp --net:\"Network 1=#{config.opts['portgroup']}\" --name=#{name} -ds=#{config.opts['datastore']} --prop:ip0=#{ip} --prop:netmask0=#{config.opts['netmask']} --prop:gateway=#{config.opts['gateway']} --prop:DNS=#{config.opts['dns']} --prop:ntp_servers=#{config.opts['ntp_servers'].join(',')} --prop:admin_password=#{config.password} #{config.opts['ova_path']} #{vcenter_target}"
|
15
|
-
logger.info "Running: #{cmd}"
|
16
|
-
logger.info `#{cmd}`
|
17
|
-
puts 'done'.green
|
18
|
-
end
|
19
|
-
|
20
|
-
def stop_current_vm(name)
|
21
|
-
print "====> Stopping vm #{name} ...".green
|
22
|
-
dc = vim.serviceInstance.find_datacenter(config.opts['vcenter']['datacenter'])
|
23
|
-
logger.info "finding vm: #{name}"
|
24
|
-
vm = dc.find_vm(name) or fail "VM not found"
|
25
|
-
vm.PowerOffVM_Task.wait_for_completion
|
26
|
-
puts 'done'.green
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
def vim
|
31
|
-
RbVmomi::VIM.connect host: config.opts['vcenter']['host'], user: URI.unescape(config.opts['vcenter']['username']), password: URI.unescape(config.opts['vcenter']['password']), insecure: true
|
32
|
-
end
|
33
|
-
|
34
|
-
def vcenter_username
|
35
|
-
Shellwords.escape(URI.encode(config.opts['vcenter']['username']))
|
36
|
-
end
|
37
|
-
|
38
|
-
def vcenter_password
|
39
|
-
Shellwords.escape(URI.encode(config.opts['vcenter']['password']))
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
|