Find an application to which user has access @param [CloudUser] user @param [String] app_name @return [Application]
# File lib/stickshift-controller/app/models/application.rb, line 170 def self.find(user, app_name) return nil if app_name.nil? or app_name.empty? app = nil if user.applications user.applications.each do |next_app| if next_app.name.downcase == app_name.downcase app = next_app break end end else app = super(user.login, app_name) return nil unless app app.user = user app.reset_state end app end
Find an applications to which user has access @param [CloudUser] user @return [Array<Application>]
# File lib/stickshift-controller/app/models/application.rb, line 192 def self.find_all(user) apps = nil if user.applications apps = user.applications else apps = super(user.login) apps.each do |app| app.user = user app.reset_state end user.applications = apps end apps end
# File lib/stickshift-controller/app/models/application.rb, line 207 def self.find_by_gear_uuid(gear_uuid) hash = StickShift::DataStore.instance.find_by_gear_uuid(gear_uuid) return nil unless hash user = CloudUser.hash_to_obj hash user.applications.each do |next_app| next_app.gears.each do |gear| if gear.uuid == gear_uuid return next_app,gear end end end return nil end
# File lib/stickshift-controller/app/models/application.rb, line 221 def self.find_by_uuid(uuid) hash = StickShift::DataStore.instance.find_by_uuid(self.name,uuid) return nil unless hash user = CloudUser.hash_to_obj hash app = nil user.applications.each do |next_app| if next_app.uuid == uuid app = next_app break end end return app end
@overload ::get_available_cartridges
@deprecated Returns List of names of available cartridges of specified type @param [String] cart_type Must be "standalone" or "embedded" or nil @return [Array<String>]
@overload ::get_available_cartridges
@return [Array<String>] Returns List of names of all available cartridges
# File lib/stickshift-controller/app/models/application.rb, line 253 def self.get_available_cartridges(cart_type=nil) cart_names = CartridgeCache.cartridge_names(cart_type) end
# File lib/stickshift-controller/app/models/application.rb, line 235 def self.hash_to_obj(hash) domain = nil if hash["domain"] domain = Domain.hash_to_obj(hash["domain"]) end app = super(hash) app.domain = domain app end
@param [CloudUser] user @param [String] app_name Application name @param [optional, String] uuid Unique identifier for the application @param [deprecated, String] #node_profile Node profile for the first application gear @param [deprecated, String] framework Cartridge name to use as the framwwork of the application
# File lib/stickshift-controller/app/models/application.rb, line 53 def initialize(user=nil, app_name=nil, uuid=nil, node_profile=nil, framework=nil, template=nil, will_scale=false, domain=nil) self.user = user self.domain = domain self.node_profile = node_profile self.creation_time = DateTime::now().strftime self.uuid = uuid || StickShift::Model.gen_uuid self.scalable = will_scale self.ngears = 0 if template.nil? if self.scalable descriptor_hash = YAML.load(template_scalable_app(app_name, framework)) from_descriptor(descriptor_hash) self.proxy_cartridge = "haproxy-1.4" else from_descriptor({"Name"=>app_name}) self.requires_feature = [] self.requires_feature << framework unless framework.nil? end else template_descriptor = YAML.load(template.descriptor_yaml) template_descriptor["Name"] = app_name if not template_descriptor["Configure-Order"] requires_list = template_descriptor["Requires"] || [] template_descriptor["Configure-Order"] = requires_list end from_descriptor(template_descriptor) @init_git_url = template.git_url end self.categories -= ["cartridge"] end
# File lib/stickshift-controller/app/models/application.rb, line 1001 def add_alias(server_alias) if !(server_alias =~ %r\A[\w\-\.]+\z/) or (server_alias =~ %r#{Rails.configuration.ss[:domain_suffix]}$/) raise StickShift::UserException.new("Invalid Server Alias '#{server_alias}' specified", 105) end self.aliases = [] unless self.aliases raise StickShift::UserException.new("Alias '#{server_alias}' already exists for '#{@name}'", 255) if self.aliases.include? server_alias reply = ResultIO.new begin self.aliases.push(server_alias) self.save reply.append self.container.add_alias(self, self.gear, self.framework, server_alias) rescue Exception => e Rails.logger.debug e.message Rails.logger.debug e.backtrace.inspect reply.append self.container.remove_alias(self, self.gear, self.framework, server_alias) self.aliases.delete(server_alias) self.save raise end reply end
# File lib/stickshift-controller/app/models/application.rb, line 851 def add_broker_key iv, token = StickShift::AuthService.instance.generate_broker_key(self) reply = ResultIO.new s,f = run_on_gears(nil,reply,false) do |gear,r| r.append gear.add_broker_auth_key(iv,token) end raise f[0][:exception] if(f.length > 0) reply end
# File lib/stickshift-controller/app/models/application.rb, line 1044 def add_dependency(dep) reply = ResultIO.new self.class.notify_observers(:before_add_dependency, {:application => self, :dependency => dep, :reply => reply}) # Create persistent storage app entry on configure (one of the first things) Rails.logger.debug "DEBUG: Adding embedded app info from persistant storage: #{@name}:#{dep}" self.cart_data = {} if @cart_data.nil? raise StickShift::UserException.new("#{dep} already embedded in '#{@name}'", 101) if self.embedded.include? dep if self.scalable raise StickShift::UserException.new("#{dep} cannot be embedded in scalable app '#{@name}'. Allowed cartridges: #{SCALABLE_EMBEDDED_CARTS.join(',')}", 108) if not SCALABLE_EMBEDDED_CARTS.include? dep end add_to_requires_feature(dep) begin reply.append self.configure_dependencies self.execute_connections rescue Exception => e remove_from_requires_feature(dep) self.elaborate_descriptor self.save raise e end self.class.notify_observers(:after_add_dependency, {:application => self, :dependency => dep, :reply => reply}) reply end
# File lib/stickshift-controller/app/models/application.rb, line 902 def add_dns(appname, namespace, public_hostname) dns = StickShift::DnsService.instance begin dns.register_application(appname, namespace, public_hostname) dns.publish ensure dns.close end end
# File lib/stickshift-controller/app/models/application.rb, line 833 def add_env_var(key, value) reply = ResultIO.new s,f = run_on_gears(nil,reply,false) do |gear,r| r.append gear.add_env_var(key, value) end raise f[0][:exception] if(f.length > 0) reply end
# File lib/stickshift-controller/app/models/application.rb, line 1270 def add_group_override(from, to) prof = @profile_name_map[@default_profile] prof.group_overrides = [] if prof.group_overrides.nil? prof.group_overrides << [from, to] end
# File lib/stickshift-controller/app/models/application.rb, line 871 def add_node_settings(gears=nil) reply = ResultIO.new gears = self.gears unless gears if @user.env_vars || @user.ssh_keys || @user.system_ssh_keys tag = "" handle = RemoteJob.create_parallel_job RemoteJob.run_parallel_on_gears(gears, handle) { |exec_handle, gear| @user.env_vars.each do |key, value| job = gear.env_var_job_add(key, value) RemoteJob.add_parallel_job(exec_handle, tag, gear, job) end if @user.env_vars @user.ssh_keys.each do |key_name, key_info| job = gear.ssh_key_job_add(key_info["key"], key_info["type"], key_name) RemoteJob.add_parallel_job(exec_handle, tag, gear, job) end if @user.ssh_keys @user.system_ssh_keys.each do |key_name, key_info| job = gear.ssh_key_job_add(key_info, nil, key_name) RemoteJob.add_parallel_job(exec_handle, tag, gear, job) end if @user.system_ssh_keys } RemoteJob.get_parallel_run_results(handle) { |tag, gear, output, status| if status != 0 raise StickShift::NodeException.new("Error applying settings to gear: #{gear} with status: #{status} and output: #{output}", 143) end } end reply end
# File lib/stickshift-controller/app/models/application.rb, line 85 def add_to_requires_feature(feature) prof = @profile_name_map[@default_profile] if self.scalable # add to the proxy component comp_name = "proxy" if comp_name.nil? prof = @profile_name_map[@default_profile] cinst = ComponentInstance::find_component_in_cart(prof, self, comp_name, self.get_name_prefix) raise StickShift::NodeException.new("Cannot find component '#{comp_name}' in app #{self.name}.", "-101", result_io) if cinst.nil? comp,profile,cart = cinst.get_component_definition(self) raise StickShift::UserException.new("#{feature} already embedded in '#{@name}'", 101) if comp.depends.include? feature fcart = self.framework conn = StickShift::Connection.new("#{feature}-web-#{fcart}") conn.components = ["proxy/#{feature}", "web/#{fcart}"] prof.add_connection(conn) conn = StickShift::Connection.new("#{feature}-proxy-#{fcart}") conn.components = ["proxy/#{feature}", "proxy/#{fcart}"] prof.add_connection(conn) # FIXME: Booya - hacks galore -- fix this to be more generic when # scalable apps allow more components in SCALABLE_EMBEDDED_CARTS if feature == "jenkins-client-1.4" conn = StickShift::Connection.new("#{feature}-proxy-haproxy-1.4") conn.components = ["proxy/#{feature}", "proxy/haproxy-1.4"] prof.add_connection(conn) end comp.depends << feature else self.requires_feature.each { |cart| conn = StickShift::Connection.new("#{feature}-#{cart}") conn.components = [cart, feature] prof.add_connection(conn) } self.requires_feature << feature end end
convinence method to cleanup an application
# File lib/stickshift-controller/app/models/application.rb, line 314 def cleanup_and_delete reply = ResultIO.new reply.append self.destroy_dns reply.append self.destroy self.delete reply end
Provides an array version of the component instance map for saving in the datastore. @return [Array<Hash>]
# File lib/stickshift-controller/app/models/application.rb, line 1211 def comp_instances @comp_instance_map = {} if @comp_instance_map.nil? @comp_instance_map.values end
Rebuilds the component instance map from an array of hashes or objects @param [Array<Hash>] data
# File lib/stickshift-controller/app/models/application.rb, line 1218 def comp_instances=(data) comp_instance_map_will_change! @comp_instance_map = {} if @comp_instance_map.nil? data.each do |value| if value.class == ComponentInstance @comp_instance_map[value.name] = value else key = value["name"] @comp_instance_map[key] = ComponentInstance.new @comp_instance_map[key].attributes=value end end end
# File lib/stickshift-controller/app/models/application.rb, line 980 def complete_namespace_update(new_ns, old_ns) self.comp_instances.each do |comp_inst| comp_inst.cart_properties.each do |prop_key, prop_value| comp_inst.cart_properties[prop_key] = prop_value.gsub(%r-#{old_ns}.#{Rails.configuration.ss[:domain_suffix]}/, "-#{new_ns}.#{Rails.configuration.ss[:domain_suffix]}") end end self.embedded.each_key do |framework| if self.embedded[framework].has_key?('info') info = self.embedded[framework]['info'] info.gsub!(%r-#{old_ns}.#{Rails.configuration.ss[:domain_suffix]}/, "-#{new_ns}.#{Rails.configuration.ss[:domain_suffix]}") self.embedded[framework]['info'] = info end end # elaborate descriptor again to execute connections, because connections need to be renewed self.elaborate_descriptor self.execute_connections self.domain.namespace = new_ns self.save end
# File lib/stickshift-controller/app/models/application.rb, line 748 def conceal_port(dependency=nil) reply = ResultIO.new self.comp_instance_map.each do |comp_inst_name, comp_inst| next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) next if comp_inst.name == "@@app" next if comp_inst.parent_cart_name == self.name group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.conceal_port(comp_inst) end # Not all cartridges will have this hook. f.each do |fail| next if fail[:exception].resultIO.exitcode == 127 raise fail[:exception] end end reply end
Elaborates the descriptor, configures cartridges that were added to the application dependencies. If a node is empty after removing components, then the gear is destroyed. Errors that occur while removing cartridges are logged but no exception is thrown. If an error occurs while configuring a cartridge, then the cartirdge is deconfigures on all nodes and an exception is thrown.
# File lib/stickshift-controller/app/models/application.rb, line 429 def configure_dependencies reply = ResultIO.new self.class.notify_observers(:before_application_configure, {:application => self, :reply => reply}) elaborate_descriptor exceptions = [] Rails.logger.debug "Configure order is #{self.configure_order.inspect}" #process new additions #TODO: fix configure after framework cartridge is no longer a requirement for adding embedded cartridges self.configure_order.each do |comp_inst_name| comp_inst = self.comp_instance_map[comp_inst_name] next if comp_inst.parent_cart_name == self.name group_inst = self.group_instance_map[comp_inst.group_instance_name] begin group_inst.fulfil_requirements(self) run_on_gears(group_inst.get_unconfigured_gears(comp_inst), reply) do |gear, r| doExpose = false if self.scalable and comp_inst.parent_cart_name!=self.proxy_cartridge doExpose = true if not gear.configured_components.include? comp_inst.name end r.append gear.configure(comp_inst, @init_git_url) begin r.append gear.expose_port(comp_inst) if doExpose rescue Exception=>e end process_cartridge_commands(r) end rescue Exception => e Rails.logger.debug e.message Rails.logger.debug e.backtrace.inspect successful_gears = [] successful_gears = e.message[:successful].map{|g| g[:gear]} if e.message[:successful] failed_gears = [] failed_gears = e.message[:failed].map{|g| g[:gear]} if e.message[:failed] gear_exception = e.message[:exception] #remove failed component from all gears run_on_gears(successful_gears, reply, false) do |gear, r| r.append gear.deconfigure(comp_inst) process_cartridge_commands(r) end run_on_gears(failed_gears, reply, false) do |gear, r| r.append gear.deconfigure(comp_inst, true) process_cartridge_commands(r) end # destroy any unused gears # TODO : if the destroy fails below... the user still sees the error as configure failure # Then to recover, if we re-elaborate (like in add_dependency), then the group instance will get lost # and any failed gears below will leak (i.e. they exist on node, their destroy failed, but they do not have any handle in Mongo) run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append group_inst.remove_gear(gear) if gear.configured_components.length == 0 end self.save exceptions << gear_exception end end unless exceptions.empty? raise exceptions.first end self.save self.class.notify_observers(:after_application_configure, {:application => self, :reply => reply}) reply end
Get the ApplicationContainerProxy object for the first gear the application is running on @return [ApplicationContainerProxy] @deprecated
# File lib/stickshift-controller/app/models/application.rb, line 1157 def container return nil if self.gear.nil? return self.gear.get_proxy end
Processes the application descriptor and creates all the gears necessary to host the application. Destroys application on all gears if any gear fails @return [ResultIO]
# File lib/stickshift-controller/app/models/application.rb, line 273 def create result_io = ResultIO.new gears_created = [] begin self.node_profile = DEFAULT_NODE_PROFILE unless self.node_profile elaborate_descriptor self.class.notify_observers(:before_application_create, {:application => self, :reply => result_io}) if self.scalable raise StickShift::UserException.new("Scalable app cannot be of type #{UNSCALABLE_FRAMEWORKS.join(' ')}", "108", result_io) if UNSCALABLE_FRAMEWORKS.include? framework min_gear_count = 0 group_instances.uniq.each { |gi| min_gear_count += gi.min } if ((user.consumed_gears+min_gear_count) > user.max_gears) raise StickShift::UserException.new("#{user.login} has a gear limit of #{user.max_gears} and this app requires #{min_gear_count} gears.", 104) end end user.applications << self Rails.logger.debug "Creating gears" group_instances.uniq.each do |ginst| create_result, new_gear = ginst.add_gear(self) result_io.append create_result end self.gear.name = self.name unless scalable self.class.notify_observers(:application_creation_success, {:application => self, :reply => result_io}) rescue Exception => e Rails.logger.debug e.message Rails.logger.debug e.backtrace.join("\n") Rails.logger.debug "Rolling back application gear creation" result_io.append self.destroy self.class.notify_observers(:application_creation_failure, {:application => self, :reply => result_io}) raise ensure save end self.class.notify_observers(:after_application_create, {:application => self, :reply => result_io}) result_io end
# File lib/stickshift-controller/app/models/application.rb, line 912 def create_dns reply = ResultIO.new self.class.notify_observers(:before_create_dns, {:application => self, :reply => reply}) public_hostname = self.container.get_public_hostname add_dns(@name, @domain.namespace, public_hostname) self.class.notify_observers(:after_create_dns, {:application => self, :reply => reply}) reply end
Deletes the application object from the datastore
# File lib/stickshift-controller/app/models/application.rb, line 266 def delete super(user.login) end
Destroys all gears. Logs message but does not throw an exception on failure to delete any particular gear.
# File lib/stickshift-controller/app/models/application.rb, line 323 def destroy reply = ResultIO.new self.class.notify_observers(:before_application_destroy, {:application => self, :reply => reply}) #only need to destroy if application has been elaborated first unless self.configure_order.nil? # Destroy in the reverse order of configure. group_instances = [] self.configure_order.reverse.each do |comp_inst_name| comp_inst = self.comp_instance_map[comp_inst_name] next if comp_inst.parent_cart_name == self.name group_inst = self.group_instance_map[comp_inst.group_instance_name] group_instances.delete(group_inst) group_instances << group_inst end failures = [] group_instances.each do |group_inst| s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append group_inst.remove_gear(gear) end failures += f end begin self.save if self.persisted? rescue Exception => e # pass on failure... because we maybe wanting a delete here instead anyway end failures.each do |data| Rails.logger.debug("Unable to clean up application on gear #{data[:gear]} due to exception #{data[:exception].message}") Rails.logger.debug(data[:exception].backtrace.inspect) end raise StickShift::NodeException.new("Could not destroy all gears of application.", 1, reply) if failures.length > 0 end self.class.notify_observers(:after_application_destroy, {:application => self, :reply => reply}) reply end
# File lib/stickshift-controller/app/models/application.rb, line 923 def destroy_dns reply = ResultIO.new self.class.notify_observers(:before_destroy_dns, {:application => self, :reply => reply}) dns = StickShift::DnsService.instance begin dns.deregister_application(@name,@domain.namespace) if self.scalable # find the group instance where the web-cartridge is residing self.group_instance_map.keys.each { |ginst_name| ginst = self.group_instance_map[ginst_name] ginst.gears.each { |gear| dns.deregister_application(gear.name,@domain.namespace) } } end dns.publish ensure dns.close end self.class.notify_observers(:after_destroy_dns, {:application => self, :reply => reply}) reply end
Parse the descriptor and build or update the runtime descriptor structure
# File lib/stickshift-controller/app/models/application.rb, line 1277 def elaborate_descriptor self.group_instance_map = {} if group_instance_map.nil? self.comp_instance_map = {} if comp_instance_map.nil? self.working_comp_inst_hash = {} self.working_group_inst_hash = {} self.group_override_map = {} self.conn_endpoints_list = [] default_profile = @profile_name_map[@default_profile] default_profile.groups.each { |g| #gpath = self.name + "." + g.name gpath = self.get_name_prefix + g.get_name_prefix gi = working_group_inst_hash[gpath] if gi.nil? gi = self.group_instance_map[gpath] if gi.nil? gi = GroupInstance.new(self, self.name, self.default_profile, g.name, gpath) else gi.merge(self.name, self.default_profile, g.name, gpath) end else gi.merge(self.name, self.default_profile, g.name, gpath) end self.group_instance_map[gpath] = gi self.working_group_inst_hash[gpath] = gi gi.elaborate(default_profile, g, self.get_name_prefix, self) } # make connection_endpoints out of provided connections default_profile.connections.each { |conn| inst1 = ComponentInstance::find_component_in_cart(default_profile, self, conn.components[0], self.get_name_prefix) inst2 = ComponentInstance::find_component_in_cart(default_profile, self, conn.components[1], self.get_name_prefix) ComponentInstance::establish_connections(inst1, inst2, self) } # check self.comp_instance_map for component instances # check self.group_instance_map for group instances # check self.conn_endpoints_list for list of connection endpoints (fully resolved) # resolve group co-locations colocate_groups # get configure_order and start_order get_exec_order(default_profile) deleted_components_list = [] self.comp_instance_map.each { |k,v| deleted_components_list << k if self.working_comp_inst_hash[k].nil? } yield deleted_components_list if block_given? # delete entries in {group,comp}_instance_map that do # not exist in working_{group,comp}_inst_hash self.group_instance_map.delete_if { |k,v| v.component_instances.delete(k) if self.working_comp_inst_hash[k].nil? and v.component_instances.include?(k) self.working_group_inst_hash[k].nil? } self.comp_instance_map.delete_if { |k,v| self.working_comp_inst_hash[k].nil? } end
Provide a list of direct dependencies of the application that are hosted on the same gear as the "framework" cartridge. @return [Array<String>] @deprecated
# File lib/stickshift-controller/app/models/application.rb, line 1186 def embedded embedded_carts = CartridgeCache.cartridge_names('embedded') retval = {} self.comp_instance_map.values.each do |comp_inst| if embedded_carts.include?(comp_inst.parent_cart_name) if comp_inst.cart_data.first.nil? retval[comp_inst.parent_cart_name] = comp_inst.cart_properties else retval[comp_inst.parent_cart_name] = comp_inst.cart_properties.merge({"info" => comp_inst.cart_data.first}) end end end retval end
# File lib/stickshift-controller/app/models/application.rb, line 499 def execute_connections return if not self.scalable self.conn_endpoints_list.each { |conn| pub_inst = self.comp_instance_map[conn.from_comp_inst] pub_ginst = self.group_instance_map[pub_inst.group_instance_name] tag = "" handle = RemoteJob.create_parallel_job RemoteJob.run_parallel_on_gears(pub_ginst.gears, handle) { |exec_handle, gear| appname = gear.name connector_name = conn.from_connector.name cart = pub_inst.parent_cart_name input_args = [appname, self.domain.namespace, gear.uuid] job = gear.get_execute_connector_job(cart, connector_name, input_args) RemoteJob.add_parallel_job(exec_handle, tag, gear, job) } pub_out = [] RemoteJob.get_parallel_run_results(handle) { |tag, gear, output, status| if status==0 pub_out.push("'#{gear}'='#{output}'") end } input_to_subscriber = Shellwords::shellescape(pub_out.join(' ')) Rails.logger.debug "Output of publisher - '#{pub_out}'" sub_inst = self.comp_instance_map[conn.to_comp_inst] sub_ginst = self.group_instance_map[sub_inst.group_instance_name] handle = RemoteJob.create_parallel_job RemoteJob.run_parallel_on_gears(sub_ginst.gears, handle) { |exec_handle, gear| appname = gear.name connector_name = conn.to_connector.name cart = sub_inst.parent_cart_name input_args = [appname, self.domain.namespace, gear.uuid, input_to_subscriber] job = gear.get_execute_connector_job(cart, connector_name, input_args) RemoteJob.add_parallel_job(exec_handle, tag, gear, job) } # we dont care about subscriber's output/status } end
Invokes #expose_port for a particular dependency on all gears that host it. @param [String] dependency Name of a cartridge
# File lib/stickshift-controller/app/models/application.rb, line 726 def expose_port(dependency=nil) reply = ResultIO.new self.comp_instance_map.each do |comp_inst_name, comp_inst| next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) next if comp_inst.name == "@@app" next if comp_inst.parent_cart_name == self.name group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.expose_port(comp_inst) end # Not all cartridges will have this hook. f.each do |fail| next if fail[:exception].resultIO.exitcode == 127 raise fail[:exception] end end reply end
# File lib/stickshift-controller/app/models/application.rb, line 44 def extended_validator notify_observers(:validate_application) end
Force stop a particular dependency on all gears that host it. @param [String] dependency Name of a cartridge to stop. Set to nil for all dependencies. @param [Boolean] throw_exception_on_failure
# File lib/stickshift-controller/app/models/application.rb, line 598 def force_stop(dependency=nil, throw_exception_on_failure=true) reply = ResultIO.new self.class.notify_observers(:before_force_stop, {:application => self, :reply => reply, :dependency => dependency}) self.start_order.each do |comp_inst_name| comp_inst = self.comp_instance_map[comp_inst_name] next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.force_stop(comp_inst) end raise f[0][:exception] if(f.length > 0 and throw_exception_on_failure) end self.class.notify_observers(:after_force_stop, {:application => self, :reply => reply, :dependency => dependency}) reply end
Get the name of framework cartridge in use by the application @return [String] @deprecated
# File lib/stickshift-controller/app/models/application.rb, line 1174 def framework framework_carts = CartridgeCache.cartridge_names('standalone') self.comp_instance_map.each { |cname, cinst| cartname = cinst.parent_cart_name return cartname if framework_carts.include? cartname } return nil end
Get the name of framework cartridge in use by the application without the version suffix @return [String] @deprecated
# File lib/stickshift-controller/app/models/application.rb, line 1165 def framework_cartridge fcart = self.framework return fcart.split('-')[0..-2].join('-') unless fcart.nil? return nil end
Returns the first Gear object on which the application is running @return [Gear] @deprecated
# File lib/stickshift-controller/app/models/application.rb, line 1121 def gear if self.group_instances.nil? elaborate_descriptor end if scalable self.group_instance_map.keys.each { |ginst_name| return self.group_instance_map[ginst_name].gears.first if ginst_name.include? self.proxy_cartridge } end group_instance = self.group_instances.first return nil unless group_instance return group_instance.gears.first end
# File lib/stickshift-controller/app/models/application.rb, line 368 def gears self.group_instances.uniq.map{ |ginst| ginst.gears }.flatten end
# File lib/stickshift-controller/app/models/application.rb, line 1266 def get_name_prefix return "@@app" end
# File lib/stickshift-controller/app/models/application.rb, line 1109 def get_public_ip_address begin return self.container.get_public_ip_address rescue Exception=>e Rails.logger.debug e.backtrace.inspect return nil end end
Provides an array version of the group instance map for saving in the datastore. @return [Array<Hash>]
# File lib/stickshift-controller/app/models/application.rb, line 1234 def group_instances @group_instance_map = {} if @group_instance_map.nil? values = @group_instance_map.values.uniq keys = @group_instance_map.keys values.each do |group_inst| group_inst.reused_by = keys.clone.delete_if{ |k| @group_instance_map[k] != group_inst } end values end
Rebuilds the group instance map from an array of hashes or objects @param [Array<Hash>] data
# File lib/stickshift-controller/app/models/application.rb, line 1248 def group_instances=(data) group_instance_map_will_change! @group_instance_map = {} if @group_instance_map.nil? data.each do |value| if value.class == GroupInstance value.reused_by.each do |k| @group_instance_map[k] = value end else ginst = GroupInstance.new(self) ginst.attributes=value ginst.reused_by.each do |k| @group_instance_map[k] = ginst end end end end
Get path for checking application health @return [String]
# File lib/stickshift-controller/app/models/application.rb, line 1337 def health_check_path case self.framework_cartridge when 'php' page = 'health_check.php' when 'perl' page = 'health_check.pl' else page = 'health' end end
# File lib/stickshift-controller/app/models/application.rb, line 961 def prepare_namespace_update(dns_service, new_ns, old_ns) updated = true result_io = ResultIO.new begin self.gears.each do |gear| gear_result_io = gear.prepare_namespace_update(dns_service, new_ns, old_ns) updated = false unless gear_result_io.exitcode == 0 result_io.append gear_result_io end rescue Exception => e result_io.append e.resultIO if e.respond_to?('resultIO') updated = false Rails.logger.debug "Exception caught updating namespace #{e.message}" Rails.logger.debug "DEBUG: Exception caught updating namespace #{e.message}" Rails.logger.debug e.backtrace end return { :success => updated, :result_io => result_io } end
# File lib/stickshift-controller/app/models/application.rb, line 1348 def process_cartridge_commands(result) commands = result.cart_commands commands.each do |command_item| case command_item[:command] when "SYSTEM_SSH_KEY_ADD" key = command_item[:args][0] self.user.add_system_ssh_key(self.name, key) when "SYSTEM_SSH_KEY_REMOVE" self.user.remove_system_ssh_key(self.name) when "ENV_VAR_ADD" key = command_item[:args][0] value = command_item[:args][1] self.user.add_env_var(key,value) when "ENV_VAR_REMOVE" key = command_item[:args][0] self.user.remove_env_var(key) when "BROKER_KEY_ADD" iv, token = StickShift::AuthService.instance.generate_broker_key(self) self.user.add_save_job('adds', 'broker_auth_keys', [self.uuid, iv, token]) when "BROKER_KEY_REMOVE" self.user.add_save_job('removes', 'broker_auth_keys', [self.uuid]) end end if user.save_jobs user.save end commands.clear end
# File lib/stickshift-controller/app/models/application.rb, line 946 def recreate_dns reply = ResultIO.new self.class.notify_observers(:before_recreate_dns, {:application => self, :reply => reply}) dns = StickShift::DnsService.instance begin public_hostname = self.container.get_public_hostname dns.modify_application(@name, @domain.namespace, public_hostname) dns.publish ensure dns.close end self.class.notify_observers(:after_recreate_dns, {:application => self, :reply => reply}) reply end
Reload a particular dependency on all gears that host it. @param [String] dependency Name of a cartridge to reload. Set to nil for all dependencies.
# File lib/stickshift-controller/app/models/application.rb, line 638 def reload(dependency=nil) reply = ResultIO.new self.class.notify_observers(:before_reload, {:application => self, :reply => reply, :dependency => dependency}) self.start_order.each do |comp_inst_name| comp_inst = self.comp_instance_map[comp_inst_name] next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.reload(comp_inst) end raise f[0][:exception] if(f.length > 0) end self.class.notify_observers(:after_reload, {:application => self, :reply => reply, :dependency => dependency}) reply end
# File lib/stickshift-controller/app/models/application.rb, line 1024 def remove_alias(server_alias) self.aliases = [] unless self.aliases reply = ResultIO.new begin reply.append self.container.remove_alias(self, self.gear, self.framework, server_alias) rescue Exception => e Rails.logger.debug e.message Rails.logger.debug e.backtrace.inspect raise ensure if self.aliases.include? server_alias self.aliases.delete(server_alias) self.save else raise StickShift::UserException.new("Alias '#{server_alias}' does not exist for '#{@name}'", 255, reply) end end reply end
# File lib/stickshift-controller/app/models/application.rb, line 862 def remove_broker_key reply = ResultIO.new s,f = run_on_gears(nil,reply,false) do |gear,r| r.append gear.remove_broker_auth_key end raise f[0][:exception] if(f.length > 0) reply end
# File lib/stickshift-controller/app/models/application.rb, line 1070 def remove_dependency(dep) reply = ResultIO.new self.class.notify_observers(:before_remove_dependency, {:application => self, :dependency => dep, :reply => reply}) self.embedded = {} unless self.embedded raise StickShift::UserException.new("#{dep} not embedded in '#{@name}', try adding it first", 101) unless self.embedded.include? dep raise StickShift::UserException.new("#{dep} is not allowed to be removed from '#{@name}'. It is a required dependency for a scalable application.", 101) if (self.scalable and self.proxy_cartridge==dep) remove_from_requires_feature(dep) elaborate_descriptor { |removed_component_instances| #remove unused components removed_component_instances.each do |comp_inst_name| comp_inst = self.comp_instance_map[comp_inst_name] next if comp_inst.parent_cart_name == self.name group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| unless gear.configured_components.length == 1 && gear.configured_components.first == comp_inst.name reply.append gear.deconfigure(comp_inst) process_cartridge_commands(r) end end f.each do |failed_data| Rails.logger.debug("Failed to deconfigure cartridge #{comp_inst.parent_cart_name} on gear #{failed_data[:gear].server_identity}:#{failed_data[:gear].uuid}") Rails.logger.debug("Exception #{failed_data[:exception].message}") Rails.logger.debug("#{failed_data[:exception].backtrace.inspect}") end run_on_gears(group_inst.gears, reply, false) do |gear, r| if gear.configured_components.empty? || (gear.configured_components.length == 1 && gear.configured_components.first == comp_inst.name) reply.append group_inst.remove_gear(gear) end end end } self.save self.class.notify_observers(:after_remove_dependency, {:application => self, :dependency => dep, :reply => reply}) reply end
# File lib/stickshift-controller/app/models/application.rb, line 842 def remove_env_var(key) reply = ResultIO.new s,f = run_on_gears(nil,reply,false) do |gear,r| r.append gear.remove_env_var(key) end raise f[0][:exception] if(f.length > 0) reply end
# File lib/stickshift-controller/app/models/application.rb, line 148 def remove_from_requires_feature(feature) prof = @profile_name_map[@default_profile] if prof.connection_name_map prof.connection_name_map.delete_if {|k,v| v.components[0].include? feature or v.components[1].include? feature } end if self.scalable comp_name = "proxy" if comp_name.nil? prof = @profile_name_map[@default_profile] cinst = ComponentInstance::find_component_in_cart(prof, self, comp_name, self.get_name_prefix) raise StickShift::NodeException.new("Cannot find component '#{comp_name}' in app #{self.name}.", "-101", result_io) if cinst.nil? comp,profile,cart = cinst.get_component_definition(self) raise StickShift::UserException.new("#{feature} not embedded in '#{@name}', try adding it first", 101) if not comp.depends.include? feature comp.depends.delete(feature) else self.requires_feature.delete feature end end
Restart a particular dependency on all gears that host it. @param [String] dependency Name of a cartridge to restart. Set to nil for all dependencies.
# File lib/stickshift-controller/app/models/application.rb, line 618 def restart(dependency=nil) reply = ResultIO.new self.class.notify_observers(:before_restart, {:application => self, :reply => reply, :dependency => dependency}) self.start_order.each do |comp_inst_name| comp_inst = self.comp_instance_map[comp_inst_name] next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.restart(comp_inst) end raise f[0][:exception] if(f.length > 0) end self.class.notify_observers(:after_restart, {:application => self, :reply => reply, :dependency => dependency}) reply end
Saves the application object in the datastore
# File lib/stickshift-controller/app/models/application.rb, line 258 def save super(user.login) self.ngears = 0 self.usage_records = nil self.destroyed_gears = [] end
# File lib/stickshift-controller/app/models/application.rb, line 394 def scaledown(comp_name=nil) result_io = ResultIO.new if not self.scalable raise StickShift::UserException.new("Cannot scale a non-scalable application", 255, result_io) end comp_name = "web" if comp_name.nil? prof = @profile_name_map[@default_profile] cinst = ComponentInstance::find_component_in_cart(prof, self, comp_name, self.get_name_prefix) raise StickShift::NodeException.new("Cannot find #{comp_name} in app #{self.name}.", 1, result_io) if cinst.nil? ginst = self.group_instance_map[cinst.group_instance_name] raise StickShift::NodeException.new("Cannot find group #{cinst.group_instance_name} for #{comp_name} in app #{self.name}.", 1, result_io) if ginst.nil? # remove any gear out of this ginst raise StickShift::UserException.new("Cannot scale below minimum gear requirements for group '#{ginst.min}'", 1, result_io) if ginst.gears.length <= ginst.min gear = ginst.gears.first dns = StickShift::DnsService.instance begin dns.deregister_application(gear.name, @domain.namespace) dns.publish ensure dns.close end result_io.append ginst.remove_gear(gear) # inform anyone who needs to know that this gear is no more self.configure_dependencies self.execute_connections result_io end
# File lib/stickshift-controller/app/models/application.rb, line 372 def scaleup(comp_name=nil) result_io = ResultIO.new if not self.scalable raise StickShift::UserException.new("Cannot scale a non-scalable application", 255, result_io) end comp_name = "web" if comp_name.nil? prof = @profile_name_map[@default_profile] cinst = ComponentInstance::find_component_in_cart(prof, self, comp_name, self.get_name_prefix) raise StickShift::NodeException.new("Cannot find #{comp_name} in app #{self.name}.", 1, result_io) if cinst.nil? ginst = self.group_instance_map[cinst.group_instance_name] raise StickShift::NodeException.new("Cannot find group #{cinst.group_instance_name} for #{comp_name} in app #{self.name}.", 1, result_io) if ginst.nil? raise StickShift::UserException.new("Cannot scale up beyond maximum gear limit '#{ginst.max}' in app #{self.name}.", 104, result_io) if ginst.gears.length >= ginst.max and ginst.max > 0 raise StickShift::UserException.new("Cannot scale up beyond gear limit '#{user.max_gears}'", 104, result_io) if user.consumed_gears >= user.max_gears result, new_gear = ginst.add_gear(self) result_io.append result result_io.append self.configure_dependencies self.execute_connections result_io end
# File lib/stickshift-controller/app/models/application.rb, line 1138 def scaling_limits(dependency=nil) if dependency.nil? if self.scalable dependency = "web" else dependency = self.framework end end prof = @profile_name_map[@default_profile] cinst = ComponentInstance::find_component_in_cart(prof, self, dependency, self.get_name_prefix) raise StickShift::NodeException.new("Cannot find #{dependency} component in app #{self.name}.", "-101", result_io) if cinst.nil? ginst = self.group_instance_map[cinst.group_instance_name] return ginst.min,ginst.max end
Provide a way of updating the component information for a given cartridge @deprecated
# File lib/stickshift-controller/app/models/application.rb, line 1203 def set_embedded_cart_info(cart_name, info) self.comp_instance_map.values.each do |comp_inst| comp_inst.cart_data = [info] if cart_name == comp_inst.parent_cart_name end end
# File lib/stickshift-controller/app/models/application.rb, line 770 def show_port(dependency=nil) reply = ResultIO.new self.comp_instance_map.each do |comp_inst_name, comp_inst| next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) next if comp_inst.name == "@@app" next if comp_inst.parent_cart_name == self.name Rails.logger.debug( comp_inst.inspect ) Rails.logger.debug( "\n" ) group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.show_port(comp_inst) end # Not all cartridges will have this hook. f.each do |fail| next if fail[:exception].resultIO.exitcode == 127 raise fail[:exception] end end reply end
Get the state of the application on all gears.
# File lib/stickshift-controller/app/models/application.rb, line 796 def show_state() gear_states = {} tag = "" handle = RemoteJob.create_parallel_job RemoteJob.run_parallel_on_gears(self.gears, handle) { |exec_handle, gear| job = gear.app_state_job_show() RemoteJob.add_parallel_job(exec_handle, tag, gear, job) } RemoteJob.get_parallel_run_results(handle) { |tag, gear, output, status| if status != 0 Rails.logger.error("Error getting application state from gear: '#{gear}' with status: '#{status}' and output: #{output}", 143) gear_states[gear] = 'unknown' else gear_states[gear] = output end } gear_states end
Start a particular dependency on all gears that host it. If unable to start a component, the application is stopped on all gears @param [String] dependency Name of a cartridge to start. Set to nil for all dependencies. @param [Boolean] force_stop_on_failure
# File lib/stickshift-controller/app/models/application.rb, line 546 def start(dependency=nil, stop_on_failure=true) reply = ResultIO.new self.class.notify_observers(:before_start, {:application => self, :reply => reply, :dependency => dependency}) self.start_order.each do |comp_inst_name| comp_inst = self.comp_instance_map[comp_inst_name] next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) next if comp_inst.parent_cart_name == self.name begin group_inst = self.group_instance_map[comp_inst.group_instance_name] run_on_gears(group_inst.gears, reply) do |gear, r| r.append gear.start(comp_inst) end rescue Exception => e gear_exception = e.message[:exception] self.stop(dependency,false,false) if stop_on_failure raise gear_exception end end self.class.notify_observers(:after_start, {:application => self, :reply => reply, :dependency => dependency}) reply end
Retrieves status for a particular dependency on all gears that host it. @param [String] dependency Name of a cartridge
# File lib/stickshift-controller/app/models/application.rb, line 658 def status(dependency=nil) reply = ResultIO.new self.comp_instance_map.each do |comp_inst_name, comp_inst| next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.status(comp_inst) end raise f[0][:exception] if(f.length > 0) end reply end
Stop a particular dependency on all gears that host it. @param [String] dependency Name of a cartridge to start. Set to nil for all dependencies. @param [Boolean] force_stop_on_failure @param [Boolean] throw_exception_on_failure
# File lib/stickshift-controller/app/models/application.rb, line 573 def stop(dependency=nil, force_stop_on_failure=true, throw_exception_on_failure=true) reply = ResultIO.new self.class.notify_observers(:before_stop, {:application => self, :reply => reply, :dependency => dependency}) self.start_order.reverse.each do |comp_inst_name| comp_inst = self.comp_instance_map[comp_inst_name] next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) next if comp_inst.parent_cart_name == self.name group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.stop(comp_inst) end if(f.length > 0) self.force_stop(dependency,false) if(force_stop_on_failure) raise f[0][:exception] if(throw_exception_on_failure) end end self.class.notify_observers(:after_stop, {:application => self, :reply => reply, :dependency => dependency}) reply end
Invokes #system_messages for a particular dependency on all gears that host it. @param [String] dependency Name of a cartridge
# File lib/stickshift-controller/app/models/application.rb, line 709 def system_messages(dependency=nil) reply = ResultIO.new self.comp_instance_map.each do |comp_inst_name, comp_inst| next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.system_messages(comp_inst) end raise f[0][:exception] if(f.length > 0) end reply end
# File lib/stickshift-controller/app/models/application.rb, line 122 def template_scalable_app(app_name, framework) return " Name: #{app_name} Components: proxy: Dependencies: [#{framework}, \"haproxy-1.4\"] web: Dependencies: [#{framework}] Groups: proxy: Components: proxy: proxy web: Components: web: web GroupOverrides: - [\"proxy\", \"proxy/haproxy-1.4\"] - [\"proxy\", \"proxy/#{framework}\"] - [\"web\", \"web/#{framework}\"] Connections: auto-scale: Components: [\"proxy/haproxy-1.4\", \"web/#{framework}\"] Configure-Order: [\"proxy/#{framework}\", \"proxy/haproxy-1.4\"] " end
Invokes threaddump for a particular dependency on all gears that host it. @param [String] dependency Name of a cartridge
# File lib/stickshift-controller/app/models/application.rb, line 692 def threaddump(dependency=nil) reply = ResultIO.new self.comp_instance_map.each do |comp_inst_name, comp_inst| next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.threaddump(comp_inst) end raise f[0][:exception] if(f.length > 0) end reply end
Invokes tidy for a particular dependency on all gears that host it. @param [String] dependency Name of a cartridge
# File lib/stickshift-controller/app/models/application.rb, line 675 def tidy(dependency=nil) reply = ResultIO.new self.comp_instance_map.each do |comp_inst_name, comp_inst| next if !dependency.nil? and (comp_inst.parent_cart_name != dependency) group_inst = self.group_instance_map[comp_inst.group_instance_name] s,f = run_on_gears(group_inst.gears, reply, false) do |gear, r| r.append gear.tidy(comp_inst) end raise f[0][:exception] if(f.length > 0) end reply end
# File lib/stickshift-controller/app/models/application.rb, line 1377 def track_usage(gear, event, usage_type=UsageRecord::USAGE_TYPES[:gear_usage]) if Rails.configuration.usage_tracking[:datastore_enabled] now = Time.now.utc uuid = StickShift::Model.gen_uuid self.usage_records = [] unless usage_records usage_record = UsageRecord.new(event, user, now, uuid, usage_type) case usage_type when UsageRecord::USAGE_TYPES[:gear_usage] usage_record.gear_uuid = gear.uuid usage_record.gear_size = gear.node_profile when UsageRecord::USAGE_TYPES[:addtl_fs_gb] usage_record.gear_uuid = gear.uuid usage_record.addtl_fs_gb = gear.group_instance.addtl_fs_gb end self.usage_records << usage_record self.class.notify_observers(:track_usage, {:gear_uuid => gear.uuid, :login => gear.app.user.login, :event => event, :time => now, :uuid => uuid, :usage_type => usage_type, :gear_size => gear.node_profile, :addtl_fs_gb => gear.group_instance.addtl_fs_gb}) end if Rails.configuration.usage_tracking[:syslog_enabled] usage_string = "User: #{user.login} Event: #{event}" case usage_type when UsageRecord::USAGE_TYPES[:gear_usage] usage_string += " Gear: #{gear.uuid} Gear Size: #{gear.node_profile}" when UsageRecord::USAGE_TYPES[:addtl_fs_gb] usage_string += " Gear: #{gear.uuid} Addtl File System GB: #{gear.group_instance.addtl_fs_gb}" end begin Syslog.open('openshift_usage', Syslog::LOG_PID) { |s| s.notice usage_string } rescue Exception => e # Can't fail because of a secondary logging error Rails.logger.error e.message Rails.logger.error e.backtrace end end end
# File lib/stickshift-controller/app/models/application.rb, line 364 def web_cart return framework end