1 /* Copyright (c) 2010 Nicira Networks
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
24 #include "command-line.h"
27 #include "poll-loop.h"
29 #include "socket-util.h"
34 #define THIS_MODULE VLM_xenserverd
37 static void parse_options(int argc, char *argv[]);
38 static void usage(void) NO_RETURN;
40 static void network_uuid_refresh_run(void);
41 static void network_uuid_refresh_wait(void);
44 main(int argc, char *argv[])
46 struct unixctl_server *unixctl;
49 proctitle_init(argc, argv);
50 set_program_name(argv[0]);
53 parse_options(argc, argv);
54 signal(SIGPIPE, SIG_IGN);
57 die_if_already_running();
60 retval = unixctl_server_create(NULL, &unixctl);
68 network_uuid_refresh_run();
69 unixctl_server_run(unixctl);
71 network_uuid_refresh_wait();
72 unixctl_server_wait(unixctl);
82 parse_options(int argc, char *argv[])
87 static struct option long_options[] = {
88 {"help", no_argument, 0, 'h'},
89 {"version", no_argument, 0, 'V'},
94 char *short_options = long_options_to_short_options(long_options);
99 c = getopt_long(argc, argv, short_options, long_options, NULL);
110 OVS_PRINT_VERSION(0, 0);
114 DAEMON_OPTION_HANDLERS
125 if (optind != argc) {
126 ovs_fatal(0, "no non-option arguments accepted");
133 printf("%s: Open vSwitch daemon for XenServer-specific functionality\n"
134 "usage: %s [OPTIONS]\n", program_name, program_name);
137 printf("\nOther options:\n"
138 " -h, --help display this help message\n"
139 " -V, --version display version information\n");
143 /* Network UUID refreshing.
145 * The vswitch database is supposed to maintain an up-to-date UUID for the
146 * system's networks in the Bridge table as external-ids:network-uuids. On
147 * XenServer systems, /opt/xensource/libexec/interface-reconfigure updates
148 * these fields as bridges are brought up and down. Most of the time, that is
149 * sufficient. However, this is one exception: when a XenServer host enters or
150 * leaves a pool, interface-reconfigure is not invoked, and neither is any
151 * other script. So we need to monitor the XenServer's pool membership status
152 * and refresh the network UUIDs (by invoking the refresh-network-uuids script)
155 * This functionality should be harmless on non-XenServer systems, since they
156 * will have neither /etc/xensource/pool.conf nor refresh-network-uuids.
159 /* Timestamp of /etc/xensource/pool.conf, or zeros if it does not exist. */
160 static struct timespec pool_conf_mtime;
162 /* The executing instance of refresh-network-uuids, or NULL if none. */
163 static struct process *refresh_script;
165 /* Time at which to start the refresh script. */
166 static long long int next_refresh = LLONG_MAX;
169 network_uuid_refresh_run(void)
171 struct timespec new_mtime;
173 /* If a script is running, don't do anything until it finishes. */
174 if (refresh_script) {
177 if (!process_exited(refresh_script)) {
181 s = process_status_msg(process_status(refresh_script));
182 VLOG_INFO("refresh-network-uuids exited, %s", s);
185 process_destroy(refresh_script);
186 refresh_script = NULL;
189 /* Otherwise, schedule a refresh in a few seconds if the timestamp has
190 * changed. Refreshing immediately doesn't work because XAPI takes a while
191 * to switch over to new UUIDs.
193 * (We will always detect a change in timestamp when we start up. That's
194 * good, since it means that the refresh-network-uuids script gets
195 * thoroughly tested and we can't miss pool changes that happen when
196 * ovs-vswitchd isn't running.) */
197 get_mtime("/etc/xensource/pool.conf", &new_mtime);
198 if (new_mtime.tv_sec != pool_conf_mtime.tv_sec
199 || new_mtime.tv_nsec != pool_conf_mtime.tv_nsec) {
200 next_refresh = time_msec() + 10 * 1000;
204 /* Otherwise, if our timer expired then start the refresh. */
205 if (time_msec() >= next_refresh) {
209 next_refresh = LLONG_MAX;
211 argv[0] = xasprintf("%s/scripts/refresh-network-uuids",
215 if (!stat(argv[0], &s)) {
216 int error = process_start(argv, NULL, 0, NULL, 0, &refresh_script);
218 VLOG_ERR("failed to refresh network UUIDs: %s could "
219 "not be started (%s)", argv[0], strerror(error));
221 VLOG_INFO("refreshing network UUIDs: started %s", argv[0]);
224 VLOG_ERR("failed to refresh network UUIDs: could not stat %s (%s)",
225 argv[0], strerror(errno));
228 pool_conf_mtime = new_mtime;
234 network_uuid_refresh_wait(void)
236 if (refresh_script) {
237 process_wait(refresh_script);
239 if (pool_conf_mtime.tv_sec) {
240 poll_timer_wait(1000);
242 if (next_refresh != LLONG_MAX) {
243 poll_timer_wait(next_refresh - time_msec());