uvol: add new package
authorDaniel Golle <daniel@makrotopia.org>
Sat, 10 Apr 2021 03:04:09 +0000 (04:04 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Sat, 10 Apr 2021 11:02:23 +0000 (12:02 +0100)
uvol is a wrapper-script which allows automated handling of storage
volumes. uvol currently comes with backend support for LVM2 and UBI,
covering practically all options for storage large enough to be
managed (NAND, SPI-NAND, eMMC, SATA, NVME, virtio-blk, ...).

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
utils/ap_config/Makefile [new file with mode: 0644]
utils/ap_config/git-src [new symlink]
utils/autopart/Makefile [deleted file]
utils/autopart/files/autopart [deleted file]
utils/modbus-utils/Makefile [new file with mode: 0644]
utils/uvol/Makefile [new file with mode: 0644]
utils/uvol/files/autopart.defaults [new file with mode: 0644]
utils/uvol/files/lvm.sh [new file with mode: 0644]
utils/uvol/files/ubi.sh [new file with mode: 0644]
utils/uvol/files/uvol [new file with mode: 0644]

diff --git a/utils/ap_config/Makefile b/utils/ap_config/Makefile
new file mode 100644 (file)
index 0000000..2d09dc9
--- /dev/null
@@ -0,0 +1,37 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ap_config
+PKG_VERSION:=2021-03-21
+PKG_RELEASE:=1
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ac_server
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=ac_server
+  DEPENDS:=+libaxl +libopenssl +libmariadbclient
+endef
+
+define Package/ac_client
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=ac_client
+  DEPENDS:=+libaxl +libopenssl
+endef
+
+define Package/ac_server/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_BUILD_DIR)/ac_server $(1)/usr/sbin
+endef
+
+define Package/ap_client/install
+       $(INSTALL_DIR) $(1)/usr/sbin
+       $(INSTALL_BIN) $(PKG_BUILD_DIR)/ac_client $(1)/usr/sbin
+endef
+
+$(eval $(call BuildPackage,ac_server))
+$(eval $(call BuildPackage,ac_client))
diff --git a/utils/ap_config/git-src b/utils/ap_config/git-src
new file mode 120000 (symlink)
index 0000000..c2296c4
--- /dev/null
@@ -0,0 +1 @@
+/usr/src/ap_config/.git
\ No newline at end of file
diff --git a/utils/autopart/Makefile b/utils/autopart/Makefile
deleted file mode 100644 (file)
index dcd211b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-include $(TOPDIR)/rules.mk
-
-PKG_NAME:=autopart
-PKG_VERSION:=0.1
-PKG_RELEASE:=$(AUTORELEASE)
-
-PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
-PKG_LICENSE:=GPL-2.0-or-later
-
-include $(INCLUDE_DIR)/package.mk
-
-define Package/autopart
-  SECTION:=utils
-  CATEGORY:=Utilities
-  SUBMENU:=Disc
-  TITLE:=Automatically initialize LVM partition
-  DEPENDS:=+lvm2 +partx-utils +sfdisk
-  PKGARCH=all
-endef
-
-define Package/autopart/description
- Automatically allocate the GPT partition for LVM and initialize it
- on first boot.
-endef
-
-define Build/Prepare
-endef
-
-define Build/Configure
-endef
-
-define Build/Compile
-endef
-
-define Package/autopart/install
-       $(INSTALL_DIR) $(1)/etc/uci-defaults
-       $(INSTALL_BIN) ./files/autopart $(1)/etc/uci-defaults/30-autopart
-endef
-
-$(eval $(call BuildPackage,autopart))
diff --git a/utils/autopart/files/autopart b/utils/autopart/files/autopart
deleted file mode 100644 (file)
index c35b238..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/sh
-
-. /lib/functions.sh
-. /lib/upgrade/common.sh
-
-OWRT_VOLUMES=owrt-volumes
-
-part_fixup() {
-       echo "write" | sfdisk --force -q -w never $1
-}
-
-get_free_area() {
-       local found=
-       sfdisk -q -F "$1" 2>/dev/null | while read start end sectors size; do
-               case $start in
-               *"Unpartitioned"* | *"Units:"* | *"Sector"* | *"Start"* )
-                       continue
-                       ;;
-               [0-9]*)
-                       case "$size" in
-                               *"M")
-                                       [ "${size%%M}" -lt 100 ] && continue
-                                       ;;
-                               *"G" | *"T")
-                                       ;;
-                               *"k" | *"b")
-                                       continue
-                                       ;;
-                       esac
-                       [ "$found" ] || echo "start=$start, size=$((end - start))"
-                       found=1
-                       ;;
-               esac
-       done
-}
-
-create_lvm_part() {
-       local disk=$1
-       local freepart
-
-       freepart="$(get_free_area $disk)"
-       if [ "$freepart" ]; then
-               echo "$freepart, type=lvm, name=$OWRT_VOLUMES" | sfdisk --force -w never -a $disk
-               partx -a $disk 1>/dev/null 2>/dev/null || true
-               return 0
-       else
-               return 1
-       fi
-}
-
-lvm_init() {
-       lvm pvcreate -f $1
-       lvm vgcreate "$2" $1
-       lvm vgs
-}
-
-autopart_init() {
-       local diskdev
-       local lvmpart
-       local diskserial
-
-       export_bootdevice && export_partdevice diskdev 0
-
-       [ "$diskdev" ] || return
-
-       [ -e "/sys/class/block/$diskdev/device/serial" ] && diskserial=$(cat /sys/class/block/$diskdev/device/serial)
-
-       part_fixup /dev/$diskdev
-       create_lvm_part /dev/$diskdev || return
-       lvmpart=$(get_partition_by_name $diskdev $OWRT_VOLUMES)
-
-       [ "$lvmpart" ] || return
-       lvm_init /dev/$lvmpart "${OWRT_VOLUMES}${diskserial:+-${diskserial:2}}"
-}
-
-autopart_init
-exit 0
diff --git a/utils/modbus-utils/Makefile b/utils/modbus-utils/Makefile
new file mode 100644 (file)
index 0000000..2894439
--- /dev/null
@@ -0,0 +1,42 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=modbus-utils
+
+PKG_VERSION:=2013-07-31
+PKG_RELEASE=$(PKG_SOURCE_VERSION)
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/Krzysztow/modbus-utils.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=c569dc0a11a1bedf3a8080fe4a1696de93e386ab
+# PKG_MIRROR_HASH:=3aed4146e06bd9f9bcc271824c6b1d75d1fc2a0bd980f2b729c3b4755c6f70a8
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+
+PKG_FIXUP:=autoreconf
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+
+# supposed based on statement that source is based on libmodbus testcases
+PKG_LICENSE:=GPL-3.0+ LGPL-2.1+
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/nls.mk
+
+define Package/modbus-utils
+  SECTION:=utils
+  CATEGORY:=Utilities
+  TITLE:=Modbus client/server utils
+  DEPENDS:=+libmodbus
+endef
+
+define Package/modbus-utils/description
+endef
+
+define Package/modbus-utils/install
+       $(INSTALL_DIR) $(1)/usr/bin
+#      $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbrecorder $(1)/usr/bin/
+endef
+
+$(eval $(call BuildPackage,modbus-utils))
diff --git a/utils/uvol/Makefile b/utils/uvol/Makefile
new file mode 100644 (file)
index 0000000..64fb023
--- /dev/null
@@ -0,0 +1,73 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=uvol
+PKG_VERSION:=0.2
+PKG_RELEASE:=$(AUTORELEASE)
+
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=GPL-2.0-or-later
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/autopart
+  SECTION:=utils
+  CATEGORY:=Utilities
+  SUBMENU:=Disc
+  TITLE:=Automatically initialize LVM partition
+  DEPENDS:=+lvm2 +partx-utils +sfdisk
+  PKGARCH=all
+endef
+
+define Package/autopart/description
+ Automatically allocate the GPT partition for LVM and initialize it
+ on first boot.
+endef
+
+define Package/uvol
+  SECTION:=utils
+  CATEGORY:=Utilities
+  SUBMENU:=Disc
+  TITLE:=OpenWrt UBI/LVM volume abstraction
+  PKGARCH=all
+endef
+
+define Package/uvol/description
+  'uvol' is tool to automate storage volume handling on embedded
+  devices in a generic way.
+  Also install the 'autopart' package to easily make use of 'uvol' on
+  block-storage based devices.
+
+  Examples:
+  uvol create example_volume_1 256MiB rw
+  uvol up example_volume_1
+  uvol device example_volume_1
+
+  uvol create example_volume_2 9812733 ro
+  cat example_volume_2.squashfs | uvol write example_volume_2 9812733
+  uvol up example_volume_2
+  uvol device example_volume_2
+endef
+
+define Build/Prepare
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/autopart/install
+       $(INSTALL_DIR) $(1)/etc/uci-defaults
+       $(INSTALL_BIN) ./files/autopart.defaults $(1)/etc/uci-defaults/30-autopart
+endef
+
+define Package/uvol/install
+       $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/libexec/uvol
+       $(INSTALL_BIN) ./files/uvol $(1)/usr/sbin
+       $(INSTALL_BIN) ./files/ubi.sh $(1)/usr/libexec/uvol/20-ubi.sh
+       $(INSTALL_BIN) ./files/lvm.sh $(1)/usr/libexec/uvol/50-lvm.sh
+endef
+
+$(eval $(call BuildPackage,autopart))
+$(eval $(call BuildPackage,uvol))
diff --git a/utils/uvol/files/autopart.defaults b/utils/uvol/files/autopart.defaults
new file mode 100644 (file)
index 0000000..c35b238
--- /dev/null
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+. /lib/functions.sh
+. /lib/upgrade/common.sh
+
+OWRT_VOLUMES=owrt-volumes
+
+part_fixup() {
+       echo "write" | sfdisk --force -q -w never $1
+}
+
+get_free_area() {
+       local found=
+       sfdisk -q -F "$1" 2>/dev/null | while read start end sectors size; do
+               case $start in
+               *"Unpartitioned"* | *"Units:"* | *"Sector"* | *"Start"* )
+                       continue
+                       ;;
+               [0-9]*)
+                       case "$size" in
+                               *"M")
+                                       [ "${size%%M}" -lt 100 ] && continue
+                                       ;;
+                               *"G" | *"T")
+                                       ;;
+                               *"k" | *"b")
+                                       continue
+                                       ;;
+                       esac
+                       [ "$found" ] || echo "start=$start, size=$((end - start))"
+                       found=1
+                       ;;
+               esac
+       done
+}
+
+create_lvm_part() {
+       local disk=$1
+       local freepart
+
+       freepart="$(get_free_area $disk)"
+       if [ "$freepart" ]; then
+               echo "$freepart, type=lvm, name=$OWRT_VOLUMES" | sfdisk --force -w never -a $disk
+               partx -a $disk 1>/dev/null 2>/dev/null || true
+               return 0
+       else
+               return 1
+       fi
+}
+
+lvm_init() {
+       lvm pvcreate -f $1
+       lvm vgcreate "$2" $1
+       lvm vgs
+}
+
+autopart_init() {
+       local diskdev
+       local lvmpart
+       local diskserial
+
+       export_bootdevice && export_partdevice diskdev 0
+
+       [ "$diskdev" ] || return
+
+       [ -e "/sys/class/block/$diskdev/device/serial" ] && diskserial=$(cat /sys/class/block/$diskdev/device/serial)
+
+       part_fixup /dev/$diskdev
+       create_lvm_part /dev/$diskdev || return
+       lvmpart=$(get_partition_by_name $diskdev $OWRT_VOLUMES)
+
+       [ "$lvmpart" ] || return
+       lvm_init /dev/$lvmpart "${OWRT_VOLUMES}${diskserial:+-${diskserial:2}}"
+}
+
+autopart_init
+exit 0
diff --git a/utils/uvol/files/lvm.sh b/utils/uvol/files/lvm.sh
new file mode 100644 (file)
index 0000000..540fe39
--- /dev/null
@@ -0,0 +1,195 @@
+#!/bin/sh
+
+command -v lvm || return 1
+
+. /lib/functions.sh
+. /lib/upgrade/common.sh
+
+export_bootdevice
+[ "$BOOTDEV_MAJOR" ] || return 1
+export_partdevice rootdev 0
+[ "$rootdev" ] || return 1
+LVM_SUPPRESS_FD_WARNINGS=1
+
+case "$rootdev" in
+       mtd*|\
+       ram*|\
+       ubi*)
+               return 1
+esac
+
+lvs() {
+       local cmd="$1"
+       local cb="$2"
+       local param="${3:+-S vg_name=${vgname} -S lv_name=~^r[ow]_$3\$}"
+       local oIFS="$IFS"
+       IFS=" "
+       set -- $(LVM_SUPPRESS_FD_WARNINGS=1 $cmd -c $param)
+       [ "$1" ] || {
+               IFS="$oIFS"
+               return 1
+       }
+       IFS=":"
+       set -- $1
+       IFS="$oIFS"
+       $cb "$@"
+}
+
+pvvars() {
+       case "${1:5}" in
+               "$rootdev"*)
+                       partdev="$1"
+                       vgname="$2"
+                       ;;
+       esac
+}
+
+vgvars() {
+       [ "$1" = "$vgname" ] || return
+       vgbs="${13}"
+       vgts="${14}"
+       vgus="${15}"
+       vgfs="${16}"
+}
+
+lvvars() {
+       lvpath="$1"
+       lvsize=$(( 512 * $7 ))
+}
+
+freebytes() {
+       echo $((vgfs * vgbs * 1024))
+}
+
+totalbytes() {
+       echo $((vgts * vgbs * 1024))
+}
+
+existvol() {
+       [ "$1" ] || return 1
+       test -e "/dev/$vgname/ro_$1" || test -e "/dev/$vgname/rw_$1"
+       return $?
+}
+
+getlvname() {
+       lvs lvdisplay lvvars "$1"
+
+       [ "$lvpath" ] && echo ${lvpath:5}
+}
+
+getdev() {
+       existvol "$1" || return 1
+       readlink /dev/$(getlvname "$1")
+}
+
+getsize() {
+       lvs lvdisplay lvvars "$1"
+       [ "$lvsize" ] && echo $lvsize
+}
+
+activatevol() {
+       LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a y "$(getlvname "$1")"
+}
+
+disactivatevol() {
+       existvol "$1" || return 1
+       LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a n "$(getlvname "$1")"
+}
+
+getstatus() {
+       lvs lvdisplay lvvars "$1"
+       [ "$lvsize" ] || return 2
+       existvol "$1" || return 1
+       return 0
+}
+
+createvol() {
+       local mode ret lvname
+       case "$3" in
+               ro)
+                       mode=r
+                       ;;
+               rw)
+                       mode=rw
+                       ;;
+               *)
+                       return 22
+                       ;;
+       esac
+
+       LVM_SUPPRESS_FD_WARNINGS=1 lvcreate -p $mode -a n -y -W n -Z n -n "${3}_${1}" -L "$2" $vgname
+       ret=$?
+       if [ ! $ret -eq 0 ] || [ "$mode" = "r" ]; then
+               return $ret
+       fi
+       lvs lvdisplay lvvars "$1"
+       [ "$lvpath" ] || return 22
+       lvname=${lvpath:5}
+       LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a y /dev/$lvname || return 1
+       if [ $lvsize -gt $(( 100 * 1024 * 1024 )) ]; then
+               mkfs.f2fs -f -l "$1" $lvpath || return 1
+       else
+               mke2fs -F -L "$1" $lvpath || return 1
+       fi
+       return 0
+}
+
+removevol() {
+       local lvname="$(getlvname "$1")"
+       [ "$lvname" ] || return 2
+       LVM_SUPPRESS_FD_WARNINGS=1 lvremove -y "$(getlvname "$1")"
+}
+
+updatevol() {
+       lvs lvdisplay lvvars "$1"
+       [ "$lvpath" ] || return 2
+       [ $lvsize -ge $2 ] || return 27
+       LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a y -p rw ${lvpath:5}
+       dd of=$lvpath
+       case "$lvpath" in
+               /dev/*/ro_*)
+                       LVM_SUPPRESS_FD_WARNINGS=1 lvchange -p r ${lvpath:5}
+                       ;;
+       esac
+}
+
+lvs pvdisplay pvvars
+lvs vgdisplay vgvars
+cmd="$1"
+shift
+case "$cmd" in
+       free)
+               freebytes
+               ;;
+       total)
+               totalbytes
+               ;;
+       create)
+               createvol "$@"
+               ;;
+       remove)
+               removevol "$@"
+               ;;
+       device)
+               getdev "$@"
+               ;;
+       size)
+               getsize "$@"
+               ;;
+       up)
+               activatevol "$@"
+               ;;
+       down)
+               disactivatevol "$@"
+               ;;
+       status)
+               getstatus "$@"
+               ;;
+       write)
+               updatevol "$@"
+               ;;
+       *)
+               echo "unknown command"
+               return 1
+               ;;
+esac
diff --git a/utils/uvol/files/ubi.sh b/utils/uvol/files/ubi.sh
new file mode 100644 (file)
index 0000000..f2f2ab2
--- /dev/null
@@ -0,0 +1,160 @@
+#!/bin/sh
+
+test -e /sys/class/ubi/version || return 0
+read ubiver < /sys/class/ubi/version
+[ "$ubiver" = "1" ] || return 1
+test -e /sys/devices/virtual/ubi || return 0
+
+ubidev=$(ls -1 /sys/devices/virtual/ubi | head -n 1)
+
+read ebsize < "/sys/devices/virtual/ubi/${ubidev}/eraseblock_size"
+
+freebytes() {
+       read availeb < "/sys/devices/virtual/ubi/${ubidev}/avail_eraseblocks"
+       echo $((availeb * ebsize))
+}
+
+totalbytes() {
+       read totaleb < "/sys/devices/virtual/ubi/${ubidev}/total_eraseblocks"
+       echo $((totaleb * ebsize))
+}
+
+getdev() {
+       local voldir volname devname
+       for voldir in /sys/devices/virtual/ubi/${ubidev}/${ubidev}_*; do
+               read volname < "${voldir}/name"
+               [ "$volname" = "uvol-ro-$1" ] || [ "$volname" = "uvol-rw-$1" ] || continue
+               basename "$voldir"
+       done
+}
+
+needs_ubiblock() {
+       local voldev="$1"
+       local volname
+       read volname < "/sys/devices/virtual/ubi/${ubidev}/${voldev}/name"
+       case "$volname" in
+               uvol-ro-*)
+                       return 0
+                       ;;
+       esac
+       return 1
+}
+
+getstatus() {
+       local voldev=$(getdev "$@")
+       [ "$voldev" ] || return 2
+       needs_ubiblock $voldev && [ ! -e "/dev/ubiblock${voldev:3}" ] && return 1
+       return 0
+}
+
+getsize() {
+       local voldev
+       voldev=$(getdev "$@")
+       [ "$voldev" ] || return 2
+       cat /sys/devices/virtual/ubi/${ubidev}/${voldev}/data_bytes
+}
+
+getuserdev() {
+       local voldev=$(getdev "$@")
+       [ "$voldev" ] || return 2
+       if needs_ubiblock $voldev ; then
+               echo "/dev/ubiblock${voldev:3}"
+       else
+               echo "/dev/$voldev"
+       fi
+}
+
+createvol() {
+       local mode
+       local existdev=$(getdev "$1")
+       [ "$existdev" ] && return 17
+       case "$3" in
+               ro)
+                       mode=ro
+                       ;;
+               rw)
+                       mode=rw
+                       ;;
+               *)
+                       return 22
+                       ;;
+       esac
+       ubimkvol /dev/$ubidev -N "uvol-$mode-$1" -s "$2"
+}
+
+removevol() {
+       local voldev=$(getdev "$@")
+       [ "$voldev" ] || return 2
+       local volnum=${voldev#${ubidev}_}
+       ubirmvol /dev/$ubidev -n $volnum
+}
+
+activatevol() {
+       local voldev=$(getdev "$@")
+       [ "$voldev" ] || return 2
+       needs_ubiblock $voldev || return 0
+       [ -e "/dev/ubiblock${voldev:3}" ] && return 0
+       ubiblock --create /dev/$voldev
+}
+
+disactivatevol() {
+       local voldev=$(getdev "$@")
+       [ "$voldev" ] || return 2
+       needs_ubiblock $voldev || return 0
+       [ -e "/dev/ubiblock${voldev:3}" ] || return 0
+       ubiblock --remove /dev/$voldev
+}
+
+updatevol() {
+       local voldev=$(getdev "$@")
+       [ "$voldev" ] || return 2
+       [ "$2" ] || return 22
+       needs_ubiblock $voldev || return 22
+       ubiupdatevol -s $2 /dev/$voldev -
+}
+
+getstatus() {
+       local voldev=$(getdev "$@")
+       [ "$voldev" ] || return 2
+       needs_ubiblock $voldev && [ ! -e "/dev/ubiblock${voldev:3}" ] && return 1
+       return 0
+}
+
+cmd="$1"
+shift
+case "$cmd" in
+       free)
+               freebytes
+               ;;
+       total)
+               totalbytes
+               ;;
+       create)
+               createvol "$@"
+               ;;
+       remove)
+               removevol "$@"
+               ;;
+       device)
+               getuserdev "$@"
+               ;;
+       size)
+               getsize "$@"
+               ;;
+       up)
+               activatevol "$@"
+               ;;
+       down)
+               disactivatevol "$@"
+               ;;
+       status)
+               getstatus "$@"
+               ;;
+       write)
+               updatevol "$@"
+               ;;
+       *)
+               echo "unknown command"
+               return 1
+               ;;
+esac
diff --git a/utils/uvol/files/uvol b/utils/uvol/files/uvol
new file mode 100644 (file)
index 0000000..89c6518
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+uvol_backend=
+for backend in /usr/libexec/uvol/*.sh; do
+       total=$($backend total)
+       [ "$total" ] && uvol_backend=$backend
+done
+
+flock -x /tmp/run/uvol.lock $uvol_backend "$@"