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