deltacloud-core 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (242) hide show
  1. data/LICENSE +145 -0
  2. data/NOTICE +10 -1
  3. data/Rakefile +50 -2
  4. data/bin/deltacloudd +111 -14
  5. data/config/addresses.xml +14 -0
  6. data/config/condor.yaml +30 -0
  7. data/config/drivers/azure.yaml +3 -0
  8. data/config/drivers/condor.yaml +3 -0
  9. data/config/{drivers.yaml → drivers/ec2.yaml} +5 -34
  10. data/config/drivers/eucalyptus.yaml +8 -0
  11. data/config/drivers/gogrid.yaml +3 -0
  12. data/config/drivers/mock.yaml +3 -0
  13. data/config/drivers/opennebula.yaml +4 -0
  14. data/config/drivers/rackspace.yaml +3 -0
  15. data/config/drivers/rhevm.yaml +3 -0
  16. data/config/drivers/rimuhosting.yaml +3 -0
  17. data/config/drivers/sbc.yaml +2 -0
  18. data/config/drivers/terremark.yaml +3 -0
  19. data/config/drivers/vsphere.yaml +8 -0
  20. data/deltacloud-core.gemspec +13 -5
  21. data/deltacloud.rb +4 -2
  22. data/lib/deltacloud/backend_capability.rb +2 -2
  23. data/lib/deltacloud/base_driver/base_driver.rb +23 -52
  24. data/lib/deltacloud/base_driver/exceptions.rb +168 -0
  25. data/lib/deltacloud/base_driver/features.rb +31 -12
  26. data/lib/deltacloud/base_driver/mock_driver.rb +2 -1
  27. data/lib/deltacloud/core_ext/string.rb +2 -0
  28. data/lib/deltacloud/drivers/azure/azure_driver.rb +5 -5
  29. data/lib/deltacloud/drivers/condor/condor_client.rb +273 -0
  30. data/lib/deltacloud/drivers/condor/condor_driver.rb +236 -0
  31. data/lib/deltacloud/drivers/condor/ip_agents/confserver.rb +75 -0
  32. data/lib/deltacloud/drivers/condor/ip_agents/default.rb +84 -0
  33. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +326 -95
  34. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +3 -3
  35. data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +40 -8
  36. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +7 -7
  37. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +42 -25
  38. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob1.yml +6 -4
  39. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob2.yml +7 -5
  40. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob3.yml +6 -4
  41. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob4.yml +6 -4
  42. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob5.yml +6 -4
  43. data/lib/deltacloud/drivers/mock/data/buckets/bucket1.yml +7 -1
  44. data/lib/deltacloud/drivers/mock/data/buckets/bucket2.yml +6 -1
  45. data/lib/deltacloud/drivers/mock/data/images/img1.yml +6 -2
  46. data/lib/deltacloud/drivers/mock/data/images/img2.yml +6 -2
  47. data/lib/deltacloud/drivers/mock/data/images/img3.yml +6 -2
  48. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +11 -10
  49. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +14 -7
  50. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +14 -7
  51. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +3 -2
  52. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +3 -2
  53. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +3 -2
  54. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +4 -3
  55. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +4 -3
  56. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +4 -3
  57. data/lib/deltacloud/drivers/mock/mock_client.rb +101 -0
  58. data/lib/deltacloud/drivers/mock/mock_driver.rb +367 -429
  59. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +6 -0
  60. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +59 -9
  61. data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +62 -8
  62. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +100 -45
  63. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +3 -2
  64. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +8 -11
  65. data/lib/deltacloud/drivers/sbc/sbc_client.rb +6 -6
  66. data/lib/deltacloud/drivers/sbc/sbc_driver.rb +16 -0
  67. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +17 -12
  68. data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +140 -0
  69. data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +405 -0
  70. data/lib/deltacloud/drivers/vsphere/vsphere_filemanager.rb +182 -0
  71. data/lib/deltacloud/hardware_profile.rb +1 -1
  72. data/lib/deltacloud/helpers.rb +2 -1
  73. data/lib/deltacloud/helpers/application_helper.rb +92 -20
  74. data/lib/deltacloud/helpers/blob_stream.rb +160 -12
  75. data/lib/deltacloud/helpers/conversion_helper.rb +6 -2
  76. data/lib/deltacloud/helpers/json_helper.rb +31 -0
  77. data/lib/deltacloud/models/address.rb +28 -0
  78. data/lib/deltacloud/models/base_model.rb +5 -1
  79. data/lib/deltacloud/models/blob.rb +1 -1
  80. data/lib/deltacloud/models/bucket.rb +10 -0
  81. data/lib/deltacloud/models/firewall.rb +22 -0
  82. data/lib/deltacloud/models/firewall_rule.rb +23 -0
  83. data/lib/deltacloud/models/image.rb +12 -0
  84. data/lib/deltacloud/models/instance.rb +20 -2
  85. data/lib/deltacloud/models/key.rb +1 -1
  86. data/lib/deltacloud/runner.rb +3 -3
  87. data/lib/deltacloud/validation.rb +3 -7
  88. data/lib/drivers.rb +7 -1
  89. data/lib/sinatra/body_proxy.rb +34 -0
  90. data/lib/sinatra/lazy_auth.rb +5 -0
  91. data/lib/sinatra/rabbit.rb +54 -31
  92. data/lib/sinatra/rack_accept.rb +157 -0
  93. data/lib/sinatra/rack_date.rb +38 -0
  94. data/lib/sinatra/rack_etag.rb +2 -3
  95. data/lib/sinatra/rack_matrix_params.rb +51 -29
  96. data/lib/sinatra/rack_runtime.rb +1 -1
  97. data/lib/sinatra/rack_syslog.rb +86 -0
  98. data/lib/sinatra/url_for.rb +14 -1
  99. data/public/images/address.png +0 -0
  100. data/public/images/balancer.png +0 -0
  101. data/public/images/blob.png +0 -0
  102. data/public/images/bucket.png +0 -0
  103. data/public/images/cloud.png +0 -0
  104. data/public/images/firewall.png +0 -0
  105. data/public/images/image.png +0 -0
  106. data/public/images/key.png +0 -0
  107. data/public/images/machine.png +0 -0
  108. data/public/images/profile.png +0 -0
  109. data/public/images/realm.png +0 -0
  110. data/public/images/snapshot.png +0 -0
  111. data/public/images/volume.png +0 -0
  112. data/public/javascripts/application.js +119 -16
  113. data/public/javascripts/jquery.min.js +18 -0
  114. data/public/javascripts/jquery.mobile-1.0b1.min.js +146 -0
  115. data/public/stylesheets/compiled/application.css +8 -0
  116. data/public/stylesheets/images/ajax-loader.png +0 -0
  117. data/public/{images → stylesheets/images}/bread-bg.png +0 -0
  118. data/public/{images → stylesheets/images}/error.png +0 -0
  119. data/public/{images → stylesheets/images}/grid.png +0 -0
  120. data/public/stylesheets/images/icon-search-black.png +0 -0
  121. data/public/stylesheets/images/icons-18-black.png +0 -0
  122. data/public/stylesheets/images/icons-18-white.png +0 -0
  123. data/public/stylesheets/images/icons-36-black.png +0 -0
  124. data/public/stylesheets/images/icons-36-white.png +0 -0
  125. data/public/{images → stylesheets/images}/logo-wide.png +0 -0
  126. data/public/{images → stylesheets/images}/pending.png +0 -0
  127. data/public/{images → stylesheets/images}/rails.png +0 -0
  128. data/public/{images → stylesheets/images}/running.png +0 -0
  129. data/public/{images → stylesheets/images}/stopped.png +0 -0
  130. data/public/{images → stylesheets/images}/topbar-bg.png +0 -0
  131. data/public/stylesheets/jquery.mobile-1.0b1.min.css +8 -0
  132. data/public/stylesheets/new.css +53 -0
  133. data/server.rb +487 -175
  134. data/support/condor/bash/cached_images.sh +8 -0
  135. data/support/condor/bash/cloud_exit_hook.sh +17 -0
  136. data/support/condor/bash/cloud_functions +175 -0
  137. data/support/condor/bash/cloud_prepare_hook.sh +20 -0
  138. data/support/condor/bash/libvirt_cloud_script.sh +13 -0
  139. data/support/condor/config/50condor_cloud.config +37 -0
  140. data/support/condor/config/50condor_cloud_node.config +37 -0
  141. data/support/condor/config/condor-cloud +2 -0
  142. data/support/condor/config/condor_config.local +44 -0
  143. data/support/fedora/deltacloud-core +48 -26
  144. data/support/fedora/deltacloud-core-config +26 -0
  145. data/support/fedora/deltacloud-core.spec +314 -68
  146. data/support/fedora/deltacloudd-fedora +5 -0
  147. data/tests/common.rb +34 -4
  148. data/tests/drivers/mock/api_test.rb +3 -3
  149. data/tests/drivers/mock/images_test.rb +12 -0
  150. data/tests/drivers/mock/instances_test.rb +2 -0
  151. data/tests/rabbit_test.rb +2 -2
  152. data/views/addresses/_address.html.haml +6 -0
  153. data/views/addresses/associate.html.haml +12 -0
  154. data/views/addresses/index.html.haml +9 -0
  155. data/views/addresses/index.xml.haml +4 -0
  156. data/views/addresses/show.html.haml +21 -0
  157. data/views/addresses/show.xml.haml +14 -0
  158. data/views/api/show.html.haml +6 -11
  159. data/views/api/show.xml.haml +2 -0
  160. data/views/blobs/new.html.haml +24 -23
  161. data/views/blobs/show.html.haml +30 -31
  162. data/views/buckets/index.html.haml +9 -21
  163. data/views/buckets/index.xml.haml +3 -7
  164. data/views/buckets/new.html.haml +13 -12
  165. data/views/buckets/show.html.haml +22 -22
  166. data/views/buckets/show.xml.haml +5 -3
  167. data/views/docs/collection.html.haml +23 -34
  168. data/views/docs/collection.xml.haml +2 -2
  169. data/views/docs/index.html.haml +9 -13
  170. data/views/docs/index.xml.haml +1 -1
  171. data/views/docs/operation.html.haml +28 -38
  172. data/views/docs/operation.xml.haml +1 -1
  173. data/views/drivers/index.html.haml +8 -13
  174. data/views/drivers/show.html.haml +18 -18
  175. data/views/error.html.haml +32 -27
  176. data/views/errors/400.html.haml +41 -0
  177. data/views/errors/{validation_failure.xml.haml → 400.xml.haml} +0 -4
  178. data/views/errors/401.html.haml +41 -0
  179. data/views/errors/{auth_exception.xml.haml → 401.xml.haml} +0 -0
  180. data/views/errors/403.html.haml +42 -0
  181. data/views/errors/{not_allowed.xml.haml → 403.xml.haml} +0 -0
  182. data/views/errors/404.html.haml +29 -0
  183. data/views/errors/{not_found.xml.haml → 404.xml.haml} +1 -1
  184. data/views/errors/405.html.haml +29 -0
  185. data/views/errors/405.xml.haml +5 -0
  186. data/views/errors/500.html.haml +43 -0
  187. data/views/errors/500.xml.haml +5 -0
  188. data/views/errors/502.html.haml +43 -0
  189. data/views/errors/{backend_error.xml.haml → 502.xml.haml} +1 -2
  190. data/views/errors/backend_capability_failure.html.haml +27 -9
  191. data/views/firewalls/index.html.haml +15 -0
  192. data/views/firewalls/index.xml.haml +28 -0
  193. data/views/firewalls/new.html.haml +11 -0
  194. data/views/firewalls/new_rule.html.haml +20 -0
  195. data/views/firewalls/show.html.haml +42 -0
  196. data/views/firewalls/show.xml.haml +26 -0
  197. data/views/hardware_profiles/index.html.haml +15 -23
  198. data/views/hardware_profiles/show.html.haml +22 -18
  199. data/views/images/index.html.haml +11 -23
  200. data/views/images/index.xml.haml +4 -13
  201. data/views/images/new.html.haml +12 -13
  202. data/views/images/show.html.haml +26 -20
  203. data/views/images/show.xml.haml +2 -1
  204. data/views/instance_states/show.html.haml +21 -25
  205. data/views/instances/index.html.haml +13 -30
  206. data/views/instances/index.xml.haml +2 -23
  207. data/views/instances/new.html.haml +83 -88
  208. data/views/instances/show.html.haml +53 -55
  209. data/views/instances/show.xml.haml +12 -10
  210. data/views/keys/index.html.haml +13 -24
  211. data/views/keys/new.html.haml +7 -7
  212. data/views/keys/show.html.haml +26 -21
  213. data/views/layout.html.haml +28 -27
  214. data/views/load_balancers/index.html.haml +11 -31
  215. data/views/load_balancers/index.xml.haml +0 -1
  216. data/views/load_balancers/new.html.haml +1 -1
  217. data/views/load_balancers/show.html.haml +33 -34
  218. data/views/load_balancers/show.xml.haml +2 -2
  219. data/views/realms/index.html.haml +11 -24
  220. data/views/realms/index.xml.haml +2 -8
  221. data/views/realms/show.html.haml +17 -15
  222. data/views/realms/show.xml.haml +2 -1
  223. data/views/storage_snapshots/index.html.haml +11 -21
  224. data/views/storage_snapshots/index.xml.haml +2 -5
  225. data/views/storage_snapshots/new.html.haml +1 -1
  226. data/views/storage_snapshots/show.html.haml +21 -13
  227. data/views/storage_snapshots/show.xml.haml +2 -1
  228. data/views/storage_volumes/index.html.haml +11 -34
  229. data/views/storage_volumes/new.html.haml +1 -1
  230. data/views/storage_volumes/show.html.haml +33 -27
  231. data/views/storage_volumes/show.xml.haml +2 -1
  232. metadata +266 -178
  233. data/lib/sinatra/respond_to.rb +0 -248
  234. data/support/fedora/deltacloudd +0 -128
  235. data/support/fedora/rubygem-deltacloud-core.spec +0 -127
  236. data/views/accounts/index.html.haml +0 -11
  237. data/views/accounts/show.html.haml +0 -30
  238. data/views/errors/auth_exception.html.haml +0 -8
  239. data/views/errors/backend_error.html.haml +0 -22
  240. data/views/errors/not_allowed.html.haml +0 -6
  241. data/views/errors/not_found.html.haml +0 -6
  242. data/views/errors/validation_failure.html.haml +0 -11
@@ -0,0 +1,236 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #
16
+
17
+ require 'deltacloud/base_driver'
18
+
19
+
20
+ class Instance
21
+ def self.convert_condor_state(state_id)
22
+ case state_id
23
+ when 0,1,5 then 'PENDING'
24
+ when 2 then 'RUNNING'
25
+ when 3,4 then 'SHUTTING_DOWN'
26
+ else raise "Unknown Condor state (#{state_id})"
27
+ end
28
+ end
29
+ end
30
+
31
+ require 'deltacloud/drivers/condor/condor_client'
32
+
33
+ module Deltacloud
34
+
35
+ module Drivers
36
+ module Condor
37
+
38
+ require 'base64'
39
+ require 'uuid'
40
+ require 'fileutils'
41
+
42
+ class CondorDriver < Deltacloud::BaseDriver
43
+
44
+ feature :instances, :user_data
45
+ feature :instances, :authentication_password
46
+
47
+ def supported_collections
48
+ DEFAULT_COLLECTIONS - [ :storage_volumes, :storage_snapshots ]
49
+ end
50
+
51
+ CONDOR_MAPPER_DIR = ENV['CONDOR_MAPPER_DIR'] || '/var/tmp'
52
+
53
+ def hardware_profiles(credentials, opts={})
54
+ results = []
55
+ new_client(credentials) do |condor|
56
+ results = condor.hardware_profiles.collect do |hwp|
57
+ HardwareProfile::new(hwp[:name]) do
58
+ architecture 'x86_64'
59
+ memory hwp[:memory]
60
+ cpu hwp[:cpus]
61
+ storage 100
62
+ end
63
+ end
64
+ end
65
+ filter_hardware_profiles(results, opts)
66
+ end
67
+
68
+ def realms(credentials, opts={})
69
+ [
70
+ Realm::new(
71
+ :id => 'default',
72
+ :name => 'Default Condor Realm',
73
+ :limit => :unlimited,
74
+ :state => 'AVAILABLE'
75
+ )
76
+ ]
77
+ end
78
+
79
+ def images(credentials, opts={})
80
+ results = []
81
+ new_client(credentials) do |condor|
82
+ results = condor.images.collect do |image|
83
+ Image::new(
84
+ :id => Digest::SHA1.hexdigest(image.name).to_s,
85
+ :name => image.name.split(':').first,
86
+ :state => image.state || 'AVAILABLE',
87
+ :architecture => 'x86_64',
88
+ :owner_id => image.owner_id || 'unknown',
89
+ :description => image.description
90
+ )
91
+ end
92
+ end
93
+ filter_on( results, :id, opts )
94
+ end
95
+
96
+ def instances(credentials, opts={})
97
+ results = []
98
+ new_client(credentials) do |condor|
99
+ results = condor.instances.collect do |instance|
100
+ vm_uuid = get_value(:uuid, instance.id)
101
+ ip_address = condor.ip_agent.find_ip_by_mac(vm_uuid)
102
+ Instance::new(
103
+ :id => instance.id,
104
+ :name => instance.name,
105
+ :realm_id => 'default',
106
+ :instance_profile => InstanceProfile::new(instance.instance_profile.name),
107
+ :image_id => instance.image_id,
108
+ :public_addresses => [ ip_address ],
109
+ :owner_id => instance.owner_id,
110
+ :description => instance.name,
111
+ :architecture => 'x86_64',
112
+ :actions => instance_actions_for(instance.state),
113
+ :launch_time => instance.launch_time,
114
+ :username => 'root',
115
+ :password => opts[:password],
116
+ :state => instance.state
117
+ )
118
+ end
119
+ end
120
+ results = filter_on( results, :state, opts )
121
+ filter_on( results, :id, opts )
122
+ end
123
+
124
+ def create_instance(credentials, image_id, opts={})
125
+ # User data should contain this Base64 encoded configuration:
126
+ #
127
+ # $config_server_ip:[$uuid]
128
+ #
129
+ # $config_server - IP address of Configuration Server to use (eg. 192.168.1.1)
130
+ # $uuid - UUID to use for instance (will be used for ConfServer <-> DC
131
+ # API communication)
132
+ # $otp - One-time-password
133
+ #
134
+ user_data = opts[:user_data] ? Base64.decode64(opts[:user_data]) : nil
135
+ if user_data
136
+ config_server_address, vm_uuid, vm_otp = opts[:user_data].strip.split(';')
137
+ if vm_uuid.nil? and vm_otp.nil?
138
+ vm_uuid = config_server_address
139
+ config_server_address = nil
140
+ end
141
+ end
142
+ vm_uuid ||= UUID::new.generate
143
+ vm_otp ||= vm_uuid[0..7]
144
+ new_client(credentials) do |condor|
145
+ config_server_address ||= condor.ip_agent.address
146
+ image = images(credentials, :id => image_id).first
147
+ hardware_profile = hardware_profiles(credentials, :id => opts[:hwp_id] || 'small').first
148
+ instance = condor.launch_instance(image, hardware_profile, {
149
+ :name => opts[:name] || "i-#{Time.now.to_i}",
150
+ :config_server_address => config_server_address,
151
+ :uuid => vm_uuid,
152
+ :otp => vm_otp,
153
+ }).first
154
+ store(:uuid, vm_uuid, instance.id)
155
+ raise "Error: VM not launched" unless instance
156
+ instance(credentials, { :id => instance.id, :password => vm_otp })
157
+ end
158
+ end
159
+
160
+ def destroy_instance(credentials, instance_id)
161
+ old_instance = instance(credentials, :id => instance_id)
162
+ new_client(credentials) do |condor|
163
+ condor.destroy_instance(instance_id)
164
+ remove_key(:uuid, instance_id)
165
+ remove_key(:mac, instance_id)
166
+ end
167
+ old_instance.state = 'PENDING'
168
+ old_instance.actions = instance_actions_for(old_instance.state),
169
+ old_instance
170
+ end
171
+
172
+ define_instance_states do
173
+ start.to( :pending ) .automatically
174
+ pending.to( :running ) .automatically
175
+ pending.to( :finish ) .on(:destroy)
176
+ running.to( :running ) .on( :reboot )
177
+ running.to( :shutting_down ) .on( :destroy )
178
+ pending.to( :finish ) .automatically
179
+ end
180
+
181
+ def valid_credentials?(credentials)
182
+ if ( credentials.user != @config[:username] ) or ( credentials.password != @config[:password] )
183
+ return false
184
+ end
185
+ return true
186
+ end
187
+
188
+ exceptions do
189
+ on /AuthException/ do
190
+ status 401
191
+ end
192
+ on /ERROR/ do
193
+ status 502
194
+ end
195
+ end
196
+
197
+ private
198
+
199
+ def new_client(credentials)
200
+ if ( credentials.user != 'condor' ) or ( credentials.password != 'deltacloud' )
201
+ raise Deltacloud::ExceptionHandler::AuthenticationFailure.new
202
+ end
203
+ safely do
204
+ yield CondorCloud::DefaultExecutor.new
205
+ end
206
+ end
207
+
208
+ def store(item, key, value)
209
+ FileUtils.mkdir_p(File.join(CONDOR_MAPPER_DIR, item.to_s))
210
+ File.open(File.join(CONDOR_MAPPER_DIR, item.to_s, key), 'w') do |f|
211
+ f.puts(value)
212
+ end
213
+ end
214
+
215
+ def get_value(key, id)
216
+ begin
217
+ File.open(File.join(CONDOR_MAPPER_DIR, key.to_s, id)).read.strip
218
+ rescue Errno::ENOENT
219
+ puts "Warning: Could not find entry for #{key} #{id} (#{File.join(CONDOR_MAPPER_DIR, key.to_s, id)})"
220
+ nil
221
+ end
222
+ end
223
+
224
+ def remove_key(key, id)
225
+ begin
226
+ FileUtils::rm(File.join(CONDOR_MAPPER_DIR, key.to_s, id))
227
+ rescue
228
+ # We should probably check for specific error conditions here. Some we will want to log or throw an error for.
229
+ puts "Warning: Cannot remove #{key} mapping for instance #{id} (#{File.join(CONDOR_MAPPER_DIR, key.to_s, id)})"
230
+ nil
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,75 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #
16
+
17
+
18
+ module CondorCloud
19
+
20
+ require 'nokogiri'
21
+ require 'rest-client'
22
+
23
+ class ConfServerIPAgent < IPAgent
24
+
25
+ def initialize(opts={})
26
+ @config = opts[:config]
27
+ self.CondorAddress = ENV['CONFIG_SERVER_CondorAddress'] || @config[:ip_agent_CondorAddress] || "10.34.32.181:4444"
28
+ @version = @config[:ip_agent_version] || '0.0.1'
29
+ @client = RestClient::Resource::new(self.CondorAddress)
30
+ # TODO: Manage MAC CondorAddresses through ConfServer
31
+ @mappings = Nokogiri::XML(File.open(opts[:file] || File.join('config', 'CondorAddresses.xml')))
32
+ end
33
+
34
+ def find_ip_by_mac(uuid)
35
+ begin
36
+ @client["/ip/%s/%s" % [@version, uuid]].get(:accept => 'text/plain').body.strip
37
+ rescue RestClient::ResourceNotFound
38
+ '127.0.0.1'
39
+ rescue
40
+ puts 'ERROR: Could not query ConfServer for an IP'
41
+ end
42
+ end
43
+
44
+ def find_mac_by_ip(ip)
45
+ end
46
+
47
+ def find_free_mac
48
+ addr_hash = {}
49
+ DefaultExecutor::new do |executor|
50
+
51
+ # Make an CondorAddress hash to speed up the inner loop.
52
+ CondorAddresses.each do |address|
53
+ addr_hash[address.mac] = address.ip
54
+ end
55
+
56
+ executor.instances.each do |instance|
57
+ instance.public_CondorAddresses.each do |public_CondorAddress|
58
+ if addr_hash.key?(public_CondorAddress.mac)
59
+ addr_hash.delete(public_CondorAddress.mac)
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ raise "No available MACs to assign to instance." if addr_hash.empty?
66
+
67
+ return addr_hash.keys.first
68
+ end
69
+
70
+ def CondorAddresses
71
+ (@mappings/'/CondorAddresses/CondorAddress').collect { |a| CondorAddress.new(:ip => a.text.strip, :mac => a[:mac]) }
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,84 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #
16
+
17
+ require 'nokogiri'
18
+
19
+ module CondorCloud
20
+
21
+ class IPAgent
22
+
23
+ attr_accessor :address
24
+
25
+ def find_mac_by_ip(ip); end
26
+ def find_ip_by_mac(mac); end
27
+ def find_free_mac
28
+ return nil
29
+ end
30
+
31
+ # This method must return an Array of 'CondorAddress' objects
32
+ # [ CondorAddress.new, CondorAddress.new ]
33
+ def addresses; end
34
+ end
35
+
36
+
37
+ # Default IP agent will lookup addresses from XML
38
+ # files stored in config directory.
39
+ # You can overide default directory using { :file => 'path' }
40
+ #
41
+ class DefaultIPAgent < IPAgent
42
+
43
+ def initialize(opts={})
44
+ @mappings = Nokogiri::XML(File.open(opts[:file] || File.join('config', 'addresses.xml')))
45
+ end
46
+
47
+ def find_free_mac
48
+ addr_hash = {}
49
+ DefaultExecutor::new do |executor|
50
+ addresses = (@mappings/'/addresses/address').collect { |a| CondorAddress.new(:ip => a.text.strip, :mac => a[:mac]) }
51
+
52
+ # Make an address hash to speed up the inner loop.
53
+ addresses.each do |address|
54
+ addr_hash[address.mac] = address.ip
55
+ end
56
+
57
+ executor.instances.each do |instance|
58
+ instance.public_addresses.each do |public_address|
59
+ if addr_hash.key?(public_address.mac)
60
+ addr_hash.delete(public_address.mac)
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ raise "No available MACs to assign to instance." if addr_hash.empty?
67
+
68
+ return addr_hash.keys.first
69
+ end
70
+
71
+ def find_ip_by_mac(mac)
72
+ t = (@mappings/"/addresses/address[@mac='#{mac}']").text
73
+ t.empty? ? nil : t
74
+ end
75
+
76
+ def find_mac_by_ip(ip)
77
+ (@mappings/"/addresses/address[.='#{ip}']").first[:mac] rescue nil
78
+ end
79
+
80
+ def addresses
81
+ (@mappings/'/addresses/address').collect { |a| CondorAddress.new(:ip => a.text.strip, :mac => a[:mac]) }
82
+ end
83
+ end
84
+ end
@@ -33,16 +33,17 @@ module Deltacloud
33
33
  class EC2Driver < Deltacloud::BaseDriver
34
34
 
35
35
  def supported_collections
36
- DEFAULT_COLLECTIONS + [ :keys, :buckets, :load_balancers ]
36
+
37
+ DEFAULT_COLLECTIONS + [ :keys, :buckets, :load_balancers, :addresses, :firewalls ]
37
38
  end
38
39
 
39
40
  feature :instances, :user_data
40
41
  feature :instances, :authentication_key
41
- feature :instances, :security_group
42
+ feature :instances, :firewalls
42
43
  feature :instances, :instance_count
43
44
  feature :images, :owner_id
44
45
  feature :buckets, :bucket_location
45
- feature :instances, :register_to_load_balancer
46
+ feature :instances, :attach_snapshot
46
47
 
47
48
  DEFAULT_REGION = 'us-east-1'
48
49
 
@@ -168,26 +169,41 @@ module Deltacloud
168
169
  end
169
170
  end
170
171
 
172
+ def destroy_image(credentials, image_id)
173
+ ec2 = new_client(credentials)
174
+ safely do
175
+ unless ec2.deregister_image(image_id)
176
+ raise "ERROR: Unable to deregister AMI"
177
+ end
178
+ end
179
+ end
180
+
181
+ def instance(credentials, opts={})
182
+ ec2 = new_client(credentials)
183
+ inst_arr = []
184
+ safely do
185
+ ec2_inst = ec2.describe_instances([opts[:id]]).first
186
+ instance = convert_instance(ec2_inst)
187
+ return nil unless instance
188
+ if ec2_inst[:aws_platform] == 'windows'
189
+ console_output = ec2.get_console_output(instance.id)
190
+ windows_password = console_output[:aws_output][%r{<Password>(.+)</Password>}m] && $1
191
+ if windows_password
192
+ instance.username = 'Administrator'
193
+ instance.password = windows_password
194
+ end
195
+ end
196
+ instance
197
+ end
198
+ end
199
+
171
200
  def instances(credentials, opts={})
172
201
  ec2 = new_client(credentials)
173
202
  inst_arr = []
174
203
  safely do
175
- inst_arr = ec2.describe_instances.collect do |instance|
204
+ inst_arr = ec2.describe_instances.collect do |instance|
176
205
  convert_instance(instance) if instance
177
206
  end.flatten
178
- if tagging?
179
- tags = ec2.describe_tags('Filter.1.Name' => 'resource-type',
180
- 'Filter.1.Value' => 'instance')
181
- inst_arr.each do |inst|
182
- name_tag = tags.select do |t|
183
- (t[:aws_resource_id] == inst.id) and t[:aws_key] == 'name'
184
- end
185
- unless name_tag.empty?
186
- inst.name = name_tag.first[:aws_value]
187
- end
188
- end
189
- delete_unused_tags(credentials, inst_arr.collect {|inst| inst.id})
190
- end
191
207
  end
192
208
  inst_arr = filter_on( inst_arr, :id, opts )
193
209
  filter_on( inst_arr, :state, opts )
@@ -200,23 +216,20 @@ module Deltacloud
200
216
  instance_options.merge!(:key_name => opts[:keyname]) if opts[:keyname]
201
217
  instance_options.merge!(:availability_zone => opts[:realm_id]) if opts[:realm_id]
202
218
  instance_options.merge!(:instance_type => opts[:hwp_id]) if opts[:hwp_id] && opts[:hwp_id].length > 0
203
- instance_options.merge!(:group_ids => opts[:security_group]) if opts[:security_group]
219
+ firewalls = opts.inject([]){|res, (k,v)| res << v if k =~ /firewalls\d+$/; res}
220
+ instance_options.merge!(:group_ids => firewalls ) unless firewalls.empty?
204
221
  instance_options.merge!(
205
222
  :min_count => opts[:instance_count],
206
223
  :max_count => opts[:instance_count]
207
224
  ) if opts[:instance_count] and opts[:instance_count].length!=0
225
+ if opts[:snapshot_id] and opts[:device_name]
226
+ instance_options.merge!(:block_device_mappings => [{
227
+ :snapshot_id => opts[:snapshot_id],
228
+ :device_name => opts[:device_name]
229
+ }])
230
+ end
208
231
  safely do
209
232
  new_instance = convert_instance(ec2.launch_instances(image_id, instance_options).first)
210
- # TODO: Rework this to use client_id for name instead of tag
211
- # Tags should be keept as an optional feature
212
- tag_instance(credentials, new_instance, opts[:name])
213
- # Register Instance to Load Balancer if load_balancer_id is set.
214
- # This parameter is a feature parameter
215
- if opts[:load_balancer_id]
216
- lb = lb_register_instance(credentials,
217
- {'id' => opts[:load_balancer_id],
218
- 'instance_id' => new_instance.id})
219
- end
220
233
  new_instance
221
234
  end
222
235
  end
@@ -234,11 +247,11 @@ module Deltacloud
234
247
  Deltacloud::Runner.execute(opts[:cmd], param)
235
248
  end
236
249
  end
237
-
250
+
238
251
  def reboot_instance(credentials, instance_id)
239
252
  ec2 = new_client(credentials)
240
253
  if ec2.reboot_instances([instance_id])
241
- instance(credentials, instance_id)
254
+ instance(credentials, :id => instance_id)
242
255
  else
243
256
  raise Deltacloud::BackendError.new(500, "Instance", "Instance reboot failed", "")
244
257
  end
@@ -246,10 +259,8 @@ module Deltacloud
246
259
 
247
260
  def destroy_instance(credentials, instance_id)
248
261
  ec2 = new_client(credentials)
249
- instance_id = instance_id
250
262
  if ec2.terminate_instances([instance_id])
251
- untag_instance(credentials, instance_id)
252
- instance(credentials, instance_id)
263
+ instance(credentials, :id => instance_id)
253
264
  else
254
265
  raise Deltacloud::BackendError.new(500, "Instance", "Instance cannot be terminated", "")
255
266
  end
@@ -348,9 +359,9 @@ module Deltacloud
348
359
  bucket_list = s3_client.buckets
349
360
  bucket_list.each do |current|
350
361
  buckets << Bucket.new({:name => current.name, :id => current.name})
351
- end #bucket_list.each
352
- end #if
353
- end #safely
362
+ end
363
+ end
364
+ end
354
365
  filter_on(buckets, :id, opts)
355
366
  end
356
367
 
@@ -359,7 +370,7 @@ module Deltacloud
359
370
  safely do
360
371
  s3_client = new_client(credentials, :s3)
361
372
  bucket_location = opts['location']
362
- if bucket_location
373
+ if (bucket_location && bucket_location.size >0)
363
374
  bucket = Aws::S3::Bucket.create(s3_client, name, true, nil, :location => bucket_location)
364
375
  else
365
376
  bucket = Aws::S3::Bucket.create(s3_client, name, true)
@@ -380,8 +391,12 @@ module Deltacloud
380
391
  blobs = []
381
392
  safely do
382
393
  s3_bucket = s3_client.bucket(opts['bucket'])
383
- s3_bucket.keys({}, true).each do |s3_object|
384
- blobs << convert_object(s3_object)
394
+ if(opts[:id])
395
+ blobs << convert_object(s3_bucket.key(opts[:id], true))
396
+ else
397
+ s3_bucket.keys({}, true).each do |s3_object|
398
+ blobs << convert_object(s3_object)
399
+ end
385
400
  end
386
401
  end
387
402
  blobs = filter_on(blobs, :id, opts)
@@ -389,7 +404,7 @@ module Deltacloud
389
404
  end
390
405
 
391
406
  #--
392
- # Create Blob
407
+ # Create Blob - NON Streaming way (i.e. was called with POST html multipart form data)
393
408
  #--
394
409
  def create_blob(credentials, bucket_id, blob_id, data = nil, opts = {})
395
410
  s3_client = new_client(credentials, :s3)
@@ -399,12 +414,12 @@ module Deltacloud
399
414
  # File stream needs to be reopened in binary mode for whatever reason
400
415
  file = File::open(data[:tempfile].path, 'rb')
401
416
  #insert ec2-specific header for user metadata ... x-amz-meta-KEY = VALUE
402
- opts.gsub_keys('HTTP_X_Deltacloud_Blobmeta_', 'x-amz-meta-')
417
+ BlobHelper::rename_metadata_headers(opts, 'x-amz-meta-')
403
418
  opts["Content-Type"] = data[:type]
404
419
  safely do
405
- res = s3_client.interface.put(bucket_id,
406
- blob_id,
407
- file,
420
+ res = s3_client.interface.put(bucket_id,
421
+ blob_id,
422
+ file,
408
423
  opts)
409
424
  end
410
425
  #create a new Blob object and return that
@@ -420,7 +435,7 @@ module Deltacloud
420
435
 
421
436
  #--
422
437
  # Delete Blob
423
- #--
438
+ #--
424
439
  def delete_blob(credentials, bucket_id, blob_id, opts={})
425
440
  s3_client = new_client(credentials, :s3)
426
441
  safely do
@@ -428,6 +443,23 @@ module Deltacloud
428
443
  end
429
444
  end
430
445
 
446
+ def blob_metadata(credentials, opts={})
447
+ s3_client = new_client(credentials, :s3)
448
+ blob_meta = {}
449
+ safely do
450
+ the_blob = s3_client.bucket(opts['bucket']).key(opts[:id], true)
451
+ blob_meta = the_blob.meta_headers
452
+ end
453
+ end
454
+
455
+ def update_blob_metadata(credentials, opts={})
456
+ s3_client = new_client(credentials, :s3)
457
+ meta_hash = BlobHelper::rename_metadata_headers(opts['meta_hash'], '')
458
+ safely do
459
+ the_blob = s3_client.bucket(opts['bucket']).key(opts[:id])
460
+ the_blob.save_meta(meta_hash)
461
+ end
462
+ end
431
463
 
432
464
  def blob_data(credentials, bucket_id, blob_id, opts={})
433
465
  s3_client = new_client(credentials, :s3)
@@ -438,6 +470,35 @@ module Deltacloud
438
470
  end
439
471
  end
440
472
 
473
+ #params: {:user,:password,:bucket,:blob,:content_type,:content_length,:metadata}
474
+ def blob_stream_connection(params)
475
+ #canonicalise metadata:
476
+ #http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
477
+ metadata = params[:metadata] || {}
478
+ signature_meta_string = ""
479
+ BlobHelper::rename_metadata_headers(metadata, 'x-amz-meta-')
480
+ keys_array = metadata.keys.sort!
481
+ keys_array.each {|k| signature_meta_string << "#{k}:#{metadata[k]}\n"}
482
+ provider = "https://#{endpoint_for_service(:s3)}"
483
+ uri = URI.parse(provider)
484
+ http = Net::HTTP.new("#{params[:bucket]}.#{uri.host}", uri.port )
485
+ http.use_ssl = true
486
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
487
+ timestamp = Time.now.httpdate
488
+ string_to_sign =
489
+ "PUT\n\n#{params[:content_type]}\n#{timestamp}\n#{signature_meta_string}/#{params[:bucket]}/#{params[:blob]}"
490
+ auth_string = Aws::Utils::sign(params[:password], string_to_sign)
491
+ request = Net::HTTP::Put.new("/#{params[:blob]}")
492
+ request['Host'] = "#{params[:bucket]}.#{uri.host}"
493
+ request['Date'] = timestamp
494
+ request['Content-Type'] = params[:content_type]
495
+ request['Content-Length'] = params[:content_length]
496
+ request['Authorization'] = "AWS #{params[:user]}:#{auth_string}"
497
+ request['Expect'] = "100-continue"
498
+ metadata.each{|k,v| request[k] = v}
499
+ return http, request
500
+ end
501
+
441
502
  def storage_volumes(credentials, opts={})
442
503
  ec2 = new_client( credentials )
443
504
  volume_list = (opts and opts[:id]) ? opts[:id] : nil
@@ -462,7 +523,7 @@ module Deltacloud
462
523
  def destroy_storage_volume(credentials, opts={})
463
524
  ec2 = new_client(credentials)
464
525
  safely do
465
- unless ec2.delete_volume(opts[:id])
526
+ unless ec2.delete_volume(opts[:id])
466
527
  raise Deltacloud::BackendError.new(500, "StorageVolume", "Cannot delete storage volume")
467
528
  end
468
529
  storage_volume(credentials, opts[:id])
@@ -509,18 +570,139 @@ module Deltacloud
509
570
  end
510
571
  end
511
572
 
573
+ def addresses(credentials, opts={})
574
+ ec2 = new_client(credentials)
575
+ address_id = (opts and opts[:id]) ? [opts[:id]] : []
576
+ safely do
577
+ begin
578
+ ec2.describe_addresses(address_id).collect do |address|
579
+ Address.new(:id => address[:public_ip], :instance_id => address[:instance_id])
580
+ end
581
+ rescue Exception => e
582
+ return [] if e.message =~ /InvalidAddress\.NotFound:/
583
+ raise e
584
+ end
585
+ end
586
+ end
587
+
588
+ def address(credentials, opts={})
589
+ addresses(credentials, :id => opts[:id]).first
590
+ end
591
+
592
+ def create_address(credentials, opts={})
593
+ ec2 = new_client(credentials)
594
+ safely do
595
+ Address.new(:id => ec2.allocate_address)
596
+ end
597
+ end
598
+
599
+ def destroy_address(credentials, opts={})
600
+ ec2 = new_client(credentials)
601
+ safely do
602
+ ec2.release_address(opts[:id])
603
+ end
604
+ end
605
+
606
+ def associate_address(credentials, opts={})
607
+ ec2 = new_client(credentials)
608
+ safely do
609
+ if ec2.associate_address(opts[:instance_id], opts[:id])
610
+ Address.new(:id => opts[:id], :instance_id => opts[:instance_id])
611
+ else
612
+ raise "ERROR: Cannot associate IP address to an Instance"
613
+ end
614
+ end
615
+ end
616
+
617
+ def disassociate_address(credentials, opts={})
618
+ ec2 = new_client(credentials)
619
+ safely do
620
+ if ec2.disassociate_address(opts[:id])
621
+ Address.new(:id => opts[:id])
622
+ else
623
+ raise "ERROR: Cannot disassociate an IP address from the Instance"
624
+ end
625
+ end
626
+ end
627
+
628
+ #--
629
+ #FIREWALLS - ec2 security groups
630
+ #--
631
+ def firewalls(credentials, opts={})
632
+ ec2 = new_client(credentials)
633
+ the_firewalls = []
634
+ groups = []
635
+ safely do
636
+ if opts[:id]
637
+ groups = ec2.describe_security_groups([opts[:id]])
638
+ else
639
+ groups = ec2.describe_security_groups()
640
+ end
641
+ end
642
+ groups.each do |security_group|
643
+ the_firewalls << convert_security_group(security_group)
644
+ end
645
+ the_firewalls
646
+ end
647
+
648
+ #--
649
+ #Create firewall
650
+ #--
651
+ def create_firewall(credentials, opts={})
652
+ ec2 = new_client(credentials)
653
+ safely do
654
+ ec2.create_security_group(opts["name"], opts["description"])
655
+ end
656
+ Firewall.new( { :id=>opts["name"], :name=>opts["name"],
657
+ :description => opts["description"], :owner_id => "", :rules => [] } )
658
+ end
659
+
660
+ #--
661
+ #Delete firewall
662
+ #--
663
+ def delete_firewall(credentials, opts={})
664
+ ec2 = new_client(credentials)
665
+ safely do
666
+ ec2.delete_security_group(opts["id"])
667
+ end
668
+ end
669
+ #--
670
+ #Create firewall rule
671
+ #--
672
+ def create_firewall_rule(credentials, opts={})
673
+ ec2 = new_client(credentials)
674
+ groups = []
675
+ opts['groups'].each do |k,v|
676
+ groups << {"group_name" => k, "owner" =>v}
677
+ end
678
+ safely do
679
+ ec2.manage_security_group_ingress(opts['id'], opts['port_from'], opts['port_to'], opts['protocol'],
680
+ "authorize", opts['addresses'], groups)
681
+ end
682
+ end
683
+ #--
684
+ #Delete firewall rule
685
+ #--
686
+ def delete_firewall_rule(credentials, opts={})
687
+ ec2 = new_client(credentials)
688
+ firewall = opts[:firewall]
689
+ protocol, from_port, to_port, addresses, groups = firewall_rule_params(opts[:rule_id])
690
+ safely do
691
+ ec2.manage_security_group_ingress(firewall, from_port, to_port, protocol, "revoke", addresses, groups)
692
+ end
693
+ end
694
+
512
695
  def valid_credentials?(credentials)
513
696
  retval = true
514
697
  begin
515
698
  realms(credentials)
516
- rescue Deltacloud::BackendError
699
+ rescue
517
700
  retval = false
518
701
  end
519
702
  retval
520
703
  end
521
704
 
522
705
  private
523
-
524
706
  def new_client(credentials, type = :ec2)
525
707
  klass = case type
526
708
  when :elb then Aws::Elb
@@ -538,47 +720,13 @@ module Deltacloud
538
720
  "machine"
539
721
  end
540
722
 
541
- def tagging?
542
- true
543
- end
544
-
545
723
  def endpoint_for_service(service)
546
- endpoint = (Thread.current[:provider] || ENV['API_PROVIDER'] || DEFAULT_REGION)
724
+ endpoint = (api_provider || DEFAULT_REGION)
547
725
  # return the endpoint if it does not map to a default endpoint, allowing
548
726
  # the endpoint to be a full hostname instead of a region.
549
727
  Deltacloud::Drivers::driver_config[:ec2][:entrypoints][service.to_s][endpoint] || endpoint
550
728
  end
551
729
 
552
- def tag_instance(credentials, instance, name)
553
- if name
554
- ec2 = new_client(credentials)
555
- safely do
556
- ec2.create_tag(instance.id, 'name', name)
557
- end
558
- end
559
- end
560
-
561
- def untag_instance(credentials, instance_id)
562
- ec2 = new_client(credentials)
563
- safely do
564
- ec2.delete_tag(instance_id, 'name')
565
- end
566
- end
567
-
568
- def delete_unused_tags(credentials, inst_ids)
569
- ec2 = new_client(credentials)
570
- tags = []
571
- safely do
572
- tags = ec2.describe_tags('Filter.1.Name' => 'resource-type', 'Filter.1.Value' => 'instance')
573
- tags.collect! { |t| t[:aws_resource_id] }
574
- inst_ids.each do |inst_id|
575
- unless tags.include?(inst_id)
576
- ec2.delete_tag(inst_id, 'name')
577
- end
578
- end
579
- end
580
- end
581
-
582
730
  def convert_bucket(s3_bucket)
583
731
  #get blob list:
584
732
  blob_list = []
@@ -602,7 +750,7 @@ module Deltacloud
602
750
  :content_type => s3_object.headers['content-type'],
603
751
  :last_modified => s3_object.last_modified,
604
752
  :user_metadata => s3_object.meta_headers
605
- )
753
+ )
606
754
  end
607
755
 
608
756
  def convert_realm(realm)
@@ -622,7 +770,7 @@ module Deltacloud
622
770
  :description => image[:aws_description] || image[:aws_location],
623
771
  :owner_id => image[:aws_owner],
624
772
  :architecture => image[:aws_architecture],
625
- :state => image[:state]
773
+ :state => image[:aws_state]
626
774
  )
627
775
  end
628
776
 
@@ -635,12 +783,13 @@ module Deltacloud
635
783
  :image_id => instance[:aws_image_id],
636
784
  :owner_id => instance[:aws_owner],
637
785
  :actions => instance_actions_for(convert_state(instance[:aws_state])),
638
- :key_name => instance[:ssh_key_name],
786
+ :keyname => instance[:ssh_key_name],
639
787
  :launch_time => instance[:aws_launch_time],
640
788
  :instance_profile => InstanceProfile.new(instance[:aws_instance_type]),
641
789
  :realm_id => instance[:aws_availability_zone],
642
790
  :private_addresses => instance[:private_dns_name],
643
791
  :public_addresses => instance[:dns_name],
792
+ :firewalls => instance[:aws_groups],
644
793
  :create_image => can_create_image
645
794
  )
646
795
  end
@@ -665,8 +814,8 @@ module Deltacloud
665
814
  :realm_id => volume[:zone],
666
815
  :device => volume[:aws_device],
667
816
  # TODO: the available actions should be tied to the current
668
- # volume state
669
- :actions => [:attach, :detach, :destroy]
817
+ # volume state
818
+ :actions => [:attach, :detach, :destroy]
670
819
  )
671
820
  end
672
821
 
@@ -697,11 +846,87 @@ module Deltacloud
697
846
  balancer.add_listener(listener)
698
847
  end
699
848
  loadbalancer[:instances].each do |instance|
700
- balancer.instances << instance(credentials, :id => instance[:id])
849
+ balancer.instances << instance(credentials, :id => instance[:instance_id])
701
850
  end
702
851
  balancer
703
852
  end
704
853
 
854
+ #generate uid from firewall rule parameters (amazon doesn't do this for us
855
+ def firewall_rule_id(user_id, protocol, from_port, to_port, sources)
856
+ sources_string = ""
857
+ sources.each do |source|
858
+ if source[:type].to_s == "group"
859
+ sources_string << "@#{source[:type]},#{source[:owner]},#{source[:name]},"
860
+ else
861
+ sources_string << "@#{source[:type]},#{source[:family]},#{source[:address]},#{source[:prefix]},"
862
+ end
863
+ end
864
+ #sources_string is @group,297467797945,test@address,ipv4,10.1.1.1,24 etc
865
+ id_string = "#{user_id}~#{protocol}~#{from_port}~#{to_port}~#{sources_string.chomp!(",")}"
866
+ #sources_string.slice(0,sources_string.length-1)}"
867
+ end
868
+
869
+ #extract params from uid
870
+ def firewall_rule_params(id)
871
+ #user_id~protocol~from_port~to_port~sources_string
872
+ params = id.split("~")
873
+ protocol = params[1]
874
+ from_port = params[2]
875
+ to_port = params[3]
876
+ sources = params[4].split("@")
877
+ sources.shift #first match is ""
878
+ addresses = []
879
+ groups = []
880
+ #@group,297467797945,test@address,ipv4,10.1.1.1,24@address,ipv4,192.168.1.1,24
881
+ sources.each do |source|
882
+ current = source.split(",")
883
+ type = current[0]
884
+ case type
885
+ when 'group'
886
+ #group,297467797945,test
887
+ owner = current[1]
888
+ name = current[2]
889
+ groups << {'group_name' => name, 'owner' => owner}
890
+ when 'address'
891
+ #address,ipv4,10.1.1.1,24
892
+ address = current[2]
893
+ address<<"/#{current[3]}"
894
+ addresses << address
895
+ end
896
+ end
897
+ return protocol, from_port, to_port, addresses, groups
898
+ end
899
+
900
+ #Convert ec2 security group to server/lib/deltacloud/models/firewall
901
+ def convert_security_group(security_group)
902
+ rules = []
903
+ security_group[:aws_perms].each do |perm|
904
+ sources = []
905
+ perm[:groups].each do |group|
906
+ sources << {:type => "group", :name => group[:group_name], :owner => group[:owner]}
907
+ end
908
+ perm[:ip_ranges].each do |ip|
909
+ sources << {:type => "address", :family=>"ipv4",
910
+ :address=>ip[:cidr_ip].split("/").first,
911
+ :prefix=>ip[:cidr_ip].split("/").last}
912
+ end
913
+ rule_id = firewall_rule_id(security_group[:aws_owner], perm[:protocol],
914
+ perm[:from_port] , perm[:to_port], sources)
915
+ rules << FirewallRule.new({:id => rule_id,
916
+ :allow_protocol => perm[:protocol],
917
+ :port_from => perm[:from_port],
918
+ :port_to => perm[:to_port],
919
+ :direction => 'ingress',
920
+ :sources => sources})
921
+ end
922
+ Firewall.new( { :id => security_group[:aws_group_name],
923
+ :name => security_group[:aws_group_name],
924
+ :description => security_group[:aws_description],
925
+ :owner_id => security_group[:aws_owner],
926
+ :rules => rules
927
+ } )
928
+ end
929
+
705
930
  def convert_state(ec2_state)
706
931
  case ec2_state
707
932
  when "terminated"
@@ -717,12 +942,18 @@ module Deltacloud
717
942
  end
718
943
  end
719
944
 
720
- def catched_exceptions_list
721
- {
722
- :auth => [ /AuthFailure/ ],
723
- :error => [ /Aws::AwsError/, /Error/ ],
724
- :glob => [ /AWS::(\w+)/, /Deltacloud::Runner::(\w+)/ ]
725
- }
945
+ exceptions do
946
+ on /(AuthFailure|InvalidAccessKeyId)/ do
947
+ status 401
948
+ end
949
+
950
+ on /Error/ do
951
+ status 502
952
+ end
953
+
954
+ on /Deltacloud::Runner::(\w+)/ do
955
+ status 500
956
+ end
726
957
  end
727
958
 
728
959
  end