filecluster 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +21 -4
- data/TODO +3 -0
- data/bin/fc-manage +11 -8
- data/lib/daemon/global_daemon_thread.rb +5 -5
- data/lib/fc/db.rb +19 -8
- data/lib/fc/item.rb +2 -2
- data/lib/fc/policy.rb +27 -8
- data/lib/fc/storage.rb +25 -18
- data/lib/fc/version.rb +1 -1
- data/lib/manage/policies.rb +69 -19
- data/lib/manage/storages.rb +79 -12
- data/lib/utils.rb +2 -2
- data/test/daemon_test.rb +9 -9
- data/test/db_test.rb +25 -12
- data/test/functional_test.rb +7 -13
- data/test/policy_test.rb +55 -16
- data/test/storage_test.rb +0 -1
- metadata +4 -4
data/README.md
CHANGED
@@ -1,12 +1,21 @@
|
|
1
|
-
#
|
1
|
+
# FileCluster
|
2
|
+
|
3
|
+
A set of scripts to manage files on multiple dc/host/drive.
|
4
|
+
|
5
|
+
Item (storage unit)- file or folder.
|
6
|
+
Storage - folder, usually separate drive.
|
7
|
+
Policy - rule for selecting storage to store the item and сreate copies.
|
8
|
+
|
9
|
+
Daemon monitors the availability of each storage and copy files between them.
|
10
|
+
|
11
|
+
If the storage is not available or ended the available space is used another available storage according to the policy.
|
2
12
|
|
3
|
-
TODO: Write a gem description
|
4
13
|
|
5
14
|
## Installation
|
6
15
|
|
7
16
|
Add this line to your application's Gemfile:
|
8
17
|
|
9
|
-
gem '
|
18
|
+
gem 'filecluster'
|
10
19
|
|
11
20
|
And then execute:
|
12
21
|
|
@@ -14,7 +23,15 @@ And then execute:
|
|
14
23
|
|
15
24
|
Or install it yourself as:
|
16
25
|
|
17
|
-
$ gem install
|
26
|
+
$ gem install filecluster
|
27
|
+
|
28
|
+
## Create policy
|
29
|
+
|
30
|
+
Selecting available storage to store item by policy.create_storages (from left to tight).
|
31
|
+
|
32
|
+
## Copy policy
|
33
|
+
|
34
|
+
Selecting available storage to copy item by policy.copy_storages (from left to tight) with the nearest copy_id.
|
18
35
|
|
19
36
|
## Usage
|
20
37
|
|
data/TODO
CHANGED
data/bin/fc-manage
CHANGED
@@ -18,19 +18,22 @@ commands_help = {
|
|
18
18
|
'show list and manage storages',
|
19
19
|
%q{Usage: fc-manage [options] storages <command>
|
20
20
|
Command:
|
21
|
-
list
|
22
|
-
show <name>
|
23
|
-
add
|
24
|
-
rm <name>
|
21
|
+
list show all stotages for all hosts
|
22
|
+
show <name> show full info for storage
|
23
|
+
add add new storage
|
24
|
+
rm <name> delete storage
|
25
|
+
change <name> change storage attributes
|
26
|
+
update_size <name> update storage size
|
25
27
|
}],
|
26
28
|
'policies' => [
|
27
29
|
'show list and manage plicies',
|
28
30
|
%q{Usage: fc-manage [options] plicies <command>
|
29
31
|
Command:
|
30
|
-
list
|
31
|
-
show <id>
|
32
|
-
add
|
33
|
-
rm <id>
|
32
|
+
list show all plicies
|
33
|
+
show <id/name> show full info for policy
|
34
|
+
add add new policy
|
35
|
+
rm <id/name> delete policy
|
36
|
+
change <id/name> change policy attributes
|
34
37
|
}],
|
35
38
|
'show' => [
|
36
39
|
'show variable',
|
@@ -32,13 +32,12 @@ class GlobalDaemonThread < BaseThread
|
|
32
32
|
# policies.get_storages => all_policies.select
|
33
33
|
all_policies.each do |policy|
|
34
34
|
metaclass = class << policy; self; end
|
35
|
-
metaclass.send(:define_method, :
|
36
|
-
|
37
|
-
all_storages.select{|storage| policy_storages.member?(storage.name)}
|
35
|
+
metaclass.send(:define_method, :get_copy_storages) do
|
36
|
+
@copy_storages_cache ||= self.copy_storages.split(',').map{|storage_name| all_storages.detect{|s| storage_name == s.name} }
|
38
37
|
end
|
39
38
|
end
|
40
39
|
|
41
|
-
sql = "SELECT i.id as item_id, i.size, i.copies as item_copies, GROUP_CONCAT(ist.storage_name) as storages, p.id as policy_id, p.copies as policy_copies "+
|
40
|
+
sql = "SELECT i.id as item_id, i.size, i.copies as item_copies, GROUP_CONCAT(ist.storage_name ORDER BY ist.id) as storages, p.id as policy_id, p.copies as policy_copies "+
|
42
41
|
"FROM #{FC::Item.table_name} as i, #{FC::Policy.table_name} as p, #{FC::ItemStorage.table_name} as ist WHERE "+
|
43
42
|
"i.policy_id = p.id AND ist.item_id = i.id AND i.copies > 0 AND i.copies < p.copies AND i.status = 'ready' AND ist.status <> 'delete' GROUP BY i.id LIMIT 1000"
|
44
43
|
r = FC::DB.connect.query(sql)
|
@@ -50,8 +49,9 @@ class GlobalDaemonThread < BaseThread
|
|
50
49
|
elsif item_storages.size >= row['policy_copies']
|
51
50
|
$log.warn("GlobalDaemonThread: ItemStorage count >= policy.copies for item #{row['item_id']}")
|
52
51
|
else
|
52
|
+
src_storage = all_storages.detect{|s| item_storages.first == s.name}
|
53
53
|
policy = all_policies.detect{|p| row['policy_id'] == p.id}
|
54
|
-
storage = policy.
|
54
|
+
storage = policy.get_proper_storage_for_copy(row['size'], src_storage.copy_id, item_storages) if src_storage && policy
|
55
55
|
error 'No available storage', :item_id => row['item_id'] unless storage
|
56
56
|
FC::Item.new(:id => row['item_id']).make_item_storage(storage, 'copy')
|
57
57
|
end
|
data/lib/fc/db.rb
CHANGED
@@ -71,14 +71,21 @@ module FC
|
|
71
71
|
size bigint NOT NULL DEFAULT 0,
|
72
72
|
size_limit bigint NOT NULL DEFAULT 0,
|
73
73
|
check_time int DEFAULT NULL,
|
74
|
+
copy_id int NOT NULL DEFAULT 0,
|
74
75
|
PRIMARY KEY (id), UNIQUE KEY (name), KEY (host)
|
75
76
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
|
76
77
|
})
|
77
78
|
proc = %{
|
78
|
-
# update policy.
|
79
|
+
# update policy.create_storages and policy.copy_storages on storage delete and update
|
79
80
|
UPDATE #{@prefix}policies,
|
80
|
-
(SELECT #{@prefix}policies.id, GROUP_CONCAT(name) as storages FROM #{@prefix}policies LEFT JOIN #{@prefix}storages ON
|
81
|
-
|
81
|
+
(SELECT #{@prefix}policies.id, GROUP_CONCAT(#{@prefix}storages.name ORDER BY FIND_IN_SET(#{@prefix}storages.name, create_storages)) as storages FROM #{@prefix}policies LEFT JOIN #{@prefix}storages ON
|
82
|
+
FIND_IN_SET(#{@prefix}storages.name, create_storages) GROUP BY #{@prefix}policies.id) as policy_create,
|
83
|
+
(SELECT #{@prefix}policies.id, GROUP_CONCAT(#{@prefix}storages.name ORDER BY FIND_IN_SET(#{@prefix}storages.name, copy_storages)) as storages FROM #{@prefix}policies LEFT JOIN #{@prefix}storages ON
|
84
|
+
FIND_IN_SET(#{@prefix}storages.name, copy_storages) GROUP BY #{@prefix}policies.id) as policy_copy
|
85
|
+
SET
|
86
|
+
#{@prefix}policies.create_storages = policy_create.storages,
|
87
|
+
#{@prefix}policies.copy_storages = policy_copy.storages
|
88
|
+
WHERE policy_create.id = #{@prefix}policies.id AND policy_copy.id = #{@prefix}policies.id;
|
82
89
|
}
|
83
90
|
proc_update = %{
|
84
91
|
IF OLD.name <> NEW.name THEN
|
@@ -91,15 +98,19 @@ module FC
|
|
91
98
|
FC::DB.connect.query(%{
|
92
99
|
CREATE TABLE #{@prefix}policies (
|
93
100
|
id int NOT NULL AUTO_INCREMENT,
|
94
|
-
|
101
|
+
name varchar(255) NOT NULL DEFAULT '',
|
102
|
+
create_storages text NOT NULL DEFAULT '',
|
103
|
+
copy_storages text NOT NULL DEFAULT '',
|
95
104
|
copies int NOT NULL DEFAULT 0,
|
96
|
-
PRIMARY KEY (id)
|
105
|
+
PRIMARY KEY (id), UNIQUE KEY (name)
|
97
106
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
|
98
107
|
})
|
99
108
|
proc = %{
|
100
|
-
# update policy.
|
101
|
-
SELECT GROUP_CONCAT(name) INTO @
|
102
|
-
|
109
|
+
# update policy.create_storages and policy.copy_storages on policy change - guarantee valid policy.storages
|
110
|
+
SELECT GROUP_CONCAT(name ORDER BY FIND_IN_SET(name, NEW.create_storages)) INTO @create_storages_list FROM #{@prefix}storages WHERE FIND_IN_SET(name, NEW.create_storages);
|
111
|
+
SELECT GROUP_CONCAT(name ORDER BY FIND_IN_SET(name, NEW.copy_storages)) INTO @copy_storages_list FROM #{@prefix}storages WHERE FIND_IN_SET(name, NEW.copy_storages);
|
112
|
+
SET NEW.create_storages = @create_storages_list;
|
113
|
+
SET NEW.copy_storages = @copy_storages_list;
|
103
114
|
}
|
104
115
|
FC::DB.connect.query("CREATE TRIGGER fc_policies_before_insert BEFORE INSERT on #{@prefix}policies FOR EACH ROW BEGIN #{proc} END")
|
105
116
|
FC::DB.connect.query("CREATE TRIGGER fc_policies_before_update BEFORE UPDATE on #{@prefix}policies FOR EACH ROW BEGIN #{proc} END")
|
data/lib/fc/item.rb
CHANGED
@@ -23,7 +23,7 @@ module FC
|
|
23
23
|
raise 'Zero size path' if item_params[:size] == 0
|
24
24
|
|
25
25
|
if local_path.include?(item_name)
|
26
|
-
storage = policy.
|
26
|
+
storage = policy.get_create_storages.detect{|s| local_path.index(s.path) == 0 && local_path.sub(s.path, '') == item_params[:name]}
|
27
27
|
FC::Error.raise "local_path #{local_path} is not valid path for policy ##{policy.id}" unless storage
|
28
28
|
end
|
29
29
|
|
@@ -47,7 +47,7 @@ module FC
|
|
47
47
|
item_storage = item.make_item_storage(storage, 'ready')
|
48
48
|
item.reload
|
49
49
|
else
|
50
|
-
storage = policy.
|
50
|
+
storage = policy.get_proper_storage_for_create(item.size)
|
51
51
|
FC::Error.raise 'No available storage', :item_id => item.id unless storage
|
52
52
|
item_storage = item.make_item_storage(storage)
|
53
53
|
item.copy_item_storage(local_path, storage, item_storage)
|
data/lib/fc/policy.rb
CHANGED
@@ -2,24 +2,43 @@
|
|
2
2
|
|
3
3
|
module FC
|
4
4
|
class Policy < DbBase
|
5
|
-
set_table :policies, '
|
5
|
+
set_table :policies, 'name, create_storages, copy_storages, copies'
|
6
6
|
|
7
7
|
class << self
|
8
8
|
attr_accessor :storages_cache_time
|
9
9
|
end
|
10
10
|
@storages_cache_time = 20 # ttl for storages cache
|
11
11
|
|
12
|
-
def
|
13
|
-
return @
|
14
|
-
@
|
15
|
-
|
12
|
+
def get_create_storages
|
13
|
+
return @create_storages_cache if @create_storages_cache && Time.new.to_i - @get_create_storages_time.to_i < self.class.storages_cache_time
|
14
|
+
@get_create_storages_time = Time.new.to_i
|
15
|
+
names = create_storages.split(',').map{|s| "'#{s}'"}.join(',')
|
16
|
+
@create_storages_cache = FC::Storage.where("name IN (#{names}) ORDER BY FIELD(name, #{names})")
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
def get_copy_storages
|
20
|
+
return @copy_storages_cache if @copy_storages_cache && Time.new.to_i - @get_copy_storages_time.to_i < self.class.storages_cache_time
|
21
|
+
@get_copy_storages_time = Time.new.to_i
|
22
|
+
names = copy_storages.split(',').map{|s| "'#{s}'"}.join(',')
|
23
|
+
@copy_storages_cache = FC::Storage.where("name IN (#{names}) ORDER BY FIELD(name, #{names})")
|
24
|
+
end
|
25
|
+
|
26
|
+
# get available storage for create by size
|
27
|
+
def get_proper_storage_for_create(size, exclude = [])
|
28
|
+
get_create_storages.detect do |storage|
|
29
|
+
!exclude.include?(storage.name) && storage.up? && storage.size + size < storage.size_limit
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# get available storage for copy by copy_id and size
|
34
|
+
def get_proper_storage_for_copy(size, copy_id = nil, exclude = [])
|
35
|
+
storages = get_copy_storages.select do |storage|
|
21
36
|
!exclude.include?(storage.name) && storage.up? && storage.size + size < storage.size_limit
|
22
37
|
end
|
38
|
+
storage = storages.detect{|s| copy_id.to_i == s.copy_id.to_i}
|
39
|
+
storage = storages.detect{|s| copy_id.to_i < s.copy_id.to_i} unless storage
|
40
|
+
storage = storages.first unless storage
|
41
|
+
storage
|
23
42
|
end
|
24
43
|
end
|
25
44
|
end
|
data/lib/fc/storage.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module FC
|
4
4
|
class Storage < DbBase
|
5
|
-
set_table :storages, 'name, host, path, url, size, size_limit, check_time'
|
5
|
+
set_table :storages, 'name, host, path, url, size, size_limit, check_time, copy_id'
|
6
6
|
|
7
7
|
class << self
|
8
8
|
attr_accessor :check_time_limit
|
@@ -16,7 +16,9 @@ module FC
|
|
16
16
|
def initialize(params = {})
|
17
17
|
path = (params['path'] || params[:path])
|
18
18
|
if path && !path.to_s.empty?
|
19
|
+
path += '/' unless path[-1] == '/'
|
19
20
|
raise "Storage path must be like '/bla/bla../'" unless path.match(/^\/.*\/$/)
|
21
|
+
params['path'] = params[:path] = path
|
20
22
|
end
|
21
23
|
super params
|
22
24
|
end
|
@@ -31,47 +33,52 @@ module FC
|
|
31
33
|
end
|
32
34
|
|
33
35
|
def up?
|
34
|
-
|
36
|
+
check_time_delay < self.class.check_time_limit
|
35
37
|
end
|
36
38
|
|
37
39
|
# copy local_path to storage
|
38
40
|
def copy_path(local_path, file_name)
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
dst_path = "#{self.path}#{file_name}"
|
42
|
+
|
43
|
+
cmd = self.class.curr_host == host ? "mkdir -p #{File.dirname(dst_path)}" : "ssh -oBatchMode=yes #{self.host} 'mkdir -p #{File.dirname(dst_path)}'"
|
44
|
+
r = `#{cmd} 2>&1`
|
45
|
+
raise r if $?.exitstatus != 0
|
46
|
+
|
47
|
+
cmd = self.class.curr_host == host ? "cp -r #{local_path} #{dst_path}" : "scp -rB #{local_path} #{self.host}:#{dst_path}"
|
42
48
|
r = `#{cmd} 2>&1`
|
43
49
|
raise r if $?.exitstatus != 0
|
44
50
|
end
|
45
51
|
|
46
52
|
# copy object to local_path
|
47
53
|
def copy_to_local(file_name, local_path)
|
48
|
-
|
49
|
-
|
50
|
-
|
54
|
+
src_path = "#{self.path}#{file_name}"
|
55
|
+
|
56
|
+
cmd = self.class.curr_host == host ? "mkdir -p #{File.dirname(local_path)}" : "ssh -oBatchMode=yes #{self.host} 'mkdir -p #{File.dirname(local_path)}'"
|
57
|
+
r = `#{cmd} 2>&1`
|
58
|
+
raise r if $?.exitstatus != 0
|
59
|
+
|
60
|
+
cmd = self.class.curr_host == host ? "cp -r #{src_path} #{local_path}" : "scp -rB #{self.host}:#{src_path} #{local_path}"
|
51
61
|
r = `#{cmd} 2>&1`
|
52
62
|
raise r if $?.exitstatus != 0
|
53
63
|
end
|
54
64
|
|
55
65
|
# delete object from storage
|
56
66
|
def delete_file(file_name)
|
57
|
-
|
58
|
-
|
59
|
-
"ssh -oBatchMode=yes #{self.host} 'rm -rf #{self.path}#{file_name}'"
|
67
|
+
dst_path = "#{self.path}#{file_name}"
|
68
|
+
cmd = self.class.curr_host == host ? "rm -rf #{dst_path}" : "ssh -oBatchMode=yes #{self.host} 'rm -rf #{dst_path}'"
|
60
69
|
r = `#{cmd} 2>&1`
|
61
70
|
raise r if $?.exitstatus != 0
|
62
71
|
|
63
|
-
cmd = self.class.curr_host == host ?
|
64
|
-
"ls -la #{self.path}#{file_name}" :
|
65
|
-
"ssh -oBatchMode=yes #{self.host} 'ls -la #{self.path}#{file_name}'"
|
72
|
+
cmd = self.class.curr_host == host ? "ls -la #{dst_path}" : "ssh -oBatchMode=yes #{self.host} 'ls -la #{dst_path}'"
|
66
73
|
r = `#{cmd} 2>/dev/null`
|
67
|
-
raise "Path #{
|
74
|
+
raise "Path #{dst_path} not deleted" unless r.empty?
|
68
75
|
end
|
69
76
|
|
70
77
|
# return object size on storage
|
71
78
|
def file_size(file_name)
|
72
|
-
|
73
|
-
|
74
|
-
|
79
|
+
dst_path = "#{self.path}#{file_name}"
|
80
|
+
|
81
|
+
cmd = self.class.curr_host == host ? "du -sb #{dst_path}" : "ssh -oBatchMode=yes #{self.host} 'du -sb #{dst_path}'"
|
75
82
|
r = `#{cmd} 2>&1`
|
76
83
|
raise r if $?.exitstatus != 0
|
77
84
|
r.to_i
|
data/lib/fc/version.rb
CHANGED
data/lib/manage/policies.rb
CHANGED
@@ -4,39 +4,46 @@ def policies_list
|
|
4
4
|
puts "No storages."
|
5
5
|
else
|
6
6
|
policies.each do |policy|
|
7
|
-
puts "##{policy.id} storages: #{policy.storages}, copies: #{policy.copies}"
|
7
|
+
puts "##{policy.id} #{policy.name}, create storages: #{policy.create_storages}, copy storages: #{policy.copy_storages}, copies: #{policy.copies}"
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
def policies_show
|
13
|
-
|
14
|
-
policy = FC::Policy.where('id = ?', id).first
|
15
|
-
if !policy
|
16
|
-
puts "Policy ##{id} not found."
|
17
|
-
else
|
13
|
+
if policy = find_policy
|
18
14
|
count = FC::DB.connect.query("SELECT count(*) as cnt FROM #{FC::Item.table_name} WHERE policy_id = #{policy.id}").first['cnt']
|
19
15
|
puts %Q{Policy
|
20
|
-
ID:
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
ID: #{policy.id}
|
17
|
+
Name: #{policy.name}
|
18
|
+
Create storages: #{policy.create_storages}
|
19
|
+
Copy storages: #{policy.copy_storages}
|
20
|
+
Copies: #{policy.copies}
|
21
|
+
Items: #{count}}
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
25
|
def policies_add
|
28
26
|
puts "Add Policy"
|
29
|
-
|
27
|
+
name = stdin_read_val('Name')
|
28
|
+
create_storages = stdin_read_val('Create storages')
|
29
|
+
copy_storages = stdin_read_val('Copy storages')
|
30
30
|
copies = stdin_read_val('Copies').to_i
|
31
|
+
|
32
|
+
storages = FC::Storage.where.map(&:name)
|
33
|
+
create_storages = create_storages.split(',').select{|s| storages.member?(s.strip)}.join(',').strip
|
34
|
+
copy_storages = copy_storages.split(',').select{|s| storages.member?(s.strip)}.join(',').strip
|
35
|
+
|
31
36
|
begin
|
32
|
-
policy = FC::Policy.new(:
|
37
|
+
policy = FC::Policy.new(:name => name, :create_storages => create_storages, :copy_storages => copy_storages, :copies => copies)
|
33
38
|
rescue Exception => e
|
34
39
|
puts "Error: #{e.message}"
|
35
40
|
exit
|
36
41
|
end
|
37
42
|
puts %Q{\nPolicy
|
38
|
-
|
39
|
-
|
43
|
+
Name: #{name}
|
44
|
+
Create storages: #{create_storages}
|
45
|
+
Copy storages: #{copy_storages}
|
46
|
+
Copies: #{copies}}
|
40
47
|
s = Readline.readline("Continue? (y/n) ", false).strip.downcase
|
41
48
|
puts ""
|
42
49
|
if s == "y" || s == "yes"
|
@@ -53,11 +60,7 @@ def policies_add
|
|
53
60
|
end
|
54
61
|
|
55
62
|
def policies_rm
|
56
|
-
|
57
|
-
policy = FC::Policy.where('id = ?', id).first
|
58
|
-
if !policy
|
59
|
-
puts "Policy ##{id} not found."
|
60
|
-
else
|
63
|
+
if policy = find_policy
|
61
64
|
s = Readline.readline("Continue? (y/n) ", false).strip.downcase
|
62
65
|
puts ""
|
63
66
|
if s == "y" || s == "yes"
|
@@ -68,3 +71,50 @@ def policies_rm
|
|
68
71
|
end
|
69
72
|
end
|
70
73
|
end
|
74
|
+
|
75
|
+
def policies_change
|
76
|
+
if policy = find_policy
|
77
|
+
puts "Change policy ##{policy.id} #{policy.name}"
|
78
|
+
name = stdin_read_val("Name (now #{policy.name})", true)
|
79
|
+
create_storages = stdin_read_val("Create storages (now #{policy.create_storages})", true)
|
80
|
+
copy_storages = stdin_read_val("Copy storages (now #{policy.copy_storages})", true)
|
81
|
+
copies = stdin_read_val("Copies (now #{policy.copies})", true)
|
82
|
+
|
83
|
+
storages = FC::Storage.where.map(&:name)
|
84
|
+
create_storages = create_storages.split(',').select{|s| storages.member?(s.strip)}.join(',').strip unless create_storages.empty?
|
85
|
+
copy_storages = copy_storages.split(',').select{|s| storages.member?(s.strip)}.join(',').strip unless copy_storages.empty?
|
86
|
+
|
87
|
+
policy.name = name unless name.empty?
|
88
|
+
policy.create_storages = name unless create_storages.empty?
|
89
|
+
policy.copy_storages = name unless copy_storages.empty?
|
90
|
+
policy.copies = copies.to_i unless copies.empty?
|
91
|
+
|
92
|
+
puts %Q{\nStorage
|
93
|
+
Name: #{policy.name}
|
94
|
+
Create storages: #{policy.create_storages}
|
95
|
+
Copy storages: #{policy.copy_storages}
|
96
|
+
Copies: #{policy.copies}}
|
97
|
+
s = Readline.readline("Continue? (y/n) ", false).strip.downcase
|
98
|
+
puts ""
|
99
|
+
if s == "y" || s == "yes"
|
100
|
+
begin
|
101
|
+
policy.save
|
102
|
+
rescue Exception => e
|
103
|
+
puts "Error: #{e.message}"
|
104
|
+
exit
|
105
|
+
end
|
106
|
+
puts "ok"
|
107
|
+
else
|
108
|
+
puts "Canceled."
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def find_policy
|
116
|
+
policy = FC::Policy.where('id = ?', ARGV[2]).first
|
117
|
+
policy = FC::Policy.where('name = ?', ARGV[2]).first unless policy
|
118
|
+
puts "Policy #{ARGV[2]} not found." unless policy
|
119
|
+
policy
|
120
|
+
end
|
data/lib/manage/storages.rb
CHANGED
@@ -13,11 +13,7 @@ def storages_list
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def storages_show
|
16
|
-
|
17
|
-
storage = FC::Storage.where('name = ?', name).first
|
18
|
-
if !storage
|
19
|
-
puts "Storage #{name} not found."
|
20
|
-
else
|
16
|
+
if storage = find_storage
|
21
17
|
count = FC::DB.connect.query("SELECT count(*) as cnt FROM #{FC::ItemStorage.table_name} WHERE storage_name='#{Mysql2::Client.escape(storage.name)}'").first['cnt']
|
22
18
|
puts %Q{Storage
|
23
19
|
Name: #{storage.name}
|
@@ -26,6 +22,7 @@ def storages_show
|
|
26
22
|
Url: #{storage.url}
|
27
23
|
Size: #{size_to_human storage.size}
|
28
24
|
Size limit: #{size_to_human storage.size_limit}
|
25
|
+
Copy id: #{storage.copy_id}
|
29
26
|
Check time: #{storage.check_time ? "#{Time.at(storage.check_time)} (#{storage.check_time_delay} seconds ago)" : ''}
|
30
27
|
Status: #{storage.up? ? colorize_string('UP', :green) : colorize_string('DOWN', :red)}
|
31
28
|
Items storages: #{count}}
|
@@ -39,8 +36,11 @@ def storages_add
|
|
39
36
|
path = stdin_read_val('Path')
|
40
37
|
url = stdin_read_val('Url')
|
41
38
|
size_limit = human_to_size stdin_read_val('Size limit') {|val| "Size limit not is valid size." unless human_to_size(val)}
|
39
|
+
copy_id = stdin_read_val('Copy id').to_i
|
42
40
|
begin
|
43
|
-
|
41
|
+
path = path +'/' unless path[-1] == '/'
|
42
|
+
path = '/' + path unless path[0] == '/'
|
43
|
+
storage = FC::Storage.new(:name => name, :host => host, :path => path, :url => url, :size_limit => size_limit, :copy_id => copy_id)
|
44
44
|
print "Calc current size.. "
|
45
45
|
size = storage.file_size('')
|
46
46
|
puts "ok"
|
@@ -54,7 +54,8 @@ def storages_add
|
|
54
54
|
Path: #{path}
|
55
55
|
Url: #{url}
|
56
56
|
Size: #{size_to_human size}
|
57
|
-
Size limit: #{size_to_human size_limit}
|
57
|
+
Size limit: #{size_to_human size_limit}
|
58
|
+
Copy id: #{copy_id}}
|
58
59
|
s = Readline.readline("Continue? (y/n) ", false).strip.downcase
|
59
60
|
puts ""
|
60
61
|
if s == "y" || s == "yes"
|
@@ -72,11 +73,7 @@ def storages_add
|
|
72
73
|
end
|
73
74
|
|
74
75
|
def storages_rm
|
75
|
-
|
76
|
-
storage = FC::Storage.where('name = ?', name).first
|
77
|
-
if !storage
|
78
|
-
puts "Storage #{name} not found."
|
79
|
-
else
|
76
|
+
if storage = find_storage
|
80
77
|
s = Readline.readline("Continue? (y/n) ", false).strip.downcase
|
81
78
|
puts ""
|
82
79
|
if s == "y" || s == "yes"
|
@@ -87,3 +84,73 @@ def storages_rm
|
|
87
84
|
end
|
88
85
|
end
|
89
86
|
end
|
87
|
+
|
88
|
+
def storages_update_size
|
89
|
+
if storage = find_storage
|
90
|
+
print "Calc current size.. "
|
91
|
+
size = storage.file_size('')
|
92
|
+
storage.size = size
|
93
|
+
begin
|
94
|
+
storage.save
|
95
|
+
rescue Exception => e
|
96
|
+
puts "Error: #{e.message}"
|
97
|
+
exit
|
98
|
+
end
|
99
|
+
puts "ok"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def storages_change
|
104
|
+
if storage = find_storage
|
105
|
+
puts "Change storage #{storage.name}"
|
106
|
+
host = stdin_read_val("Host (now #{storage.host})", true)
|
107
|
+
path = stdin_read_val("Path (now #{storage.path})", true)
|
108
|
+
url = stdin_read_val("Url (now #{storage.url})", true)
|
109
|
+
size_limit = stdin_read_val("Size (now #{size_to_human(storage.size_limit)})", true) {|val| "Size limit not is valid size." if !val.empty? && !human_to_size(val)}
|
110
|
+
copy_id = stdin_read_val("Copy id (now #{storage.copy_id})", true)
|
111
|
+
|
112
|
+
storage.host = host unless host.empty?
|
113
|
+
if !path.empty? && path != storage.path
|
114
|
+
path = path +'/' unless path[-1] == '/'
|
115
|
+
path = '/' + path unless path[0] == '/'
|
116
|
+
storage.path = path
|
117
|
+
print "Calc current size.. "
|
118
|
+
storage.size = storage.file_size('')
|
119
|
+
puts "ok"
|
120
|
+
end
|
121
|
+
storage.url = url unless url.empty?
|
122
|
+
storage.size_limit = human_to_size(size_limit) unless size_limit.empty?
|
123
|
+
storage.copy_id = copy_id.to_i
|
124
|
+
|
125
|
+
puts %Q{\nStorage
|
126
|
+
Name: #{storage.name}
|
127
|
+
Host: #{storage.host}
|
128
|
+
Path: #{storage.path}
|
129
|
+
Url: #{storage.url}
|
130
|
+
Size: #{size_to_human storage.size}
|
131
|
+
Size limit: #{size_to_human storage.size_limit}
|
132
|
+
Copy id: #{copy_id}}
|
133
|
+
s = Readline.readline("Continue? (y/n) ", false).strip.downcase
|
134
|
+
puts ""
|
135
|
+
if s == "y" || s == "yes"
|
136
|
+
begin
|
137
|
+
storage.save
|
138
|
+
rescue Exception => e
|
139
|
+
puts "Error: #{e.message}"
|
140
|
+
exit
|
141
|
+
end
|
142
|
+
puts "ok"
|
143
|
+
else
|
144
|
+
puts "Canceled."
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def find_storage
|
152
|
+
name = ARGV[2]
|
153
|
+
storage = FC::Storage.where('name = ?', name).first
|
154
|
+
puts "Storage #{name} not found." if !storage
|
155
|
+
storage
|
156
|
+
end
|
data/lib/utils.rb
CHANGED
@@ -40,9 +40,9 @@ def human_to_size(size)
|
|
40
40
|
result.to_i
|
41
41
|
end
|
42
42
|
|
43
|
-
def stdin_read_val(name)
|
43
|
+
def stdin_read_val(name, can_empty = false)
|
44
44
|
while val = Readline.readline("#{name}: ", false).strip.downcase
|
45
|
-
if val.empty?
|
45
|
+
if val.empty? && !can_empty
|
46
46
|
puts "Input non empty #{name}."
|
47
47
|
else
|
48
48
|
if block_given?
|
data/test/daemon_test.rb
CHANGED
@@ -37,12 +37,12 @@ class DaemonTest < Test::Unit::TestCase
|
|
37
37
|
`dd if=/dev/urandom of=#{@@test_file_path} bs=1M count=1 2>&1`
|
38
38
|
|
39
39
|
@@storages = []
|
40
|
-
@@storages << FC::Storage.new(:name => 'host1-sda', :host => 'host1', :path => '/tmp/host1-sda/', :size_limit => 1000000000)
|
41
|
-
@@storages << FC::Storage.new(:name => 'host1-sdb', :host => 'host1', :path => '/tmp/host1-sdb/', :size_limit => 1000000000)
|
42
|
-
@@storages << FC::Storage.new(:name => 'host1-sdc', :host => 'host1', :path => '/tmp/host1-sdc/', :size_limit => 1000000000)
|
40
|
+
@@storages << FC::Storage.new(:name => 'host1-sda', :host => 'host1', :path => '/tmp/host1-sda/', :copy_id => 1, :size_limit => 1000000000)
|
41
|
+
@@storages << FC::Storage.new(:name => 'host1-sdb', :host => 'host1', :path => '/tmp/host1-sdb/', :copy_id => 2, :size_limit => 1000000000)
|
42
|
+
@@storages << FC::Storage.new(:name => 'host1-sdc', :host => 'host1', :path => '/tmp/host1-sdc/', :copy_id => 1, :size_limit => 1000000000)
|
43
43
|
@@storages.each { |storage| storage.save}
|
44
44
|
|
45
|
-
@@policy = FC::Policy.new(:
|
45
|
+
@@policy = FC::Policy.new(:create_storages => 'host1-sda,host1-sdb,host1-sdc', :copy_storages => 'host1-sda,host1-sdb,host1-sdc', :copies => 2, :name => 'policy 1')
|
46
46
|
@@policy.save
|
47
47
|
|
48
48
|
# wait for running fc-daemon
|
@@ -70,9 +70,9 @@ class DaemonTest < Test::Unit::TestCase
|
|
70
70
|
|
71
71
|
FC::Storage.any_instance.stubs(:host).returns('host1')
|
72
72
|
FC::Storage.stubs(:curr_host).returns('host1')
|
73
|
-
assert_nothing_raised { @item1 = FC::Item.create_from_local(@@test_file_path, 'test1', @@policy, {:tag => 'test1'}) }
|
74
|
-
assert_nothing_raised { @item2 = FC::Item.create_from_local(@@test_file_path, 'test2', @@policy, {:tag => 'test2'}) }
|
75
|
-
assert_nothing_raised { @item3 = FC::Item.create_from_local(@@test_file_path, 'test3', @@policy, {:tag => 'test3'}) }
|
73
|
+
assert_nothing_raised { @item1 = FC::Item.create_from_local(@@test_file_path, 'bla/bla/test1', @@policy, {:tag => 'test1'}) }
|
74
|
+
assert_nothing_raised { @item2 = FC::Item.create_from_local(@@test_file_path, 'bla/bla/test2', @@policy, {:tag => 'test2'}) }
|
75
|
+
assert_nothing_raised { @item3 = FC::Item.create_from_local(@@test_file_path, 'bla/bla/test3', @@policy, {:tag => 'test3'}) }
|
76
76
|
|
77
77
|
@@policy.copies = 3
|
78
78
|
@@policy.save
|
@@ -81,7 +81,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
81
81
|
# wait for copy
|
82
82
|
[1, 2, 3].each do |i|
|
83
83
|
['b', 'c'].each do |j|
|
84
|
-
assert_equal `du -b /tmp/host1-sda/test$i 2>&1`.to_i, `du -b /tmp/host$i-sd$j/test$i 2>&1`.to_i
|
84
|
+
assert_equal `du -b /tmp/host1-sda/bla/bla/test$i 2>&1`.to_i, `du -b /tmp/host$i-sd$j/bla/bla/test$i 2>&1`.to_i
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -91,7 +91,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
91
91
|
item_storage.status = 'delete'
|
92
92
|
item_storage.save
|
93
93
|
sleep 2
|
94
|
-
assert_equal 0, `du -b /tmp/host1-sdc/test1 2>&1`.to_i
|
94
|
+
assert_equal 0, `du -b /tmp/host1-sdc/bla/bla/test1 2>&1`.to_i
|
95
95
|
|
96
96
|
assert_equal @@errors_count, FC::Error.where.count, "new errors in errors table"
|
97
97
|
end
|
data/test/db_test.rb
CHANGED
@@ -15,9 +15,9 @@ class DbTest < Test::Unit::TestCase
|
|
15
15
|
@@storages_ids = storages.map{|storage| storage.save; storage.id }
|
16
16
|
|
17
17
|
policies = []
|
18
|
-
policies << FC::Policy.new(:
|
19
|
-
policies << FC::Policy.new(:
|
20
|
-
policies << FC::Policy.new(:
|
18
|
+
policies << FC::Policy.new(:create_storages => 'rec1-sda,rec1-sdd', :copy_storages => 'rec2-sda,rec2-sdd', :copies => 2, :name => 'policy 1')
|
19
|
+
policies << FC::Policy.new(:create_storages => 'rec1-sda,bla,rec2-sdd', :copy_storages => 'rec2-sda,bla,rec1-sdd', :copies => 3, :name => 'policy 2')
|
20
|
+
policies << FC::Policy.new(:create_storages => 'bla,rec1-sda,test', :copy_storages => 'bla,rec2-sda,test', :copies => 4, :name => 'policy 3')
|
21
21
|
@@policies_ids = policies.map{|policy| policy.save; policy.id }
|
22
22
|
|
23
23
|
items = []
|
@@ -75,26 +75,39 @@ class DbTest < Test::Unit::TestCase
|
|
75
75
|
|
76
76
|
should "policies and storages" do
|
77
77
|
assert @policies.count > 0, 'Policies not loaded'
|
78
|
-
assert_equal 'rec1-sda,rec1-sdd', @policies[0].
|
79
|
-
assert_equal 'rec1-sda,rec2-sdd', @policies[1].
|
80
|
-
assert_equal 'rec1-sda', @policies[2].
|
81
|
-
|
78
|
+
assert_equal 'rec1-sda,rec1-sdd', @policies[0].create_storages, "Policy (id=#{@policies[0].id}) incorrect create_storages"
|
79
|
+
assert_equal 'rec1-sda,rec2-sdd', @policies[1].create_storages, "Policy (id=#{@policies[0].id}) incorrect create_storages"
|
80
|
+
assert_equal 'rec1-sda', @policies[2].create_storages, "Policy (id=#{@policies[0].id}) incorrect create_storages"
|
81
|
+
assert_equal 'rec2-sda,rec2-sdd', @policies[0].copy_storages, "Policy (id=#{@policies[0].id}) incorrect copy_storages"
|
82
|
+
assert_equal 'rec2-sda,rec1-sdd', @policies[1].copy_storages, "Policy (id=#{@policies[0].id}) incorrect copy_storages"
|
83
|
+
assert_equal 'rec2-sda', @policies[2].copy_storages, "Policy (id=#{@policies[0].id}) incorrect copy_storages"
|
84
|
+
|
85
|
+
assert_raise(Mysql2::Error, 'Create policy with uniq name') { FC::Policy.new(:create_storages => 'bla,test', :copy_storages => 'rec2-sda', :name => 'policy 1').save }
|
86
|
+
assert_raise(Mysql2::Error, 'Create policy with incorrect create_storages') { FC::Policy.new(:create_storages => 'bla,test', :copy_storages => 'rec2-sda', :name => 'new policy').save }
|
87
|
+
assert_raise(Mysql2::Error, 'Create policy with incorrect copy_storages') { FC::Policy.new(:create_storages => 'rec1-sda', :copy_storages => 'bla,test', :name => 'new policy').save }
|
88
|
+
|
82
89
|
assert_raise(Mysql2::Error, 'Change storage name with linked polices') { @storages[0].name = 'blabla'; @storages[0].save }
|
83
90
|
assert_raise(Mysql2::Error, 'Delete storage name with linked polices') { @storages[0].delete }
|
84
91
|
assert_nothing_raised { @storages[6].name = 'rec2-sdc-new'; @storages[6].save }
|
85
92
|
@storages[3].name = 'rec1-sdd-new' #rec1-sdd
|
86
93
|
@storages[3].save
|
87
94
|
@policies[0].reload
|
88
|
-
|
95
|
+
@policies[1].reload
|
96
|
+
assert_equal 'rec1-sda', @policies[0].create_storages, "Policy (id=#{@policies[0].id}) incorrect create_storages after storage change"
|
97
|
+
assert_equal 'rec2-sda', @policies[1].copy_storages, "Policy (id=#{@policies[1].id}) incorrect copy_storages after storage change"
|
89
98
|
@storages[7].delete #rec2-sdd
|
90
99
|
@@storages_ids.delete(@storages[7].id)
|
100
|
+
@policies[0].reload
|
91
101
|
@policies[1].reload
|
92
|
-
assert_equal 'rec1-sda', @policies[1].
|
93
|
-
@policies[0].
|
102
|
+
assert_equal 'rec1-sda', @policies[1].create_storages, "Policy (id=#{@policies[1].id}) incorrect create_storages after storage delete"
|
103
|
+
assert_equal 'rec2-sda', @policies[0].copy_storages, "Policy (id=#{@policies[0].id}) incorrect copy_storages after storage delete"
|
104
|
+
@policies[0].create_storages = 'rec2-sda,rec1-sda,bla bla'
|
105
|
+
@policies[0].copy_storages = 'rec1-sdb,rec2-sda,bla bla'
|
94
106
|
@policies[0].save
|
95
107
|
@policies[0].reload
|
96
|
-
assert_equal '
|
97
|
-
|
108
|
+
assert_equal 'rec2-sda,rec1-sda', @policies[0].create_storages, "Policy (id=#{@policies[0].id}) incorrect create_storages after change"
|
109
|
+
assert_equal 'rec1-sdb,rec2-sda', @policies[0].copy_storages, "Policy (id=#{@policies[0].id}) incorrect copy_storages after change"
|
110
|
+
assert_raise(Mysql2::Error, 'Save empty policy storage') { @policies[0].create_storages = 'blabla'; @policies[0].save }
|
98
111
|
end
|
99
112
|
|
100
113
|
should "item_storages doubles" do
|
data/test/functional_test.rb
CHANGED
@@ -20,10 +20,10 @@ class FunctionalTest < Test::Unit::TestCase
|
|
20
20
|
@@storages.each { |storage| storage.save}
|
21
21
|
|
22
22
|
@@policies = []
|
23
|
-
@@policies << FC::Policy.new(:
|
24
|
-
@@policies << FC::Policy.new(:
|
25
|
-
@@policies << FC::Policy.new(:
|
26
|
-
@@policies << FC::Policy.new(:
|
23
|
+
@@policies << FC::Policy.new(:create_storages => 'host1-sda,host2-sda', :copy_storages => 'host1-sdb', :copies => 2, :name => 'policy 1')
|
24
|
+
@@policies << FC::Policy.new(:create_storages => 'host1-sdb,host2-sdb', :copy_storages => 'host1-sdb', :copies => 2, :name => 'policy 2')
|
25
|
+
@@policies << FC::Policy.new(:create_storages => 'host3-sda', :copy_storages => 'host1-sdb', :copies => 1, :name => 'policy 3')
|
26
|
+
@@policies << FC::Policy.new(:create_storages => 'host2-sda', :copy_storages => 'host1-sdb', :copies => 1, :name => 'policy 4')
|
27
27
|
@@policies.each { |policy| policy.save}
|
28
28
|
end
|
29
29
|
def shutdown
|
@@ -41,10 +41,10 @@ class FunctionalTest < Test::Unit::TestCase
|
|
41
41
|
end
|
42
42
|
|
43
43
|
should "item create_from_local successful" do
|
44
|
-
assert_nothing_raised { @item = FC::Item.create_from_local(@@test_file_path, 'test1', @@policies[0], {:tag => 'test'}) }
|
44
|
+
assert_nothing_raised { @item = FC::Item.create_from_local(@@test_file_path, '/bla/bla/test1', @@policies[0], {:tag => 'test'}) }
|
45
45
|
assert_kind_of FC::Item, @item
|
46
|
-
assert_equal `du -b /tmp/host1-sda/test1 2>&1`.to_i, `du -b #{@@test_file_path} 2>&1`.to_i
|
47
|
-
assert_equal `du -b /tmp/host1-sda/test1 2>&1`.to_i, @item.size
|
46
|
+
assert_equal `du -b /tmp/host1-sda/bla/bla/test1 2>&1`.to_i, `du -b #{@@test_file_path} 2>&1`.to_i
|
47
|
+
assert_equal `du -b /tmp/host1-sda/bla/bla/test1 2>&1`.to_i, @item.size
|
48
48
|
assert_equal 'ready', @item.status
|
49
49
|
item_storages = @item.get_item_storages
|
50
50
|
assert_equal 1, item_storages.count
|
@@ -53,12 +53,6 @@ class FunctionalTest < Test::Unit::TestCase
|
|
53
53
|
assert_equal 'host1-sda', item_storage.storage_name
|
54
54
|
end
|
55
55
|
|
56
|
-
should "item create_from_local error local path" do
|
57
|
-
errors_count = FC::Error.where.count
|
58
|
-
assert_raise(RuntimeError) { FC::Item.create_from_local(@@test_file_path, 'test2', @@policies[1], {:tag => 'test'}) }
|
59
|
-
assert_equal errors_count+1, FC::Error.where.count, "Error not saved after error local path"
|
60
|
-
end
|
61
|
-
|
62
56
|
should "item create_from_local replace" do
|
63
57
|
@item = FC::Item.new(:name => 'test2', :policy_id => @@policies[0].id)
|
64
58
|
@item.save
|
data/test/policy_test.rb
CHANGED
@@ -4,11 +4,13 @@ class PolicyTest < Test::Unit::TestCase
|
|
4
4
|
class << self
|
5
5
|
def startup
|
6
6
|
@@storages = []
|
7
|
-
@@storages << FC::Storage.new(:name => 'rec1-sda', :host => 'rec1', :size => 0, :size_limit => 10)
|
8
|
-
@@storages << FC::Storage.new(:name => 'rec2-sda', :host => 'rec2', :size => 0, :size_limit => 100)
|
7
|
+
@@storages << FC::Storage.new(:name => 'rec1-sda', :host => 'rec1', :size => 0, :copy_id => 1, :size_limit => 10)
|
8
|
+
@@storages << FC::Storage.new(:name => 'rec2-sda', :host => 'rec2', :size => 0, :copy_id => 2 , :size_limit => 100)
|
9
9
|
@@storages.each {|storage| storage.save}
|
10
|
-
|
11
|
-
@@
|
10
|
+
@@storage3 = FC::Storage.new(:name => 'rec3-sda', :host => 'rec3', :size => 8, :copy_id => 3 , :size_limit => 10)
|
11
|
+
@@storage3.save
|
12
|
+
|
13
|
+
@@policy = FC::Policy.new(:create_storages => 'rec1-sda,rec2-sda', :copy_storages => 'rec1-sda,rec2-sda', :copies => 1, :name => 'policy 1')
|
12
14
|
@@policy.save
|
13
15
|
end
|
14
16
|
def shutdown
|
@@ -17,26 +19,63 @@ class PolicyTest < Test::Unit::TestCase
|
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
|
-
should "
|
22
|
+
should "get_create_storages" do
|
21
23
|
FC::Policy.storages_cache_time = 10
|
22
|
-
assert_same_elements @@storages.map(&:id), @@policy.
|
23
|
-
|
24
|
-
@@policy.storages = 'rec1-sda,rec2-sda,rec2-sdc'
|
24
|
+
assert_same_elements @@storages.map(&:id), @@policy.get_create_storages.map(&:id)
|
25
|
+
@@policy.create_storages = 'rec1-sda,rec2-sda,rec3-sda'
|
25
26
|
@@policy.save
|
26
|
-
assert_equal @@storages.size, @@policy.
|
27
|
+
assert_equal @@storages.size, @@policy.get_create_storages.size
|
27
28
|
FC::Policy.storages_cache_time = 0
|
28
|
-
assert_equal @@storages.size+1, @@policy.
|
29
|
+
assert_equal @@storages.size+1, @@policy.get_create_storages.size
|
29
30
|
end
|
30
31
|
|
31
|
-
should "
|
32
|
+
should "get_copy_storages" do
|
33
|
+
@@policy.copy_storages = 'rec1-sda,rec2-sda'
|
34
|
+
@@policy.save
|
35
|
+
FC::Policy.storages_cache_time = 10
|
36
|
+
assert_same_elements @@storages.map(&:id), @@policy.get_copy_storages.map(&:id)
|
37
|
+
@@policy.copy_storages = 'rec1-sda,rec2-sda,rec3-sda'
|
38
|
+
@@policy.save
|
39
|
+
assert_equal @@storages.size, @@policy.get_copy_storages.size
|
32
40
|
FC::Policy.storages_cache_time = 0
|
33
|
-
|
41
|
+
assert_equal @@storages.size+1, @@policy.get_copy_storages.size
|
42
|
+
end
|
43
|
+
|
44
|
+
should "get_proper_storage_for_create" do
|
45
|
+
@@storages.each {|storage| storage.check_time = 0; storage.save}
|
46
|
+
@@storage3.check_time = 0
|
47
|
+
@@storage3.save
|
48
|
+
FC::Policy.storages_cache_time = 0
|
49
|
+
assert_nil @@policy.get_proper_storage_for_create(1), 'all storages down'
|
34
50
|
@@storages[0].update_check_time
|
35
|
-
assert_equal @@storages[0].id, @@policy.
|
36
|
-
assert_nil @@policy.
|
51
|
+
assert_equal @@storages[0].id, @@policy.get_proper_storage_for_create(5).id, 'first storages up'
|
52
|
+
assert_nil @@policy.get_proper_storage_for_create(20), 'first storage full'
|
37
53
|
@@storages[1].update_check_time
|
38
|
-
assert_equal @@storages[1].id, @@policy.
|
39
|
-
assert_nil @@policy.
|
54
|
+
assert_equal @@storages[1].id, @@policy.get_proper_storage_for_create(20).id, 'second storages up'
|
55
|
+
assert_nil @@policy.get_proper_storage_for_create(1000), 'all storages full'
|
40
56
|
end
|
41
57
|
|
58
|
+
should "get_proper_storage_for_copy" do
|
59
|
+
@@storages.each {|storage| storage.check_time = 0; storage.save}
|
60
|
+
FC::Policy.storages_cache_time = 0
|
61
|
+
assert_nil @@policy.get_proper_storage_for_copy(1), 'all storages down'
|
62
|
+
@@storages[0].update_check_time
|
63
|
+
@@storage3.update_check_time
|
64
|
+
assert_equal @@storages[0].id, @@policy.get_proper_storage_for_copy(5).id, 'first storages up'
|
65
|
+
assert_nil @@policy.get_proper_storage_for_copy(20), 'first storage full'
|
66
|
+
@@storages[1].update_check_time
|
67
|
+
assert_equal @@storages[1].id, @@policy.get_proper_storage_for_copy(20).id, 'second storages up'
|
68
|
+
assert_nil @@policy.get_proper_storage_for_copy(1000), 'all storages full'
|
69
|
+
|
70
|
+
@@policy.copy_storages = 'rec3-sda,rec1-sda,rec2-sda'
|
71
|
+
@@policy.save
|
72
|
+
assert_equal 'rec3-sda', @@policy.get_proper_storage_for_copy(1).name, 'first storage in copy_storages'
|
73
|
+
assert_equal 'rec2-sda', @@policy.get_proper_storage_for_copy(1, 2).name, 'storage by copy_id'
|
74
|
+
@@policy.copy_storages = 'rec1-sda,rec3-sda'
|
75
|
+
@@policy.save
|
76
|
+
assert_equal 'rec3-sda', @@policy.get_proper_storage_for_copy(1, 2).name, 'storage by copy_id'
|
77
|
+
@@policy.copy_storages = 'rec2-sda,rec3-sda,rec1-sda'
|
78
|
+
@@policy.save
|
79
|
+
assert_equal 'rec2-sda', @@policy.get_proper_storage_for_copy(1, 4).name, 'storage by copy_id'
|
80
|
+
end
|
42
81
|
end
|
data/test/storage_test.rb
CHANGED
@@ -7,7 +7,6 @@ class StorageTest < Test::Unit::TestCase
|
|
7
7
|
|
8
8
|
should "initialize" do
|
9
9
|
assert_raise(RuntimeError) { FC::Storage.new :path => 'test' }
|
10
|
-
assert_raise(RuntimeError) { FC::Storage.new :path => '/test' }
|
11
10
|
assert_raise(RuntimeError) { FC::Storage.new :path => 'test/' }
|
12
11
|
assert_nothing_raised { FC::Storage.new :path => '/test/' }
|
13
12
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filecluster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rb-readline
|
@@ -186,7 +186,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
186
186
|
version: '0'
|
187
187
|
segments:
|
188
188
|
- 0
|
189
|
-
hash:
|
189
|
+
hash: -919880063
|
190
190
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
191
191
|
none: false
|
192
192
|
requirements:
|
@@ -195,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
195
195
|
version: '0'
|
196
196
|
segments:
|
197
197
|
- 0
|
198
|
-
hash:
|
198
|
+
hash: -919880063
|
199
199
|
requirements: []
|
200
200
|
rubyforge_project:
|
201
201
|
rubygems_version: 1.8.24
|