186593ff2dedad74535fc058ad0ee9b5c6dd0fe3
[racktables-incomplete-works] / wwwroot / inc / ophandlers.php
1 <?php
2
3 # This file is a part of RackTables, a datacenter and server room management
4 # framework. See accompanying file "COPYING" for the full copyright and
5 # licensing information.
6
7 /*
8
9 "Ophandler" in RackTables stands for "operation handler", or a function
10 that handles execution of "operation" (in the meaning explained in
11 navigation.php). Most of the ophandlers are meant to perform one specific
12 action, for example, to set a name of an object. Each such action often
13 requires a set of parameters (e. g. ID of the object and the new name),
14 and it is responsibility of each ophandler function to verify, that all
15 necessary parameters are provided by the user and have proper values. There
16 is a number of helper functions to make such verification simpler.
17
18 Errors occuring in ophandlers are typically indicated with exceptions of
19 assorted classes. Namely, an "InvalidRequestArgException" class means, that
20 at least one of the parameters provided by the user is not acceptable. This
21 is a "soft" error, which gets displayed in the standard message area of
22 otherwise usual interface. A different case is "InvalidArgException", which
23 means that one of the internal functions detected its argument(s) invalid
24 or corrupted, and that argument(s) did not come from user's input (and thus
25 cannot be fixed without fixing a bug in the code). Such "hard" errors don't
26 get special early handling and end up in the default catching block. The
27 latter may print a detailed stack trace instead of the interface HTML to
28 help a developer debug the issue.
29
30 As long as an ophandler makes through its request (extracting arguments,
31 performing validation and actually updating records in the database), it
32 may queue up messages (often referred to as "green" and "red" bars) by
33 means of showError() and showSuccess() functions. The messages are not
34 displayed immediately, because successfull ophandlers are expected to
35 return only the new URL, where the user will be immediately redirected to
36 (it is also possible to return an empty string to mean, that the current
37 logical location remains the same). The page at the "next" location is
38 supposed to translate message buffer into the standard message area.
39
40 A very special case of an ophandler is tableHandler(). This generic
41 function handles the most trivial actions, which map to a single INSERT,
42 UPDATE or DELETE SQL statement with a fixed number of arguments. The rules
43 of argument validation and mapping are listed in $opspec_list (operation
44 specifications list) array.
45
46 */
47
48 // This array is deprecated. Please do not add new message constants to it.
49 // use the new showError, showWarning, showSuccess functions instead
50 global $msgcode;
51 $msgcode = array();
52
53 global $opspec_list;
54 $opspec_list = array();
55
56 $opspec_list['object-edit-unlinkObjects'] = array
57 (
58 'table' => 'EntityLink',
59 'action' => 'DELETE',
60 'arglist' => array
61 (
62 array ('url_argname' => 'link_id', 'table_colname' => 'id', 'assertion' => 'uint'),
63 ),
64 );
65 $opspec_list['object-ports-useup'] = array
66 (
67 'table' => 'Port',
68 'action' => 'UPDATE',
69 'set_arglist' => array
70 (
71 array ('fix_argname' => 'reservation_comment', 'fix_argvalue' => NULL),
72 ),
73 'where_arglist' => array
74 (
75 array ('url_argname' => 'port_id', 'table_colname' => 'id', 'assertion' => 'uint'),
76 array ('url_argname' => 'object_id', 'assertion' => 'uint'), # preserve context
77 ),
78 );
79 $opspec_list['object-ports-delPort'] = array
80 (
81 'table' => 'Port',
82 'action' => 'DELETE',
83 'arglist' => array
84 (
85 array ('url_argname' => 'port_id', 'table_colname' => 'id', 'assertion' => 'uint'),
86 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
87 ),
88 );
89 $opspec_list['object-ports-deleteAll'] = array
90 (
91 'table' => 'Port',
92 'action' => 'DELETE',
93 'arglist' => array
94 (
95 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
96 ),
97 );
98 $opspec_list['location-log-del'] = array
99 (
100 'table' => 'ObjectLog',
101 'action' => 'DELETE',
102 'arglist' => array
103 (
104 array ('url_argname' => 'log_id', 'table_colname' => 'id', 'assertion' => 'uint'),
105 array ('url_argname' => 'location_id', 'table_colname' => 'object_id', 'assertion' => 'uint'),
106 ),
107 );
108 $opspec_list['object-log-del'] = array
109 (
110 'table' => 'ObjectLog',
111 'action' => 'DELETE',
112 'arglist' => array
113 (
114 array ('url_argname' => 'log_id', 'table_colname' => 'id', 'assertion' => 'uint'),
115 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
116 ),
117 );
118 $opspec_list['rack-log-del'] = array
119 (
120 'table' => 'ObjectLog',
121 'action' => 'DELETE',
122 'arglist' => array
123 (
124 array ('url_argname' => 'log_id', 'table_colname' => 'id', 'assertion' => 'uint'),
125 array ('url_argname' => 'rack_id', 'table_colname' => 'object_id', 'assertion' => 'uint'),
126 ),
127 );
128 $opspec_list['ipv4vs-editlblist-delLB'] =
129 $opspec_list['ipv4rspool-editlblist-delLB'] =
130 $opspec_list['object-editrspvs-delLB'] = array
131 (
132 'table' => 'IPv4LB',
133 'action' => 'DELETE',
134 'arglist' => array
135 (
136 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
137 array ('url_argname' => 'pool_id', 'table_colname' => 'rspool_id', 'assertion' => 'uint'),
138 array ('url_argname' => 'vs_id', 'assertion' => 'uint'),
139 ),
140 );
141 $opspec_list['ipv4vs-editlblist-updLB'] =
142 $opspec_list['ipv4rspool-editlblist-updLB'] =
143 $opspec_list['object-editrspvs-updLB'] = array
144 (
145 'table' => 'IPv4LB',
146 'action' => 'UPDATE',
147 'set_arglist' => array
148 (
149 array ('url_argname' => 'vsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
150 array ('url_argname' => 'rsconfig', 'assertion' => 'string0', 'if_empty' => 'NULL'),
151 array ('url_argname' => 'prio', 'assertion' => 'string0', 'if_empty' => 'NULL'),
152 ),
153 'where_arglist' => array
154 (
155 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
156 array ('url_argname' => 'pool_id', 'table_colname' => 'rspool_id', 'assertion' => 'uint'),
157 array ('url_argname' => 'vs_id', 'assertion' => 'uint'),
158 ),
159 );
160 $opspec_list['object-cacti-add'] = array
161 (
162 'table' => 'CactiGraph',
163 'action' => 'INSERT',
164 'arglist' => array
165 (
166 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
167 array ('url_argname' => 'server_id', 'assertion' => 'uint'),
168 array ('url_argname' => 'graph_id', 'assertion' => 'uint'),
169 array ('url_argname' => 'caption', 'assertion' => 'string0'),
170 ),
171 );
172 $opspec_list['object-cacti-del'] = array
173 (
174 'table' => 'CactiGraph',
175 'action' => 'DELETE',
176 'arglist' => array
177 (
178 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
179 array ('url_argname' => 'server_id', 'assertion' => 'uint'),
180 array ('url_argname' => 'graph_id', 'assertion' => 'uint'),
181 ),
182 );
183 $opspec_list['object-munin-add'] = array
184 (
185 'table' => 'MuninGraph',
186 'action' => 'INSERT',
187 'arglist' => array
188 (
189 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
190 array ('url_argname' => 'server_id', 'assertion' => 'uint'),
191 array ('url_argname' => 'graph', 'assertion' => 'string'),
192 array ('url_argname' => 'caption', 'assertion' => 'string0'),
193 ),
194 );
195 $opspec_list['object-munin-del'] = array
196 (
197 'table' => 'MuninGraph',
198 'action' => 'DELETE',
199 'arglist' => array
200 (
201 array ('url_argname' => 'object_id', 'assertion' => 'uint'),
202 array ('url_argname' => 'server_id', 'assertion' => 'uint'),
203 array ('url_argname' => 'graph', 'assertion' => 'string'),
204 ),
205 );
206 $opspec_list['ipv4rspool-editrslist-delRS'] = array
207 (
208 'table' => 'IPv4RS',
209 'action' => 'DELETE',
210 'arglist' => array
211 (
212 array ('url_argname' => 'id', 'assertion' => 'uint'),
213 ),
214 );
215 $opspec_list['parentmap-edit-add'] = array
216 (
217 'table' => 'ObjectParentCompat',
218 'action' => 'INSERT',
219 'arglist' => array
220 (
221 array ('url_argname' => 'parent_objtype_id', 'assertion' => 'uint'),
222 array ('url_argname' => 'child_objtype_id', 'assertion' => 'uint'),
223 ),
224 );
225 $opspec_list['parentmap-edit-del'] = array
226 (
227 'table' => 'ObjectParentCompat',
228 'action' => 'DELETE',
229 'arglist' => array
230 (
231 array ('url_argname' => 'parent_objtype_id', 'assertion' => 'uint'),
232 array ('url_argname' => 'child_objtype_id', 'assertion' => 'uint'),
233 ),
234 );
235 $opspec_list['portmap-edit-add'] = array
236 (
237 'table' => 'PortCompat',
238 'action' => 'INSERT',
239 'arglist' => array
240 (
241 array ('url_argname' => 'type1', 'assertion' => 'uint'),
242 array ('url_argname' => 'type2', 'assertion' => 'uint'),
243 ),
244 );
245 $opspec_list['portmap-edit-del'] = array
246 (
247 'table' => 'PortCompat',
248 'action' => 'DELETE',
249 'arglist' => array
250 (
251 array ('url_argname' => 'type1', 'assertion' => 'uint'),
252 array ('url_argname' => 'type2', 'assertion' => 'uint'),
253 ),
254 );
255 $opspec_list['portifcompat-edit-add'] = array
256 (
257 'table' => 'PortInterfaceCompat',
258 'action' => 'INSERT',
259 'arglist' => array
260 (
261 array ('url_argname' => 'iif_id', 'assertion' => 'uint'),
262 array ('url_argname' => 'oif_id', 'assertion' => 'uint'),
263 ),
264 );
265 $opspec_list['portifcompat-edit-del'] = array
266 (
267 'table' => 'PortInterfaceCompat',
268 'action' => 'DELETE',
269 'arglist' => array
270 (
271 array ('url_argname' => 'iif_id', 'assertion' => 'uint'),
272 array ('url_argname' => 'oif_id', 'assertion' => 'uint'),
273 ),
274 );
275 $opspec_list['portoifs-edit-add'] = array
276 (
277 'table' => 'PortOuterInterface',
278 'action' => 'INSERT',
279 'arglist' => array
280 (
281 array ('url_argname' => 'oif_name', 'assertion' => 'string'),
282 ),
283 );
284 $opspec_list['portoifs-edit-del'] = array
285 (
286 'table' => 'PortOuterInterface',
287 'action' => 'DELETE',
288 'arglist' => array
289 (
290 array ('url_argname' => 'id', 'assertion' => 'uint'),
291 ),
292 );
293 $opspec_list['portoifs-edit-upd'] = array
294 (
295 'table' => 'PortOuterInterface',
296 'action' => 'UPDATE',
297 'set_arglist' => array
298 (
299 array ('url_argname' => 'oif_name', 'assertion' => 'string'),
300 ),
301 'where_arglist' => array
302 (
303 array ('url_argname' => 'id', 'assertion' => 'uint'),
304 ),
305 );
306 $opspec_list['attrs-editmap-del'] = array
307 (
308 'table' => 'AttributeMap',
309 'action' => 'DELETE',
310 'arglist' => array
311 (
312 array ('url_argname' => 'attr_id', 'assertion' => 'uint'),
313 array ('url_argname' => 'objtype_id', 'assertion' => 'uint'),
314 ),
315 );
316 $opspec_list['attrs-editattrs-add'] = array
317 (
318 'table' => 'Attribute',
319 'action' => 'INSERT',
320 'arglist' => array
321 (
322 array ('url_argname' => 'attr_type', 'table_colname' => 'type', 'assertion' => 'enum/attr_type'),
323 array ('url_argname' => 'attr_name', 'table_colname' => 'name', 'assertion' => 'string'),
324 ),
325 );
326 $opspec_list['attrs-editattrs-del'] = array
327 (
328 'table' => 'Attribute',
329 'action' => 'DELETE',
330 'arglist' => array
331 (
332 array ('url_argname' => 'attr_id', 'table_colname' => 'id', 'assertion' => 'uint'),
333 ),
334 );
335 $opspec_list['attrs-editattrs-upd'] = array
336 (
337 'table' => 'Attribute',
338 'action' => 'UPDATE',
339 'set_arglist' => array
340 (
341 array ('url_argname' => 'attr_name', 'table_colname' => 'name', 'assertion' => 'string'),
342 ),
343 'where_arglist' => array
344 (
345 array ('url_argname' => 'attr_id', 'table_colname' => 'id', 'assertion' => 'uint'),
346 ),
347 );
348 $opspec_list['dict-chapters-add'] = array
349 (
350 'table' => 'Chapter',
351 'action' => 'INSERT',
352 'arglist' => array
353 (
354 array ('url_argname' => 'chapter_name', 'table_colname' => 'name', 'assertion' => 'string')
355 ),
356 );
357 $opspec_list['chapter-edit-add'] = array
358 (
359 'table' => 'Dictionary',
360 'action' => 'INSERT',
361 'arglist' => array
362 (
363 array ('url_argname' => 'chapter_no', 'table_colname' => 'chapter_id', 'assertion' => 'uint'),
364 array ('url_argname' => 'dict_value', 'assertion' => 'string'),
365 ),
366 );
367 $opspec_list['chapter-edit-del'] = array
368 (
369 'table' => 'Dictionary',
370 'action' => 'DELETE',
371 'arglist' => array
372 (
373 // Technically dict_key is enough to delete, but including chapter_id into
374 // WHERE clause makes sure, that the action actually happends for the same
375 // chapter that authorization was granted for.
376 array ('url_argname' => 'chapter_no', 'table_colname' => 'chapter_id', 'assertion' => 'uint'),
377 array ('url_argname' => 'dict_key', 'assertion' => 'uint'),
378 array ('fix_argname' => 'dict_sticky', 'fix_argvalue' => 'no'), # protect system rows
379 ),
380 );
381 $opspec_list['chapter-edit-upd'] = array
382 (
383 'table' => 'Dictionary',
384 'action' => 'UPDATE',
385 'set_arglist' => array
386 (
387 array ('url_argname' => 'dict_value', 'assertion' => 'string'),
388 ),
389 'where_arglist' => array
390 (
391 # same as above for listing chapter_no
392 array ('url_argname' => 'chapter_no', 'table_colname' => 'chapter_id', 'assertion' => 'uint'),
393 array ('url_argname' => 'dict_key', 'assertion' => 'uint'),
394 array ('fix_argname' => 'dict_sticky', 'fix_argvalue' => 'no'), # protect system rows
395 ),
396 );
397 $opspec_list['tagtree-edit-createTag'] = array
398 (
399 'table' => 'TagTree',
400 'action' => 'INSERT',
401 'arglist' => array
402 (
403 array ('url_argname' => 'tag_name', 'table_colname' => 'tag', 'assertion' => 'tag'),
404 array ('url_argname' => 'parent_id', 'assertion' => 'uint0', 'if_empty' => 'NULL'),
405 array ('url_argname' => 'is_assignable', 'assertion' => 'enum/yesno'),
406 ),
407 );
408 $opspec_list['tagtree-edit-destroyTag'] = array
409 (
410 'table' => 'TagTree',
411 'action' => 'DELETE',
412 'arglist' => array
413 (
414 array ('url_argname' => 'tag_id', 'table_colname' => 'id', 'assertion' => 'uint'),
415 ),
416 );
417 $opspec_list['8021q-vstlist-add'] = array
418 (
419 'table' => 'VLANSwitchTemplate',
420 'action' => 'INSERT',
421 'arglist' => array
422 (
423 array ('url_argname' => 'vst_descr', 'table_colname' => 'description', 'assertion' => 'string'),
424 ),
425 );
426 $opspec_list['8021q-vstlist-del'] = array
427 (
428 'table' => 'VLANSwitchTemplate',
429 'action' => 'DELETE',
430 'arglist' => array
431 (
432 array ('url_argname' => 'vst_id', 'table_colname' => 'id', 'assertion' => 'uint'),
433 ),
434 );
435 $opspec_list['8021q-vstlist-upd'] = array
436 (
437 'table' => 'VLANSwitchTemplate',
438 'action' => 'UPDATE',
439 'set_arglist' => array
440 (
441 array ('url_argname' => 'vst_descr', 'table_colname' => 'description', 'assertion' => 'string'),
442 ),
443 'where_arglist' => array
444 (
445 array ('url_argname' => 'vst_id', 'table_colname' => 'id', 'assertion' => 'uint'),
446 ),
447 );
448 $opspec_list['8021q-vdlist-del'] = array
449 (
450 'table' => 'VLANDomain',
451 'action' => 'DELETE',
452 'arglist' => array
453 (
454 array ('url_argname' => 'vdom_id', 'table_colname' => 'id', 'assertion' => 'uint'),
455 ),
456 );
457 $opspec_list['8021q-vdlist-upd'] = array
458 (
459 'table' => 'VLANDomain',
460 'action' => 'UPDATE',
461 'set_arglist' => array
462 (
463 array ('url_argname' => 'vdom_descr', 'table_colname' => 'description', 'assertion' => 'string'),
464 ),
465 'where_arglist' => array
466 (
467 array ('url_argname' => 'vdom_id', 'table_colname' => 'id', 'assertion' => 'uint'),
468 ),
469 );
470 $opspec_list['vlandomain-vlanlist-add'] = array
471 (
472 'table' => 'VLANDescription',
473 'action' => 'INSERT',
474 'arglist' => array
475 (
476 array ('url_argname' => 'vdom_id', 'table_colname' => 'domain_id', 'assertion' => 'uint'),
477 array ('url_argname' => 'vlan_id', 'assertion' => 'vlan'),
478 array ('url_argname' => 'vlan_type', 'assertion' => 'enum/vlan_type'),
479 array ('url_argname' => 'vlan_descr', 'assertion' => 'string0', 'if_empty' => 'NULL'),
480 ),
481 );
482 $opspec_list['vlandomain-vlanlist-del'] = array
483 (
484 'table' => 'VLANDescription',
485 'action' => 'DELETE',
486 'arglist' => array
487 (
488 array ('url_argname' => 'vdom_id', 'table_colname' => 'domain_id', 'assertion' => 'uint'),
489 array ('url_argname' => 'vlan_id', 'assertion' => 'vlan'),
490 ),
491 );
492 $opspec_list['vlan-edit-upd'] = // both locations are using the same tableHandler op
493 $opspec_list['vlandomain-vlanlist-upd'] = array
494 (
495 'table' => 'VLANDescription',
496 'action' => 'UPDATE',
497 'set_arglist' => array
498 (
499 array ('url_argname' => 'vlan_type', 'assertion' => 'enum/vlan_type'),
500 array ('url_argname' => 'vlan_descr', 'assertion' => 'string0', 'if_empty' => 'NULL'),
501 ),
502 'where_arglist' => array
503 (
504 array ('url_argname' => 'vdom_id', 'table_colname' => 'domain_id', 'assertion' => 'uint'),
505 array ('url_argname' => 'vlan_id', 'assertion' => 'vlan'),
506 ),
507 );
508 $opspec_list['dict-chapters-upd'] = array
509 (
510 'table' => 'Chapter',
511 'action' => 'UPDATE',
512 'set_arglist' => array
513 (
514 array ('url_argname' => 'chapter_name', 'table_colname' => 'name', 'assertion' => 'string'),
515 ),
516 'where_arglist' => array
517 (
518 array ('url_argname' => 'chapter_no', 'table_colname' => 'id', 'assertion' => 'uint'),
519 array ('fix_argname' => 'sticky', 'fix_argvalue' => 'no'), # protect system chapters
520 ),
521 );
522 $opspec_list['dict-chapters-del'] = array
523 (
524 'table' => 'Chapter',
525 'action' => 'DELETE',
526 'arglist' => array
527 (
528 array ('url_argname' => 'chapter_no', 'table_colname' => 'id', 'assertion' => 'uint'),
529 array ('fix_argname' => 'sticky', 'fix_argvalue' => 'no'), # protect system chapters
530 ),
531 );
532 $opspec_list['cacti-servers-add'] = array
533 (
534 'table' => 'CactiServer',
535 'action' => 'INSERT',
536 'arglist' => array
537 (
538 array ('url_argname' => 'base_url', 'assertion' => 'string'),
539 array ('url_argname' => 'username', 'assertion' => 'string0'),
540 array ('url_argname' => 'password', 'assertion' => 'string0'),
541 ),
542 );
543 $opspec_list['cacti-servers-del'] = array
544 (
545 'table' => 'CactiServer',
546 'action' => 'DELETE',
547 'arglist' => array
548 (
549 array ('url_argname' => 'id', 'assertion' => 'uint'),
550 ),
551 );
552 $opspec_list['cacti-servers-upd'] = array
553 (
554 'table' => 'CactiServer',
555 'action' => 'UPDATE',
556 'set_arglist' => array
557 (
558 array ('url_argname' => 'base_url', 'assertion' => 'string'),
559 array ('url_argname' => 'username', 'assertion' => 'string0'),
560 array ('url_argname' => 'password', 'assertion' => 'string0'),
561 ),
562 'where_arglist' => array
563 (
564 array ('url_argname' => 'id', 'assertion' => 'uint'),
565 ),
566 );
567 $opspec_list['munin-servers-add'] = array
568 (
569 'table' => 'MuninServer',
570 'action' => 'INSERT',
571 'arglist' => array
572 (
573 array ('url_argname' => 'base_url', 'assertion' => 'string')
574 ),
575 );
576 $opspec_list['munin-servers-del'] = array
577 (
578 'table' => 'MuninServer',
579 'action' => 'DELETE',
580 'arglist' => array
581 (
582 array ('url_argname' => 'id', 'assertion' => 'uint'),
583 ),
584 );
585 $opspec_list['munin-servers-upd'] = array
586 (
587 'table' => 'MuninServer',
588 'action' => 'UPDATE',
589 'set_arglist' => array
590 (
591 array ('url_argname' => 'base_url', 'assertion' => 'string'),
592 ),
593 'where_arglist' => array
594 (
595 array ('url_argname' => 'id', 'assertion' => 'uint'),
596 ),
597 );
598 $opspec_list['cables-heaps-add'] = array
599 (
600 'table' => 'PatchCableHeap',
601 'action' => 'INSERT',
602 'arglist' => array
603 (
604 array ('url_argname' => 'end1_conn_id', 'assertion' => 'uint'),
605 array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
606 array ('url_argname' => 'end2_conn_id', 'assertion' => 'uint'),
607 array ('fix_argname' => 'amount', 'fix_argvalue' => 0),
608 array ('url_argname' => 'length', 'assertion' => 'decimal'),
609 array ('url_argname' => 'description', 'assertion' => 'string0'),
610 ),
611 );
612 $opspec_list['cables-heaps-del'] = array
613 (
614 'table' => 'PatchCableHeap',
615 'action' => 'DELETE',
616 'arglist' => array
617 (
618 array ('url_argname' => 'id', 'assertion' => 'uint'),
619 ),
620 );
621 $opspec_list['cables-heaps-upd'] = array
622 (
623 'table' => 'PatchCableHeap',
624 'action' => 'UPDATE',
625 'set_arglist' => array
626 (
627 array ('url_argname' => 'end1_conn_id', 'assertion' => 'uint'),
628 array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
629 array ('url_argname' => 'end2_conn_id', 'assertion' => 'uint'),
630 array ('url_argname' => 'amount', 'assertion' => 'uint0'),
631 array ('url_argname' => 'length', 'assertion' => 'decimal'),
632 array ('url_argname' => 'description', 'assertion' => 'string0'),
633 ),
634 'where_arglist' => array
635 (
636 array ('url_argname' => 'id', 'assertion' => 'uint'),
637 ),
638 );
639 $opspec_list['cableconf-connectors-add'] = array
640 (
641 'table' => 'PatchCableConnector',
642 'action' => 'INSERT',
643 'arglist' => array
644 (
645 array ('url_argname' => 'connector', 'assertion' => 'string'),
646 array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
647 ),
648 );
649 $opspec_list['cableconf-connectors-del'] = array
650 (
651 'table' => 'PatchCableConnector',
652 'action' => 'DELETE',
653 'arglist' => array
654 (
655 array ('url_argname' => 'id', 'assertion' => 'uint'),
656 array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
657 ),
658 );
659 $opspec_list['cableconf-connectors-upd'] = array
660 (
661 'table' => 'PatchCableConnector',
662 'action' => 'UPDATE',
663 'set_arglist' => array
664 (
665 array ('url_argname' => 'connector', 'assertion' => 'string'),
666 ),
667 'where_arglist' => array
668 (
669 array ('url_argname' => 'id', 'assertion' => 'uint'),
670 array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
671 ),
672 );
673 $opspec_list['cableconf-cabletypes-add'] = array
674 (
675 'table' => 'PatchCableType',
676 'action' => 'INSERT',
677 'arglist' => array
678 (
679 array ('url_argname' => 'pctype', 'assertion' => 'string'),
680 array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
681 ),
682 );
683 $opspec_list['cableconf-cabletypes-del'] = array
684 (
685 'table' => 'PatchCableType',
686 'action' => 'DELETE',
687 'arglist' => array
688 (
689 array ('url_argname' => 'id', 'assertion' => 'uint'),
690 array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
691 ),
692 );
693 $opspec_list['cableconf-cabletypes-upd'] = array
694 (
695 'table' => 'PatchCableType',
696 'action' => 'UPDATE',
697 'set_arglist' => array
698 (
699 array ('url_argname' => 'pctype', 'assertion' => 'string'),
700 ),
701 'where_arglist' => array
702 (
703 array ('url_argname' => 'id', 'assertion' => 'uint'),
704 array ('fix_argname' => 'origin', 'fix_argvalue' => 'custom'),
705 ),
706 );
707 $opspec_list['cableconf-conncompat-add'] = array
708 (
709 'table' => 'PatchCableConnectorCompat',
710 'action' => 'INSERT',
711 'arglist' => array
712 (
713 array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
714 array ('url_argname' => 'connector_id', 'assertion' => 'uint'),
715 ),
716 );
717 $opspec_list['cableconf-conncompat-del'] = array
718 (
719 'table' => 'PatchCableConnectorCompat',
720 'action' => 'DELETE',
721 'arglist' => array
722 (
723 array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
724 array ('url_argname' => 'connector_id', 'assertion' => 'uint'),
725 ),
726 );
727 $opspec_list['cableconf-oifcompat-add'] = array
728 (
729 'table' => 'PatchCableOIFCompat',
730 'action' => 'INSERT',
731 'arglist' => array
732 (
733 array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
734 array ('url_argname' => 'oif_id', 'assertion' => 'uint'),
735 ),
736 );
737 $opspec_list['cableconf-oifcompat-del'] = array
738 (
739 'table' => 'PatchCableOIFCompat',
740 'action' => 'DELETE',
741 'arglist' => array
742 (
743 array ('url_argname' => 'pctype_id', 'assertion' => 'uint'),
744 array ('url_argname' => 'oif_id', 'assertion' => 'uint'),
745 ),
746 );
747
748 $msgcode['addPortForwarding']['OK'] = 48;
749 function addPortForwarding ()
750 {
751 assertUIntArg ('object_id');
752 $localip_bin = assertIPv4Arg ('localip');
753 $remoteip_bin = assertIPv4Arg ('remoteip');
754 if ($_REQUEST['proto'] != 'ALL')
755 {
756 assertUIntArg ('localport');
757 assertUIntArg ('remoteport');
758 }
759 assertStringArg ('proto');
760 assertStringArg ('description', TRUE);
761 $remoteport = isset ($_REQUEST['remoteport']) ? $_REQUEST['remoteport'] : '';
762 if (!strlen ($remoteport))
763 $remoteport = $_REQUEST['localport'];
764
765 newPortForwarding
766 (
767 $_REQUEST['object_id'],
768 $localip_bin,
769 $_REQUEST['localport'],
770 $remoteip_bin,
771 $remoteport,
772 $_REQUEST['proto'],
773 $_REQUEST['description']
774 );
775
776 showFuncMessage (__FUNCTION__, 'OK');
777 }
778
779 $msgcode['delPortForwarding']['OK'] = 49;
780 function delPortForwarding ()
781 {
782 assertUIntArg ('object_id');
783 $localip_bin = assertIPv4Arg ('localip');
784 $remoteip_bin = assertIPv4Arg ('remoteip');
785 if ($_REQUEST['proto'] != 'ALL')
786 {
787 assertUIntArg ('localport');
788 assertUIntArg ('remoteport');
789 }
790 assertStringArg ('proto');
791
792 deletePortForwarding
793 (
794 $_REQUEST['object_id'],
795 $localip_bin,
796 $_REQUEST['localport'],
797 $remoteip_bin,
798 $_REQUEST['remoteport'],
799 $_REQUEST['proto']
800 );
801 showFuncMessage (__FUNCTION__, 'OK');
802 }
803
804 $msgcode['updPortForwarding']['OK'] = 51;
805 function updPortForwarding ()
806 {
807 assertUIntArg ('object_id');
808 $localip_bin = assertIPv4Arg ('localip');
809 $remoteip_bin = assertIPv4Arg ('remoteip');
810 if ($_REQUEST['proto'] != 'ALL')
811 {
812 assertUIntArg ('localport');
813 assertUIntArg ('remoteport');
814 }
815 assertStringArg ('proto');
816 assertStringArg ('description', TRUE);
817
818 updatePortForwarding
819 (
820 $_REQUEST['object_id'],
821 $localip_bin,
822 $_REQUEST['localport'],
823 $remoteip_bin,
824 $_REQUEST['remoteport'],
825 $_REQUEST['proto'],
826 $_REQUEST['description']
827 );
828 showFuncMessage (__FUNCTION__, 'OK');
829 }
830
831 $msgcode['addPortForObject']['OK'] = 48;
832 function addPortForObject ()
833 {
834 assertStringArg ('port_name', TRUE);
835 genericAssertion ('port_l2address', 'l2address0');
836 genericAssertion ('port_name', 'string');
837 commitAddPort
838 (
839 $_REQUEST['object_id'],
840 trim ($_REQUEST['port_name']),
841 $_REQUEST['port_type_id'],
842 trim ($_REQUEST['port_label']),
843 trim ($_REQUEST['port_l2address'])
844 );
845 showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['port_name']));
846 }
847
848 $msgcode['editPortForObject']['OK'] = 6;
849 function editPortForObject ()
850 {
851 global $sic;
852 assertUIntArg ('port_id');
853 assertUIntArg ('port_type_id');
854 assertStringArg ('reservation_comment', TRUE);
855 genericAssertion ('l2address', 'l2address0');
856 genericAssertion ('name', 'string');
857 commitUpdatePort ($sic['object_id'], $sic['port_id'], $sic['name'], $sic['port_type_id'], $sic['label'], $sic['l2address'], $sic['reservation_comment']);
858 if (array_key_exists ('cable', $_REQUEST))
859 commitUpdatePortLink ($sic['port_id'], $sic['cable']);
860 showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['name']));
861 }
862
863 $msgcode['addMultiPorts']['OK'] = 10;
864 function addMultiPorts ()
865 {
866 assertStringArg ('format');
867 assertStringArg ('input');
868 assertStringArg ('port_type');
869 $format = $_REQUEST['format'];
870 $port_type = $_REQUEST['port_type'];
871 $object_id = $_REQUEST['object_id'];
872 // Input lines are escaped, so we have to explode and to chop by 2-char
873 // \n and \r respectively.
874 $lines1 = explode ("\n", $_REQUEST['input']);
875 foreach ($lines1 as $line)
876 {
877 $parts = explode ('\r', $line);
878 reset ($parts);
879 if (!strlen ($parts[0]))
880 continue;
881 else
882 $lines2[] = rtrim ($parts[0]);
883 }
884 $ports = array();
885 foreach ($lines2 as $line)
886 {
887 switch ($format)
888 {
889 case 'fisxii':
890 $words = explode (' ', preg_replace ('/[[:space:]]+/', ' ', $line));
891 list ($slot, $port) = explode ('/', $words[0]);
892 $ports[] = array
893 (
894 'name' => "e ${slot}/${port}",
895 'l2address' => $words[8],
896 'label' => "slot ${slot} port ${port}"
897 );
898 break;
899 case 'c3600asy':
900 $words = explode (' ', preg_replace ('/[[:space:]]+/', ' ', trim (substr ($line, 3))));
901 /*
902 How Async Lines are Numbered in Cisco 3600 Series Routers
903 http://www.cisco.com/en/US/products/hw/routers/ps274/products_tech_note09186a00801ca70b.shtml
904
905 Understanding 16- and 32-Port Async Network Modules
906 http://www.cisco.com/en/US/products/hw/routers/ps274/products_tech_note09186a00800a93f0.shtml
907 */
908 $async = $words[0];
909 $slot = floor (($async - 1) / 32);
910 $octalgroup = floor (($async - 1 - $slot * 32) / 8);
911 $cable = $async - $slot * 32 - $octalgroup * 8;
912 $og_label[0] = 'async 0-7';
913 $og_label[1] = 'async 8-15';
914 $og_label[2] = 'async 16-23';
915 $og_label[3] = 'async 24-31';
916 $ports[] = array
917 (
918 'name' => "async ${async}",
919 'l2address' => '',
920 'label' => "slot ${slot} " . $og_label[$octalgroup] . " cable ${cable}"
921 );
922 break;
923 case 'fiwg':
924 $words = explode (' ', preg_replace ('/[[:space:]]+/', ' ', $line));
925 $ifnumber = $words[0] * 1;
926 $ports[] = array
927 (
928 'name' => "e ${ifnumber}",
929 'l2address' => "${words[8]}",
930 'label' => "${ifnumber}"
931 );
932 break;
933 case 'ssv1':
934 $words = explode (' ', $line);
935 if (!strlen ($words[0]) or !strlen ($words[1]))
936 continue;
937 $ports[] = array
938 (
939 'name' => $words[0],
940 'l2address' => $words[1],
941 'label' => ''
942 );
943 break;
944 default:
945 throw new InvalidRequestArgException ('format', $format);
946 break;
947 }
948 }
949 // Create ports, if they don't exist.
950 $added_count = $updated_count = $error_count = 0;
951 foreach ($ports as $port)
952 {
953 $port_ids = getPortIDs ($object_id, $port['name']);
954 if (!count ($port_ids))
955 {
956 commitAddPort ($object_id, $port['name'], $port_type, $port['label'], $port['l2address']);
957 $added_count++;
958 }
959 elseif (count ($port_ids) == 1) // update only single-socket ports
960 {
961 commitUpdatePort ($object_id, $port_ids[0], $port['name'], $port_type, $port['label'], $port['l2address']);
962 $updated_count++;
963 }
964 }
965 showFuncMessage (__FUNCTION__, 'OK', array ($added_count, $updated_count, $error_count));
966 }
967
968 $msgcode['addBulkPorts']['OK'] = 82;
969 function addBulkPorts ()
970 {
971 assertStringArg ('port_type_id');
972 assertStringArg ('port_name', TRUE);
973 assertStringArg ('port_label', TRUE);
974 assertUIntArg ('port_numbering_start', TRUE);
975 assertUIntArg ('port_numbering_count');
976
977 $object_id = $_REQUEST['object_id'];
978 $port_name = $_REQUEST['port_name'];
979 $port_type_id = $_REQUEST['port_type_id'];
980 $port_label = $_REQUEST['port_label'];
981 $port_numbering_start = $_REQUEST['port_numbering_start'];
982 $port_numbering_count = $_REQUEST['port_numbering_count'];
983
984 $added_count = $error_count = 0;
985 if(strrpos($port_name, "%u") === false )
986 $port_name .= '%u';
987 for ($i=0,$c=$port_numbering_start; $i<$port_numbering_count; $i++,$c++)
988 {
989 commitAddPort ($object_id, @sprintf($port_name,$c), $port_type_id, @sprintf($port_label,$c), '');
990 $added_count++;
991 }
992 showFuncMessage (__FUNCTION__, 'OK', array ($added_count, $error_count));
993 }
994
995 $msgcode['updIPAllocation']['OK'] = 51;
996 function updIPAllocation ()
997 {
998 $ip_bin = assertIPArg ('ip');
999 assertUIntArg ('object_id');
1000 assertStringArg ('bond_name', TRUE);
1001 genericAssertion ('bond_type', 'enum/alloc_type');
1002 updateIPBond ($ip_bin, $_REQUEST['object_id'], $_REQUEST['bond_name'], $_REQUEST['bond_type']);
1003 showFuncMessage (__FUNCTION__, 'OK');
1004 return buildRedirectURL (NULL, NULL, array ('hl_ip' => ip_format ($ip_bin)));
1005 }
1006
1007 $msgcode['delIPAllocation']['OK'] = 49;
1008 function delIPAllocation ()
1009 {
1010 $ip_bin = assertIPArg ('ip');
1011 assertUIntArg ('object_id');
1012
1013 unbindIPFromObject ($ip_bin, $_REQUEST['object_id']);
1014 showFuncMessage (__FUNCTION__, 'OK');
1015 }
1016
1017 $msgcode['addIPAllocation']['OK'] = 48;
1018 $msgcode['addIPAllocation']['ERR1'] = 170;
1019 function addIPAllocation ()
1020 {
1021 $ip_bin = assertIPArg ('ip');
1022 assertUIntArg ('object_id');
1023 assertStringArg ('bond_name', TRUE);
1024 genericAssertion ('bond_type', 'enum/alloc_type');
1025
1026 if (getConfigVar ('IPV4_JAYWALK') != 'yes' and NULL === getIPAddressNetworkId ($ip_bin))
1027 {
1028 showFuncMessage (__FUNCTION__, 'ERR1', array (ip_format ($ip_bin)));
1029 return;
1030 }
1031
1032 bindIPToObject ($ip_bin, $_REQUEST['object_id'], $_REQUEST['bond_name'], $_REQUEST['bond_type']);
1033
1034 showFuncMessage (__FUNCTION__, 'OK');
1035 return buildRedirectURL (NULL, NULL, array ('hl_ip' => ip_format ($ip_bin)));
1036 }
1037
1038 function addIPv4Prefix ()
1039 {
1040 assertStringArg ('range');
1041 assertStringArg ('name', TRUE);
1042 $taglist = genericAssertion ('taglist', 'array0');
1043 global $sic;
1044 $vlan_ck = empty ($sic['vlan_ck']) ? NULL : genericAssertion ('vlan_ck', 'uint-vlan1');
1045 $net_id = createIPv4Prefix ($_REQUEST['range'], $sic['name'], isCheckSet ('is_connected'), $taglist, $vlan_ck);
1046 showSuccess ('IP network ' . mkA ($_REQUEST['range'], 'ipv4net', $net_id) . ' has been created');
1047 }
1048
1049 function addIPv6Prefix ()
1050 {
1051 assertStringArg ('range');
1052 assertStringArg ('name', TRUE);
1053 $taglist = genericAssertion ('taglist', 'array0');
1054 global $sic;
1055 $vlan_ck = empty ($sic['vlan_ck']) ? NULL : genericAssertion ('vlan_ck', 'uint-vlan1');
1056 $net_id = createIPv6Prefix ($_REQUEST['range'], $sic['name'], isCheckSet ('is_connected'), $taglist, $vlan_ck);
1057 showSuccess ('IP network ' . mkA ($_REQUEST['range'], 'ipv6net', $net_id) . ' has been created');
1058 }
1059
1060 $msgcode['delIPv4Prefix']['OK'] = 49;
1061 function delIPv4Prefix ()
1062 {
1063 assertUIntArg ('id');
1064 $netinfo = spotEntity ('ipv4net', $_REQUEST['id']);
1065 loadIPAddrList ($netinfo);
1066 if (! isIPNetworkEmpty ($netinfo))
1067 {
1068 showError ("There are allocations within prefix, delete forbidden");
1069 return;
1070 }
1071 if (array_key_exists ($netinfo['ip_bin'], $netinfo['addrlist']))
1072 updateV4Address ($netinfo['ip_bin'], '', 'no');
1073 $last_ip = ip_last ($netinfo);
1074 if (array_key_exists ($last_ip, $netinfo['addrlist']))
1075 updateV4Address ($last_ip, '', 'no');
1076 destroyIPv4Prefix ($_REQUEST['id']);
1077 showFuncMessage (__FUNCTION__, 'OK');
1078 global $pageno;
1079 if ($pageno == 'ipv4net')
1080 return buildRedirectURL ('index', 'default');
1081 }
1082
1083 $msgcode['delIPv6Prefix']['OK'] = 49;
1084 function delIPv6Prefix ()
1085 {
1086 assertUIntArg ('id');
1087 $netinfo = spotEntity ('ipv6net', $_REQUEST['id']);
1088 loadIPAddrList ($netinfo);
1089 if (! isIPNetworkEmpty ($netinfo))
1090 {
1091 showError ("There are allocations within prefix, delete forbidden");
1092 return;
1093 }
1094 if (array_key_exists ($netinfo['ip_bin'], $netinfo['addrlist']))
1095 updateV6Address ($netinfo['ip_bin'], '', 'no');
1096 destroyIPv6Prefix ($_REQUEST['id']);
1097 showFuncMessage (__FUNCTION__, 'OK');
1098 global $pageno;
1099 if ($pageno == 'ipv6net')
1100 return buildRedirectURL ('index', 'default');
1101 }
1102
1103 $msgcode['editAddress']['OK'] = 51;
1104 function editAddress ()
1105 {
1106 assertStringArg ('name', TRUE);
1107 assertStringArg ('comment', TRUE);
1108 $ip_bin = assertIPArg ('ip');
1109 updateAddress ($ip_bin, $_REQUEST['name'], isCheckSet ('reserved', 'yesno'), $_REQUEST['comment']);
1110 showFuncMessage (__FUNCTION__, 'OK');
1111 }
1112
1113 $msgcode['createUser']['OK'] = 5;
1114 function createUser ()
1115 {
1116 assertStringArg ('username');
1117 assertStringArg ('realname', TRUE);
1118 assertStringArg ('password');
1119 $username = $_REQUEST['username'];
1120 $password = sha1 ($_REQUEST['password']);
1121 $user_id = commitCreateUserAccount ($username, $_REQUEST['realname'], $password);
1122 if (isset ($_REQUEST['taglist']))
1123 produceTagsForNewRecord ('user', $_REQUEST['taglist'], $user_id);
1124 showFuncMessage (__FUNCTION__, 'OK', array ($username));
1125 }
1126
1127 $msgcode['updateUser']['OK'] = 6;
1128 function updateUser ()
1129 {
1130 genericAssertion ('user_id', 'uint');
1131 $username = assertStringArg ('username');
1132 assertStringArg ('realname', TRUE);
1133 $new_password = assertStringArg ('password', TRUE);
1134 $userinfo = spotEntity ('user', $_REQUEST['user_id']);
1135 // Set new password only if provided.
1136 $new_password = mb_strlen ($new_password) ? sha1 ($new_password) : $userinfo['user_password_hash'];
1137 commitUpdateUserAccount ($_REQUEST['user_id'], $username, $_REQUEST['realname'], $new_password);
1138 // if user account renaming is being performed, change key value in UserConfig table
1139 if ($userinfo['user_name'] !== $username)
1140 usePreparedUpdateBlade ('UserConfig', array ('user' => $username), array('user' => $userinfo['user_name']));
1141 showFuncMessage (__FUNCTION__, 'OK', array ($username));
1142 }
1143
1144 $msgcode['supplementAttrMap']['OK'] = 48;
1145 $msgcode['supplementAttrMap']['ERR1'] = 154;
1146 function supplementAttrMap ()
1147 {
1148 assertUIntArg ('attr_id');
1149 assertUIntArg ('objtype_id');
1150 $attrMap = getAttrMap();
1151 if ($attrMap[$_REQUEST['attr_id']]['type'] != 'dict')
1152 $chapter_id = NULL;
1153 else
1154 {
1155 try
1156 {
1157 assertUIntArg ('chapter_no');
1158 }
1159 catch (InvalidRequestArgException $e)
1160 {
1161 showFuncMessage (__FUNCTION__, 'ERR1', array ('chapter not selected'));
1162 return;
1163 }
1164 $chapter_id = $_REQUEST['chapter_no'];
1165 }
1166 commitSupplementAttrMap ($_REQUEST['attr_id'], $_REQUEST['objtype_id'], $chapter_id);
1167 showFuncMessage (__FUNCTION__, 'OK');
1168 }
1169
1170 $msgcode['clearSticker']['OK'] = 49;
1171 function clearSticker ()
1172 {
1173 global $sic;
1174 assertUIntArg ('attr_id');
1175 if (permitted (NULL, NULL, NULL, array (array ('tag' => '$attr_' . $sic['attr_id']))))
1176 commitUpdateAttrValue (getBypassValue(), $sic['attr_id']);
1177 else
1178 {
1179 $oldvalues = getAttrValues (getBypassValue());
1180 showError ('Permission denied, "' . $oldvalues[$sic['attr_id']]['name'] . '" left unchanged');
1181 }
1182 }
1183
1184 $msgcode['updateObjectAllocation']['OK'] = 63;
1185 function updateObjectAllocation ()
1186 {
1187 global $remote_username, $sic;
1188 if (!isset ($_REQUEST['got_atoms']))
1189 {
1190 unset($_GET['page']);
1191 unset($_GET['tab']);
1192 unset($_GET['op']);
1193 unset($_POST['page']);
1194 unset($_POST['tab']);
1195 unset($_POST['op']);
1196 return buildRedirectURL (NULL, NULL, $_REQUEST);
1197 }
1198 $object_id = getBypassValue();
1199 $changecnt = 0;
1200 // Get a list of all of this object's parents,
1201 // then trim the list to only include parents that are racks
1202 $objectParents = getEntityRelatives('parents', 'object', $object_id);
1203 $parentRacks = array();
1204 foreach ($objectParents as $parentData)
1205 if ($parentData['entity_type'] == 'rack')
1206 $parentRacks[] = $parentData['entity_id'];
1207 $workingRacksData = array();
1208 foreach ($_REQUEST['rackmulti'] as $cand_id)
1209 {
1210 if (!isset ($workingRacksData[$cand_id]))
1211 {
1212 $rackData = spotEntity ('rack', $cand_id);
1213 amplifyCell ($rackData);
1214 $workingRacksData[$cand_id] = $rackData;
1215 }
1216 // It's zero-U mounted to this rack on the form, but not in the DB. Mount it.
1217 if (isset($_REQUEST["zerou_${cand_id}"]) && !in_array($cand_id, $parentRacks))
1218 {
1219 $changecnt++;
1220 commitLinkEntities ('rack', $cand_id, 'object', $object_id);
1221 }
1222 // It's not zero-U mounted to this rack on the form, but it is in the DB. Unmount it.
1223 if (!isset($_REQUEST["zerou_${cand_id}"]) && in_array($cand_id, $parentRacks))
1224 {
1225 $changecnt++;
1226 commitUnlinkEntities ('rack', $cand_id, 'object', $object_id);
1227 }
1228 }
1229
1230 foreach ($workingRacksData as &$rd)
1231 applyObjectMountMask ($rd, $object_id);
1232
1233 $oldMolecule = getMoleculeForObject ($object_id);
1234 foreach ($workingRacksData as $rack_id => $rackData)
1235 {
1236 if (! processGridForm ($rackData, 'F', 'T', $object_id))
1237 continue;
1238 $changecnt++;
1239 // Reload our working copy after form processing.
1240 $rackData = spotEntity ('rack', $cand_id);
1241 amplifyCell ($rackData);
1242 applyObjectMountMask ($rackData, $object_id);
1243 $workingRacksData[$rack_id] = $rackData;
1244 }
1245 if ($changecnt)
1246 {
1247 // Log a record.
1248 $newMolecule = getMoleculeForObject ($object_id);
1249 usePreparedInsertBlade
1250 (
1251 'MountOperation',
1252 array
1253 (
1254 'object_id' => $object_id,
1255 'old_molecule_id' => count ($oldMolecule) ? createMolecule ($oldMolecule) : NULL,
1256 'new_molecule_id' => count ($newMolecule) ? createMolecule ($newMolecule) : NULL,
1257 'user_name' => $remote_username,
1258 'comment' => empty ($sic['comment']) ? NULL : $sic['comment'],
1259 )
1260 );
1261 }
1262 showFuncMessage (__FUNCTION__, 'OK', array ($changecnt));
1263 }
1264
1265 $msgcode['updateObject']['OK'] = 51;
1266 function updateObject ()
1267 {
1268 $taglist = genericAssertion ('taglist', 'array0');
1269 genericAssertion ('num_attrs', 'uint0');
1270 genericAssertion ('object_name', 'string0');
1271 genericAssertion ('object_label', 'string0');
1272 genericAssertion ('object_asset_no', 'string0');
1273 genericAssertion ('object_comment', 'string0');
1274 genericAssertion ('object_type_id', 'uint');
1275 $object_id = getBypassValue();
1276
1277 global $dbxlink, $sic;
1278 $dbxlink->beginTransaction();
1279 commitUpdateObject
1280 (
1281 $object_id,
1282 $_REQUEST['object_name'],
1283 $_REQUEST['object_label'],
1284 isCheckSet ('object_has_problems', 'yesno'),
1285 $_REQUEST['object_asset_no'],
1286 $_REQUEST['object_comment']
1287 );
1288 updateObjectAttributes ($object_id);
1289 $object = spotEntity ('object', $object_id);
1290 if ($sic['object_type_id'] != $object['objtype_id'])
1291 {
1292 if (! array_key_exists ($sic['object_type_id'], getObjectTypeChangeOptions ($object_id)))
1293 throw new InvalidRequestArgException ('new type_id', $sic['object_type_id'], 'incompatible with requested attribute values');
1294 usePreparedUpdateBlade ('Object', array ('objtype_id' => $sic['object_type_id']), array ('id' => $object_id));
1295 }
1296 // Invalidate thumb cache of all racks objects could occupy.
1297 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1298 usePreparedDeleteBlade ('RackThumbnail', array ('rack_id' => $rack_id));
1299 $dbxlink->commit();
1300 rebuildTagChainForEntity ('object', $object_id, buildTagChainFromIds ($taglist), TRUE);
1301 showFuncMessage (__FUNCTION__, 'OK');
1302 }
1303
1304 // Used when updating an object, location or rack
1305 function updateObjectAttributes ($object_id)
1306 {
1307 global $dbxlink;
1308 $type_id = getObjectType ($object_id);
1309 $oldvalues = getAttrValues ($object_id);
1310 $num_attrs = isset ($_REQUEST['num_attrs']) ? $_REQUEST['num_attrs'] : 0;
1311 for ($i = 0; $i < $num_attrs; $i++)
1312 {
1313 genericAssertion ("${i}_attr_id", 'uint');
1314 $attr_id = $_REQUEST["${i}_attr_id"];
1315 if (! array_key_exists ($attr_id, $oldvalues))
1316 throw new InvalidRequestArgException ('attr_id', $attr_id, 'malformed request');
1317 $value = $_REQUEST["${i}_value"];
1318
1319 // If the object is a rack, skip certain attributes as they are handled elsewhere
1320 // (height, sort_order)
1321 if ($type_id == 1560 and ($attr_id == 27 or $attr_id == 29))
1322 continue;
1323
1324 // Delete attribute and move on, when the field is empty or if the field
1325 // type is a dictionary and it is the "--NOT SET--" value of 0.
1326 if ($value == '' || ($oldvalues[$attr_id]['type'] == 'dict' && $value == 0))
1327 {
1328 if (permitted (NULL, NULL, NULL, array (array ('tag' => '$attr_' . $attr_id))))
1329 commitUpdateAttrValue ($object_id, $attr_id);
1330 else
1331 showError ('Permission denied, "' . $oldvalues[$attr_id]['name'] . '" left unchanged');
1332 continue;
1333 }
1334
1335 // The value could be uint/float, but we don't know ATM. Let SQL
1336 // server check this and complain.
1337 if ('date' == $oldvalues[$attr_id]['type'])
1338 $value = assertDateArg ("${i}_value");
1339 else
1340 assertStringArg ("${i}_value");
1341
1342 switch ($oldvalues[$attr_id]['type'])
1343 {
1344 case 'uint':
1345 case 'float':
1346 case 'string':
1347 case 'date':
1348 $oldvalue = $oldvalues[$attr_id]['value'];
1349 break;
1350 case 'dict':
1351 $oldvalue = $oldvalues[$attr_id]['key'];
1352 break;
1353 default:
1354 }
1355 if ($value === $oldvalue) // ('' == 0), but ('' !== 0)
1356 continue;
1357 if (permitted (NULL, NULL, NULL, array (array ('tag' => '$attr_' . $attr_id))))
1358 commitUpdateAttrValue ($object_id, $attr_id, $value);
1359 else
1360 showError ('Permission denied, "' . $oldvalues[$attr_id]['name'] . '" left unchanged');
1361 }
1362 }
1363
1364 function addMultipleObjects()
1365 {
1366 $taglist = genericAssertion ('taglist', 'array0');
1367 $max = getConfigVar ('MASSCOUNT');
1368 for ($i = 0; $i < $max; $i++)
1369 {
1370 if (!isset ($_REQUEST["${i}_object_type_id"]))
1371 {
1372 showError ('Submitted form is invalid at line ' . ($i + 1));
1373 return;
1374 }
1375
1376 assertUIntArg ("${i}_object_type_id", TRUE);
1377 assertStringArg ("${i}_object_name", TRUE);
1378 assertStringArg ("${i}_object_label", TRUE);
1379 assertStringArg ("${i}_object_asset_no", TRUE);
1380 $name = $_REQUEST["${i}_object_name"];
1381
1382 // It's better to skip silently, than to print a notice.
1383 if ($_REQUEST["${i}_object_type_id"] == 0)
1384 continue;
1385 try
1386 {
1387 $object_id = commitAddObject
1388 (
1389 $name,
1390 $_REQUEST["${i}_object_label"],
1391 $_REQUEST["${i}_object_type_id"],
1392 $_REQUEST["${i}_object_asset_no"],
1393 $taglist
1394 );
1395 $info = spotEntity ('object', $object_id);
1396 amplifyCell ($info);
1397 showSuccess ("added object " . formatPortLink ($info['id'], $info['dname'], NULL, NULL));
1398 }
1399 catch (RTDatabaseError $e)
1400 {
1401 showError ("Error creating object '$name': " . $e->getMessage());
1402 continue;
1403 }
1404 }
1405 }
1406
1407 function addLotOfObjects()
1408 {
1409 $taglist = genericAssertion ('taglist', 'array0');
1410 assertUIntArg ('global_type_id', TRUE);
1411 assertStringArg ('namelist', TRUE);
1412 $global_type_id = $_REQUEST['global_type_id'];
1413 if ($global_type_id == 0 or !strlen ($_REQUEST['namelist']))
1414 {
1415 showError ('Incomplete form has been ignored. Cheers.');
1416 return;
1417 }
1418 else
1419 {
1420 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
1421 $names1 = explode ("\n", $_REQUEST['namelist']);
1422 $names2 = array();
1423 foreach ($names1 as $line)
1424 {
1425 $parts = explode ('\r', $line);
1426 reset ($parts);
1427 if (!strlen ($parts[0]))
1428 continue;
1429 else
1430 $names2[] = rtrim ($parts[0]);
1431 }
1432 foreach ($names2 as $name)
1433 try
1434 {
1435 $object_id = commitAddObject ($name, NULL, $global_type_id, '', $taglist);
1436 $info = spotEntity ('object', $object_id);
1437 amplifyCell ($info);
1438 showSuccess ("added object " . formatPortLink ($info['id'], $info['dname'], NULL, NULL));
1439 }
1440 catch (RTDatabaseError $e)
1441 {
1442 showError ("Error creating object '$name': " . $e->getMessage());
1443 continue;
1444 }
1445 }
1446 }
1447
1448 function linkObjects ()
1449 {
1450 assertStringArg ('parent_entity_type');
1451 assertUIntArg ('parent_entity_id');
1452 assertStringArg ('child_entity_type');
1453 assertUIntArg ('child_entity_id');
1454
1455 commitLinkEntities
1456 (
1457 $_REQUEST['parent_entity_type'],
1458 $_REQUEST['parent_entity_id'],
1459 $_REQUEST['child_entity_type'],
1460 $_REQUEST['child_entity_id']
1461 );
1462 showSuccess ('Container set successfully');
1463 }
1464
1465 $msgcode['deleteObject']['OK'] = 7;
1466 function deleteObject ()
1467 {
1468 assertUIntArg ('object_id');
1469 $oinfo = spotEntity ('object', $_REQUEST['object_id']);
1470
1471 $racklist = getResidentRacksData ($_REQUEST['object_id'], FALSE);
1472 commitDeleteObject ($_REQUEST['object_id']);
1473 foreach ($racklist as $rack_id)
1474 usePreparedDeleteBlade ('RackThumbnail', array ('rack_id' => $rack_id));
1475 showFuncMessage (__FUNCTION__, 'OK', array ($oinfo['dname']));
1476 }
1477
1478 $msgcode['resetObject']['OK'] = 57;
1479 function resetObject ()
1480 {
1481 $racklist = getResidentRacksData (getBypassValue(), FALSE);
1482 commitResetObject (getBypassValue());
1483 foreach ($racklist as $rack_id)
1484 usePreparedDeleteBlade ('RackThumbnail', array ('rack_id' => $rack_id));
1485 showFuncMessage (__FUNCTION__, 'OK');
1486 }
1487
1488 $msgcode['updateUI']['OK'] = 51;
1489 function updateUI ()
1490 {
1491 assertUIntArg ('num_vars');
1492
1493 for ($i = 0; $i < $_REQUEST['num_vars']; $i++)
1494 {
1495 assertStringArg ("${i}_varname");
1496 assertStringArg ("${i}_varvalue", TRUE);
1497 $varname = $_REQUEST["${i}_varname"];
1498 $varvalue = $_REQUEST["${i}_varvalue"];
1499
1500 // If form value = value in DB, don't bother updating DB
1501 if (!isConfigVarChanged($varname, $varvalue))
1502 continue;
1503 // any exceptions will be handled by process.php
1504 setConfigVar ($varname, $varvalue, TRUE);
1505 }
1506 showFuncMessage (__FUNCTION__, 'OK');
1507 }
1508
1509 $msgcode['saveMyPreferences']['OK'] = 51;
1510 function saveMyPreferences ()
1511 {
1512 assertUIntArg ('num_vars');
1513
1514 for ($i = 0; $i < $_REQUEST['num_vars']; $i++)
1515 {
1516 assertStringArg ("${i}_varname");
1517 assertStringArg ("${i}_varvalue", TRUE);
1518 $varname = $_REQUEST["${i}_varname"];
1519 $varvalue = $_REQUEST["${i}_varvalue"];
1520
1521 // If form value = value in DB, don't bother updating DB
1522 if (!isConfigVarChanged($varname, $varvalue))
1523 continue;
1524 setUserConfigVar ($varname, $varvalue);
1525 }
1526 showFuncMessage (__FUNCTION__, 'OK');
1527 }
1528
1529 $msgcode['resetMyPreference']['OK'] = 51;
1530 function resetMyPreference ()
1531 {
1532 assertStringArg ("varname");
1533 resetUserConfigVar ($_REQUEST["varname"]);
1534 showFuncMessage (__FUNCTION__, 'OK');
1535 }
1536
1537 $msgcode['resetUIConfig']['OK'] = 57;
1538 function resetUIConfig()
1539 {
1540 setConfigVar ('MASSCOUNT','8');
1541 setConfigVar ('MAXSELSIZE','30');
1542 setConfigVar ('ROW_SCALE','2');
1543 setConfigVar ('IPV4_ADDRS_PER_PAGE','256');
1544 setConfigVar ('DEFAULT_RACK_HEIGHT','42');
1545 setConfigVar ('DEFAULT_SLB_VS_PORT','');
1546 setConfigVar ('DEFAULT_SLB_RS_PORT','');
1547 setConfigVar ('DETECT_URLS','no');
1548 setConfigVar ('RACK_PRESELECT_THRESHOLD','1');
1549 setConfigVar ('DEFAULT_IPV4_RS_INSERVICE','no');
1550 setConfigVar ('AUTOPORTS_CONFIG','4 = 1*33*kvm + 2*24*eth%u;15 = 1*446*kvm');
1551 setConfigVar ('SHOW_EXPLICIT_TAGS','yes');
1552 setConfigVar ('SHOW_IMPLICIT_TAGS','yes');
1553 setConfigVar ('SHOW_AUTOMATIC_TAGS','no');
1554 setConfigVar ('DEFAULT_OBJECT_TYPE','4');
1555 setConfigVar ('IPV4_AUTO_RELEASE','1');
1556 setConfigVar ('SHOW_LAST_TAB', 'yes');
1557 setConfigVar ('EXT_IPV4_VIEW', 'yes');
1558 setConfigVar ('TREE_THRESHOLD', '25');
1559 setConfigVar ('IPV4_JAYWALK', 'no');
1560 setConfigVar ('ADDNEW_AT_TOP', 'yes');
1561 setConfigVar ('IPV4_TREE_SHOW_USAGE', 'no');
1562 setConfigVar ('PREVIEW_TEXT_MAXCHARS', '10240');
1563 setConfigVar ('PREVIEW_TEXT_ROWS', '25');
1564 setConfigVar ('PREVIEW_TEXT_COLS', '80');
1565 setConfigVar ('PREVIEW_IMAGE_MAXPXS', '320');
1566 setConfigVar ('VENDOR_SIEVE', '');
1567 setConfigVar ('IPV4LB_LISTSRC', 'false');
1568 setConfigVar ('IPV4OBJ_LISTSRC','not ({$typeid_3} or {$typeid_9} or {$typeid_10} or {$typeid_11})');
1569 setConfigVar ('IPV4NAT_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8} or {$typeid_798}');
1570 setConfigVar ('ASSETWARN_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8}');
1571 setConfigVar ('NAMEWARN_LISTSRC','{$typeid_4} or {$typeid_7} or {$typeid_8}');
1572 setConfigVar ('RACKS_PER_ROW','12');
1573 setConfigVar ('FILTER_PREDICATE_SIEVE','');
1574 setConfigVar ('FILTER_DEFAULT_ANDOR','and');
1575 setConfigVar ('FILTER_SUGGEST_ANDOR','yes');
1576 setConfigVar ('FILTER_SUGGEST_TAGS','yes');
1577 setConfigVar ('FILTER_SUGGEST_PREDICATES','yes');
1578 setConfigVar ('FILTER_SUGGEST_EXTRA','no');
1579 setConfigVar ('DEFAULT_SNMP_COMMUNITY','public');
1580 setConfigVar ('IPV4_ENABLE_KNIGHT','yes');
1581 setConfigVar ('TAGS_TOPLIST_SIZE','50');
1582 setConfigVar ('TAGS_QUICKLIST_SIZE','20');
1583 setConfigVar ('TAGS_QUICKLIST_THRESHOLD','50');
1584 setConfigVar ('ENABLE_MULTIPORT_FORM', 'no');
1585 setConfigVar ('DEFAULT_PORT_IIF_ID', '1');
1586 setConfigVar ('DEFAULT_PORT_OIF_IDS', '1=24; 3=1078; 4=1077; 5=1079; 6=1080; 8=1082; 9=1084; 10=1588; 11=1668');
1587 setConfigVar ('IPV4_TREE_RTR_AS_CELL', 'no');
1588 setConfigVar ('PROXIMITY_RANGE', 0);
1589 setConfigVar ('IPV4_TREE_SHOW_VLAN', 'yes');
1590 setConfigVar ('VLANSWITCH_LISTSRC', '');
1591 setConfigVar ('VLANIPV4NET_LISTSRC', '');
1592 setConfigVar ('DEFAULT_VDOM_ID', '');
1593 setConfigVar ('DEFAULT_VST_ID', '');
1594 setConfigVar ('STATIC_FILTER', 'yes');
1595 setConfigVar ('8021Q_DEPLOY_MINAGE', '300');
1596 setConfigVar ('8021Q_DEPLOY_MAXAGE', '3600');
1597 setConfigVar ('8021Q_DEPLOY_RETRY', '10800');
1598 setConfigVar ('8021Q_WRI_AFTER_CONFT_LISTSRC', 'false');
1599 setConfigVar ('8021Q_INSTANT_DEPLOY', 'no');
1600 setConfigVar ('CDP_RUNNERS_LISTSRC', '');
1601 setConfigVar ('LLDP_RUNNERS_LISTSRC', '');
1602 setConfigVar ('SHRINK_TAG_TREE_ON_CLICK', 'yes');
1603 setConfigVar ('MAX_UNFILTERED_ENTITIES', '0');
1604 setConfigVar ('SYNCDOMAIN_MAX_PROCESSES', '0');
1605 setConfigVar ('PORT_EXCLUSION_LISTSRC', '{$typeid_3} or {$typeid_10} or {$typeid_11} or {$typeid_1505} or {$typeid_1506}');
1606 setConfigVar ('FILTER_RACKLIST_BY_TAGS', 'yes');
1607 setConfigVar ('MGMT_PROTOS', 'ssh: {$typeid_4}; telnet: {$typeid_8}');
1608 setConfigVar ('SYNC_802Q_LISTSRC', '');
1609 setConfigVar ('QUICK_LINK_PAGES', 'depot,ipv4space,rackspace');
1610 setConfigVar ('CACTI_LISTSRC', 'false');
1611 setConfigVar ('MUNIN_LISTSRC', 'false');
1612 setConfigVar ('VIRTUAL_OBJ_LISTSRC', '1504,1505,1506,1507');
1613 setConfigVar ('DATETIME_ZONE', 'UTC');
1614 setConfigVar ('DATETIME_FORMAT', '%Y-%m-%d');
1615 setConfigVar ('SEARCH_DOMAINS', '');
1616 setConfigVar ('8021Q_EXTSYNC_LISTSRC', 'false');
1617 setConfigVar ('8021Q_MULTILINK_LISTSRC', 'false');
1618 setConfigVar ('REVERSED_RACKS_LISTSRC', 'false');
1619 setConfigVar ('NEAREST_RACKS_CHECKBOX', 'yes');
1620 showFuncMessage (__FUNCTION__, 'OK');
1621 }
1622
1623 $msgcode['addRealServer']['OK'] = 48;
1624 // Add single record.
1625 function addRealServer ()
1626 {
1627 global $sic;
1628 $rsip_bin = assertIPArg ('rsip');
1629 assertStringArg ('rsport', TRUE);
1630 assertStringArg ('rsconfig', TRUE);
1631 assertStringArg ('comment', TRUE);
1632 addRStoRSPool
1633 (
1634 getBypassValue(),
1635 $rsip_bin,
1636 $_REQUEST['rsport'],
1637 isCheckSet ('inservice', 'yesno'),
1638 $sic['rsconfig'],
1639 $sic['comment']
1640 );
1641 showFuncMessage (__FUNCTION__, 'OK');
1642 }
1643
1644 $msgcode['addRealServers']['OK'] = 37;
1645 $msgcode['addRealServers']['ERR1'] = 131;
1646 // Parse textarea submitted and try adding a real server for each line.
1647 function addRealServers ()
1648 {
1649 global $sic;
1650 assertStringArg ('format');
1651 assertStringArg ('rawtext');
1652 $ngood = 0;
1653 // Keep in mind, that the text will have HTML entities (namely '>') escaped.
1654 foreach (explode ("\n", dos2unix ($sic['rawtext'])) as $line)
1655 {
1656 if (!strlen ($line))
1657 continue;
1658 $match = array ();
1659 switch ($_REQUEST['format'])
1660 {
1661 case 'ipvs_2': // address and port only
1662 if (!preg_match ('/^ -> ([0-9\.]+):([0-9]+) /', $line, $match))
1663 if (!preg_match ('/^ -> \[([0-9a-fA-F:]+)\]:([0-9]+) /', $line, $match))
1664 continue;
1665 addRStoRSPool (getBypassValue(), ip_parse ($match[1]), $match[2], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), '');
1666 break;
1667 case 'ipvs_3': // address, port and weight
1668 if (!preg_match ('/^ -> ([0-9\.]+):([0-9]+) +[a-zA-Z]+ +([0-9]+) /', $line, $match))
1669 if (!preg_match ('/^ -> \[([0-9a-fA-F:]+)\]:([0-9]+) +[a-zA-Z]+ +([0-9]+) /', $line, $match))
1670 continue;
1671 addRStoRSPool (getBypassValue(), ip_parse ($match[1]), $match[2], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), 'weight ' . $match[3]);
1672 break;
1673 case 'ssv_2': // IP address and port
1674 if (!preg_match ('/^([0-9\.a-fA-F:]+) ([0-9]+)$/', $line, $match))
1675 continue;
1676 addRStoRSPool (getBypassValue(), ip_parse ($match[1]), $match[2], getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), '');
1677 break;
1678 case 'ssv_1': // IP address
1679 if (! $ip_bin = ip_checkparse ($line))
1680 continue;
1681 addRStoRSPool (getBypassValue(), $ip_bin, 0, getConfigVar ('DEFAULT_IPV4_RS_INSERVICE'), '');
1682 break;
1683 default:
1684 showFuncMessage (__FUNCTION__, 'ERR1');
1685 return;
1686 }
1687 $ngood++;
1688 }
1689 showFuncMessage (__FUNCTION__, 'OK', array ($ngood));
1690 }
1691
1692 function addVService ()
1693 {
1694 global $sic;
1695 $vip_bin = assertIPArg ('vip');
1696 genericAssertion ('proto', 'enum/ipproto');
1697 assertStringArg ('name', TRUE);
1698 assertStringArg ('vsconfig', TRUE);
1699 assertStringArg ('rsconfig', TRUE);
1700 if ($_REQUEST['proto'] == 'MARK')
1701 $vport = NULL;
1702 else
1703 {
1704 assertUIntArg ('vport');
1705 $vport = $_REQUEST['vport'];
1706 }
1707 usePreparedInsertBlade
1708 (
1709 'IPv4VS',
1710 array
1711 (
1712 'vip' => $vip_bin,
1713 'vport' => $vport,
1714 'proto' => $_REQUEST['proto'],
1715 'name' => !mb_strlen ($_REQUEST['name']) ? NULL : $_REQUEST['name'],
1716 'vsconfig' => !strlen ($sic['vsconfig']) ? NULL : $sic['vsconfig'],
1717 'rsconfig' => !strlen ($sic['rsconfig']) ? NULL : $sic['rsconfig'],
1718 )
1719 );
1720 $vs_id = lastInsertID();
1721 lastCreated ('ipv4vs', $vs_id);
1722 if (isset ($_REQUEST['taglist']))
1723 produceTagsForNewRecord ('ipv4vs', $_REQUEST['taglist'], $vs_id);
1724 $vsinfo = spotEntity ('ipv4vs', $vs_id);
1725 showSuccess (mkCellA ($vsinfo) . ' created successfully');
1726 }
1727
1728 function addVSG ()
1729 {
1730 $name = assertStringArg ('name');
1731 usePreparedInsertBlade ('VS', array ('name' => $name));
1732 $vs_id = lastInsertID();
1733 lastCreated ('ipvs', $vs_id);
1734 if (isset ($_REQUEST['taglist']))
1735 produceTagsForNewRecord ('ipvs', $_REQUEST['taglist'], $vs_id);
1736 $vsinfo = spotEntity ('ipvs', $vs_id);
1737 showSuccess (mkCellA ($vsinfo) . ' created successfully');
1738 }
1739
1740 $msgcode['deleteVService']['OK'] = 49;
1741 function deleteVService ()
1742 {
1743 assertUIntArg ('vs_id');
1744 $vsinfo = spotEntity ('ipv4vs', $_REQUEST['vs_id']);
1745 if ($vsinfo['refcnt'] != 0)
1746 {
1747 showError ("Could not delete linked virtual service");
1748 return;
1749 }
1750 commitDeleteVS ($vsinfo['id']);
1751 showFuncMessage (__FUNCTION__, 'OK');
1752 return buildRedirectURL ('ipv4slb', 'default');
1753 }
1754
1755 function deleteVS()
1756 {
1757 $vsinfo = spotEntity ('ipvs', assertUIntArg ('vs_id'));
1758 if (count (getTriplets ($vsinfo)) != 0)
1759 {
1760 showError ("Could not delete linked virtual service group");
1761 return;
1762 }
1763 commitDeleteVSG ($vsinfo['id']);
1764 showSuccess (formatEntityName ($vsinfo) . ' deleted');
1765 return buildRedirectURL ('ipv4slb', 'vs');
1766 }
1767
1768 $msgcode['updateSLBDefConfig']['OK'] = 43;
1769 function updateSLBDefConfig ()
1770 {
1771 global $sic;
1772 commitUpdateSLBDefConf
1773 (
1774 array
1775 (
1776 'vs' => $sic['vsconfig'],
1777 'rs' => $sic['rsconfig'],
1778 )
1779 );
1780 showFuncMessage (__FUNCTION__, 'OK');
1781 }
1782
1783 $msgcode['updateRealServer']['OK'] = 51;
1784 function updateRealServer ()
1785 {
1786 global $sic;
1787 assertUIntArg ('rs_id');
1788 $rsip_bin = assertIPArg ('rsip');
1789 assertStringArg ('rsport', TRUE);
1790 assertStringArg ('rsconfig', TRUE);
1791 assertStringArg ('comment', TRUE);
1792 commitUpdateRS (
1793 $_REQUEST['rs_id'],
1794 $rsip_bin,
1795 $_REQUEST['rsport'],
1796 isCheckSet ('inservice', 'yesno'),
1797 $sic['rsconfig'],
1798 $sic['comment']
1799 );
1800 showFuncMessage (__FUNCTION__, 'OK');
1801 }
1802
1803 $msgcode['updateVService']['OK'] = 51;
1804 function updateVService ()
1805 {
1806 global $sic;
1807 assertUIntArg ('vs_id');
1808 $taglist = genericAssertion ('taglist', 'array0');
1809 $vip_bin = assertIPArg ('vip');
1810 genericAssertion ('proto', 'enum/ipproto');
1811 if ($_REQUEST['proto'] == 'MARK')
1812 assertStringArg ('vport', TRUE);
1813 else
1814 assertUIntArg ('vport');
1815 assertStringArg ('name', TRUE);
1816 assertStringArg ('vsconfig', TRUE);
1817 assertStringArg ('rsconfig', TRUE);
1818 commitUpdateVS (
1819 $_REQUEST['vs_id'],
1820 $vip_bin,
1821 $_REQUEST['vport'],
1822 $_REQUEST['proto'],
1823 $_REQUEST['name'],
1824 $sic['vsconfig'],
1825 $sic['rsconfig']
1826 );
1827 rebuildTagChainForEntity ('ipvs', $_REQUEST['vs_id'], buildTagChainFromIds ($taglist), TRUE);
1828 showFuncMessage (__FUNCTION__, 'OK');
1829 }
1830
1831 function updateVS ()
1832 {
1833 $taglist = genericAssertion ('taglist', 'array0');
1834 $vs_id = assertUIntArg ('vs_id');
1835 $name = assertStringArg ('name');
1836 $vsconfig = nullEmptyStr (assertStringArg ('vsconfig', TRUE));
1837 $rsconfig = nullEmptyStr (assertStringArg ('rsconfig', TRUE));
1838
1839 usePreparedUpdateBlade ('VS', array ('name' => $name, 'vsconfig' => $vsconfig, 'rsconfig' => $rsconfig), array ('id' => $vs_id));
1840 rebuildTagChainForEntity ('ipvs', $vs_id, buildTagChainFromIds ($taglist), TRUE);
1841 showSuccess ("Service updated successfully");
1842 }
1843
1844 function addIPToVS()
1845 {
1846 $ip_bin = assertIPArg ('ip');
1847 $vsinfo = spotEntity ('ipvs', assertUIntArg ('vs_id'));
1848 amplifyCell ($vsinfo);
1849 $row = array ('vs_id' => $vsinfo['id'], 'vip' => $ip_bin, 'vsconfig' => NULL, 'rsconfig' => NULL);
1850 if ($vip = isVIPEnabled ($row, $vsinfo['vips']))
1851 {
1852 showError ("Service already contains IP " . formatVSIP ($vip));
1853 return;
1854 }
1855 usePreparedInsertBlade ('VSIPs', $row);
1856 showSuccess ("IP addded");
1857 }
1858
1859 function addPortToVS()
1860 {
1861 global $vs_proto;
1862 $proto = assertStringArg ('proto');
1863 if (! in_array ($proto, $vs_proto))
1864 throw new InvalidRequestArgException ('proto', "Invalid VS protocol");
1865 $vport = assertUIntArg ('port', TRUE);
1866 if ($proto == 'MARK')
1867 {
1868 if ($vport > 0xFFFFFFFF)
1869 {
1870 showError ("fwmark value is too large");
1871 return;
1872 }
1873 }
1874 else
1875 if ($vport == 0 || $vport >= 0xFFFF)
1876 {
1877 showError ("Invalid $proto port value");
1878 return;
1879 }
1880
1881 $vsinfo = spotEntity ('ipvs', assertUIntArg ('vs_id'));
1882 amplifyCell ($vsinfo);
1883 $row = array ('vs_id' => $vsinfo['id'], 'proto' => $proto, 'vport' => $vport, 'vsconfig' => NULL, 'rsconfig' => NULL);
1884 if ($port = isPortEnabled ($row, $vsinfo['ports']))
1885 {
1886 showError ("Service already contains port " . formatVSPort ($port));
1887 return;
1888 }
1889 usePreparedInsertBlade ('VSPorts', $row);
1890 showSuccess ("port addded");
1891 }
1892
1893 function updateIPInVS()
1894 {
1895 $vs_id = assertUIntArg ('vs_id');
1896 $ip_bin = assertIPArg ('ip');
1897 $vsconfig = nullEmptyStr (assertStringArg ('vsconfig', TRUE));
1898 $rsconfig = nullEmptyStr (assertStringArg ('rsconfig', TRUE));
1899 if (usePreparedUpdateBlade ('VSIPs', array ('vsconfig' => $vsconfig, 'rsconfig' => $rsconfig), array ('vs_id' => $vs_id, 'vip' => $ip_bin)))
1900 showSuccess ("IP configuration updated");
1901 else
1902 showNotice ("Nothing changed");
1903 }
1904
1905 function updatePortInVS()
1906 {
1907 $vs_id = assertUIntArg ('vs_id');
1908 $proto = assertStringArg ('proto');
1909 $vport = assertUIntArg ('port', TRUE);
1910 $vsconfig = nullEmptyStr (assertStringArg ('vsconfig', TRUE));
1911 $rsconfig = nullEmptyStr (assertStringArg ('rsconfig', TRUE));
1912 if (usePreparedUpdateBlade ('VSPorts', array ('vsconfig' => $vsconfig, 'rsconfig' => $rsconfig), array ('vs_id' => $vs_id, 'proto' => $proto, 'vport' => $vport)))
1913 showSuccess ("Port configuration updated");
1914 else
1915 showNotice ("Nothing changed");
1916 }
1917
1918 function removeIPFromVS()
1919 {
1920 $vip = array ('vip' => assertIPArg ('ip'));
1921 $vsinfo = spotEntity ('ipvs', assertUIntArg ('vs_id'));
1922 amplifyCell ($vsinfo);
1923 $used = 0;
1924 foreach (getTriplets ($vsinfo) as $triplet)
1925 if (isVIPEnabled ($vip, $triplet['vips']))
1926 $used++;
1927 if (usePreparedDeleteBlade ('VSIPs', array ('vs_id' => $vsinfo['id']) + $vip))
1928 showSuccess ("IP removed" . ($used ? ", it was binded with $used SLBs" : ''));
1929 else
1930 showNotice ("Nothing changed");
1931 }
1932
1933 function removePortFromVS()
1934 {
1935 $port = array ('proto' => assertStringArg ('proto'), 'vport' => assertUIntArg ('port', TRUE));
1936 $vsinfo = spotEntity ('ipvs', assertUIntArg ('vs_id'));
1937 amplifyCell ($vsinfo);
1938 $used = 0;
1939 foreach (getTriplets ($vsinfo) as $triplet)
1940 if (isPortEnabled ($port, $triplet['ports']))
1941 $used++;
1942 if (usePreparedDeleteBlade ('VSPorts', array ('vs_id' => $vsinfo['id']) + $port))
1943 showSuccess ("Port removed" . ($used ? ", it was binded with $used SLBs" : ''));
1944 else
1945 showNotice ("Nothing changed");
1946 }
1947
1948 function updateTripletConfig()
1949 {
1950 $key_fields = array
1951 (
1952 'object_id' => assertUIntArg ('object_id'),
1953 'vs_id' => assertUIntArg ('vs_id'),
1954 'rspool_id' => assertUIntArg ('rspool_id'),
1955 );
1956 $config_fields = array
1957 (
1958 'vsconfig' => nullEmptyStr (assertStringArg ('vsconfig', TRUE)),
1959 'rsconfig' => nullEmptyStr (assertStringArg ('rsconfig', TRUE)),
1960 );
1961
1962 $vsinfo = spotEntity ('ipvs', $key_fields['vs_id']);
1963 amplifyCell ($vsinfo);
1964 $found = FALSE;
1965
1966 if ($_REQUEST['op'] == 'updPort')
1967 {
1968 $table = 'VSEnabledPorts';
1969 $proto = assertStringArg ('proto');
1970 $vport = assertUIntArg ('port', TRUE);
1971 $key_fields['proto'] = $proto;
1972 $key_fields['vport'] = $vport;
1973 $key = "Port $proto-$vport";
1974 // check if such port exists in VS
1975 foreach ($vsinfo['ports'] as $vs_port)
1976 if ($vs_port['proto'] == $proto && $vs_port['vport'] == $vport)
1977 {
1978 $found = TRUE;
1979 break;
1980 }
1981 }
1982 else
1983 {
1984 $table = 'VSEnabledIPs';
1985 $vip = assertIPArg ('vip');
1986 $config_fields['prio'] = nullEmptyStr (assertStringArg ('prio', TRUE));
1987 $key_fields['vip'] = $vip;
1988 $key = "IP " . ip_format ($vip);
1989 // check if such VIP exists in VS
1990 foreach ($vsinfo['vips'] as $vs_vip)
1991 if ($vs_vip['vip'] === $vip)
1992 {
1993 $found = TRUE;
1994 break;
1995 }
1996 }
1997 if (! $found)
1998 {
1999 showError ("$key not found in VS");
2000 return;
2001 }
2002
2003 $nchanged = 0;
2004 if (! isCheckSet ('enabled'))
2005 {
2006 if ($nchanged += usePreparedDeleteBlade ($table, $key_fields))
2007 {
2008 showSuccess ("$key disabled");
2009 return;
2010 }
2011 }
2012 else
2013 {
2014 global $dbxlink;
2015 $dbxlink->beginTransaction();
2016 $q = "SELECT * FROM $table WHERE";
2017 $sep = '';
2018 $params = array();
2019 foreach ($key_fields as $field => $value)
2020 {
2021 $q .= " $sep $field = ?";
2022 $params[] = $value;
2023 $sep = 'AND';
2024 }
2025 $result = usePreparedSelectBlade ("$q FOR UPDATE", $params);
2026 $row = $result->fetch (PDO::FETCH_ASSOC);
2027 unset ($result);
2028 if ($row)
2029 {
2030 if ($nchanged += usePreparedUpdateBlade ($table, $config_fields, $key_fields))
2031 showSuccess ("$key config updated");
2032 }
2033 else
2034 {
2035 if (
2036 $nchanged += ($table == 'VSEnabledIPs' ?
2037 addSLBIPLink ($key_fields + $config_fields) :
2038 addSLBPortLink ($key_fields + $config_fields)
2039 )
2040 )
2041 showSuccess ("$key enabled");
2042 }
2043 $dbxlink->commit();
2044 }
2045 if (! $nchanged)
2046 showNotice ("No changes made");
2047 }
2048
2049 function removeTriplet()
2050 {
2051 $key_fields = array
2052 (
2053 'object_id' => assertUIntArg ('object_id'),
2054 'vs_id' => assertUIntArg ('vs_id'),
2055 'rspool_id' => assertUIntArg ('rspool_id'),
2056 );
2057
2058 global $dbxlink;
2059 $dbxlink->beginTransaction();
2060 usePreparedDeleteBlade ('VSEnabledIPs', $key_fields);
2061 usePreparedDeleteBlade ('VSEnabledPorts', $key_fields);
2062 $dbxlink->commit();
2063 showSuccess ('Triplet deleted');
2064 }
2065
2066 function createTriplet()
2067 {
2068 global $dbxlink;
2069 $object_id = assertUIntArg ('object_id');
2070 $vs_id = assertUIntArg ('vs_id');
2071 $rspool_id = assertUIntArg ('rspool_id');
2072 $vips = genericAssertion ('enabled_vips', 'array0');
2073 $ports = genericAssertion ('enabled_ports', 'array0');
2074
2075 $vsinfo = spotEntity ('ipvs', $vs_id);
2076 amplifyCell ($vsinfo);
2077 try
2078 {
2079 $dbxlink->beginTransaction();
2080 foreach ($vsinfo['vips'] as $vip)
2081 if (in_array (ip_format ($vip['vip']), $vips))
2082 addSLBIPLink (array ('object_id' => $object_id, 'vs_id' => $vs_id, 'rspool_id' => $rspool_id, 'vip' => $vip['vip']));
2083 foreach ($vsinfo['ports'] as $port)
2084 if (in_array($port['proto'] . '-' . $port['vport'], $ports))
2085 addSLBPortLink (array ('object_id' => $object_id, 'vs_id' => $vs_id, 'rspool_id' => $rspool_id, 'proto' => $port['proto'], 'vport' => $port['vport']));
2086 $dbxlink->commit();
2087 }
2088 catch (RTDatabaseError $e)
2089 {
2090 $dbxlink->rollBack();
2091 throw $e;
2092 }
2093 showSuccess ("SLB triplet created");
2094 }
2095
2096 $msgcode['addLoadBalancer']['OK'] = 48;
2097 function addLoadBalancer ()
2098 {
2099 global $sic;
2100 assertUIntArg ('pool_id');
2101 assertUIntArg ('object_id');
2102 assertUIntArg ('vs_id');
2103 assertStringArg ('vsconfig', TRUE);
2104 assertStringArg ('rsconfig', TRUE);
2105 assertStringArg ('prio', TRUE);
2106
2107 addLBtoRSPool (
2108 $_REQUEST['pool_id'],
2109 $_REQUEST['object_id'],
2110 $_REQUEST['vs_id'],
2111 $sic['vsconfig'],
2112 $sic['rsconfig'],
2113 $_REQUEST['prio']
2114 );
2115 showFuncMessage (__FUNCTION__, 'OK');
2116 }
2117
2118 function addRSPool ()
2119 {
2120 global $sic;
2121 assertStringArg ('name');
2122 assertStringArg ('vsconfig', TRUE);
2123 assertStringArg ('rsconfig', TRUE);
2124 $pool_id = commitCreateRSPool
2125 (
2126 $_REQUEST['name'],
2127 $sic['vsconfig'],
2128 $sic['rsconfig'],
2129 isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array()
2130 );
2131 showSuccess ('RS pool ' . mkA ($_REQUEST['name'], 'ipv4rspool', $pool_id) . ' created successfully');
2132 }
2133
2134 $msgcode['deleteRSPool']['OK'] = 49;
2135 function deleteRSPool ()
2136 {
2137 assertUIntArg ('pool_id');
2138 $poolinfo = spotEntity ('ipv4rspool', $_REQUEST['pool_id']);
2139 if ($poolinfo['refcnt'] != 0)
2140 {
2141 showError ("Could not delete linked RS pool");
2142 return;
2143 }
2144 commitDeleteRSPool ($poolinfo['id']);
2145 showFuncMessage (__FUNCTION__, 'OK');
2146 return buildRedirectURL ('ipv4slb', 'rspools');
2147 }
2148
2149 $msgcode['importPTRData']['OK'] = 26;
2150 $msgcode['importPTRData']['ERR'] = 141;
2151 function importPTRData ()
2152 {
2153 $net = spotEntity ('ipv4net', getBypassValue());
2154 assertUIntArg ('addrcount');
2155 $nbad = $ngood = 0;
2156 for ($i = 1; $i <= $_REQUEST['addrcount']; $i++)
2157 {
2158 $inputname = "import_${i}";
2159 if (! isCheckSet ($inputname))
2160 continue;
2161 $ip_bin = assertIPv4Arg ("addr_${i}");
2162 assertStringArg ("descr_${i}", TRUE);
2163 assertStringArg ("rsvd_${i}");
2164 // Non-existent addresses will not have this argument set in request.
2165 $rsvd = 'no';
2166 if ($_REQUEST["rsvd_${i}"] == 'yes')
2167 $rsvd = 'yes';
2168 try
2169 {
2170 if (! ip_in_range ($ip_bin, $net))
2171 throw new InvalidArgException ('ip_bin', $ip_bin);
2172 updateAddress ($ip_bin, $_REQUEST["descr_${i}"], $rsvd);
2173 $ngood++;
2174 }
2175 catch (RackTablesError $e)
2176 {
2177 $nbad++;
2178 }
2179 }
2180 if (!$nbad)
2181 showFuncMessage (__FUNCTION__, 'OK', array ($ngood));
2182 else
2183 showFuncMessage (__FUNCTION__, 'ERR', array ($nbad, $ngood));
2184 }
2185
2186 $msgcode['generateAutoPorts']['OK'] = 21;
2187 function generateAutoPorts ()
2188 {
2189 $object = spotEntity ('object', getBypassValue());
2190 executeAutoPorts ($object['id'], $object['objtype_id']);
2191 showFuncMessage (__FUNCTION__, 'OK');
2192 return buildRedirectURL (NULL, 'ports');
2193 }
2194
2195 function updateTag ()
2196 {
2197 assertUIntArg ('tag_id');
2198 genericAssertion ('tag_name', 'tag');
2199 assertUIntArg ('parent_id', TRUE);
2200 genericAssertion ('is_assignable', 'enum/yesno');
2201 commitUpdateTag ($_REQUEST['tag_id'], $_REQUEST['tag_name'], $_REQUEST['parent_id'], $_REQUEST['is_assignable']);
2202 showSuccess ('Tag updated successfully');
2203 }
2204
2205 $msgcode['saveEntityTags']['OK'] = 43;
2206 function saveEntityTags ()
2207 {
2208 global $pageno, $etype_by_pageno;
2209 if (!isset ($etype_by_pageno[$pageno]))
2210 throw new RackTablesError ('key not found in etype_by_pageno', RackTablesError::INTERNAL);
2211 $realm = $etype_by_pageno[$pageno];
2212 $entity_id = getBypassValue();
2213 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
2214 rebuildTagChainForEntity ($realm, $entity_id, buildTagChainFromIds ($taglist), TRUE);
2215 showFuncMessage (__FUNCTION__, 'OK');
2216 }
2217
2218 $msgcode['rollTags']['OK'] = 67;
2219 $msgcode['rollTags']['ERR'] = 149;
2220 function rollTags ()
2221 {
2222 assertStringArg ('sum', TRUE);
2223 assertUIntArg ('realsum');
2224 if ($_REQUEST['sum'] != $_REQUEST['realsum'])
2225 {
2226 showFuncMessage (__FUNCTION__, 'ERR');
2227 return;
2228 }
2229 // Even if the user requested an empty tag list, don't bail out, but process existing
2230 // tag chains with "zero" extra. This will make sure, that the stuff processed will
2231 // have its chains refined to "normal" form.
2232 $extratags = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
2233 $n_ok = 0;
2234 // Minimizing the extra chain early, so that tag rebuilder doesn't have to
2235 // filter out the same tag again and again. It will have own noise to cancel.
2236 $extrachain = getExplicitTagsOnly (buildTagChainFromIds ($extratags));
2237 foreach (listCells ('rack', getBypassValue()) as $rack)
2238 {
2239 if (rebuildTagChainForEntity ('rack', $rack['id'], $extrachain))
2240 $n_ok++;
2241 amplifyCell ($rack);
2242 foreach ($rack['mountedObjects'] as $object_id)
2243 if (rebuildTagChainForEntity ('object', $object_id, $extrachain))
2244 $n_ok++;
2245 }
2246 showFuncMessage (__FUNCTION__, 'OK', array ($n_ok));
2247 }
2248
2249 $msgcode['changeMyPassword']['OK'] = 51;
2250 $msgcode['changeMyPassword']['ERR1'] = 150;
2251 $msgcode['changeMyPassword']['ERR2'] = 151;
2252 $msgcode['changeMyPassword']['ERR3'] = 152;
2253 function changeMyPassword ()
2254 {
2255 global $remote_username, $user_auth_src;
2256 if ($user_auth_src != 'database')
2257 {
2258 showFuncMessage (__FUNCTION__, 'ERR1');
2259 return;
2260 }
2261 assertStringArg ('oldpassword');
2262 assertStringArg ('newpassword1');
2263 assertStringArg ('newpassword2');
2264 $remote_userid = getUserIDByUsername ($remote_username);
2265 $userinfo = spotEntity ('user', $remote_userid);
2266 if ($userinfo['user_password_hash'] != sha1 ($_REQUEST['oldpassword']))
2267 {
2268 showFuncMessage (__FUNCTION__, 'ERR2');
2269 return;
2270 }
2271 if ($_REQUEST['newpassword1'] != $_REQUEST['newpassword2'])
2272 {
2273 showFuncMessage (__FUNCTION__, 'ERR3');
2274 return;
2275 }
2276 commitUpdateUserAccount ($remote_userid, $userinfo['user_name'], $userinfo['user_realname'], sha1 ($_REQUEST['newpassword1']));
2277 showFuncMessage (__FUNCTION__, 'OK');
2278 }
2279
2280 $msgcode['saveRackCode']['OK'] = 43;
2281 $msgcode['saveRackCode']['ERR1'] = 154;
2282 function saveRackCode ()
2283 {
2284 assertStringArg ('rackcode');
2285 // For the test to succeed, unescape LFs, strip CRs.
2286 $newcode = dos2unix ($_REQUEST['rackcode']);
2287 $parseTree = getRackCode ($newcode);
2288 if ($parseTree['result'] != 'ACK')
2289 {
2290 showFuncMessage (__FUNCTION__, 'ERR1', array ($parseTree['load']));
2291 return;
2292 }
2293 saveScript ('RackCode', $newcode);
2294 saveScript ('RackCodeCache', base64_encode (serialize ($parseTree)));
2295 showFuncMessage (__FUNCTION__, 'OK');
2296 }
2297
2298 function submitSLBConfig ()
2299 {
2300 showNotice ("You should redefine submitSLBConfig ophandler in your local extension to install SLB config");
2301 }
2302
2303 $msgcode['addLocation']['OK'] = 5;
2304 function addLocation ()
2305 {
2306 assertUIntArg ('parent_id', TRUE);
2307 assertStringArg ('name');
2308
2309 $location_id = commitAddObject ($_REQUEST['name'], NULL, 1562, NULL);
2310 if ($_REQUEST['parent_id'])
2311 commitLinkEntities ('location', $_REQUEST['parent_id'], 'location', $location_id);
2312 showSuccess ('added location ' . mkA ($_REQUEST['name'], 'location', $location_id));
2313 }
2314
2315 $msgcode['updateLocation']['OK'] = 6;
2316 // This function is used by two forms:
2317 // - renderEditLocationForm - all attributes may be modified
2318 // - renderRackspaceLocationEditor - only the name and parent may be modified
2319 function updateLocation ()
2320 {
2321 global $pageno;
2322 assertUIntArg ('location_id');
2323 assertUIntArg ('parent_id', TRUE);
2324 assertStringArg ('name');
2325
2326 if ($pageno == 'location')
2327 {
2328 $taglist = genericAssertion ('taglist', 'array0');
2329 $has_problems = (isset ($_REQUEST['has_problems']) and $_REQUEST['has_problems'] == 'on') ? 'yes' : 'no';
2330 assertStringArg ('comment', TRUE);
2331 commitUpdateObject ($_REQUEST['location_id'], $_REQUEST['name'], NULL, $has_problems, NULL, $_REQUEST['comment']);
2332 updateObjectAttributes ($_REQUEST['location_id']);
2333 rebuildTagChainForEntity ('location', $_REQUEST['location_id'], buildTagChainFromIds ($taglist), TRUE);
2334 }
2335 else
2336 commitRenameObject ($_REQUEST['location_id'], $_REQUEST['name']);
2337
2338 $locationData = spotEntity ('location', $_REQUEST['location_id']);
2339
2340 // parent_id was submitted, but no link exists - create it
2341 if ($_REQUEST['parent_id'] > 0 && !$locationData['parent_id'])
2342 commitLinkEntities ('location', $_REQUEST['parent_id'], 'location', $_REQUEST['location_id']);
2343
2344 // parent_id was submitted, but it doesn't match the existing link - update it
2345 if ($_REQUEST['parent_id'] > 0 && $_REQUEST['parent_id'] != $locationData['parent_id'])
2346 commitUpdateEntityLink
2347 (
2348 'location', $locationData['parent_id'], 'location', $_REQUEST['location_id'],
2349 'location', $_REQUEST['parent_id'], 'location', $_REQUEST['location_id']
2350 );
2351
2352 // no parent_id was submitted, but a link exists - delete it
2353 if ($_REQUEST['parent_id'] == 0 && $locationData['parent_id'])
2354 commitUnlinkEntities ('location', $locationData['parent_id'], 'location', $_REQUEST['location_id']);
2355
2356 showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['name']));
2357 }
2358
2359 $msgcode['deleteLocation']['OK'] = 7;
2360 $msgcode['deleteLocation']['ERR1'] = 206;
2361 function deleteLocation ()
2362 {
2363 assertUIntArg ('location_id');
2364 $locationData = spotEntity ('location', $_REQUEST['location_id']);
2365 amplifyCell ($locationData);
2366 if (count ($locationData['locations']) || count ($locationData['rows']))
2367 {
2368 showFuncMessage (__FUNCTION__, 'ERR1', array ($locationData['name']));
2369 return;
2370 }
2371 releaseFiles ('location', $_REQUEST['location_id']);
2372 destroyTagsForEntity ('location', $_REQUEST['location_id']);
2373 commitDeleteObject ($_REQUEST['location_id']);
2374 showFuncMessage (__FUNCTION__, 'OK', array ($locationData['name']));
2375 return buildRedirectURL ('rackspace', 'editlocations');
2376 }
2377
2378 $msgcode['addRow']['OK'] = 5;
2379 function addRow ()
2380 {
2381 assertUIntArg ('location_id', TRUE);
2382 assertStringArg ('name');
2383 $row_id = commitAddObject ($_REQUEST['name'], NULL, 1561, NULL);
2384 if ($_REQUEST['location_id'])
2385 commitLinkEntities ('location', $_REQUEST['location_id'], 'row', $row_id);
2386 showSuccess ('added row ' . mkA ($_REQUEST['name'], 'row', $row_id));
2387 }
2388
2389 $msgcode['updateRow']['OK'] = 6;
2390 // This function is used by two forms:
2391 // - renderEditRowForm - all attributes may be modified
2392 // - renderRackspaceRowEditor - only the name and location may be modified
2393 function updateRow ()
2394 {
2395 assertUIntArg ('row_id');
2396 assertUIntArg ('location_id', TRUE);
2397 assertStringArg ('name');
2398
2399 commitUpdateObject ($_REQUEST['row_id'], $_REQUEST['name'], NULL, NULL, NULL, NULL);
2400
2401 global $pageno;
2402 if ($pageno == 'row')
2403 updateObjectAttributes ($_REQUEST['row_id']);
2404
2405 $rowData = spotEntity ('row', $_REQUEST['row_id']);
2406
2407 // location_id was submitted, but no link exists - create it
2408 if ($_REQUEST['location_id'] > 0 && !$rowData['location_id'])
2409 commitLinkEntities ('location', $_REQUEST['location_id'], 'row', $_REQUEST['row_id']);
2410
2411 // location_id was submitted, but it doesn't match the existing link - update it
2412 if ($_REQUEST['location_id'] > 0 && $_REQUEST['location_id'] != $rowData['location_id'])
2413 commitUpdateEntityLink
2414 (
2415 'location', $rowData['location_id'], 'row', $_REQUEST['row_id'],
2416 'location', $_REQUEST['location_id'], 'row', $_REQUEST['row_id']
2417 );
2418
2419 // no parent_id was submitted, but a link exists - delete it
2420 if ($_REQUEST['location_id'] == 0 && $rowData['location_id'])
2421 commitUnlinkEntities ('location', $rowData['location_id'], 'row', $_REQUEST['row_id']);
2422
2423 showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['name']));
2424 }
2425
2426 $msgcode['deleteRow']['OK'] = 7;
2427 $msgcode['deleteRow']['ERR1'] = 206;
2428 function deleteRow ()
2429 {
2430 assertUIntArg ('row_id');
2431 $rowData = spotEntity ('row', $_REQUEST['row_id']);
2432 amplifyCell ($rowData);
2433 if (count ($rowData['racks']))
2434 {
2435 showFuncMessage (__FUNCTION__, 'ERR1', array ($rowData['name']));
2436 return;
2437 }
2438 commitDeleteObject ($_REQUEST['row_id']);
2439 showFuncMessage (__FUNCTION__, 'OK', array ($rowData['name']));
2440 return buildRedirectURL ('rackspace', 'editrows');
2441 }
2442
2443 $msgcode['addRack']['ERR2'] = 172;
2444 function addRack ()
2445 {
2446 $taglist = genericAssertion ('taglist', 'array0');
2447
2448 // The new rack(s) should be placed on the bottom of the list, sort-wise
2449 $rowInfo = getRowInfo($_REQUEST['row_id']);
2450 $sort_order = $rowInfo['count']+1;
2451
2452 if (isset ($_REQUEST['got_data']))
2453 {
2454 assertStringArg ('name');
2455 assertUIntArg ('height1');
2456 assertStringArg ('asset_no', TRUE);
2457 $rack_id = commitAddObject ($_REQUEST['name'], NULL, 1560, $_REQUEST['asset_no'], $taglist);
2458
2459 // Set the height and sort order
2460 commitUpdateAttrValue ($rack_id, 27, $_REQUEST['height1']);
2461 commitUpdateAttrValue ($rack_id, 29, $sort_order);
2462
2463 // Link it to the row
2464 commitLinkEntities ('row', $_REQUEST['row_id'], 'rack', $rack_id);
2465 showSuccess ('added rack ' . mkA ($_REQUEST['name'], 'rack', $rack_id));
2466 }
2467 elseif (isset ($_REQUEST['got_mdata']))
2468 {
2469 assertUIntArg ('height2');
2470 assertStringArg ('names', TRUE);
2471 // copy-and-paste from renderAddMultipleObjectsForm()
2472 $names1 = explode ("\n", $_REQUEST['names']);
2473 $names2 = array();
2474 foreach ($names1 as $line)
2475 {
2476 $parts = explode ('\r', $line);
2477 reset ($parts);
2478 if (!strlen ($parts[0]))
2479 continue;
2480 else
2481 $names2[] = rtrim ($parts[0]);
2482 }
2483 foreach ($names2 as $cname)
2484 {
2485 $rack_id = commitAddObject ($cname, NULL, 1560, NULL, $taglist);
2486
2487 // Set the height and sort order
2488 commitUpdateAttrValue ($rack_id, 27, $_REQUEST['height2']);
2489 commitUpdateAttrValue ($rack_id, 29, $sort_order);
2490 $sort_order++;
2491
2492 // Link it to the row
2493 commitLinkEntities ('row', $_REQUEST['row_id'], 'rack', $rack_id);
2494 showSuccess ('added rack ' . mkA ($cname, 'rack', $rack_id));
2495 }
2496 }
2497 else
2498 showFuncMessage (__FUNCTION__, 'ERR2');
2499 }
2500
2501 $msgcode['updateRack']['OK'] = 6;
2502 function updateRack ()
2503 {
2504 assertUIntArg ('row_id');
2505 assertStringArg ('name');
2506 assertUIntArg ('height');
2507 assertStringArg ('asset_no', TRUE);
2508 assertStringArg ('comment', TRUE);
2509 $taglist = genericAssertion ('taglist', 'array0');
2510 $rack_id = getBypassValue();
2511 usePreparedDeleteBlade ('RackThumbnail', array ('rack_id' => $rack_id));
2512 commitUpdateRack
2513 (
2514 $rack_id,
2515 $_REQUEST['row_id'],
2516 $_REQUEST['name'],
2517 $_REQUEST['height'],
2518 isCheckSet ('has_problems', 'yesno'),
2519 $_REQUEST['asset_no'],
2520 $_REQUEST['comment']
2521 );
2522 updateObjectAttributes ($rack_id);
2523 rebuildTagChainForEntity ('rack', $rack_id, buildTagChainFromIds ($taglist), TRUE);
2524 showFuncMessage (__FUNCTION__, 'OK', array ($_REQUEST['name']));
2525 }
2526
2527 $msgcode['deleteRack']['OK'] = 7;
2528 $msgcode['deleteRack']['ERR1'] = 206;
2529 function deleteRack ()
2530 {
2531 assertUIntArg ('rack_id');
2532 $rackData = spotEntity ('rack', $_REQUEST['rack_id']);
2533 amplifyCell ($rackData);
2534 if (count ($rackData['mountedObjects']))
2535 {
2536 showFuncMessage (__FUNCTION__, 'ERR1');
2537 return;
2538 }
2539 releaseFiles ('rack', $_REQUEST['rack_id']);
2540 destroyTagsForEntity ('rack', $_REQUEST['rack_id']);
2541 usePreparedDeleteBlade ('RackSpace', array ('rack_id' => $_REQUEST['rack_id']));
2542 commitDeleteObject ($_REQUEST['rack_id']);
2543 resetRackSortOrder ($rackData['row_id']);
2544 showFuncMessage (__FUNCTION__, 'OK', array ($rackData['name']));
2545 return buildRedirectURL ('rackspace', 'default');
2546 }
2547
2548 function updateRackDesign ()
2549 {
2550 $rackData = spotEntity ('rack', getBypassValue());
2551 amplifyCell ($rackData);
2552 applyRackDesignMask($rackData);
2553 if (processGridForm ($rackData, 'A', 'F'))
2554 showSuccess ("Saved successfully");
2555 else
2556 showNotice ("Nothing saved");
2557 }
2558
2559 function updateRackProblems ()
2560 {
2561 $rackData = spotEntity ('rack', getBypassValue());
2562 amplifyCell ($rackData);
2563 applyRackProblemMask($rackData);
2564 if (processGridForm ($rackData, 'F', 'U'))
2565 showSuccess ("Saved successfully");
2566 else
2567 showNotice ("Nothing saved");
2568 }
2569
2570 function querySNMPData ()
2571 {
2572 genericAssertion ('ver', 'uint');
2573 $snmpsetup = array ();
2574 switch ($_REQUEST['ver'])
2575 {
2576 case 1:
2577 case 2:
2578 genericAssertion ('community', 'string');
2579 $snmpsetup['community'] = $_REQUEST['community'];
2580 break;
2581 case 3:
2582 assertStringArg ('sec_name');
2583 assertStringArg ('sec_level');
2584 assertStringArg ('auth_protocol');
2585 assertStringArg ('auth_passphrase', TRUE);
2586 assertStringArg ('priv_protocol');
2587 assertStringArg ('priv_passphrase', TRUE);
2588
2589 $snmpsetup['sec_name'] = $_REQUEST['sec_name'];
2590 $snmpsetup['sec_level'] = $_REQUEST['sec_level'];
2591 $snmpsetup['auth_protocol'] = $_REQUEST['auth_protocol'];
2592 $snmpsetup['auth_passphrase'] = $_REQUEST['auth_passphrase'];
2593 $snmpsetup['priv_protocol'] = $_REQUEST['priv_protocol'];
2594 $snmpsetup['priv_passphrase'] = $_REQUEST['priv_passphrase'];
2595 break;
2596 default:
2597 throw new InvalidRequestArgException ('ver', $_REQUEST['ver']);
2598 }
2599 $snmpsetup['version'] = $_REQUEST['ver'];
2600 doSNMPmining (getBypassValue(), $snmpsetup); // shows message by itself
2601 }
2602
2603 $msgcode['addFileWithoutLink']['OK'] = 5;
2604 // File-related functions
2605 function addFileWithoutLink ()
2606 {
2607 assertStringArg ('comment', TRUE);
2608
2609 // Make sure the file can be uploaded
2610 if (get_cfg_var('file_uploads') != 1)
2611 throw new RackTablesError ('file uploads not allowed, change "file_uploads" parameter in php.ini', RackTablesError::MISCONFIGURED);
2612
2613 $fp = fopen($_FILES['file']['tmp_name'], 'rb');
2614 global $sic;
2615 $file_id = commitAddFile ($_FILES['file']['name'], $_FILES['file']['type'], $fp, $sic['comment']);
2616 if (isset ($_REQUEST['taglist']))
2617 produceTagsForNewRecord ('file', $_REQUEST['taglist'], $file_id);
2618 showFuncMessage (__FUNCTION__, 'OK', array (htmlspecialchars ($_FILES['file']['name'])));
2619 }
2620
2621 $msgcode['addFileToEntity']['OK'] = 5;
2622 $msgcode['addFileToEntity']['ERR1'] = 207;
2623 function addFileToEntity ()
2624 {
2625 global $pageno, $etype_by_pageno;
2626 if (!isset ($etype_by_pageno[$pageno]))
2627 throw new RackTablesError ('key not found in etype_by_pageno', RackTablesError::INTERNAL);
2628 $realm = $etype_by_pageno[$pageno];
2629 assertStringArg ('comment', TRUE);
2630
2631 // Make sure the file can be uploaded
2632 if (get_cfg_var('file_uploads') != 1)
2633 throw new RackTablesError ('file uploads not allowed, change "file_uploads" parameter in php.ini', RackTablesError::MISCONFIGURED);
2634
2635 // Exit if the upload failed
2636 if ($_FILES['file']['error'])
2637 {
2638 showFuncMessage (__FUNCTION__, 'ERR1', array ($_FILES['file']['error']));
2639 return;
2640 }
2641
2642 $fp = fopen($_FILES['file']['tmp_name'], 'rb');
2643 global $sic;
2644 commitAddFile ($_FILES['file']['name'], $_FILES['file']['type'], $fp, $sic['comment']);
2645 usePreparedInsertBlade
2646 (
2647 'FileLink',
2648 array
2649 (
2650 'file_id' => lastInsertID(),
2651 'entity_type' => $realm,
2652 'entity_id' => getBypassValue(),
2653 )
2654 );
2655 showFuncMessage (__FUNCTION__, 'OK', array (htmlspecialchars ($_FILES['file']['name'])));
2656 }
2657
2658 $msgcode['linkFileToEntity']['OK'] = 71;
2659 function linkFileToEntity ()
2660 {
2661 assertUIntArg ('file_id');
2662 global $pageno, $etype_by_pageno, $sic;
2663 if (!isset ($etype_by_pageno[$pageno]))
2664 throw new RackTablesError ('key not found in etype_by_pageno', RackTablesError::INTERNAL);
2665
2666 usePreparedInsertBlade
2667 (
2668 'FileLink',
2669 array
2670 (
2671 'file_id' => $sic['file_id'],
2672 'entity_type' => $etype_by_pageno[$pageno],
2673 'entity_id' => getBypassValue(),
2674 )
2675 );
2676 $fi = spotEntity ('file', $sic['file_id']);
2677 showFuncMessage (__FUNCTION__, 'OK', array (htmlspecialchars ($fi['name'])));
2678 }
2679
2680 $msgcode['replaceFile']['OK'] = 7;
2681 $msgcode['replaceFile']['ERR2'] = 201;
2682 function replaceFile ()
2683 {
2684 // Make sure the file can be uploaded
2685 if (get_cfg_var('file_uploads') != 1)
2686 throw new RackTablesError ('file uploads not allowed, change "file_uploads" parameter in php.ini', RackTablesError::MISCONFIGURED);
2687 $shortInfo = spotEntity ('file', getBypassValue());
2688
2689 if (FALSE === $fp = fopen ($_FILES['file']['tmp_name'], 'rb'))
2690 {
2691 showFuncMessage (__FUNCTION__, 'ERR2');
2692 return;
2693 }
2694 commitReplaceFile ($shortInfo['id'], $fp);
2695
2696 showFuncMessage (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
2697 }
2698
2699 $msgcode['unlinkFile']['OK'] = 72;
2700 function unlinkFile ()
2701 {
2702 assertUIntArg ('link_id');
2703 commitUnlinkFile ($_REQUEST['link_id']);
2704 showFuncMessage (__FUNCTION__, 'OK');
2705 }
2706
2707 $msgcode['deleteFile']['OK'] = 7;
2708 function deleteFile ()
2709 {
2710 assertUIntArg ('file_id');
2711 $shortInfo = spotEntity ('file', $_REQUEST['file_id']);
2712 commitDeleteFile ($_REQUEST['file_id']);
2713 showFuncMessage (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
2714 }
2715
2716 $msgcode['updateFileText']['OK'] = 6;
2717 $msgcode['updateFileText']['ERR1'] = 179;
2718 $msgcode['updateFileText']['ERR2'] = 155;
2719 function updateFileText ()
2720 {
2721 assertStringArg ('mtime_copy');
2722 assertStringArg ('file_text', TRUE); // it's Ok to save empty
2723 $shortInfo = spotEntity ('file', getBypassValue());
2724 if ($shortInfo['mtime'] != $_REQUEST['mtime_copy'])
2725 {
2726 showFuncMessage (__FUNCTION__, 'ERR1');
2727 return;
2728 }
2729 global $sic;
2730 commitReplaceFile ($shortInfo['id'], $sic['file_text']);
2731 showFuncMessage (__FUNCTION__, 'OK', array (htmlspecialchars ($shortInfo['name'])));
2732 }
2733
2734 $msgcode['addIIFOIFCompatPack']['OK'] = 37;
2735 function addIIFOIFCompatPack ()
2736 {
2737 genericAssertion ('standard', 'enum/wdmstd');
2738 genericAssertion ('iif_id', 'iif');
2739 global $wdm_packs, $sic;
2740 $ngood = 0;
2741 foreach ($wdm_packs[$sic['standard']]['oif_ids'] as $oif_id)
2742 {
2743 commitSupplementPIC ($sic['iif_id'], $oif_id);
2744 $ngood++;
2745 }
2746 showFuncMessage (__FUNCTION__, 'OK', array ($ngood));
2747 }
2748
2749 $msgcode['delIIFOIFCompatPack']['OK'] = 38;
2750 function delIIFOIFCompatPack ()
2751 {
2752 genericAssertion ('standard', 'enum/wdmstd');
2753 genericAssertion ('iif_id', 'iif');
2754 global $wdm_packs, $sic;
2755 $ngood = 0;
2756 foreach ($wdm_packs[$sic['standard']]['oif_ids'] as $oif_id)
2757 {
2758 usePreparedDeleteBlade ('PortInterfaceCompat', array ('iif_id' => $sic['iif_id'], 'oif_id' => $oif_id));
2759 $ngood++;
2760 }
2761 showFuncMessage (__FUNCTION__, 'OK', array ($ngood));
2762 }
2763
2764 $msgcode['addOIFCompatPack']['OK'] = 21;
2765 function addOIFCompatPack ()
2766 {
2767 genericAssertion ('standard', 'enum/wdmstd');
2768 global $wdm_packs;
2769 $oifs = $wdm_packs[$_REQUEST['standard']]['oif_ids'];
2770 foreach ($oifs as $oif_id_1)
2771 {
2772 $args = $qmarks = array();
2773 $query = 'REPLACE INTO PortCompat (type1, type2) VALUES ';
2774 foreach ($oifs as $oif_id_2)
2775 {
2776 $qmarks[] = '(?, ?)';
2777 $args[] = $oif_id_1;
2778 $args[] = $oif_id_2;
2779 }
2780 $query .= implode (', ', $qmarks);
2781 usePreparedExecuteBlade ($query, $args);
2782 }
2783 showFuncMessage (__FUNCTION__, 'OK');
2784 }
2785
2786 $msgcode['delOIFCompatPack']['OK'] = 21;
2787 function delOIFCompatPack ()
2788 {
2789 genericAssertion ('standard', 'enum/wdmstd');
2790 global $wdm_packs;
2791 $oifs = $wdm_packs[$_REQUEST['standard']]['oif_ids'];
2792 foreach ($oifs as $oif_id_1)
2793 foreach ($oifs as $oif_id_2)
2794 if ($oif_id_1 != $oif_id_2) # leave narrow-band mapping intact
2795 usePreparedDeleteBlade ('PortCompat', array ('type1' => $oif_id_1, 'type2' => $oif_id_2));
2796 showFuncMessage (__FUNCTION__, 'OK');
2797 }
2798
2799 $msgcode['add8021QOrder']['OK'] = 48;
2800 function add8021QOrder ()
2801 {
2802 assertUIntArg ('vdom_id');
2803 assertUIntArg ('object_id');
2804 assertUIntArg ('vst_id');
2805 global $sic, $pageno;
2806 fixContext();
2807 if ($pageno != 'object')
2808 spreadContext (spotEntity ('object', $sic['object_id']));
2809 if ($pageno != 'vst')
2810 spreadContext (spotEntity ('vst', $sic['vst_id']));
2811 assertPermission();
2812 usePreparedExecuteBlade
2813 (
2814 'INSERT INTO VLANSwitch (domain_id, object_id, template_id, last_change, out_of_sync) ' .
2815 'VALUES (?, ?, ?, NOW(), "yes")',
2816 array ($sic['vdom_id'], $sic['object_id'], $sic['vst_id'])
2817 );
2818 showFuncMessage (__FUNCTION__, 'OK');
2819 }
2820
2821 $msgcode['del8021QOrder']['OK'] = 49;
2822 function del8021QOrder ()
2823 {
2824 assertUIntArg ('object_id');
2825 assertUIntArg ('vdom_id');
2826 assertUIntArg ('vst_id');
2827 global $sic, $pageno;
2828 fixContext();
2829 if ($pageno != 'object')
2830 spreadContext (spotEntity ('object', $sic['object_id']));
2831 if ($pageno != 'vst')
2832 spreadContext (spotEntity ('vst', $sic['vst_id']));
2833 assertPermission();
2834 usePreparedDeleteBlade ('VLANSwitch', array ('object_id' => $sic['object_id']));
2835 $focus_hints = array
2836 (
2837 'prev_objid' => $_REQUEST['object_id'],
2838 'prev_vstid' => $_REQUEST['vst_id'],
2839 'prev_vdid' => $_REQUEST['vdom_id'],
2840 );
2841 showFuncMessage (__FUNCTION__, 'OK');
2842 return buildRedirectURL (NULL, NULL, $focus_hints);
2843 }
2844
2845 $msgcode['createVLANDomain']['OK'] = 48;
2846 function createVLANDomain ()
2847 {
2848 assertStringArg ('vdom_descr');
2849 global $sic;
2850 usePreparedInsertBlade
2851 (
2852 'VLANDomain',
2853 array
2854 (
2855 'description' => $sic['vdom_descr'],
2856 )
2857 );
2858 $domain_id = lastInsertID();
2859 lastCreated ('vdom', $domain_id);
2860 usePreparedInsertBlade
2861 (
2862 'VLANDescription',
2863 array
2864 (
2865 'domain_id' => $domain_id,
2866 'vlan_id' => VLAN_DFL_ID,
2867 'vlan_type' => 'compulsory',
2868 'vlan_descr' => 'default',
2869 )
2870 );
2871 showFuncMessage (__FUNCTION__, 'OK');
2872 }
2873
2874 function save8021QPorts ()
2875 {
2876 global $sic;
2877 assertUIntArg ('mutex_rev', TRUE); // counts from 0
2878 assertStringArg ('form_mode');
2879 if ($sic['form_mode'] != 'save' and $sic['form_mode'] != 'duplicate')
2880 throw new InvalidRequestArgException ('form_mode', $sic['form_mode']);
2881 $extra = array();
2882
2883 // prepare the $changes array
2884 $changes = array();
2885 switch ($sic['form_mode'])
2886 {
2887 case 'save':
2888 assertUIntArg ('nports');
2889 if ($sic['nports'] == 1)
2890 {
2891 assertStringArg ('pn_0');
2892 $extra = array ('port_name' => $sic['pn_0']);
2893 }
2894 for ($i = 0; $i < $sic['nports']; $i++)
2895 {
2896 assertStringArg ('pn_' . $i);
2897 assertStringArg ('pm_' . $i);
2898 // An access port only generates form input for its native VLAN,
2899 // which we derive allowed VLAN list from.
2900 $native = isset ($sic['pnv_' . $i]) ? $sic['pnv_' . $i] : 0;
2901 switch ($sic["pm_${i}"])
2902 {
2903 case 'trunk':
2904 # assertArrayArg ('pav_' . $i);
2905 $allowed = isset ($sic['pav_' . $i]) ? $sic['pav_' . $i] : array();
2906 break;
2907 case 'access':
2908 if ($native == 'same')
2909 continue 2;
2910 assertUIntArg ('pnv_' . $i);
2911 $allowed = array ($native);
2912 break;
2913 default:
2914 throw new InvalidRequestArgException ("pm_${i}", $_REQUEST["pm_${i}"], 'unknown port mode');
2915 }
2916 $changes[$sic['pn_' . $i]] = array
2917 (
2918 'mode' => $sic['pm_' . $i],
2919 'allowed' => $allowed,
2920 'native' => $native,
2921 );
2922 }
2923 break;
2924 case 'duplicate':
2925 assertStringArg ('from_port');
2926 # assertArrayArg ('to_ports');
2927 $before = getStored8021QConfig ($sic['object_id'], 'desired');
2928 if (!array_key_exists ($sic['from_port'], $before))
2929 throw new InvalidArgException ('from_port', $sic['from_port'], 'this port does not exist');
2930 foreach ($sic['to_ports'] as $tpn)
2931 if (!array_key_exists ($tpn, $before))
2932 throw new InvalidArgException ('to_ports[]', $tpn, 'this port does not exist');
2933 elseif ($tpn != $sic['from_port'])
2934 $changes[$tpn] = $before[$sic['from_port']];
2935 break;
2936 }
2937 apply8021qChangeRequest ($sic['object_id'], $changes, TRUE, $sic['mutex_rev']);
2938 return buildRedirectURL (NULL, NULL, $extra);
2939 }
2940
2941 $msgcode['bindVLANtoIPv4']['OK'] = 48;
2942 function bindVLANtoIPv4 ()
2943 {
2944 genericAssertion ('id', 'uint');
2945 genericAssertion ('vlan_ck', 'uint-vlan1');
2946 global $sic;
2947 commitSupplementVLANIPv4 ($sic['vlan_ck'], $sic['id']);
2948 showFuncMessage (__FUNCTION__, 'OK');
2949 }
2950
2951 $msgcode['bindVLANtoIPv6']['OK'] = 48;
2952 function bindVLANtoIPv6 ()
2953 {
2954 genericAssertion ('id', 'uint');
2955 genericAssertion ('vlan_ck', 'uint-vlan1');
2956 global $sic;
2957 commitSupplementVLANIPv6 ($sic['vlan_ck'], $_REQUEST['id']);
2958 showFuncMessage (__FUNCTION__, 'OK');
2959 }
2960
2961 $msgcode['unbindVLANfromIPv4']['OK&apos