]> git.ipfire.org Git - people/ms/network.git/blame - src/functions/functions.zone
zone: accept also hids in zone_config()
[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)
e9582016
JS
553 # usually ${1} is a valid hid
554 local hid=${1}
555 shift 1
556
557 # We convert the hid into an id
558 local id=$(zone_config_convert_hid_to_id ${zone} ${hid})
559
560 # If id isset the hid is valid and we can go on with the id
561 if isset id; then
562 zone_config_destroy "${zone}" "${id}" "$@"
563
564 # If we can't get a valid hid we check if we got a valid id
ea37ec0b 565 else
e9582016
JS
566 if zone_config_id_is_valid ${zone} ${hid}; then
567 zone_config_destroy "${zone}" ${hid} "$@"
568 else
569 log ERROR "${id} is not a valid id or hid"
570 fi
ea37ec0b 571 fi
a5ebb169 572 ;;
a5d2c758
JS
573 list)
574 zone_config_list "${zone}" "$@"
575 ;;
a5ebb169 576 *)
e9582016
JS
577 # usually ${1} is a valid hid
578 local hid=${cmd}
579 local cmd=${1}
580 shift 1
581
582 local id=$(zone_config_convert_hid_to_id ${zone} ${hid})
583
584 # If id isset the hid is valid and we can go on with the id
585 if isset id && [[ ${cmd} == "edit" ]]; then
586 zone_config_edit "${zone}" "${id}" "$@"
e6a03d56 587
e9582016 588 # If we didn't get a valid hid we check if we got a valid id
e6a03d56 589 else
e9582016
JS
590 if zone_config_id_is_valid ${zone} ${id} && [[ ${cmd} == "edit" ]]; then
591 shift 1
592 zone_config_edit "${zone}" "${id}" "$@"
593 else
594 # in ${hid} is saved the command after network zone ${zone} config
595 error "Unrecognized argument: ${hid}"
596 cli_usage root-zone-config-subcommands
597 exit ${EXIT_ERROR}
598 fi
e6a03d56 599 fi
a5ebb169
MT
600 ;;
601 esac
602}
603
1c6a4e30 604zone_config_cmd() {
ea699552 605 assert [ $# -gt 2 ]
a5ebb169 606
ea699552
MT
607 local cmd="${1}"
608 local zone="${2}"
609 shift 2
610
611 local hook="$(zone_get_hook "${zone}")"
a5ebb169
MT
612 assert isset hook
613
ea699552
MT
614 hook_zone_exec "${hook}" "config_${cmd}" "${zone}" "$@"
615}
616
2a6b2397 617zone_config_new() {
44b8ade9
SS
618 local zone="${1}"
619 shift
620
621 # Create a new configuration, but exit when that was
622 # not successful.
623 zone_config_cmd "new" "${zone}" "$@" || return ${?}
624
625 # If the config could be created, we will try to bring
626 # it up if the zone is up, too.
627 if zone_is_up "${zone}"; then
628 zone_configs_up "${zone}"
629 fi
ea699552
MT
630}
631
2a6b2397
MT
632zone_config_destroy() {
633 zone_config_cmd "destroy" "$@"
ea699552
MT
634}
635
2a6b2397
MT
636zone_config_edit() {
637 zone_config_cmd "edit" "$@"
ea699552
MT
638}
639
a5d2c758
JS
640zone_config_list() {
641 # This function list in an nice way all configs of a zone
642 local zone=${1}
643 assert isset zone
644
645 # Print a nice header
646 local format="%-3s %-20s"
647 print "${format}" "ID" "HOOK"
648
649 local config
650 local hook
651 local id
652
653 # Print for all config:
654 # id and hook
655 # TODO: Add hids here
656 for config in $(zone_configs_list "${zone}"); do
657 id=${config##*.}
658 hook=$(zone_config_get_hook "${zone}" "${config}")
659 assert isset hook
660 print "${format}" "${id}" "${hook}"
661 done
662}
663
1c6a4e30 664zone_config_show() {
ea699552 665 zone_config_cmd "show" "$@"
a5ebb169
MT
666}
667
d2998dc2
JS
668# Returns a list of all used ids for a zone
669zone_config_list_ids() {
670 assert [ $# -eq 1 ]
671
672 local zone=${1}
673 local config
674 local ids
675
676 for config in $(zone_configs_list ${zone}); do
677 list_append ids "$(config_get_id_from_config ${config})"
678 done
679
680 echo ${ids}
681}
682
450afe05
JS
683# List all hids of a zone
684zone_config_list_hids() {
685 assert [ $# -eq 1 ]
686
687 local zone=${1}
688
689 local config
690 for config in $(zone_configs_list ${zone}); do
691 zone_config_get_hid "${zone}" "${config}"
692 done
693}
694
695# get the hid from a given config
696zone_config_get_hid() {
697 assert [ $# -eq 2 ]
698
699 local zone=${1}
700 local config=${2}
701
702 local hook="$(zone_config_get_hook "${zone}" "${config}")"
703
704 hook_exec "config" "${hook}" "hid" "${zone}" "${config}"
705}
706
707# Checks if a hid is valid for a given zone
708zone_config_hid_is_valid() {
709 assert [ $# -eq 2]
710
711 local zone=${1}
712 local hid=${2}
713
714 local _hid
715 for _hid in $(zone_config_list_hids "${zone}"); do
716 if [[ ${_hid} = ${hid} ]]; then
717 return ${EXIT_TRUE}
718 fi
719 done
720
721 return ${EXIT_FALSE}
722}
723
724# This function converts a hid to a id
725zone_config_convert_hid_to_id() {
726 assert [ $# -eq 2 ]
727
728 local zone=${1}
729 local hid=${2}
730
731 local config
732 for config in $(zone_configs_list ${zone}); do
733 # Get hook from config
734 local hook="$(zone_config_get_hook "${zone}" "${config}")"
735
736 if [[ "$(hook_exec "config" "${hook}" "hid" "${zone}" "${config}")" == "${hid}" ]]; then
737 config_get_id_from_config "${config}"
738 return ${EXIT_TRUE}
739 fi
740 done
741
742 return ${EXIT_FALSE}
743}
744
1c6a4e30 745zone_show() {
1848564d
MT
746 local zone=${1}
747
748 echo "${zone}"
749 echo " Type: $(zone_get_hook ${zone})"
750 echo
751}
752
1c6a4e30 753zones_show() {
1848564d
MT
754 local zone
755
756 for zone in $(zones_get $@); do
757 zone_show ${zone}
758 done
759}
760
1c6a4e30 761zones_get_all() {
1848564d 762 local zone
d61a01d4 763 for zone in $(zone_dir)/*; do
1848564d
MT
764 zone=$(basename ${zone})
765 zone_exists ${zone} || continue
766
767 echo "${zone}"
03170817 768 done
1848564d
MT
769}
770
1ca5fe9f
JS
771zones_get_next_free() {
772 # This function return the next free zones.
773 # Example net0 upl0 upl1 are configured so the next free zones are:
774 # net1 upl2
775 local i
776 local zone_name
777 for zone_name in ${VALID_ZONES}; do
778 i=0
779
780 while true; do
781 local zone="${zone_name}${i}"
782 if ! zone_exists ${zone}; then
783 echo "${zone}"
784 break
785 fi
786 i=$(( i + 1 ))
787 done
788 done
789}
790
1c6a4e30 791zones_get_local() {
1848564d
MT
792 local zone
793 for zone in $(zones_get_all); do
794 zone_is_local ${zone} && echo "${zone}"
795 done
796}
797
1c6a4e30 798zones_get_nonlocal() {
1848564d
MT
799 local zone
800 for zone in $(zones_get_all); do
5e42d659 801 zone_is_nonlocal ${zone} && echo "${zone}"
1848564d
MT
802 done
803}
804
1c6a4e30 805zones_get() {
1848564d
MT
806 local local=1
807 local remote=1
808
809 local zones
810
811 while [ $# -gt 0 ]; do
812 case "${1}" in
813 --local-only)
814 local=1
815 remote=0
816 ;;
817 --remote-only)
818 local=0
819 remote=1
820 ;;
821 --all)
822 local=1
823 remote=1
824 ;;
825 *)
826 if zone_name_is_valid ${1}; then
827 zones="${zones} ${1}"
828 else
829 warning "Unrecognized argument '${1}'"
830 fi
831 ;;
832 esac
833 shift
834 done
835
836 if [ -n "${zones}" ]; then
837 local zone
838 for zone in ${zones}; do
839 zone_exists ${zone} && echo "${zone}"
840 done
841 exit ${EXIT_OK}
842 fi
843
844 if [ ${local} -eq 1 ] && [ ${remote} -eq 1 ]; then
845 zones_get_all
846 elif [ ${local} -eq 1 ]; then
847 zones_get_local
848 elif [ ${remote} -eq 1 ]; then
849 zones_get_nonlocal
850 fi
851}
852
1c6a4e30 853zone_ports_list() {
1848564d
MT
854 local zone=${1}
855
856 local port
a5ebb169 857 for port in $(zone_dir ${zone})/ports/*; do
1848564d
MT
858 [ -e "${port}" ] || continue
859
860 echo $(basename ${port})
03170817 861 done
1848564d
MT
862}
863
1c6a4e30 864zone_port_attach() {
ac694a6a
MT
865 local zone="${1}"
866 assert isset zone
867
868 local port="${2}"
869 assert isset port
870
871 shift 2
872
873 # Check if the port actually exists.
874 if ! port_exists "${port}"; then
875 error "Cannot attach port '${port}' which does not exist"
876 return ${EXIT_ERROR}
877 fi
878
879 # Check if the port is already connected to this or any other zone.
880 local z
881 for z in $(zones_get_all); do
882 if zone_has_port "${z}" "${port}"; then
883 error "Port '${port}' is already attached to zone '${z}'"
884 return ${EXIT_ERROR}
885 fi
886 done
887
888 local hook="$(zone_get_hook "${zone}")"
889 assert isset hook
890
f5ee091e 891 # Make the port briefly flash if supported
01a079e0
MT
892 if device_exists ${port}; then
893 port_identify "${port}" --background
894 fi
f5ee091e 895
ac694a6a
MT
896 hook_zone_exec "${hook}" "port_attach" "${zone}" "${port}" "$@"
897 local ret="${?}"
898
899 case "${ret}" in
900 ${EXIT_OK})
901 log INFO "${port} has been attached to ${zone}"
902
903 # Automatically connect the port
abba34c1 904 zone_port_start "${zone}" "${port}"
ac694a6a
MT
905 ;;
906 *)
907 log CRITICAL "${port} could not be attached to ${zone}"
908 ;;
909 esac
910
911 return ${ret}
912}
913
1c6a4e30 914zone_port_edit() {
ac694a6a
MT
915 local zone="${1}"
916 assert isset zone
917
918 local port="${2}"
919 assert isset port
920
921 shift 2
922
923 # Check if the port actually exists.
924 if ! port_exists "${port}"; then
925 error "Port '${port}' does not exist"
926 return ${EXIT_ERROR}
927 fi
928
929 # Check if the zone actually has this port.
930 if ! zone_has_port "${zone}" "${port}"; then
931 error "Port '${port}' is not attached to zone '${zone}'"
932 return ${EXIT_ERROR}
933 fi
934
935 local hook=$(zone_get_hook "${zone}")
936 assert isset hook
937
938 hook_zone_exec "${hook}" "port_edit" "${zone}" "${port}" "$@"
939}
940
1c6a4e30 941zone_port_detach() {
ac694a6a
MT
942 local zone="${1}"
943 assert isset zone
944
945 local port="${2}"
946 assert isset port
947
1848564d
MT
948 shift 2
949
ac694a6a
MT
950 # Check if the zone actually has this port.
951 if ! zone_has_port "${zone}" "${port}"; then
952 error "Port '${port}' is not attached to zone '${zone}'"
953 return ${EXIT_ERROR}
954 fi
955
956 local hook=$(zone_get_hook "${zone}")
957 assert isset hook
958
f5ee091e
MT
959 # Make the port briefly flash if supported
960 port_identify "${port}" --background
961
ac694a6a
MT
962 hook_zone_exec "${hook}" "port_detach" "${zone}" "${port}" "$@"
963 local ret="${?}"
964
965 case "${ret}" in
966 ${EXIT_OK})
967 log INFO "${port} has been detached from ${zone}"
968
969 # Bring down the port if needed
abba34c1 970 zone_port_stop "${zone}" "${port}"
ac694a6a
MT
971 ;;
972 *)
973 log CRITICAL "${port} could not be detached from ${zone}"
974 ;;
975 esac
976
977 return ${ret}
978}
979
1c6a4e30 980zone_port_cmd() {
ac694a6a 981 local cmd="${1}"
711ffac1 982 assert isset cmd
ac694a6a
MT
983
984 local zone="${2}"
711ffac1 985 assert isset zone
1848564d 986
ac694a6a
MT
987 local port="${3}"
988 assert isset port
1848564d 989
ac694a6a
MT
990 shift 3
991
992 local hook="$(zone_get_hook "${zone}")"
993 assert isset hook
994
995 # Dispatch command to hook
996 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" $@
997}
998
1c6a4e30 999zone_port_create() {
ac694a6a
MT
1000 zone_port_cmd "port_create" $@
1001}
1002
1c6a4e30 1003zone_port_remove() {
ac694a6a
MT
1004 zone_port_cmd "port_remove" $@
1005}
1006
1c6a4e30 1007zone_port_up() {
ac694a6a
MT
1008 zone_port_cmd "port_up" $@
1009}
1010
1c6a4e30 1011zone_port_down() {
ac694a6a
MT
1012 zone_port_cmd "port_down" $@
1013}
1014
abba34c1
MT
1015# The next two functions automagically bring up and down
1016# port that are attached to a bridge or similar.
1017# The problem that is tried to overcome here is that there
1018# are ports which exist all the time (like ethernet ports)
1019# and therefore do not dispatch a hotplug event when
1020# port_create is called.
1021
1c6a4e30 1022zone_port_start() {
abba34c1
MT
1023 local zone="${1}"
1024 local port="${2}"
1025
1026 if zone_is_active "${zone}"; then
1027 if device_exists "${port}"; then
1028 zone_port_up "${zone}" "${port}"
1029 return ${?}
1030 else
1031 zone_port_create "${zone}" "${port}"
1032 return ${?}
1033 fi
1034 fi
1035
1036 return ${EXIT_OK}
1037}
1038
1c6a4e30 1039zone_port_stop() {
abba34c1
MT
1040 local zone="${1}"
1041 local port="${2}"
1042
1043 # Shut down the port if necessary
1044 if zone_is_active "${zone}" && port_is_up "${port}"; then
1045 zone_port_down "${zone}" "${port}"
1046 fi
1047
1048 # Remove the port
1049 zone_port_remove "${zone}" "${port}"
1050}
1051
1c6a4e30 1052zone_port_status() {
ac694a6a
MT
1053 zone_port_cmd "port_status" $@
1054}
1055
1c6a4e30 1056zone_ports_cmd() {
ac694a6a
MT
1057 local cmd="${1}"
1058 assert isset cmd
1059
1060 local zone="${2}"
1061 assert isset zone
1062
1063 shift 2
1064
1065 local hook="$(zone_get_hook "${zone}")"
711ffac1
MT
1066
1067 local port
1068 for port in $(zone_get_ports ${zone}); do
ac694a6a 1069 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" $@
1848564d
MT
1070 done
1071}
1072
1c6a4e30 1073zone_ports_create() {
1ba6a2bb
MT
1074 zone_ports_cmd "port_create" $@
1075}
1076
1c6a4e30 1077zone_ports_remove() {
1ba6a2bb
MT
1078 zone_ports_cmd "port_remove" $@
1079}
1080
1c6a4e30 1081zone_ports_up() {
ac694a6a 1082 zone_ports_cmd "port_up" $@
1848564d
MT
1083}
1084
1c6a4e30 1085zone_ports_down() {
ac694a6a 1086 zone_ports_cmd "port_down" $@
711ffac1
MT
1087}
1088
1c6a4e30 1089zone_ports_status() {
ac694a6a 1090 zone_ports_cmd "port_status" $@
1848564d
MT
1091}
1092
1c6a4e30 1093zone_configs_cmd() {
2472e0ea 1094 assert [ $# -ge 2 ]
ea699552
MT
1095
1096 local cmd="${1}"
1097 local zone="${2}"
1848564d
MT
1098 shift 2
1099
ea699552 1100 assert zone_exists "${zone}"
1848564d 1101
1848564d 1102 local config
2472e0ea
MT
1103 for config in $(zone_configs_list "${zone}"); do
1104 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1105 assert isset config_hook
1106
1107 hook_config_exec "${config_hook}" "${cmd}" "${zone}" "${config}" $@
1848564d
MT
1108 done
1109}
1110
1c6a4e30 1111zone_configs_up() {
ea699552 1112 zone_configs_cmd "up" $@
1848564d
MT
1113}
1114
1c6a4e30 1115zone_configs_down() {
ea699552 1116 zone_configs_cmd "down" $@
1848564d
MT
1117}
1118
1c6a4e30 1119zone_configs_status() {
ea699552
MT
1120 zone_configs_cmd "status" $@
1121}
1122
1c6a4e30 1123zone_configs_list() {
ea699552
MT
1124 local zone=${1}
1125
1126 local config
1127 for config in $(zone_dir ${zone})/configs/*; do
1128 [ -e "${config}" ] || continue
1129
1130 basename ${config}
1131 done
a5ebb169
MT
1132}
1133
0afedf0d
JS
1134zone_config_get_new_id() {
1135 # This functions returns the next free id for a zone
1136
1137 assert [ $# -eq 1 ]
1138 local zone=${1}
1139
1140 local zone_path=$(zone_dir ${zone})
1141 local i=0
1142
1143 while true; do
1144 if [ ! -f ${zone_path}/configs/*.${i} ]; then
1145 echo "${i}"
1146 return ${EXIT_OK}
1147 fi
1148 (( i++ ))
1149 done
1150}
1151
1c6a4e30 1152zone_config_get_hook() {
2472e0ea
MT
1153 assert [ $# -eq 2 ]
1154
1155 local zone="${1}"
1156 assert isset zone
1157
1158 local config="${2}"
1159 assert isset config
1160
1161 local HOOK
1162 zone_config_settings_read "${zone}" "${config}" \
1163 --ignore-superfluous-settings HOOK
1164
1165 print "${HOOK}"
1166}
1167
41f8233d
JS
1168zone_config_hook_is_configured() {
1169 # Checks if a zone has already at least one config with the given hook.
1170 # Returns True when yes and False when no
1171
1172 assert [ $# -eq 2 ]
1173 local zone=${1}
1174 local hook=${2}
1175
1176 local config
1177 for config in $(zone_configs_list "${zone}"); do
1178 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1179 assert isset config_hook
1180 if [[ ${hook} == ${config_hook} ]]; then
1181 return ${EXIT_TRUE}
1182 fi
1183
1184 done
1185
1186 # If we get here the zone has no config with the given hook
1187 return ${EXIT_FALSE}
1188}
1189
f158dc66
JS
1190zone_config_id_is_valid() {
1191 # This function checks if a given id is valid for a zone
1192 # Return True when yes and false when no
1193
1194 assert [ $# -eq 2 ]
1195 local zone=${1}
1196 local id=${2}
1197
1198 local zone_path=$(zone_dir ${zone})
1199
1200 [ -f ${zone_path}/configs/*.${id} ];
1201}
1202
450afe05
JS
1203# This function checks if a given hid is valid for a zone
1204# Return True when yes and false when no
1205zone_config_hid_is_valid() {
1206 assert [ $# -eq 2 ]
1207 local zone=${1}
1208 local hid=${2}
1209
1210 local _hid
1211 for _hid in $(zone_config_list_hids ${zone}); do
1212 if [[ ${_hid} == ${hid} ]]; then
1213 return ${EXIT_TRUE}
1214 fi
1215 done
1216
1217 return ${EXIT_FALSE}
1218}
1219
cdf4266d
JS
1220zone_config_get_hook_from_id() {
1221 # Returns the hook for a given id
1222 assert [ $# -eq 2 ]
1223 local zone=${1}
1224 local id=${2}
1225
1226 local config
1227 for config in $(zone_configs_list "${zone}"); do
1228 if [[ ${config} == *.${id} ]]; then
1229 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1230 assert isset config_hook
1231 print "${config_hook}"
1232 return "${EXIT_OK}"
1233 fi
1234 done
1235
1236 # If we get here the zone has no config with the given id
1237 return ${EXIT_ERROR}
1238}
1239
1c6a4e30 1240zone_has_ip() {
38f61548 1241 device_has_ip $@
4231f419
MT
1242}
1243
1c6a4e30 1244zone_db() {
059469a8
MT
1245 local zone=${1}
1246 local action=${2}
1247 shift 2
1248
1249 case "${action}" in
1250 starting|started|stopping|stopped)
1251 db_connection_update ${zone} ${action}
1252 ;;
1253 esac
1254}
5e42d659 1255
1c6a4e30 1256zone_is_up() {
5e42d659
MT
1257 local zone=${1}
1258
1259 device_is_up ${zone}
1260}
1261
1c6a4e30 1262zone_is_down() {
5e42d659
MT
1263 ! zone_is_up $@
1264}
711ffac1 1265
1c6a4e30 1266zone_get_supported_port_hooks() {
711ffac1
MT
1267 local zone=${1}
1268
1269 local hook=$(zone_get_hook ${zone})
1270
1271 hook_zone_ports_get_all ${hook}
1272}
1273
1c6a4e30 1274zone_get_supported_config_hooks() {
ea699552 1275 hook_config_get_all
a5ebb169
MT
1276}
1277
1c6a4e30 1278zone_file() {
711ffac1
MT
1279 local zone=${1}
1280
1281 assert isset zone
1282
1283 echo "$(zone_dir ${zone})/settings"
1284}
1285
1c6a4e30 1286zone_settings_read() {
711ffac1 1287 local zone=${1}
711ffac1 1288 assert isset zone
52acd25f
MT
1289 shift
1290
1291 local args
1292 if [ $# -eq 0 ] && [ -n "${HOOK_SETTINGS}" ]; then
1293 list_append args ${HOOK_SETTINGS}
1294 else
1295 list_append args $@
1296 fi
711ffac1 1297
bfd6c282
MT
1298 # Save the HOOK variable.
1299 local hook="${HOOK}"
1300
52acd25f 1301 settings_read "$(zone_file "${zone}")" ${args}
bfd6c282
MT
1302
1303 # Restore hook.
1304 HOOK="${hook}"
711ffac1
MT
1305}
1306
1c6a4e30 1307zone_settings_write() {
1e6f187e 1308 local zone="${1}"
711ffac1
MT
1309 assert isset zone
1310
1e6f187e
MT
1311 local args
1312 if function_exists "hook_check_settings"; then
1313 list_append args "--check=\"hook_check_settings\""
1314 fi
1315 list_append args ${HOOK_SETTINGS}
1316
1317 settings_write "$(zone_file ${zone})" ${args}
711ffac1
MT
1318}
1319
1c6a4e30 1320zone_settings_set() {
711ffac1
MT
1321 local zone=${1}
1322 shift
1323 local args="$@"
1324
1325 assert isset zone
1326
1327 (
e9df08ad 1328 zone_settings_read ${zone}
711ffac1
MT
1329
1330 for arg in ${args}; do
1331 eval "${arg}"
1332 done
1333
e9df08ad 1334 zone_settings_write ${zone}
711ffac1
MT
1335 )
1336}
6b3f9c85 1337
1c6a4e30 1338zone_settings_get() {
6b3f9c85
MT
1339 local zone=${1}
1340 local key=${2}
1341
1342 assert isset zone
1343 assert isset key
1344
1345 (
1e6f187e
MT
1346 zone_settings_read "${zone}" "${key}" \
1347 --ignore-superfluous-settings
6b3f9c85
MT
1348
1349 echo "${!key}"
1350 )
1351}
e9df08ad 1352
1c6a4e30 1353zone_config_settings_read() {
c8132752 1354 assert [ $# -ge 2 ]
e9df08ad
MT
1355
1356 local zone="${1}"
1357 local config="${2}"
1358 shift 2
1359
c8132752
MT
1360 local args
1361 if [ $# -eq 0 ] && [ -n "${HOOK_CONFIG_SETTINGS}" ]; then
1362 list_append args ${HOOK_CONFIG_SETTINGS}
1363 else
1364 list_append args $@
1365 fi
1366
e9df08ad 1367 local path="$(zone_dir "${zone}")/configs/${config}"
c8132752 1368 settings_read "${path}" ${args}
e9df08ad
MT
1369}
1370
1c6a4e30 1371zone_config_settings_write() {
c8132752 1372 assert [ $# -ge 2 ]
e9df08ad
MT
1373
1374 local zone="${1}"
0959b0b9
JS
1375 local hook="${2}"
1376 local id=${3}
1377
1378 if ! isset id; then
1379 id=$(zone_config_get_new_id ${zone})
1380 log DEBUG "ID for the config is: ${id}"
1381 fi
e9df08ad 1382
c8132752
MT
1383 local args
1384 if function_exists "hook_check_config_settings"; then
1385 list_append args "--check=\"hook_check_config_settings\""
1386 fi
1387 list_append args ${HOOK_CONFIG_SETTINGS}
1388
0959b0b9 1389 local path="$(zone_dir "${zone}")/configs/${hook}.${id}"
c8132752 1390 settings_write "${path}" ${args}
e9df08ad
MT
1391}
1392
ea96cf52
JS
1393zone_config_settings_destroy() {
1394 # This function deletes the config file for a given zone and config
1395 assert [ $# -ge 2 ]
1396 local zone="${1}"
1397 local config="${2}"
1398
1399 local path="$(zone_dir "${zone}")/configs/${config}"
1400
1401 # Check if path is valid
1402 if [ ! -f ${path} ]; then
1403 log ERROR "Path: '${path}' is not valid"
1404 return ${EXIT_ERROR}
1405 fi
1406
1407 log DEBUG "Deleting config file ${path}"
1408 rm -f "${path}"
1409
1410}
1c6a4e30 1411zone_port_settings_read() {
ac694a6a 1412 assert [ $# -ge 2 ]
e9df08ad
MT
1413
1414 local zone="${1}"
1415 local port="${2}"
1416 shift 2
1417
ac694a6a
MT
1418 local args
1419 if [ $# -eq 0 ] && [ -n "${HOOK_PORT_SETTINGS}" ]; then
1420 list_append args ${HOOK_PORT_SETTINGS}
1421 else
1422 list_append args $@
1423 fi
1424
e9df08ad 1425 local path="$(zone_dir "${zone}")/ports/${port}"
ac694a6a 1426 settings_read "${path}" ${args}
e9df08ad
MT
1427}
1428
1c6a4e30 1429zone_port_settings_write() {
02236ca6 1430 assert [ $# -ge 2 ]
e9df08ad
MT
1431
1432 local zone="${1}"
1433 local port="${2}"
1434 shift 2
1435
1e6f187e
MT
1436 local args
1437 if function_exists "hook_check_port_settings"; then
1438 list_append args "--check=\"hook_check_port_settings\""
1439 fi
ac694a6a 1440 list_append args ${HOOK_PORT_SETTINGS}
1e6f187e 1441
e9df08ad 1442 local path="$(zone_dir "${zone}")/ports/${port}"
1e6f187e 1443 settings_write "${path}" ${args}
e9df08ad
MT
1444}
1445
1c6a4e30 1446zone_port_settings_remove() {
e9df08ad
MT
1447 assert [ $# -eq 2 ]
1448
1449 local zone="${1}"
1450 local port="${2}"
1451
1452 local path="$(zone_dir "${zone}")/ports/${port}"
1453 settings_remove "${path}"
1454}
410d2e85
JS
1455
1456zone_get_color() {
1457 # This function return the color of a zone
1458 assert [ $# -eq 1 ]
1459
1460 local name=${1}
1461 color_read "zone" ${name}
1462}
5de34b4c
JS
1463
1464zone_get_description_title() {
1465 assert [ $# -eq 1 ]
1466
1467 local name=${1}
1468 description_title_read $(description_format_filename "zone" "${name}")
1469}