Class: OpenShift::ApplicationContainer
- Inherits:
-
Model
- Object
- Model
- OpenShift::ApplicationContainer
- Includes:
- Utils::ShellExec
- Defined in:
- lib/openshift-origin-node/model/application_container.rb
Overview
Application Container
Defined Under Namespace
Modules: State
Instance Attribute Summary collapse
-
#application_uuid ⇒ Object
readonly
Returns the value of attribute application_uuid.
-
#user ⇒ Object
readonly
Returns the value of attribute user.
-
#uuid ⇒ Object
readonly
Returns the value of attribute uuid.
Instance Method Summary collapse
-
#create ⇒ Object
Create gear - model/unix_user.rb.
-
#destroy(skip_hooks = false) ⇒ Object
Destroy gear - model/unix_user.rb.
-
#force_stop ⇒ Object
Public: Sets the app state to “stopped” and causes an immediate forced termination of all gear processes.
-
#get_app_state ⇒ Object
Public: Fetch application state from gear.
-
#initialize(application_uuid, container_uuid, user_uid = nil, app_name = nil, container_name = nil, namespace = nil, quota_blocks = nil, quota_files = nil, logger = nil) ⇒ ApplicationContainer
constructor
A new instance of ApplicationContainer.
-
#load_env ⇒ Object
Public: Load a gears environment variables into the environment.
- #name ⇒ Object
-
#set_app_state(new_state) ⇒ Object
Public: Sets the application state.
-
#tidy ⇒ Object
Public: Cleans up the gear, providing any installed cartridges with the opportinity to perform their own cleanup operations via the tidy hook.
-
#tidy_action ⇒ Object
Executes a block, trapping ShellExecutionExceptions and treating them as warnings.
Methods included from Utils::ShellExec
Constructor Details
#initialize(application_uuid, container_uuid, user_uid = nil, app_name = nil, container_name = nil, namespace = nil, quota_blocks = nil, quota_files = nil, logger = nil) ⇒ ApplicationContainer
Returns a new instance of ApplicationContainer.
40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 40 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) @logger = logger ||= Logger.new(STDOUT) @config = OpenShift::Config.new @uuid = container_uuid @application_uuid = application_uuid @user = UnixUser.new(application_uuid, container_uuid, user_uid, app_name, container_name, namespace, quota_blocks, quota_files) end |
Instance Attribute Details
#application_uuid ⇒ Object (readonly)
Returns the value of attribute application_uuid.
27 28 29 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 27 def application_uuid @application_uuid end |
#user ⇒ Object (readonly)
Returns the value of attribute user.
27 28 29 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 27 def user @user end |
#uuid ⇒ Object (readonly)
Returns the value of attribute uuid.
27 28 29 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 27 def uuid @uuid end |
Instance Method Details
#create ⇒ Object
Create gear - model/unix_user.rb
57 58 59 60 61 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 57 def create notify_observers(:before_container_create) @user.create notify_observers(:after_container_create) end |
#destroy(skip_hooks = false) ⇒ Object
Destroy gear - model/unix_user.rb
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 64 def destroy(skip_hooks=false) notify_observers(:before_container_destroy) hook_timeout=30 output = "" errout = "" retcode = 0 hooks={} ["pre", "post"].each do |hooktype| if @user.homedir.nil? || ! File.exists?(@user.homedir) hooks[hooktype]=[] else hooks[hooktype] = Dir.entries(@user.homedir).map { |cart| [ File.join(@config.get("CARTRIDGE_BASE_PATH"),cart,"info","hooks","#{hooktype}-destroy"), File.join(@config.get("CARTRIDGE_BASE_PATH"),"embedded",cart,"info","hooks","#{hooktype}-destroy"), ].select { |hook| File.exists? hook }[0] }.select { |hook| not hook.nil? }.map { |hook| "#{hook} #{@user.container_name} #{@user.namespace} #{@user.container_uuid}" } end end unless skip_hooks hooks["pre"].each do | cmd | out,err,rc = shellCmd(cmd, "/", true, 0, hook_timeout) errout << err if not err.nil? output << out if not out.nil? retcode = 121 if rc != 0 end end @user.destroy unless skip_hooks hooks["post"].each do | cmd | out,err,rc = shellCmd(cmd, "/", true, 0, hook_timeout) errout << err if not err.nil? output << out if not out.nil? retcode = 121 if rc != 0 end end notify_observers(:after_container_destroy) return output, errout, retcode end |
#force_stop ⇒ Object
Public: Sets the app state to “stopped” and causes an immediate forced termination of all gear processes.
TODO: exception handling
155 156 157 158 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 155 def force_stop set_app_state(:STOPPED) UnixUser.kill_procs(@user.uid) end |
#get_app_state ⇒ Object
Public: Fetch application state from gear. Returns app state as string on Success and ‘unknown’ on Failure
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 117 def get_app_state env = load_env app_state_file=File.join(env[:OPENSHIFT_HOMEDIR], 'app-root', 'runtime', '.state') if File.exists?(app_state_file) app_state = nil File.open(app_state_file) { |input| app_state = input.read.chomp } else app_state = :UNKNOWN end app_state end |
#load_env ⇒ Object
Public: Load a gears environment variables into the environment
Examples
load_env
# => {"OPENSHIFT_APP_NAME"=>"myapp"}
Returns env Array
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 279 def load_env env = {} # Load environment variables into a hash Dir["#{user.homedir}/.env/*"].each { | f | next if File.directory?(f) contents = nil File.open(f) {|input| contents = input.read.chomp index = contents.index('=') contents = contents[(index + 1)..-1] contents = contents[/'(.*)'/, 1] if contents.start_with?("'") contents = contents[/"(.*)"/, 1] if contents.start_with?('"') } env[File.basename(f).intern] = contents } env end |
#name ⇒ Object
52 53 54 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 52 def name @uuid end |
#set_app_state(new_state) ⇒ Object
Public: Sets the application state.
new_state - The new state to assign. Must be an ApplicationContainer::State.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 133 def set_app_state(new_state) new_state_val = nil begin new_state_val = State.const_get(new_state) rescue raise ArgumentError, "Invalid state '#{new_state}' specified" end env = load_env app_state_file = File.join(env[:OPENSHIFT_HOMEDIR], 'app-root', 'runtime', '.state') raise "Couldn't find app state file at #{app_state_file}" unless File.exists?(app_state_file) File.open(app_state_file, File::WRONLY|File::TRUNC|File::CREAT, 0o0660) {|file| file.write "#{new_state_val}\n" } end |
#tidy ⇒ Object
Public: Cleans up the gear, providing any installed cartridges with the opportinity 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.
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 174 def tidy @logger.debug("Starting tidy on gear #{@uuid}") env = load_env 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') begin # Stop the gear. If this fails, consider the tidy a failure. out, err, rc = 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.} --- stdout ---\n#{e.stdout} --- stderr ---\n#{e.stderr} }) raise "Tidy failed on gear #{@uuid}; the gear couldn't be stopped successfully" end # Perform the individual tidy actions. At this point, the gear has been stopped, # and so we'll attempt to start the gear no matter what tidy operations fail. begin # Git pruning tidy_action do out, err, rc = shellCmd("git prune", gear_repo_dir, false, 0) @logger.debug("Pruned git directory at #{gear_repo_dir}. Output:\n#{out}") end # Git GC tidy_action do out, err, rc = shellCmd("git gc --aggressive", gear_repo_dir, false, 0) @logger.debug("Executed git gc for repo #{gear_repo_dir}. Output:\n#{out}") 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 # Execute the tidy hooks in any installed carts, in the context # of the gear user. For now, we detect cart installations by iterating # over the gear subdirs and using the dir names to construct a path # to cart scripts in the base cartridge directory. If such a file exists, # it's assumed the cart is installed on the gear. cart_tidy_timeout = 30 Dir.entries(gear_dir).each do |gear_subdir| tidy_script = File.join(@config.get("CARTRIDGE_BASE_PATH"), gear_subdir, "info", "hooks", "tidy") next unless File.exists?(tidy_script) begin # Execute the hook in the context of the gear user @logger.debug("Executing cart tidy script #{tidy_script} in gear #{@uuid} as user #{@user.uid}:#{@user.gid}") OpenShift::Utils::ShellExec.run_as(@user.uid, @user.gid, tidy_script, gear_dir, false, 0, cart_tidy_timeout) rescue OpenShift::Utils::ShellExecutionException => e @logger.warn("Cartridge tidy operation failed on gear #{@uuid} for cart #{gear_dir}: #{e.} (rc=#{e.rc})") end end rescue Exception => e @logger.warn("An unknown exception occured during tidy for gear #{@uuid}: #{e.}\n#{e.backtrace}") ensure begin # Start the gear, and if that fails raise an exception, as the app is now # in a bad state. out, err, rc = 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.} --- stdout ---\n#{e.stdout} --- stderr ---\n#{e.stderr} }) raise "Tidy of gear #{@uuid} failed, and the gear was not successfuly restarted" end end @logger.debug("Completed tidy for gear #{@uuid}") end |
#tidy_action ⇒ Object
Executes a block, trapping ShellExecutionExceptions and treating them as warnings. Any other exceptions are unexpected and will bubble out.
259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/openshift-origin-node/model/application_container.rb', line 259 def tidy_action begin yield rescue OpenShift::Utils::ShellExecutionException => e @logger.warn(%Q{ Tidy operation failed on gear #{@uuid}: #{e.} --- stdout ---\n#{e.stdout} --- stderr ---\n#{e.stderr} }) end end |