Commit e91bade7 authored by Leigh Stoller's avatar Leigh Stoller

Fixes to deal with shared lan race condition.

parent 76e89d3f
......@@ -5244,27 +5244,144 @@ sub SyncPortLans($)
}
#
# Call snmpit once for each experiment that owns one of the
# target vlans.
# Call snmpit once for each lan.
#
my $experiment = $portvlan->GetExperiment();
return -1
if (!defined($experiment));
$portlans{$experiment->idx()} = $experiment;
$portlans{$portvlan->lanid()} = $portvlan;
}
#
# Now do it.
#
foreach my $idx (keys(%portlans)) {
my $experiment = $portlans{$idx};
my $portvlan = $portlans{$idx};
my $experiment = $portvlan->GetExperiment();
return -1
if (!defined($experiment));
my $pid = $experiment->pid();
my $eid = $experiment->eid();
print "Syncing target vlans in $experiment\n";
mysystem("$TB/bin/snmpit_test -f --redirect-err -X $pid $eid");
return -1
if ($?);
#
# The lan is obviously shared, so we have to lock it.
# It should not spend much time locked though, so the
# timeout should not be too long; indicates an error if
# it is.
#
if ($portvlan->Lock(180) != 0) {
tberror("Could not lock $portvlan for a long time!\n");
return -1;
}
print "Syncing target vlan $idx in $experiment\n";
mysystem("$TB/bin/snmpit_test -f --redirect-err -X $pid $eid $idx");
if ($?) {
$portvlan->Unlock();
return -1;
}
$portvlan->Unlock();
}
return 0;
}
#
# When swapping in an experiment, need to copy the ports to the
# shared lans.
#
sub SetupPortLans($)
{
my ($self) = @_;
require Lan;
my @lans;
if (Lan->ExperimentLans($self, \@lans) != 0) {
tberror("Could not get list of all lans for $self\n");
return -1;
}
foreach my $lan (@lans) {
next
if ($lan->type() ne "portlan");
my $target_lanid;
$lan->GetAttribute("target_lanid", \$target_lanid) == 0
or return -1;
my $portvlan = Lan->Lookup($target_lanid);
if (!defined($portvlan)) {
tberror("Could not lookup portvlan $target_lanid\n");
return -1;
}
#
# The lan is obviously shared, so we have to lock it.
# It should not spend much time locked though, so the
# timeout should not be too long; indicates an error if
# it is.
#
if ($portvlan->Lock(180) != 0) {
tberror("Could not lock $portvlan for a long time!\n");
return -1;
}
#
# The idea here is to remove any members for this lan
# from the target lan, and then add the new ones. This
# violates update, in that an error after this will not
# restore the missing ports. Need to fix that.
#
my @members;
if ($portvlan->MemberList(\@members) != 0) {
tberror("Could not get member list for $portvlan\n");
$portvlan->Unlock();
return -1;
}
foreach my $member (@members) {
my $member_exptidx;
my $member_lanname;
$member->GetAttribute("portlan_exptidx", \$member_exptidx);
$member->GetAttribute("portlan_lanname", \$member_lanname);
# Not a port in an external lan; a native port.
next
if (!defined($member_exptidx) && !defined($member_lanname));
if (! (defined($member_exptidx) && defined($member_lanname))) {
tberror("Could not get idx/lanname from $member\n");
$portvlan->Unlock();
return -1;
}
next
if (! ($member_exptidx == $self->idx() &&
$member_lanname eq $lan->vname()));
if ($portvlan->DelMember($member)) {
tberror("Could not delete $member from $portvlan\n");
$portvlan->Unlock();
return -1;
}
}
#
# Now add new members.
#
if ($lan->MemberList(\@members) != 0) {
tberror("Could not get member list for $lan\n");
$portvlan->Unlock();
return -1;
}
foreach my $member (@members) {
my $nodeid;
my $iface;
$member->GetNodeIface(\$nodeid, \$iface);
my $newmember = $portvlan->AddMember($nodeid, $iface);
if (!defined($newmember)) {
tberror("Could not add $member to $portvlan\n");
$portvlan->Unlock();
return -1;
}
$self->printdb("Added $newmember to $portvlan\n");
# Mark where the member came from.
$newmember->SetAttribute("portlan_exptidx", $self->idx());
$newmember->SetAttribute("portlan_lanname", $lan->vname());
}
}
return 0;
}
......@@ -5298,6 +5415,17 @@ sub ClearPortLans($)
return -1;
}
#
# The lan is obviously shared, so we have to lock it.
# It should not spend much time locked though, so the
# timeout should not be too long; indicates an error if
# it is.
#
if ($portvlan->Lock(180) != 0) {
tberror("Could not lock $portvlan for a long time!\n");
return -1;
}
#
# The idea here is to remove any members for this lan
# from the target lan. Then sync the target.
......@@ -5305,6 +5433,7 @@ sub ClearPortLans($)
my @members;
if ($portvlan->MemberList(\@members) != 0) {
tberror("Could not get member list for $portvlan\n");
$portvlan->Unlock();
return -1;
}
foreach my $member (@members) {
......@@ -5319,6 +5448,7 @@ sub ClearPortLans($)
if (! (defined($member_exptidx) || defined($member_lanname))) {
tberror("Could not get idx/lanname from $member\n");
$portvlan->Unlock();
return -1;
}
next
......@@ -5328,23 +5458,29 @@ sub ClearPortLans($)
# Delete the member.
if ($portvlan->DelMember($member)) {
tberror("Could not delete $member from $portvlan\n");
$portvlan->Unlock();
return -1;
}
}
#
# Call snmpit once for each experiment that owns one of the
# target vlans.
# Call snmpit on the lan.
#
my $experiment = $portvlan->GetExperiment();
return -1
if (!defined($experiment));
if (!defined($experiment)) {
$portvlan->Unlock();
return -1;
}
my $pid = $experiment->pid();
my $eid = $experiment->eid();
my $lanid = $portvlan->lanid();
print "Syncing target vlans in $experiment\n";
mysystem("$TB/bin/snmpit_test -f --redirect-err -X $pid $eid");
return -1
if ($?);
print "Syncing target vlan $lanid in $experiment\n";
mysystem("$TB/bin/snmpit_test -f --redirect-err -X $pid $eid $lanid");
if ($?) {
$portvlan->Unlock();
return -1;
}
$portvlan->Unlock();
}
return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment