Project

General

Profile

Download (7.64 KB) Statistics
| Branch: | Tag: | Revision:
#
# Copyright 2014 Red Hat, Inc.
#
# This software is licensed to you under the GNU General Public
# License as published by the Free Software Foundation; either version
# 2 of the License (GPLv2) or (at your option) any later version.
# There is NO WARRANTY for this software, express or implied,
# including the implied warranties of MERCHANTABILITY,
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
# have received a copy of GPLv2 along with this software; if not, see
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.

# rubocop:disable ClassVars
module Katello
class SyncManagementController < Katello::ApplicationController
include TranslationHelper
include ActionView::Helpers::DateHelper
include ActionView::Helpers::NumberHelper
include SyncManagementHelper::RepoMethods
respond_to :html, :json

# to avoid problems when generating Headpin documenation when
# building RPMs
if Katello.config.use_pulp
@@status_values = { PulpSyncStatus::Status::WAITING => _("Queued."),
PulpSyncStatus::Status::FINISHED => _("Sync complete."),
PulpSyncStatus::Status::ERROR => _("Error syncing!"),
PulpSyncStatus::Status::RUNNING => _("Running."),
PulpSyncStatus::Status::CANCELED => _("Canceled."),
PulpSyncStatus::Status::NOT_SYNCED => ""}
else
@@status_values = {}
end

before_filter :find_provider, :except => [:index, :sync, :sync_status, :manage]
before_filter :find_providers, :only => [:sync, :sync_status]
before_filter :authorize

def menu_definition
{:manage => :admin_menu}.with_indifferent_access
end

def section_id
'contents'
end

def rules

list_test = lambda{current_organization && Provider.any_readable?(current_organization) }
sync_read_test = lambda do
@providers.each { |prov| return false if !prov.readable? }
return true
end
sync_test = lambda {current_organization && current_organization.syncable?}

{ :index => list_test,
:manage => list_test,
:sync_status => sync_read_test,
:product_status => sync_read_test,
:sync => sync_test,
:destroy => sync_test
}
end

def index
org = current_organization
@products = org.library.products.readable(org)
redhat_products, custom_products = @products.partition(&:redhat?)
redhat_products.sort_by { |p| p.name.downcase }
custom_products.sort_by { |p| p.name.downcase }

@products = redhat_products + custom_products
@product_size = {}
@repo_status = {}
@product_map = collect_repos(@products, org.library, false, false)

@products.each { |product| get_product_info(product) }
end

def manage
@products = []
@sproducts = []
@product_map = []
@product_size = {}
@repo_status = {}
@show_org = true

User.current.allowed_organizations.each do |org|
products = org.library.products.readable(org)
next if products.blank?
@sproducts.concat products.select(&:syncable_content?)
@product_map.concat collect_repos(products, org.library)
products.each { |product| get_product_info(product) }
@products.concat products
end

@sync_plans = SyncPlan.all
end

def sync
ids = sync_repos(params[:repoids]) || {}
respond_with(ids) do |format|
format.js { render :json => ids.to_json, :status => :ok }
end
end

def sync_status
collected = []
params[:repoids].each do |id|
begin
repo = Repository.find(id)
progress = format_sync_progress(repo.sync_status, repo)
collected.push(progress)
rescue ActiveRecord::RecordNotFound => e
notify.exception e # debugging and skip for now
next
end
end

respond_with(collected) do |format|
format.js { render :json => collected.to_json, :status => :ok }
end
end

def destroy
Repository.find(params[:id]).cancel_sync
render :text => ""
end

private

def find_provider
Repository.find(params[:repo] || params[:id]).product.provider
end

def find_providers
ids = params[:repoids]
ids = [params[:repoids]] if !params[:repoids].is_a? Array
@providers = []
ids.each do |id|
repo = Repository.find(id)
@providers << repo.product.provider
end
end

def format_sync_progress(sync_status, repo)
progress = sync_status.progress
error_details = progress.error_details

not_running_states = [PulpSyncStatus::Status::FINISHED,
PulpSyncStatus::Status::ERROR,
PulpSyncStatus::Status::WAITING,
PulpSyncStatus::Status::CANCELED,
PulpSyncStatus::Status::NOT_SYNCED]
{ :id => repo.id,
:product_id => repo.product.id,
:progress => calc_progress(sync_status, repo.content_type),
:sync_id => sync_status.uuid,
:state => format_state(sync_status.state),
:raw_state => sync_status.state,
:start_time => format_date(sync_status.start_time),
:finish_time => format_date(sync_status.finish_time),
:duration => format_duration(sync_status.finish_time, sync_status.start_time),
:packages => sync_status.progress.total_count,
:display_size => number_to_human_size(sync_status.progress.total_size),
:size => sync_status.progress.total_size,
:is_running => !not_running_states.include?(sync_status.state.to_sym),
:error_details => error_details ? error_details : "No errors."
}
end

def format_state(state)
@@status_values[state.to_sym]
end

def format_duration(finish, start)
retval = nil
if !finish.nil? && !start.nil?
retval = distance_of_time_in_words(finish, start)
end
retval
end

def format_date(check_date)
retval = nil
if !check_date.nil?
retval = relative_time_in_words(check_date)
end
retval
end

# loop through checkbox list of products and sync
def sync_repos(repos)
repos = [repos] if !repos.is_a? Array
collected = []
repos.each do |id|
repo = Repository.find(id)
begin
resp = repo.sync(:notify => true).first
collected.push(:id => id, :product_id => repo.product.id, :state => resp[:state])
rescue RestClient::Conflict
notify.error N_("There is already an active sync process for the '%s' repository. Please try again later") %
repo.name
end
end
collected
end

# calculate the % complete of ongoing sync from pulp
def calc_progress(val, content_type)

if content_type == Repository::PUPPET_TYPE
completed = val.progress.total_count - val.progress.items_left
progress = if val.state =~ /error/i then -1
elsif val.progress.total_count == 0 then 0
else completed.to_f / val.progress.total_count.to_f * 100
end
else
completed = val.progress.total_size - val.progress.size_left
progress = if val.state =~ /error/i then -1
elsif val.progress.total_size == 0 then 0
else completed.to_f / val.progress.total_size.to_f * 100
end
end

{:count => val.progress.total_count,
:left => val.progress.items_left,
:progress => progress
}
end

def get_product_info(product)
product_size = 0
product.repos(product.organization.library).each do |repo|
status = repo.sync_status
@repo_status[repo.id] = format_sync_progress(status, repo)
product_size += status.progress.total_size
end
@product_size[product.id] = number_to_human_size(product_size)
end
end
end
(27-27/31)