diff --git a/.gitignore b/.gitignore index 486dde110639..713246fd8793 100644 --- a/.gitignore +++ b/.gitignore @@ -81,6 +81,12 @@ src/supervisor/* !src/supervisor/patch/ src/swig/* !src/swig/Makefile +src/systemd-sonic-generator/systemd-sonic-generator +src/systemd-sonic-generator/debian/* +!src/systemd-sonic-generator/debian/changelog +!src/systemd-sonic-generator/debian/compat +!src/systemd-sonic-generator/debian/control +!src/systemd-sonic-generator/debian/rules src/telemetry/debian/* !src/telemetry/debian/changelog !src/telemetry/debian/compat diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index 3930dcd54e2d..0f27c15273c1 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -37,6 +37,8 @@ FILESYSTEM_ROOT_USR_SHARE="$FILESYSTEM_ROOT_USR/share" FILESYSTEM_ROOT_USR_SHARE_SONIC="$FILESYSTEM_ROOT_USR_SHARE/sonic" FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES="$FILESYSTEM_ROOT_USR_SHARE_SONIC/templates" +GENERATED_SERVICE_FILE="$FILESYSTEM_ROOT/etc/sonic/generated_services.conf" + clean_sys() { sudo umount $FILESYSTEM_ROOT/sys/fs/cgroup/* \ $FILESYSTEM_ROOT/sys/fs/cgroup \ @@ -157,21 +159,21 @@ sudo cp -f $IMAGE_CONFIGS/cron.d/* $FILESYSTEM_ROOT/etc/cron.d/ # Copy NTP configuration files and templates sudo cp $IMAGE_CONFIGS/ntp/ntp-config.service $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable ntp-config.service +echo "ntp-config.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/ntp/ntp-config.sh $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/ntp/ntp.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ # Copy warmboot-finalizer files sudo LANG=C cp $IMAGE_CONFIGS/warmboot-finalizer/finalize-warmboot.sh $FILESYSTEM_ROOT/usr/local/bin/finalize-warmboot.sh sudo LANG=C cp $IMAGE_CONFIGS/warmboot-finalizer/warmboot-finalizer.service $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable warmboot-finalizer.service +echo "warmboot-finalizer.service" | sudo tee -a $GENERATED_SERVICE_FILE # Copy rsyslog configuration files and templates sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-config.service $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable rsyslog-config.service sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-config.sh $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog.d/* $FILESYSTEM_ROOT/etc/rsyslog.d/ +echo "rsyslog-config.service" | sudo tee -a $GENERATED_SERVICE_FILE # Copy logrotate.d configuration files sudo cp -f $IMAGE_CONFIGS/logrotate/logrotate.d/* $FILESYSTEM_ROOT/etc/logrotate.d/ @@ -181,9 +183,9 @@ sudo cp -f $IMAGE_CONFIGS/systemd/journald.conf $FILESYSTEM_ROOT/etc/systemd/ # Copy interfaces configuration files and templates sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.service $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable interfaces-config.service sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.sh $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/interfaces/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +echo "interfaces-config.service" | sudo tee -a $GENERATED_SERVICE_FILE # Copy initial interfaces configuration file, will be overwritten on first boot sudo cp $IMAGE_CONFIGS/interfaces/init_interfaces $FILESYSTEM_ROOT/etc/network/interfaces @@ -191,7 +193,7 @@ sudo mkdir -p $FILESYSTEM_ROOT/etc/network/interfaces.d # Copy hostcfgd files sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd.service $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable hostcfgd.service +echo "hostcfgd.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/hostcfgd/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ @@ -203,13 +205,13 @@ sudo cp $BUILD_TEMPLATES/qos_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATE # Copy hostname configuration scripts sudo cp $IMAGE_CONFIGS/hostname/hostname-config.service $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable hostname-config.service +echo "hostname-config.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/hostname/hostname-config.sh $FILESYSTEM_ROOT/usr/bin/ # Copy updategraph script and service file j2 files/build_templates/updategraph.service.j2 | sudo tee $FILESYSTEM_ROOT/etc/systemd/system/updategraph.service -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable updategraph.service sudo cp $IMAGE_CONFIGS/updategraph/updategraph $FILESYSTEM_ROOT/usr/bin/ +echo "updategraph.service" | sudo tee -a $GENERATED_SERVICE_FILE {% if enable_dhcp_graph_service == "y" %} sudo bash -c "echo enabled=true > $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" sudo bash -c "echo src=dhcp >> $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" @@ -235,12 +237,12 @@ sudo cp $IMAGE_CONFIGS/sudoers/sudoers.lecture $FILESYSTEM_ROOT/etc/ # Copy control plane ACL management daemon files sudo cp $IMAGE_CONFIGS/caclmgrd/caclmgrd.service $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable caclmgrd.service +echo "caclmgrd.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/caclmgrd/caclmgrd $FILESYSTEM_ROOT/usr/bin/ # Copy process-reboot-cause service files sudo cp $IMAGE_CONFIGS/process-reboot-cause/process-reboot-cause.service $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable process-reboot-cause.service +echo "process-reboot-cause.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/process-reboot-cause/process-reboot-cause $FILESYSTEM_ROOT/usr/bin/ ## Install package without starting service @@ -331,7 +333,7 @@ sudo cp {{script}} $FILESYSTEM_ROOT/usr/bin/ {% for service in installer_services.split(' ') -%} if [ -f {{service}} ]; then sudo cp {{service}} $FILESYSTEM_ROOT/etc/systemd/system/ - sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable {{service}} + echo "{{service}}" | sudo tee -a $GENERATED_SERVICE_FILE fi {% endfor %} sudo LANG=C chroot $FILESYSTEM_ROOT fuser -km /sys || true diff --git a/platform/barefoot/one-aboot.mk b/platform/barefoot/one-aboot.mk index 71e3a95da3ab..4e5e808d2ab9 100644 --- a/platform/barefoot/one-aboot.mk +++ b/platform/barefoot/one-aboot.mk @@ -4,6 +4,7 @@ SONIC_ONE_ABOOT_IMAGE = sonic-aboot-barefoot.swi $(SONIC_ONE_ABOOT_IMAGE)_MACHINE = barefoot $(SONIC_ONE_ABOOT_IMAGE)_IMAGE_TYPE = aboot $(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(BFN_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_ONE_ABOOT_IMAGE)_LAZY_INSTALLS += $(BFN_PLATFORM_MODULE) $(SONIC_ONE_ABOOT_IMAGE)_LAZY_INSTALLS += $(BFN_MONTARA_PLATFORM_MODULE) $(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(ARISTA_PLATFORM_MODULE_DRIVERS) \ diff --git a/platform/barefoot/one-image.mk b/platform/barefoot/one-image.mk index 6fcb4d7ea51b..36823baa8781 100644 --- a/platform/barefoot/one-image.mk +++ b/platform/barefoot/one-image.mk @@ -4,6 +4,7 @@ SONIC_ONE_IMAGE = sonic-barefoot.bin $(SONIC_ONE_IMAGE)_MACHINE = barefoot $(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie $(SONIC_ONE_IMAGE)_INSTALLS += $(BFN_MODULE) $(PYTHON_THRIFT) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_MONTARA_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(WNC_OSW1800_PLATFORM_MODULE) diff --git a/platform/broadcom/one-aboot.mk b/platform/broadcom/one-aboot.mk index 71829fca4013..66f3ca8797f4 100644 --- a/platform/broadcom/one-aboot.mk +++ b/platform/broadcom/one-aboot.mk @@ -4,5 +4,6 @@ SONIC_ONE_ABOOT_IMAGE = sonic-aboot-broadcom.swi $(SONIC_ONE_ABOOT_IMAGE)_MACHINE = broadcom $(SONIC_ONE_ABOOT_IMAGE)_IMAGE_TYPE = aboot $(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL) $(ARISTA_PLATFORM_MODULE_DRIVERS) $(ARISTA_PLATFORM_MODULE_PYTHON2) $(ARISTA_PLATFORM_MODULE_PYTHON3) $(ARISTA_PLATFORM_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_ONE_ABOOT_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) SONIC_INSTALLERS += $(SONIC_ONE_ABOOT_IMAGE) diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index b87c6dc14706..966e22edbe5a 100755 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -4,6 +4,7 @@ SONIC_ONE_IMAGE = sonic-broadcom.bin $(SONIC_ONE_IMAGE)_MACHINE = broadcom $(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie $(SONIC_ONE_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(DELL_Z9264F_PLATFORM_MODULE) \ $(DELL_S5232F_PLATFORM_MODULE) \ diff --git a/platform/broadcom/raw-image.mk b/platform/broadcom/raw-image.mk index 2591d32c1be8..15534e893937 100644 --- a/platform/broadcom/raw-image.mk +++ b/platform/broadcom/raw-image.mk @@ -4,6 +4,7 @@ SONIC_RAW_IMAGE = sonic-broadcom.raw $(SONIC_RAW_IMAGE)_MACHINE = broadcom $(SONIC_RAW_IMAGE)_IMAGE_TYPE = raw $(SONIC_RAW_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL) +$(SONIC_RAW_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_RAW_IMAGE)_LAZY_INSTALLS += $($(SONIC_ONE_IMAGE)_LAZY_INSTALLS) $(SONIC_RAW_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) SONIC_INSTALLERS += $(SONIC_RAW_IMAGE) diff --git a/platform/cavium/one-image.mk b/platform/cavium/one-image.mk index 658c2d60b587..d81763430c05 100644 --- a/platform/cavium/one-image.mk +++ b/platform/cavium/one-image.mk @@ -5,6 +5,7 @@ $(SONIC_ONE_IMAGE)_MACHINE = cavium $(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie $(SONIC_ONE_IMAGE)_INSTALLS += $(CAVM_PLATFORM_DEB) $(SONIC_ONE_IMAGE)_INSTALLS += $(CAVM_XPNET_DEB) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) ifeq ($(INSTALL_DEBUG_TOOLS),y) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) $(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) diff --git a/platform/centec/one-image.mk b/platform/centec/one-image.mk index c5cc1f26f5fc..0e057b24df03 100644 --- a/platform/centec/one-image.mk +++ b/platform/centec/one-image.mk @@ -3,6 +3,7 @@ SONIC_ONE_IMAGE = sonic-centec.bin $(SONIC_ONE_IMAGE)_MACHINE = centec $(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS = $(SYSTEMD_SONIC_GENERATOR) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E582_48X6Q_PLATFORM_MODULE) \ $(CENTEC_E582_48X2Q4Z_PLATFORM_MODULE) ifeq ($(INSTALL_DEBUG_TOOLS),y) diff --git a/platform/generic/aboot-image.mk b/platform/generic/aboot-image.mk index ecc91bba54c0..c3f21b616254 100644 --- a/platform/generic/aboot-image.mk +++ b/platform/generic/aboot-image.mk @@ -3,6 +3,6 @@ SONIC_GENERIC_ABOOT_IMAGE = sonic-aboot-generic.swi $(SONIC_GENERIC_ABOOT_IMAGE)_MACHINE = generic $(SONIC_GENERIC_ABOOT_IMAGE)_IMAGE_TYPE = aboot -$(SONIC_GENERIC_ABOOT_IMAGE)_INSTALLS = +$(SONIC_GENERIC_ABOOT_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_GENERIC_ABOOT_IMAGE)_DOCKERS = SONIC_INSTALLERS += $(SONIC_GENERIC_ABOOT_IMAGE) diff --git a/platform/generic/onie-image.mk b/platform/generic/onie-image.mk index 1a2ddb143505..5dc8bfb9f885 100644 --- a/platform/generic/onie-image.mk +++ b/platform/generic/onie-image.mk @@ -3,6 +3,6 @@ SONIC_GENERIC_ONIE_IMAGE = sonic-generic.bin $(SONIC_GENERIC_ONIE_IMAGE)_MACHINE = generic $(SONIC_GENERIC_ONIE_IMAGE)_IMAGE_TYPE = onie -$(SONIC_GENERIC_ONIE_IMAGE)_INSTALLS = +$(SONIC_GENERIC_ONIE_IMAGE)_INSTALLS = $(SYSTEMD_SONIC_GENERATOR) $(SONIC_GENERIC_ONIE_IMAGE)_DOCKERS = SONIC_INSTALLERS += $(SONIC_GENERIC_ONIE_IMAGE) diff --git a/platform/marvell/one-image.mk b/platform/marvell/one-image.mk index 270a5307d0e1..fcac03854348 100644 --- a/platform/marvell/one-image.mk +++ b/platform/marvell/one-image.mk @@ -3,6 +3,7 @@ SONIC_ONE_IMAGE = sonic-marvell.bin $(SONIC_ONE_IMAGE)_MACHINE = marvell $(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) ifeq ($(INSTALL_DEBUG_TOOLS),y) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) $(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) diff --git a/platform/mellanox/one-image.mk b/platform/mellanox/one-image.mk index 45a48c79bc33..2946ae53f47b 100644 --- a/platform/mellanox/one-image.mk +++ b/platform/mellanox/one-image.mk @@ -4,6 +4,7 @@ SONIC_ONE_IMAGE = sonic-mellanox.bin $(SONIC_ONE_IMAGE)_MACHINE = mellanox $(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie $(SONIC_ONE_IMAGE)_INSTALLS += $(SX_KERNEL) $(KERNEL_MFT) $(MFT_OEM) $(MFT) $(MLNX_HW_MANAGEMENT) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) ifeq ($(INSTALL_DEBUG_TOOLS),y) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) $(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) diff --git a/platform/nephos/one-image.mk b/platform/nephos/one-image.mk index 8199401d26ad..3651325456c7 100644 --- a/platform/nephos/one-image.mk +++ b/platform/nephos/one-image.mk @@ -4,6 +4,7 @@ SONIC_ONE_IMAGE = sonic-nephos.bin $(SONIC_ONE_IMAGE)_MACHINE = nephos $(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie $(SONIC_ONE_IMAGE)_INSTALLS += $(NEPHOS_MODULE) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9130_32X_PLATFORM_MODULE) \ $(INGRASYS_S9230_64X_PLATFORM_MODULE) \ $(ACCTON_AS7116_54X_PLATFORM_MODULE) \ diff --git a/platform/vs/kvm-image.mk b/platform/vs/kvm-image.mk index 90073749db55..439a6fc1e418 100644 --- a/platform/vs/kvm-image.mk +++ b/platform/vs/kvm-image.mk @@ -1,6 +1,7 @@ # sonic kvm image SONIC_KVM_IMAGE = sonic-vs.img.gz +$(SONIC_KVM_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_KVM_IMAGE)_MACHINE = vs $(SONIC_KVM_IMAGE)_IMAGE_TYPE = kvm ifeq ($(INSTALL_DEBUG_TOOLS),y) diff --git a/platform/vs/one-image.mk b/platform/vs/one-image.mk index 4f478ac11869..cf4f535382bc 100644 --- a/platform/vs/one-image.mk +++ b/platform/vs/one-image.mk @@ -1,6 +1,7 @@ # sonic vs one image installer SONIC_ONE_IMAGE = sonic-vs.bin +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) $(SONIC_ONE_IMAGE)_MACHINE = vs $(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie ifeq ($(INSTALL_DEBUG_TOOLS),y) diff --git a/rules/systemd-sonic-generator.mk b/rules/systemd-sonic-generator.mk new file mode 100644 index 000000000000..cea08099177f --- /dev/null +++ b/rules/systemd-sonic-generator.mk @@ -0,0 +1,3 @@ +SYSTEMD_SONIC_GENERATOR = systemd-sonic-generator_1.0.0_$(CONFIGURED_ARCH).deb +$(SYSTEMD_SONIC_GENERATOR)_SRC_PATH = $(SRC_PATH)/systemd-sonic-generator +SONIC_MAKE_DEBS += $(SYSTEMD_SONIC_GENERATOR) diff --git a/src/systemd-sonic-generator/Makefile b/src/systemd-sonic-generator/Makefile new file mode 100644 index 000000000000..973c0d64eaed --- /dev/null +++ b/src/systemd-sonic-generator/Makefile @@ -0,0 +1,22 @@ +CC=gcc +CFLAGS=-std=gnu99 + +BINARY = systemd-sonic-generator +MAIN_TARGET = $(BINARY)_1.0.0_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + dpkg-buildpackage -us -uc -b + mv ../$(MAIN_TARGET) $(DEST)/ + rm ../$(BINARY)-* ../$(BINARY)_* + +$(BINARY): systemd-sonic-generator.c + rm -f ./systemd-sonic-generator + + $(CC) $(CFLAGS) -o $@ $^ + +install: $(BINARY) + mkdir -p $(DESTDIR) + mkdir -p $(DESTDIR)/lib + mkdir -p $(DESTDIR)/lib/systemd + mkdir -p $(DESTDIR)/lib/systemd/system-generators + cp ./systemd-sonic-generator $(DESTDIR)/lib/systemd/system-generators diff --git a/src/systemd-sonic-generator/debian/changelog b/src/systemd-sonic-generator/debian/changelog new file mode 100644 index 000000000000..1cc6c755e6c8 --- /dev/null +++ b/src/systemd-sonic-generator/debian/changelog @@ -0,0 +1,3 @@ +systemd-sonic-generator (1.0.0) UNRELEASED; urgency=medium + * Initial version + -- Lawrence Lee Tue, 23 Jul 2019 16:00:00 -0800 diff --git a/src/systemd-sonic-generator/debian/compat b/src/systemd-sonic-generator/debian/compat new file mode 100644 index 000000000000..b4de39476753 --- /dev/null +++ b/src/systemd-sonic-generator/debian/compat @@ -0,0 +1 @@ +11 diff --git a/src/systemd-sonic-generator/debian/control b/src/systemd-sonic-generator/debian/control new file mode 100644 index 000000000000..cbf8989e8dfb --- /dev/null +++ b/src/systemd-sonic-generator/debian/control @@ -0,0 +1,6 @@ +Source: systemd-sonic-generator +Maintainer: Lawrence Lee + +Package: systemd-sonic-generator +Architecture: any +Description: Systemd generator for SONiC services diff --git a/src/systemd-sonic-generator/debian/rules b/src/systemd-sonic-generator/debian/rules new file mode 100755 index 000000000000..945fcf9d99b7 --- /dev/null +++ b/src/systemd-sonic-generator/debian/rules @@ -0,0 +1,18 @@ +#!/usr/bin/make -f + +DISTRIBUTION = $(shell sed -n "s/^VERSION_CODENAME=//p" /etc/os-release) +VERSION = 1.0.0 +PACKAGEVERSION = $(VERSION) + +%: + dh $@ + +override_dh_auto_clean: +override_dh_auto_test: +override_dh_auto_build: +override_dh_auto_install: + make systemd-sonic-generator + make install DESTDIR=debian/systemd-sonic-generator + +override_dh_gencontrol: + dh_gencontrol -- -v$(PACKAGEVERSION) diff --git a/src/systemd-sonic-generator/systemd-sonic-generator.c b/src/systemd-sonic-generator/systemd-sonic-generator.c new file mode 100644 index 000000000000..a2723a28ff03 --- /dev/null +++ b/src/systemd-sonic-generator/systemd-sonic-generator.c @@ -0,0 +1,309 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NUM_TARGETS 5 +#define MAX_NUM_INSTALL_LINES 5 +#define MAX_NUM_UNITS 128 + +static const char* UNIT_FILE_PREFIX = "/etc/systemd/system/"; +static const char* CONFIG_FILE = "/etc/sonic/generated_services.conf"; + + +void strip_trailing_newline(char* str) { + /*** + Strips trailing newline from a string if it exists + ***/ + + size_t l = strlen(str); + if (l > 0 && str[l-1] == '\n') + str[l-1] = '\0'; +} + + +static int get_target_lines(char* unit_file, char* target_lines[]) { + /*** + Gets installation information for a given unit file + + Returns lines in the [Install] section of a unit file + ***/ + FILE *fp; + char *line = NULL; + size_t len = 0; + ssize_t nread; + bool found_install; + int num_target_lines; + + + fp = fopen(unit_file, "r"); + + if (fp == NULL) { + fprintf(stderr, "Failed to open file %s\n", unit_file); + return -1; + } + + found_install = false; + num_target_lines = 0; + + while ((nread = getline(&line, &len, fp)) != -1 ) { + // Assumes that [Install] is the last section of the unit file + if (strstr(line, "[Install]") != NULL) { + found_install = true; + } + else if (found_install) { + if (num_target_lines >= MAX_NUM_INSTALL_LINES) { + fprintf(stderr, "Number of lines in [Install] section of %s exceeds MAX_NUM_INSTALL_LINES\n", unit_file); + fputs("Extra [Install] lines will be ignored\n", stderr); + return num_target_lines; + } + target_lines[num_target_lines] = strdup(line); + num_target_lines++; + } + } + + free(line); + + fclose(fp); + + return num_target_lines; +} + +static int get_install_targets_from_line(char* target_string, char* suffix, char* targets[], int existing_targets) { + /*** + Helper fuction for get_install_targets + + Given a space delimited string of target directories and a suffix, + puts each target directory plus the suffix into the targets array + ***/ + char* token; + char* target; + char final_target[PATH_MAX]; + int num_targets = 0; + + while ((token = strtok_r(target_string, " ", &target_string))) { + target = strdup(token); + strip_trailing_newline(target); + + strcpy(final_target, target); + strcat(final_target, suffix); + + free(target); + + if (num_targets + existing_targets >= MAX_NUM_TARGETS) { + fputs("Number of targets found exceeds MAX_NUM_TARGETS\n", stderr); + fputs("Additional targets will be ignored \n", stderr); + return num_targets; + } + + targets[num_targets + existing_targets] = strdup(final_target); + num_targets++; + } + return num_targets; +} + +static int get_install_targets(char* unit_file, char* targets[]) { + /*** + Returns install targets for a unit file + + Parses the information in the [Install] section of a given + unit file to determine which directories to install the unit in + ***/ + char file_path[PATH_MAX]; + char *target_lines[MAX_NUM_INSTALL_LINES]; + int num_target_lines; + int num_targets; + int found_targets; + char* token; + char* line = NULL; + bool first; + char* target_suffix; + + strcpy(file_path, UNIT_FILE_PREFIX); + strcat(file_path, unit_file); + + num_target_lines = get_target_lines(file_path, target_lines); + if (num_target_lines < 0) { + fprintf(stderr, "Error parsing targets for %s\n", unit_file); + return -1; + } + + num_targets = 0; + + for (int i = 0; i < num_target_lines; i++) { + line = target_lines[i]; + first = true; + + while ((token = strtok_r(line, "=", &line))) { + if (first) { + first = false; + + if (strstr(token, "RequiredBy") != NULL) { + target_suffix = ".requires"; + } + else if (strstr(token, "WantedBy") != NULL) { + target_suffix = ".wants"; + } + } + else { + found_targets = get_install_targets_from_line(token, target_suffix, targets, num_targets); + num_targets += found_targets; + } + } + free(target_lines[i]); + } + return num_targets; +} + + +static int get_unit_files(char* unit_files[]) { + /*** + Reads a list of unit files to be installed from /etc/sonic/generated_services.conf + ***/ + FILE *fp; + char *line = NULL; + size_t len = 0; + ssize_t read; + + fp = fopen(CONFIG_FILE, "r"); + + if (fp == NULL) { + fprintf(stderr, "Failed to open %s\n", CONFIG_FILE); + exit(EXIT_FAILURE); + } + + int num_unit_files = 0; + + while ((read = getline(&line, &len, fp)) != -1) { + if (num_unit_files >= MAX_NUM_UNITS) { + fprintf(stderr, "Maximum number of units exceeded, ignoring extras\n"); + return num_unit_files; + } + strip_trailing_newline(line); + unit_files[num_unit_files] = strdup(line); + num_unit_files++; + } + + free(line); + + fclose(fp); + + return num_unit_files; +} + + +static int install_unit_file(char* unit_file, char* target, char* install_dir) { + /*** + Creates a symlink for a unit file installation + + For a given unit file and target directory, + create the appropriate symlink in the target directory + to enable the unit and have it started by Systemd + ***/ + char final_install_dir[PATH_MAX]; + char src_path[PATH_MAX]; + char dest_path[PATH_MAX]; + struct stat st; + int r; + + assert(unit_file); + assert(target); + + strcpy(final_install_dir, install_dir); + strcat(final_install_dir, target); + + strcpy(src_path, UNIT_FILE_PREFIX); + strcat(src_path, unit_file); + + if (stat(final_install_dir, &st) == -1) { + // If doesn't exist, create + r = mkdir(final_install_dir, 0755); + if (r == -1) { + fprintf(stderr, "Unable to create target directory %s\n", final_install_dir); + return -1; + } + } + else if (S_ISREG(st.st_mode)) { + // If is regular file, remove and create + r = remove(final_install_dir); + if (r == -1) { + fprintf(stderr, "Unable to remove file with same name as target directory %s\n", final_install_dir); + return -1; + } + + r = mkdir(final_install_dir, 0755); + if (r == -1) { + fprintf(stderr, "Unable to create target directory %s\n", final_install_dir); + return -1; + } + } + else if (S_ISDIR(st.st_mode)) { + // If directory, verify correct permissions + r = chmod(final_install_dir, 0755); + if (r == -1) { + fprintf(stderr, "Unable to change permissions of existing target directory %s\n", final_install_dir); + return -1; + } + } + + + strcpy(dest_path, final_install_dir); + strcat(dest_path, "/"); + strcat(dest_path, unit_file); + + r = symlink(src_path, dest_path); + + if (r < 0) { + if (errno == EEXIST) + return 0; + fprintf(stderr, "Error creating symlink %s from source %s\n", dest_path, src_path); + return -1; + } + + return 0; +} + + +int main(int argc, char **argv) { + char* unit_files[MAX_NUM_UNITS]; + char install_dir[PATH_MAX]; + char* targets[MAX_NUM_TARGETS]; + int num_unit_files; + int num_targets; + + if (argc <= 1) { + fputs("Installation directory required as argument\n", stderr); + return 1; + } + + strcpy(install_dir, argv[1]); + strcat(install_dir, "/"); + + num_unit_files = get_unit_files(unit_files); + + // For each unit file, get the installation targets and install the unit + for (int i = 0; i < num_unit_files; i++) { + num_targets = get_install_targets(unit_files[i], targets); + if (num_targets < 0) { + fprintf(stderr, "Error parsing %s\n", unit_files[i]); + free(unit_files[i]); + continue; + } + + for (int j = 0; j < num_targets; j++) { + if (install_unit_file(unit_files[i], targets[j], install_dir) != 0) + fprintf(stderr, "Error installing %s to target directory %s\n", unit_files[i], targets[j]); + + free(targets[j]); + } + + free(unit_files[i]); + } + return 0; +}