|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC] Shutdown event script for xl toolstack
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);
+}
+
+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
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |