jellyfish-manageiq 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +202 -0
- data/README.md +109 -0
- data/Rakefile +25 -0
- data/app/assets/images/jellyfish_manageiq/products/apache.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/aws_ec2.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/aws_rds.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/aws_s3.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/bugzilla.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/confluence.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/database.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/dna.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/exchange.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/f5.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/firewall.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/hadoop.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/java.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/jira.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/kb.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/man.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/mean.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/mssql.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/netapp.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/oracle.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/php.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/postgresql.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/rails.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/redhat.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/teradata.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/ubuntu.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/windows.png +0 -0
- data/app/assets/images/jellyfish_manageiq/products/woman.png +0 -0
- data/app/assets/javascripts/jellyfish_manageiq/application.js +13 -0
- data/app/assets/javascripts/jellyfish_manageiq/products_admin_controller.js +63 -0
- data/app/assets/stylesheets/jellyfish_manageiq/application.css +15 -0
- data/app/controllers/manageiq/automate_controller.rb +61 -0
- data/app/controllers/manageiq/order_items_controller.rb +64 -0
- data/app/helpers/application_helper.rb +2 -0
- data/app/models/manage_iq_client.rb +12 -0
- data/app/models/manage_iq_client/base.rb +61 -0
- data/app/models/manage_iq_client/cluster.rb +9 -0
- data/app/models/manage_iq_client/datastore.rb +9 -0
- data/app/models/manage_iq_client/host.rb +9 -0
- data/app/models/manage_iq_client/policy.rb +9 -0
- data/app/models/manage_iq_client/policy_profile.rb +9 -0
- data/app/models/manage_iq_client/provider.rb +9 -0
- data/app/models/manage_iq_client/resource.rb +82 -0
- data/app/models/manage_iq_client/resource_pool.rb +9 -0
- data/app/models/manage_iq_client/server.rb +34 -0
- data/app/models/manage_iq_client/service.rb +9 -0
- data/app/models/manage_iq_client/service_catalog.rb +9 -0
- data/app/models/manage_iq_client/service_template.rb +9 -0
- data/app/models/manage_iq_client/template.rb +25 -0
- data/app/models/manage_iq_client/virtual_machine.rb +27 -0
- data/app/models/manage_iq_client/zone.rb +9 -0
- data/app/policies/manageiq/order_item_policy.rb +16 -0
- data/app/views/manageiq/automate/catalog_item_initialization.html.erb +0 -0
- data/app/views/manageiq/automate/create_chef_node.html.erb +97 -0
- data/app/views/manageiq/automate/create_ec2.html.erb +140 -0
- data/app/views/manageiq/automate/create_rds.html.erb +146 -0
- data/app/views/manageiq/automate/create_s3.html.erb +100 -0
- data/app/views/manageiq/automate/create_ses.html.erb +114 -0
- data/app/views/manageiq/automate/create_vmware_vm.html.erb +102 -0
- data/app/views/manageiq/automate/provision_rds.html.erb +130 -0
- data/app/views/manageiq/automate/retire_ec2.html.erb +96 -0
- data/app/views/manageiq/automate/retire_rds.html.erb +117 -0
- data/app/views/manageiq/automate/retire_s3.html.erb +93 -0
- data/app/views/manageiq/automate/retire_ses.html.erb +98 -0
- data/app/views/manageiq/automate/retire_vmware_vm.html.erb +70 -0
- data/app/views/manageiq/automate/update_servicemix_and_chef.html.erb +364 -0
- data/config/initializers/manage_iq_client.rb +9 -0
- data/config/initializers/product_types.rb +6 -0
- data/config/initializers/provisioners.rb +9 -0
- data/config/initializers/task_scheduler.rb +12 -0
- data/config/product_questions/big_data.json +50 -0
- data/config/product_questions/database.json +79 -0
- data/config/product_questions/infrastructure.json +49 -0
- data/config/product_questions/storage.json +57 -0
- data/config/provisioners.json +6 -0
- data/config/routes.rb +38 -0
- data/db/migrate/20150513221625_create_jellyfish_manageiq_database_products.rb +16 -0
- data/db/migrate/20150513221938_create_jellyfish_manageiq_big_data_products.rb +14 -0
- data/db/migrate/20150513222020_create_jellyfish_manageiq_infrastructure_products.rb +13 -0
- data/db/migrate/20150513222056_create_jellyfish_manageiq_storage_products.rb +13 -0
- data/lib/jellyfish/manageiq.rb +34 -0
- data/lib/jellyfish/manageiq/big_data.rb +6 -0
- data/lib/jellyfish/manageiq/databases.rb +6 -0
- data/lib/jellyfish/manageiq/engine.rb +19 -0
- data/lib/jellyfish/manageiq/infrastructure.rb +6 -0
- data/lib/jellyfish/manageiq/provisioner.rb +115 -0
- data/lib/jellyfish/manageiq/storage.rb +6 -0
- data/lib/jellyfish/manageiq/version.rb +5 -0
- data/lib/tasks/pollvms.rake +42 -0
- metadata +360 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
# Description: This MIQ Method deletes an RDS instance
|
2
|
+
# From an instance collection
|
3
|
+
|
4
|
+
require 'aws-sdk'
|
5
|
+
require 'net/http'
|
6
|
+
require 'securerandom'
|
7
|
+
require 'uri/http'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
def send_order_status(referer, headers, status, order_id, information, message = '')
|
11
|
+
path = "/order_items/#{order_id}/provision_update"
|
12
|
+
host = URI.parse(referer).host
|
13
|
+
url = "http://#{host}#{path}"
|
14
|
+
uri = URI.parse(url)
|
15
|
+
|
16
|
+
information = information.merge('provision_status' => status.downcase)
|
17
|
+
$evm.log('info', "send_order_status: Information: #{information}")
|
18
|
+
json = {
|
19
|
+
status: "#{status}",
|
20
|
+
message: "#{message}",
|
21
|
+
info: information
|
22
|
+
}
|
23
|
+
$evm.log('info', "send_order_status: Information #{json}")
|
24
|
+
begin
|
25
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
26
|
+
request = Net::HTTP::Put.new(uri.path)
|
27
|
+
request.content_type = 'application/json'
|
28
|
+
request.body = json.to_json
|
29
|
+
response = http.request(request)
|
30
|
+
$evm.log('info', "send_order_status: HTTP Response code: #{response.code}")
|
31
|
+
$evm.log('info', "send_order_status: HTTP Response message: #{response.message}")
|
32
|
+
rescue StandardError => e
|
33
|
+
$evm.log('error', "send_order_status: Exception caught while sending response back to core: #{e.message}")
|
34
|
+
end
|
35
|
+
end # End of function
|
36
|
+
|
37
|
+
# Retrieve properties from request
|
38
|
+
# MIQ makes product_details into a string.
|
39
|
+
# Must make into a hash
|
40
|
+
product_details = $evm.root['dialog_order_item']
|
41
|
+
order_item_hash = JSON.parse(product_details.gsub("'", '"').gsub('=>', ':'))
|
42
|
+
product_hash = order_item_hash['product_details']
|
43
|
+
order_id = order_item_hash['id']
|
44
|
+
uuid = order_item_hash['uuid']
|
45
|
+
db_instance_id = product_hash['instance_name']
|
46
|
+
snapshot_identifier = product_hash['snapshot_identifier']
|
47
|
+
final_snapshot = Integer(product_hash['final_snapshot'])
|
48
|
+
access_key = product_hash['access_key_id']
|
49
|
+
secret_access_key = product_hash['secret_access_key']
|
50
|
+
host = $evm.root['dialog_referer']
|
51
|
+
headers = [$evm.root['dialog_email'], $evm.root['dialog_token']]
|
52
|
+
|
53
|
+
$evm.log('info', "RDSRetire: snapshot identifier #{snapshot_identifier}")
|
54
|
+
$evm.log('info', "RDSRetire: final snapshot #{final_snapshot}")
|
55
|
+
$evm.log('info', "RDSRetire: DB_Instance_ID: #{db_instance_id}")
|
56
|
+
|
57
|
+
$evm.log('info', 'RDSRetire: Enter retirement method.')
|
58
|
+
rds = AWS::RDS.new(
|
59
|
+
access_key_id: access_key,
|
60
|
+
secret_access_key: secret_access_key
|
61
|
+
)
|
62
|
+
|
63
|
+
# Obtain the selected instance from AWS
|
64
|
+
instance_collection = rds.db_instances
|
65
|
+
instance = instance_collection[db_instance_id]
|
66
|
+
|
67
|
+
info = {
|
68
|
+
'id' => order_id,
|
69
|
+
'uuid' => uuid
|
70
|
+
}
|
71
|
+
|
72
|
+
# Delete the instance
|
73
|
+
if instance.exists?
|
74
|
+
$evm.log('info', 'RDSRetire: Instance exists. Begin retirement.')
|
75
|
+
if final_snapshot == 0
|
76
|
+
begin
|
77
|
+
instance.delete(
|
78
|
+
skip_final_snapshot: true
|
79
|
+
)
|
80
|
+
rescue AWS::RDS::Errors::InvalidDBInstanceState => e
|
81
|
+
$evm.log('error', "RDSRetire: Invalid Instance state: #{e.message}")
|
82
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
83
|
+
exit
|
84
|
+
rescue AWS::RDS::Errors => e
|
85
|
+
$evm.log('error', "RDSRetire: Exception caught when deleting instance: #{e.message}")
|
86
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
87
|
+
exit
|
88
|
+
end
|
89
|
+
elsif final_snapshot == 1
|
90
|
+
begin
|
91
|
+
instance.delete(
|
92
|
+
skip_final_snapshot: false,
|
93
|
+
final_db_snapshot_identifier: snapshot_identifier
|
94
|
+
)
|
95
|
+
rescue AWS::RDS::Errors::InvalidDBInstanceState => e
|
96
|
+
$evm.log('error', "RDSRetire: Invalid Instance state: #{e.message}")
|
97
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
98
|
+
exit
|
99
|
+
rescue AWS::RDS::Errors => e
|
100
|
+
$evm.log('error', "RDSRetire: Exception caught when deleting instance: #{e.message}")
|
101
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
102
|
+
exit
|
103
|
+
end
|
104
|
+
else
|
105
|
+
$evm.log('error', 'RDSRetire: Must specify final snapshot value.')
|
106
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, 'Must specify final snapshot value')
|
107
|
+
end
|
108
|
+
while instance.exists? && instance.status == 'deleting'
|
109
|
+
$evm.log('info', 'RDSRetire: Instance is deleting.')
|
110
|
+
sleep 5
|
111
|
+
end
|
112
|
+
$evm.log('info', 'RDSRetire: Instance deletion complete. Begin payload response.')
|
113
|
+
send_order_status(host, headers, 'OK', order_id, info, 'Instance retired.')
|
114
|
+
else
|
115
|
+
$evm.log('error', "RDSRetire: Instance #{db_instance_id} does not exist.")
|
116
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, 'Instance does not exist')
|
117
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# Description: This MIQ Method destroys an S3 instance
|
2
|
+
# Based off of the criteria selected in the marketplace
|
3
|
+
|
4
|
+
# For use in MIQ under the
|
5
|
+
# For use in Service/Provisioning/StateMachines/Methods/RetireS3
|
6
|
+
|
7
|
+
require 'aws-sdk'
|
8
|
+
require 'uri/http'
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
def send_order_status(referer, headers, status, order_id, information, message = '')
|
12
|
+
path = "/order_items/#{order_id}/provision_update"
|
13
|
+
host = URI.parse(referer).host
|
14
|
+
url = "http://#{host}#{path}"
|
15
|
+
uri = URI.parse(url)
|
16
|
+
|
17
|
+
information = information.merge('provision_status' => status.downcase)
|
18
|
+
$evm.log('info', "send_order_status: Information: #{information}")
|
19
|
+
json = {
|
20
|
+
status: "#{status}",
|
21
|
+
message: "#{message}",
|
22
|
+
info: information
|
23
|
+
}
|
24
|
+
$evm.log('info', "send_order_status: Information #{json}")
|
25
|
+
begin
|
26
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
27
|
+
request = Net::HTTP::Put.new(uri.path)
|
28
|
+
request.content_type = 'application/json'
|
29
|
+
request.body = json.to_json
|
30
|
+
response = http.request(request)
|
31
|
+
$evm.log('info', "send_order_status: HTTP Response code: #{response.code}")
|
32
|
+
$evm.log('info', "send_order_status: HTTP Response message: #{response.message}")
|
33
|
+
rescue StandardError => e
|
34
|
+
$evm.log('error', "send_order_status: Exception caught while sending response back to core: #{e.message}")
|
35
|
+
end
|
36
|
+
end # End of function
|
37
|
+
|
38
|
+
$evm.log('info', 'RetireS3: Enter Method.')
|
39
|
+
|
40
|
+
# Retrieve properties from request
|
41
|
+
# MIQ makes product_details into a string.
|
42
|
+
# Must make into a hash
|
43
|
+
product_details = $evm.root['dialog_order_item']
|
44
|
+
order_item_hash = JSON.parse(product_details.gsub("'", '"').gsub('=>', ':'))
|
45
|
+
product_hash = order_item_hash['product_details']
|
46
|
+
order_id = order_item_hash['id']
|
47
|
+
uuid = order_item_hash['uuid']
|
48
|
+
access_key = product_hash['access_key_id']
|
49
|
+
secret_access_key = product_hash['secret_access_key']
|
50
|
+
bucket_name = product_hash['instance_name']
|
51
|
+
host = $evm.root['dialog_referer']
|
52
|
+
headers = [$evm.root['dialog_email'], $evm.root['dialog_token']]
|
53
|
+
|
54
|
+
S3 = AWS::S3.new(
|
55
|
+
access_key_id: access_key,
|
56
|
+
secret_access_key: secret_access_key
|
57
|
+
)
|
58
|
+
|
59
|
+
$evm.log('info', 'RetireS3: Bucket name: #{bucket_name}')
|
60
|
+
begin
|
61
|
+
info = {
|
62
|
+
'id' => order_id,
|
63
|
+
'uuid' => uuid
|
64
|
+
}
|
65
|
+
bucket = S3.buckets[bucket_name]
|
66
|
+
if bucket.exists?
|
67
|
+
bucket.delete
|
68
|
+
else
|
69
|
+
$evm.log('error', 'Retire S3: Bucket does not exist. ')
|
70
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, 'Bucket does not exist and cannot be deleted')
|
71
|
+
exit
|
72
|
+
end
|
73
|
+
rescue AWS::S3::Errors::InvalidClientTokenId => e
|
74
|
+
$evm.log('error', "RetireS3: Invalid client token exception caught: #{e.message}.")
|
75
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
76
|
+
exit
|
77
|
+
rescue AWS::S3::Errors::InvalidParameterValue => e
|
78
|
+
$evm.log('error', "RetireS3: Invalid parameter exception caught: #{e.message}")
|
79
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
80
|
+
exit
|
81
|
+
rescue AWS::S3::Errors => e
|
82
|
+
$evm.log('error', "RetireS3: AWS S3 exception caught: #{e.message}")
|
83
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
84
|
+
exit
|
85
|
+
rescue StandardError => e
|
86
|
+
$evm.log('error', "RetireS3: General exception caught: #{e.message}")
|
87
|
+
$evm.log('error', "RetireS3: General exception backtrace: #{e.message}")
|
88
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
89
|
+
exit
|
90
|
+
end
|
91
|
+
|
92
|
+
$evm.log('info', 'RetireS3: Bucket deleted successfully.')
|
93
|
+
send_order_status(host, headers, 'OK', order_id, info, 'Instance retired.')
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# Description: This MIQ Method un-verifies e-mail addresses
|
2
|
+
# From an existing SES service
|
3
|
+
|
4
|
+
# For use in MIQ under the
|
5
|
+
# /Provisioning/StateMachines/Methods/CreateSES
|
6
|
+
|
7
|
+
require 'aws-sdk'
|
8
|
+
require 'net/http'
|
9
|
+
require 'uri/http'
|
10
|
+
require 'json'
|
11
|
+
|
12
|
+
$evm.log('info', 'RetireSES: Entering method')
|
13
|
+
|
14
|
+
def send_order_status(referer, headers, status, order_id, information, message = '')
|
15
|
+
path = "/order_items/#{order_id}/provision_update"
|
16
|
+
host = URI.parse(referer).host
|
17
|
+
url = "http://#{host}#{path}"
|
18
|
+
uri = URI.parse(url)
|
19
|
+
|
20
|
+
information = information.merge('provision_status' => status.downcase)
|
21
|
+
$evm.log('info', "send_order_status: Information: #{information}")
|
22
|
+
json = {
|
23
|
+
status: "#{status}",
|
24
|
+
message: "#{message}",
|
25
|
+
info: information
|
26
|
+
}
|
27
|
+
$evm.log('info', "send_order_status: Information #{json}")
|
28
|
+
begin
|
29
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
30
|
+
request = Net::HTTP::Put.new(uri.path)
|
31
|
+
request.content_type = 'application/json'
|
32
|
+
request.body = json.to_json
|
33
|
+
response = http.request(request)
|
34
|
+
$evm.log('info', "send_order_status: HTTP Response code: #{response.code}")
|
35
|
+
$evm.log('info', "send_order_status: HTTP Response message: #{response.message}")
|
36
|
+
rescue StandardError => e
|
37
|
+
$evm.log('error', "send_order_status: Exception caught while sending response back to core: #{e.message}")
|
38
|
+
end
|
39
|
+
end # End of function
|
40
|
+
|
41
|
+
# Retrieve dialog properties
|
42
|
+
# Retrieve properties from request
|
43
|
+
# MIQ makes product_details into a string.
|
44
|
+
# Must make into a hash
|
45
|
+
product_details = $evm.root['dialog_order_item']
|
46
|
+
order_item_hash = JSON.parse(product_details.gsub("'", '"').gsub('=>', ':'))
|
47
|
+
product_hash = order_item_hash['product_details']
|
48
|
+
order_id = order_item_hash['id']
|
49
|
+
uuid = order_item_hash['uuid']
|
50
|
+
access_key = product_hash['access_key_id']
|
51
|
+
secret_access_key = product_hash['secret_access_key']
|
52
|
+
email = product_hash['email']
|
53
|
+
host = $evm.root['dialog_referer']
|
54
|
+
headers = [$evm.root['dialog_email'], $evm.root['dialog_token']]
|
55
|
+
|
56
|
+
AWS.config(
|
57
|
+
access_key_id: access_key,
|
58
|
+
secret_access_key: secret_access_key
|
59
|
+
)
|
60
|
+
|
61
|
+
$evm.log('info', 'RetireSES: create service')
|
62
|
+
|
63
|
+
info = {
|
64
|
+
'id' => order_id,
|
65
|
+
'uuid' => uuid
|
66
|
+
}
|
67
|
+
|
68
|
+
ses = AWS::SimpleEmailService.new
|
69
|
+
|
70
|
+
# Setup a verified sender if a sender was chosen
|
71
|
+
if email != ''
|
72
|
+
begin
|
73
|
+
email_identities = email.split(',')
|
74
|
+
email_identities.each do |e|
|
75
|
+
$evm.log('info', "RetireSES: E-mail Identity: #{e}")
|
76
|
+
ses.identities[e].delete
|
77
|
+
$evm.log('info', 'RetireSES: Email Identity removed.')
|
78
|
+
end
|
79
|
+
rescue AWS::SimpleEmailService::Errors::InvalidClientTokenId => e
|
80
|
+
$evm.log('error', "RetireSES: Exception caught when creating instance: #{e.message}")
|
81
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
82
|
+
exit
|
83
|
+
rescue AWS::SimpleEmailService::Errors::InvalidParameterValue => e
|
84
|
+
$evm.log('error', "RetireSES: Invalid parameter exception caught: #{e.message}")
|
85
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
86
|
+
exit
|
87
|
+
rescue AWS::SimpleEmailService::Errors => e
|
88
|
+
$evm.log('error', "RetireSES: Exception caught: #{e.message}")
|
89
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
90
|
+
exit
|
91
|
+
rescue StandardError => e
|
92
|
+
$evm.log('error', "RetireSES: Exception caught #{e.message}")
|
93
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "#{e.message}")
|
94
|
+
exit
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
send_order_status(host, headers, 'OK', order_id, info, 'Instance retired.')
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# This method will delete a specified VM
|
2
|
+
|
3
|
+
require 'rbvmomi'
|
4
|
+
require 'net/http'
|
5
|
+
require 'uri/http'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
def send_order_status(host, headers, status, order_id, information, message = '')
|
9
|
+
path = "/order_items/#{order_id}/provision_update"
|
10
|
+
url = "http://#{host}#{path}"
|
11
|
+
uri = URI.parse(url)
|
12
|
+
|
13
|
+
information = information.merge('provision_status' => status.downcase)
|
14
|
+
$evm.log('info', "send_order_status: Information: #{information}")
|
15
|
+
json = {
|
16
|
+
status: "#{status}",
|
17
|
+
message: "#{message}",
|
18
|
+
info: information
|
19
|
+
}
|
20
|
+
$evm.log('info', "send_order_status: Information #{json}")
|
21
|
+
begin
|
22
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
23
|
+
request = Net::HTTP::Put.new(uri.path)
|
24
|
+
request.content_type = 'application/json'
|
25
|
+
request.body = json.to_json
|
26
|
+
response = http.request(request)
|
27
|
+
$evm.log('info', "send_order_status: HTTP Response code: #{response.code}")
|
28
|
+
$evm.log('info', "send_order_status: HTTP Response message: #{response.message}")
|
29
|
+
rescue HTTPExceptions => e
|
30
|
+
$evm.log('error', "send_order_status: HTTP Exception caught while sending response back to core: #{e.message}")
|
31
|
+
rescue StandardError => e
|
32
|
+
$evm.log('error', "send_order_status: Exception caught while sending response back to core: #{e.message}")
|
33
|
+
end
|
34
|
+
end # End of function
|
35
|
+
|
36
|
+
# Retrieve all information set from the marketplace
|
37
|
+
product_details = $evm.root['dialog_product_details']
|
38
|
+
$evm.log('info', "CreateVMWareVM: Product Details: #{product_details}")
|
39
|
+
product_hash = JSON.parse(product_details.gsub("'", '"').gsub('=>', ':'))
|
40
|
+
datacenter = product_hash['datacenter']
|
41
|
+
host = product_hash['host']
|
42
|
+
port = Integer(product_hash['port']) unless product_hash['port'].nil || product_hash[port] == ''
|
43
|
+
user = product_hash['user']
|
44
|
+
password = product_hash['password']
|
45
|
+
uuid = product_hash['uuid']
|
46
|
+
order_id = product_hash['id']
|
47
|
+
instance_name = product_hash['instance_name']
|
48
|
+
headers = [$evm.root['dialog_email'], $evm.root['dialog_token']]
|
49
|
+
info = {
|
50
|
+
'id' => order_id,
|
51
|
+
'uuid' => uuid
|
52
|
+
}
|
53
|
+
|
54
|
+
begin
|
55
|
+
$evm.log('info', 'DeleteVMWareVM: Begin')
|
56
|
+
vim = RbVmomi::VIM.connect host: host, port: port, user: user, password: password, insecure: false
|
57
|
+
dc = vim.serviceInstance.find_datacenter(datacenter)
|
58
|
+
$evm.log('info', 'DeleteVMWareVM: Found datacenter')
|
59
|
+
vm = dc.find_vm(instance_name)
|
60
|
+
if vm.nil?
|
61
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, 'Could not find VM')
|
62
|
+
exit
|
63
|
+
end
|
64
|
+
$evm.log('info', 'DeleteVMWareVM: Found VM')
|
65
|
+
vm.Destroy_Task(this: vm)
|
66
|
+
rescue StandardError => e
|
67
|
+
send_order_status(host, headers, 'CRITICAL', order_id, info, "Exception caught while creating VM: #{e.message}")
|
68
|
+
$evm.log('error', "DeleteVMWareVM: Error while deleting VM: #{e.message}")
|
69
|
+
exit
|
70
|
+
end
|
@@ -0,0 +1,364 @@
|
|
1
|
+
#
|
2
|
+
# Description: This miq method will update chef and send back information to servicemix
|
3
|
+
#
|
4
|
+
require 'json'
|
5
|
+
require 'aws-sdk'
|
6
|
+
require 'chef'
|
7
|
+
require 'chef/config'
|
8
|
+
require 'chef/log'
|
9
|
+
require 'chef/rest'
|
10
|
+
require 'chef/http'
|
11
|
+
require 'chef/node'
|
12
|
+
require 'rest-client' # must be after chef/rest
|
13
|
+
require 'erb'
|
14
|
+
|
15
|
+
# =================================
|
16
|
+
# miq connector module
|
17
|
+
# =================================
|
18
|
+
module MiqConnector
|
19
|
+
|
20
|
+
class ServicemixPayload
|
21
|
+
attr_accessor :data, :template
|
22
|
+
|
23
|
+
def initialize(data)
|
24
|
+
# if we want to specify the template in an external file we could get it this way
|
25
|
+
# vs declaring it inline.
|
26
|
+
#@template = File.read(template)
|
27
|
+
|
28
|
+
# We aren't sending the engine tags as of 2014-09-18
|
29
|
+
# "tags": [ <%= item[:tags].map{|i| '"' + i + '"'}.join(',') %> ],
|
30
|
+
|
31
|
+
# status should be one of the following: OK, WARNING, CRITICAL, UNKNOWN
|
32
|
+
@template = %{
|
33
|
+
{
|
34
|
+
"status": "#{data[:status]}",
|
35
|
+
"description": "#{data[:description]}",
|
36
|
+
"order_id":"#{data[:order_id]}",
|
37
|
+
"items": [
|
38
|
+
<% data[:items].each_with_index do |item, index| %>
|
39
|
+
{
|
40
|
+
"order_product_id":"#{data[:order_product_id]}",
|
41
|
+
"mpuuid": "<%= item[:mpuuid] %>",
|
42
|
+
"public_fqdn": "<%=item[:fqdn] %>",
|
43
|
+
"cloudforms_guid": "<%= item[:cloudforms_guid] %>",
|
44
|
+
"public_ip_addr": "<%= item[:public_ip_address] %>",
|
45
|
+
"aws_instance_id": "<%= item[:aws_instance_id] %>",
|
46
|
+
"private_fqdn": "<%= item[:private_fqdn] %>",
|
47
|
+
"private_ip_addr": "<%= item[:private_ip_address] %>",
|
48
|
+
"status": "<%= item[:status] %>",
|
49
|
+
"vmid": "<%= item[:vmid] %>"
|
50
|
+
}<% if index+1 != data[:items].length %>,<% end %>
|
51
|
+
<% end %>
|
52
|
+
]
|
53
|
+
}
|
54
|
+
}
|
55
|
+
@data = data
|
56
|
+
end
|
57
|
+
|
58
|
+
def json()
|
59
|
+
b = binding
|
60
|
+
template = ERB.new(@template, 0, "%<>")
|
61
|
+
return template.result(b)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
class MiqConnector
|
67
|
+
attr_accessor :aws_instance_data, :miq_request_data
|
68
|
+
|
69
|
+
def log(msg)
|
70
|
+
#@logger_file.puts(msg)
|
71
|
+
$evm.log("info", msg)
|
72
|
+
end
|
73
|
+
|
74
|
+
def initialize(miq_request_data)
|
75
|
+
@miq_request_data = miq_request_data
|
76
|
+
#@logger_file = File.open('/home/miqbuilder/miq_connector.log', 'a')
|
77
|
+
|
78
|
+
raise "Unexpected/Incomplete configuration" if !self.is_configured?
|
79
|
+
# extract the vm ids
|
80
|
+
aws_vm_ids = @miq_request_data[:aws_vms].map {|vm| vm.uid_ems}
|
81
|
+
log("Loading AWS data ....")
|
82
|
+
@aws_instance_data = load_amazon_instance_collection_info(aws_vm_ids)
|
83
|
+
log("AWS data loaded")
|
84
|
+
log("== AWS data ===============")
|
85
|
+
log(@aws_instance_data.inspect)
|
86
|
+
log("== END AWS data ===============")
|
87
|
+
end
|
88
|
+
|
89
|
+
def process_order
|
90
|
+
# json template for servicemix
|
91
|
+
data = {}
|
92
|
+
data[:status] = "completed"
|
93
|
+
data[:description] = "Order Provisioned Successfully"
|
94
|
+
data[:order_product_id] = @miq_request_data[:order_product_id]
|
95
|
+
data[:order_id] = @miq_request_data[:order_id]
|
96
|
+
items = [] # this should only be one item
|
97
|
+
|
98
|
+
if @aws_instance_data.data.has_key?(:instances_set)
|
99
|
+
puts "has 'instances_set'"
|
100
|
+
instances = @aws_instance_data.data[:instances_set]
|
101
|
+
else
|
102
|
+
instances = @aws_instance_data.data[:instance_index]
|
103
|
+
end
|
104
|
+
|
105
|
+
# this should only be a single instance
|
106
|
+
instances.each do |aws_i|
|
107
|
+
aws_instance = aws_i[1]
|
108
|
+
# find the aws vm object that matches the current aws instance
|
109
|
+
miq_vm = @miq_request_data[:aws_vms].find{|e| e.uid_ems == aws_instance[:instance_id]}
|
110
|
+
|
111
|
+
# must be done in the loop because we have to update each chef server indvidually
|
112
|
+
update_chef(aws_instance[:private_ip_address], @miq_request_data[:chef_roles])
|
113
|
+
|
114
|
+
# build the item array of hashes for servicemix
|
115
|
+
item = {
|
116
|
+
:order_product_id => @miq_request_data[:order_product_id],
|
117
|
+
:mpuuid => @miq_request_data[:mpuuid],
|
118
|
+
:public_fqdn => aws_instance[:dns_name],
|
119
|
+
:cloudforms_guid => miq_vm.guid,
|
120
|
+
:public_ip_address => aws_instance[:ip_address],
|
121
|
+
:aws_instance_id => aws_instance[:instance_id],
|
122
|
+
:private_fqdn => aws_instance[:private_dns_name],
|
123
|
+
:private_ip_address => aws_instance[:private_ip_address],
|
124
|
+
:chef_roles => @miq_request_data[:chef_roles],
|
125
|
+
:ip_addr => aws_instance[:ip_address],
|
126
|
+
:vmid => miq_vm.id,
|
127
|
+
:status => "completed"
|
128
|
+
|
129
|
+
}
|
130
|
+
|
131
|
+
# add the item to items array for this order
|
132
|
+
items.push item
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
data[:items] = items
|
137
|
+
|
138
|
+
# inject the data into the template
|
139
|
+
servicemix_payload = ServicemixPayload.new(data)
|
140
|
+
servicemix_data = servicemix_payload.json()
|
141
|
+
|
142
|
+
# send the data off to servicemix with all of the instance data
|
143
|
+
log(servicemix_data.to_json)
|
144
|
+
update_servicemix(servicemix_data)
|
145
|
+
end
|
146
|
+
|
147
|
+
def is_configured?
|
148
|
+
if (is_chef_configured? && is_servicemix_configured? && is_amazon_configured?)
|
149
|
+
return true
|
150
|
+
else
|
151
|
+
return false
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def is_chef_configured?
|
156
|
+
if !@miq_request_data[:chef_server_url].nil? && !@miq_request_data[:chef_client_name].nil? && !@miq_request_data[:chef_signing_key_filename].nil?
|
157
|
+
# TODO test to see that pem file is accessible
|
158
|
+
return true
|
159
|
+
else
|
160
|
+
return false
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def is_servicemix_configured?
|
165
|
+
if !@miq_request_data[:servicemix_url].nil?
|
166
|
+
return true
|
167
|
+
else
|
168
|
+
return false
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# this should probably be more generic for any cloud provider configuration
|
173
|
+
def is_amazon_configured?
|
174
|
+
if !@miq_request_data[:aws_access_key_id].nil? && !@miq_request_data[:aws_secret_access_key].nil?
|
175
|
+
return true
|
176
|
+
else
|
177
|
+
return false
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def chef_node_name(private_ip_address)
|
182
|
+
chef_name = "ip-#{private_ip_address.gsub('.','-')}"
|
183
|
+
return chef_name
|
184
|
+
end
|
185
|
+
|
186
|
+
def load_amazon_instance_collection_info(instance_ids)
|
187
|
+
ec2_client = AWS::EC2::Client.new(
|
188
|
+
:access_key_id => @miq_request_data[:aws_access_key_id],
|
189
|
+
:secret_access_key => @miq_request_data[:aws_secret_access_key]
|
190
|
+
)
|
191
|
+
log("== EC2 Client created")
|
192
|
+
return ec2_client.describe_instances(:instance_ids => instance_ids)
|
193
|
+
end
|
194
|
+
|
195
|
+
def update_chef(private_ip, roles)
|
196
|
+
begin
|
197
|
+
rest = Chef::REST.new(@miq_request_data[:chef_server_url], @miq_request_data[:chef_client_name], @miq_request_data[:chef_signing_key_filename])
|
198
|
+
resource = "nodes/#{chef_node_name(private_ip)}"
|
199
|
+
log("== Chef Node Name")
|
200
|
+
log(resource)
|
201
|
+
log("== End Chef Node Name")
|
202
|
+
|
203
|
+
log("== Chef Roles ============================")
|
204
|
+
log(roles.inspect)
|
205
|
+
log("Roles is a: #{roles.class}")
|
206
|
+
log("== End Chef Roles ============================")
|
207
|
+
|
208
|
+
chef_node = rest.get_rest(resource)
|
209
|
+
|
210
|
+
log("== Chef Data Fetched ============================")
|
211
|
+
log(chef_node.to_json)
|
212
|
+
log("== End Chef Data Fetched============================")
|
213
|
+
|
214
|
+
#reformat the role list to use the format "role[rolname]"
|
215
|
+
roles.map {|r| "role[#{r}]"}
|
216
|
+
|
217
|
+
# set the roles
|
218
|
+
chef_node.run_list(roles)
|
219
|
+
|
220
|
+
log("== Updated Chef Data ============================")
|
221
|
+
log(chef_node.to_json)
|
222
|
+
log("== End Updated Chef Data ============================")
|
223
|
+
|
224
|
+
|
225
|
+
# update this chef node with the roles
|
226
|
+
rest.put(resource, chef_node)
|
227
|
+
|
228
|
+
updated_node = rest.get(resource)
|
229
|
+
|
230
|
+
log("== Retrieved Chef Data ============================")
|
231
|
+
log(updated_node.to_json)
|
232
|
+
log("== End Retrieved Chef Data ============================")
|
233
|
+
log("== Chef successfully updated")
|
234
|
+
|
235
|
+
return chef_node.to_json
|
236
|
+
rescue => err
|
237
|
+
failed_msg = %{
|
238
|
+
{
|
239
|
+
"status": "WARNING",
|
240
|
+
"description": "There was a problem updating chef.",
|
241
|
+
"order_id":"#{@miq_request_data[:order_id]}",
|
242
|
+
"items": [{
|
243
|
+
"order_product_id": "#{@miq_request_data[:order_product_id]}",
|
244
|
+
"mpuuid": "none",
|
245
|
+
"public_fqdn": "none",
|
246
|
+
"cloudforms_guid": "none",
|
247
|
+
"public_ip_addr": "none",
|
248
|
+
"aws_instance_id": "none",
|
249
|
+
"private_fqdn": "",
|
250
|
+
"private_ip_addr": "",
|
251
|
+
"status": "failed",
|
252
|
+
"vmid": "none"
|
253
|
+
}]
|
254
|
+
}
|
255
|
+
}
|
256
|
+
|
257
|
+
update_servicemix(failed_msg)
|
258
|
+
log(err.message)
|
259
|
+
log(err.backtrace.inspect)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def update_servicemix(json_to_post)
|
264
|
+
begin
|
265
|
+
resp = RestClient.post(@miq_request_data[:servicemix_url], json_to_post, :content_type => :json){|response, request, result, &block|
|
266
|
+
log("== Data sent to servicemix ============================")
|
267
|
+
log(json_to_post)
|
268
|
+
log("== End Data sent to servicemix ============================")
|
269
|
+
case response.code
|
270
|
+
|
271
|
+
when 200
|
272
|
+
log("servicemix returned code 200 and updated successfully")
|
273
|
+
else
|
274
|
+
log("servicemix returned code #{response.code}")
|
275
|
+
end
|
276
|
+
|
277
|
+
}
|
278
|
+
rescue => e
|
279
|
+
log("== Problem sending data to servicemix")
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# =================================
|
287
|
+
# end miq connector module
|
288
|
+
# =================================
|
289
|
+
|
290
|
+
begin
|
291
|
+
|
292
|
+
@method = '======= Update servicemix and Chef =========='
|
293
|
+
@debug = true
|
294
|
+
|
295
|
+
$evm.log("info", "#{@method}")
|
296
|
+
|
297
|
+
if ($evm.root['dialog_chef_roles'].nil?)
|
298
|
+
chef_roles = ['boozallen']
|
299
|
+
else
|
300
|
+
# extract the chef roles from the json
|
301
|
+
chef_roles = JSON.parse($evm.root['dialog_chef_roles'])
|
302
|
+
# make sure that the roles include "boozallen"
|
303
|
+
chef_roles.unshift('boozallen')
|
304
|
+
end
|
305
|
+
|
306
|
+
# build the data that the miq connector class need to be instantiated
|
307
|
+
miq_request_data = {
|
308
|
+
:chef_server_url => $evm.root['dialog_chef_url'],
|
309
|
+
:chef_client_name => $evm.root['dialog_chef_client_name'],
|
310
|
+
:chef_signing_key_filename => $evm.root['dialog_chef_signing_key_filename'],
|
311
|
+
:servicemix_url => $evm.root['dialog_servicemix_url'],
|
312
|
+
:order_id => $evm.root['dialog_order_id'],
|
313
|
+
:order_product_id => $evm.root['dialog_order_product_id'],
|
314
|
+
:aws_access_key_id => $evm.root['dialog_aws_access_id'],
|
315
|
+
:aws_secret_access_key => $evm.root['dialog_aws_secret_access_key'],
|
316
|
+
:aws_vms => $evm.root['service_template_provision_task'].destination.vms,
|
317
|
+
:chef_roles => chef_roles,
|
318
|
+
:mpuuid => $evm.root['dialog_mpuuid']
|
319
|
+
}
|
320
|
+
|
321
|
+
# Get current provisioning status
|
322
|
+
task = $evm.root['service_template_provision_task']
|
323
|
+
task_status = task['status']
|
324
|
+
|
325
|
+
$evm.log("info", "Task Status==#{task_status}")
|
326
|
+
dpi = MiqConnector::MiqConnector.new(miq_request_data)
|
327
|
+
$evm.log("info", "dpi object instantiated successfully")
|
328
|
+
|
329
|
+
# if the order wasn't provisioned return
|
330
|
+
if task.status != 'ok'
|
331
|
+
$evm.log("warn", "Provision Failed for order: #{$evm.root['dialog_order_id']}, order_product_id:#{$evm.root['dialog_order_product_id']}")
|
332
|
+
failed_msg = %{
|
333
|
+
{
|
334
|
+
"status": "failed",
|
335
|
+
"description": "The order has failed",
|
336
|
+
"order_id":"#{$evm.root['dialog_order_id']}",
|
337
|
+
"items": [{
|
338
|
+
"order_product_id": "#{@miq_request_data[:order_product_id]}",
|
339
|
+
"mpuuid": "none",
|
340
|
+
"public_fqdn": "none",
|
341
|
+
"cloudforms_guid": "none",
|
342
|
+
"public_ip_addr": "none",
|
343
|
+
"aws_instance_id": "none",
|
344
|
+
"private_fqdn": "",
|
345
|
+
"private_ip_addr": "",
|
346
|
+
"status": "failed",
|
347
|
+
"vmid": "none"
|
348
|
+
}]
|
349
|
+
}
|
350
|
+
}
|
351
|
+
dpi.update_servicemix(failed_msg)
|
352
|
+
else
|
353
|
+
dpi.process_order()
|
354
|
+
end
|
355
|
+
$evm.log("info", "servicemix and Chef updated successfully.")
|
356
|
+
|
357
|
+
|
358
|
+
|
359
|
+
exit MIQ_OK
|
360
|
+
|
361
|
+
rescue => err
|
362
|
+
$evm.log("error", "#{@method} - [#{err}]\n#{err.backtrace.join("\n")}")
|
363
|
+
exit MIQ_STOP
|
364
|
+
end
|