OmniOS r151038k is now available.
Microcode for Intel CPUs has been updated to the 2021-06-08 release.
Python has been upgraded to 3.9.6.
It is now possible to use a netgroup database without a system being linked to an LDAP or NIS server. Refer to netgroup(4) for more information.
lx branded zones have been updated to better support distributions using systemd >= v247.
lx branded zones now have basic support for
The Insyde BMC virtual CD-ROM device is now supported.
SMB encryption was not working with MacOS 11.4 clients.
netstat showed duplicate data for UDP source and destination addresses.
netstat -u could associate sockets with the wrong process.
bhyve branded zones could place pass-through devices into the wrong PCI function slot causing problems for the guest. Devices are now always placed in numerical order and the location can be overridden - see bhyve(5)
csh would not always operate correctly when being used to run scripts.
pkg now uses less memory when loading catalogues.
The PCI and USB information databases have been updated.
It was possible, although rare, to encounter a kernel panic when using kernel FPU acceleration in conjunction with RAIDZ pools.
A rare ZFS panic that could occur when deleting millions of files has been fixed.
NFS server performance has been improved.
Several fixes for the in-kernel CIFS/SMB support have been incorporated.
For further details, please see https://omnios.org/releasenotes
Any problems or questions, please get in touch.
Last summer I ended up getting licensed as a radio amateur. (Yes, it took me 11 months to mention it here.) Since then, I’ve been keeping myself busy trying out various aspects of the hobby. A week and a half ago, I got to combine a few of these aspects and participate in the ARRL June VHF contest. Namely, I wanted to try combining: contesting, roving, operating from a park, and antenna building.
I’ve been meaning to try roving for the past 7 months, but every time there was a good opportunity (in other words a VHF contest), life got in the way and I couldn’t participate.
Since I first got the idea, I’ve emailed with a number of people about a variety of radio-related topics. Speaking specifically of VHF contest roving, WB8LYJ and WW7D provided me with plenty of information. As a matter of fact, they gave me so much roving info I didn’t even use it all—yet. Thank you!
Every rove starts with planning of the route. In order to be a rover, one must make contacts from at least two grid squares during the contest. Given that this was going to be my first rove, I decided to do the bare minimum and visit only two grids to get some experience for the next time.
I live in FN42, so I went with a location I knew would work—the Middlesex Fells Reservation. I’ve been there a couple of times, so I knew exactly which hill I wanted to use. This requires a 200 m hike with about 15 m of elevation gain to get to from the parking lot.
Living pretty much in the center of FN42, I have three equally annoying options for the second grid—FN32 to the west, FN43 to the north, and FN41 to the south.
I looked for parks just outside FN42 to operate from and eventually settled on Wells State Park in Sturbridge, MA in FN32.
At VHF and UHF frequencies, the elevation of the antennas matters quite a bit, so I was happy to see that Wells State Park has a decent hill—Carpenter’s Rocks. The peak is at about 260 m while the parking lot at the bottom of the park is at 190 m—or about 70 m of elevation gain over 1.1 km of distance. Hiking up the hill with the necessary radio equipment didn’t seem like too crazy of an idea while sitting at my computer.
Finally, both Wells and Middlesex Fells are in the Parks on the Air and World Wide Flora & Fauna databases. Wells is K-2462 and KFF-2462, while Middlesex Fells is K-8414 and KFF-5690, respectively. So, not only do any contacts made there count toward the contest, I can also use them to get credit for activating the parks. (Well, I didn’t realize that Wells was a WWFF park until after the contest.)
To keep the timing simple, I was going to spend Saturday at Wells and Sunday at Middlesex Fells.
The plan for a few months was to build yagis for 2 m and 70 cm bands and some (weakly) directional antenna for the 6 m band. Somehow, I ran out of time and only managed to build the 2 m yagi the day of the contest.
I went with WA5VJB’s cheap yagi design. I used a 2 inch by 1 inch wooden furring strip for the boom and 1/8 inch aluminum tubes for the elements.
Here’s the antenna after the contest. The elements are beaten up and slightly misaligned.
I bought an 8 foot long furring strip and cut it in half, which gives plenty of space as the 4-element “cheap yagi” design requires 40.5 inches between the reflector and the second director. I placed the reflector about 5 inches from the end of the boom which leaves enough room to act as a hand grip. This left about 2 inches extra on the other end.
Because I didn’t have time to figure out how to attach it to a mast, I drilled 3/8 inch holes about 1 inch from both ends of the boom to let me suspend it on a rope from a tree branch.
The aluminum tubes I found come in 3 foot sections. Unfortunately, three of the four elements in the design are longer than 3 feet, so I had to splice them together to make the longer lengths.
At the hardware store, I noticed that the 3/32 inch aluminum tube fit nicely (but loosely) inside the 1/8 inch tubes. So, the plan was to use bits of the smaller diameter tube as a stub to hold the sections together.
At first, I tried to solder the sections together, but the solder just wasn’t sticking to the aluminum. After nearly giving up on the build, I realized that I can crimp the pieces together. The 0.100 hex die I have for coax crimping works perfectly for this.
So, whenever I needed to do a splice, I’d insert a 1 inch section of the 3/32 inch aluminum tube between the two section of 1/8 inch tube to be joined and I’d crimp each side. This provides decent mechanical and electrical connections.
Completed splice on the driven element:
Unfortunately, the aluminum tubes themselves are rather fragile. While carrying the fully built yagi up and down a hill, it was far too easy to bump one of the elements and bend it immediately next to the boom. It didn’t take many bumps for metal fatigue to result in a break. Thankfully, the one and only break happened on the way home. I still had to fix it in order to use the antenna on the second day of the contest.
I would not recommend 1/8 inch aluminum tubes for 2 m yagis. The elements stick out a bit too much. Combine that with the softness of aluminum, and you have an antenna that’ll break far too easily. A yagi for 70 cm might be narrow enough that these aluminum tubes would work well, but I haven’t tried. I plan to repurpose the tubes from this build for a 10-element 1296 MHz yagi. With the widest element being only 4.3 inches, it should be relatively robust. And if one of the elements breaks, it is simple enough to just cut a new one instead of having to splice things back together.
For the 6 m band, I reused my 1/4 wave vertical that I’ve been using for Parks On The Air activations over the past two months. (I plan on making a separate post about my 1/4 wave verticals.)
I don’t have a dedicated 70 cm antenna. However, I have an Ed Fong DBJ-1, which is a 2 m/70 cm wire J-pole antenna. It only really works on the 440-450 MHz part of the band, but it is better than nothing.
Unsurprisingly, not everything went according to plan.
Suspending the yagi from a branch worked, but it was a bit fiddly. Specifically, it was far too easy to tilt it up or down instead of keeping it level. It was also a bit difficult to aim the antenna in a specific direction since the coax hanging down constantly tried to turn it back to where it started.
The contest started at 18:00Z. I planned to leave early enough that I could drive over to Wells State Park, grab all the gear, hike up the hill, set up, test everything, and then have a few minutes to relax before the start.
Well, I ended up leaving late because of last minute antenna building. I planned to leave about two hours before the start of the contest, but managed to leave only 5 minutes before the start.
I arrived at the park, and it became obvious that I wasn’t quite sure how to get to the top of the hill. Instead of roaming aimlessly around the forest with all the gear, I did a quick hike to the top to find a reasonable way. This extra hiking added another 30 minute delay to my start.
When I got back to the car, I grabbed everything and headed up again. The second ascent was much harder because of the ~16 kg (~35 lbs) of radios, coax, battery, water, etc. Having my hands literally full also made it harder to defend myself from mosquitoes on the way up. Thankfully, the top of the hill didn’t have any.
Once back at the top, I took a few minutes to reduce my heart rate and then I started setting up. That’s when I discovered that even though I brought three antennas with me, I hauled only two coaxes up the hill. I left the third (and spare fourth) in the car. There was no way I was going to go back to the car, so I resorted to moving one of the coaxes between the Ed Fong and the 6 m 1/4 wave. During the first coax swap, I realized that I also forgot a coax switch.
Anyway, at least the view was nice. (You can see the Ed Fong antenna hanging in the tree on the left.)
At 00:00Z, about 20 minutes before sunset, I called it a day, packed up, and descended through the mosquito territory once more to get to the car. During the descent, I managed to break off one of the elements on the yagi.
The first thing I did Sunday morning was fix the yagi. This took extra effort because the break happened at a crimped joint. So, the first step was to remove the broken inner aluminum tube. Once removed, re-crimping took very little time.
After that, eating breakfast, repacking everything, and so on, I headed out to Middlesex Fells. I hiked up the hill, set up the three antennas, and started working stations around noon (16:00Z).
I’m not sure what happened, but I think the repair I did on the yagi or something else messed up its pattern. It seemed as if the pattern rotated 20-30 degrees.
I planned to stay about 8 hours—from noon to 8pm (16:00Z–00:00Z), but about half way through the breeze died down enough that the mosquitoes started biting. It was nowhere near as bad as during the hikes at Wells, but enough that by 5pm (17:00Z) I decided to call it quits. I packed up and headed home. On the way home, I realized that I could use my handheld radio to catch a few more FM contacts by going to Robbins Farm Park. It is near home, has good elevation, and overlooks Boston, Cambridge, etc. — in other words, places with people and therefore hams.
I made it up to Robbins Farm Park about an hour later. I called for good 25 minutes before I got a response. The person that got back to me happens to be a new-ish ham. We chatted for about half an hour about antenna building, portable operations, ham radio in general, software (we’re both software developers), and programming languages. After that contact, I decided that I wanted dinner and went home.
So, how did I do? I ended up with a score of 832 points. Not great, but not bad either.
In more detail, I…
I definitely learned quite a bit about about VHF contesting and roving. None of it is ground breaking, and I’ve heard some variant of each of my conclusions before, but I can confirm that they are valid ideas. :)
The next relevant contest is the CQ World Wide VHF Contest in July. Which means that I have a month to rebuild the 2 m yagi, construct something directional for 6 m that is still easy enough to transport, and figure out a mast. I should also start scoping out locations. Finally, I need to subscribe to some mailing lists so I have a place to announce my intentions.
On several occasions, I expressed opinions about what I consider good and bad ideas as far as sysadmin-friendly interfaces are concerned. Recently, I had a reason to try to organize those thoughts a bit more, and so I decided to write them down in this post.
You may have heard me say that I don’t like “magical behavior”. Instead, I want everything system software does to be explicit. The rest of this post is going to be about words and my mantra when designing sysadmin friendly interfaces.
First of all, explicit does not mean manual. Explicit behavior is simply something the sysadmin has to ask for. A manual behavior is something the sysadmin has to do by hand.
The opposite of explicit is magical. That is, something which has a varying behavior depending subtle differences in “some state” of something related.
The opposite of manual is automatic. That is, repetitive actions are performed by the computer instead of the human operator.
For the tl;dr crowd:
explicit & automatic = good
magical & manual = bad
To “prove” this by example, let me analyze the good ol’ Unix rm command.
By default, it will refuse to remove a directory. You have to explicitly tell it that it is ok to do by using the -d flag (either directly or implicitly via the -r flag).
The command does not try to guess what you likely intended to do—that’d be magical behavior.
At the same time, rm can delete many files without manually listing every single one. In other words, rm has automation built in, and therefore it isn’t manual.
Makes sense? Good.
What does this mean for more complicated software than rm? Well, I came up with these “rules” to guide your design:
Let me go through each of these rules and explain what I mean. I jump between examples of APIs and user (sysadmin) interfaces. In many ways, the same ideas apply to both and so I reach for whichever is easier to talk about at the time.
Avoid magical behavior by not guessing what the user may have intended.
Just like installing a second web browser shouldn’t change all your settings, installing a new RDBMS shouldn’t just randomly find some disk space and reformat it for its use. Similarly, when a new host in a cluster starts up, the software has no way of knowing what the intent is. Is it supposed to go into production immediately? What if it is Friday at 5pm? Would it make sense to wait till Monday morning? Is it supposed to be a spare?
The software should give the sysadmin the tools to perform whatever actions may be needed but leave it up to the sysadmin to decide when to do them. This is very similar to the idea of separation of mechanism and policy.
So, won’t this create a lot of work for the sysadmin? Glad you asked! Keep reading to find out why it doesn’t ;)
Err on the side of caution and error out if the user’s intent isn’t clear.
Error out if you aren’t sure what exactly the user intended. This is really a form of the first rule—avoid magical behavior.
It is better to be (slightly) annoying to use, than to misinterpret the user’s intentions and lose data. “Annoying to use” can be addressed in the future with new commands and APIs. Lost data cannot be “unlost” by code changes.
Provide interfaces and tools to encapsulate implementation details.
If the installation instructions for an operating system included disk byte offsets and values to store there, you’d either think that it is insane or that you are living in the 1970’s and you just got a super fancy 8-bit computer with a (floppy) disk drive.
Any modern OS installer will encapsulate all these disk writes by several layers of abstractions. Disk driver, file system, some sort of mkfs utility, and so on. Depending on the intended users’ skill level, the highest abstraction visible may be a fully functional shell or just a single “Install now” button.
Similarly, a program that requires a database should provide some (explicit) “initialize the database” command instead of requiring the user to run manual queries. (Yes, there is software requiring setup steps like that!) Or in the “new host in a cluster” scenario, the new host should have a “add self to cluster” command for the sysadmin.
With these interfaces and commands, it is possible to automate tasks if the need arises. For example, since the cluster admin already has some form of provisioning or configuration management tool, it is rather easy to add the “add self to cluster” command invocation to the existing tooling. Whether or not to automate this (as well as when exactly to run the command) is a matter of policy and therefore shouldn’t be dictated by the developer.
Err on the side of caution and create (reasonably) low-level primitives.
Different tasks benefit from different levels of abstraction. The higher the abstraction level, the less flexible it is, but the easier it is to use—but only if that’s exactly what you want to do. If what you want to do is not quite what the level of abstraction provides, it can be very difficult (or outright impossible) to accomplish what you are after.
Therefore, it is better to have a solid lower-level abstraction that can be built on rather than a higher-level abstraction that you have to fight with.
Note that these two aren’t mutually exclusive, it is possible to have a low-level abstraction with a few higher level primitives that help with common tasks.
Consider a simple file access API. We could implement functions to delete a single file, delete a set of files, delete recursively, and so on. This would take a lot of effort and would create a lot of code that needs to be maintained. If you are uncertain what the users will need, do the simplest thing you expect them to need. For example, give them a way to delete one file and to list files. Users are clever, and before long they’ll script ways to delete multiple files or to delete recursively.
Then, when you have some user feedback (“I always end up writing the same complicated command over and over”), you can revisit the set of provided primitives, and add or modify as needed.
It doesn’t matter if you are providing a file API, a cluster management API, or something else, providing some form of create, read, update, delete, and list API for each “thing” you expect the users to operate on is sufficient to get going. Of course the type of object will dictate the exact set of operations. For example, better command names may be add/remove (cluster node) instead of a create/delete.
Err on the side of caution and do not commit to support APIs and other interfaces.
It is essentially impossible to predict what APIs or other interfaces will actually end up being useful. It can become a huge maintenance burden (in time and cost) to maintain seldom used interfaces that have only a handful of users. Unfortunately, users like being able to rely on functionality not going away. Therefore, for your own sanity, make it clear:
The first two items are self-explanatory, but the last one requires a few extra words.
It is tempting to say that “function foo is supported”, but that is the wrong way to do it. Rather, you want to say “function foo, which does only bar, is supported”.
For example, suppose that we have a function which returns an array of names (strings). Let’s also assume that it is convenient to keep track of those names internally using a balanced binary search tree. When we implement this get-names function, we are likely to simply iterate the tree appending all the names to the output array. This results in the output being sorted because of the tree-based implementation.
Now, consider these two possible statements of what is supported. First, a bad one:
Function get-names is supported. The function returns all names.
And now a better one:
Function get-names is supported. The function returns all names in an unspecified order.
Using the first (bad) description, it is completely reasonable for someone to start relying on the fact that the returned names are sorted. This ties our hands in multiple ways.
The second (better) description makes it clear that the order of the names can be anything and therefore the users shouldn’t rely on a particular order. It better communicates our intention of what is and what isn’t supported.
Now, say that we’d like to replace the tree with a hash table. (Maybe the tree insertion cost is too high for what we are trying to do.) This is a pretty simple change, but now our get-names output is unsorted. If we used the first description and some major consumer relied on the sorted behavior, we have to add a O(n log n) sort to the end of get-names making everyone pay the penalty instead of just the consumers that want sorted output. On the other hand, the second description lets us do this hash table change.
So, be very explicit about what is and what isn’t supported.
I used a function in the above example, but the same applies to utilities and other tools. For example, it is perfectly reasonable to make the default output of a command implementation dependant, but provide arguments that force certain columns, values, or units for the consumers that care.
A project I worked on a number of years ago had very simple rules for what was supported. Everything was unsupported, unless otherwise stated.
In short, we supported any API function and utility command that had a manpage that didn’t explicitly say that it was a developer-only interface or that the specific behavior should not be relied upon.
Yes, there have been a few instances where our users assumed something was supported when it wasn’t, and inevitably they filed bugs. However, we were able to tell them that there was a better (and supported) way to accomplishing their task. Once they fixed their assumptions, their system became more robust and significantly less likely to break in the future.
Finally, make your interfaces consistent.
Not only internally consistent (e.g., always use the same option name for the same behavior) but also consistent with the rest of the system (e.g., use the same option names that commonly used software uses). This is a rephrasing of the principle of least astonishment.
There are other ways of approaching interface design, but the only one I’ve seen that doesn’t turn into a mess (or doesn’t cause a user revolt) is what I tried to outline here. Specifically, start with a small, simple, consistent, and explicit interface that you barely support and evolve over time.
This was a long post with a lot of information, but it still barely scratches the surface of what could be said. Really, most of the rules could easily turn into lengthy posts of their own. Maybe if there is interest (and I find the time), I’ll elaborate on some of these.
OmniOS weekly releases for w/c 14th of June 2021 are now available.
We have backported a number of fixes and improvements to the r151038 LTS release this week as shown below.
The bhyve hypervisor and the bhyve branded zone have received several updates that enable running with fewer resources and fewer privileges than before.
bhyve VNC sessions are now named based on the underlying virtual machine name rather than always being called “bhyve”.
Additional network backends are available for bhyve, including an emulated
e1000 interface type.
SMB3 encryption no longer breaks MacOS Big Sur clients.
Fixes for kernel FPU use.
The ZFS ARC algorithm has been adjusted to restore memory pressure; see illumos issue 13766.
Several ZFS L2ARC fixes and improvements have been incorporated.
zdb command could crash when processing RAIDZ pools, this has been resolved.
segkpsize tunable can now be adjusted using the
eeprom command - see eeprom(1M).
Improvements to the native C++ and rust demangling library.
The CDP daemon (in.cdpd) now runs with reduced privileges;
zpool list -vp now shows parsable sizes in all fields.
nvmeadm now supports parsable output; see nvmeadm(1M)
profiles -l could crash when an LDAP backend was in use, this has been resolved.
For further details, please see https://omnios.org/releasenotes
Any problems or questions, please get in touch.