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 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