On 20/03/10 17:31, Nigel Kersten wrote:
> On Sat, Mar 20, 2010 at 8:46 AM, Brice Figureau
> <brice-pup...@daysofwonder.com> wrote:
>> On 20/03/10 14:56, Nigel Kersten wrote:
>>> On Sat, Mar 20, 2010 at 3:45 AM, Brice Figureau
>>> <brice-pup...@daysofwonder.com> wrote:
>>>> On 20/03/10 02:51, Nigel Kersten wrote:
>>>>> So this seemed worth another thread given the significant progress...
>>>>> just about all done by Brice as usual.... :)
>>>>>
>>>>> With jruby 1.4.0 and jetty-rackup from
>>>>> http://github.com/geekq/jetty-rackup and a simple config.ru file that
>>>>> looks like:
>>>>
>>>> I'm using without issue:
>>>> jruby 1.5.0.dev (ruby 1.8.7 patchlevel 174) (2010-03-08 1cc36d4)
>>>>
>>>>> -----------------
>>>>> $0 = "puppetmasterd"
>>>>> require 'puppet'
>>>>>
>>>>> ARGV << "--verbose"
>>>>> #ARGV << "--debug"
>>>>> #ARGV << "--trace"
>>>>>  # I have a special config file for my servers
>>>>> ARGV << "--config" << "/etc/puppet/puppetmasterd.conf"
>>>>> ARGV << "--no-daemonize"
>>>>> ARGV << "--user" << "puppet"
>>>>> ARGV << "--no-ca"
>>>>>
>>>>> ARGV << "--rack"
>>>>> require 'puppet/application/puppetmasterd'
>>>>> # we're usually running inside a Rack::Builder.new {} block,
>>>>> # therefore we need to call run *here*.
>>>>> run Puppet::Application[:puppetmasterd].run
>>>>> -----------------
>>>>>
>>>>> then this little modification to jetty-rackup
>>>>> -----------------
>>>>> jetty = org.mortbay.jetty.Server.new options[:Port]
>>>>> # next 3 lines are new
>>>>> jetty.get_connectors.each do |c|
>>>>>   c.set_header_buffer_size 8192
>>>>> end
>>>>> -----------------
>>>>
>>>> I was about to send you this one :-) but you figured out it.
>>>>
>>>>> and we have something that almost works.
>>>>>
>>>>> err: Could not retrieve catalog: Uncaught exception fork is unsafe and
>>>>> disabled by default on JRuby in method puppetmaster.getconfig
>>>>
>>>> It's strange I don't get that.
>>>>
>>>> Maybe we could rewrite Puppet::Util#execute for jruby to use the JVM
>>>> execute instead of forking.
>>>>
>>>>> I've enabled forking.... -J-Djruby.fork.enabled=true and crossed my
>>>>> fingers... oh look at all this...
>>>>>
>>>>> WARNING: fork is highly unlikely to be safe or stable on the JVM. Have 
>>>>> fun!
>>>>> WARNING: fork is highly unlikely to be safe or stable on the JVM. Have 
>>>>> fun!
>>>>> WARNING: fork is highly unlikely to be safe or stable on the JVM. Have 
>>>>> fun!
>>>>>
>>>>> and we blow up earlier than we did before...  Tried the latest HEAD,
>>>>> it was completely broken, so reverted to a few commits earlier, and
>>>>> made some progress... but then the actual forking looks to fail.
>>>>>
>>>>> info: Autoloaded module base
>>>>> debug: Puppet::Type::Package::ProviderRpm: Executing '/usr/bin/rpm 
>>>>> --version'
>>>>> Could not autoload rpm: No child processes - No child processes
>>>>
>>>> OK, in fact looking harder, I have this call to execute, but it fails in
>>>> my JRuby version without impacting the compilation itself.
>>>>
>>>> In fact the issue comes from this code from the rpm provider:
>>>>    if command('rpm')
>>>>        confine :true => begin
>>>>                rpm('--version')
>>>>           rescue Puppet::ExecutionFailure
>>>>               false
>>>>           else
>>>>               true
>>>>           end
>>>>    end
>>>>
>>>> This code is executed because each type when compiling is asked if it's
>>>> a builtin type, which in turn autoload each provider, which in turn
>>>> executes such "global" code (ie checking confine).
>>>> I don't think it is necessary to autoload the providers (type should be
>>>> enough for the master, isn't it?), but I'm afraid it isn't possible.
>>>
>>> So when I thought about this more, I got more confused. I really
>>> thought providers were pretty much ignored by the server. This seems
>>> quite undesirable to have any of this come into play at all on the
>>> server.
>>
>> I was surprised to find this too. I really thought we weren't loading
>> any provider on the server.
>>
>>> I take it you're saying that it isn't possible to just autoload the
>>> type without the provider?
>>
>> I don't see why it shouldn't be possible, but looking the type auto
>> loader code there is this:
>>
>> # Define a new type.
>> def newtype(name, options = {}, &block)
>>  ...
>>  # Now set up autoload any providers that might exist for this type.
>>  klass.providerloader = Puppet::Util::Autoload.new(klass,
>>           "puppet/provider/#{klass.name.to_s}"
>>  )
>>
>>  # We have to load everything so that we can figure out the default type.
>>  klass.providerloader.loadall()
>>  ...
>> end
>>
>> I don't think it's necessary to load the provider on the server, but
>> this last comment looks strange to me.
>>
>> I think it is safe to comment those lines in puppet/metatype/manager.rb
>> for your experiment.
> 
> yeah, no difference with a quick test. I'll do some more tracing later
> to work out where this is coming from.

That means something else is loading the providers.
I'm wondering where.
I still thinks it is not necessary to load the providers on the master
(this has no real sense).

>>
>>>>
>>>> Anyway if you checkout jruby 1cc36d4 and use the default option you get
>>>> a nice stack trace but no failure of the compilation :-)
>>>
>>> ahah ;) I'll give that a try.
>>>
>>>>
>>>>> It looks like we only fork in three places in Puppet for what it's worth.
>>>>
>>>> Yes, it's:
>>>>  - when daemonizing which you and I are not doing
>>>>  - when executing (or generate)
>>>>  - in puppetrun
>>>>
>>>> I think execute should be rewritten to use the JVM Runtime.exe or
>>>> ProcessBuilder for JRuby, instead of forking. I'll see if I can come
>>>> with a patch later in the week-end.
>>>
>>> I was thinking the same thing, I'll have a poke around too.
>>
>> Something along of:
>>
>> require 'java'
>>
>> include_class 'java.lang.Runtime'
>> include_class 'java.io.InputStreamReader'
>> include_class 'java.io.BufferedReader'
>>
>> process = Runtime.runtime.exec(command)
>> stream = BufferedReader.new(
>>                 InputStreamReader.new(
>>                       process.input_stream
>>                 )
>>         )
>>
>> output = ""
>> while line = stream.read_line
>>        output << "#{line}\n"
>> end
>>
>> process.wait_for
>>
>> should do it fine
> 
> For normal execution :)

Yes, but that should be more than enough for generate() to work on a master.

> Our execute method is a little weirder with all the failonfail,
> stdinfile and combine args, some of which some of my providers rely
> on.

Yes, but I don't think you run your providers on your master. puppetd on
Jruby will be more difficult to have.

> Let's assume we're in the happy place where JRuby is working perfectly
> apart from this issue. How would we maintain this cleanly in the code
> base?

I don't think we should. I think we should indeed push patches to JRuby.
But I fear not everything will be supported (ie fork for instance might
be really difficult to add to JRuby).
To specifically answer your question, maybe we could have a
Puppet::JRuby module in which we could put our jruby stuff.
An interesting question: how do we check we run on JRuby?
-- 
Brice Figureau
My Blog: http://www.masterzen.fr/

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to puppet-...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-dev+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to