openshift-origin-controller 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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