diff -urp ./mogile_svn_r237/trunk/api/perl/MogileFS.pm ./mogile_svn_network_patch/trunk/api/perl/MogileFS.pm --- ./mogile_svn_r237/trunk/api/perl/MogileFS.pm 2006-04-20 12:05:08.000000000 +0100 +++ ./mogile_svn_network_patch/trunk/api/perl/MogileFS.pm 2006-04-21 17:02:55.000000000 +0100 @@ -82,6 +82,8 @@ sub new_file { key => $key, fid => $opts->{fid} || 0, # fid should be specified, or pass 0 meaning to auto-generate one multi_dest => 1, + like_network => $opts->{like_network}, + dislike_network => $opts->{dislike_network}, }) or return undef; my $dests = []; # [ [devid,path], [devid,path], ... ] Only in ./mogile_svn_network_patch/trunk/api/perl: version diff -urp ./mogile_svn_r237/trunk/server/mogilefsd ./mogile_svn_network_patch/trunk/server/mogilefsd --- ./mogile_svn_r237/trunk/server/mogilefsd 2006-04-20 12:05:08.000000000 +0100 +++ ./mogile_svn_network_patch/trunk/server/mogilefsd 2006-04-25 19:22:57.000000000 +0100 @@ -77,6 +77,7 @@ my ( $min_free_space, $max_disk_age, $node_timeout, # time in seconds to wait for storage node responses + $network_replicate, # try and replicate copies to another network ); # Command-line options will override @@ -99,6 +100,7 @@ Getopt::Long::GetOptions( 'minfreespace=i' => \$cmdline{min_free_space}, 'default_mindevcount=i' => \$cmdline{default_mindevcount}, 'node_timeout=i' => \$cmdline{node_timeout}, + 'network_replicate' => \$network_replicate, ); $config = $DEFAULT_CONFIG if !$config && -r $DEFAULT_CONFIG; @@ -161,6 +163,7 @@ $DEBUG = choose_value( 'debug', $USE_HTTP = ! choose_value( 'no_http', 0, 1); $default_mindevcount = choose_value( 'default_mindevcount', 2 ); $node_timeout = choose_value( 'node_timeout', 3 ); +$network_replicate = choose_value( 'network_replicate', 0); ### initial setup Mgd::validate_dbh(); @@ -756,6 +759,16 @@ sub replicate { return $retunlock->(0, "Source is no longer available replicating $fid") if $on_count == 0; return $retunlock->(0, "No eligible devices available replicating $fid") if @exist_devid == 0; + my %dislike_network; + if ($network_replicate) { + # try and replicate to a different network + foreach my $host_id (keys %on_host) { + my ($network) = ($Mgd::cache_host{$host_id}->{hostip} =~ m/(\d+\.\d+\.\d+\.)/); + $network .= '0/24'; + $dislike_network{$network}++; + } + } + my $sdevid; while ($on_count < $min) { @@ -765,6 +778,7 @@ sub replicate { random => 1, not_on_hosts => [ keys %on_host ], weight_by_free => 1, + dislike_network => [ keys %dislike_network ], ); # wasn't able to replicate enough? @@ -1139,6 +1153,8 @@ use vars qw($cache_device_summary $cache # weight_by_free => 1, # find result weighted by free space # max_disk_age => 5, # minutes of age the last usage report can be before we ignore the disk # not_on_hosts => [ 1, 2 ], # no devices on hosts 1 and 2 +# like_network => [ '192.168.1.0/24'], # try and find a good device on these networks +# dislike_network => [ '10.0.0.0/24' ], # try and avoid using a device on these netorks # ); # # returns undef if no suitable device was found. else, if you wanted an @@ -1161,6 +1177,8 @@ sub find_deviceid { my $start = $opts{random} ? int(rand($devcount)) : 0; my %not_on_host = ( map { $_ => 1 } @{$opts{not_on_hosts} || []} ); my $total_free = 0; + my @like_network = grep {$_} map { Net::Netmask->new2($_) } @{$opts{like_network} || []}; + my @dislike_network = grep {$_} map { Net::Netmask->new2($_) } @{$opts{dislike_network} || []}; # now find a device that matches what they want my @list; @@ -1181,17 +1199,60 @@ sub find_deviceid { $total_free += $dev->{mb_free}; } + my @liked_devices; + my @not_disliked_devices; + if (@like_network or @dislike_network) { + Mgd::check_host_cache(); + + foreach my $dev_id (@list) { + my $dev = $devs->{$dev_id}; + + foreach my $liked_netmask (@like_network) { + if ($liked_netmask->match($cache_host{$dev->{hostid}}->{hostip})) { + # error("pushing $dev_id to liked_devices"); + push @liked_devices, $dev_id; + } + } + # fixme liked devices are also not_disliked_devices + # so that's a waste of effort + foreach my $disliked_netmask (@dislike_network) { + if (not $disliked_netmask->match($cache_host{$dev->{hostid}}->{hostip})) { + # error("pushing $dev_id to not_disliked_devices"); + push @not_disliked_devices, $dev_id; + } + } + } + + if (@dislike_network) { + if (not scalar(@not_disliked_devices)) { + error("no devices left that aren't on disliked networks (need at least 3 hosts)"); + } + else { + @list = @not_disliked_devices; + } + } + + if (@like_network) { + if (not scalar(@liked_devices)) { + error('cannot find a device on a liked network (need at least 3 hosts)'); + } + else { + @list = @liked_devices; + } + } + } + # now we have a list ordered randomly, do free space weighting if ($opts{weight_by_free}) { my $rand = int(rand($total_free)); my $cur = 0; - + foreach my $devid (@list) { $cur += $devs->{$devid}->{mb_free}; return $devid if $cur >= $rand; } } - + # return whole list if wanting array, else just first item return wantarray ? @list : shift(@list); } @@ -2390,6 +2451,7 @@ sub cmd_create_open { my $dmid = $self->check_domain($args) or return 0; my $key = $args->{key} || ""; my $multi = $args->{multi_dest} ? 1 : 0; + my @like_network = split(',',$args->{like_network} || ''); my $fid = ($args->{fid} + 0) || undef; # we want it to be undef if they didn't give one # and we want to force it numeric... @@ -2416,6 +2478,7 @@ sub cmd_create_open { random => 1, weight_by_free => 1, not_on_hosts => \@hosts, + like_network => \@like_network, ); last unless defined $devid;