On 02/27/2017 09:14 AM, Josef Reidinger wrote: > In short I agree that layer between would be nice. And I think in past > such layer is provided by y2-storage and I think it make sense to > continue with it.
And being honest to ourselves, that layer is also there in yast-storage-ng, just in a non-explicit way. We have refinements and patches on top of the libstorage-ng classes to fulfill the YaST use-cases and requirements. Using those refinements has already saved us from adapting the code at yast-country, yast-packager, yast-bootloader and the storage proposal when we introduced encryption support in the library. Patches and refinements are an un-obvious solution (patches are even dangerous). The explicit solution (a visible middle layer) is much preferred in my opinion. > Only reason to not place it directly to y2-storage is > if someone else would like to use storage-ng from ruby, then using > better API from y2-storage can be problematic. Not sure if I got this point. > > Josef Cheers. > On Mon, 27 Feb 2017 08:51:01 +0100 > Ancor Gonzalez Sosa <[email protected]> wrote: > >> Since the original thread is already ruined with discussions about >> concrete API design details that were not the main topic of my >> question, I will try once again from scratch. >> >> Do we need a layer between libstorage-ng and (the rest) of YaST? >> >> I think so. Why do I? >> >> TLDR; libstorage-ng is multilanguage (with a Ruby-agnostic API, to say >> the least) and YaST-agnostic. Therefore, we need a layer to close the >> distance between libstorage-ng and Ruby/YaST. The alternative is to >> have boilerplate code all along YaST (like downcast) and our own >> customization for the Ruby tools. >> >> If you agree, please say so. >> >> If you disagree, please provide counterarguments. >> >> >> Now the long version of my reasoning (and you know that "long" means >> in my case). ;-) >> >> >> A) Libstorage-ng API is designed to be useful for many languages and >> for many potential users, not only Ruby and YaST. >> >> B) Libstorage-ng is designed to be relatively low-level, not hiding >> details about how the different moving pieces (devices, filesystems, >> etc.) are connected and allowing to model all the possibilities that >> can happen in reality. >> >> That's perfectly fine. It makes libstorage-ng more versatile and >> powerful. But it has some implications. >> >> A consequence for (A): when taking API design decisions, if there are >> several ways of doing something and no way is universally better than >> the others[*], libstorage-ng always work in the way that is not >> standard in Ruby. >> >> That means libstorage-ng does not play nicely with the Ruby ecosystem, >> causing extra work for the Ruby developers just to keep using the >> tools chosen for YaST development and testing. >> >> For (B) it means libstorage-ng does not offer a direct answer to the >> kind of questions usually asked all around YaST (yast-packager, >> yast-bootloader, yast-country....). Although examples-based discussion >> has proved to lead to off-topic, I will try once again: >> >> A typical question from YaST to the storage layer: >> - For this given filesystem, which are the physical disks (whatever >> technology is used)? >> >> That question would be plain wrong from the libstorage-ng POV, because >> there is no such a direct relationship (not always) and therefore the >> user of the library is expected to know all the possible paths from a >> a filesystem to its disks and traverse all those paths doing the >> corresponding checks for empty and performing the downcasts in every >> step. >> >> In other words, there is no >> >> a_filesystem.all_disks >> >> But the user is expected to do this >> >> blk_dev = a_filesystem.blk_devices[0] >> if Storage.encryption?(blk_device) >> blk_device = Storage.to_encryption(blk_device).blk_device >> end >> return [Storage.to_disk(blk_dev)] if Storage.disk?(blk_dev) >> if Storage.partition?(blk_device) >> partition = Storage.to_partition(blk_device) >> if Storage.disk?(partition.partition_table.partitionable) >> return [Storage.to_disk(partition.partition_table.partitionable)] >> else >> # MD case >> end >> elsif Storage.lvm_lv?(blk_device) >> # The LVM case, which is double the size than the partition one >> end >> >> This is a simplified example don't taking into account he >> possibilities of multi-device filesystems or encryptions in other >> layers than the very first one (right below the filesystem). >> >> While adapting other modules to use the new libstorage directly we >> have found many examples of that gap between the abstraction level >> expected by YaST and the level of "clarity" about the internal >> structure enforced by libstorage-ng. So please refrain from >> discussing every single variable name in the example or providing an >> alternative with 4 fewer lines. That will not change the main >> point. :) >> >> So, as said at the beginning, libstorage-ng is perfect as it is, for >> the goal it is designed. That goal is not to be Ruby-compliant or to >> match the YaST use-case 100%. So we need an extra layer to walk that >> way. >> >> IMHO, opposing to the creation of that layer just to avoid the fact >> that some developers has to know and work with both layers is not >> reasonable. >> >> If you disagree, please provide counter-arguments to the provided >> arguments, instead of discussing the wording of the examples. ;-) >> >> Cheers. >> >> [*] As proved by the endless discussions focused on examples and >> counter-examples in which nobody convinces nobody else. > -- Ancor González Sosa YaST Team at SUSE Linux GmbH -- To unsubscribe, e-mail: [email protected] To contact the owner, e-mail: [email protected]
