openshift-origin-controller 1.3.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openshift-origin-controller might be problematic. Click here for more details.

Files changed (180) hide show
  1. data/COPYRIGHT +1 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +12 -0
  4. data/README.md +3 -0
  5. data/Rakefile +9 -0
  6. data/app/controllers/app_events_controller.rb +115 -0
  7. data/app/controllers/application_templates_controller.rb +19 -0
  8. data/app/controllers/applications_controller.rb +214 -0
  9. data/app/controllers/base_controller.rb +367 -0
  10. data/app/controllers/cartridges_controller.rb +48 -0
  11. data/app/controllers/descriptors_controller.rb +23 -0
  12. data/app/controllers/dns_resolvable_controller.rb +35 -0
  13. data/app/controllers/domains_controller.rb +156 -0
  14. data/app/controllers/emb_cart_controller.rb +276 -0
  15. data/app/controllers/emb_cart_events_controller.rb +52 -0
  16. data/app/controllers/environment_controller.rb +11 -0
  17. data/app/controllers/estimates_controller.rb +71 -0
  18. data/app/controllers/gear_groups_controller.rb +53 -0
  19. data/app/controllers/gears_controller.rb +70 -0
  20. data/app/controllers/keys_controller.rb +96 -0
  21. data/app/controllers/legacy_broker_controller.rb +510 -0
  22. data/app/controllers/quickstarts_controller.rb +29 -0
  23. data/app/controllers/user_controller.rb +38 -0
  24. data/app/helpers/cartridge_helper.rb +25 -0
  25. data/app/helpers/legacy_broker_helper.rb +21 -0
  26. data/app/helpers/user_action_logger.rb +38 -0
  27. data/app/models/application.rb +1718 -0
  28. data/app/models/application_template.rb +27 -0
  29. data/app/models/cartridge_cache.rb +51 -0
  30. data/app/models/cloud_user.rb +334 -0
  31. data/app/models/component_instance.rb +228 -0
  32. data/app/models/connection_endpoint.rb +10 -0
  33. data/app/models/district.rb +210 -0
  34. data/app/models/domain.rb +234 -0
  35. data/app/models/gear.rb +376 -0
  36. data/app/models/group_instance.rb +306 -0
  37. data/app/models/key.rb +20 -0
  38. data/app/models/legacy_reply.rb +15 -0
  39. data/app/models/legacy_request.rb +126 -0
  40. data/app/models/link.rb +11 -0
  41. data/app/models/message.rb +10 -0
  42. data/app/models/name_server_cache.rb +46 -0
  43. data/app/models/optional_param.rb +12 -0
  44. data/app/models/param.rb +13 -0
  45. data/app/models/remote_job.rb +57 -0
  46. data/app/models/rest_application.rb +126 -0
  47. data/app/models/rest_application10.rb +106 -0
  48. data/app/models/rest_application12.rb +124 -0
  49. data/app/models/rest_application_estimate.rb +12 -0
  50. data/app/models/rest_application_template.rb +20 -0
  51. data/app/models/rest_cartridge10.rb +41 -0
  52. data/app/models/rest_cartridge11.rb +151 -0
  53. data/app/models/rest_domain.rb +43 -0
  54. data/app/models/rest_domain10.rb +42 -0
  55. data/app/models/rest_estimates.rb +16 -0
  56. data/app/models/rest_gear.rb +14 -0
  57. data/app/models/rest_gear_group.rb +26 -0
  58. data/app/models/rest_key.rb +24 -0
  59. data/app/models/rest_reply.rb +31 -0
  60. data/app/models/rest_user.rb +43 -0
  61. data/app/models/result_io.rb +67 -0
  62. data/app/models/usage_record.rb +37 -0
  63. data/app/models/validators/app_validator.rb +30 -0
  64. data/app/models/validators/key_validator.rb +30 -0
  65. data/app/models/validators/namespace_validator.rb +18 -0
  66. data/config/routes.rb +36 -0
  67. data/lib/controller_engine.rb +7 -0
  68. data/lib/openshift-origin-controller.rb +14 -0
  69. data/lib/openshift/application_container_proxy.rb +241 -0
  70. data/lib/openshift/auth_service.rb +101 -0
  71. data/lib/openshift/data_store.rb +33 -0
  72. data/lib/openshift/dns_service.rb +41 -0
  73. data/lib/openshift/mongo_data_store.rb +671 -0
  74. data/openshift-origin-controller.gemspec +42 -0
  75. data/rubygem-openshift-origin-controller.spec +274 -0
  76. data/test/cucumber/application-estimate.feature +25 -0
  77. data/test/cucumber/cartridge-10gen-mms-agent.feature +28 -0
  78. data/test/cucumber/cartridge-cron.feature +32 -0
  79. data/test/cucumber/cartridge-haproxy.feature +31 -0
  80. data/test/cucumber/cartridge-jenkins-build.feature +12 -0
  81. data/test/cucumber/cartridge-jenkins-client.feature +10 -0
  82. data/test/cucumber/cartridge-lifecycle-diy.feature +21 -0
  83. data/test/cucumber/cartridge-lifecycle-jbossas.feature +61 -0
  84. data/test/cucumber/cartridge-lifecycle-jbosseap.feature +61 -0
  85. data/test/cucumber/cartridge-lifecycle-jbossews10.feature +61 -0
  86. data/test/cucumber/cartridge-lifecycle-jenkins.feature +41 -0
  87. data/test/cucumber/cartridge-lifecycle-nodejs.feature +59 -0
  88. data/test/cucumber/cartridge-lifecycle-perl.feature +40 -0
  89. data/test/cucumber/cartridge-lifecycle-php.feature +106 -0
  90. data/test/cucumber/cartridge-lifecycle-python.feature +40 -0
  91. data/test/cucumber/cartridge-lifecycle-ruby18.feature +49 -0
  92. data/test/cucumber/cartridge-lifecycle-ruby19.feature +41 -0
  93. data/test/cucumber/cartridge-mongodb.feature +31 -0
  94. data/test/cucumber/cartridge-mysql.feature +30 -0
  95. data/test/cucumber/cartridge-php.feature +14 -0
  96. data/test/cucumber/cartridge-phpmyadmin.feature +32 -0
  97. data/test/cucumber/cartridge-postgresql.feature +32 -0
  98. data/test/cucumber/cartridge-runtime-extended-db.feature +64 -0
  99. data/test/cucumber/cartridge-runtime-extended-jboss.feature +24 -0
  100. data/test/cucumber/cartridge-runtime-extended-nodejs.feature +21 -0
  101. data/test/cucumber/cartridge-runtime-extended-perl.feature +18 -0
  102. data/test/cucumber/cartridge-runtime-extended-php.feature +19 -0
  103. data/test/cucumber/cartridge-runtime-extended-python.feature +18 -0
  104. data/test/cucumber/cartridge-runtime-extended-ruby.feature +22 -0
  105. data/test/cucumber/cartridge-runtime-standard-diy.feature +6 -0
  106. data/test/cucumber/cartridge-runtime-standard-jbossas.feature +7 -0
  107. data/test/cucumber/cartridge-runtime-standard-jbosseap.feature +7 -0
  108. data/test/cucumber/cartridge-runtime-standard-jbossews10.feature +7 -0
  109. data/test/cucumber/cartridge-runtime-standard-jenkins.feature +8 -0
  110. data/test/cucumber/cartridge-runtime-standard-nodejs.feature +7 -0
  111. data/test/cucumber/cartridge-runtime-standard-perl.feature +6 -0
  112. data/test/cucumber/cartridge-runtime-standard-php.feature +6 -0
  113. data/test/cucumber/cartridge-runtime-standard-python.feature +6 -0
  114. data/test/cucumber/cartridge-runtime-standard-ruby.feature +19 -0
  115. data/test/cucumber/cartridge-switchyard.feature +36 -0
  116. data/test/cucumber/descriptor.feature +40 -0
  117. data/test/cucumber/embedded.feature +44 -0
  118. data/test/cucumber/idler.feature +75 -0
  119. data/test/cucumber/misc/descriptor/manifest.yml +22 -0
  120. data/test/cucumber/misc/php/db_test.php +21 -0
  121. data/test/cucumber/openshift-node.feature +21 -0
  122. data/test/cucumber/rest-application-templates.feature +31 -0
  123. data/test/cucumber/rest-applications.feature +431 -0
  124. data/test/cucumber/rest-cartridge-types.feature +16 -0
  125. data/test/cucumber/rest-domains.feature +276 -0
  126. data/test/cucumber/rest-gears.feature +38 -0
  127. data/test/cucumber/rest-keys.feature +247 -0
  128. data/test/cucumber/rest-quickstarts.feature +27 -0
  129. data/test/cucumber/rest-workflow.feature +64 -0
  130. data/test/cucumber/step_definitions/api_steps.rb +369 -0
  131. data/test/cucumber/step_definitions/application-estimate-steps.rb +51 -0
  132. data/test/cucumber/step_definitions/application_steps.rb +215 -0
  133. data/test/cucumber/step_definitions/cartridge-10gen-mms-agent_steps.rb +11 -0
  134. data/test/cucumber/step_definitions/cartridge-cron_steps.rb +51 -0
  135. data/test/cucumber/step_definitions/cartridge-haproxy_steps.rb +30 -0
  136. data/test/cucumber/step_definitions/cartridge-jenkins_steps.rb +93 -0
  137. data/test/cucumber/step_definitions/cartridge-lifecycle-nodejs_steps.rb +30 -0
  138. data/test/cucumber/step_definitions/cartridge-mongodb_steps.rb +60 -0
  139. data/test/cucumber/step_definitions/cartridge-mysql_steps.rb +56 -0
  140. data/test/cucumber/step_definitions/cartridge-php_steps.rb +72 -0
  141. data/test/cucumber/step_definitions/cartridge-postgresql_steps.rb +59 -0
  142. data/test/cucumber/step_definitions/cartridge-switchyard_steps.rb +29 -0
  143. data/test/cucumber/step_definitions/client_steps.rb +12 -0
  144. data/test/cucumber/step_definitions/descriptor_step.rb +32 -0
  145. data/test/cucumber/step_definitions/idler_steps.rb +37 -0
  146. data/test/cucumber/step_definitions/node_steps.rb +203 -0
  147. data/test/cucumber/step_definitions/runtime_steps.rb +547 -0
  148. data/test/cucumber/step_definitions/runtime_url_steps.rb +46 -0
  149. data/test/cucumber/step_definitions/trap-user-extended_steps.rb +14 -0
  150. data/test/cucumber/step_definitions/trap-user_steps.rb +58 -0
  151. data/test/cucumber/support/00_setup_helper.rb +106 -0
  152. data/test/cucumber/support/app_helper.rb +243 -0
  153. data/test/cucumber/support/assertions.rb +52 -0
  154. data/test/cucumber/support/command_helper.rb +453 -0
  155. data/test/cucumber/support/dns_helper.rb +54 -0
  156. data/test/cucumber/support/env.rb +5 -0
  157. data/test/cucumber/support/process_helper.rb +44 -0
  158. data/test/cucumber/support/runtime_support.rb +440 -0
  159. data/test/cucumber/support/unused.rb +27 -0
  160. data/test/cucumber/support/user_helper.rb +37 -0
  161. data/test/cucumber/trap-user-extended.feature +53 -0
  162. data/test/cucumber/trap-user.feature +34 -0
  163. data/test/ddns/1.168.192-rev.db.init +13 -0
  164. data/test/ddns/HOWTO.txt +207 -0
  165. data/test/ddns/Kexample.com.+157+06142.key +1 -0
  166. data/test/ddns/Kexample.com.+157+06142.private +7 -0
  167. data/test/ddns/authconfig.rb +14 -0
  168. data/test/ddns/example.com.db.init +23 -0
  169. data/test/ddns/example.com.key +4 -0
  170. data/test/ddns/named.ca +52 -0
  171. data/test/ddns/named.conf +48 -0
  172. data/test/ddns/named.empty +10 -0
  173. data/test/ddns/named.localhost +10 -0
  174. data/test/ddns/named.loopback +11 -0
  175. data/test/ddns/named.rfc1912.zones +42 -0
  176. data/test/ddns/named.root.key +5 -0
  177. data/test/ddns/named_service.rb +127 -0
  178. data/test/unit/bind_dns_service_test.rb +167 -0
  179. data/test/unit/broker_auth_test.rb +28 -0
  180. metadata +545 -0
@@ -0,0 +1,376 @@
1
+ class Gear < OpenShift::Model
2
+ attr_accessor :uuid, :uid, :server_identity, :group_instance_name, :node_profile, :container, :app, :configured_components, :name
3
+ primary_key :uuid
4
+ exclude_attributes :container, :app
5
+
6
+ def initialize(app, group_instance, uuid=nil, uid=nil)
7
+ self.app = app
8
+ @uuid = uuid || OpenShift::Model.gen_uuid
9
+ self.name = @uuid[0..9]
10
+ self.group_instance_name = group_instance.name
11
+ self.node_profile = group_instance.node_profile
12
+ self.configured_components = []
13
+ @uid = uid
14
+ get_proxy
15
+ end
16
+
17
+ def node_profile
18
+ # node_profile can be nil for older data. Should migrate everything to have a node_profile
19
+ # with the next major migration. Although technically node_profile shouldn't even be on gear.
20
+ if @node_profile.nil?
21
+ return Application::DEFAULT_NODE_PROFILE
22
+ else
23
+ return @node_profile
24
+ end
25
+ end
26
+
27
+ def get_proxy
28
+ if self.container.nil? and !@server_identity.nil?
29
+ self.container = OpenShift::ApplicationContainerProxy.instance(@server_identity)
30
+ end
31
+ return self.container
32
+ end
33
+
34
+ def create
35
+ if server_identity.nil?
36
+ ret = nil
37
+ begin
38
+ self.app.ngears += 1
39
+ self.container = OpenShift::ApplicationContainerProxy.find_available(self.node_profile)
40
+ self.server_identity = self.container.id
41
+ self.uid = self.container.reserve_uid
42
+ self.group_instance.gears << self
43
+ self.app.save
44
+ ret = self.container.create(app,self)
45
+ self.app.track_usage(self, UsageRecord::EVENTS[:begin]) if ret.exitcode == 0
46
+ rescue Exception => e
47
+ Rails.logger.debug e.message
48
+ Rails.logger.debug e.backtrace.join("\n")
49
+ ret = ResultIO.new
50
+ ret.errorIO << e.message
51
+ ret.exitcode = 5
52
+ end
53
+
54
+ ## recovery action if creation failed above
55
+ if ret.exitcode != 0
56
+ begin
57
+ get_proxy.destroy(self.app, self)
58
+ rescue Exception => e
59
+ end
60
+ self.app.ngears -= 1
61
+ self.group_instance.gears.delete(self)
62
+ self.app.save
63
+ raise OpenShift::NodeException.new("Unable to create gear on node", 1, ret)
64
+ end
65
+ return ret
66
+ end
67
+ end
68
+
69
+ def destroy
70
+ ret = get_proxy.destroy(app, self)
71
+ if ret.exitcode == 0
72
+ self.app.destroyed_gears = [] unless self.app.destroyed_gears
73
+ self.app.destroyed_gears << @uuid
74
+ track_destroy_usage
75
+ self.app.ngears -= 1
76
+ self.group_instance.gears.delete(self)
77
+ app.process_cartridge_commands(ret)
78
+ self.app.save
79
+ else
80
+ raise OpenShift::NodeException.new("Unable to destroy gear on node", 1, ret)
81
+ end
82
+ return ret
83
+ end
84
+
85
+ def force_destroy
86
+ ret = nil
87
+ begin
88
+ begin
89
+ ret = get_proxy.destroy(app, self)
90
+ rescue Exception => e
91
+ Rails.logger.error("ERROR: Ignoring a failed destroy for gear with uuid: #{uuid}")
92
+ end
93
+ self.app.destroyed_gears = [] unless self.app.destroyed_gears
94
+ self.app.destroyed_gears << @uuid
95
+ track_destroy_usage
96
+ ensure
97
+ self.app.ngears -= 1
98
+ self.group_instance.gears.delete(self)
99
+ if ret
100
+ begin
101
+ app.process_cartridge_commands(ret)
102
+ rescue Exception => e
103
+ Rails.logger.error("ERROR: Ignoring a failed process_cartridge_commands for gear with uuid: #{uuid}")
104
+ end
105
+ end
106
+ self.app.save
107
+ end
108
+ return ret
109
+ end
110
+
111
+ def configure(comp_inst, template_git_url=nil)
112
+ r = ResultIO.new
113
+ return r if self.configured_components.include?(comp_inst.name)
114
+ result_io, cart_data = get_proxy.configure_cartridge(app, self, comp_inst.parent_cart_name, template_git_url)
115
+ r.append result_io
116
+ comp_inst.process_cart_data(cart_data)
117
+ comp_inst.process_cart_properties(result_io.cart_properties)
118
+ self.configured_components.push(comp_inst.name)
119
+ r
120
+ end
121
+
122
+ def deconfigure(comp_inst, force=false)
123
+ r = ResultIO.new
124
+ return r unless self.configured_components.include?(comp_inst.name) or force
125
+ r.append get_proxy.deconfigure_cartridge(app,self,comp_inst.parent_cart_name)
126
+ self.configured_components.delete(comp_inst.name)
127
+ r
128
+ end
129
+
130
+ def execute_connector(comp_inst, connector_name, input_args)
131
+ get_proxy.execute_connector(app, self, comp_inst.parent_cart_name, connector_name, input_args)
132
+ end
133
+
134
+ def get_execute_connector_job(cart, connector_name, input_args)
135
+ get_proxy.get_execute_connector_job(app, self, cart, connector_name, input_args)
136
+ end
137
+
138
+ def start(comp_inst)
139
+ get_proxy.start(app, self, comp_inst.parent_cart_name)
140
+ end
141
+
142
+ def stop(comp_inst)
143
+ get_proxy.stop(app, self, comp_inst.parent_cart_name)
144
+ end
145
+
146
+ def restart(comp_inst)
147
+ get_proxy.restart(app, self, comp_inst.parent_cart_name)
148
+ end
149
+
150
+ def force_stop(comp_inst)
151
+ get_proxy.force_stop(app, self, comp_inst.parent_cart_name)
152
+ end
153
+
154
+ def reload(comp_inst)
155
+ get_proxy.reload(app, self, comp_inst.parent_cart_name)
156
+ end
157
+
158
+ def status(comp_inst)
159
+ get_proxy.status(app, self, comp_inst.parent_cart_name)
160
+ end
161
+
162
+ def status_job(comp_inst)
163
+ job = get_proxy.get_status_job(app, self, comp_inst.parent_cart_name)
164
+ job
165
+ end
166
+
167
+ def show_state()
168
+ get_proxy.show_state(app, self)
169
+ end
170
+
171
+ def tidy(comp_inst)
172
+ get_proxy.tidy(app, self, comp_inst.parent_cart_name)
173
+ end
174
+
175
+ def expose_port(comp_inst)
176
+ get_proxy.expose_port(app, self, comp_inst.parent_cart_name)
177
+ end
178
+
179
+ def conceal_port(comp_inst)
180
+ get_proxy.conceal_port(app, self, comp_inst.parent_cart_name)
181
+ end
182
+
183
+ def show_port(comp_inst)
184
+ get_proxy.show_port(app, self, comp_inst.parent_cart_name)
185
+ end
186
+
187
+ def threaddump(comp_inst)
188
+ get_proxy.threaddump(app, self, comp_inst.parent_cart_name)
189
+ end
190
+
191
+ def system_messages(comp_inst)
192
+ get_proxy.system_messages(app, self, comp_inst.parent_cart_name)
193
+ end
194
+
195
+ def add_alias(server_alias)
196
+ if app.gear.uuid == self.uuid
197
+ get_proxy.add_alias(app, self, server_alias)
198
+ else
199
+ ResultIO.new
200
+ end
201
+ end
202
+
203
+ def remove_alias(server_alias)
204
+ if app.gear.uuid == self.uuid
205
+ get_proxy.remove_alias(app, self, server_alias)
206
+ else
207
+ ResultIO.new
208
+ end
209
+ end
210
+
211
+ def add_authorized_ssh_key(ssh_key, key_type=nil, comment=nil)
212
+ get_proxy.add_authorized_ssh_key(app, self, ssh_key, key_type, comment)
213
+ end
214
+
215
+ def remove_authorized_ssh_key(ssh_key, comment=nil)
216
+ get_proxy.remove_authorized_ssh_key(app, self, ssh_key, comment)
217
+ end
218
+
219
+ def add_env_var(key, value)
220
+ get_proxy.add_env_var(app, self, key, value)
221
+ end
222
+
223
+ def set_quota(storage_in_gb, inodes)
224
+ get_proxy.set_quota(self, storage_in_gb, inodes)
225
+ end
226
+
227
+ def get_quota()
228
+ get_proxy.get_quota(self)
229
+ end
230
+
231
+ def gear_quota_job_show()
232
+ job = get_proxy.get_show_gear_quota_job(self)
233
+ job
234
+ end
235
+
236
+ def gear_quota_job_update(storage_in_gb, inodes)
237
+ job = get_proxy.get_update_gear_quota_job(self, storage_in_gb, inodes)
238
+ job
239
+ end
240
+
241
+ def app_state_job_show()
242
+ job = get_proxy.get_show_state_job(app, self)
243
+ job
244
+ end
245
+
246
+ def env_var_job_add(key, value)
247
+ job = get_proxy.get_env_var_add_job(app, self, key, value)
248
+ job
249
+ end
250
+
251
+ def ssh_key_job_add(ssh_key, ssh_key_type, ssh_key_comment)
252
+ job = get_proxy.get_add_authorized_ssh_key_job(app, self, ssh_key, ssh_key_type, ssh_key_comment)
253
+ job
254
+ end
255
+
256
+ def broker_auth_key_job_add(iv, token)
257
+ job = get_proxy.get_broker_auth_key_add_job(app, self, iv, token)
258
+ job
259
+ end
260
+
261
+ def env_var_job_remove(key)
262
+ job = get_proxy.get_env_var_remove_job(app, self, key)
263
+ job
264
+ end
265
+
266
+ def ssh_key_job_remove(ssh_key, ssh_key_comment)
267
+ job = get_proxy.get_remove_authorized_ssh_key_job(app, self, ssh_key, ssh_key_comment)
268
+ job
269
+ end
270
+
271
+ def broker_auth_key_job_remove()
272
+ job = get_proxy.get_broker_auth_key_remove_job(app, self)
273
+ job
274
+ end
275
+
276
+ def remove_env_var(key)
277
+ get_proxy.remove_env_var(app, self, key)
278
+ end
279
+
280
+ def add_broker_auth_key(iv,token)
281
+ get_proxy.add_broker_auth_key(app, self, iv, token)
282
+ end
283
+
284
+ def remove_broker_auth_key
285
+ get_proxy.remove_broker_auth_key(app, self)
286
+ end
287
+
288
+ def cartridges
289
+ gi = group_instance
290
+ carts = gi.component_instances.map{ |comp_instance_name| app.comp_instance_map[comp_instance_name].parent_cart_name }
291
+ carts.delete(app.name)
292
+ carts
293
+ end
294
+
295
+ def group_instance
296
+ self.app.group_instance_map[self.group_instance_name]
297
+ end
298
+
299
+ def group_instance_name
300
+ return @group_instance_name if self.app.group_instance_map[@group_instance_name]
301
+ self.app.group_instance_map.each { |gi_name, gi|
302
+ gi.gears.each { |gi_gear|
303
+ if gi_gear.uuid==self.uuid
304
+ @group_instance_name = gi_name
305
+ return @group_instance_name
306
+ end
307
+ }
308
+ }
309
+ return self.app.get_name_prefix
310
+ end
311
+
312
+ def prepare_namespace_update(dns_service, new_ns, old_ns)
313
+ results = []
314
+ gi = group_instance
315
+ contains_proxy = false
316
+ contains_framework = false
317
+ result_io = ResultIO.new
318
+
319
+ gi.component_instances.each do |cname|
320
+ ci = self.app.comp_instance_map[cname]
321
+ contains_proxy = true if ci.parent_cart_name == self.app.proxy_cartridge
322
+ contains_framework = true if ci.parent_cart_name == self.app.framework
323
+ end
324
+
325
+ if contains_proxy || !self.app.scalable
326
+ #proxy gear gets public dns
327
+ register_application(dns_service, old_ns, new_ns, self.app.name)
328
+ else
329
+ #non-proxy gear gets gear specific dns
330
+ register_application(dns_service, old_ns, new_ns, self.name)
331
+ end
332
+
333
+ if contains_framework
334
+ result_io.append call_update_namespace_hook(self.app.framework, new_ns, old_ns)
335
+ else
336
+ result_io.append call_update_namespace_hook("abstract", new_ns, old_ns)
337
+ end
338
+ result_io
339
+ end
340
+
341
+ def self.valid_gear_size?(gear_size)
342
+ Rails.configuration.openshift[:gear_sizes].include?(gear_size)
343
+ end
344
+
345
+ def self.gear_sizes_display_string
346
+ # Ex: (small(default)|jumbo|exlarge|large|medium|micro)
347
+ out = '('
348
+ Rails.configuration.openshift[:gear_sizes].each_with_index do |gear_size, index|
349
+ out += gear_size
350
+ out += '(default)' if gear_size == Rails.configuration.openshift[:default_gear_size]
351
+ out += '|' unless index == (Rails.configuration.openshift[:gear_sizes].length - 1)
352
+ end
353
+ out += ')'
354
+ end
355
+
356
+ private
357
+
358
+ def track_destroy_usage
359
+ self.app.track_usage(self, UsageRecord::EVENTS[:end])
360
+ if self.group_instance.addtl_fs_gb && self.group_instance.addtl_fs_gb > 0
361
+ self.app.track_usage(self, UsageRecord::EVENTS[:end], UsageRecord::USAGE_TYPES[:addtl_fs_gb])
362
+ end
363
+ end
364
+
365
+ def call_update_namespace_hook(cart_name, new_ns, old_ns)
366
+ result = get_proxy.update_namespace(self.app, self, cart_name, new_ns, old_ns)
367
+ self.app.process_cartridge_commands(result)
368
+ return result
369
+ end
370
+
371
+ def register_application(dns_service, old_ns, new_ns, name)
372
+ public_hostname = get_proxy.get_public_hostname
373
+ dns_service.deregister_application(name, old_ns)
374
+ dns_service.register_application(name, new_ns, public_hostname)
375
+ end
376
+ end
@@ -0,0 +1,306 @@
1
+ class GroupInstance < OpenShift::Model
2
+ attr_accessor :uuid, :app, :gears, :node_profile, :component_instances, :supported_min, :supported_max,
3
+ :name, :cart_name, :profile_name, :group_name, :reused_by, :min, :max, :addtl_fs_gb
4
+ primary_key :uuid
5
+ exclude_attributes :app
6
+
7
+ include LegacyBrokerHelper
8
+
9
+ def initialize(app, cartname=nil, profname=nil, groupname=nil, path=nil)
10
+ self.uuid = OpenShift::Model.gen_uuid
11
+ self.app = app
12
+ self.name = path
13
+ self.cart_name = cartname
14
+ self.profile_name = profname
15
+ self.component_instances = []
16
+ self.group_name = groupname
17
+ self.reused_by = []
18
+ self.gears = []
19
+ self.addtl_fs_gb = 0
20
+ self.node_profile = app.node_profile
21
+ self.supported_min = 1
22
+ self.supported_max = -1
23
+ self.min = 1
24
+ self.max = -1
25
+ end
26
+
27
+ def node_profile
28
+ # node_profile can be nil for older data. Should migrate everything to have a node_profile
29
+ # with the next major migration.
30
+ if @node_profile.nil?
31
+ return Application::DEFAULT_NODE_PROFILE
32
+ else
33
+ return @node_profile
34
+ end
35
+ end
36
+
37
+ def self.get(app, id)
38
+ app.group_instances.each do |ginst|
39
+ return ginst if ginst.uuid == id
40
+ end if app.group_instances
41
+ return nil
42
+ end
43
+
44
+ def merge_inst(ginst)
45
+ reused = [self.name, self.cart_name, self.profile_name, self.group_name]
46
+ self.reused_by << reused
47
+ self.name = ginst.name
48
+ self.cart_name = ginst.cart_name
49
+ self.profile_name = ginst.profile_name
50
+ self.group_name = ginst.group_name
51
+ ginst.component_instances.each { |ci_name|
52
+ cinst = self.app.comp_instance_map[ci_name]
53
+ next if cinst.nil?
54
+ cur_ginst = self.app.group_instance_map[cinst.group_instance_name]
55
+ self.app.group_instance_map[cinst.group_instance_name] = self if ginst==cur_ginst
56
+ }
57
+ self.component_instances = (self.component_instances + ginst.component_instances).uniq unless ginst.component_instances.nil?
58
+ if not ginst.gears.nil? and ginst.gears.length > 0
59
+ self.gears = [] if self.gears.nil?
60
+ @gears += ginst.gears
61
+ if self.gears.length == 0
62
+ self.uuid = ginst.uuid
63
+ else
64
+ # Since two gear groups are being merged and the structure is being changed,
65
+ # we cannot re-use the uuid from either of the two gear groups
66
+ # Also, how do we merge two group instances that have gears in them
67
+ # without deleting the gears that exist in them
68
+ end
69
+ end
70
+ self.supported_min, self.supported_max = GroupInstance::merge_min_max(self.supported_min, self.supported_max, ginst.supported_min, ginst.supported_max)
71
+ self.min, self.max = GroupInstance::merge_min_max(self.min, self.max, ginst.min, ginst.max)
72
+ end
73
+
74
+ def merge(cartname, profname, groupname, path, comp_instance_list=nil)
75
+ reused = [self.name, self.cart_name, self.profile_name, self.group_name]
76
+ self.reused_by << reused
77
+ self.name = path
78
+ self.cart_name = cartname
79
+ self.profile_name = profname
80
+ self.group_name = groupname
81
+ self.component_instances = (self.component_instances + comp_instance_list).uniq unless comp_instance_list.nil?
82
+ # component_instances remains a flat collection
83
+ end
84
+
85
+ def fix_gear_uuid(app, gear)
86
+ #FIXME: backward compat: first gears UUID = app.uuid
87
+ if app.scalable
88
+ # Override/set gear's uuid with app's uuid if its a scalable app w/ the
89
+ # proxy component.
90
+ if self.component_instances.include? "@@app/comp-proxy/cart-haproxy-1.4"
91
+ gear.uuid = app.uuid
92
+ gear.name = app.name
93
+ end
94
+ else
95
+ # For non scalable app's, gear's uuid is the app uuid.
96
+ gear.uuid = app.uuid
97
+ gear.name = app.name
98
+ end
99
+ end
100
+
101
+ def add_gear(app)
102
+ gear = Gear.new(app, self)
103
+ fix_gear_uuid(app, gear)
104
+
105
+ # create the gear
106
+ create_result = gear.create
107
+
108
+ begin
109
+ if app.scalable and not self.component_instances.include? "@@app/comp-proxy/cart-haproxy-1.4"
110
+ app.add_dns(gear.name, app.domain.namespace, gear.get_proxy.get_public_hostname)
111
+ end
112
+ rescue Exception => e
113
+ Rails.logger.debug e.message
114
+ Rails.logger.debug e.backtrace.inspect
115
+ # Cleanup
116
+ gear.destroy
117
+ raise e
118
+ end
119
+
120
+ if @addtl_fs_gb.kind_of?(Integer) or @addtl_fs_gb.kind_of?(Float) and @addtl_fs_gb > 0
121
+ min_storage = get_cached_min_storage_in_gb()
122
+ set_quota(@addtl_fs_gb + min_storage, nil, [gear])
123
+ end
124
+
125
+ app.add_node_settings([gear])
126
+ return [create_result, gear]
127
+ end
128
+
129
+ def remove_gear(gear, force=false)
130
+ if force
131
+ return gear.force_destroy
132
+ else
133
+ return gear.destroy
134
+ end
135
+ end
136
+
137
+ def update_quota(additional_storage, inodes=nil, gear_list=nil)
138
+ set_quota(@addtl_fs_gb+additional_storage+get_cached_min_storage_in_gb, inodes, gear_list)
139
+ end
140
+
141
+ def set_quota(storage_in_gb, inodes=nil, gear_list=nil)
142
+ reply = ResultIO.new
143
+ tag = ""
144
+ previous_fs_gb = @addtl_fs_gb
145
+ gear_list = @gears if gear_list.nil?
146
+
147
+ handle = RemoteJob.create_parallel_job
148
+ RemoteJob.run_parallel_on_gears(gear_list, handle) { |exec_handle, gear|
149
+ job = gear.gear_quota_job_update(storage_in_gb, inodes)
150
+ RemoteJob.add_parallel_job(exec_handle, tag, gear, job)
151
+ }
152
+
153
+ RemoteJob.get_parallel_run_results(handle) { |tag, gear_uuid, output, status|
154
+ if status != 0
155
+ raise OpenShift::NodeException.new("Error setting quota on gear: #{gear_uuid} with status: #{status} and output: #{output}", 143)
156
+ else
157
+ @gears.each { |gi_gear|
158
+ if gi_gear.uuid == gear_uuid
159
+ # :end usage event for previous quota
160
+ unless previous_fs_gb.nil? || previous_fs_gb == 0
161
+ @addtl_fs_gb = previous_fs_gb
162
+ app.track_usage(gi_gear, UsageRecord::EVENTS[:end], UsageRecord::USAGE_TYPES[:addtl_fs_gb])
163
+ end
164
+
165
+ # :begin usage event for new quota
166
+ @addtl_fs_gb = storage_in_gb - get_cached_min_storage_in_gb
167
+
168
+ app.track_usage(gi_gear, UsageRecord::EVENTS[:begin], UsageRecord::USAGE_TYPES[:addtl_fs_gb]) if @addtl_fs_gb > 0
169
+ break
170
+ end
171
+ }
172
+ end
173
+ }
174
+
175
+ reply
176
+ end
177
+
178
+ def get_quota
179
+ additional_storage = @addtl_fs_gb.nil? ? 0 : Integer(@addtl_fs_gb)
180
+ return { "additional_gear_storage" => additional_storage, "base_gear_storage" => get_cached_min_storage_in_gb }
181
+ end
182
+
183
+ def get_cached_min_storage_in_gb
184
+ return 1 if @gears.nil? or @gears.length == 0
185
+
186
+ quota_blocks_str = get_cached(node_profile + "quota_blocks", :expires_in => 1.day) {@gears[0].get_proxy.get_quota_blocks}
187
+ quota_blocks = Integer(quota_blocks_str)
188
+ # calculate the minimum storage in GB - blocks are 1KB each
189
+ min_storage = quota_blocks / 1024 / 1024
190
+ return min_storage
191
+ end
192
+
193
+ def fulfil_requirements(app)
194
+ result_io = ResultIO.new
195
+ return result_io if not app.scalable
196
+ deficit = self.min - self.gears.length
197
+ u = CloudUser.find(self.app.user.login)
198
+ if (deficit + u.consumed_gears) > u.max_gears
199
+ raise OpenShift::UserException.new("#{u.login} has a gear limit of #{u.max_gears} and this app requires #{deficit} more gears. Check the 'scales_from' limit of all cartridges of the app?", 104)
200
+ end
201
+ deficit.times do
202
+ result, new_gear = add_gear(app)
203
+ result_io.append result
204
+ end
205
+ result_io
206
+ end
207
+
208
+ def get_unconfigured_gears(comp_inst)
209
+ unconfigured_gears = []
210
+ self.gears.each do |gear|
211
+ unconfigured_gears << gear if not gear.configured_components.include?(comp_inst.name)
212
+ end
213
+ unconfigured_gears
214
+ end
215
+
216
+ def gears=(data)
217
+ @gears = [] if @gears.nil?
218
+ data.each do |hash|
219
+ if hash.class == Gear
220
+ @gears.push hash
221
+ else
222
+ gear = Gear.new(@app,self)
223
+ gear.attributes=hash
224
+ @gears.push gear
225
+ end
226
+ end
227
+ end
228
+
229
+ def elaborate(profile, group, parent_comp_path, app)
230
+ group_inst_hash = {}
231
+ new_components = []
232
+ group.component_refs.each { |comp_ref|
233
+ if self.cart_name == app.name
234
+ cpath = parent_comp_path + comp_ref.get_name_prefix(profile)
235
+ else
236
+ cpath = parent_comp_path + "/cart-" + self.cart_name + comp_ref.get_name_prefix(profile)
237
+ end
238
+ old_ci = app.comp_instance_map[cpath]
239
+ ci = ComponentInstance.new(self.cart_name, self.profile_name, self.group_name, comp_ref.name, cpath, self)
240
+ ci.cart_data += old_ci.cart_data unless old_ci.nil?
241
+ ci.addtl_fs_gb = old_ci.addtl_fs_gb unless old_ci.nil?
242
+ ci.process_cart_properties(old_ci.cart_properties) unless old_ci.nil?
243
+ new_components << cpath
244
+ self.component_instances << cpath if not self.component_instances.include? cpath
245
+ app.comp_instance_map[cpath] = ci
246
+ app.working_comp_inst_hash[cpath] = ci
247
+ comp_groups = ci.elaborate(app)
248
+ c_comp,c_prof,c_cart = ci.get_component_definition(app)
249
+ c_group = c_prof.groups(ci.parent_cart_group)
250
+ self.supported_min, self.supported_max = GroupInstance::merge_min_max(self.supported_min, @supported_max, c_group.scaling.min, c_group.scaling.max)
251
+ self.min, self.max = GroupInstance::merge_min_max(self.min, @max, c_group.scaling.min, c_group.scaling.max)
252
+ group_inst_hash[comp_ref.name] = comp_groups
253
+ }
254
+
255
+ # TODO: For FUTURE : if one wants to optimize by merging the groups
256
+ # then pick group_inst_hash and merge them up
257
+ # e.g. first component needs 4 groups, second one needs 3
258
+ # then, make the first three groups of first component also contain
259
+ # the second component and discard the second component's 3 groups
260
+ # (to remove groups, erase them from app.comp_instance_map for sure)
261
+
262
+ # remove any entries in component_instances that are not part of
263
+ # application's working component instance hash, because that indicates
264
+ # deleted components
265
+ self.component_instances.delete_if { |cpath| app.working_comp_inst_hash[cpath].nil? }
266
+ new_components
267
+ end
268
+
269
+ def supported_max
270
+ if app and not app.scalable
271
+ return @supported_min
272
+ else
273
+ return @supported_max
274
+ end
275
+ end
276
+
277
+ def max
278
+ if app and not app.scalable
279
+ return @min
280
+ else
281
+ return @max
282
+ end
283
+ end
284
+
285
+ def self.merge_min_max(min1, max1, min2, max2)
286
+ newmin = min1>min2 ? min1 : min2
287
+
288
+ if max1 < max2
289
+ if max1 >= 0
290
+ newmax = max1
291
+ else
292
+ newmax = max2
293
+ end
294
+ elsif max2 >= 0
295
+ newmax = max2
296
+ else
297
+ newmax = max1
298
+ end
299
+
300
+ if newmin > newmax and newmax >= 0
301
+ newmin = newmax
302
+ end
303
+ return newmin,newmax
304
+ end
305
+
306
+ end