]> git.ipfire.org Git - people/ms/network.git/blame - src/functions/functions.zone
zone: add config hid functions
[people/ms/network.git] / src / functions / functions.zone
CommitLineData
1848564d
MT
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
1c6a4e30 22zone_dir() {
1848564d
MT
23 local zone=${1}
24
d2a21d01 25 echo "${NETWORK_ZONE_DIR}/zones/${zone}"
1848564d
MT
26}
27
1c6a4e30 28zone_exists() {
1848564d 29 local zone=${1}
711ffac1
MT
30 assert isset zone
31
1848564d
MT
32 [ -d "$(zone_dir ${zone})" ]
33}
34
1c6a4e30 35zone_match() {
1848564d
MT
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
1c6a4e30 46zone_name_is_valid() {
1848564d 47 local zone=${1}
4fedddef
MT
48
49 # Don't accept empty strings.
50 [ -z "${zone}" ] && return ${EXIT_FALSE}
711ffac1 51
1848564d
MT
52 [[ ${zone} =~ $(zone_match) ]]
53}
54
1c6a4e30 55zone_is_local() {
1848564d
MT
56 local zone=${1}
57
7de0637a 58 [[ "${zone:0:${#ZONE_LOCAL}}" = "${ZONE_LOCAL}" ]]
5e42d659
MT
59}
60
1c6a4e30 61zone_is_nonlocal() {
5e42d659
MT
62 local zone=${1}
63
7de0637a 64 [[ "${zone:0:${#ZONE_NONLOCAL}}" = "${ZONE_NONLOCAL}" ]]
1848564d
MT
65}
66
1c6a4e30 67zone_get_hook() {
1848564d 68 local zone=${1}
711ffac1
MT
69 assert isset zone
70
1848564d
MT
71 config_get_hook $(zone_dir ${zone})/settings
72}
73
1c6a4e30 74zone_start() {
5bb2429a
MT
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
1d08b9b3 81 service_start "network@${zone}.service"
5bb2429a
MT
82}
83
1c6a4e30 84zone_start_auto() {
2a969c27
MT
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
1c6a4e30 106zone_stop() {
5bb2429a
MT
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
1d08b9b3 113 service_stop "network@${zone}.service"
5bb2429a
MT
114}
115
1c6a4e30 116zone_reload() {
e6fd23fd
MT
117 local zone="${1}"
118 assert zone_exists "${zone}"
119
120 service_reload "network@${zone}.service"
121}
122
1c6a4e30 123zone_hotplug_event() {
fb8c7c92 124 local zone="${1}"
2a969c27 125 assert isset zone
fb8c7c92 126
2a969c27 127 hotplug_assert_in_hotplug_event
fb8c7c92 128
2a969c27 129 zone_cmd "hotplug" "${zone}"
fb8c7c92
MT
130}
131
1c6a4e30 132zone_enable() {
5c5b8e36
SS
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
1c6a4e30 152zone_disable() {
5c5b8e36
SS
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
1c6a4e30 172zone_is_enabled() {
5c5b8e36
SS
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
1c6a4e30 184zone_is_active() {
e6fd23fd
MT
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
1c6a4e30 195zone_is_enabled_or_active() {
2a969c27
MT
196 local zone="${1}"
197 assert isset zone
198
199 zone_is_enabled "${zone}" || zone_is_active "${zone}"
200}
201
1c6a4e30 202zone_cmd() {
2a969c27
MT
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
1c6a4e30 216zone_new() {
1848564d
MT
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
d61a01d4 231 if ! hook_zone_exists ${hook}; then
1848564d
MT
232 error "Hook '${hook}' does not exist."
233 return ${EXIT_ERROR}
234 fi
235
236 mkdir -p $(zone_dir ${zone})
237
a5ebb169
MT
238 # Create directories for configs and ports
239 mkdir -p $(zone_dir ${zone})/{configs,ports}
943e3f7e 240
cf0fc8ab 241 hook_zone_exec "${hook}" "new" "${zone}" $@
1848564d
MT
242 local ret=$?
243
cf0fc8ab 244 # Maybe the zone new hook did not exit correctly.
1848564d 245 # If this is the case we remove the created zone immediately.
a63e51c6 246 if [ "${ret}" != "${EXIT_OK}" ]; then
cf0fc8ab 247 zone_destroy_now "${zone}"
5c5b8e36 248 return ${EXIT_ERROR}
1848564d 249 fi
5c5b8e36
SS
250
251 # Automatically enable zone.
252 zone_enable "${zone}"
ac694a6a
MT
253
254 # Bring up the zone immediately after
255 zone_start "${zone}"
1848564d
MT
256}
257
1c6a4e30 258zone_edit() {
1848564d
MT
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
69ace22b 267 # Check if the zone is tagged for removal.
cf0fc8ab 268 if zone_has_destroy_tag ${zone}; then
69ace22b
MT
269 error "You cannot edit a zone that is tagged for removal."
270 return ${EXIT_ERROR}
271 fi
272
2472e0ea 273 local hook="$(zone_get_hook "${zone}")"
1848564d
MT
274 if [ -z "${hook}" ]; then
275 error "Config file did not provide any hook."
276 return ${EXIT_ERROR}
277 fi
278
d61a01d4 279 if ! hook_zone_exists ${hook}; then
1848564d
MT
280 error "Hook '${hook}' does not exist."
281 return ${EXIT_ERROR}
282 fi
283
d61a01d4 284 hook_zone_exec ${hook} edit ${zone} $@
1848564d
MT
285}
286
2bb20bbd
SS
287zone_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
69ace22b 327
1c6a4e30 328zone_destroy() {
cf0fc8ab
MT
329 local zone="${1}"
330 assert zone_exists "${zone}"
1848564d 331
69ace22b 332 # Make the zone for removal.
cf0fc8ab 333 touch "$(zone_dir "${zone}")/.destroy"
69ace22b
MT
334
335 log INFO "Zone '${zone}' has been tagged for removal."
336}
337
1c6a4e30 338zone_has_destroy_tag() {
cf0fc8ab
MT
339 local zone="${1}"
340 assert zone_exists "${zone}"
69ace22b 341
cf0fc8ab 342 [ -e "$(zone_dir "${zone}")/.destroy" ]
69ace22b
MT
343}
344
345# This function will remove the given zone
cf0fc8ab 346# RIGHT NOW. Use zone_destroy to remove it
69ace22b 347# at the next status change.
1c6a4e30 348zone_destroy_now() {
cf0fc8ab
MT
349 local zone="${1}"
350 assert zone_exists "${zone}"
69ace22b
MT
351
352 log INFO "Removing zone '${zone}' right now."
1848564d 353
69ace22b 354 # Force the zone down.
d5c9bd17 355 zone_is_active "${zone}" && zone_stop "${zone}"
1848564d 356
5c5b8e36
SS
357 # Disable zone.
358 zone_disable "${zone}"
359
cf0fc8ab 360 rm -rf "$(zone_dir "${zone}")"
1848564d
MT
361}
362
1c6a4e30 363zone_up() {
1848564d
MT
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
69ace22b 372 # Check if a zone has got the remove tag.
fa0eb21f 373 if zone_has_destroy_tag ${zone}; then
69ace22b
MT
374 error "Cannot bring up any zone which is to be removed."
375 return ${EXIT_ERROR}
376 fi
377
2472e0ea 378 local hook="$(zone_get_hook "${zone}")"
1848564d
MT
379 if [ -z "${hook}" ]; then
380 error "Config file did not provide any hook."
381 return ${EXIT_ERROR}
382 fi
383
d61a01d4 384 if ! hook_zone_exists ${hook}; then
1848564d
MT
385 error "Hook '${hook}' does not exist."
386 return ${EXIT_ERROR}
387 fi
388
059469a8
MT
389 zone_db ${zone} starting
390
d61a01d4
MT
391 hook_zone_exec ${hook} up ${zone} $@
392
059469a8 393 zone_db ${zone} started
de3cecef
MT
394
395 # Execute all triggers after the zone got up
396 triggers_execute_all "up" ZONE="${zone}"
1848564d
MT
397}
398
1c6a4e30 399zone_down() {
1848564d
MT
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
2472e0ea 408 local hook="$(zone_get_hook "${zone}")"
1848564d
MT
409 if [ -z "${hook}" ]; then
410 error "Config file did not provide any hook."
411 return ${EXIT_ERROR}
412 fi
413
d61a01d4 414 if ! hook_zone_exists ${hook}; then
1848564d
MT
415 error "Hook '${hook}' does not exist."
416 return ${EXIT_ERROR}
417 fi
418
059469a8
MT
419 zone_db ${zone} stopping
420
d61a01d4 421 hook_zone_exec ${hook} down ${zone} $@
059469a8
MT
422
423 zone_db ${zone} stopped
69ace22b 424
de3cecef
MT
425 # Execute all triggers after the zone went down
426 triggers_execute_all "down" ZONE="${zone}"
427
69ace22b 428 # Remove the zone, if it has got a remove tag.
cf0fc8ab
MT
429 if zone_has_destroy_tag "${zone}"; then
430 zone_destroy_now "${zone}"
69ace22b 431 fi
1848564d
MT
432}
433
1c6a4e30 434zone_status() {
2472e0ea
MT
435 local zone="${1}"
436 assert isset zone
1848564d
MT
437 shift
438
2472e0ea 439 if ! zone_exists "${zone}"; then
1848564d
MT
440 error "Zone '${zone}' does not exist."
441 return ${EXIT_ERROR}
442 fi
443
2472e0ea 444 local hook="$(zone_get_hook "${zone}")"
1848564d
MT
445 if [ -z "${hook}" ]; then
446 error "Config file did not provide any hook."
447 return ${EXIT_ERROR}
448 fi
449
2472e0ea 450 if ! hook_zone_exists "${hook}"; then
1848564d
MT
451 error "Hook '${hook}' does not exist."
452 return ${EXIT_ERROR}
453 fi
454
2472e0ea 455 hook_zone_exec "${hook}" "status" "${zone}" "$@"
69ace22b
MT
456
457 # Show that the zone it to be removed soon.
fa0eb21f 458 if zone_has_destroy_tag ${zone}; then
69ace22b
MT
459 warning "This zone is tagged for removal."
460 fi
1848564d
MT
461}
462
f5ee091e
MT
463zone_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
1c6a4e30 492zone_get_ports() {
711ffac1
MT
493 local zone=${1}
494
495 assert isset zone
496
497 local port
943e3f7e 498 for port in $(zone_dir ${zone})/ports/*; do
711ffac1 499 port=$(basename ${port})
711ffac1
MT
500
501 if port_exists ${port}; then
502 echo "${port}"
503 fi
504 done
505}
506
1c6a4e30 507zone_get_ports_num() {
529141df
MT
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
1c6a4e30 525zone_has_port() {
3a7fef62
MT
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
1c6a4e30 539zone_config() {
ea699552
MT
540 local zone="${1}"
541 local cmd="${2}"
a5ebb169
MT
542 shift 2
543
544 assert isset zone
ea699552
MT
545 assert isset cmd
546 assert zone_exists "${zone}"
a5ebb169 547
ea699552 548 case "${cmd}" in
2a6b2397
MT
549 new)
550 zone_config_new "${zone}" "$@"
551 ;;
552 destroy)
ea37ec0b
JS
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
a5ebb169 559 ;;
a5d2c758
JS
560 list)
561 zone_config_list "${zone}" "$@"
562 ;;
a5ebb169 563 *)
e6a03d56
JS
564 # Check is we get a valid id
565 # TODO This could be also a valid hid
566 local id=${cmd}
567
a0c5827f 568 if zone_config_id_is_valid ${zone} ${id} && [[ ${1} == "edit" ]]; then
e6a03d56 569 shift 1
a0c5827f 570 zone_config_edit "${zone}" "${id}" "$@"
e6a03d56
JS
571 else
572 error "Unrecognized argument: ${cmd}"
573 cli_usage root-zone-config-subcommands
574 exit ${EXIT_ERROR}
575 fi
a5ebb169
MT
576 ;;
577 esac
578}
579
1c6a4e30 580zone_config_cmd() {
ea699552 581 assert [ $# -gt 2 ]
a5ebb169 582
ea699552
MT
583 local cmd="${1}"
584 local zone="${2}"
585 shift 2
586
587 local hook="$(zone_get_hook "${zone}")"
a5ebb169
MT
588 assert isset hook
589
ea699552
MT
590 hook_zone_exec "${hook}" "config_${cmd}" "${zone}" "$@"
591}
592
2a6b2397 593zone_config_new() {
44b8ade9
SS
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
ea699552
MT
606}
607
2a6b2397
MT
608zone_config_destroy() {
609 zone_config_cmd "destroy" "$@"
ea699552
MT
610}
611
2a6b2397
MT
612zone_config_edit() {
613 zone_config_cmd "edit" "$@"
ea699552
MT
614}
615
a5d2c758
JS
616zone_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
1c6a4e30 640zone_config_show() {
ea699552 641 zone_config_cmd "show" "$@"
a5ebb169
MT
642}
643
d2998dc2
JS
644# Returns a list of all used ids for a zone
645zone_config_list_ids() {
646 assert [ $# -eq 1 ]
647
648 local zone=${1}
649 local config
650 local ids
651
652 for config in $(zone_configs_list ${zone}); do
653 list_append ids "$(config_get_id_from_config ${config})"
654 done
655
656 echo ${ids}
657}
658
450afe05
JS
659# List all hids of a zone
660zone_config_list_hids() {
661 assert [ $# -eq 1 ]
662
663 local zone=${1}
664
665 local config
666 for config in $(zone_configs_list ${zone}); do
667 zone_config_get_hid "${zone}" "${config}"
668 done
669}
670
671# get the hid from a given config
672zone_config_get_hid() {
673 assert [ $# -eq 2 ]
674
675 local zone=${1}
676 local config=${2}
677
678 local hook="$(zone_config_get_hook "${zone}" "${config}")"
679
680 hook_exec "config" "${hook}" "hid" "${zone}" "${config}"
681}
682
683# Checks if a hid is valid for a given zone
684zone_config_hid_is_valid() {
685 assert [ $# -eq 2]
686
687 local zone=${1}
688 local hid=${2}
689
690 local _hid
691 for _hid in $(zone_config_list_hids "${zone}"); do
692 if [[ ${_hid} = ${hid} ]]; then
693 return ${EXIT_TRUE}
694 fi
695 done
696
697 return ${EXIT_FALSE}
698}
699
700# This function converts a hid to a id
701zone_config_convert_hid_to_id() {
702 assert [ $# -eq 2 ]
703
704 local zone=${1}
705 local hid=${2}
706
707 local config
708 for config in $(zone_configs_list ${zone}); do
709 # Get hook from config
710 local hook="$(zone_config_get_hook "${zone}" "${config}")"
711
712 if [[ "$(hook_exec "config" "${hook}" "hid" "${zone}" "${config}")" == "${hid}" ]]; then
713 config_get_id_from_config "${config}"
714 return ${EXIT_TRUE}
715 fi
716 done
717
718 return ${EXIT_FALSE}
719}
720
1c6a4e30 721zone_show() {
1848564d
MT
722 local zone=${1}
723
724 echo "${zone}"
725 echo " Type: $(zone_get_hook ${zone})"
726 echo
727}
728
1c6a4e30 729zones_show() {
1848564d
MT
730 local zone
731
732 for zone in $(zones_get $@); do
733 zone_show ${zone}
734 done
735}
736
1c6a4e30 737zones_get_all() {
1848564d 738 local zone
d61a01d4 739 for zone in $(zone_dir)/*; do
1848564d
MT
740 zone=$(basename ${zone})
741 zone_exists ${zone} || continue
742
743 echo "${zone}"
03170817 744 done
1848564d
MT
745}
746
1ca5fe9f
JS
747zones_get_next_free() {
748 # This function return the next free zones.
749 # Example net0 upl0 upl1 are configured so the next free zones are:
750 # net1 upl2
751 local i
752 local zone_name
753 for zone_name in ${VALID_ZONES}; do
754 i=0
755
756 while true; do
757 local zone="${zone_name}${i}"
758 if ! zone_exists ${zone}; then
759 echo "${zone}"
760 break
761 fi
762 i=$(( i + 1 ))
763 done
764 done
765}
766
1c6a4e30 767zones_get_local() {
1848564d
MT
768 local zone
769 for zone in $(zones_get_all); do
770 zone_is_local ${zone} && echo "${zone}"
771 done
772}
773
1c6a4e30 774zones_get_nonlocal() {
1848564d
MT
775 local zone
776 for zone in $(zones_get_all); do
5e42d659 777 zone_is_nonlocal ${zone} && echo "${zone}"
1848564d
MT
778 done
779}
780
1c6a4e30 781zones_get() {
1848564d
MT
782 local local=1
783 local remote=1
784
785 local zones
786
787 while [ $# -gt 0 ]; do
788 case "${1}" in
789 --local-only)
790 local=1
791 remote=0
792 ;;
793 --remote-only)
794 local=0
795 remote=1
796 ;;
797 --all)
798 local=1
799 remote=1
800 ;;
801 *)
802 if zone_name_is_valid ${1}; then
803 zones="${zones} ${1}"
804 else
805 warning "Unrecognized argument '${1}'"
806 fi
807 ;;
808 esac
809 shift
810 done
811
812 if [ -n "${zones}" ]; then
813 local zone
814 for zone in ${zones}; do
815 zone_exists ${zone} && echo "${zone}"
816 done
817 exit ${EXIT_OK}
818 fi
819
820 if [ ${local} -eq 1 ] && [ ${remote} -eq 1 ]; then
821 zones_get_all
822 elif [ ${local} -eq 1 ]; then
823 zones_get_local
824 elif [ ${remote} -eq 1 ]; then
825 zones_get_nonlocal
826 fi
827}
828
1c6a4e30 829zone_ports_list() {
1848564d
MT
830 local zone=${1}
831
832 local port
a5ebb169 833 for port in $(zone_dir ${zone})/ports/*; do
1848564d
MT
834 [ -e "${port}" ] || continue
835
836 echo $(basename ${port})
03170817 837 done
1848564d
MT
838}
839
1c6a4e30 840zone_port_attach() {
ac694a6a
MT
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 port actually exists.
850 if ! port_exists "${port}"; then
851 error "Cannot attach port '${port}' which does not exist"
852 return ${EXIT_ERROR}
853 fi
854
855 # Check if the port is already connected to this or any other zone.
856 local z
857 for z in $(zones_get_all); do
858 if zone_has_port "${z}" "${port}"; then
859 error "Port '${port}' is already attached to zone '${z}'"
860 return ${EXIT_ERROR}
861 fi
862 done
863
864 local hook="$(zone_get_hook "${zone}")"
865 assert isset hook
866
f5ee091e 867 # Make the port briefly flash if supported
01a079e0
MT
868 if device_exists ${port}; then
869 port_identify "${port}" --background
870 fi
f5ee091e 871
ac694a6a
MT
872 hook_zone_exec "${hook}" "port_attach" "${zone}" "${port}" "$@"
873 local ret="${?}"
874
875 case "${ret}" in
876 ${EXIT_OK})
877 log INFO "${port} has been attached to ${zone}"
878
879 # Automatically connect the port
abba34c1 880 zone_port_start "${zone}" "${port}"
ac694a6a
MT
881 ;;
882 *)
883 log CRITICAL "${port} could not be attached to ${zone}"
884 ;;
885 esac
886
887 return ${ret}
888}
889
1c6a4e30 890zone_port_edit() {
ac694a6a
MT
891 local zone="${1}"
892 assert isset zone
893
894 local port="${2}"
895 assert isset port
896
897 shift 2
898
899 # Check if the port actually exists.
900 if ! port_exists "${port}"; then
901 error "Port '${port}' does not exist"
902 return ${EXIT_ERROR}
903 fi
904
905 # Check if the zone actually has this port.
906 if ! zone_has_port "${zone}" "${port}"; then
907 error "Port '${port}' is not attached to zone '${zone}'"
908 return ${EXIT_ERROR}
909 fi
910
911 local hook=$(zone_get_hook "${zone}")
912 assert isset hook
913
914 hook_zone_exec "${hook}" "port_edit" "${zone}" "${port}" "$@"
915}
916
1c6a4e30 917zone_port_detach() {
ac694a6a
MT
918 local zone="${1}"
919 assert isset zone
920
921 local port="${2}"
922 assert isset port
923
1848564d
MT
924 shift 2
925
ac694a6a
MT
926 # Check if the zone actually has this port.
927 if ! zone_has_port "${zone}" "${port}"; then
928 error "Port '${port}' is not attached to zone '${zone}'"
929 return ${EXIT_ERROR}
930 fi
931
932 local hook=$(zone_get_hook "${zone}")
933 assert isset hook
934
f5ee091e
MT
935 # Make the port briefly flash if supported
936 port_identify "${port}" --background
937
ac694a6a
MT
938 hook_zone_exec "${hook}" "port_detach" "${zone}" "${port}" "$@"
939 local ret="${?}"
940
941 case "${ret}" in
942 ${EXIT_OK})
943 log INFO "${port} has been detached from ${zone}"
944
945 # Bring down the port if needed
abba34c1 946 zone_port_stop "${zone}" "${port}"
ac694a6a
MT
947 ;;
948 *)
949 log CRITICAL "${port} could not be detached from ${zone}"
950 ;;
951 esac
952
953 return ${ret}
954}
955
1c6a4e30 956zone_port_cmd() {
ac694a6a 957 local cmd="${1}"
711ffac1 958 assert isset cmd
ac694a6a
MT
959
960 local zone="${2}"
711ffac1 961 assert isset zone
1848564d 962
ac694a6a
MT
963 local port="${3}"
964 assert isset port
1848564d 965
ac694a6a
MT
966 shift 3
967
968 local hook="$(zone_get_hook "${zone}")"
969 assert isset hook
970
971 # Dispatch command to hook
972 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" $@
973}
974
1c6a4e30 975zone_port_create() {
ac694a6a
MT
976 zone_port_cmd "port_create" $@
977}
978
1c6a4e30 979zone_port_remove() {
ac694a6a
MT
980 zone_port_cmd "port_remove" $@
981}
982
1c6a4e30 983zone_port_up() {
ac694a6a
MT
984 zone_port_cmd "port_up" $@
985}
986
1c6a4e30 987zone_port_down() {
ac694a6a
MT
988 zone_port_cmd "port_down" $@
989}
990
abba34c1
MT
991# The next two functions automagically bring up and down
992# port that are attached to a bridge or similar.
993# The problem that is tried to overcome here is that there
994# are ports which exist all the time (like ethernet ports)
995# and therefore do not dispatch a hotplug event when
996# port_create is called.
997
1c6a4e30 998zone_port_start() {
abba34c1
MT
999 local zone="${1}"
1000 local port="${2}"
1001
1002 if zone_is_active "${zone}"; then
1003 if device_exists "${port}"; then
1004 zone_port_up "${zone}" "${port}"
1005 return ${?}
1006 else
1007 zone_port_create "${zone}" "${port}"
1008 return ${?}
1009 fi
1010 fi
1011
1012 return ${EXIT_OK}
1013}
1014
1c6a4e30 1015zone_port_stop() {
abba34c1
MT
1016 local zone="${1}"
1017 local port="${2}"
1018
1019 # Shut down the port if necessary
1020 if zone_is_active "${zone}" && port_is_up "${port}"; then
1021 zone_port_down "${zone}" "${port}"
1022 fi
1023
1024 # Remove the port
1025 zone_port_remove "${zone}" "${port}"
1026}
1027
1c6a4e30 1028zone_port_status() {
ac694a6a
MT
1029 zone_port_cmd "port_status" $@
1030}
1031
1c6a4e30 1032zone_ports_cmd() {
ac694a6a
MT
1033 local cmd="${1}"
1034 assert isset cmd
1035
1036 local zone="${2}"
1037 assert isset zone
1038
1039 shift 2
1040
1041 local hook="$(zone_get_hook "${zone}")"
711ffac1
MT
1042
1043 local port
1044 for port in $(zone_get_ports ${zone}); do
ac694a6a 1045 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" $@
1848564d
MT
1046 done
1047}
1048
1c6a4e30 1049zone_ports_create() {
1ba6a2bb
MT
1050 zone_ports_cmd "port_create" $@
1051}
1052
1c6a4e30 1053zone_ports_remove() {
1ba6a2bb
MT
1054 zone_ports_cmd "port_remove" $@
1055}
1056
1c6a4e30 1057zone_ports_up() {
ac694a6a 1058 zone_ports_cmd "port_up" $@
1848564d
MT
1059}
1060
1c6a4e30 1061zone_ports_down() {
ac694a6a 1062 zone_ports_cmd "port_down" $@
711ffac1
MT
1063}
1064
1c6a4e30 1065zone_ports_status() {
ac694a6a 1066 zone_ports_cmd "port_status" $@
1848564d
MT
1067}
1068
1c6a4e30 1069zone_configs_cmd() {
2472e0ea 1070 assert [ $# -ge 2 ]
ea699552
MT
1071
1072 local cmd="${1}"
1073 local zone="${2}"
1848564d
MT
1074 shift 2
1075
ea699552 1076 assert zone_exists "${zone}"
1848564d 1077
1848564d 1078 local config
2472e0ea
MT
1079 for config in $(zone_configs_list "${zone}"); do
1080 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1081 assert isset config_hook
1082
1083 hook_config_exec "${config_hook}" "${cmd}" "${zone}" "${config}" $@
1848564d
MT
1084 done
1085}
1086
1c6a4e30 1087zone_configs_up() {
ea699552 1088 zone_configs_cmd "up" $@
1848564d
MT
1089}
1090
1c6a4e30 1091zone_configs_down() {
ea699552 1092 zone_configs_cmd "down" $@
1848564d
MT
1093}
1094
1c6a4e30 1095zone_configs_status() {
ea699552
MT
1096 zone_configs_cmd "status" $@
1097}
1098
1c6a4e30 1099zone_configs_list() {
ea699552
MT
1100 local zone=${1}
1101
1102 local config
1103 for config in $(zone_dir ${zone})/configs/*; do
1104 [ -e "${config}" ] || continue
1105
1106 basename ${config}
1107 done
a5ebb169
MT
1108}
1109
0afedf0d
JS
1110zone_config_get_new_id() {
1111 # This functions returns the next free id for a zone
1112
1113 assert [ $# -eq 1 ]
1114 local zone=${1}
1115
1116 local zone_path=$(zone_dir ${zone})
1117 local i=0
1118
1119 while true; do
1120 if [ ! -f ${zone_path}/configs/*.${i} ]; then
1121 echo "${i}"
1122 return ${EXIT_OK}
1123 fi
1124 (( i++ ))
1125 done
1126}
1127
1c6a4e30 1128zone_config_get_hook() {
2472e0ea
MT
1129 assert [ $# -eq 2 ]
1130
1131 local zone="${1}"
1132 assert isset zone
1133
1134 local config="${2}"
1135 assert isset config
1136
1137 local HOOK
1138 zone_config_settings_read "${zone}" "${config}" \
1139 --ignore-superfluous-settings HOOK
1140
1141 print "${HOOK}"
1142}
1143
41f8233d
JS
1144zone_config_hook_is_configured() {
1145 # Checks if a zone has already at least one config with the given hook.
1146 # Returns True when yes and False when no
1147
1148 assert [ $# -eq 2 ]
1149 local zone=${1}
1150 local hook=${2}
1151
1152 local config
1153 for config in $(zone_configs_list "${zone}"); do
1154 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1155 assert isset config_hook
1156 if [[ ${hook} == ${config_hook} ]]; then
1157 return ${EXIT_TRUE}
1158 fi
1159
1160 done
1161
1162 # If we get here the zone has no config with the given hook
1163 return ${EXIT_FALSE}
1164}
1165
f158dc66
JS
1166zone_config_id_is_valid() {
1167 # This function checks if a given id is valid for a zone
1168 # Return True when yes and false when no
1169
1170 assert [ $# -eq 2 ]
1171 local zone=${1}
1172 local id=${2}
1173
1174 local zone_path=$(zone_dir ${zone})
1175
1176 [ -f ${zone_path}/configs/*.${id} ];
1177}
1178
450afe05
JS
1179# This function checks if a given hid is valid for a zone
1180# Return True when yes and false when no
1181zone_config_hid_is_valid() {
1182 assert [ $# -eq 2 ]
1183 local zone=${1}
1184 local hid=${2}
1185
1186 local _hid
1187 for _hid in $(zone_config_list_hids ${zone}); do
1188 if [[ ${_hid} == ${hid} ]]; then
1189 return ${EXIT_TRUE}
1190 fi
1191 done
1192
1193 return ${EXIT_FALSE}
1194}
1195
cdf4266d
JS
1196zone_config_get_hook_from_id() {
1197 # Returns the hook for a given id
1198 assert [ $# -eq 2 ]
1199 local zone=${1}
1200 local id=${2}
1201
1202 local config
1203 for config in $(zone_configs_list "${zone}"); do
1204 if [[ ${config} == *.${id} ]]; then
1205 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1206 assert isset config_hook
1207 print "${config_hook}"
1208 return "${EXIT_OK}"
1209 fi
1210 done
1211
1212 # If we get here the zone has no config with the given id
1213 return ${EXIT_ERROR}
1214}
1215
1c6a4e30 1216zone_has_ip() {
38f61548 1217 device_has_ip $@
4231f419
MT
1218}
1219
1c6a4e30 1220zone_db() {
059469a8
MT
1221 local zone=${1}
1222 local action=${2}
1223 shift 2
1224
1225 case "${action}" in
1226 starting|started|stopping|stopped)
1227 db_connection_update ${zone} ${action}
1228 ;;
1229 esac
1230}
5e42d659 1231
1c6a4e30 1232zone_is_up() {
5e42d659
MT
1233 local zone=${1}
1234
1235 device_is_up ${zone}
1236}
1237
1c6a4e30 1238zone_is_down() {
5e42d659
MT
1239 ! zone_is_up $@
1240}
711ffac1 1241
1c6a4e30 1242zone_get_supported_port_hooks() {
711ffac1
MT
1243 local zone=${1}
1244
1245 local hook=$(zone_get_hook ${zone})
1246
1247 hook_zone_ports_get_all ${hook}
1248}
1249
1c6a4e30 1250zone_get_supported_config_hooks() {
ea699552 1251 hook_config_get_all
a5ebb169
MT
1252}
1253
1c6a4e30 1254zone_file() {
711ffac1
MT
1255 local zone=${1}
1256
1257 assert isset zone
1258
1259 echo "$(zone_dir ${zone})/settings"
1260}
1261
1c6a4e30 1262zone_settings_read() {
711ffac1 1263 local zone=${1}
711ffac1 1264 assert isset zone
52acd25f
MT
1265 shift
1266
1267 local args
1268 if [ $# -eq 0 ] && [ -n "${HOOK_SETTINGS}" ]; then
1269 list_append args ${HOOK_SETTINGS}
1270 else
1271 list_append args $@
1272 fi
711ffac1 1273
bfd6c282
MT
1274 # Save the HOOK variable.
1275 local hook="${HOOK}"
1276
52acd25f 1277 settings_read "$(zone_file "${zone}")" ${args}
bfd6c282
MT
1278
1279 # Restore hook.
1280 HOOK="${hook}"
711ffac1
MT
1281}
1282
1c6a4e30 1283zone_settings_write() {
1e6f187e 1284 local zone="${1}"
711ffac1
MT
1285 assert isset zone
1286
1e6f187e
MT
1287 local args
1288 if function_exists "hook_check_settings"; then
1289 list_append args "--check=\"hook_check_settings\""
1290 fi
1291 list_append args ${HOOK_SETTINGS}
1292
1293 settings_write "$(zone_file ${zone})" ${args}
711ffac1
MT
1294}
1295
1c6a4e30 1296zone_settings_set() {
711ffac1
MT
1297 local zone=${1}
1298 shift
1299 local args="$@"
1300
1301 assert isset zone
1302
1303 (
e9df08ad 1304 zone_settings_read ${zone}
711ffac1
MT
1305
1306 for arg in ${args}; do
1307 eval "${arg}"
1308 done
1309
e9df08ad 1310 zone_settings_write ${zone}
711ffac1
MT
1311 )
1312}
6b3f9c85 1313
1c6a4e30 1314zone_settings_get() {
6b3f9c85
MT
1315 local zone=${1}
1316 local key=${2}
1317
1318 assert isset zone
1319 assert isset key
1320
1321 (
1e6f187e
MT
1322 zone_settings_read "${zone}" "${key}" \
1323 --ignore-superfluous-settings
6b3f9c85
MT
1324
1325 echo "${!key}"
1326 )
1327}
e9df08ad 1328
1c6a4e30 1329zone_config_settings_read() {
c8132752 1330 assert [ $# -ge 2 ]
e9df08ad
MT
1331
1332 local zone="${1}"
1333 local config="${2}"
1334 shift 2
1335
c8132752
MT
1336 local args
1337 if [ $# -eq 0 ] && [ -n "${HOOK_CONFIG_SETTINGS}" ]; then
1338 list_append args ${HOOK_CONFIG_SETTINGS}
1339 else
1340 list_append args $@
1341 fi
1342
e9df08ad 1343 local path="$(zone_dir "${zone}")/configs/${config}"
c8132752 1344 settings_read "${path}" ${args}
e9df08ad
MT
1345}
1346
1c6a4e30 1347zone_config_settings_write() {
c8132752 1348 assert [ $# -ge 2 ]
e9df08ad
MT
1349
1350 local zone="${1}"
0959b0b9
JS
1351 local hook="${2}"
1352 local id=${3}
1353
1354 if ! isset id; then
1355 id=$(zone_config_get_new_id ${zone})
1356 log DEBUG "ID for the config is: ${id}"
1357 fi
e9df08ad 1358
c8132752
MT
1359 local args
1360 if function_exists "hook_check_config_settings"; then
1361 list_append args "--check=\"hook_check_config_settings\""
1362 fi
1363 list_append args ${HOOK_CONFIG_SETTINGS}
1364
0959b0b9 1365 local path="$(zone_dir "${zone}")/configs/${hook}.${id}"
c8132752 1366 settings_write "${path}" ${args}
e9df08ad
MT
1367}
1368
ea96cf52
JS
1369zone_config_settings_destroy() {
1370 # This function deletes the config file for a given zone and config
1371 assert [ $# -ge 2 ]
1372 local zone="${1}"
1373 local config="${2}"
1374
1375 local path="$(zone_dir "${zone}")/configs/${config}"
1376
1377 # Check if path is valid
1378 if [ ! -f ${path} ]; then
1379 log ERROR "Path: '${path}' is not valid"
1380 return ${EXIT_ERROR}
1381 fi
1382
1383 log DEBUG "Deleting config file ${path}"
1384 rm -f "${path}"
1385
1386}
1c6a4e30 1387zone_port_settings_read() {
ac694a6a 1388 assert [ $# -ge 2 ]
e9df08ad
MT
1389
1390 local zone="${1}"
1391 local port="${2}"
1392 shift 2
1393
ac694a6a
MT
1394 local args
1395 if [ $# -eq 0 ] && [ -n "${HOOK_PORT_SETTINGS}" ]; then
1396 list_append args ${HOOK_PORT_SETTINGS}
1397 else
1398 list_append args $@
1399 fi
1400
e9df08ad 1401 local path="$(zone_dir "${zone}")/ports/${port}"
ac694a6a 1402 settings_read "${path}" ${args}
e9df08ad
MT
1403}
1404
1c6a4e30 1405zone_port_settings_write() {
02236ca6 1406 assert [ $# -ge 2 ]
e9df08ad
MT
1407
1408 local zone="${1}"
1409 local port="${2}"
1410 shift 2
1411
1e6f187e
MT
1412 local args
1413 if function_exists "hook_check_port_settings"; then
1414 list_append args "--check=\"hook_check_port_settings\""
1415 fi
ac694a6a 1416 list_append args ${HOOK_PORT_SETTINGS}
1e6f187e 1417
e9df08ad 1418 local path="$(zone_dir "${zone}")/ports/${port}"
1e6f187e 1419 settings_write "${path}" ${args}
e9df08ad
MT
1420}
1421
1c6a4e30 1422zone_port_settings_remove() {
e9df08ad
MT
1423 assert [ $# -eq 2 ]
1424
1425 local zone="${1}"
1426 local port="${2}"
1427
1428 local path="$(zone_dir "${zone}")/ports/${port}"
1429 settings_remove "${path}"
1430}
410d2e85
JS
1431
1432zone_get_color() {
1433 # This function return the color of a zone
1434 assert [ $# -eq 1 ]
1435
1436 local name=${1}
1437 color_read "zone" ${name}
1438}
5de34b4c
JS
1439
1440zone_get_description_title() {
1441 assert [ $# -eq 1 ]
1442
1443 local name=${1}
1444 description_title_read $(description_format_filename "zone" "${name}")
1445}