We've started to decommission our Solaris 10 fileservers
Our migration from our old fileservers to
our new fileservers has been a slow process
that's hit some rough spots. Still, we've
hit a distinct point that I want to mark: this past week we reached
the point where we did '
zpool destroy' on one old fileserver's
old pools and powered down its backend disks.
While we can migrate rapidly when we need to, our decommissionings usually go slowly. Unless we need the rack space or the hardware for something, we mostly leave old servers and so on running until they get annoying for some reason. This makes the whole thing a gradual process, instead of the big bang that I expect some people have. In our case we actually started losing bits of the old fileserver environment almost a year ago, when we started removing bits of our old test environment. More recently we used our hot spare fileserver as a hardware donor during a crisis; we're unlikely to replace it, although we theoretically could.
(In fact we decommissioned this particular fileserver mostly because it was getting annoying. One of the disks in one of its backends failed, causing us to get plaintive email about the situation, so we decided that we wanted to power off all of the remaining disks to preserve them as potential future spares. Destroying the pools instead of just exporting them insures that the disks won't be seen as still in use by a ZFS pool if we reuse them later.)
On the one hand, this is a trivial step and the fileserver had
already had its last filesystems migrated a week or so before this
(and we've destroyed some migrated filesystems for various reasons,
which is far more irreversible than '
zpool destroy'). On the other
hand, it simply feels significant. In a way, it makes the whole
thing real; we've decisively torn down what used to be a production
fileserver. I can now really believe in a relatively near future
where we have no Solaris 10 machines any more.
(It won't be an immediate future; given recent issues all remaining filesystem migrations to the new fileservers are probably on hold until January. In general we try not to do too much in late November and early December due to the university's long holiday around Christmas and the end of the year.)
States in a state machine aren't your only representation of state
I think in terms of state machines a lot; they're one of my standard approaches to problems and I wind up using them quite a bit. I've recently been planning out a multi-threaded program that has to coordinate back and forth between threads as they manipulate the state of host authentication. At first I had a simple set of states, then I realized that these simple states only covered the main flow of events and needed to be more and more complicated, and then I had a blinding realization:
Not all state needs to be represented as state machine states.
When you have a state machine it is not so much tempting as obvious to represent every variation in the state of your entities as another state machine state. But if you do this, then like me you may wind up with an explosion of states, many of which are extremely similar to each other and more or less handled the same way. This isn't necessary. Instead, it's perfectly sensible to represent certain things as flags, additional or detailed status fields, or the like. If you want to mark something as going to be deleted once it's unused, there's no need to add new states to represent this if you can just add a flag. If you have three or four different ways for something to fail and they all lead to basically the same processing, well, you don't need three or four different states for 'failed X way'; you can have just one 'failed' state and then another field with the details of why.
Off the top of my head now, I think that states are best for things
that have a different flow of processing (ideally a significantly
different flow). The more both the origin state and the processing
of two 'states' resembles each other, the less they need to be
separate states and the more the difference can be captured in a
different variable or field (and then handled in the code with only
(On the other hand, if two different states were handled the same way but came from different origin states and transitioned to different destination states, I think I'd definitely keep them as separate states and just share the common code somehow. This would preserve the clarity of state flow in the system. Although if two separate states needed exactly the same handling in the code, I might think I was overlooking something about the states in general.)