10 use MogileFS::Util qw(error_code);
11 use MogileFS
::ReplicationPolicy
::MultipleNetworks
;
16 # need just the one, so we only have to stuff the cache once
17 my $polclass = "MogileFS::ReplicationPolicy::MultipleNetworks";
18 my $pol = $polclass->new;
20 # test that the MultipleHosts stuff still works
21 # we cope when there are no ips
24 is
(rr
("min=2 h1[d1=X d2=_] h2[d3=X d4=_]"),
25 "all_good", "all good");
27 # need to get it onto host2...
28 is
(rr
("min=2 h1[d1=X d2=_] h2[d3=_ d4=_]"),
29 "ideal(3,4)", "need host2");
31 # still needs to be on host2, even though 2 copies on host1
32 is
(rr
("min=2 h1[d1=X d2=X] h2[d3=_ d4=_]"),
33 "ideal(3,4)", "need host2, even though 2 on host1");
35 # anywhere will do. (can happen on, say, rebalance)
36 is
(rr
("min=2 h1[d1=_ d2=_] h2[d3=_ d4=_]"),
37 "ideal(1,2,3,4)", "anywhere");
39 # should desperately try d2, since host2 is down
40 is
(rr
("min=2 h1[d1=X d2=_] h2=down[d3=_ d4=_]"),
43 # should try host3, since host2 is down
44 is
(rr
("min=2 h1[d1=X d2=_] h2=down[d3=_ d4=_] h3[d5=_ d6=_]"),
47 # need a copy on a non-dead disk on host1
48 is
(rr
("min=2 h1[d1=_ d2=X,dead] h2=alive[d3=X d4=_]"),
51 # this is an ideal move, since we only have 2 unique hosts:
52 is
(rr
("min=3 h1[d1=_ d2=X] h2[d3=X d4=_]"),
55 # ... but if we have a 3rd host, it's gotta be there
56 is
(rr
("min=3 h1[d1=_ d2=X] h2[d3=X d4=_] h3[d5=_]"),
59 # ... unless that host is down, in which case it's back to 1/4,
61 is
(rr
("min=3 h1[d1=_ d2=X] h2[d3=X d4=_] h3=down[d5=_]"),
64 # too good, uniq hosts > min
65 is
(rr
("min=2 h1[d1=X d2=_] h2[d3=X d4=_] h3[d5=X]"),
68 # too good, but but with uniq hosts == min
69 is
(rr
("min=2 h1[d1=X d2=X] h2[d3=X d4=_]"),
72 # be happy with 3 copies, even though two are on same host (that's our max unique hosts)
73 is
(rr
("min=3 h1[d1=_ d2=X] h2[d3=X d4=X]"),
78 # actual network policy tests
79 my ($ad1, $ad2) = ("#192.168.0.2#" ,"#192.168.0.3#" );
80 my ($ad3, $ad4) = ("#10.0.0.2#" ,"#10.0.0.3#" );
81 my ($ad5, $ad6) = ("#146.101.246.2#","#146.101.142.130#");
83 # stuff the cache with the default, otherwise it'll go to the db
84 $pol->stuff_cache('192.168.0.2' , Net
::Netmask
->new('192.168.0.0/16'));
85 $pol->stuff_cache('192.168.0.3' , Net
::Netmask
->new('192.168.0.0/16'));
86 $pol->stuff_cache('10.0.0.2' , Net
::Netmask
->new('10.0.0.0/16'));
87 $pol->stuff_cache('10.0.0.3' , Net
::Netmask
->new('10.0.0.0/16'));
88 $pol->stuff_cache('146.101.246.2' , Net
::Netmask
->new('146.101.0.0/16'));
89 $pol->stuff_cache('146.101.142.130', Net
::Netmask
->new('146.101.0.0/16'));
91 # retest some multiple Host logic all on the same network
92 # already good. (there's only one network)
93 is
(rr
("min=2 h1[d1=X d2=_]$ad1 h2[d3=X d4=_]$ad2"),
94 "all_good", "all good");
96 # need to get it onto host2...
97 is
(rr
("min=2 h1[d1=X d2=_]$ad1 h2[d3=_ d4=_]$ad2"),
98 "desperate(2,3,4)", "need host2");
100 # still needs to be on host2, even though 2 copies on host1
101 is
(rr
("min=2 h1[d1=X d2=X]$ad1 h2[d3=_ d4=_]$ad2"),
102 "desperate(3,4)", "need host2, even though 2 on host1");
104 # target another network
105 is
(rr
("min=2 h1[d1=_ d2=X]$ad1 h2[d3=_ d4=_]$ad2 h3[d5=_ d6=_]$ad3 h4[d7=_ d8=_]$ad4"),
106 "ideal(5,6,7,8)","target other network"); # no device 3 or 4 (or 1) in the ideal
109 is
(rr
("min=2 h1[d1=_ d2=X]$ad1 h2[d3=_ d4=_]$ad2 h3=down[d5=_ d6=_]$ad3 h4=down[d7=_ d8=_]$ad4"),
110 "desperate(1,3,4)", "desperate this network");
112 is
(rr
("min=2 h1[d1=_ d2=X]$ad1 h2[d3=_ d4=_]$ad2 h3[d5=_ d6=_]$ad3 h4[d7=_ d8=_]$ad5"),
113 "ideal(5,6,7,8)","include both other networks with three networks");
115 is
(rr
("min=2 h1[d1=_ d2=X]$ad1 h2[d3=_ d4=_]$ad2 h3=down[d5=_ d6=_]$ad3 h4[d7=_ d8=_]$ad5"),
116 "ideal(7,8)","one of three networks down");
118 is
(rr
("min=2 h1[d1=_ d2=X,dead]$ad1 h2=alive[d3=_ d4=_]$ad2 h3=alive[d5=X d6=_]$ad3"),
119 "ideal(1,3,4)","dead copies don't exclude a network");
121 is
(rr
("min=2 h1[d1=_ d2=X]$ad1 h2[d3=_ d4=_]$ad2 h3[d5=X d6=_]$ad3"),
122 "all_good","enough copies on different networks");
124 is
(rr
("min=2 h1[d1=_ d2=X]$ad1 h2[d3=X d4=X]$ad2"),
125 "too_good","3 copies on 2 networks with a min of 2 is too good");
127 # too many copies on one network, not enough on another, want to over-replicate
128 is
(rr
("min=2 h1[d1=X d2=X]$ad1 h2[d3=X d4=X]$ad2 h3[d5=_ d6=_]$ad3 h4[d7=_ d8=_]$ad4"),
129 "ideal(5,6,7,8)", "more than min hosts, but all on one network");
132 $pol->stuff_cache('146.101.246.2' , Net
::Netmask
->new('146.101.246.0/24'));
133 $pol->stuff_cache('146.101.142.130', Net
::Netmask
->new('146.101.142.0/24'));
135 is
(rr
("min=2 h1[d1=_ d2=X]$ad6 h2[d3=_ d4=_]$ad5 h3[d5=_ d6=_]$ad4 h4[d7=_ d8=_]$ad3"),
136 "ideal(3,4,5,6,7,8)","target other network"); # ad5 and ad6 are no longer the same network
140 my $ostate = $state; # original
142 MogileFS
::Factory
::Host
->t_wipe;
143 MogileFS
::Factory
::Device
->t_wipe;
144 MogileFS
::Config
->set_config_no_broadcast("min_free_space", 100);
145 my $hfac = MogileFS
::Factory
::Host
->get_factory;
146 my $dfac = MogileFS
::Factory
::Device
->get_factory;
149 if ($state =~ s/^\bmin=(\d+)\b//) {
157 my $parse_error = sub {
158 die "Can't parse:\n $ostate\n"
160 while ($state =~ s/\bh(\d+)(?:=(.+?))?\[(.+?)\](#\d+\.\d+\.\d+\.\d+\.?#)?//) {
161 my ($n, $opts, $devstr, $ip) = ($1, $2, $3, $4);
163 die "dup host $n" if $hosts->{$n};
165 # print "1 2 3 4 : <<$1>> <<$2>> <<$3>> <<$4>>\n";
171 $extras{hostip
} = $ip;
174 my $h = $hosts->{$n} = $hfac->set({ hostid
=> $n,
175 status
=> ($opts || "alive"), observed_state
=> "reachable",
176 hostname
=> $n, %extras });
179 foreach my $ddecl (split(/\s+/, $devstr)) {
180 $ddecl =~ /^d(\d+)=([_X])(?:,(\w+))?$/
182 my ($dn, $on_not, $status) = ($1, $2, $3);
183 die "dup device $dn" if $devs->{$dn};
184 my $d = $devs->{$dn} = $dfac->set({ devid
=> $dn,
185 hostid
=> $h->id, observed_state
=> "writeable",
186 status
=> ($status || "alive"), mb_total
=> 1000,
188 if ($on_not eq "X" && $d->dstate->should_have_files) {
193 $parse_error->() if $state =~ /\S/;
195 my $rr = $pol->replicate_to(
202 return $rr->t_as_string;