|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC] Shutdown event script for xl toolstack
On 1 April 2012 09:13, Joseph Glanville <joseph.glanville@xxxxxxxxxxxxxx> wrote:
> On 31 March 2012 05:08, Joseph Glanville
> <joseph.glanville@xxxxxxxxxxxxxx> wrote:
>> On 31 March 2012 01:03, Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> wrote:
>>> Joseph Glanville writes ("[RFC] Shutdown event script for xl toolstack"):
>>>> Previously I had a series of out of tree patches to xend that added a
>>>> shutdown event callback on domain death that would call a script with
>>>> the reason why the domain shutdown.
>>>> Basically analagous to this:
>>>> /etc/xen/scripts/shutdown-event $event $domname $domid
>>>
>>> I think this is a good idea, although it shouldn't be enabled by
>>> default and I don't see the need to provide an example script.
>>
>> Yep fair enough, agree on both points.
>>
>>>
>>>> My general idea is to add a config option for a path to an event
>>>> handler script:
>>>> on_shutdown_event = "/etc/xen/scripts/shutdown-event"
>>>
>>> Yes, this is good. Shouldn't the argument be a string list so that
>>> you can specify all the arguments to exec() ? Will the script inherit
>>> the domid or name in an environment variable ?
>>>
>>> You need to document this fully I think, in docs/man/xl.cfg.pod.5.
>>
>> I didn't think of this but you make a very valid point, especially
>> considering we can use environment vars to provide the domain data as
>> you suggested.
>>
>>>
>>> It would also be good for the script to be able to give instructions
>>> to the daemonic xl, for example to cause the daemonic xl to neither
>>> reboot nor preserve the domain. So if you wanted your domain to get a
>>> different config when it reboots, you write a hook script which
>>> destroys the previous domain and starts the new one by hand.
>>
>> Hmm this is interesting and something I hadn't really thought of
>> implementing.
>> Something that uses the return code of the script I think would be
>> appropriate.
>>
>>>
>>>> Create the event during handle_domain_death in xl_cmdimpl.c and fire
>>>> the script once shutdown reason and action has been parsed.
>>>
>>> When you say "create the event" what do you mean ?
>>
>> I think "create" was most definitely incorrect terminology. :)
>> "catch" probably would have been a much better way of terming it now I
>> look at it.
>>
>>>
>>>> I implemented a hacky version to illustrate my point but I would like
>>>> some advice on how to do this properly and what tools/framework within
>>>> libxl I could leverage to make it cleaner.
>>>
>>> This is going in the right direction. I'll comment in more detail
>>> below.
>>>
>>>> A quick overview of the following would help immensely:
>>>> Where to add in a new config option and what steps it goes through to
>>>> get to libxl_domain_config.
>>>
>>> This hook script functionality should be part of xl, not part of
>>> libxl, so arguably you shouldn't add it to libxl_domain_config.
>>>
>>> Indeed I think it's arguably a mistake that the on_{poweroff,...}
>>> items are in libxl_domain_config rather than in something provided in
>>> xl.
>>>
>>> The config parsing is done in parse_config_data.
>>
>> Cheers will take a look.
>>
>>>
>>>> How to exec an external script safely, can I use usual fork/exec or
>>>> should I be using libxl__exec or libxl_spawn*?
>>>
>>> In xl I think you should use fork/exec. You may not use any functions
>>> libxl__* as they are private for libxl.
>>
>> Thanks for clarifying, I also read the naming convention docs this
>> morning which cleared this up too.
>>
>>>
>>>> Best place/way to get the event data, atm handle_domain_death looks
>>>> like an easy target but there might be more elegant ways..
>>>
>>> handle_domain_death is called in only one place, the event loop in the
>>> daemonic xl. And yes, it seems like the right place to do this.
>>>
>>>> diff --git a/tools/hotplug/Linux/shutdown-event
>>>> b/tools/hotplug/Linux/shutdown-event
>>>
>>> As I say I don't think we need an example like this.
>>>
>>> Also do we think asking the user to handle this with a switch in their
>>> event script is really better than providing four separate config
>>> options for separate commands ? Doing the latter will make the
>>> scripts simpler, which is good because they'll be very annoying to
>>> debug.
>>
>> Agreed, that is a much better approach.
>>
>>>
>>>> + char event_name[10];
>>>> + char event_cmd[100];
>>>>
>>>> switch (info->shutdown_reason) {
>>>> case SHUTDOWN_poweroff:
>>>> action = d_config->on_poweroff;
>>>> + strcpy(event_name,"poweroff");
>>>
>>> Surely event_name should be
>>> const char *event_name;
>>> and then you can do
>>> event_name = "poweroff";
>>>
>>> But this goes away if you have four separate hook script config
>>> options.
>>>
>>>> + snprintf(event_cmd, 100, SHUTDOWN_EVENT_SCRIPT, event_name,
>>>> d_config->c_info.name, domid);
>>>> + ret = system(event_cmd);
>>>
>>> This part needs serious work. We need firstly to define an
>>> interface. And, I don't really like system(). You should be using
>>> fork/exec.
>>
>> Yep, now that has been clarified I will work on something cleaner.
>> I think taking the array of string approach in the config file and
>> then parsing that array verbatim as the args to exec is a great idea.
>>
>>>
>>> Thanks,
>>> Ian.
>>
>> I will refactor this into a v1 patch after I work out the config file
>> stuff, sensible script interface and return values etc.
>>
>> Thanks for all of your help!
>>
>> Joseph.
>>
>> --
>> Founder | Director | VP Research
>> Orion Virtualisation Solutions | www.orionvm.com.au | Phone: 1300 56
>> 99 52 | Mobile: 0428 754 846
>
> Hi Ian,
>
> I have a few more questions.
>
> As I have become more acquainted with the codebase I can see the line
> between libxl and xl quite clearly.
> However the config file territory seems somewhat ambiguous.
> Domain configuration is stored in libxl_domain_config which is a part
> of libxl but there isn't currently a structure for data that is
> private to xl, that is xl daemon or utility specific configuration.
> Is it considered bad form to add a configuration variable to
> libxl_domain_config that only xl will benefit from? if so what is the
> best course of action here?
> I could create another structure for private data but I feel seeking
> guidance on this as prudent.
>
> In the meantime I had added it to libxl_domain_config but I intend to
> have found/made a cleaner solution before submitting the patch for
> inclusion.
>
> In terms of interface I have come up with what I think is inherently
> simple and reliable.
> The shutdown_event_handler is executed with DOM_ID, DOM_NAME, ACTION
> and REASON in it's environment.
> The return code stipulates what action xl will then take, in
> correspondence with the LIBXL_ACTION_ON_SHUTDOWN* counterparts.
>
> I am yet to document this in the xl.cfg.pod file, I will do so in the
> next revision along with adding support for arguments - once we have
> where we are going to store them sorted out at least.
> Patch is only compile tested at this time, I am away from my testing
> environment atm.
>
> Thanks in advance and kind regards,
> Joseph.
>
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index 6b69030..b3e5fb1 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -370,6 +370,8 @@ typedef struct {
> libxl_action_on_shutdown on_reboot;
> libxl_action_on_shutdown on_watchdog;
> libxl_action_on_shutdown on_crash;
> +
> + char *shutdown_event_handler;
> } libxl_domain_config;
> char *libxl_domain_config_to_json(libxl_ctx *ctx, libxl_domain_config *p);
>
> diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
> index 1d59b89..1096f23 100644
> --- a/tools/libxl/xl_cmdimpl.c
> +++ b/tools/libxl/xl_cmdimpl.c
> @@ -664,6 +664,10 @@ static void parse_config_data(const char
> *configfile_filename_report,
> exit(1);
> }
>
> + if (xlu_cfg_replace_string (config, "shutdown_event_handler",
> + &d_config->shutdown_event_handler, 0))
> + d_config->shutdown_event_handler = NULL;
> +
> /* libxl_get_required_shadow_memory() must be called after final values
> * (default or specified) for vcpus and memory are set, because the
> * calculation depends on those values. */
> @@ -1206,6 +1210,63 @@ skip_vfb:
> xlu_cfg_destroy(config);
> }
>
> +static int xl_exec(const char *arg0, char **args, char **envp,
> + useconds_t timeout)
> +{
> + int status;
> + useconds_t sleep_time = 10, wait_time = 0;
> + pid_t child_pid, wpid;
> +
> + child_pid = fork();
> + if (child_pid < 0) {
> + LOG("Failed to fork in xl_exec");
> + exit(-1);
> + } else if (child_pid == 0) {
> + execvpe(arg0,args,envp);
> + } else {
> + do {
> + wpid = waitpid(child_pid, &status, WNOHANG);
> + if (wpid == 0) {
> + if (wait_time < timeout) {
> + usleep(sleep_time);
> + wait_time += sleep_time;
> + } else {
> + kill(child_pid, SIGKILL);
> + }
> + }
> + } while (wpid == 0 && wait_time <= timeout);
> +
> + if (WIFSIGNALED(status)) {
> + return WEXITSTATUS(status);
> + }
> + }
> + return WTERMSIG(status);
> +}
Ahh I fumbled it. Obviously WTERMSIG and WEXITSTATUS should be
reversed here. No idea how I missed this on my last glance over.
> +
> +static int user_shutdown_action(libxl_domain_config *d_config, uint32_t
> domid,
> + int action, unsigned shutdown_reason)
> +{
> + int ret;
> + const char* arg0 = d_config->shutdown_event_handler;
> + char* argv[] = {NULL};
> + char* envp[4];
> + useconds_t timeout = 1000;
> +
> + asprintf(&envp[0],"DOM_ID=%d", domid);
> + asprintf(&envp[1],"DOM_NAME=%s", d_config->c_info.name);
> + asprintf(&envp[2],"ACTION=%d", action);
> + asprintf(&envp[3],"REASON=%u", shutdown_reason);
> + envp[4] = NULL;
> +
> + ret = xl_exec(arg0,argv,envp,timeout);
> +
> + if ((ret < 0) || ( ret > 6)) {
> + LOG("Invalid shutdown action requested: %d, ignoring",ret);
> + return action;
> + }
> + return ret;
> +}
> +
> /* Returns 1 if domain should be restarted,
> * 2 if domain should be renamed then restarted, or 0 */
> static int handle_domain_death(libxl_ctx *ctx, uint32_t domid,
> @@ -1237,6 +1298,10 @@ static int handle_domain_death(libxl_ctx *ctx,
> uint32_t domid,
> action = LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
> }
>
> + if (d_config->shutdown_event_handler)
> + action = user_shutdown_action(d_config, domid, action,
> +
> event->u.domain_shutdown.shutdown_reason);
> +
> LOG("Action for shutdown reason code %d is %s",
> event->u.domain_shutdown.shutdown_reason,
> action_on_shutdown_names[action])
>
> --
> Founder | Director | VP Research
> Orion Virtualisation Solutions | www.orionvm.com.au | Phone: 1300 56
> 99 52 | Mobile: 0428 754 846
--
Founder | Director | VP Research
Orion Virtualisation Solutions | www.orionvm.com.au | Phone: 1300 56
99 52 | Mobile: 0428 754 846
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |