From 8e837648693d3a807f6adce72eb69f804dbb916d Mon Sep 17 00:00:00 2001 From: Maarten Vanraes Date: Sun, 15 May 2016 01:33:13 +0200 Subject: PartitionTable: new system, add changedpart handler, implement diff --- lib/ManaTools/Shared/disk_backend.pm | 34 ++++++++ lib/ManaTools/Shared/disk_backend/Part.pm | 52 ++++++++++++ .../Shared/disk_backend/Plugin/Partition.pm | 98 ++++++++++++++++++++++ 3 files changed, 184 insertions(+) diff --git a/lib/ManaTools/Shared/disk_backend.pm b/lib/ManaTools/Shared/disk_backend.pm index d42f6499..9491c42f 100644 --- a/lib/ManaTools/Shared/disk_backend.pm +++ b/lib/ManaTools/Shared/disk_backend.pm @@ -362,6 +362,40 @@ sub changedpart { #============================================================= +=head2 diff + +=head3 INPUT + + $from: PartState (L, P, S) + $to: PartState (L, P, S) + +=head3 OUTPUT + + list of translated strings explaining the differences + +=head3 DESCRIPTION + + this method will call diff on all Parts with $from state on their $to counterpart. + +=cut + +#============================================================= +sub diff { + my $self = shift; + my $from = shift; + my $to = shift; + + my @res = (); + for my $part (grep {$_->is_state($from)} @{$self->parts}) { + for my $str ($part->diff($to)) { + push @res, $str; + } + } + return @res; +} + +#============================================================= + =head2 probeio =head3 OUTPUT diff --git a/lib/ManaTools/Shared/disk_backend/Part.pm b/lib/ManaTools/Shared/disk_backend/Part.pm index c88328ba..59f2cb0c 100644 --- a/lib/ManaTools/Shared/disk_backend/Part.pm +++ b/lib/ManaTools/Shared/disk_backend/Part.pm @@ -241,6 +241,8 @@ sub _reverse_tag { return 'parent' if ($tag eq 'child'); return 'previous' if ($tag eq 'next'); return 'next' if ($tag eq 'previous'); + return undef if ($tag eq 'first'); + return undef if ($tag eq 'last'); return undef if ($tag eq 'loaded'); return undef if ($tag eq 'probed'); return undef if ($tag eq 'saved'); @@ -418,6 +420,28 @@ sub changedpart { return $db->changedpart($self, $partstate); } +sub _save { + return 1; +} + +sub save { + my $self = shift; + $self->_save(); + # TODO: merge loaded into saved +} + +sub _diff { + return (); +} + +sub diff { + my $self = shift; + my $partstate = shift; + my $part = $self->part_state($partstate); + + return $self->_diff($part, $partstate); +} + has 'ins' => ( is => 'ro', isa => 'ManaTools::Shared::disk_backend::IOs', @@ -529,6 +553,34 @@ sub is_state { #============================================================= +=head2 part_state + +=head3 INPUT + + $state: PartState + +=head3 OUTPUT + + ManaTools::Shared::disk_backend::Part|undef + +=head3 DESCRIPTION + + this method returns to requested state of this part + +=cut + +#============================================================= +sub part_state { + my $self = shift; + my $state = shift; + return $self->loaded() if ($state == ManaTools::Shared::disk_backend::Part->LoadedState); + return $self->probed() if ($state == ManaTools::Shared::disk_backend::Part->CurrentState); + return $self->saved() if ($state == ManaTools::Shared::disk_backend::Part->FutureState); + return undef; +} + +#============================================================= + =head2 is_loaded =head3 OUTPUT diff --git a/lib/ManaTools/Shared/disk_backend/Plugin/Partition.pm b/lib/ManaTools/Shared/disk_backend/Plugin/Partition.pm index b6f5a3d8..44549c0b 100644 --- a/lib/ManaTools/Shared/disk_backend/Plugin/Partition.pm +++ b/lib/ManaTools/Shared/disk_backend/Plugin/Partition.pm @@ -70,6 +70,104 @@ has '+tools' => ( } ); +sub _mkparttable { + my $self = shift; + my $part = shift; + + return ManaTools::Shared::disk_backend::PartitionTable->new(parted => $self->tool('parted'), disk => $part->file()); +} + +#============================================================= + +=head2 changedpart + +=head3 INPUT + + $part: ManaTools::Shared::disk_backend::Part + $partstate: PartState + +=head3 OUTPUT + + 0 if failed, 1 if success or unneeded + +=head3 DESCRIPTION + + this overridden method will load/probe/save a partition table when it's called + +=cut + +#============================================================= +override ('changedpart', sub { + my $self = shift; + my $part = shift; + my $partstate = shift; + + ## LOAD + # read the partition table + if ($partstate == ManaTools::Shared::disk_backend::Part->PastState) { + # only BlockDevices for loading + return 1 if (!$part->does('ManaTools::Shared::disk_backend::BlockDevice')); + my $pt = $self->_mkparttable($part); + + # exit if there is no detected PartitionTable + return 1 if (!defined($pt)); + + # make the PartitionElement children + my $prevchild = undef; + for my $p (values %{$pt->partitions()}) { + # define tags + my @tags = ('child', 'loaded', 'saved'); + if (!defined $prevchild) { + push @tags, 'first'; + } + + # create the child with id based on the filename + my $child = $part->mkpart('PartitionElement', {id => $p->{'file'} =~ s'^.+/''r}, @tags); + # TODO: what about earlier loaded parts, or modified saved parts to clean up because we're reloading this one? + + # link with ordered siblings to the previous one + $child->add_taglink($prevchild, 'previous', 'sibling') if (defined $prevchild); + + # set the necessary properties + my @stat = stat($p->{'file'}); + my $dev = $stat[6]; + my $minor = $dev % 256; + my $major = int (($dev - $minor) / 256); + $child->prop('dev', $major .':'. $minor); + $child->sync_majorminor(); + $child->prop('start', $p->{'start'}); + $child->prop('size', $p->{'size'}); + $child->prop('num', $p->{'num'}); + $prevchild = $child; + } + + # add an extra tag to the last child + $part->add_taglink($prevchild, 'last') if (defined $prevchild); + + # trigger changedpart on all children for other plugins to load further + for my $child ($part->find_parts('PartitionElement', 'child', 'loaded')) { + $child->changedpart($partstate); + } + } + + ## PROBE + # TODO: check in the kernel partition table by reading /sys + if ($partstate == ManaTools::Shared::disk_backend::Part->PresentState) { + } + + ## SAVE + # save the partition table + if ($partstate == ManaTools::Shared::disk_backend::Part->FutureState) { + # in all child parts, find PartitionTable entries and trigger ->save(); + for my $p ($part->find_parts(undef, 'child')) { + # TODO: need to be able to abort during save!!! + $p->save(); + } + } + + return 1; +}); + #============================================================= =head2 load -- cgit v1.2.1