filecluster 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,12 +1,21 @@
1
- # Dstorage
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 'dstorage'
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 dstorage
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
@@ -1,3 +1,6 @@
1
+ периодически удалять пустые папки
2
+ при создании item-а по папке проверять что папка не пустая
3
+ проработать item-ы папки
1
4
  добавить в check storage проверку на дорступность урла
2
5
 
3
6
  алерт на доступность в каждоый политике стораджа на запись
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 show all stotages for all hosts
22
- show <name> show full info for storage
23
- add add new storage
24
- rm <name> delete storage
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 show all plicies
31
- show <id> show full info for policy
32
- add add new policy
33
- rm <id> delete policy
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, :get_storages) do
36
- policy_storages = self.storages.split(',')
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.get_proper_storage(row['size'], item_storages) if 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.storages on storage delete and update
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 FIND_IN_SET(name, storages) GROUP BY #{@prefix}policies.id) as new_policy
81
- SET #{@prefix}policies.storages = new_policy.storages WHERE #{@prefix}policies.id = new_policy.id;
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
- storages text NOT NULL DEFAULT '',
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.storages on policy change - guarantee valid policy.storages
101
- SELECT GROUP_CONCAT(name) INTO @storages_list FROM #{@prefix}storages WHERE FIND_IN_SET(name, NEW.storages);
102
- SET NEW.storages = @storages_list;
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.get_storages.detect{|s| local_path.index(s.path) == 0 && local_path.sub(s.path, '') == item_params[:name]}
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.get_proper_storage(item.size)
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, 'storages, copies'
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 get_storages
13
- return @storages_cache if @storages_cache && Time.new.to_i - @get_storages_time.to_i < self.class.storages_cache_time
14
- @get_storages_time = Time.new.to_i
15
- @storages_cache = FC::Storage.where("name IN (#{storages.split(',').map{|s| "'#{s}'"}.join(',')})")
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
- # get available storage for object by size
19
- def get_proper_storage(size, exclude = [])
20
- get_storages.detect do |storage|
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
- Time.new.to_i - check_time.to_i < self.class.check_time_limit
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
- cmd = self.class.curr_host == host ?
40
- "cp -r #{local_path} #{self.path}#{file_name}" :
41
- "scp -rB #{local_path} #{self.host}:#{self.path}#{file_name}"
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
- cmd = self.class.curr_host == host ?
49
- "cp -r #{self.path}#{file_name} #{local_path}" :
50
- "scp -rB #{self.host}:#{self.path}#{file_name} #{local_path}"
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
- cmd = self.class.curr_host == host ?
58
- "rm -rf #{self.path}#{file_name}" :
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 #{self.path}#{file_name} not deleted" unless r.empty?
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
- cmd = self.class.curr_host == host ?
73
- "du -sb #{self.path}#{file_name}" :
74
- "ssh -oBatchMode=yes #{self.host} 'du -sb #{self.path}#{file_name}'"
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
@@ -1,3 +1,3 @@
1
1
  module FC
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -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
- id = ARGV[2]
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: #{policy.id}
21
- Storages: #{policy.storages}
22
- Copies: #{policy.copies}
23
- Items: #{count}}
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
- storages = stdin_read_val('Storages')
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(:storages => storages, :copies => copies)
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
- Storages: #{storages}
39
- Copies: #{copies}}
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
- id = ARGV[2]
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
@@ -13,11 +13,7 @@ def storages_list
13
13
  end
14
14
 
15
15
  def storages_show
16
- name = ARGV[2]
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
- storage = FC::Storage.new(:name => name, :host => host, :path => path, :url => url, :size_limit => size_limit)
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
- name = ARGV[2]
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(:storages => 'host1-sda,host1-sdb,host1-sdc', :copies => 2)
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(:storages => 'rec1-sda,rec1-sdd', :copies => 2)
19
- policies << FC::Policy.new(:storages => 'rec1-sda,bla,rec2-sdd', :copies => 3)
20
- policies << FC::Policy.new(:storages => 'bla,rec1-sda,test', :copies => 4)
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].storages, "Policy (id=#{@policies[0].id}) incorrect storages"
79
- assert_equal 'rec1-sda,rec2-sdd', @policies[1].storages, "Policy (id=#{@policies[0].id}) incorrect storages"
80
- assert_equal 'rec1-sda', @policies[2].storages, "Policy (id=#{@policies[0].id}) incorrect storages"
81
- assert_raise(Mysql2::Error, 'Create policy with incorrect storages') { FC::Policy.new(:storages => 'bla,test').save }
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
- assert_equal 'rec1-sda', @policies[0].storages, "Policy (id=#{@policies[0].id}) incorrect storages after storage change"
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].storages, "Policy (id=#{@policies[1].id}) incorrect storages after storage delete"
93
- @policies[0].storages = 'rec1-sda,rec2-sda,bla bla'
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 'rec1-sda,rec2-sda', @policies[0].storages, "Policy (id=#{@policies[0].id}) incorrect storages after change"
97
- assert_raise(Mysql2::Error, 'Save empty policy storage') { @policies[0].storages = 'blabla'; @policies[0].save }
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
@@ -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(:storages => 'host1-sda,host2-sda', :copies => 2)
24
- @@policies << FC::Policy.new(:storages => 'host1-sdb,host2-sdb', :copies => 2)
25
- @@policies << FC::Policy.new(:storages => 'host3-sda', :copies => 1)
26
- @@policies << FC::Policy.new(:storages => 'host2-sda', :copies => 1)
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
- @@policy = FC::Policy.new(:storages => 'rec1-sda,rec2-sda', :copies => 1)
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 "get_storages" do
22
+ should "get_create_storages" do
21
23
  FC::Policy.storages_cache_time = 10
22
- assert_same_elements @@storages.map(&:id), @@policy.get_storages.map(&:id)
23
- FC::Storage.new(:name => 'rec2-sdc', :host => 'rec2').save
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.get_storages.size
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.get_storages.size
29
+ assert_equal @@storages.size+1, @@policy.get_create_storages.size
29
30
  end
30
31
 
31
- should "get_proper_storage" do
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
- assert_nil @@policy.get_proper_storage(1), 'all storages down'
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.get_proper_storage(1).id, 'first storages up'
36
- assert_nil @@policy.get_proper_storage(20), 'first storage full'
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.get_proper_storage(20).id, 'second storages up'
39
- assert_nil @@policy.get_proper_storage(1000), 'all storages full'
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.8
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-13 00:00:00.000000000 Z
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: 3979001515347744911
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: 3979001515347744911
198
+ hash: -919880063
199
199
  requirements: []
200
200
  rubyforge_project:
201
201
  rubygems_version: 1.8.24