After some hiatus, there has been some work here on the project, and after some work… here is it the (in)famous RC3 with the so much talked refactor :-D
It was known that NodeOS architecture was still too much dependent of the original centrilized design in part done due to the CUSL. This made it dificult to maintain because code was heavily cohexive, and the whole build process was painfully slow. After splittin it in several projects for each layer it was shown that this main project was almost empty having all the logic on each layer, so after some initial serious intention to port NodeOS to ARM once for all (but unsuccesful? More on this later), the conclusion was that it was needed to clean-up the code first. A lot. And so I did :-)
- Now all the logic regarding the generation of NodeOS for each platform is moved to the main NodeOS project itself, making each layer and sub-project to generate just simple and focused products that later are aggregated. Just plain ol’ school UNIX filosophy. For example, nodeos-barebones now just only generates a
.cpio.gzinitram to be embedded in the kernel (and the kernel itself, but it’s planned to be moved out too in the foresee future), without worrying about what particular NodeOS flavor will use it since it will be later customized, or nodeos-usersfs now don’t have any dependency on the other layers, making it easier to understand how to create other custom users filesystems. It also convert and pack the different layers as the format needed by the target platform, being that a tarfile or an
ext2filesystem or whatever, customizing them by adding or removing specific files if needed.
nodeos-rootfsmodule has been finally deprecated and replaced by the nodeos-bootfs tool, that generate the
/bootpartition or ISO image only when needed. It was there for legacy reasons before making each user to have their own root filesystem, but it was just a no-op in the cases where there was no need for a boot partition, so finally it was removed.
- One important point is that each layer now has its own tests, that help to easily and sooner identify the problems that could arise by making each layer more independent, and in fact some of them has appear during the process of adding them (and a test is not good enough if it doesn’t show some bugs ;-) ). One of the biggest missing testing areas was to check that the prebuild release images of NodeOS where in fact bootable, that has been fixed both by creating a wrapping module on top of the libblkid library to be able to detect the partitions by their UUID instead of hardcoded device, and by showing the Syslinux bootloader prompt for just 0.1 seconds so the test can be able to detect and hook on it and append
console=ttyS0to the kernel command line, so now it’s not only possible to capture its output and control the console but also the users can move the partitions around and add their own boot arguments without problems. The wrapper for
libblkidhas not be done without problems, due to the lack of documentation of how internally it works (at first I was not interested on compile it but just only to know how it detected the partitions UUIDs, because util-linux is a huge monolithic library) and later due to a lot of legacy code that prevented to compile it easily with recent tools (I needed to hack its code to make it compile with node-gyp…).
- Since now each layer is more independent and has their own tests it makes sense to also generate their own
prebuildimages automatically, and the fact is that this has helped to improve the NodeOS build time A LOT. By (ab)using the prebuild-install module now they checks if there’s available a prebuild image for the target platform, and if so then it’s used instead of download its source code and compile it, and to don’t need to download useless build dependencies for them, I’ve also created the buildDependencies module to download them for you in case they are needed by reusing the
devDependenciesfield. So, do you remember the infamous step of pick some microwave pop-corn and go to see a movie from the NodeOS build instructions? Well… now with a decent internet connection and a somewhat fast laptop, maybe you’ll not be able to finish your cup of coffee while using the
BigRedButtonscript to build and test all the NodeOS supported architectures and platforms at once. Yes, so fast is it now :sweat_smile:
nodeos-cross-toolchainand the NodeOS layers build process now accept arguments following the QEmu scheme, and their generated products have been changued to follow them too. This has the side effect that now the
$PLATFORMenvironment variable only define the format of the final products and has nothing to do with the architecture details. It also makes it easier to port to new platforms and architectures and to test them too by having a clear build matrix to follow. It keeps to convert the usage of specific “generic” CPUs identifiers to the more abstract Node.js architecture, so it would not be needed to be translated them several times but just once.
nodeos-bootfshave not been the only modules created for this RC. tar2ext has been created to generate partition images for
usersfsin a similar way to how cpio2tar works, and
chroot, but being on an independent module would help to move forward to use real LXC containers in the future in a simple way.
prebuild images (
musl) publishing releases of both, but definitelly the most important things that need to be fixed is the support to exec interactive console apps in
nsh and the removal of the several projects forks by getting them to be merged upstream, so let’s start to give them some pressure ;-) Oh, and as always, improve the documentation of the different sub-projects, of course…
Regarding ARM, now both
nodeos-nodejs support them and host prebuild images for Raspberry Pi 2, but NodeOS itself can be tested due to problems with QEmu, seems regarding to the loading address of the kernel image. It needs to check if they run in fact on real hardware to confirm that’s a QEmu problem, but until that it has been added support for the Raspberry Pi original because it now has been added support for the board (also untested for the same reasons), and plan to add support for the
versalitepb board since it’s the default one for ARM machines on QEmu and one year ago I was able to boot NodeOS on it (althought getting a kernel panic when executing the
/init binary), so at least let’s hope to be able to tests the ARM architecture too :-)
And now, the…
The RC3 was published last week, but I have been really busy this week and also caught a cold so my mind was not in the perfect state to concentrate and write this essay, so since I had back in my mind the feeling that I almost got something “interesting” to work, I employed the few spare time I got to work on it a little bit each time, and finally this morning I got it:
[email protected]:~/Proyectos/NodeOS$ npm run docker > [email protected] docker /home/piranna/Proyectos/NodeOS > scripts/docker mount procfs: Resource busy Hello! I'm a user init script :-) Welcome to NodeOS!: username: nodeos · : password: ~ >
Yes, that’s it: NodeOS fully booting inside Docker!!! :-D The problem with usersfs has been solved thanks to the refactor by being able now to convert the generated tarfile to a Docker Volume and assigning it directly to
/tmp inside the NodeOS filesystem hierarchy, and it’s configured to support
FUSE filesystems (needed by ExclFS) and OverlayFS (needed by the by-user root filesystem). It’s fairly experimental since I needed to tweak some things, for example I needed to change the Docker storage driver to
overlay2 because the default
aufs one was freezing my machine needing to reboot, and that makes it impractical for debugging it and make it work (maybe now that’s fixed it could work but it’s untested, YMMV). To be honest I’ve needed to do some tricks like disable the usage of node-bin-getty to manage the console because I was not being able to make it owner of the console (maybe I’m doing something wrong?) and exec directly logon and also seems to be there a “little” problem with the user ID:
~ > pstree init ├── exclfs ├─┬ nsh │ └── pstree └── nodeos-reverse- ~ > ls proc/ [ '1', '110', '16', '45', '47', 'acpi', ...
As we can see here, although we login with the
nodeos account we are having the UID
0 and seeing the administrative processes, but at least it works to show how much few processes with administrative permissions are needed for a fully working system, that’s one of the purposses of NodeOS :-D I’m not sure if it could be a problem on NodeOS (I have checked the files directly on the layers managed by Docker and they have the correct UIDs and GIDs) or about Docker ignoring the UIDs and using just only
root for everything because the LXC containers already isolate the processes from the underlying system so by design it’s supposed they are given the least possible permissions (I didn’t found any example that execute a process not as
root inside a Docker instance so far…). In any case, that’s a huge milestone and promise some very interesting things for the future of NodeOS ;-) Next step, vagga ;-)