[18:23] <sadmac2> notting: read my blog?
[18:24] <notting> saw it. have not looked at the code.
[18:24] <sadmac2> cool
[19:08] <Keybuk> ion_: I wrote a new allocator over the weekend ;)
[19:09] <ion_> Ooo
[19:09] <sadmac2> Keybuk: get my email?
[19:09] <Keybuk> sadmac2: yes.  I still think your state machine is crazy
[19:10] <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:11] <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:12] <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:13] <Keybuk> no you haven't
[19:14] <sadmac2> there was an auto keyword at plumbers
[19:14] <sadmac2> that vanished last time we spoke
[19:16] <Keybuk> err, that vanished after a lengthy debate both on the mailing list and on here
[19:17] <sadmac2> must've missed it here. Dunno where it was on the mailing list
[19:17] <Keybuk> "upstart configuration", Nov 2008
[19:18] <sadmac2> ah, so its add a manual now
[19:18] <Keybuk> no
[19:18] <sadmac2> the functionality is still there then
[19:19] <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:21] <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:23] <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:24] <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:25] <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:26] <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:27] <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:28] <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:29] <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:30] <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:31] <Keybuk> how can the service come up if it's waiting on a dependency using test-by?
[19:32] <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:33] <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:34] <sadmac2> Keybuk: on setenforce(1)..until setenforce(0)
[19:35] <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:36] <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:37] <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:38] <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:39] <sadmac2>     when can-exec("/usr/bin/selinux")
[19:39] <sadmac2>     exec /usr/bin/selinux
[19:40] <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:41] <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:42] <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:43] <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:44] <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:45] <Keybuk> ok
[19:45] <Keybuk> so we're up
[19:45] <Keybuk> what happens now?
[19:47] <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:48] <sadmac2> ok.
[19:48] <Keybuk> upstart has started, it has parsed its configuration, what happens next?
[19:49] <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:50] <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:51] <sadmac2> it tells us we are allowed to execute /usr/sbin/selinux.
[19:51] <sadmac2> */usr/bin/setroubleshoot
[19:52] <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:54] <sadmac2> this triggers a netsplit
[20:11] <Keybuk> wb
 this triggers a whole bunch of states not relevant to this example.
 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:16] <sadmac_> Keybuk: ok, what'd we collectively miss?
 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:20] <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:21] <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:22] <Keybuk> if we're going to have goals, let's just use initng
[20:22] <sadmac> umm, what?
[20:22] <sadmac> why?
[20:23] <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:24] <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:25] <Keybuk> it's been a while since I played with it
[20:25] <sadmac> in upstart
[20:26] <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:27] <sadmac> yes it is
[20:27] <Keybuk> no, it really isn't
[20:27] <sadmac> why not?
[20:28] <Keybuk> let's put this discussion on abeyance for a moment
[20:28] <Keybuk> and go back to your example
 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:29] <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:30] <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:31] <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:32] <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:33] <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:34] <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:35] <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:36] <sadmac> but how is an event based init daemon /that solves the problems in 0.5/ still different?
[20:38] <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:39] <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:40] <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:41] <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:42] <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:43] <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:44] <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:45] <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:46] <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:47] <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:48] <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:49] <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:50] <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:51] <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:53] <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:54] <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:55] <sadmac> it is emitted with one argument: the contents of that file.
[20:56]  * 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:57] <sadmac> so the sysadmin changes enforcing, and this satisfies selinux's one and only when clause
[20:58] <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:59] <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
[21:00] <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:01] <sadmac> network-up test-by ping %host
[21:01] <sadmac> even the ingrained unreliabilities there are better than we could do otherwise.
[21:02] <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:08] <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:09] <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:10] <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:11] <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:12] <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:13] <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:15] <sadmac> barring that then, what else is different between the mechanisms?
[21:16] <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:17] <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
 <actions>
[21:17] <Keybuk> ie. when the state on the left is true, the actions on the right are performed
[21:18] <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
 <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:19] <sadmac> the state[s!] on the left behave in the manner described on the right
[21:20] <sadmac> my model never talks about one state
[21:20] <sadmac> it always talks about sets of them
[21:21] <sadmac> mounted(type: nfs, mountpoint: /) is a subset of mounted(type: nfs) is a subset of mounted()
[21:22] <sadmac> if you want a model for it, its awk
[21:22] <sadmac> pattern: transformation
[21:38] <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:39] <sadmac> yeah. that is it
[21:40] <Keybuk> not to mention arguments, which your system fundamentally relies on
[21:47] <sadmac_> Keybuk: what'd I miss? last thing I saw was last thing I said to you
 not to mention arguments, which your system fundamentally relies on
[21:47] <sadmac> Keybuk: you don't have any arguments at all?
[21:51] <Keybuk> let me describe things as I see them
[21:52] <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:53] <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:54] <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:55] <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:56] <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:57] <Keybuk> ok so far?
[21:57] <sadmac> yes
[21:57] <Keybuk> ok, great
[21:57] <Keybuk> Objects are just definitions
[21:58] <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:59] <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)
[22:00] <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:01] <Keybuk> Objects reference each other in their matches
[22:02] <Keybuk> if an Instance of an Object is created, then an Instance of all Objects that reference it are created as well
[22:03] <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:04] <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:05] <Keybuk> and Upstart knows which apache2 instance each is linked to
[22:05] <Keybuk> Instances have two additional attributes over Objects
[22:06] <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:07] <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:08] <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:09] <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:10] <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:11] <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:12] <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:13] <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:14] <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:15] <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:16] <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:17] <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:18] <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:19] <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:20] <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:21] <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:22] <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:23] <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:24] <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:25] <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:26] <Keybuk>   any <Object>
[22:27] <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:28] <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:29] <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:30] <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:31] <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:32] <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:34] <sadmac> Keybuk: so you have a computer on/under your desk, right?
[22:34] <Keybuk> yes
[22:35] <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:36] <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:37] <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:38] <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:39] <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:40] <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:41] <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:42] <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:43] <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:44] <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:45] <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:46] <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:47] <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:48] <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:49] <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:50] <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:51] <sadmac> Keybuk: another (infinity-1) services didn't launch
[22:51] <sadmac> its worth trying again to launch one of them
[22:54] <sadmac> foo(bar: baz) is a statement. A sentence
[22:55] <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:58] <sadmac> so for your bind9 example
[22:58] <sadmac> the first one starts bind9()
[22:59] <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?
[23:13] <Keybuk> yeah
[23:13] <Keybuk> I still say your state machine is insanely complicated
[23:13] <Keybuk> I prefer mine
[23:22] <sadmac> its logic
[23:22] <sadmac> its not hard
[23:23] <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:24] <sadmac> plus implementing it is really nice