Merge lp:~gandelman-a/ubuntu/precise/cobbler-enlist/868492 into lp:ubuntu/precise/cobbler-enlist

Proposed by Adam Gandelman
Status: Merged
Merge reported by: Dave Walker
Merged at revision: not available
Proposed branch: lp:~gandelman-a/ubuntu/precise/cobbler-enlist/868492
Merge into: lp:ubuntu/precise/cobbler-enlist
Diff against target: 441 lines (+238/-75)
4 files modified
cobbler-enlist.c (+32/-15)
cobbler-enlist.h (+168/-40)
cobbler-xmlrpc.h (+30/-20)
debian/changelog (+8/-0)
To merge this branch: bzr merge lp:~gandelman-a/ubuntu/precise/cobbler-enlist/868492
Reviewer Review Type Date Requested Status
Dave Walker (community) Approve
Review via email: mp+80642@code.launchpad.net

Description of the change

  Register all valid network interfaces when enlisting (LP: #868492)

  This converts enlister->netif to a linked-list (enlister->netifs). Each node
  of the LL is of struct netif, which contains an interface name and macaddr.

  Any number of interfaces can be supplied via the command line. Each interface
  is appended to the link list as a struct netif with the macaddr left NULL.

  If no interfaces are supplied via argv, the list is populated with every
  interface on the system (the macaddr for each left NULL).

  What is contained in the enlister->netifs list is then verified. In the event
  a non-existent interface was supplied via argv, it is removed from the list.
  If enlister->netifs is empty (ie, none of the interfaces supplied actually
  exist), die.

  Nodes remaining in enlister->netifs get their mac addr's populated via ioctl.
  Non-standard devices (ie, bridges not backed by any device) may contain a bad
  mac addr, these are skipped. After populating, error out if the list does not
  contain at least one valid mac address.

  During system registration, loop over enlister->netifs and register each device.

  On the cobbler side, the system ends up with something like:

  # cobbler system dumpvars --name=testnode | grep mac_address_
  mac_address_eth0 : 90:e6:ba:54:93:b9
  mac_address_eth1 : 00:04:5a:5e:62:5f
  mac_address_virbr1 : 52:54:00:c2:5d:94
  mac_address_vnet0 : fe:16:3e:3e:a9:1a
  mac_address_vnet1 : fe:54:00:4d:7e:a0

  Cobbler will serve the profile via netboot to any of the interfaces.

To post a comment you must log in.
Revision history for this message
C de-Avillez (hggdh2) wrote :

We should keep an option to select specific interfaces, both on install and run-time. There are environments where strict separation of interface usage is enforced, and selecting all interfaces will trigger an audit finding.

Revision history for this message
Dave Walker (davewalker) wrote :

@Carlos, If i read the comment correctly.. It should default to sending all mac addresses, but support comma separated list of interfaces it should use. This should also work via preseed (the real target), but I am concerned how this will work with cobbler generic preseeds (as it was my intention to ship default of register all interfaces)

thoughts?

Revision history for this message
Adam Gandelman (gandelman-a) wrote :

To be clear, the default behavior after this patch is to register ALL valid interfaces+mac addrs on the system. If one or multiple interfaces is specified on the command line, those (and only those) interfaces+macaddrs will be registered.

It seems we're still determining how best to gather system information and post back. This change set provides the necessary internals to register multiple NICs + mac addrs, which is something that will be desired regardless of how decide to gather them. I predict we'll move from obtaining mac addrs via ioctl() to parsing it outside of cobbler-enlist. While the front end argv handling will likely change over time, the internal enlister->netifs changes here (which is the bulk of the patch) should meet our needs regardless.

9. By Adam Gandelman

Fix malloc() casting and memory initialization

Revision history for this message
C de-Avillez (hggdh2) wrote :

@Daviey: A generic cobbler preseed could (and should, I think) default to all interfaces; those that need to enforce separation of usage can then adjust the preseed(s) as needed (I believe this is possible ;-). I would also expect that these customers would probably restrict to one, at most two interfaces.

Hum. We do not support, anymore, d-i selection of interfaces?

10. By Adam Gandelman

Add support for multiple network interfaces (convert enlister->netif
to linked list enlister->netifs). When no interfaces specified, defaults
to registering all interfaces on the system. (LP: #868492)

11. By Adam Gandelman

Merge trunk

Revision history for this message
Dave Walker (davewalker) wrote :

Changed the pocket and version, and uploaded

Thanks.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'cobbler-enlist.c'
--- cobbler-enlist.c 2011-08-02 15:49:55 +0000
+++ cobbler-enlist.c 2011-11-21 19:59:24 +0000
@@ -48,13 +48,14 @@
48main (int const argc, char **argv)48main (int const argc, char **argv)
49{49{
50 int rc;50 int rc;
51
52 struct cobbler_client *enlister;51 struct cobbler_client *enlister;
53 enlister = (struct cobbler_client *) malloc(sizeof(struct cobbler_client));52 enlister = (struct cobbler_client *) malloc(sizeof(struct cobbler_client));
53 if (enlister == NULL)
54 die("malloc() failed for enlister- main()");
55 memset(enlister, 0, sizeof(struct cobbler_client));
54 init_client(enlister);56 init_client(enlister);
55 int c;57 int c;
5658
57 //int this_option_optind = optind ? optind : 1;
58 int option_index = 0;59 int option_index = 0;
5960
60 const char* const short_options = "hds:u:p:n:P:i:m:";61 const char* const short_options = "hds:u:p:n:P:i:m:";
@@ -67,7 +68,6 @@
67 {"netif", 1, 0, 'i'},68 {"netif", 1, 0, 'i'},
68 {"manclass", 1, 0, 'm'},69 {"manclass", 1, 0, 'm'},
69 {"help", 0, 0, 'h'},70 {"help", 0, 0, 'h'},
70 //{"default-interface", 1, 0, 0},
71 {0, 0, 0, 0}71 {0, 0, 0, 0}
72 };72 };
7373
@@ -111,9 +111,8 @@
111 break;111 break;
112112
113 case 'i':113 case 'i':
114 enlister->netif = optarg;114 append_netif(enlister, optarg);
115 break;115 break;
116
117 case 'm':116 case 'm':
118 enlister->mgmt_class = optarg;117 enlister->mgmt_class = optarg;
119 break;118 break;
@@ -145,16 +144,30 @@
145 (enlister->name == NULL) ||144 (enlister->name == NULL) ||
146 (enlister->profile == NULL))145 (enlister->profile == NULL))
147 {146 {
148 fprintf(stderr, "[%s] ERROR: not all required parameters were passed\n", argv[0]);
149 help(argv[0]);147 help(argv[0]);
150 exit (1);148 die("Not all required parameters were passed");
151 }149 }
152150
153151 /* if no interfaces were specified on command line, add all interfaces on
154 if ((rc = get_mac_address(enlister)) != 0) {152 the system */
155 printf("ERROR: Could not determine mac address for any interface on system.\n");153 if (!enlister->netifs) {
156 exit(1);154 if (debug)
157 }155 printf("[DEBUG] Populating netifs list with all interfaces on system.\n");
156 struct if_nameindex *ifs = if_nameindex();
157 while (ifs && ifs->if_name) {
158 if (strcasecmp(ifs->if_name, "lo") != 0)
159 append_netif(enlister, ifs->if_name);
160 ifs++;
161 }
162 }
163
164 /* ensure list isn't empty and all interfaces exist */
165 if (verify_netifs(enlister) != 0)
166 die("Could not verify any of specified interfaces");
167
168 /* get mac addresses for interfaces contained in enlister->netifs */
169 if (get_mac_addresses(enlister) != 0)
170 die("Could not determine mac address for any interface on system.");
158171
159 if (debug)172 if (debug)
160 display_config(enlister);173 display_config(enlister);
@@ -162,12 +175,16 @@
162 /* Initialize our error-handling environment. */175 /* Initialize our error-handling environment. */
163 if ((rc = init_xmlrpc_env(enlister)) != 0)176 if ((rc = init_xmlrpc_env(enlister)) != 0)
164 goto out;177 goto out;
178 /* Initialize the client */
165 if ((rc = init_xmlrpc_client(enlister)) != 0)179 if ((rc = init_xmlrpc_client(enlister)) != 0)
166 goto out;180 goto out;
181 /* Login to cobbler */
167 if ((rc = cobbler_login(enlister)) != 0)182 if ((rc = cobbler_login(enlister)) != 0)
168 goto out;183 goto out;
169 if ((rc = cobbler_register_system(enlister)) != 0)184 /* Register new system with everything contained in the enlister */
185 if ((rc = cobbler_register_system(enlister)) != 0)
170 goto out;186 goto out;
187 /* Save the system */
171 if ((rc = cobbler_save_system(enlister)) != 0)188 if ((rc = cobbler_save_system(enlister)) != 0)
172 goto out;189 goto out;
173190
174191
=== modified file 'cobbler-enlist.h'
--- cobbler-enlist.h 2011-09-28 00:43:36 +0000
+++ cobbler-enlist.h 2011-11-21 19:59:24 +0000
@@ -38,6 +38,8 @@
38#define OPT_NETIF 538#define OPT_NETIF 5
39#define OPT_HELP 639#define OPT_HELP 6
4040
41#define NO_MACADDR "00:00:00:00:00:00"
42
41static int debug = 0;43static int debug = 0;
4244
43struct cobbler_client {45struct cobbler_client {
@@ -54,7 +56,16 @@
54 const char *netif;56 const char *netif;
55 const char *mgmt_class;57 const char *mgmt_class;
56 const char *macaddr;58 const char *macaddr;
57};59 struct netif *netifs;
60};
61
62struct netif {
63 const char *interface;
64 const char *macaddr;
65 struct netif *next;
66};
67
68void get_netifs(struct cobbler_client *enlister);
5869
59int init_client(struct cobbler_client *enlister) {70int init_client(struct cobbler_client *enlister) {
60 enlister->client = NULL;71 enlister->client = NULL;
@@ -68,6 +79,7 @@
68 enlister->netif = NULL;79 enlister->netif = NULL;
69 enlister->mgmt_class = NULL;80 enlister->mgmt_class = NULL;
70 enlister->macaddr = NULL;81 enlister->macaddr = NULL;
82 enlister->netifs = NULL;
71 return 0;83 return 0;
72}84}
7385
@@ -78,11 +90,80 @@
78 printf("\tpassword: %s\n", enlister->password);90 printf("\tpassword: %s\n", enlister->password);
79 printf("\tname: %s\n", enlister->name);91 printf("\tname: %s\n", enlister->name);
80 printf("\tprofile: %s\n", enlister->profile);92 printf("\tprofile: %s\n", enlister->profile);
81 if (enlister->netif)93 if (enlister->netifs) {
82 printf("\tnetif: %s\n", enlister->netif);94 get_netifs(enlister);
95 }
83 if (enlister->mgmt_class)96 if (enlister->mgmt_class)
84 printf("\tmgmt class: %s\n", enlister->mgmt_class);97 printf("\tmgmt class: %s\n", enlister->mgmt_class);
85 printf("\tmac addr: %s\n", enlister->macaddr);98}
99
100void get_netifs(struct cobbler_client *enlister) {
101 struct netif *current = enlister->netifs;
102 if (current == NULL) {
103 printf("Interface list is empty\n");
104 return;
105 }
106 int i = 0;
107 while (current != NULL) {
108 printf("\tinterface %d: %s - %s\n", i, current->interface, current->macaddr);
109 i++;
110 current = current->next;
111 }
112}
113
114void die(char *msg) {
115 fprintf(stderr, "[ERROR] %s\n", msg);
116 exit(1);
117}
118
119/* append a new interface to the netifs list. macaddr remains empty
120 until populated by get_macaddresses() */
121int append_netif(struct cobbler_client *enlister, char *netif) {
122 if (debug)
123 printf("[DEBUG] Appending interface %s to enlister's netif list\n", netif);
124 struct netif *new_netif, *current;
125 new_netif = (struct netif *) malloc(sizeof(struct netif));
126 if (new_netif == NULL)
127 die("malloc() - append_netif()");
128 memset(new_netif, 0, sizeof(struct netif));
129 new_netif->interface = netif;
130 new_netif->macaddr = NULL;
131 new_netif->next = NULL;
132 if (enlister->netifs == NULL) {
133 enlister->netifs = new_netif;
134 return 0;
135 }
136 int i;
137 current = enlister->netifs;
138 while (current->next != NULL) {
139 current = current->next;
140 i++;
141 }
142 current->next = new_netif;
143 return 0;
144}
145
146/* delete an interface from the netifs list */
147int remove_netif(struct cobbler_client *enlister, const char *interface) {
148 if (debug)
149 printf("[DEBUG] Removing from interface list: %s\n", interface);
150 struct netif *current = enlister->netifs;
151 int i = 0;
152 if (strcasecmp(current->interface, interface) == 0) {
153 enlister->netifs = current->next;
154 return 0;
155 }
156 i++;
157 while (current->next) {
158 if (strcasecmp(current->next->interface, interface) == 0) {
159 current->next = current->next->next;
160 return 0;
161 }
162 current = current->next;
163 i++;
164 }
165 printf("ERROR: NEtif: %s doesn't exist in enlister->netifs\n", interface);
166 return 1;
86}167}
87168
88// Overide ether_ntoa_r because stock decides the convention of leading zeros is silly.169// Overide ether_ntoa_r because stock decides the convention of leading zeros is silly.
@@ -96,46 +177,93 @@
96 return buf;177 return buf;
97}178}
98179
99int get_mac_address(struct cobbler_client *enlister) {180int interface_exists(const char *interface) {
100 if (debug)181 if (debug)
101 printf("[DEBUG] get_mac_address()\n");182 printf("[DEBUG] Checking for interface: %s\n", interface);
102183 struct if_nameindex *curif, *ifs = if_nameindex();
103 int fd;184 for (curif = ifs; curif && curif->if_name; curif++) {
104 struct if_nameindex *curif, *ifs;185 if (strcasecmp(interface, curif->if_name) == 0)
105 char mac_str[25];186 return 0;
106 char interface[255];187 }
107 char *macaddr = malloc(sizeof(mac_str));188 return 1;
108189}
190
191/* inspect each enlister->netifs. Make sure the interface exists on the system
192 Remove it from the list if it doesn't.
193 If we've cleaned the entire list because none of them exist, return 1.
194 Can/should be extended to do more verification?
195*/
196int verify_netifs(struct cobbler_client *enlister) {
197 struct netif *current = enlister->netifs;
198 while (current) {
199 if (interface_exists(current->interface) != 0) {
200 printf("[WARNING] Interface %s doesn't exist, removing.\n", current->interface);
201 remove_netif(enlister, current->interface);
202 }
203 current = current->next;
204 }
205 if (enlister->netifs == NULL)
206 return 1;
207 return 0;
208}
209
210/* utility function to test whether the netifs list contains at least
211 one mac address
212*/
213int contains_one_macaddr(struct cobbler_client *enlister) {
214 struct netif *current = enlister->netifs;
215 while (current) {
216 if ((current->macaddr != NULL) &&
217 (strcasecmp(current->macaddr, NO_MACADDR) != 0)) {
218 return 0;
219 }
220 }
221 return 1;
222}
223
224char *get_interface_macaddr(const char *interface) {
225 if (debug)
226 printf("[DEBUG] Getting mac addr for interface %s\n", interface);
227 char mac_str[255];
228 char *macaddr;
109 int ioctl_data = 0;229 int ioctl_data = 0;
110 struct ifreq ifr;230 struct ifreq ifr;
111231 ioctl_data = socket(PF_INET, SOCK_STREAM, 0);
112 if ((fd = socket (PF_INET, SOCK_DGRAM, 0)) != -1) {232 memset(&ifr, 0, sizeof(ifr));
113 ifs = if_nameindex ();233 strncpy(ifr.ifr_name, interface, sizeof(interface));
114 for (curif = ifs; curif && curif->if_name; curif++) {234 ioctl(ioctl_data, SIOCGIFHWADDR, &ifr);
115 if (((enlister->netif == NULL) ||235 ether_ntoa_r((const struct ether_addr *) &(ifr.ifr_hwaddr.sa_data), mac_str);
116 (strcasecmp(enlister->netif, curif->if_name) == 0))236 macaddr = malloc(sizeof(mac_str));
117 && (strcasecmp(curif->if_name, "lo") !=0)) {237 if (macaddr == NULL)
118238 die("malloc() - get_interface_macaddr()");
119 ioctl_data = socket (PF_INET, SOCK_STREAM, 0);239 strncpy(macaddr, mac_str, sizeof(mac_str));
120 memset (&ifr, 0, sizeof (ifr));240 return macaddr;
121 strncpy (ifr.ifr_name, curif->if_name, sizeof (ifr.ifr_name));241}
122 strncpy (interface, curif->if_name, sizeof (interface));242
123 ioctl (ioctl_data, SIOCGIFHWADDR, &ifr);243/* iterate through enlister->netifs, populating macaddr for each.
124 ether_ntoa_r( (const struct ether_addr *)244 if we can't determine a valid mac addr, remove from list and continue
125 &(ifr.ifr_hwaddr.sa_data), mac_str);245 returns non-zero if the resulting enlister->netifs does not contain at least
126 if (debug)246 one mac addr.
127 printf("[DEBUG] Using interface: %s Addr: %s\n", interface, mac_str);247*/
128 if (enlister->netif == NULL)248int get_mac_addresses(struct cobbler_client *enlister) {
129 enlister->netif = curif->if_name;249 if (debug)
130 strncpy(macaddr, mac_str, sizeof(mac_str));250 printf("[DEBUG] get_mac_address()\n");
131 enlister->macaddr = macaddr;251 const char *addr;
132 return 0;252 struct netif *current = enlister->netifs;
133 }253 while (current != NULL) {
134 }254 addr = get_interface_macaddr(current->interface);
255 if (strcasecmp(addr, NO_MACADDR) == 0) {
256 printf("[WARNING] Could not determine mac addr for %s, skipping.\n",
257 current->interface);
258 remove_netif(enlister, current->interface);
259 } else {
260 current->macaddr = addr;
261 };
262 current = current->next;
135 }263 }
264 return contains_one_macaddr(enlister);
265}
136266
137 return 1;
138}
139void help(char *progname)267void help(char *progname)
140{268{
141 printf("Usage: %s --help -- provides this help\n" , progname);269 printf("Usage: %s --help -- provides this help\n" , progname);
142270
=== modified file 'cobbler-xmlrpc.h'
--- cobbler-xmlrpc.h 2011-08-02 15:49:55 +0000
+++ cobbler-xmlrpc.h 2011-11-21 19:59:24 +0000
@@ -109,7 +109,7 @@
109 xmlrpc_value *token = xmlrpc_string_new(&enlister->env, enlister->token);109 xmlrpc_value *token = xmlrpc_string_new(&enlister->env, enlister->token);
110 xmlrpc_value *name = xmlrpc_string_new(&enlister->env, enlister->name);110 xmlrpc_value *name = xmlrpc_string_new(&enlister->env, enlister->name);
111 xmlrpc_value *profile = xmlrpc_string_new(&enlister->env, enlister->profile);111 xmlrpc_value *profile = xmlrpc_string_new(&enlister->env, enlister->profile);
112 xmlrpc_value *macaddr = xmlrpc_string_new(&enlister->env, enlister->macaddr);112// xmlrpc_value *macaddr = xmlrpc_string_new(&enlister->env, enlister->macaddr);
113113
114 /* used for forming modify_interface request */114 /* used for forming modify_interface request */
115 xmlrpc_value *macaddr_struct = xmlrpc_struct_new(&enlister->env);115 xmlrpc_value *macaddr_struct = xmlrpc_struct_new(&enlister->env);
@@ -162,23 +162,35 @@
162 if ((rc = make_xmlrpc_call(enlister, "modify_system", argument_array)) != 0)162 if ((rc = make_xmlrpc_call(enlister, "modify_system", argument_array)) != 0)
163 goto out;163 goto out;
164 if (debug)164 if (debug)
165 printf("[DEBUG] Modified system profile: %d\n", rc);165 printf("[DEBUG] Modified system profile: %d\n", rc);
166166
167 /* set its mac address */167 /* set its mac addresses */
168 sprintf(macaddr_form_item, "macaddress-%s", enlister->netif);168 struct netif *current_netif = enlister->netifs;
169 xmlrpc_struct_set_value(&enlister->env, macaddr_struct,169 while (current_netif != NULL) {
170 macaddr_form_item, macaddr);170 if (debug) {
171 argument_array = xmlrpc_array_new(&enlister->env);171 printf("[DEBUG] Registering interface and macaddr: %s %s\n",
172 xmlrpc_array_append_item(&enlister->env, argument_array, system);172 current_netif->interface, current_netif->macaddr);
173 xmlrpc_array_append_item(&enlister->env, argument_array,173 }
174 xmlrpc_string_new(&enlister->env, "modify_interface"));174 xmlrpc_value *macaddr = xmlrpc_string_new(&enlister->env,
175 xmlrpc_array_append_item(&enlister->env, argument_array, macaddr_struct);175 current_netif->macaddr);
176 xmlrpc_array_append_item(&enlister->env, argument_array, token);176 sprintf(macaddr_form_item, "macaddress-%s", current_netif->interface);
177 if ((rc = make_xmlrpc_call(enlister, "modify_system", argument_array)) != 0)177 xmlrpc_struct_set_value(&enlister->env, macaddr_struct,
178 goto out;178 macaddr_form_item, macaddr);
179 if (debug)179 argument_array = xmlrpc_array_new(&enlister->env);
180 printf("[DEBUG] Modified interface: %d\n", rc);180 xmlrpc_array_append_item(&enlister->env, argument_array, system);
181181 xmlrpc_array_append_item(&enlister->env, argument_array,
182 xmlrpc_string_new(&enlister->env, "modify_interface"));
183 xmlrpc_array_append_item(&enlister->env, argument_array, macaddr_struct);
184 xmlrpc_array_append_item(&enlister->env, argument_array, token);
185 if ((rc = make_xmlrpc_call(enlister, "modify_system", argument_array)) != 0) {
186 xmlrpc_DECREF(macaddr);
187 xmlrpc_DECREF(macaddr_struct);
188 goto out;
189 }
190 if (debug)
191 printf("[DEBUG] Modified interface: %d\n", rc);
192 current_netif = current_netif->next;
193 }
182 /* assign a mgmt class */194 /* assign a mgmt class */
183 if (enlister->mgmt_class) {195 if (enlister->mgmt_class) {
184 xmlrpc_value *mgmt_class = xmlrpc_string_new(&enlister->env,196 xmlrpc_value *mgmt_class = xmlrpc_string_new(&enlister->env,
@@ -202,8 +214,6 @@
202 xmlrpc_DECREF(name);214 xmlrpc_DECREF(name);
203 xmlrpc_DECREF(profile);215 xmlrpc_DECREF(profile);
204 xmlrpc_DECREF(system);216 xmlrpc_DECREF(system);
205 xmlrpc_DECREF(macaddr);
206 xmlrpc_DECREF(macaddr_struct);
207 xmlrpc_DECREF(argument_array);217 xmlrpc_DECREF(argument_array);
208 return rc;218 return rc;
209}219}
210220
=== modified file 'debian/changelog'
--- debian/changelog 2011-11-12 11:07:07 +0000
+++ debian/changelog 2011-11-21 19:59:24 +0000
@@ -1,3 +1,11 @@
1cobbler-enlist (0.2-1ubuntu1) oneiric; urgency=low
2
3 * Add support for multiple network interfaces (convert enlister->netif
4 to linked list enlister->netifs). When no interfaces specified, defaults
5 to registering all interfaces on the system. (LP: #868492)
6
7 -- Adam Gandelman <adamg@canonical.com> Mon, 21 Nov 2011 11:40:37 -0800
8
1cobbler-enlist (0.2-1build2) precise; urgency=low9cobbler-enlist (0.2-1build2) precise; urgency=low
210
3 * Rebuild for libxmlrpc-core-c3-udeb.11 * Rebuild for libxmlrpc-core-c3-udeb.

Subscribers

People subscribed via source and target branches