def move_gear(app, gear, destination_container, destination_district_uuid, allow_change_district, node_profile)
reply = ResultIO.new
state_map = {}
gear.node_profile = node_profile if node_profile
orig_uid = gear.uid
destination_container, destination_district_uuid, keep_uid = resolve_destination(app, gear, destination_container, destination_district_uuid, allow_change_district)
source_container = gear.container
destination_node_profile = destination_container.get_node_profile
if app.scalable and source_container.get_node_profile != destination_node_profile
log_debug "Cannot change node_profile for a gear belonging to a scalable application. The destination container's node profile is #{destination_node_profile}, while the gear's node_profile is #{gear.node_profile}"
raise OpenShift::UserException.new("Error moving app. Cannot change node profile.", 1)
end
quota_blocks = nil
quota_files = nil
idle, leave_stopped, quota_blocks, quota_files = get_app_status(app)
gi = app.group_instance_map[gear.group_instance_name]
gi.component_instances.each do |ci_name|
cinst = app.comp_instance_map[ci_name]
cart = cinst.parent_cart_name
next if cart == app.name
state_map[ci_name] = [idle, leave_stopped]
end
begin
reply.append move_gear_pre(app, gear, state_map, keep_uid)
begin
rsync_destination_container(app, gear, destination_container, destination_district_uuid, quota_blocks, quota_files, keep_uid)
app.configure_order.each do |ci_name|
next if not gi.component_instances.include? ci_name
cinst = app.comp_instance_map[ci_name]
cart = cinst.parent_cart_name
next if cart == app.name
idle, leave_stopped = state_map[ci_name]
if embedded_carts.include? cart
if app.scalable and cart.include? app.proxy_cartridge
log_debug "DEBUG: Performing cartridge level move for '#{cart}' on #{destination_container.id}"
reply.append destination_container.send(:run_cartridge_command, cart, app, gear, "move", idle ? '--idle' : nil, false)
else
log_debug "DEBUG: Performing cartridge level move for embedded #{cart} for '#{app.name}' on #{destination_container.id}"
embedded_reply = destination_container.send(:run_cartridge_command, "embedded/" + cart, app, gear, "move", nil, false)
component_details = embedded_reply.appInfoIO.string
unless component_details.empty?
app.set_embedded_cart_info(cart, component_details)
end
reply.append embedded_reply
unless keep_uid
log_debug "DEBUG: Performing cartridge level post-move for embedded #{cart} for '#{app.name}' on #{destination_container.id}"
reply.append destination_container.send(:run_cartridge_command, "embedded/" + cart, app, gear, "post-move", nil, false)
end
end
end
if framework_carts.include? cart
log_debug "DEBUG: Performing cartridge level move for '#{cart}' on #{destination_container.id}"
reply.append destination_container.send(:run_cartridge_command, cart, app, gear, "move", idle ? '--idle' : nil, false)
end
if app.scalable and not cart.include? app.proxy_cartridge
begin
reply.append destination_container.expose_port(app, gear, cinst.parent_cart_name)
rescue Exception=>e
end
end
end
reply.append move_gear_post(app, gear, destination_container, state_map)
app.elaborate_descriptor
app.execute_connections
if app.scalable
app.start_order.reverse.each do |ci_name|
next if not gi.component_instances.include? ci_name
cinst = app.comp_instance_map[ci_name]
cart = cinst.parent_cart_name
next if cart==app.name
idle, leave_stopped = state_map[ci_name]
if leave_stopped and cart.include? app.proxy_cartridge
log_debug "DEBUG: Explicitly stopping cartridge '#{cart}' in '#{app.name}' after move on #{destination_container.id}"
reply.append destination_container.stop(app, gear, cart)
end
end
end
if gear.node_profile != destination_node_profile
log_debug "DEBUG: The gear's node profile changed from #{gear.node_profile} to #{destination_node_profile}"
gear.node_profile = destination_node_profile
if not app.scalable
app.node_profile = destination_node_profile
gi.node_profile = destination_node_profile
end
end
app.save
rescue Exception =>e
gear.container = source_container
log_debug "DEBUG: Moving failed. Rolling back gear '#{gear.name}' '#{app.name}' with remove-httpd-proxy on '#{destination_container.id}'"
gi.component_instances.each do |ci_name|
cinst = app.comp_instance_map[ci_name]
cart = cinst.parent_cart_name
next if cart == app.name
if framework_carts.include? cart
begin
reply.append destination_container.send(:run_cartridge_command, cart, app, gear, "remove-httpd-proxy", nil, false)
rescue Exception => e
log_debug "DEBUG: Remove httpd proxy with cart '#{cart}' failed on '#{destination_container.id}' - gear: '#{gear.name}', app: '#{app.name}'"
end
end
end
log_debug "DEBUG: Moving failed. Rolling back gear '#{gear.name}' in '#{app.name}' with destroy on '#{destination_container.id}'"
reply.append destination_container.destroy(app, gear, keep_uid, nil, true)
raise
end
rescue Exception => e
begin
unless keep_uid
gi.component_instances.each do |ci_name|
cinst = app.comp_instance_map[ci_name]
cart = cinst.parent_cart_name
next if cart==app.name
proxy_cart = (app.proxy_cartridge or "")
if embedded_carts.include? cart and not cart.include? proxy_cart
begin
log_debug "DEBUG: Performing cartridge level post-move for embedded #{cart} for '#{app.name}' on #{source_container.id}"
reply.append source_container.send(:run_cartridge_command, "embedded/" + cart, app, gear, "post-move", nil, false)
rescue Exception => e
log_error "ERROR: Error performing cartridge level post-move for embedded #{cart} for '#{app.name}' on #{source_container.id}: #{e.message}"
end
end
end
end
gi.component_instances.each do |ci_name|
cinst = app.comp_instance_map[ci_name]
cart = cinst.parent_cart_name
next if cart==app.name
idle, leave_stopped = state_map[ci_name]
if not leave_stopped
reply.append source_container.run_cartridge_command(cart, app, gear, "start", nil, false) if framework_carts.include? cart
end
end
ensure
raise
end
end
move_gear_destroy_old(app, gear, keep_uid, orig_uid, source_container, destination_container)
log_debug "Successfully moved '#{app.name}' with gear uuid '#{gear.uuid}' from '#{source_container.id}' to '#{destination_container.id}'"
reply
end