# File lib/openshift-origin-node/model/application_container.rb, line 64 def self.get_build_model(user, config) # TODO: When v2 is the default cartridge format change this default... build_model = :v1 if user.homedir && File.exist?(user.homedir) build_model = :v2 if OpenShift::Utils::Sdk.new_sdk_app?(user.homedir) else build_model = OpenShift::Utils::Sdk.node_default_model(config) end build_model end
# File lib/openshift-origin-node/model/application_container.rb, line 41 def initialize(application_uuid, container_uuid, user_uid = nil, app_name = nil, container_name = nil, namespace = nil, quota_blocks = nil, quota_files = nil, logger = nil) @config = OpenShift::Config.new @uuid = container_uuid @application_uuid = application_uuid @container_name = container_name @user = UnixUser.new(application_uuid, container_uuid, user_uid, app_name, container_name, namespace, quota_blocks, quota_files) @state = OpenShift::Utils::ApplicationState.new(container_uuid) build_model = self.class.get_build_model(@user, @config) # When v2 is the default cartridge format flip the test... if build_model == :v1 @cartridge_model = V1CartridgeModel.new(@config, @user) else @cartridge_model = V2CartridgeModel.new(@config, @user) end NodeLogger.logger.debug("Creating #{build_model} model for #{container_uuid}: #{__callee__}") end
build application
# File lib/openshift-origin-node/model/application_container.rb, line 375 def build(cart_name) @state.value = OpenShift::State::BUILDING @cartridge_model.do_control("build", cart_name) end
Add cartridge to gear. This method establishes the cartridge model to use, but does not mark the application. Marking the application is the responsibility of the cart model.
This method does not enforce constraints on whether the cartridge being added is compatible with other installed cartridges. That is the responsibility of the broker.
context: root -> gear user -> root @param cart_name cartridge name
# File lib/openshift-origin-node/model/application_container.rb, line 91 def configure(cart_name, template_git_url=nil) @cartridge_model.configure(cart_name, template_git_url) end
# File lib/openshift-origin-node/model/application_container.rb, line 331 def connector_execute(cart_name, connector, args) @cartridge_model.connector_execute(cart_name, connector, args) end
create gear
model/unix_user.rb
context: root
# File lib/openshift-origin-node/model/application_container.rb, line 107 def create notify_observers(:before_container_create) @user.create if :v2 == OpenShift::Utils::Sdk.node_default_model(@config) Utils::Sdk.mark_new_sdk_app(@user.homedir) end notify_observers(:after_container_create) end
Creates public endpoints for the given cart. Public proxy mappings are created via the FrontendProxyServer, and the resulting mapped ports are written to environment variables with names based on the cart manifest endpoint entries.
Returns nil on success, or raises an exception if any errors occur: all errors here are considered fatal.
# File lib/openshift-origin-node/model/application_container.rb, line 149 def create_public_endpoints(cart_name) env = Utils::Environ::for_gear(@user.homedir) cart = @cartridge_model.get_cartridge(cart_name) proxy = OpenShift::FrontendProxyServer.new # TODO: better error handling cart.public_endpoints.each do |endpoint| # Load the private IP from the gear private_ip = env[endpoint.private_ip_name] if private_ip == nil raise "Missing private IP #{endpoint.private_ip_name} for cart #{cart.name} in gear #{@uuid}, " "required to create public endpoint #{endpoint.public_port_name}" end # Attempt the actual proxy mapping assignment public_port = proxy.add(@user.uid, private_ip, endpoint.private_port) @user.add_env_var(endpoint.public_port_name, public_port) logger.info("Created public endpoint for cart #{cart.name} in gear #{@uuid}: " "[#{endpoint.public_port_name}=#{public_port}]") end end
Remove cartridge from gear
context: root -> gear user -> root @param cart_name cartridge name
# File lib/openshift-origin-node/model/application_container.rb, line 99 def deconfigure(cart_name) @cartridge_model.deconfigure(cart_name) end
Deletes all public endpoints for the given cart. Public port mappings are looked up and deleted using the FrontendProxyServer, and all corresponding environment variables are deleted from the gear.
Returns nil on success. Failed public port delete operations are logged and skipped.
# File lib/openshift-origin-node/model/application_container.rb, line 181 def delete_public_endpoints(cart_name) env = Utils::Environ::for_gear(@user.homedir) cart = @cartridge_model.get_cartridge(cart_name) proxy = OpenShift::FrontendProxyServer.new public_ports = [] public_port_vars = [] cart.public_endpoints.each do |endpoint| # Load the private IP from the gear private_ip = env[endpoint.private_ip_name] public_port_vars << endpoint.public_port_name public_port = proxy.find_mapped_proxy_port(@user.uid, private_ip, endpoint.private_port) public_ports << public_port unless public_port == nil end begin # Remove the proxy entries rc = proxy.delete_all(public_ports, true) logger.info("Deleted all public endpoints for cart #{cart.name} in gear #{@uuid}\n" "Endpoints: #{public_port_vars}\n" "Public ports: #{public_ports}") rescue => e logger.warn(%Q{Couldn't delete all public endpoints for cart #{cart.name} in gear #{@uuid}: #{e.message} Endpoints: #{public_port_vars} Public ports: #{public_ports} #{e.backtrace} }) end # Clean up the environment variables public_port_vars.each { |var| @user.remove_env_var(var) } end
deploy application
# File lib/openshift-origin-node/model/application_container.rb, line 381 def deploy(cart_name) @state.value = OpenShift::State::DEPLOYING @cartridge_model.do_control("deploy", cart_name) end
# File lib/openshift-origin-node/model/application_container.rb, line 335 def deploy_httpd_proxy(cart_name) @cartridge_model.deploy_httpd_proxy(cart_name) end
Destroy gear
model/unix_user.rb
context: root @param skip_hooks should destroy call the gear's hooks before destroying the gear
# File lib/openshift-origin-node/model/application_container.rb, line 123 def destroy(skip_hooks=false) notify_observers(:before_container_destroy) # possible mismatch across cart model versions output, errout, retcode = @cartridge_model.destroy(skip_hooks) notify_observers(:after_container_destroy) return output, errout, retcode end
Public: Sets the app state to “stopped” and causes an immediate forced termination of all gear processes.
TODO: exception handling
# File lib/openshift-origin-node/model/application_container.rb, line 138 def force_stop @state.value = OpenShift::State::STOPPED UnixUser.kill_procs(@user.uid) end
# File lib/openshift-origin-node/model/application_container.rb, line 293 def gear_level_tidy(gear_repo_dir, gear_tmp_dir) # Git pruning tidy_action do OpenShift::Utils::ShellExec.run_as(@user.uid, @user.gid, "git prune", gear_repo_dir, false, 0) logger.debug("Pruned git directory at #{gear_repo_dir}") end # Git GC tidy_action do OpenShift::Utils::ShellExec.run_as(@user.uid, @user.gid, "git gc --aggressive", gear_repo_dir, false, 0) logger.debug("Executed git gc for repo #{gear_repo_dir}") end # Temp dir cleanup tidy_action do FileUtils.rm_rf(Dir.glob(File.join(gear_tmp_dir, "*"))) logger.debug("Cleaned gear temp dir at #{gear_tmp_dir}") end end
# File lib/openshift-origin-node/model/application_container.rb, line 347 def move(cart_name, idle) @cartridge_model.move(cart_name, idle) end
# File lib/openshift-origin-node/model/application_container.rb, line 77 def name @uuid end
# File lib/openshift-origin-node/model/application_container.rb, line 355 def post_move(cart_name) @cartridge_model.post_move(cart_name) end
# File lib/openshift-origin-node/model/application_container.rb, line 351 def pre_move(cart_name) @cartridge_model.pre_move(cart_name) end
reload gear as supported by cartridges
# File lib/openshift-origin-node/model/application_container.rb, line 392 def reload(cart_name) @cartridge_model.do_control("reload", cart_name) end
# File lib/openshift-origin-node/model/application_container.rb, line 339 def remove_httpd_proxy(cart_name) @cartridge_model.remove_httpd_proxy(cart_name) end
restart gear as supported by cartridges
# File lib/openshift-origin-node/model/application_container.rb, line 387 def restart(cart_name) @cartridge_model.do_control("restart", cart_name) end
# File lib/openshift-origin-node/model/application_container.rb, line 343 def restart_httpd_proxy(cart_name) @cartridge_model.restart_httpd_proxy(cart_name) end
restore gear from tar ball
# File lib/openshift-origin-node/model/application_container.rb, line 397 def restore(cart_name) raise NotImplementedError.new("restore") end
write gear to tar ball
# File lib/openshift-origin-node/model/application_container.rb, line 402 def snapshot(cart_name) raise NotImplementedError.new("snapshot") end
start gear Throws ShellExecutionException on failure
# File lib/openshift-origin-node/model/application_container.rb, line 363 def start(cart_name) @state.value = OpenShift::State::STARTED @cartridge_model.do_control("start", cart_name) end
# File lib/openshift-origin-node/model/application_container.rb, line 276 def start_gear(gear_dir) # TODO: remove shell command begin # Start the gear, and if that fails raise an exception, as the app is now # in a bad state. out, err, rc = OpenShift::Utils::ShellExec.shellCmd("/usr/sbin/oo-admin-ctl-gears startgear #{@user.uuid}", gear_dir) logger.debug("Started gear #{@uuid}. Output:\n#{out}") rescue OpenShift::Utils::ShellExecutionException => e logger.error(%Q{ Failed to restart gear #{@uuid} following tidy: #{e.message} --- stdout ---\n#{e.stdout} --- stderr ---\n#{e.stderr} }) raise "Tidy of gear #{@uuid} failed, and the gear was not successfuly restarted" end end
# File lib/openshift-origin-node/model/application_container.rb, line 406 def status(cart_name) @cartridge_model.do_control("status", cart_name) end
stop gear
# File lib/openshift-origin-node/model/application_container.rb, line 369 def stop(cart_name) @state.value = OpenShift::State::STOPPED @cartridge_model.do_control("stop", cart_name) end
# File lib/openshift-origin-node/model/application_container.rb, line 260 def stop_gear(gear_dir) # TODO: remove shell command begin # Stop the gear. If this fails, consider the tidy a failure. out, err, rc = OpenShift::Utils::ShellExec.shellCmd("/usr/sbin/oo-admin-ctl-gears stopgear #{@user.uuid}", gear_dir, false, 0) logger.debug("Stopped gear #{@uuid}. Output:\n#{out}") rescue OpenShift::Utils::ShellExecutionException => e logger.error(%Q{ Couldn't stop gear #{@uuid} for tidy: #{e.message} --- stdout ---\n#{e.stdout} --- stderr ---\n#{e.stderr} }) raise "Tidy failed on gear #{@uuid}; the gear couldn't be stopped successfully" end end
# File lib/openshift-origin-node/model/application_container.rb, line 410 def threaddump(cart_name) @cartridge_model.do_control("threaddump", cart_name) end
Public: Cleans up the gear, providing any installed cartridges with the opportunity to perform their own cleanup operations via the tidy hook.
The generic gear-level cleanup flow is:
Stop the gear
Git cleanup
Gear temp dir cleanup
Cartridge tidy hook executions
Start the gear
Raises an Exception if an internal error occurs, and ignores failed cartridge tidy hook executions.
# File lib/openshift-origin-node/model/application_container.rb, line 232 def tidy logger.debug("Starting tidy on gear #{@uuid}") env = Utils::Environ::for_gear(@user.homedir) gear_dir = env['OPENSHIFT_HOMEDIR'] app_name = env['OPENSHIFT_APP_NAME'] gear_repo_dir = File.join(gear_dir, 'git', "#{app_name}.git") gear_tmp_dir = File.join(gear_dir, '.tmp') stop_gear(gear_dir) # Perform the gear- and cart- level tidy actions. At this point, the gear has # been stopped; we'll attempt to start the gear no matter what tidy operations fail. begin gear_level_tidy(gear_repo_dir, gear_tmp_dir) # Delegate to cartridge model to perform cart-level tidy operations for all installed carts. @cartridge_model.tidy rescue Exception => e logger.warn("An unknown exception occured during tidy for gear #{@uuid}: #{e.message}\n#{e.backtrace}") ensure start_gear(gear_dir) end logger.debug("Completed tidy for gear #{@uuid}") end
Executes a block, trapping ShellExecutionExceptions and treating them as warnings. Any other exceptions are unexpected and will bubble out.
# File lib/openshift-origin-node/model/application_container.rb, line 315 def tidy_action begin yield rescue OpenShift::Utils::ShellExecutionException => e logger.warn(%Q{ Tidy operation failed on gear #{@uuid}: #{e.message} --- stdout ---\n#{e.stdout} --- stderr ---\n#{e.stderr} }) end end
# File lib/openshift-origin-node/model/application_container.rb, line 327 def update_namespace(cart_name, old_namespace, new_namespace) @cartridge_model.update_namespace(cart_name, old_namespace, new_namespace) end