Page Menu
Home
GRNET
Search
Configure Global Search
Log In
Files
F886081
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Fri, Aug 8, 8:43 PM
Size
15 KB
Mime Type
text/x-diff
Expires
Sun, Aug 10, 8:43 PM (21 h, 38 m)
Engine
blob
Format
Raw Data
Handle
246039
Attached To
rARCHIVING archiving
View Options
diff --git a/app/assets/javascripts/clients.js b/app/assets/javascripts/clients.js
index f28100b..3a433e5 100644
--- a/app/assets/javascripts/clients.js
+++ b/app/assets/javascripts/clients.js
@@ -1,41 +1,46 @@
$(document).ready(function() {
if ($('#select-files').size() > 0) {
$('#file-selector').hide();
$('#reset-button').hide();
$('#select-files').click(function() {
$('#file-selector').show();
$('#reset-button').show();
});
}
});
$(document).ready(function() {
if ($('#file-submitter').size() > 0) {
$("#file-tree").on("select_node.jstree",
function(evt, data) {
- add_input(data.node.id);
+ if (data.instance.is_leaf(data.node)) {
+ add_input(data.node.id, $('#file-tree').jstree(true).get_path(data.node, '/'));
+ }
});
$("#file-tree").on("deselect_node.jstree",
function(evt, data) {
remove_input(data.node.id);
});
}
if ($('#invitation_user_id').size() > 0) {
$('#invitation_user_id').chosen();
}
});
-function add_input(id) {
+function add_input(id, name) {
$('#file-submitter').
append('<input type="hidden" name="files[]" multiple="multiple" value="' + id + '" id="js-file-id-' + id + '" class="js-file-input"/>');
+ $('#restore_data_files').
+ append('<li id="restore_data_files_' + id + '">' + name + '</li>');
if ($('.js-file-input').size() > 0 && $('#file-submitter > input[type="submit"]').attr('disabled') == 'disabled') {
$('#file-submitter > input[type="submit"]').attr('disabled', false);
}
}
function remove_input(id) {
$('#js-file-id-' + id).remove();
+ $('#restore_data_files_' + id).remove();
if ($('.js-file-input').size() == 0) {
$('#file-submitter > input[type="submit"]').attr('disabled', true);
}
}
diff --git a/app/controllers/clients_controller.rb b/app/controllers/clients_controller.rb
index 8ddbc87..c915113 100644
--- a/app/controllers/clients_controller.rb
+++ b/app/controllers/clients_controller.rb
@@ -1,189 +1,189 @@
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/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]
- restore_point = fetch_restore_point
- restore_client = fetch_restore_client
+ 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)
+ !@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
+ 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]
- Client.for_user(current_user.id).find_by(ClientId: params[:restore_client]).try(:name)
+ @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 =
- "#{params[:restore_date]} #{params['restore_time(4i)']}:#{params['restore_time(5i)']}:00"
- begin
- DateTime.strptime(restore_point, '%Y-%m-%d %H:%M:%S')
- rescue
- return nil
- end
- restore_point
+ @restore_point =
+ begin
+ DateTime.strptime(
+ "#{params[:restore_date]} #{params['restore_time(4i)']}:#{params['restore_time(5i)']}:00",
+ '%Y-%m-%d %H:%M:%S')
+ rescue
+ nil
+ end
end
end
diff --git a/app/views/clients/_file_selector.html.erb b/app/views/clients/_file_selector.html.erb
index 7b7c98c..aef99b9 100644
--- a/app/views/clients/_file_selector.html.erb
+++ b/app/views/clients/_file_selector.html.erb
@@ -1,22 +1,57 @@
<div id='file-selector' class="col-xs-4">
<div class='panel panel-default'>
<div class='panel-heading'>
<h3> Files </h3>
</div>
<div class="loader">
<h3>LOADING</h3>
</div>
<div id="file-tree"></div>
</div>
</div>
-<div class="col-xs-2">
- <%= form_tag(restore_selected_client_path, { id: 'file-submitter', style: 'display:none' }) do %>
- <%= submit_tag 'Restore Selected Files', class: 'btn btn-default', disabled: true %>
- <% end %>
-</div>
+<div class="col-xs-4">
+ <div class="panel panel-default" id="restore-details" style="display:none">
+ <div class="panel-heading">
+ <h3>Restore details</h3>
+ </div>
+ <div class="panel-body">
+ <div class="row">
+ <div class="col-xs-4" id="reset-button">
+ <%= link_to restore_client_path(@client), class: 'btn btn-default' do %>
+ <span class="glyphicon glyphicon-menu-left text-primary"></span>
+ Cancel
+ <% end %>
+ </div>
-<div class="col-xs-1" id="reset-button">
- <%= link_to 'Cancel', restore_client_path(@client), role: 'button',
- class: 'btn btn-default text-warning' %>
+ <div class="col-xs-4 text-right">
+ <%= form_tag(restore_selected_client_path, { id: 'file-submitter' }) do %>
+ <%= submit_tag 'Restore Selected Files', class: 'btn btn-default', disabled: true %>
+ <% end %>
+ </div>
+ </div>
+ <hr />
+ <br />
+ <div class="row">
+ <table class="table table-bordered table-condensed">
+ <tr>
+ <td>DateTime</td>
+ <td id="restore_data_point"></td>
+ </tr>
+ <tr>
+ <td>Restore Location</td>
+ <td id="restore_data_location"></td>
+ </tr>
+ <tr>
+ <td>Restore Client</td>
+ <td id="restore_data_client"></td>
+ </tr>
+ <tr>
+ <td>Files</td>
+ <td><ul id="restore_data_files"></ul></td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </div>
</div>
diff --git a/app/views/clients/restore.html.erb b/app/views/clients/restore.html.erb
index 8e356f0..7399d41 100644
--- a/app/views/clients/restore.html.erb
+++ b/app/views/clients/restore.html.erb
@@ -1,77 +1,74 @@
<div class="row">
<div class="col-xs-4">
<% if @client.is_backed_up? %>
<div class="panel panel-default">
<div class="panel-heading">
<h3>Restore files for "<%= @client.name %>"</h3>
</div>
<div class="panel-body">
<%= bootstrap_form_tag(url: run_restore_client_path(@client), remote: true,
layout: :horizontal, label_col: 'col-xs-4', control_col: 'col-xs-7',
html: { id: 'basic-form' } ) do |f| %>
<%= help_block('Restore to most recent backup by leaving date and time blank',
'col-xs-4', 'col-xs-7') %>
<%= f.text_field :restore_date %>
<%= f.time_select :restore_time, ignore_date: true, minute_step: 30, prompt: true %>
<%= f.select(:fileset,
options_from_collection_for_select(@client.file_sets, :id, :file_set)) %>
<%= f.text_field :restore_location, placeholder: '/tmp/default_restore' %>
<hr />
<%= help_block(
'Restore and backup clients <strong>must</strong> have the same encryption key'.html_safe,
'col-xs-4', 'col-xs-7') %>
<%= f.select(
:restore_client,
options_from_collection_for_select(@restore_clients,
:id, :name, @client.id),
label: tooltip_label('Restore Client',
'Client where the backup will be restored to')) %>
<hr />
<div class="row">
- <div class="col-xs-5 col-xs-offset-6 text-right">
+ <div class="col-xs-4 col-xs-offset-4">
<%= f.submit 'Select Specific Files', id: 'select-files', class: 'btn btn-primary' %>
</div>
- </div>
- <br />
- <div class="row">
- <div class="col-xs-3 col-xs-offset-8">
+ <div class="col-xs-4">
<%= f.submit 'Restore All Files', class: 'btn btn-warning text-right',
data: { confirm: "This will restore all your files" }
%>
</div>
</div>
<% end %>
</div>
</div>
<% else %>
<div class="alert alert-warning">
<p>Can not issue a restore for this client. It does not have any successful backups</p>
</div>
<% end %>
<%= link_to client_path(@client), class: 'btn btn-default' do %>
<span class="glyphicon glyphicon-menu-left text-primary"></span>
Back to client
<% end %>
</div>
<%= render partial: 'file_selector' %>
</div>
<script type="text/javascript">
<% min_date, max_date = @client.backup_enabled_datetime_range %>
var minDate = '<%= min_date %>';
var maxDate = '<%= max_date %>';
$('#restore_date').datepicker({
dateFormat: 'yy-mm-dd',
minDate: minDate,
maxDate: maxDate
});
</script>
diff --git a/app/views/clients/select_files.js.erb b/app/views/clients/select_files.js.erb
index c92a56e..77c4f70 100644
--- a/app/views/clients/select_files.js.erb
+++ b/app/views/clients/select_files.js.erb
@@ -1,27 +1,30 @@
$('#basic-form input').attr('disabled', true);
$('#basic-form select').attr('disabled', true);
$('.loader').hide();
$('#file-tree').jstree({
'core': {
'data' : {
"url" : "<%= escape_javascript(tree_client_path(client_id: @client.id)) %>",
"data" : function(node) {
return { "id" : node.id };
},
"dataType" : "json"
}
},
'checkbox' : {
'three_state': false
},
"types" : {
"file" : {
"icon" : "glyphicon glyphicon-file"
}
},
"plugins" : ["types", "checkbox"]
});
-$('#file-submitter').show();
+$('#restore-details').show();
$('#file-submitter').
append('<input type="hidden" name="location" value="<%= escape_javascript(@location) %>"/>');
+$('#restore_data_point').html("<%= @restore_point || Time.now.strftime('%Y-%m-%d %H:%M:%S') %>");
+$('#restore_data_location').html("<%= @location %>");
+$('#restore_data_client').html("<%= @restore_client || @client.name %>");
Event Timeline
Log In to Comment