bootinfo_mysql.c 4.39 KB
Newer Older
1
2
3
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
4
#include <syslog.h>
5
6
7
8
9
10
11
12

#include <oskit/boot/bootwhat.h>
#include <mysql/mysql.h>

#ifdef USE_MYSQL_DB

static char dbname[] = "tbdb";
static char dbquery[] =
Mike Hibler's avatar
Mike Hibler committed
13
14
15
16
17
18
   "select n.next_boot_path, n.next_boot_cmd_line, n.def_boot_image_id, "
   "d.img_desc, p.partition, n.def_boot_cmd_line, d.img_path from nodes "
   "as n left join partitions as p on n.node_id=p.node_id and "
   "n.def_boot_image_id=p.image_id left join disk_images as d on "
   "p.image_id=d.image_id left join interfaces as i on "
   "i.node_id=n.node_id where i.IP = '%s'";
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

static MYSQL db;

int
open_bootinfo_db(void)
{
	return 0;
}

int
query_bootinfo_db(struct in_addr ipaddr, boot_what_t *info)
{
	char querybuf[1024];
	int n, nrows, ncols, part;
	MYSQL db;
	MYSQL_RES *res;
	MYSQL_ROW row;

	n = snprintf(querybuf, sizeof querybuf, dbquery, inet_ntoa(ipaddr));
	if (n > sizeof querybuf) {
39
		syslog(LOG_ERR, "query too long for buffer");
40
41
		return 1;
	}
Mike Hibler's avatar
Mike Hibler committed
42
	
43
44
	mysql_init(&db);
	if (mysql_real_connect(&db, 0, 0, 0, dbname, 0, 0, 0) == 0) {
45
		syslog(LOG_ERR, "%s: connect failed: %s",
46
47
48
49
			dbname, mysql_error(&db));
		return 1;
	}

Mike Hibler's avatar
Mike Hibler committed
50
51
52
53
	/* Debug message into log:
	syslog(LOG_ERR, "USING QUERY: %s", querybuf);
	*/
	
54
	if (mysql_real_query(&db, querybuf, n) != 0) {
55
		syslog(LOG_ERR, "%s: query failed: %s",
56
57
58
59
60
61
62
			dbname, mysql_error(&db));
		mysql_close(&db);
		return 1;
	}

	res = mysql_store_result(&db);
	if (res == 0) {
63
		syslog(LOG_ERR, "%s: store_result failed: %s",
64
65
66
67
68
69
70
71
72
73
			dbname, mysql_error(&db));
		mysql_close(&db);
		return 1;

	}
	mysql_close(&db);

	nrows = (int)mysql_num_rows(res);
	switch (nrows) {
	case 0:
74
		syslog(LOG_ERR, "%s: no entry for host %s",
75
76
77
78
79
80
			dbname, inet_ntoa(ipaddr));
		mysql_free_result(res);
		return 1;
	case 1:
		break;
	default:
81
		syslog(LOG_ERR, "%s: %d entries for IP %s, using first",
82
83
84
85
86
87
			dbname, nrows, inet_ntoa(ipaddr));
		break;
	}

	ncols = (int)mysql_num_fields(res);
	switch (ncols) {
Mike Hibler's avatar
Mike Hibler committed
88
	case 7: /* Should have 7 fields */
89
90
		break;
	default:
91
		syslog(LOG_ERR, "%s: %d fields in query for IP %s!",
92
93
94
95
96
97
			dbname, ncols, inet_ntoa(ipaddr));
		mysql_free_result(res);
		return 1;
	}

	row = mysql_fetch_row(res);
Mike Hibler's avatar
Mike Hibler committed
98
99
100
101
102
103
104
105
106

#if 1
	/*
	 * First element is next_boot_path.  If set, assume it is a
	 * multiboot kernel.
	 */
	if (row[0] != 0 && row[0][0] != '\0') {
		info->type = BIBOOTWHAT_TYPE_MB;
		info->what.mb.tftp_ip.s_addr = 0;
107
108
109
110
111
		strncpy(info->what.mb.filename, row[0], MAX_BOOT_PATH-1);
		if (row[1] != 0 && row[1][0] != '\0')
			strncpy(info->cmdline, row[1], MAX_BOOT_CMDLINE-1);
		else
			info->cmdline[0] = 0;	/* Must zero first byte! */
Mike Hibler's avatar
Mike Hibler committed
112
113
114
115
116
117
118
		mysql_free_result(res);
		return 0;
	}
#endif

	/* Fifth element (row[4]) should have the partition number */
	if (row[4] == 0 || row[4][0] == '\0') {
119
		syslog(LOG_ERR, "%s: null query result for IP %s!",
120
121
122
123
124
125
126
127
128
			dbname, inet_ntoa(ipaddr));
		mysql_free_result(res);
		return 1;
	}

	/*
	 * Just 45000 lines of code later, we have the 32 bits of info
	 * we wanted!
	 */
Mike Hibler's avatar
Mike Hibler committed
129
	part = atoi(row[4]);
130
131
132
133
	mysql_free_result(res);

	info->type = BIBOOTWHAT_TYPE_PART;
	info->what.partition = part;
134
135
136
137
138
	if (row[5] != 0 && row[5][0] != '\0')
		strncpy(info->cmdline, row[5], MAX_BOOT_CMDLINE-1);
	else
		info->cmdline[0] = 0;	/* Must zero first byte! */
	
139
140
141
142
143
144
145
146
147
148
	return 0;
}

int
close_bootinfo_db(void)
{
	return 0;
}

#ifdef TEST
149
150
151
152
153
154
155
156
157
158
159
160
161
#include <stdarg.h>

void
syslog(int prio, const char *msg, ...)
{
	va_list ap;

	va_start(ap, msg);
	vfprintf(stderr, msg, ap);
	va_end(ap);
	fprintf(stderr, "\n");
}

Mike Hibler's avatar
Mike Hibler committed
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
static void
print_bootwhat(boot_what_t *bootinfo)
{
	switch (bootinfo->type) {
	case BIBOOTWHAT_TYPE_PART:
		printf("boot from partition %d\n",
		       bootinfo->what.partition);
		break;
	case BIBOOTWHAT_TYPE_SYSID:
		printf("boot from partition with sysid %d\n",
		       bootinfo->what.sysid);
		break;
	case BIBOOTWHAT_TYPE_MB:
		printf("boot multiboot image %s:%s\n",
		       inet_ntoa(bootinfo->what.mb.tftp_ip),
		       bootinfo->what.mb.filename);
		break;
	}
180
181
182
	if (bootinfo->cmdline[0])
		printf("Command line %s\n", bootinfo->cmdline);
		
Mike Hibler's avatar
Mike Hibler committed
183
184
}

185
186
187
188
189
190
main(int argc, char **argv)
{
	struct in_addr ipaddr;
	boot_info_t boot_info;
	boot_what_t *boot_whatp = (boot_what_t *)&boot_info.data;

191
	open_bootinfo_db();
192
193
	while (--argc > 0) {
		if (inet_aton(*++argv, &ipaddr))
Mike Hibler's avatar
Mike Hibler committed
194
195
196
197
			if (query_bootinfo_db(ipaddr, boot_whatp) == 0) {
				printf("%s: ", *argv);
				print_bootwhat(boot_whatp);
			} else
198
				printf("%s: failed\n", *argv);
199
200
201
		else
			printf("bogus IP address `%s'\n", *argv);
	}
202
	close_bootinfo_db();
203
204
205
206
207
	exit(0);
}
#endif

#endif