]> git.ipfire.org Git - people/stevee/network.git/blob - src/functions/functions.zone
zone: fix zone_config()
[people/stevee/network.git] / src / functions / functions.zone
1 #!/bin/bash
2 ###############################################################################
3 # #
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2010 Michael Tremer & Christian Schmidt #
6 # #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
11 # #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
16 # #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 # #
20 ###############################################################################
21
22 zone_dir() {
23 local zone=${1}
24
25 echo "${NETWORK_ZONE_DIR}/zones/${zone}"
26 }
27
28 zone_exists() {
29 local zone=${1}
30 assert isset zone
31
32 [ -d "$(zone_dir ${zone})" ]
33 }
34
35 zone_match() {
36 local match
37
38 local i
39 for i in ${VALID_ZONES}; do
40 match="${match}|${i}[0-9]{1,5}"
41 done
42
43 echo "${match:1:${#match}}"
44 }
45
46 zone_name_is_valid() {
47 local zone=${1}
48
49 # Don't accept empty strings.
50 [ -z "${zone}" ] && return ${EXIT_FALSE}
51
52 [[ ${zone} =~ $(zone_match) ]]
53 }
54
55 zone_is_local() {
56 local zone=${1}
57
58 [[ "${zone:0:${#ZONE_LOCAL}}" = "${ZONE_LOCAL}" ]]
59 }
60
61 zone_is_nonlocal() {
62 local zone=${1}
63
64 [[ "${zone:0:${#ZONE_NONLOCAL}}" = "${ZONE_NONLOCAL}" ]]
65 }
66
67 zone_get_hook() {
68 local zone=${1}
69 assert isset zone
70
71 config_get_hook $(zone_dir ${zone})/settings
72 }
73
74 zone_start() {
75 # This function will bring up the zone
76 # 'asynchronously' with help of systemd.
77
78 local zone=${1}
79 assert zone_exists ${zone}
80
81 service_start "network@${zone}.service"
82 }
83
84 zone_start_auto() {
85 local zone="${1}"
86 assert zone_exists "${zone}"
87
88 # If the zone has already been started, we
89 # will reload it so the current configuration
90 # is re-applied.
91 if zone_is_active "${zone}"; then
92 zone_reload "${zone}"
93 return ${?}
94
95 # If the zone is still down, but in auto-start mode,
96 # we will start it.
97 elif zone_is_enabled "${zone}"; then
98 zone_start "${zone}"
99 return ${?}
100 fi
101
102 # Otherwise, nothing will be done.
103 return ${EXIT_OK}
104 }
105
106 zone_stop() {
107 # This function will bring down the zone
108 # 'asynchronously' with help of systemd.
109
110 local zone=${1}
111 assert zone_exists ${zone}
112
113 service_stop "network@${zone}.service"
114 }
115
116 zone_reload() {
117 local zone="${1}"
118 assert zone_exists "${zone}"
119
120 service_reload "network@${zone}.service"
121 }
122
123 zone_hotplug_event() {
124 local zone="${1}"
125 assert isset zone
126
127 hotplug_assert_in_hotplug_event
128
129 zone_cmd "hotplug" "${zone}"
130 }
131
132 zone_enable() {
133 # This function will enable the zone
134 # with help of systemd.
135
136 local zone="${1}"
137 assert zone_exists "${zone}"
138
139 # Enable service for the zone
140 service_enable "network@${zone}.service"
141 local ret=$?
142
143 if [ ${ret} -eq ${EXIT_OK} ]; then
144 log INFO "Auto-start enabled for zone ${zone}"
145 return ${EXIT_OK}
146 fi
147
148 log ERROR "Could not enable zone ${zone}: ${ret}"
149 return ${ret}
150 }
151
152 zone_disable() {
153 # This function will disable the zone
154 # with help of systemd.
155
156 local zone="${1}"
157 assert zone_exists "${zone}"
158
159 # Disable service for the zone
160 service_disable "network@${zone}.service"
161 local ret=$?
162
163 if [ ${ret} -eq ${EXIT_OK} ]; then
164 log INFO "Auto-start disabled for zone ${zone}"
165 return ${EXIT_OK}
166 fi
167
168 log ERROR "Could not disable zone ${zone}: ${ret}"
169 return ${ret}
170 }
171
172 zone_is_enabled() {
173 local zone="${1}"
174 assert isset zone
175
176 # Ask systemd if the zone is enabled.
177 if service_is_enabled "network@${zone}.service"; then
178 return ${EXIT_TRUE}
179 fi
180
181 return ${EXIT_FALSE}
182 }
183
184 zone_is_active() {
185 local zone="${1}"
186 assert isset zone
187
188 if service_is_active "network@${zone}.service"; then
189 return ${EXIT_TRUE}
190 fi
191
192 return ${EXIT_FALSE}
193 }
194
195 zone_is_enabled_or_active() {
196 local zone="${1}"
197 assert isset zone
198
199 zone_is_enabled "${zone}" || zone_is_active "${zone}"
200 }
201
202 zone_cmd() {
203 local cmd="${1}"
204 local port="${2}"
205 shift 2
206
207 assert isset cmd
208 assert isset zone
209
210 local hook="$(zone_get_hook ${zone})"
211 assert isset hook
212
213 hook_exec zone "${hook}" "${cmd}" "${zone}" $@
214 }
215
216 zone_new() {
217 local zone=${1}
218 local hook=${2}
219 shift 2
220
221 if ! zone_name_is_valid ${zone}; then
222 error "Zone name '${zone}' is not valid."
223 return ${EXIT_ERROR}
224 fi
225
226 if zone_exists ${zone}; then
227 error "Zone '${zone}' does already exist."
228 return ${EXIT_ERROR}
229 fi
230
231 if ! hook_zone_exists ${hook}; then
232 error "Hook '${hook}' does not exist."
233 return ${EXIT_ERROR}
234 fi
235
236 mkdir -p $(zone_dir ${zone})
237
238 # Create directories for configs and ports
239 mkdir -p $(zone_dir ${zone})/{configs,ports}
240
241 hook_zone_exec "${hook}" "new" "${zone}" $@
242 local ret=$?
243
244 # Maybe the zone new hook did not exit correctly.
245 # If this is the case we remove the created zone immediately.
246 if [ "${ret}" = "${EXIT_ERROR}" ]; then
247 zone_destroy_now "${zone}"
248 return ${EXIT_ERROR}
249 fi
250
251 # Automatically enable zone.
252 zone_enable "${zone}"
253
254 # Bring up the zone immediately after
255 zone_start "${zone}"
256 }
257
258 zone_edit() {
259 local zone=${1}
260 shift
261
262 if ! zone_exists ${zone}; then
263 error "Zone '${zone}' does not exist."
264 return ${EXIT_ERROR}
265 fi
266
267 # Check if the zone is tagged for removal.
268 if zone_has_destroy_tag ${zone}; then
269 error "You cannot edit a zone that is tagged for removal."
270 return ${EXIT_ERROR}
271 fi
272
273 local hook="$(zone_get_hook "${zone}")"
274 if [ -z "${hook}" ]; then
275 error "Config file did not provide any hook."
276 return ${EXIT_ERROR}
277 fi
278
279 if ! hook_zone_exists ${hook}; then
280 error "Hook '${hook}' does not exist."
281 return ${EXIT_ERROR}
282 fi
283
284 hook_zone_exec ${hook} edit ${zone} $@
285 }
286
287 zone_rename() {
288 assert [ $# -eq 2 ]
289
290 local zone="${1}"
291 local name="${2}"
292
293 assert zone_exists "${zone}"
294 assert not zone_has_destroy_tag "${zone}"
295 assert not zone_exists "${name}"
296
297 # The zone must be shut down before, is then renamed and
298 # potentially brought up again
299
300 # Save if the zone is running right now
301 zone_is_active "${zone}"
302 local zone_was_active="${?}"
303
304 # Save if the zone is enabled (i.e. auto-start)
305 zone_is_enabled "${zone}"
306 local zone_was_enabled="${?}"
307
308 # Stop the zone
309 zone_stop "${zone}"
310
311 # Disable the zone
312 zone_disable "${zone}"
313
314 # Rename the configuration files
315 mv -f "$(zone_dir "${zone}")" "$(zone_dir "${name}")"
316
317 # Enable the zone if it was enabled before
318 [ ${zone_was_enabled} -eq ${EXIT_TRUE} ] && zone_enable "${name}"
319
320 # Start the zone if it was up before
321 [ ${zone_was_active} -eq ${EXIT_TRUE} ] && zone_start "${name}"
322
323 log INFO "Zone ${zone} was renamed to ${name}"
324 return ${EXIT_OK}
325 }
326
327
328 zone_destroy() {
329 local zone="${1}"
330 assert zone_exists "${zone}"
331
332 # Make the zone for removal.
333 touch "$(zone_dir "${zone}")/.destroy"
334
335 log INFO "Zone '${zone}' has been tagged for removal."
336 }
337
338 zone_has_destroy_tag() {
339 local zone="${1}"
340 assert zone_exists "${zone}"
341
342 [ -e "$(zone_dir "${zone}")/.destroy" ]
343 }
344
345 # This function will remove the given zone
346 # RIGHT NOW. Use zone_destroy to remove it
347 # at the next status change.
348 zone_destroy_now() {
349 local zone="${1}"
350 assert zone_exists "${zone}"
351
352 log INFO "Removing zone '${zone}' right now."
353
354 # Force the zone down.
355 zone_is_active "${zone}" && zone_stop "${zone}"
356
357 # Disable zone.
358 zone_disable "${zone}"
359
360 rm -rf "$(zone_dir "${zone}")"
361 }
362
363 zone_up() {
364 local zone=${1}
365 shift
366
367 if ! zone_exists ${zone}; then
368 error "Zone '${zone}' does not exist."
369 return ${EXIT_ERROR}
370 fi
371
372 # Check if a zone has got the remove tag.
373 if zone_has_destroy_tag ${zone}; then
374 error "Cannot bring up any zone which is to be removed."
375 return ${EXIT_ERROR}
376 fi
377
378 local hook="$(zone_get_hook "${zone}")"
379 if [ -z "${hook}" ]; then
380 error "Config file did not provide any hook."
381 return ${EXIT_ERROR}
382 fi
383
384 if ! hook_zone_exists ${hook}; then
385 error "Hook '${hook}' does not exist."
386 return ${EXIT_ERROR}
387 fi
388
389 zone_db ${zone} starting
390
391 hook_zone_exec ${hook} up ${zone} $@
392
393 zone_db ${zone} started
394
395 # Execute all triggers after the zone got up
396 triggers_execute_all "up" ZONE="${zone}"
397 }
398
399 zone_down() {
400 local zone=${1}
401 shift
402
403 if ! zone_exists ${zone}; then
404 error "Zone '${zone}' does not exist."
405 return ${EXIT_ERROR}
406 fi
407
408 local hook="$(zone_get_hook "${zone}")"
409 if [ -z "${hook}" ]; then
410 error "Config file did not provide any hook."
411 return ${EXIT_ERROR}
412 fi
413
414 if ! hook_zone_exists ${hook}; then
415 error "Hook '${hook}' does not exist."
416 return ${EXIT_ERROR}
417 fi
418
419 zone_db ${zone} stopping
420
421 hook_zone_exec ${hook} down ${zone} $@
422
423 zone_db ${zone} stopped
424
425 # Execute all triggers after the zone went down
426 triggers_execute_all "down" ZONE="${zone}"
427
428 # Remove the zone, if it has got a remove tag.
429 if zone_has_destroy_tag "${zone}"; then
430 zone_destroy_now "${zone}"
431 fi
432 }
433
434 zone_status() {
435 local zone="${1}"
436 assert isset zone
437 shift
438
439 if ! zone_exists "${zone}"; then
440 error "Zone '${zone}' does not exist."
441 return ${EXIT_ERROR}
442 fi
443
444 local hook="$(zone_get_hook "${zone}")"
445 if [ -z "${hook}" ]; then
446 error "Config file did not provide any hook."
447 return ${EXIT_ERROR}
448 fi
449
450 if ! hook_zone_exists "${hook}"; then
451 error "Hook '${hook}' does not exist."
452 return ${EXIT_ERROR}
453 fi
454
455 hook_zone_exec "${hook}" "status" "${zone}" "$@"
456
457 # Show that the zone it to be removed soon.
458 if zone_has_destroy_tag ${zone}; then
459 warning "This zone is tagged for removal."
460 fi
461 }
462
463 zone_identify() {
464 assert [ $# -ge 1 ]
465
466 local zone="${1}"
467 shift
468
469 assert zone_exists "${zone}"
470
471 log INFO "Identifying zone ${zone}"
472 local pids
473
474 local pid
475 local port
476 for port in $(zone_get_ports "${zone}"); do
477 # Identify all the ports
478 port_identify "${port}" --background $@
479
480 # Save the PIDs of the subprocesses
481 list_append pids "$(cmd_background_get_pid)"
482 done
483
484 # Wait until all port_identfy processes have finished
485 for pid in ${pids}; do
486 cmd_background_result "${pid}"
487 done
488
489 return ${EXIT_OK}
490 }
491
492 zone_get_ports() {
493 local zone=${1}
494
495 assert isset zone
496
497 local port
498 for port in $(zone_dir ${zone})/ports/*; do
499 port=$(basename ${port})
500
501 if port_exists ${port}; then
502 echo "${port}"
503 fi
504 done
505 }
506
507 zone_get_ports_num() {
508 local zone="${1}"
509 assert isset zone
510
511 local counter=0
512 local port
513 for port in $(zone_dir "${zone}")/ports/*; do
514 port="$(basename "${port}")"
515
516 if port_exists "${port}"; then
517 counter=$(( ${counter} + 1 ))
518 fi
519 done
520
521 echo "${counter}"
522 return ${EXIT_OK}
523 }
524
525 zone_has_port() {
526 # Check, if the given port is configured
527 # in this zone.
528
529 local zone=${1}
530 local port=${2}
531 shift 2
532
533 assert isset zone
534 assert isset port
535
536 [ -e "$(zone_dir ${zone})/ports/${port}" ]
537 }
538
539 zone_config() {
540 local zone="${1}"
541 local cmd="${2}"
542 shift 2
543
544 assert isset zone
545 assert isset cmd
546 assert zone_exists "${zone}"
547
548 case "${cmd}" in
549 new)
550 zone_config_new "${zone}" "$@"
551 ;;
552 destroy)
553 local id=${1}
554 if zone_config_id_is_valid ${zone} ${id}; then
555 zone_config_destroy "${zone}" "$@"
556 else
557 log ERROR "${id} is not a valid id"
558 fi
559 ;;
560 list)
561 zone_config_list "${zone}" "$@"
562 ;;
563 *)
564 # Check is we get a valid id
565 # TODO This could be also a valid hid
566 local id=${cmd}
567
568 if zone_config_id_is_valid ${zone} ${id} && [[ ${1} == "edit" ]]; then
569 shift 1
570 zone_config_edit "${zone}" "${id}" "$@"
571 else
572 error "Unrecognized argument: ${cmd}"
573 cli_usage root-zone-config-subcommands
574 exit ${EXIT_ERROR}
575 fi
576 ;;
577 esac
578 }
579
580 zone_config_cmd() {
581 assert [ $# -gt 2 ]
582
583 local cmd="${1}"
584 local zone="${2}"
585 shift 2
586
587 local hook="$(zone_get_hook "${zone}")"
588 assert isset hook
589
590 hook_zone_exec "${hook}" "config_${cmd}" "${zone}" "$@"
591 }
592
593 zone_config_new() {
594 local zone="${1}"
595 shift
596
597 # Create a new configuration, but exit when that was
598 # not successful.
599 zone_config_cmd "new" "${zone}" "$@" || return ${?}
600
601 # If the config could be created, we will try to bring
602 # it up if the zone is up, too.
603 if zone_is_up "${zone}"; then
604 zone_configs_up "${zone}"
605 fi
606 }
607
608 zone_config_destroy() {
609 zone_config_cmd "destroy" "$@"
610 }
611
612 zone_config_edit() {
613 zone_config_cmd "edit" "$@"
614 }
615
616 zone_config_list() {
617 # This function list in an nice way all configs of a zone
618 local zone=${1}
619 assert isset zone
620
621 # Print a nice header
622 local format="%-3s %-20s"
623 print "${format}" "ID" "HOOK"
624
625 local config
626 local hook
627 local id
628
629 # Print for all config:
630 # id and hook
631 # TODO: Add hids here
632 for config in $(zone_configs_list "${zone}"); do
633 id=${config##*.}
634 hook=$(zone_config_get_hook "${zone}" "${config}")
635 assert isset hook
636 print "${format}" "${id}" "${hook}"
637 done
638 }
639
640 zone_config_show() {
641 zone_config_cmd "show" "$@"
642 }
643
644 zone_show() {
645 local zone=${1}
646
647 echo "${zone}"
648 echo " Type: $(zone_get_hook ${zone})"
649 echo
650 }
651
652 zones_show() {
653 local zone
654
655 for zone in $(zones_get $@); do
656 zone_show ${zone}
657 done
658 }
659
660 zones_get_all() {
661 local zone
662 for zone in $(zone_dir)/*; do
663 zone=$(basename ${zone})
664 zone_exists ${zone} || continue
665
666 echo "${zone}"
667 done
668 }
669
670 zones_get_next_free() {
671 # This function return the next free zones.
672 # Example net0 upl0 upl1 are configured so the next free zones are:
673 # net1 upl2
674 local i
675 local zone_name
676 for zone_name in ${VALID_ZONES}; do
677 i=0
678
679 while true; do
680 local zone="${zone_name}${i}"
681 if ! zone_exists ${zone}; then
682 echo "${zone}"
683 break
684 fi
685 i=$(( i + 1 ))
686 done
687 done
688 }
689
690 zones_get_local() {
691 local zone
692 for zone in $(zones_get_all); do
693 zone_is_local ${zone} && echo "${zone}"
694 done
695 }
696
697 zones_get_nonlocal() {
698 local zone
699 for zone in $(zones_get_all); do
700 zone_is_nonlocal ${zone} && echo "${zone}"
701 done
702 }
703
704 zones_get() {
705 local local=1
706 local remote=1
707
708 local zones
709
710 while [ $# -gt 0 ]; do
711 case "${1}" in
712 --local-only)
713 local=1
714 remote=0
715 ;;
716 --remote-only)
717 local=0
718 remote=1
719 ;;
720 --all)
721 local=1
722 remote=1
723 ;;
724 *)
725 if zone_name_is_valid ${1}; then
726 zones="${zones} ${1}"
727 else
728 warning "Unrecognized argument '${1}'"
729 fi
730 ;;
731 esac
732 shift
733 done
734
735 if [ -n "${zones}" ]; then
736 local zone
737 for zone in ${zones}; do
738 zone_exists ${zone} && echo "${zone}"
739 done
740 exit ${EXIT_OK}
741 fi
742
743 if [ ${local} -eq 1 ] && [ ${remote} -eq 1 ]; then
744 zones_get_all
745 elif [ ${local} -eq 1 ]; then
746 zones_get_local
747 elif [ ${remote} -eq 1 ]; then
748 zones_get_nonlocal
749 fi
750 }
751
752 zone_ports_list() {
753 local zone=${1}
754
755 local port
756 for port in $(zone_dir ${zone})/ports/*; do
757 [ -e "${port}" ] || continue
758
759 echo $(basename ${port})
760 done
761 }
762
763 zone_port_attach() {
764 local zone="${1}"
765 assert isset zone
766
767 local port="${2}"
768 assert isset port
769
770 shift 2
771
772 # Check if the port actually exists.
773 if ! port_exists "${port}"; then
774 error "Cannot attach port '${port}' which does not exist"
775 return ${EXIT_ERROR}
776 fi
777
778 # Check if the port is already connected to this or any other zone.
779 local z
780 for z in $(zones_get_all); do
781 if zone_has_port "${z}" "${port}"; then
782 error "Port '${port}' is already attached to zone '${z}'"
783 return ${EXIT_ERROR}
784 fi
785 done
786
787 local hook="$(zone_get_hook "${zone}")"
788 assert isset hook
789
790 # Make the port briefly flash if supported
791 if device_exists ${port}; then
792 port_identify "${port}" --background
793 fi
794
795 hook_zone_exec "${hook}" "port_attach" "${zone}" "${port}" "$@"
796 local ret="${?}"
797
798 case "${ret}" in
799 ${EXIT_OK})
800 log INFO "${port} has been attached to ${zone}"
801
802 # Automatically connect the port
803 zone_port_start "${zone}" "${port}"
804 ;;
805 *)
806 log CRITICAL "${port} could not be attached to ${zone}"
807 ;;
808 esac
809
810 return ${ret}
811 }
812
813 zone_port_edit() {
814 local zone="${1}"
815 assert isset zone
816
817 local port="${2}"
818 assert isset port
819
820 shift 2
821
822 # Check if the port actually exists.
823 if ! port_exists "${port}"; then
824 error "Port '${port}' does not exist"
825 return ${EXIT_ERROR}
826 fi
827
828 # Check if the zone actually has this port.
829 if ! zone_has_port "${zone}" "${port}"; then
830 error "Port '${port}' is not attached to zone '${zone}'"
831 return ${EXIT_ERROR}
832 fi
833
834 local hook=$(zone_get_hook "${zone}")
835 assert isset hook
836
837 hook_zone_exec "${hook}" "port_edit" "${zone}" "${port}" "$@"
838 }
839
840 zone_port_detach() {
841 local zone="${1}"
842 assert isset zone
843
844 local port="${2}"
845 assert isset port
846
847 shift 2
848
849 # Check if the zone actually has this port.
850 if ! zone_has_port "${zone}" "${port}"; then
851 error "Port '${port}' is not attached to zone '${zone}'"
852 return ${EXIT_ERROR}
853 fi
854
855 local hook=$(zone_get_hook "${zone}")
856 assert isset hook
857
858 # Make the port briefly flash if supported
859 port_identify "${port}" --background
860
861 hook_zone_exec "${hook}" "port_detach" "${zone}" "${port}" "$@"
862 local ret="${?}"
863
864 case "${ret}" in
865 ${EXIT_OK})
866 log INFO "${port} has been detached from ${zone}"
867
868 # Bring down the port if needed
869 zone_port_stop "${zone}" "${port}"
870 ;;
871 *)
872 log CRITICAL "${port} could not be detached from ${zone}"
873 ;;
874 esac
875
876 return ${ret}
877 }
878
879 zone_port_cmd() {
880 local cmd="${1}"
881 assert isset cmd
882
883 local zone="${2}"
884 assert isset zone
885
886 local port="${3}"
887 assert isset port
888
889 shift 3
890
891 local hook="$(zone_get_hook "${zone}")"
892 assert isset hook
893
894 # Dispatch command to hook
895 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" $@
896 }
897
898 zone_port_create() {
899 zone_port_cmd "port_create" $@
900 }
901
902 zone_port_remove() {
903 zone_port_cmd "port_remove" $@
904 }
905
906 zone_port_up() {
907 zone_port_cmd "port_up" $@
908 }
909
910 zone_port_down() {
911 zone_port_cmd "port_down" $@
912 }
913
914 # The next two functions automagically bring up and down
915 # port that are attached to a bridge or similar.
916 # The problem that is tried to overcome here is that there
917 # are ports which exist all the time (like ethernet ports)
918 # and therefore do not dispatch a hotplug event when
919 # port_create is called.
920
921 zone_port_start() {
922 local zone="${1}"
923 local port="${2}"
924
925 if zone_is_active "${zone}"; then
926 if device_exists "${port}"; then
927 zone_port_up "${zone}" "${port}"
928 return ${?}
929 else
930 zone_port_create "${zone}" "${port}"
931 return ${?}
932 fi
933 fi
934
935 return ${EXIT_OK}
936 }
937
938 zone_port_stop() {
939 local zone="${1}"
940 local port="${2}"
941
942 # Shut down the port if necessary
943 if zone_is_active "${zone}" && port_is_up "${port}"; then
944 zone_port_down "${zone}" "${port}"
945 fi
946
947 # Remove the port
948 zone_port_remove "${zone}" "${port}"
949 }
950
951 zone_port_status() {
952 zone_port_cmd "port_status" $@
953 }
954
955 zone_ports_cmd() {
956 local cmd="${1}"
957 assert isset cmd
958
959 local zone="${2}"
960 assert isset zone
961
962 shift 2
963
964 local hook="$(zone_get_hook "${zone}")"
965
966 local port
967 for port in $(zone_get_ports ${zone}); do
968 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" $@
969 done
970 }
971
972 zone_ports_create() {
973 zone_ports_cmd "port_create" $@
974 }
975
976 zone_ports_remove() {
977 zone_ports_cmd "port_remove" $@
978 }
979
980 zone_ports_up() {
981 zone_ports_cmd "port_up" $@
982 }
983
984 zone_ports_down() {
985 zone_ports_cmd "port_down" $@
986 }
987
988 zone_ports_status() {
989 zone_ports_cmd "port_status" $@
990 }
991
992 zone_configs_cmd() {
993 assert [ $# -ge 2 ]
994
995 local cmd="${1}"
996 local zone="${2}"
997 shift 2
998
999 assert zone_exists "${zone}"
1000
1001 local config
1002 for config in $(zone_configs_list "${zone}"); do
1003 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1004 assert isset config_hook
1005
1006 hook_config_exec "${config_hook}" "${cmd}" "${zone}" "${config}" $@
1007 done
1008 }
1009
1010 zone_configs_up() {
1011 zone_configs_cmd "up" $@
1012 }
1013
1014 zone_configs_down() {
1015 zone_configs_cmd "down" $@
1016 }
1017
1018 zone_configs_status() {
1019 zone_configs_cmd "status" $@
1020 }
1021
1022 zone_configs_list() {
1023 local zone=${1}
1024
1025 local config
1026 for config in $(zone_dir ${zone})/configs/*; do
1027 [ -e "${config}" ] || continue
1028
1029 basename ${config}
1030 done
1031 }
1032
1033 zone_config_get_new_id() {
1034 # This functions returns the next free id for a zone
1035
1036 assert [ $# -eq 1 ]
1037 local zone=${1}
1038
1039 local zone_path=$(zone_dir ${zone})
1040 local i=0
1041
1042 while true; do
1043 if [ ! -f ${zone_path}/configs/*.${i} ]; then
1044 echo "${i}"
1045 return ${EXIT_OK}
1046 fi
1047 (( i++ ))
1048 done
1049 }
1050
1051 zone_config_get_hook() {
1052 assert [ $# -eq 2 ]
1053
1054 local zone="${1}"
1055 assert isset zone
1056
1057 local config="${2}"
1058 assert isset config
1059
1060 local HOOK
1061 zone_config_settings_read "${zone}" "${config}" \
1062 --ignore-superfluous-settings HOOK
1063
1064 print "${HOOK}"
1065 }
1066
1067 zone_config_hook_is_configured() {
1068 # Checks if a zone has already at least one config with the given hook.
1069 # Returns True when yes and False when no
1070
1071 assert [ $# -eq 2 ]
1072 local zone=${1}
1073 local hook=${2}
1074
1075 local config
1076 for config in $(zone_configs_list "${zone}"); do
1077 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1078 assert isset config_hook
1079 if [[ ${hook} == ${config_hook} ]]; then
1080 return ${EXIT_TRUE}
1081 fi
1082
1083 done
1084
1085 # If we get here the zone has no config with the given hook
1086 return ${EXIT_FALSE}
1087 }
1088
1089 zone_config_id_is_valid() {
1090 # This function checks if a given id is valid for a zone
1091 # Return True when yes and false when no
1092
1093 assert [ $# -eq 2 ]
1094 local zone=${1}
1095 local id=${2}
1096
1097 local zone_path=$(zone_dir ${zone})
1098
1099 [ -f ${zone_path}/configs/*.${id} ];
1100 }
1101
1102 zone_config_get_hook_from_id() {
1103 # Returns the hook for a given id
1104 assert [ $# -eq 2 ]
1105 local zone=${1}
1106 local id=${2}
1107
1108 local config
1109 for config in $(zone_configs_list "${zone}"); do
1110 if [[ ${config} == *.${id} ]]; then
1111 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1112 assert isset config_hook
1113 print "${config_hook}"
1114 return "${EXIT_OK}"
1115 fi
1116 done
1117
1118 # If we get here the zone has no config with the given id
1119 return ${EXIT_ERROR}
1120 }
1121
1122 zone_has_ip() {
1123 device_has_ip $@
1124 }
1125
1126 zone_db() {
1127 local zone=${1}
1128 local action=${2}
1129 shift 2
1130
1131 case "${action}" in
1132 starting|started|stopping|stopped)
1133 db_connection_update ${zone} ${action}
1134 ;;
1135 esac
1136 }
1137
1138 zone_is_up() {
1139 local zone=${1}
1140
1141 device_is_up ${zone}
1142 }
1143
1144 zone_is_down() {
1145 ! zone_is_up $@
1146 }
1147
1148 zone_get_supported_port_hooks() {
1149 local zone=${1}
1150
1151 local hook=$(zone_get_hook ${zone})
1152
1153 hook_zone_ports_get_all ${hook}
1154 }
1155
1156 zone_get_supported_config_hooks() {
1157 hook_config_get_all
1158 }
1159
1160 zone_file() {
1161 local zone=${1}
1162
1163 assert isset zone
1164
1165 echo "$(zone_dir ${zone})/settings"
1166 }
1167
1168 zone_settings_read() {
1169 local zone=${1}
1170 assert isset zone
1171 shift
1172
1173 local args
1174 if [ $# -eq 0 ] && [ -n "${HOOK_SETTINGS}" ]; then
1175 list_append args ${HOOK_SETTINGS}
1176 else
1177 list_append args $@
1178 fi
1179
1180 # Save the HOOK variable.
1181 local hook="${HOOK}"
1182
1183 settings_read "$(zone_file "${zone}")" ${args}
1184
1185 # Restore hook.
1186 HOOK="${hook}"
1187 }
1188
1189 zone_settings_write() {
1190 local zone="${1}"
1191 assert isset zone
1192
1193 local args
1194 if function_exists "hook_check_settings"; then
1195 list_append args "--check=\"hook_check_settings\""
1196 fi
1197 list_append args ${HOOK_SETTINGS}
1198
1199 settings_write "$(zone_file ${zone})" ${args}
1200 }
1201
1202 zone_settings_set() {
1203 local zone=${1}
1204 shift
1205 local args="$@"
1206
1207 assert isset zone
1208
1209 (
1210 zone_settings_read ${zone}
1211
1212 for arg in ${args}; do
1213 eval "${arg}"
1214 done
1215
1216 zone_settings_write ${zone}
1217 )
1218 }
1219
1220 zone_settings_get() {
1221 local zone=${1}
1222 local key=${2}
1223
1224 assert isset zone
1225 assert isset key
1226
1227 (
1228 zone_settings_read "${zone}" "${key}" \
1229 --ignore-superfluous-settings
1230
1231 echo "${!key}"
1232 )
1233 }
1234
1235 zone_config_settings_read() {
1236 assert [ $# -ge 2 ]
1237
1238 local zone="${1}"
1239 local config="${2}"
1240 shift 2
1241
1242 local args
1243 if [ $# -eq 0 ] && [ -n "${HOOK_CONFIG_SETTINGS}" ]; then
1244 list_append args ${HOOK_CONFIG_SETTINGS}
1245 else
1246 list_append args $@
1247 fi
1248
1249 local path="$(zone_dir "${zone}")/configs/${config}"
1250 settings_read "${path}" ${args}
1251 }
1252
1253 zone_config_settings_write() {
1254 assert [ $# -ge 2 ]
1255
1256 local zone="${1}"
1257 local hook="${2}"
1258 local id=${3}
1259
1260 if ! isset id; then
1261 id=$(zone_config_get_new_id ${zone})
1262 log DEBUG "ID for the config is: ${id}"
1263 fi
1264
1265 local args
1266 if function_exists "hook_check_config_settings"; then
1267 list_append args "--check=\"hook_check_config_settings\""
1268 fi
1269 list_append args ${HOOK_CONFIG_SETTINGS}
1270
1271 local path="$(zone_dir "${zone}")/configs/${hook}.${id}"
1272 settings_write "${path}" ${args}
1273 }
1274
1275 zone_port_settings_read() {
1276 assert [ $# -ge 2 ]
1277
1278 local zone="${1}"
1279 local port="${2}"
1280 shift 2
1281
1282 local args
1283 if [ $# -eq 0 ] && [ -n "${HOOK_PORT_SETTINGS}" ]; then
1284 list_append args ${HOOK_PORT_SETTINGS}
1285 else
1286 list_append args $@
1287 fi
1288
1289 local path="$(zone_dir "${zone}")/ports/${port}"
1290 settings_read "${path}" ${args}
1291 }
1292
1293 zone_port_settings_write() {
1294 assert [ $# -ge 2 ]
1295
1296 local zone="${1}"
1297 local port="${2}"
1298 shift 2
1299
1300 local args
1301 if function_exists "hook_check_port_settings"; then
1302 list_append args "--check=\"hook_check_port_settings\""
1303 fi
1304 list_append args ${HOOK_PORT_SETTINGS}
1305
1306 local path="$(zone_dir "${zone}")/ports/${port}"
1307 settings_write "${path}" ${args}
1308 }
1309
1310 zone_port_settings_remove() {
1311 assert [ $# -eq 2 ]
1312
1313 local zone="${1}"
1314 local port="${2}"
1315
1316 local path="$(zone_dir "${zone}")/ports/${port}"
1317 settings_remove "${path}"
1318 }
1319
1320 zone_get_color() {
1321 # This function return the color of a zone
1322 assert [ $# -eq 1 ]
1323
1324 local name=${1}
1325 color_read "zone" ${name}
1326 }
1327
1328 zone_get_description_title() {
1329 assert [ $# -eq 1 ]
1330
1331 local name=${1}
1332 description_title_read $(description_format_filename "zone" "${name}")
1333 }