diff --git a/app/controllers/clients_controller.rb b/app/controllers/clients_controller.rb index 31ccb97..e0f252a 100644 --- a/app/controllers/clients_controller.rb +++ b/app/controllers/clients_controller.rb @@ -1,189 +1,191 @@ class ClientsController < ApplicationController before_action :require_logged_in before_action :fetch_client, only: [:show, :jobs, :logs, :stats, :users, :restore, :run_restore, :restore_selected, :remove_user] - before_action :fetch_logs, only: [:logs] before_action :require_non_blocked_client, only: [:restore, :restore_selected, :run_restore] # GET /clients # POST /clients def index @client_ids = Client.for_user(current_user.id).pluck(:ClientId) @clients = Client.where(ClientId: @client_ids).includes(:jobs) @hosts = current_user.hosts.not_baculized fetch_jobs_info get_charts end # GET /clients/1 def show @schedules = @client.host.job_templates.map(&:schedule) @filesets = @client.host.job_templates.map(&:fileset) @jobs = @client.jobs.backup_type.terminated.group(:name).maximum(:EndTime) end # GET /clients/1/jobs def jobs @jobs = @client.recent_jobs.page(params[:page]) end - # GET /clients/1/logs - def logs; end + # GET /clients/1/logs?job_id=1 + def logs + @job = @client.jobs.find(params[:job_id]) + @logs = @job.logs.page(params[:page]).per(50) + end # GET /clients/1/stats # POST /clients/1/stats def stats get_charts end # GET /clients/1/users def users @users = @client.host.users if @client.manually_inserted? @invitation = @client.host.invitations.new excluded_ids = @users.pluck(:id) + @client.host.invitations.pluck(:user_id) @available_users = User.where(enabled: true).institutional. where.not(id: excluded_ids).pluck(:username, :id) end end # DELETE /clients/1/user def remove_user user = @client.host.users.find(params[:user_id]) redirect_path = users_client_path(@client) if @client.host.users.count == 1 flash[:alert] = 'You can not remove the last user' elsif @client.host.users.delete(user) flash[:success] = if @client.manually_inserted? 'User successfully removed' else 'User must be removed from the VM\'s list from your VM provider too (ViMa or Okeanos).' end if user.id == current_user.id redirect_path = clients_path end else flash[:alert] = 'User not removed, something went wrong' end redirect_to redirect_path end # GET /clients/1/restore def restore @restore_clients = Client.for_user(current_user.id) return if @client.is_backed_up? flash[:error] = 'Can not issue a restore for this client' redirect_to client_path(@client) end # POST /clients/1/run_restore def run_restore @location = params[:restore_location].blank? ? '/tmp/bacula_restore' : params[:restore_location] fileset = params[:fileset] fetch_restore_point fetch_restore_client if params[:commit] == 'Restore All Files' if @location.nil? || fileset.nil? || !@client.host.restore(fileset, @location, @restore_point, @restore_client) flash[:error] = 'Something went wrong, try again later' else msg = "Restore job issued successfully, files will be soon available in #{@location}" msg << " of client #{@restore_client}" if @restore_client.present? flash[:success] = msg end render js: "window.location = '#{client_path(@client)}'" else session[:job_ids] = @client.get_job_ids(fileset, @restore_point) session[:restore_client] = @restore_client Bvfs.new(@client, session[:job_ids]).update_cache render 'select_files' end end # POST /clients/1/restore_selected def restore_selected Bvfs.new(@client, session[:job_ids]). restore_selected_files(params[:files], params[:location], nil, session[:restore_client]) session.delete(:job_ids) session.delete(:restore_client) flash[:success] = "Restore job issued successfully, files will be soon available in #{params[:location]}" redirect_to client_path(@client) end # GET /clients/1/tree?id=1 def tree @client = Client.for_user(current_user.id).find(params[:client_id]) bvfs = Bvfs.new(@client, session[:job_ids]) pathid = params[:id].to_i if pathid.nonzero? bvfs.fetch_dirs(pathid) else bvfs.fetch_dirs end tree = bvfs.extract_dir_id_and_name.map do |id, name| { id: id, text: name, state: { checkbox_disabled: true }, children: true } end if pathid.nonzero? bvfs.fetch_files(pathid) bvfs.extract_file_id_and_name.each do |id, name| tree << { id: id, text: name, type: 'file' } end end render json: tree end private def require_non_blocked_client if @client.host.blocked? flash[:error] = 'Client disabled by admins' redirect_to clients_path end end def fetch_client @client = Client.for_user(current_user.id).find(params[:id]) @client_ids = [@client.id] end def fetch_restore_client if params[:restore_client] @restore_client = Client.for_user(current_user.id).find_by(ClientId: params[:restore_client]).try(:name) end end def fetch_jobs_info @stats = JobStats.new(@client_ids) end def get_charts @job_status = ChartGenerator.job_statuses(@client_ids, days_ago) @job_stats = ChartGenerator.job_stats(@client_ids, days_ago - 1) end def fetch_restore_point if params['restore_time(4i)'].blank? || params['restore_time(5i)'].blank? || params[:restore_date].blank? return nil end @restore_point = begin DateTime.parse( "#{params[:restore_date]} #{params['restore_time(4i)']}:#{params['restore_time(5i)']}:00"). strftime('%Y-%m-%d %H:%M:%S') rescue nil end end end diff --git a/app/views/clients/_header.html.erb b/app/views/clients/_header.html.erb index 881b1de..863d3a5 100644 --- a/app/views/clients/_header.html.erb +++ b/app/views/clients/_header.html.erb @@ -1,10 +1,10 @@ <p id="notice"><%= notice %></p> <%= tabs_with Client: client_path(@client), 'Recent Jobs' => jobs_client_path(@client), - Stats: stats_client_path(@client), Logs: logs_client_path(@client), + Stats: stats_client_path(@client), Users: users_client_path(@client) %> <h2> <%= @client.name %> <%= host_status_label(@client.host) %> </h2> diff --git a/app/views/clients/_log.html.erb b/app/views/clients/_log.html.erb index 0826e59..ddeee99 100644 --- a/app/views/clients/_log.html.erb +++ b/app/views/clients/_log.html.erb @@ -1,9 +1,9 @@ <tr> <td><%= log.log_id %></td> - <td><%= log.job.id %></td> - <td><%= log.job.name %></td> + <td><%= @job.id %></td> + <td><%= @job.name %></td> <td><%= log.time_formatted %></td> <td style='max-width: 650px'><pre class='pre-scrollable'> <%= log.log_text %> </pre></td> </tr> diff --git a/app/views/clients/_recent_job.html.erb b/app/views/clients/_recent_job.html.erb index a7ff17c..fbf12aa 100644 --- a/app/views/clients/_recent_job.html.erb +++ b/app/views/clients/_recent_job.html.erb @@ -1,12 +1,12 @@ <tr class="<%= success_class(recent_job.job_status) %>"> <td><%= recent_job.name %></td> - <td><%= recent_job.job_id %></td> + <td><%= link_to recent_job.job_id, logs_client_path(@client.id, job_id: recent_job.job_id) %></td> <td><%= recent_job.level_human %></td> <td><%= recent_job.fileset %></td> <td><%= recent_job.start_time_formatted %></td> <td><%= recent_job.end_time_formatted %></td> <td><%= recent_job.duration %></td> <td><%= number_to_human_size(recent_job.job_bytes) %></td> <td><%= number_by_magnitude(recent_job.job_files) %></td> <td><%= recent_job.status_human %></td> </tr> diff --git a/app/views/clients/logs.html.erb b/app/views/clients/logs.html.erb index 5388966..90be2b4 100644 --- a/app/views/clients/logs.html.erb +++ b/app/views/clients/logs.html.erb @@ -1,46 +1,57 @@ -<%= render partial: 'header' %> +<p id="notice"><%= notice %></p> + +<ul class="nav nav-tabs" role="tablist"> + <li role="presentation"> + <%= link_to 'Client', client_path(@client), 'aria-controls' => 'client', 'role' => 'tab' %> + </li> + <li class="active" role="presentation"> + <%= link_to 'Recent Jobs', jobs_client_path(@client), + 'aria-controls' => 'recent jobs', 'role' => 'tab' %> + </li> + <li role="presentation"> + <%= link_to 'Stats', stats_client_path(@client), + 'aria-controls' => 'stats', 'role' => 'tab' %> + </li> + <li role="presentation"> + <%= link_to 'Users', users_client_path(@client), + 'aria-controls' => 'users', 'role' => 'tab' %> + </li> +</ul> + +<h2> + <%= @client.name %> + <%= host_status_label(@client.host) %> +</h2> <div class='row'> <div class='col-xs-3'> <h3>Logs <small>(<%= @logs.count %>)</small></h3> </div> <div class="col-xs-4 right text-right"> <%= page_entries_info @logs, entry_name: 'log' %> <%= paginate @logs %> </div> </div> <div class="row"> <div class="col-xs-12"> - <%= bootstrap_form_tag(url: '', method: :get, layout: :inline) do |form| %> - <%= form.text_field :start_date, value: @dates[:start], - class: 'datepicker' %> - <%= form.text_field :end_date, value: @dates[:end], - class: 'datepicker' %> - <%= form.submit 'Show Logs', class: 'btn btn-default' %> - <% end %> - </div> -</div> - -<div class="row"> - <div class="col-xs-12"> <div class="datatable-wrapper"> <div class="table-responsive"> <table id="logs" class="table table-striped table-bordered table-condensed"> <thead> <tr> <th>LogId</th> <th>JobId</th> <th>Job</th> <th>Time</th> <th class="no-order">Text</th> </tr> </thead> <tbody> <%= render partial: 'log', collection: @logs %> </tbody> </table> </div> </div> </div> </div>