fab-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Fab-user] Wait for parallel task to complete


From: anatoly techtonik
Subject: Re: [Fab-user] Wait for parallel task to complete
Date: Fri, 27 Apr 2012 08:32:28 +0300

Thanks for the explanation. I read the tutorial. Still I see I can't
construct the system that will satisfy the following usability
requirements:

  1. Define (or override) hosts from command line
  2. Execute each scheduled task in parallel
  3. Wait until previous task completes successfully on all servers
before moving to the next one
  4. Ability to run each task separately or use master task as a helper command

Command line hosts (1) is needed to test new nodes and control
deployment from 3rd party application.
Parallel execution (2) and (3) is critical to minimize servers downtime.
Master task (4) is also highly desired, because full deployment process
contains a lot of steps.

It seems that this could be real with the @mastertask decorator that
would make task run without servers at all. With it the following
could work as expected.

@task
@parallel
def test:pass

@task
@parallel
def update:pass

@mastertask
def deploy():
   execute(test)
   execute(update)

--
anatoly t.


On Fri, Apr 27, 2012 at 1:28 AM, Morgan Goose <address@hidden> wrote:
> I just read that last line, where you said you wanted to run them with
> hosts defined at runtime. You can either use functions to generate the
> hosts lists or with said example i gave change it up to get rid of the
> deploy task, and then run the fabfile like:
>    $ fab -H local,remote test update
>
> As that will be sequential and honor the host list as well. It will
> also run the test on all hosts before moving to the next task listed,
> update.
>
> -goose
>
> On Thu, Apr 26, 2012 at 3:25 PM, Morgan Goose <address@hidden> wrote:
>> First have you read the tutorial? This is the section that will get
>> you in on host list defining, and point you the the more detailed
>> information that I link to below it:
>> http://docs.fabfile.org/en/1.4.1/tutorial.html#defining-connections-beforehand
>> http://docs.fabfile.org/en/1.4.1/usage/execution.html#host-lists
>>
>> As to what you want to do. Each task will loop over it's list of hosts
>> to run on. So top down it's TaskA over all HostListA's hosts. Then if
>> no errors move to the other task with the same or unique host list
>> (defined either globally or per task).
>>
>> From what you're wanting to do you will construct the fabfile like this:
>>
>> local = ['a','b']
>> remote = ['c','d']
>>
>> def test:pass
>> def update:pass
>>
>> @task
>> @sequential
>> def deploy():
>>    execute(test, hosts=local+remote)
>>    execute(update, hosts=local+remote)
>>
>>
>> Then all hosts will have the test task run on them before moving to
>> looping over the two hosts lists and running the update. You then call
>> it simply with:
>>
>> $ fab deploy
>>
>> And you never run the test and update tasks themselves. Nor do you
>> define anything to be parallel. As parallel runs on the task would
>> test on both hosts in parallel, and then deploy to both hosts in
>> parallel. This was, running sequential and explicitly defined to do
>> so, will fail fast on the test hosts if one dies. Because the host
>> list's order is honored.
>>
>> -goose
>>
>> On Wed, Apr 25, 2012 at 1:13 PM, anatoly techtonik <address@hidden> wrote:
>>> On Sat, Apr 21, 2012 at 7:51 PM, Jeff Forcier <address@hidden> wrote:
>>>> On Fri, Apr 20, 2012 at 5:31 AM, anatoly techtonik <address@hidden> wrote:
>>>>
>>>>> Is it possible in fabric to wait until a subtask completes on all
>>>>> servers successfully before moving to next step?
>>>>
>>>> You need to use execute() to treat subroutines as if they were full
>>>> fledged tasks. execute() is the machinery that says "take this
>>>> function and run it once per host in this list of hosts." Right now
>>>> that machinery is just applying implicitly to your deploy() task and
>>>> you're probably using env.hosts to set your host list.
>>>>
>>>> Remove env.hosts and maybe make that host list a role in env.roledefs.
>>>> Then you can do this:
>>>>
>>>>    env.roledefs = {'myrole': ['a', 'b', 'c']}
>>>>
>>>>    def test(): ...
>>>>    def update(): ...
>>>>
>>>>    def deploy():
>>>>        execute(test, role='myrole')
>>>>        execute(update, role='myrole')
>>>>
>>>> That should have the effect you want: "fab deploy" => first test()
>>>> runs once per host, and when it's all done, update() will run once per
>>>> host. deploy() itself will end up running only one time total -- it's
>>>> just a "meta" task now.
>>>
>>> It took time to realize the that execute() iterates over the global
>>> list of hosts. I expected that the following two to be equivalent, but
>>> they were not:
>>>
>>>  1. fab -H local,remote test update
>>>  2. fab -H local,remote deploy
>>>
>>> I used the script without roles:
>>>
>>>  def test(): ...
>>>  def update(): ...
>>>  def deploy():
>>>      execute(test)
>>>      execute(update)
>>>
>>> 1st execution variant is fully synchronous (i.e. next task doesn't
>>> start until previous finishes) and gave the sequence:
>>>
>>>  local test
>>>  local update
>>>  remote test
>>>  remove update
>>>
>>> but the 2nd variant with subtasks was confusing (I indented to see
>>> what's going on):
>>>
>>>  local deploy
>>>    local test
>>>    remote test
>>>    local update
>>>    remote update
>>>  remote deploy
>>>    local test
>>>    remote test
>>>    local update
>>>    remote update
>>>
>>> I found fabric pretty counter-intuitive in this case. I tried to fix
>>> that without roles by explicitly passing current host:
>>>
>>>  def test(): ...
>>>  def update(): ...
>>>  def deploy():
>>>      execute(test, host=env.host_string)
>>>      execute(update, host=env.host_string)
>>>
>>> This gives:
>>>  local deploy
>>>    local test
>>>    local update
>>>  remote deploy
>>>    remote test
>>>    remove update
>>>
>>> Still not the desired behavior. The desired is:
>>>  deploy
>>>    local test
>>>    remote test
>>>    wait
>>>    local update
>>>    remote update
>>>
>>> I've tried using @parallel decorator for deploy task and it seemed to
>>> work fine at first.
>>>  local deploy
>>>  remote deploy
>>>  remote test
>>>  local test
>>>  local update
>>>  remote update
>>>
>>> But the test step didn't not synchronize - local update executed while
>>> remote test was still running. It looks like the roles is the only
>>> chance, but I'd like to avoid hardcoding server names at all costs. Is
>>> it possible?
>>>
>>> --
>>> anatoly t.
>>>
>>> _______________________________________________
>>> Fab-user mailing list
>>> address@hidden
>>> https://lists.nongnu.org/mailman/listinfo/fab-user



reply via email to

[Prev in Thread] Current Thread [Next in Thread]