=== sadmac_ is now known as sadmac | ||
=== magnetic is now known as foolano | ||
sadmac2 | notting: read my blog? | 18:23 |
---|---|---|
notting | saw it. have not looked at the code. | 18:24 |
sadmac2 | cool | 18:24 |
Keybuk | ion_: I wrote a new allocator over the weekend ;) | 19:08 |
ion_ | Ooo | 19:09 |
sadmac2 | Keybuk: get my email? | 19:09 |
Keybuk | sadmac2: yes. I still think your state machine is crazy | 19:09 |
Keybuk | ion_: nih_alloc and nih_free still work as before (alloc with parent, free anyway) | 19:10 |
Keybuk | but now you have nih_alloc_ref (add a new parent), nih_alloc_unref (drop a parent) and nih_discard (throw away only if there are no parents) | 19:10 |
sadmac2 | Keybuk: and I still haven't seen you propose a mechanism behind that pretty syntax of yours | 19:10 |
ion_ | keybuk: Alright | 19:10 |
ion_ | keybuk: Does unref automatically discard? | 19:10 |
Keybuk | ion_: yes | 19:11 |
Keybuk | sadmac2: err, I've told you exactly what I'm going to do - it hasn't changed since plumbers | 19:11 |
sadmac2 | Keybuk: really? because I haven't read about it the same way twice | 19:12 |
sadmac2 | depsolving keeps disappearing and reappearing... | 19:12 |
Keybuk | "depsolving" ? | 19:12 |
sadmac2 | if you start foo, which depends on bar, does it start both or just error and tell the user "Fix it?" I've heard you tell it both ways | 19:12 |
Keybuk | no you haven't | 19:13 |
sadmac2 | there was an auto keyword at plumbers | 19:14 |
sadmac2 | that vanished last time we spoke | 19:14 |
Keybuk | err, that vanished after a lengthy debate both on the mailing list and on here | 19:16 |
sadmac2 | must've missed it here. Dunno where it was on the mailing list | 19:17 |
Keybuk | "upstart configuration", Nov 2008 | 19:17 |
sadmac2 | ah, so its add a manual now | 19:18 |
Keybuk | no | 19:18 |
sadmac2 | the functionality is still there then | 19:18 |
Keybuk | it's treat disabling jobs as a separate thing to their definition | 19:19 |
Keybuk | a sysadmin can flag a job as disabled | 19:19 |
Keybuk | bit more like SMF | 19:19 |
Keybuk | I ran it by our server team here, their eyes lit up with joy, so it's a keeper | 19:19 |
sadmac2 | ok, so the fundamental difference is in your system states/jobs are first class objects | 19:21 |
sadmac2 | where my system essentially doesn't have a first class object | 19:21 |
sadmac2 | can you solve all the use cases with yours? mounting? (dbus I know you've done) | 19:23 |
Keybuk | I suspect that leads to a lot of differences, both fundamental and trivial | 19:23 |
sadmac2 | I'm fairly certain yours could be implemented on top of mine (not that we should, but its very significant that we can). | 19:23 |
Keybuk | stateless mounting still can't be solved in yours, so I don't see that to be a useful example | 19:23 |
sadmac2 | can you mount at all? | 19:24 |
sadmac2 | can you manage the state for stateful mounting? | 19:24 |
Keybuk | yes, of course | 19:24 |
sadmac2 | 0.5 can't do /either/ that's the importance of the case | 19:24 |
Keybuk | I can manage the state for stateful mounting without Upstart at all | 19:25 |
Keybuk | just by using udev and some shell scripts | 19:25 |
Keybuk | so I'm not sure that's a useful example either | 19:25 |
sadmac2 | I don't know that you can easily express virtual states either (explanation follows): | 19:25 |
sadmac2 | so my usecase would be SELinux | 19:26 |
sadmac2 | its damn useful to know if the system is enforcing or not and act based on this. | 19:26 |
sadmac2 | you can check if the system is enforcing by running getenforce | 19:26 |
sadmac2 | but its hard to get an event stream from which you can derive it | 19:27 |
sadmac2 | in my model its not hard to describe states coming from anywhere. so you could define: | 19:27 |
sadmac2 | selinux: test-by /usr/bin/getenforce | 19:27 |
Keybuk | and it would run that how many times a second? | 19:28 |
sadmac2 | Keybuk: it would run it when it needed to know. When the user lists states or when dependency checking is interested in the selinux state | 19:28 |
sadmac2 | the rest of the time selinux would be neither up nor down | 19:28 |
sadmac2 | its "quantum." neither running nor not running until observed | 19:29 |
Keybuk | it needs to know continually | 19:29 |
Keybuk | otherwise how would it know when to stop a service because selinux is no longer being enforced? | 19:29 |
Keybuk | also would it only check that if a sysadmin issues a start command? | 19:30 |
Keybuk | otherwise when would it check that for other reasons? | 19:30 |
sadmac2 | when the service came up | 19:30 |
sadmac2 | Keybuk: and this can be used in combination with regular ons and when (event1..event2) | 19:30 |
Keybuk | how can the service come up if it's waiting on a dependency using test-by? | 19:31 |
sadmac2 | Keybuk: if there's an exec stanza, then it goes by the usual method (it can verify the test after execing, or not, that's a bit more of a philisophical question) | 19:32 |
Keybuk | sorry | 19:33 |
Keybuk | but it sounds like you really haven't thought this through | 19:33 |
Keybuk | since you're not bothering to answer the question | 19:33 |
sadmac2 | Keybuk: on setenforce(1)..until setenforce(0) | 19:34 |
sadmac2 | Keybuk: the events can still stop it | 19:35 |
Keybuk | ok, let's do a worked example | 19:35 |
sadmac2 | Keybuk: /but/ we don't get the initial setenforce, because its done in initrd (and there be pjones) | 19:35 |
Keybuk | give me a real example of a service that would depend on selinux in this fashion | 19:35 |
sadmac2 | so the additional test-by is necessary | 19:35 |
sadmac2 | Keybuk: setroubleshootd | 19:36 |
sadmac2 | no, that runs in permissive too. If we had one for "disabled" then that works | 19:36 |
Keybuk | ok, let's use setroubleshootd for a moment | 19:36 |
Keybuk | how would its definition be expressed? | 19:37 |
sadmac2 | setroubleshootd when selinux | 19:37 |
Keybuk | no : s ? | 19:37 |
Keybuk | no paths or arguments ? | 19:37 |
sadmac2 | that's just the setroubleshootd ->selinux dep | 19:38 |
Keybuk | setroubleshootd has no other dependencies (not even filesystem writable or mounted?) | 19:38 |
Keybuk | please don't shorthand | 19:38 |
Keybuk | give the full example | 19:38 |
Keybuk | use pastebin if you like | 19:38 |
sadmac2 | setroubleshootd | 19:38 |
sadmac2 | when selinux | 19:38 |
sadmac2 | when can-exec("/usr/bin/selinux") | 19:39 |
sadmac2 | exec /usr/bin/selinux | 19:39 |
sadmac2 | can-exec test-by [ -x %1 ] | 19:40 |
sadmac2 | selinux | 19:40 |
sadmac2 | test-by getenforce | 19:40 |
sadmac2 | when (setenforce(1)..setenforce(0)) | 19:40 |
sadmac2 | #eof | 19:40 |
Keybuk | ok | 19:40 |
Keybuk | now give me a worked example of a system boot | 19:40 |
Keybuk | it's just come up | 19:40 |
Keybuk | Upstart has started | 19:40 |
Keybuk | now what happens? | 19:40 |
Keybuk | well, assumedly it parses the job definitions | 19:41 |
Keybuk | so let's say it's done that <g> | 19:41 |
Keybuk | now what? | 19:41 |
sadmac2 | shit. missing a line | 19:41 |
sadmac2 | can-exec when mounted | 19:42 |
sadmac2 | ^^for efficiency. not mandatory | 19:42 |
Keybuk | you haven't defined mounted in the above, so please do that | 19:42 |
Keybuk | (feel free to just claim it's a state that comes up at some useful point) | 19:42 |
sadmac2 | Keybuk: its a state that comes up whenever a filesystem is mounted. | 19:43 |
Keybuk | what brings that state up? | 19:43 |
Keybuk | I think if you're going to rely on such a thing right now, you need to define it ;) | 19:43 |
Keybuk | it might be easier for your example just to assume that there's only one filesystem and no such state | 19:43 |
sadmac2 | yeah, ignore that. there's some particulars to this stage of boot I'm not thinking of | 19:44 |
sadmac2 | ok, so we're up | 19:44 |
Keybuk | ok | 19:45 |
Keybuk | so we're up | 19:45 |
Keybuk | what happens now? | 19:45 |
sadmac2 | we trip an initial event, say startup. | 19:47 |
sadmac2 | this triggers a whole bunch of states not relevant to this example. | 19:47 |
Keybuk | perhaps | 19:47 |
Keybuk | though that event is not referenced in your above example | 19:47 |
Keybuk | so let's ignore it | 19:47 |
sadmac2 | ok. | 19:48 |
Keybuk | upstart has started, it has parsed its configuration, what happens next? | 19:48 |
sadmac2 | it triggers some state which wants setroubleshootd | 19:49 |
sadmac2 | setroubleshootd in turn wants selinux | 19:49 |
sadmac2 | selinux was enabled with setenforce, but this happened in initrd, so we don't know | 19:49 |
sadmac2 | this being a fresh boot, the state is indeterminate, so we run test-by | 19:49 |
sadmac2 | getenforce tells us selinux is up. we clear that dependency for selinux' | 19:50 |
sadmac2 | can-exec is never triggered by anything but the test-by. | 19:50 |
sadmac2 | so we run the test stanza there | 19:50 |
sadmac2 | it tells us we are allowed to execute /usr/sbin/selinux. | 19:51 |
sadmac2 | */usr/bin/setroubleshoot | 19:51 |
sadmac2 | we bring the state tentatively up, and tell the service manager to run /usr/bin/setroubleshoot | 19:52 |
sadmac2 | it returns a service handle, which we add to our parameters, and come all the way up | 19:52 |
sadmac2 | this triggers a netsplit | 19:54 |
Keybuk | wb | 20:11 |
Keybuk | <sadmac2> this triggers a whole bunch of states not relevant to this example. | 20:11 |
Keybuk | <Keybuk> so let's ignore them | 20:11 |
Keybuk | your example is all that interests me | 20:11 |
Keybuk | and it is self-contained | 20:11 |
Keybuk | it makes no reference to other events, or other states | 20:11 |
Keybuk | upstart has started, it has parsed its configuration, what happens next? | 20:11 |
Keybuk | -- | 20:11 |
Keybuk | that's as far as things got before the split | 20:11 |
sadmac_ | Keybuk: ok, what'd we collectively miss? | 20:16 |
=== sadmac_ is now known as sadmac | ||
Keybuk | <Keybuk> wb | 20:18 |
Keybuk | <sadmac2> this triggers a whole bunch of states not relevant to this example. | 20:18 |
Keybuk | <Keybuk> so let's ignore them | 20:18 |
Keybuk | your example is all that interests me | 20:18 |
Keybuk | and it is self-contained | 20:18 |
Keybuk | it makes no reference to other events, or other states | 20:18 |
Keybuk | upstart has started, it has parsed its configuration, what happens next? | 20:18 |
Keybuk | -- | 20:18 |
Keybuk | that's as far as things got before the split | 20:18 |
Keybuk | --> sadmac_ (n=sadmac@nat/redhat/x-6753e36432a1150f) has joined #upstart | 20:18 |
sadmac | Keybuk: ok, well, we need one more state: running_normal | 20:20 |
sadmac | Keybuk: it has lots and lots and lots of deps. one of them is setroubleshoot | 20:20 |
Keybuk | a goal state | 20:21 |
sadmac | if you so please | 20:21 |
Keybuk | one that lists the services that should be running in normal configuration? | 20:21 |
sadmac | yes | 20:21 |
Keybuk | I consider this a failure | 20:21 |
Keybuk | if we're going to have goals, let's just use initng | 20:22 |
sadmac | umm, what? | 20:22 |
sadmac | why? | 20:22 |
Keybuk | the reasons I wrote Upstart, instead of just modifying something that already exists, is that I expressly did not want goals, runlevels, or anything similar | 20:23 |
Keybuk | it's the _only_ difference between Upstart and those other systems | 20:23 |
sadmac | Keybuk: and its the _most_ requested feature I get from people | 20:23 |
Keybuk | then those people should use initng or launchd or smf | 20:23 |
sadmac | Keybuk: the advantage here is 1) goals aren't mutualy exclusive | 20:23 |
Keybuk | they aren't mutually exclusive in initng either | 20:23 |
sadmac | 2) goals are named, and there are infinitely many | 20:24 |
Keybuk | they are named in initng | 20:24 |
sadmac | 3) they can be expressed in terms of each other | 20:24 |
Keybuk | goals in initng can depend on each other | 20:24 |
sadmac | Keybuk: ok, how do I start a predefined subset of my usual services from the command line? | 20:24 |
Keybuk | in initng? ngc start wibble I think | 20:24 |
Keybuk | it's been a while since I played with it | 20:25 |
sadmac | in upstart | 20:25 |
Keybuk | in my plan for Upstart ? | 20:26 |
sadmac | yes | 20:26 |
Keybuk | start my-predefined-subset-of-my-usual-services | 20:26 |
Keybuk | which is a file that looks something like: | 20:26 |
Keybuk | while service1 and service2 and service3 | 20:26 |
sadmac | a goal state | 20:26 |
Keybuk | you can also just do: | 20:26 |
Keybuk | start service1 | 20:26 |
Keybuk | start service2 | 20:26 |
Keybuk | start service3 | 20:26 |
Keybuk | and that has the same effect | 20:26 |
Keybuk | no, it's not a goal | 20:26 |
sadmac | a set of goal states | 20:26 |
sadmac | yes it is | 20:27 |
Keybuk | no, it really isn't | 20:27 |
sadmac | why not? | 20:27 |
Keybuk | let's put this discussion on abeyance for a moment | 20:28 |
Keybuk | and go back to your example | 20:28 |
Keybuk | <sadmac2> setroubleshootd | 20:28 |
Keybuk | when selinux | 20:28 |
Keybuk | when can-exec("/usr/bin/selinux") | 20:28 |
Keybuk | exec /usr/bin/selinux | 20:28 |
Keybuk | can-exec test-by [ -x %1 ] | 20:28 |
Keybuk | selinux | 20:28 |
Keybuk | test-by getenforce | 20:28 |
Keybuk | when (setenforce(1)..setenforce(0)) | 20:28 |
Keybuk | that is what you defined | 20:28 |
Keybuk | and upstart has started, has parsed its configuration, and is now waiting | 20:28 |
Keybuk | what happens next? | 20:28 |
sadmac | it knows its supposed to start running_normal (from other configuration, kernel cmdline, your pick) | 20:29 |
sadmac | and so it does, and it depsolves it as it starts it | 20:29 |
Keybuk | running_normal isn't defined above | 20:29 |
Keybuk | so please, again, do not reference anything outside your example | 20:29 |
sadmac | I defined it as I came in | 20:29 |
sadmac | in syntax.. | 20:29 |
sadmac | running_normal: | 20:30 |
sadmac | when setroubleshoot | 20:30 |
Keybuk | ok | 20:30 |
sadmac | when <lots of other stuff we won't talk about> | 20:30 |
Keybuk | upstart is waiting | 20:30 |
Keybuk | what tells it to start "running_normal"? | 20:30 |
Keybuk | what tells it to start "setroubleshootd"? | 20:30 |
Keybuk | what tells it to start "selinux?" | 20:30 |
sadmac | upstart's first action on running is always to start some kind of "strap state" which in our case is configured (one way or another) as running_normal | 20:31 |
Keybuk | ok | 20:31 |
Keybuk | that is what I call a "goal" | 20:31 |
sadmac | it does a solve-and-start on the strap state | 20:31 |
Keybuk | goal, strap state, runlevel, etc. | 20:31 |
sadmac | ok | 20:31 |
Keybuk | upstart has a predefined state it tries to reach | 20:31 |
sadmac | I'm not disputing its a goal | 20:31 |
Keybuk | this state is defined as a series of dependencies | 20:31 |
Keybuk | to reach it, it solves the dependency set, starting each service in term | 20:32 |
Keybuk | perhaps applying some kind of ordering to that | 20:32 |
Keybuk | congratulations, you've designed a dependency-based init daemon | 20:32 |
Keybuk | http://initng.org/ - enjoy ;P | 20:32 |
sadmac | Keybuk: what of this strategy are you escaping with upstart? | 20:32 |
Keybuk | Upstart, in its very original definition, is an event-based system | 20:33 |
Keybuk | not a dependency-based system | 20:33 |
sadmac | which is broken | 20:33 |
Keybuk | from the very first document I wrote on the subject, I outlined this as the distinction between Upstart and what else exists out there today | 20:33 |
Keybuk | if that is broken, then Upstart is a failed project and should be abandoned | 20:34 |
Keybuk | our efforts would be better spent on the pre-existing dependency based init daemons | 20:34 |
sadmac | what are we changing then? | 20:34 |
Keybuk | (if you consider that not broken) | 20:34 |
sadmac | what does your plan do that is not a goal? | 20:34 |
Keybuk | if you truly believe that Upstart, as an event-based init daemon, is broken | 20:35 |
Keybuk | and you believe that a dependency-based init daemon works, then you should look into one of the dependency-based daemons | 20:35 |
Keybuk | initng is the prime example here | 20:35 |
Keybuk | if the licence isn't a problem, SMF might be appealing - though it isn't as flexible | 20:35 |
sadmac | ok | 20:35 |
sadmac | but how is an event based init daemon /that solves the problems in 0.5/ still different? | 20:36 |
Keybuk | the difference between the two can be defined quite simply | 20:38 |
Keybuk | a dependency-based init daemon knows where it's going, and figures out how to get there | 20:38 |
Keybuk | an event-based init daemon has no idea, and just does whatever it can | 20:38 |
sadmac | ok, I see your problem. let me adjust my example | 20:39 |
sadmac | to setroubleshoot add: | 20:39 |
sadmac | when running_normal | 20:39 |
sadmac | auto | 20:39 |
sadmac | (the auto is an artifact of the present syntax. It can be massaged out) | 20:40 |
sadmac | and delete running_normal's definition altogether | 20:40 |
sadmac | same result | 20:40 |
sadmac | actually, that's better | 20:40 |
sadmac | now there's no depsolving in standard boot | 20:40 |
Keybuk | so let's go back to the same worked example | 20:40 |
Keybuk | upstart has parsed its configuration | 20:41 |
Keybuk | what does it do next? | 20:41 |
sadmac | well, it marks running_normal as up, by config. This is now just a marker though. It has no deps | 20:41 |
Keybuk | a ground state? | 20:42 |
Keybuk | ie. replace startup with a state? | 20:42 |
sadmac | yes | 20:42 |
Keybuk | (would just "on startup" not be a valid example there?) | 20:42 |
sadmac | ok. I think in the long run this way is better for a few reasons, but sure. | 20:43 |
sadmac | running_normal on startup | 20:43 |
Keybuk | that fulfills one of setroubleshootd's when clauses | 20:43 |
Keybuk | but not the other | 20:43 |
Keybuk | sorry, not the other TWO | 20:43 |
Keybuk | it has a dep on the can-exec("/usr/sbin/selinux") state | 20:44 |
Keybuk | and the selinux state itself | 20:44 |
sadmac | and it doesn't /trigger/ it, let's go into that for a second and then we'll look at those | 20:44 |
sadmac | so running normal comes up. | 20:44 |
sadmac | as upstart finishes doing this, it adds an event to the event queue: trigger-auto-services | 20:45 |
sadmac | this causes setroubleshootd to be brought into question | 20:45 |
sadmac | upstart iterates through setroubleshootd's deps. theres running_normal. that's satisfied. | 20:46 |
sadmac | there's can_exec. upstart looks at the can_exec state and sees that it is undetermined and has a test_by | 20:46 |
sadmac | it runs the test by and finds that /usr/bin/setroubleshootd is accessible | 20:47 |
sadmac | so can_exec is up | 20:47 |
sadmac | note that it does not /come/ up | 20:47 |
sadmac | it /is/ up | 20:47 |
sadmac | upstart just didn't know it before :) | 20:47 |
sadmac | selinux is much the same way. its test_by is run and it is determined to be up. | 20:47 |
Keybuk | for the sake of argument | 20:48 |
sadmac | setroubleshootd's when's now satisfied, it leaps upward | 20:48 |
Keybuk | let's say that selinux is not up | 20:48 |
Keybuk | the test-by fails | 20:48 |
sadmac | test-by fails, selinux remains undetermined, and no setroubleshootd | 20:48 |
sadmac | /now/ | 20:49 |
sadmac | suppose we added this line to our config | 20:49 |
Keybuk | no | 20:49 |
Keybuk | no changing things | 20:49 |
Keybuk | setroubleshootd didn't come up on boot | 20:49 |
sadmac | fine | 20:49 |
Keybuk | the sysadmin notices that, and realises that selinux wasn't enabled | 20:50 |
Keybuk | and enables selinux | 20:50 |
Keybuk | what happens now? | 20:50 |
Keybuk | nothing | 20:50 |
sadmac | no | 20:50 |
sadmac | selinux had 2 lines of config | 20:51 |
Keybuk | nothing tells your system to re-evaluate its test-by clauses | 20:51 |
sadmac | look at number 2 | 20:51 |
sadmac | and let me elaborate | 20:51 |
sadmac | when (setenforce(1)..setenforce(0)) | 20:51 |
sadmac | the sysadmin brings up selinux | 20:51 |
Keybuk | you didn't define setenforce in your example, so I ignored it | 20:51 |
sadmac | you didn't mention this hypothetical appendix in your example | 20:53 |
Keybuk | err | 20:53 |
sadmac | so I didn't elaborate on the mechanisms that would make that case work | 20:53 |
Keybuk | the whole point of working an example is to find out what happens ;) | 20:53 |
sadmac | no, I /know/ what happens | 20:53 |
Keybuk | that means working through all the cases | 20:53 |
sadmac | the point is to tell you | 20:53 |
sadmac | ok, we'll define setenforce | 20:54 |
sadmac | setenforce, through whatever syntax is defined on inotify noticing a change in /selinux/enforcing | 20:54 |
sadmac | (yes, said file supports inotify) | 20:54 |
sadmac | it is emitted with one argument: the contents of that file. | 20:55 |
* sadmac needs selinux auto | 20:56 | |
sadmac | yeah, I'll work on getting the auto thing out of the syntax | 20:56 |
sadmac | its kinda a pain | 20:56 |
sadmac | so the sysadmin changes enforcing, and this satisfies selinux's one and only when clause | 20:57 |
sadmac | from here there's a couple things it could do, and I'm flexible as to which: | 20:58 |
sadmac | we could re-run the test-by to be sure (not certain I like that) | 20:58 |
Keybuk | this is my fundamental issue with test-by | 20:58 |
Keybuk | you have to re-run it periodically | 20:59 |
sadmac | or, and this is my assumption, we simply jump right up. once up, if we are configured with a debug flag, we run the test clause, and if it disagrees with what we just did, we through -EDUMBASS | 20:59 |
sadmac | Keybuk: but we've run it exactly 2 times now, both times deterministically | 20:59 |
sadmac | no interval timer yet | 21:00 |
sadmac | Keybuk: the other thing is even if its unreliable it can still be useful in some form. for example | 21:00 |
sadmac | mount(type: nfs, host: *) | 21:00 |
sadmac | when network-up(%host) | 21:00 |
sadmac | network-up test-by ping %host | 21:01 |
sadmac | even the ingrained unreliabilities there are better than we could do otherwise. | 21:01 |
sadmac | when it fails due to insufficient repitition the mount just takes longer to timeout | 21:02 |
sadmac | when it works though we have a bit more verification and probably a quicker abort, | 21:02 |
Keybuk | to be fair, I should give how I'd do it | 21:08 |
Keybuk | I'm not familar with selinux, but judging above the above | 21:08 |
Keybuk | selinux would look like: | 21:08 |
Keybuk | pre-start exec getenforce || setenforce | 21:08 |
Keybuk | post-stop exec setenforce 0 | 21:08 |
Keybuk | -- | 21:09 |
Keybuk | setroubleshootd would look like: | 21:09 |
Keybuk | while selinux | 21:09 |
Keybuk | exec /usr/sbin/selinux | 21:09 |
Keybuk | the worked example would be | 21:09 |
Keybuk | upstart parses its configuration | 21:09 |
Keybuk | the selinux job has no while condition, so can be immediately started | 21:09 |
Keybuk | if selinux was enabled already, getenforce would succeed so the state would be up | 21:09 |
Keybuk | if selinux was not enabled already, getenforce would fail, so setenforce is run and the state would be up | 21:10 |
Keybuk | (it setenforce failed, then selinux would be down) | 21:10 |
Keybuk | selinux coming up fulfills the while condition for setroubleshootd | 21:10 |
Keybuk | so that would exec /usr/sbin/selinux and come up | 21:10 |
sadmac | what if sbin isn't mounted | 21:10 |
Keybuk | no need for any startup event or ground state, etc. | 21:11 |
Keybuk | you mean /usr ;-) | 21:11 |
sadmac | Keybuk: you've known saner storage admins than me I gues | 21:11 |
sadmac | s | 21:11 |
sadmac | :P | 21:11 |
Keybuk | /sbin cannot be on a separate filesystem | 21:11 |
Keybuk | it contains init | 21:11 |
Keybuk | anyway | 21:12 |
Keybuk | now, the above has a slight disadvantage in that it requires you to not use setenforce directly, but instead use "stop selinux" or "start selinux" as the commands | 21:12 |
Keybuk | that in of itself isn't insane, but it's maybe annoying to experienced sysadmins | 21:12 |
Keybuk | I'd solve that the same way you would | 21:12 |
Keybuk | redefine selinux in terms of the contents of /selinux/enforcing | 21:12 |
Keybuk | that might be something like | 21:13 |
Keybuk | while file-contains /selinux/enforcing 1 | 21:13 |
Keybuk | where file-contains was a built-in that used inotify | 21:13 |
sadmac | you've mostly talked me out of test-by | 21:13 |
sadmac | barring that then, what else is different between the mechanisms? | 21:15 |
sadmac | syntax is somewhat an artifact and somewhat not. I don't care about the syntax but the differences in mine are an artifact of it doing things yours doesn't | 21:16 |
Keybuk | the fact that everything my way is first class | 21:16 |
Keybuk | and it's massively simpler to understand | 21:16 |
sadmac | not really | 21:17 |
Keybuk | I'll go back to what I said months ago | 21:17 |
Keybuk | when I figured it out | 21:17 |
sadmac | foo(bar: baz) == all foos with bar = baz have these properties: | 21:17 |
Keybuk | yours can be summed up as | 21:17 |
Keybuk | <state>: <actions> | 21:17 |
Keybuk | ie. when the state on the left is true, the actions on the right are performed | 21:17 |
sadmac | no | 21:18 |
sadmac | that's very wrong | 21:18 |
sadmac | because there are no actions | 21:18 |
Keybuk | that's how you defined it yourself not so long ago ;) | 21:18 |
sadmac | its declarative, and its backward | 21:18 |
Keybuk | oh, no | 21:18 |
Keybuk | sorry | 21:18 |
Keybuk | <state>: <tests> | 21:18 |
Keybuk | the state on the left is true, while all of the tests on the right are true | 21:18 |
sadmac | I wouldn't go with that either | 21:18 |
Keybuk | confusing it with something else I was thinking of | 21:18 |
sadmac | <set of states>: <properties> | 21:18 |
sadmac | the state[s!] on the left behave in the manner described on the right | 21:19 |
sadmac | my model never talks about one state | 21:20 |
sadmac | it always talks about sets of them | 21:20 |
sadmac | mounted(type: nfs, mountpoint: /) is a subset of mounted(type: nfs) is a subset of mounted() | 21:21 |
sadmac | if you want a model for it, its awk | 21:22 |
sadmac | pattern: transformation | 21:22 |
sadmac | Keybuk: if you put filename: at the top of all your files, how does yours behave differently than mine? | 21:38 |
sadmac | serious question. | 21:38 |
Keybuk | probably in terms of such things as instancing | 21:38 |
sadmac | yeah. that is it | 21:39 |
Keybuk | not to mention arguments, which your system fundamentally relies on | 21:40 |
sadmac_ | Keybuk: what'd I miss? last thing I saw was last thing I said to you | 21:47 |
Keybuk | <Keybuk> not to mention arguments, which your system fundamentally relies on | 21:47 |
=== sadmac_ is now known as sadmac | ||
sadmac | Keybuk: you don't have any arguments at all? | 21:47 |
Keybuk | let me describe things as I see them | 21:51 |
Keybuk | you define in files, or over D-Bus, services, tasks, states and other objects you would like Upstart to control | 21:52 |
Keybuk | as far as Upstart is concerned, these are all just different names for the same thing | 21:52 |
sadmac | ok | 21:52 |
Keybuk | let's call them Objects for now | 21:52 |
Keybuk | (to avoid any inference of behaviour from previous versions) | 21:53 |
sadmac | same so far. except I don't give them different names | 21:53 |
Keybuk | Objects have three basic attributes | 21:53 |
Keybuk | - the condition in which they may be running | 21:53 |
Keybuk | - an activation which starts them | 21:53 |
Keybuk | - and what to do | 21:53 |
Keybuk | a fun fictional example that uses all three | 21:54 |
Keybuk | while apache2 | 21:54 |
Keybuk | on control-alt-delete | 21:54 |
Keybuk | exec echo "don't kill my web server" | wall | 21:54 |
sadmac | ok | 21:54 |
Keybuk | if an object has no condition, then it may be running at all times | 21:55 |
Keybuk | if an object has no activation, it will be activated as soon as the condition is true | 21:55 |
Keybuk | if an object has nothing to do, it is simply a state | 21:55 |
Keybuk | while apache2 | 21:55 |
Keybuk | is valid, except exceedingly pointless | 21:55 |
Keybuk | on control-alt-delete | 21:55 |
Keybuk | exec shutdown -r now | 21:55 |
Keybuk | is valid, it may be run at any time when control-alt-delete is pressed | 21:56 |
Keybuk | exec /sbin/udevd | 21:56 |
Keybuk | is valid, it defines a service that should always be running | 21:56 |
Keybuk | ok so far? | 21:57 |
sadmac | yes | 21:57 |
Keybuk | ok, great | 21:57 |
Keybuk | Objects are just definitions | 21:57 |
Keybuk | Instances are the important thing | 21:58 |
Keybuk | when an Object is running, what we really mean is "there is an Instance of Object" | 21:58 |
Keybuk | when an Object is not running, what we really mean is "there are no Instances of Object" | 21:58 |
Keybuk | when I start apache2, I am not starting the apache2 Object, I am creating an Instance of the apache2 Object and starting that instance | 21:59 |
Keybuk | (not quite true actually, but the definition suffices for now) | 21:59 |
sadmac | ok | 22:00 |
Keybuk | it would be more truthful to say that you start and stop an Instance of the apache2 Object - you don't create it | 22:00 |
Keybuk | Objects reference each other in their matches | 22:01 |
Keybuk | if an Instance of an Object is created, then an Instance of all Objects that reference it are created as well | 22:02 |
Keybuk | that's a very complicated way of saying something very simple | 22:03 |
Keybuk | you can have as many copies of apache2 running as you like | 22:03 |
Keybuk | and for each copy of apache2 that you run, you will get a second copy of everything that depends on apache2 as well | 22:03 |
sadmac | what if you try to run something that depends on apache2 after that? | 22:03 |
Keybuk | Upstart only exposes *Instances* | 22:04 |
Keybuk | if there is something defined that depends on apache2, you will see two copies of it in the list | 22:04 |
Keybuk | so you'd inherently be picking which one you want to run (or probably both) | 22:04 |
Keybuk | and Upstart knows which apache2 instance each is linked to | 22:05 |
Keybuk | Instances have two additional attributes over Objects | 22:05 |
Keybuk | - state (up or down) | 22:06 |
Keybuk | - environment/properties (FOO=BAR) | 22:06 |
Keybuk | an Instance's environment is taken from the exported list of environment of Instances that created it - and optionally the sysadmin's own start command | 22:06 |
sadmac | how do you prevent the rooting problem? | 22:07 |
Keybuk | "the rooting problem" ? | 22:07 |
sadmac | ok, so you have fooservice which depends on barservice | 22:07 |
Keybuk | err | 22:07 |
Keybuk | no I don't | 22:08 |
Keybuk | I can have fooservice which includes barservice in its condition | 22:08 |
sadmac | ok then | 22:08 |
Keybuk | I *very* explicitly avoided the term "depends on" | 22:08 |
Keybuk | fooservice is conditional on barservice? :p | 22:08 |
sadmac | 17:03 < Keybuk> and for each copy of apache2 that you run, you will get a second copy of everything that depends on apache2 as well | 22:08 |
sadmac | depends on | 22:08 |
sadmac | gotcha! | 22:08 |
Keybuk | oh, damn | 22:08 |
Keybuk | :p | 22:08 |
Keybuk | got me | 22:08 |
Keybuk | I'm trying very hard not to call them jobs :p | 22:09 |
Keybuk | anyway | 22:09 |
Keybuk | the rooting problem | 22:09 |
Keybuk | fooservice has while barservice in it | 22:09 |
sadmac | ok, so you have 2 copies of fooservice, and 2 copies of barservice (instances rather | 22:09 |
Keybuk | right | 22:10 |
sadmac | now bazservice comes along, and it has when fooservice, and when barservice | 22:10 |
sadmac | how come you don't get 4 copies of it? | 22:10 |
Keybuk | ok | 22:10 |
Keybuk | I'll talk this one through forwards | 22:11 |
Keybuk | we have a barservice Object | 22:11 |
Keybuk | we have a fooservice Object | 22:11 |
Keybuk | we have a bazservice Object | 22:11 |
Keybuk | fooservice links to barservice | 22:11 |
Keybuk | bazservice links to fooservice and barservice | 22:11 |
Keybuk | right? | 22:12 |
Keybuk | we create an instance of barservice | 22:12 |
sadmac | k | 22:12 |
Keybuk | let's call it bar1 | 22:12 |
Keybuk | this tracks back its links | 22:12 |
Keybuk | fooservice has a link, so we get a new instance "foo1" that links to bar1 | 22:12 |
Keybuk | bazservice has a link to fooservice, so we get a new instance "baz1" that links to "foo1" that links to "bar1" | 22:13 |
Keybuk | bazservice has a link to barservice, but there's already the baz1->bar1 instance | 22:13 |
Keybuk | so no instance needs to be created | 22:13 |
sadmac | what ensures that order | 22:13 |
Keybuk | let's create the second instance the other way | 22:13 |
Keybuk | we create an instance of barservice "bar2" | 22:13 |
sadmac | suppose we evaluate "bazservice has a link to barservice" first? | 22:14 |
Keybuk | bazservice has a link to barservice, but its condition on fooservice is not yet met, so no instance is created | 22:14 |
Keybuk | fooservice has a link, so we get a new instance "foo2" that links to "bar2" | 22:15 |
Keybuk | bazservice has a link to fooservice, so we get a new instance "baz2" that links to "foo2" that links to "bar2" | 22:15 |
sadmac | ok, swap those last two: | 22:15 |
Keybuk | you can't swap the last two | 22:15 |
Keybuk | it's a tree | 22:15 |
Keybuk | a -> b -> c | 22:16 |
sadmac | we have foo1, bar1, foo2, bar2 | 22:16 |
Keybuk | -> c | 22:16 |
sadmac | we go to evaluate bazservice: | 22:16 |
Keybuk | we don't "go to" do anything, we follow trees | 22:16 |
sadmac | what's to keep bazservice from grabbing bar1, then foo2 | 22:16 |
Keybuk | we have a tree | 22:16 |
sadmac | oh, I get it now | 22:16 |
Keybuk | a -> b -> c | 22:17 |
Keybuk | -> c | 22:17 |
sadmac | but the deps aren't necessarily a tree | 22:17 |
sadmac | in fact they aren't now | 22:17 |
Keybuk | there are two valid ways to iterate that | 22:17 |
Keybuk | a, b, c, c | 22:17 |
Keybuk | or a, c, b, c | 22:17 |
Keybuk | either way, c always ends up last ;) | 22:17 |
Keybuk | they damned well are trees | 22:17 |
sadmac | ok, so consider only one foo1 and one bar1 | 22:17 |
sadmac | cut the 2s | 22:17 |
Keybuk | ok | 22:17 |
Keybuk | you have | 22:18 |
sadmac | so we have foo1->bar1, baz1->foo1, baz1->bar1 | 22:18 |
Keybuk | bar1 | 22:18 |
sadmac | triangle | 22:18 |
Keybuk | foo1->bar1 | 22:18 |
Keybuk | baz1->foo1,bar1 | 22:18 |
sadmac | that's triangular | 22:18 |
sadmac | thats not a tree | 22:18 |
Keybuk | no it's not? | 22:18 |
sadmac | draw it | 22:19 |
Keybuk | a -> b -> c | 22:19 |
Keybuk | -> c | 22:19 |
Keybuk | that's a tree | 22:19 |
Keybuk | I can do it the other way too | 22:19 |
sadmac | those 2 cs are the same node | 22:19 |
Keybuk | c -> b -> a | 22:19 |
Keybuk | b -> a | 22:19 |
Keybuk | a | 22:19 |
Keybuk | that's still a tree | 22:19 |
Keybuk | just a baobab ;P | 22:19 |
sadmac | no, it has a cycle | 22:19 |
Keybuk | sure | 22:20 |
Keybuk | it's a bit of a twisty tree ;) | 22:20 |
Keybuk | but it's still a tree | 22:20 |
sadmac | its not a tree | 22:20 |
sadmac | its a directed graph | 22:20 |
Keybuk | (actually it is a digraph because foo could depend on baz) | 22:21 |
Keybuk | but we're not considering that case here :p | 22:21 |
sadmac | digraph is short for directed | 22:21 |
Keybuk | I know | 22:21 |
sadmac | if you can start at any node and get to another by more than one route without backtracking its not a tree | 22:21 |
Keybuk | exxxxcept | 22:22 |
Keybuk | that the only way to iterate it is as a tree | 22:22 |
Keybuk | it's self-breaking | 22:22 |
Keybuk | so while the mesh of objects is a digraph | 22:22 |
Keybuk | the mesh of instances is a tree | 22:22 |
Keybuk | actually, it's more of a bag than anything else, but hey :p | 22:22 |
sadmac | so it has an MST | 22:22 |
sadmac | that just makes it a graph | 22:22 |
sadmac | and well connected | 22:22 |
Keybuk | so now we're finished arguing about terminology, you can see that it works? :p | 22:23 |
sadmac | more or less | 22:23 |
sadmac | go on | 22:23 |
Keybuk | well, that's it really | 22:23 |
sadmac | ok | 22:24 |
sadmac | mine actually doesn't have states the more I think about it. | 22:24 |
sadmac | I keep wanting to call them that, but they're not | 22:24 |
Keybuk | you can never end up with four copies of baz because the instances ref-count each other | 22:24 |
Keybuk | you'd have two instances ref-counting the same instance | 22:24 |
Keybuk | and that's not allowed by model | 22:24 |
Keybuk | oh, one more thing | 22:25 |
Keybuk | you can avoid inheriting instances | 22:25 |
Keybuk | so you only get one instance no matter how many instances of your parent there are | 22:25 |
Keybuk | but in that case, you don't get any environment from them | 22:25 |
Keybuk | any <Object> | 22:26 |
Keybuk | a good example to all of the above is a D-Bus interface to Bind9 (replacing rndc?) | 22:27 |
sadmac | right | 22:27 |
Keybuk | while dbus and bind9 | 22:27 |
Keybuk | exec /usr/sbin/bind9dbd | 22:27 |
Keybuk | you get a copy for each dbus bus daemon you run and each bind9 bus daemon you run | 22:27 |
Keybuk | interconnecting each of them | 22:27 |
Keybuk | (dbus exports the session bus address, assumedly bind9 exports the socket address) | 22:28 |
Keybuk | if you had another service that depended on that and dbus | 22:28 |
Keybuk | while bind9dbd and dbus | 22:28 |
Keybuk | you get a copy for each bind9dbd | 22:29 |
Keybuk | connected to that dbus daemon | 22:29 |
Keybuk | it doesn't multiply | 22:29 |
Keybuk | in fact, in many cases, it gives you fewer than you might actually expect, but usually the number you need | 22:29 |
Keybuk | err, sorry, you get a copy for each dbus connected to a bind9dbd on that dbus daemon | 22:30 |
Keybuk | had that backwards | 22:30 |
sadmac | sounds ok | 22:30 |
sadmac | its actually more complicated than mine XD | 22:31 |
Keybuk | it's far simpler to describe though | 22:31 |
Keybuk | without technical terms | 22:31 |
sadmac | Keybuk: most of the difficulty is I've been insistent on calling them states and dealing with it in this way | 22:32 |
Keybuk | To define your DNS service, create a file /etc/init/bind9 and in that put "exec /usr/sbin/bind9" | 22:32 |
sadmac | Keybuk: I think I can explain it now | 22:32 |
Keybuk | if that DNS service may only be running during certain times, add "while blah and blah or blah" to that file | 22:32 |
sadmac | Keybuk: so you have a computer on/under your desk, right? | 22:34 |
Keybuk | yes | 22:34 |
sadmac | now, there's a lot of things you could say about this computer. "Its fast" (kind of subjective) "Its purple" (maybe maybe not) etc. | 22:35 |
sadmac | my "state machine" manages statements like this | 22:35 |
sadmac | when you configure it, you tell it what can and cannot be true. It then reads events and works out what is true. | 22:35 |
sadmac | "Apache is running" implies that "The harddisk is mounted" | 22:36 |
Keybuk | how do I run apache when the harddisk isn't mounted? | 22:36 |
sadmac | "Apache is running" implies that "The harddisk is not mounted" | 22:37 |
sadmac | now obviously this is too verbose, so we allow shorthand | 22:37 |
Keybuk | no | 22:37 |
Keybuk | I mean | 22:37 |
Keybuk | I'm a sysadmin | 22:38 |
sadmac | apache when not disk | 22:38 |
Keybuk | I have booted, and the hard disk failed to mount | 22:38 |
Keybuk | but I need to start apache | 22:38 |
sadmac | the example is contrived | 22:38 |
Keybuk | hardly | 22:38 |
sadmac | no I mean perhaps the rule is bad | 22:38 |
Keybuk | replace apache with any other service that might normally be only running in a full multi-user condition but for which I might need | 22:38 |
Keybuk | here's a good one | 22:38 |
Keybuk | syslog | 22:39 |
Keybuk | I often need to start that one when debugging | 22:39 |
Keybuk | your system *only* permits you to do the things the daemon allows | 22:39 |
Keybuk | there's no separation | 22:39 |
sadmac | Keybuk: my system is necessarily equivalent to yours | 22:39 |
sadmac | its second order logic. you can define all of computing with it | 22:39 |
sadmac | unless yours isn't a piece of software... | 22:40 |
Keybuk | well, use my example then | 22:40 |
Keybuk | unless I'm mistaken, in order to have two dbus daemons, I would need to define two different dbus daemons | 22:40 |
sadmac | no | 22:40 |
sadmac | well, that's getting ahead actually | 22:41 |
Keybuk | well, dbus with two different possible arguments | 22:41 |
sadmac | ok, that's true | 22:41 |
Keybuk | the point being, the person who wrote the dbus service has to allow, up front, the sysadmin to have multiple copies of it | 22:41 |
Keybuk | it's kinda like the 0.5 instance model | 22:42 |
Keybuk | the service has to define the limits of instantiation | 22:42 |
sadmac | why do you need 2 identical copies of the same service? | 22:42 |
Keybuk | chroot | 22:42 |
Keybuk | namespace | 22:42 |
sadmac | 2 /identical/ copies | 22:42 |
Keybuk | no, you're missing my point | 22:42 |
Keybuk | your system requires that the service define the ways in which they may be different | 22:43 |
sadmac | yes | 22:43 |
sadmac | with the exception that they propagate their arguments | 22:43 |
Keybuk | if you want to allow dbus to be run on different bus addresses, the service has to, up-front, accept an argument to allow that | 22:43 |
sadmac | (this is a recent change) | 22:43 |
sadmac | so different deps yields a different service | 22:43 |
Keybuk | if you want to allow dbus to be run in different chroots, the service has to, up-front, accept an argument to allow that | 22:43 |
Keybuk | it all has to be up-front designed | 22:44 |
sadmac | Keybuk: watch closely. this isn't far from possible: | 22:44 |
sadmac | *(*): when namespace | 22:44 |
Keybuk | use the chroot example? | 22:45 |
sadmac | dbus: exec /usr/bin/dbus-daemon | us_set %bus_id | 22:45 |
Keybuk | *(%chroot): chroot %chroot ? | 22:45 |
Keybuk | everything takes a chroot argument that specifies its chroot? | 22:45 |
sadmac | Keybuk: propagation has been made automatic now | 22:45 |
sadmac | so no %s | 22:45 |
Keybuk | ok | 22:46 |
Keybuk | so the dbus example | 22:46 |
Keybuk | the bus_id is actually set by starting dbus | 22:46 |
sadmac | right | 22:46 |
sadmac | you can see in the script how it works | 22:47 |
sadmac | 17:45 < sadmac> dbus: exec /usr/bin/dbus-daemon | us_set %bus_id | 22:47 |
Keybuk | how do you create a second one? | 22:47 |
sadmac | Keybuk: if you say start dbus, you get dbus(bus_id: deadbeef) | 22:47 |
sadmac | if you say it again you get dbus(bus_id: feedface) | 22:48 |
Keybuk | so if I say start bind9, but there's a bind9 running | 22:48 |
Keybuk | how does that *not* create another bind9? | 22:48 |
sadmac | because bind9's script doesn't set any variables inside of it | 22:48 |
Keybuk | so it has to parse its own exec/script stuff to figure out whether it might set any variables? | 22:49 |
Keybuk | what happens if that just looks like: | 22:49 |
Keybuk | script | 22:49 |
sadmac | Keybuk: it doesn't have to know ahead of time | 22:49 |
Keybuk | echo < FOO | 22:49 |
Keybuk | you might want to use us_set %bus_id | 22:49 |
Keybuk | FOO | 22:49 |
Keybuk | end script | 22:49 |
Keybuk | yes it does | 22:49 |
sadmac | nope | 22:49 |
Keybuk | it has to know *before* it starts bind9! | 22:49 |
sadmac | no it doesn't | 22:49 |
Keybuk | it doesn't know that it shouldn't start another dbus-daemon until it's started it | 22:49 |
Keybuk | because it doesn't know what the value of that variable is until it's read the output | 22:49 |
Keybuk | therefore it cannot know *not* to start bind9 either | 22:50 |
sadmac | Keybuk: but it knows the first time a variable was set | 22:50 |
Keybuk | no it doesn't | 22:50 |
sadmac | yes it does | 22:50 |
sadmac | Keybuk: it attempted to start dbus(*) | 22:50 |
sadmac | Keybuk: only dbus(bus_id: deadbeef) came up | 22:50 |
sadmac | Keybuk: another (infinity-1) services didn't launch | 22:51 |
sadmac | its worth trying again to launch one of them | 22:51 |
sadmac | foo(bar: baz) is a statement. A sentence | 22:54 |
sadmac | It reads "any thing foo such that bar = baz is true" | 22:55 |
sadmac | if you also say foo | 22:55 |
sadmac | it reads "any thing foo is true" | 22:55 |
sadmac | if the second is true, the first must be by definition | 22:55 |
sadmac | so if foo() is up, then foo(bar: baz) is up by definition, but the converse is /not/ true | 22:55 |
sadmac | so for your bind9 example | 22:58 |
sadmac | the first one starts bind9() | 22:58 |
sadmac | the second one can't hope to start bind9(foo: bar), bind9(chicken: never), bind9(wibble: wobble) because these are /already true conditions/ | 22:59 |
sadmac | Keybuk: with me? | 22:59 |
Keybuk | yeah | 23:13 |
Keybuk | I still say your state machine is insanely complicated | 23:13 |
Keybuk | I prefer mine | 23:13 |
sadmac | its logic | 23:22 |
sadmac | its not hard | 23:22 |
sadmac | plus the last 3 ways you got it wrong all would have yielded correct configuration files in most situations :D | 23:23 |
sadmac | In a way I agree that its complicated, but I think the user has to understand it less completely | 23:23 |
sadmac | most guesses will result in you operating it correctly | 23:23 |
sadmac | plus implementing it is really nice | 23:24 |
Generated by irclog2html.py 2.7 by Marius Gedminas - find it at mg.pov.lt!