From d876a63e8f08789d2c1663c0767c3e10362ca562 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sun, 5 Mar 2017 18:58:46 +0200 Subject: [PATCH] re-added pycurl package; initial work on platform update --- configs/bananapi_defconfig | 1 + configs/odroidc1_defconfig | 1 + configs/odroidc2_defconfig | 12 ++ configs/odroidxu4_defconfig | 1 + configs/raspberrypi2_defconfig | 1 + configs/raspberrypi3_defconfig | 1 + configs/raspberrypi_defconfig | 1 + package/motioneye/platformupdate.py | 53 ++++++ package/motioneye/update.py | 263 ---------------------------- 9 files changed, 71 insertions(+), 263 deletions(-) create mode 100644 package/motioneye/platformupdate.py delete mode 100644 package/motioneye/update.py diff --git a/configs/bananapi_defconfig b/configs/bananapi_defconfig index 1f72d3bdf6..ea0a6c3697 100644 --- a/configs/bananapi_defconfig +++ b/configs/bananapi_defconfig @@ -70,6 +70,7 @@ BR2_PACKAGE_PYTHON_SSL=y BR2_PACKAGE_PYTHON_HASHLIB=y BR2_PACKAGE_PYTHON_JINJA2=y BR2_PACKAGE_PYTHON_PILLOW=y +BR2_PACKAGE_PYTHON_PYCURL=y BR2_PACKAGE_PYTHON_PYTZ=y BR2_PACKAGE_PYTHON_TORNADO=y BR2_PACKAGE_PYTHON_VERSIONTOOLS=y diff --git a/configs/odroidc1_defconfig b/configs/odroidc1_defconfig index 82bcae8a82..b26e40cb86 100644 --- a/configs/odroidc1_defconfig +++ b/configs/odroidc1_defconfig @@ -75,6 +75,7 @@ BR2_PACKAGE_PYTHON_SSL=y BR2_PACKAGE_PYTHON_HASHLIB=y BR2_PACKAGE_PYTHON_JINJA2=y BR2_PACKAGE_PYTHON_PILLOW=y +BR2_PACKAGE_PYTHON_PYCURL=y BR2_PACKAGE_PYTHON_PYTZ=y BR2_PACKAGE_PYTHON_TORNADO=y BR2_PACKAGE_PYTHON_VERSIONTOOLS=y diff --git a/configs/odroidc2_defconfig b/configs/odroidc2_defconfig index 345f0292df..7e35a09c8d 100644 --- a/configs/odroidc2_defconfig +++ b/configs/odroidc2_defconfig @@ -24,7 +24,9 @@ BR2_PACKAGE_FFMPEG=y BR2_PACKAGE_FFMPEG_GPL=y BR2_PACKAGE_FFMPEG_NONFREE=y BR2_PACKAGE_FFMPEG_SWSCALE=y +BR2_PACKAGE_LIBWEBCAM=y BR2_PACKAGE_MOTION=y +BR2_PACKAGE_GZIP=y BR2_PACKAGE_JQ=y BR2_PACKAGE_CIFS_UTILS=y # BR2_PACKAGE_E2FSPROGS_BADBLOCKS is not set @@ -57,11 +59,21 @@ BR2_PACKAGE_LINUX_FIRMWARE_RTL_81XX=y BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX=y BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y BR2_PACKAGE_USB_MODESWITCH_DATA=y +BR2_PACKAGE_PYTHON_SSL=y +BR2_PACKAGE_PYTHON_HASHLIB=y +BR2_PACKAGE_PYTHON_JINJA2=y +BR2_PACKAGE_PYTHON_PILLOW=y +BR2_PACKAGE_PYTHON_PYCURL=y +BR2_PACKAGE_PYTHON_PYTZ=y +BR2_PACKAGE_PYTHON_RPI_GPIO=y +BR2_PACKAGE_PYTHON_TORNADO=y +BR2_PACKAGE_PYTHON_VERSIONTOOLS=y BR2_PACKAGE_CA_CERTIFICATES=y BR2_PACKAGE_NETTLE=y BR2_PACKAGE_LIBFUSE=y BR2_PACKAGE_JPEG=y BR2_PACKAGE_LIBV4L=y +BR2_PACKAGE_LIBV4L_UTILS=y BR2_PACKAGE_LIBXML2=y BR2_PACKAGE_LIBTHEORA=y BR2_PACKAGE_X264=y diff --git a/configs/odroidxu4_defconfig b/configs/odroidxu4_defconfig index d99c7ca9d3..c84538e2b0 100644 --- a/configs/odroidxu4_defconfig +++ b/configs/odroidxu4_defconfig @@ -65,6 +65,7 @@ BR2_PACKAGE_PYTHON_SSL=y BR2_PACKAGE_PYTHON_HASHLIB=y BR2_PACKAGE_PYTHON_JINJA2=y BR2_PACKAGE_PYTHON_PILLOW=y +BR2_PACKAGE_PYTHON_PYCURL=y BR2_PACKAGE_PYTHON_PYTZ=y BR2_PACKAGE_PYTHON_TORNADO=y BR2_PACKAGE_PYTHON_VERSIONTOOLS=y diff --git a/configs/raspberrypi2_defconfig b/configs/raspberrypi2_defconfig index 4c876eb972..6f251e042e 100644 --- a/configs/raspberrypi2_defconfig +++ b/configs/raspberrypi2_defconfig @@ -70,6 +70,7 @@ BR2_PACKAGE_PYTHON_SSL=y BR2_PACKAGE_PYTHON_HASHLIB=y BR2_PACKAGE_PYTHON_JINJA2=y BR2_PACKAGE_PYTHON_PILLOW=y +BR2_PACKAGE_PYTHON_PYCURL=y BR2_PACKAGE_PYTHON_PYTZ=y BR2_PACKAGE_PYTHON_RPI_GPIO=y BR2_PACKAGE_PYTHON_TORNADO=y diff --git a/configs/raspberrypi3_defconfig b/configs/raspberrypi3_defconfig index 91f3f40fb4..204286c3dc 100644 --- a/configs/raspberrypi3_defconfig +++ b/configs/raspberrypi3_defconfig @@ -70,6 +70,7 @@ BR2_PACKAGE_PYTHON_SSL=y BR2_PACKAGE_PYTHON_HASHLIB=y BR2_PACKAGE_PYTHON_JINJA2=y BR2_PACKAGE_PYTHON_PILLOW=y +BR2_PACKAGE_PYTHON_PYCURL=y BR2_PACKAGE_PYTHON_PYTZ=y BR2_PACKAGE_PYTHON_RPI_GPIO=y BR2_PACKAGE_PYTHON_TORNADO=y diff --git a/configs/raspberrypi_defconfig b/configs/raspberrypi_defconfig index 3f89ed2c7a..5d8c8e4f27 100644 --- a/configs/raspberrypi_defconfig +++ b/configs/raspberrypi_defconfig @@ -72,6 +72,7 @@ BR2_PACKAGE_PYTHON_SSL=y BR2_PACKAGE_PYTHON_HASHLIB=y BR2_PACKAGE_PYTHON_JINJA2=y BR2_PACKAGE_PYTHON_PILLOW=y +BR2_PACKAGE_PYTHON_PYCURL=y BR2_PACKAGE_PYTHON_PYTZ=y BR2_PACKAGE_PYTHON_RPI_GPIO=y BR2_PACKAGE_PYTHON_TORNADO=y diff --git a/package/motioneye/platformupdate.py b/package/motioneye/platformupdate.py new file mode 100644 index 0000000000..5f8caff60d --- /dev/null +++ b/package/motioneye/platformupdate.py @@ -0,0 +1,53 @@ + +# Copyright (c) 2017 Calin Crisan +# This file is part of motionEyeOS. +# +# motionEyeOS is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import logging +import os +import subprocess + + +def get_all_versions(): + try: + return subprocess.check_output('fwupdate versions', shell=True).strip().split('\n') + + except Exception as e: + logging.error('failed to list versions: %s' % e) + + +def perform_update(version): + logging.info('stopping motioneye watch script') + os.system('kill $(pidof S85motioneye)') + + logging.info('stopping netwatch script') + os.system('/etc/init.d/S41netwatch stop') + + logging.error('downloading firmware version %s' % version) + if os.system('fwupdate download %s > /dev/null' % version): + logging.error('firmware download failed') + + logging.error('extracting firmware') + if os.system('fwupdate extract > /dev/null'): + logging.error('firmware extracting failed') + + logging.error('flashing boot partition') + if os.system('fwupdate flashboot > /dev/null'): + logging.error('firmware flash boot failed') + + logging.error('rebooting') + if os.system('fwupdate flashreboot > /dev/null'): + logging.error('firmware flash reboot failed') + diff --git a/package/motioneye/update.py b/package/motioneye/update.py deleted file mode 100644 index e9fd184b4b..0000000000 --- a/package/motioneye/update.py +++ /dev/null @@ -1,263 +0,0 @@ - -# Copyright (c) 2015 Calin Crisan -# This file is part of motionEyeOS. -# -# motionEyeOS is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import json -import logging -import os.path -import re -import shutil -import ssl -import subprocess -import time -import urllib2 - -import settings - - -_BOARD = open('/etc/board').read().strip() -_REPO = ('ccrisan', 'motioneyeos') -_DOWNLOAD_URL = 'https://github.com/{owner}/{repo}/releases/download/%(version)s/motioneyeos-%(board)s-%(version)s.img.gz'.format( - owner=_REPO[0], repo=_REPO[1]) -_LIST_VERSIONS_URL = 'https://api.github.com/repos/{owner}/{repo}/releases'.format( - owner=_REPO[0], repo=_REPO[1]) -_DOWNLOAD_DIR = '/data/.firmware_update' -_DOWNLOAD_FILE_NAME = os.path.join(_DOWNLOAD_DIR, 'firmware.gz') - - -# versions - -def get_version(): - import motioneye - - return motioneye.VERSION - - -def get_all_versions(): - url = _LIST_VERSIONS_URL - url += '?_=' + str(int(time.time())) # prevents caching - - want_prereleases = subprocess.check_output('source /data/etc/os.conf && echo $os_prereleases', shell=True, stderr=subprocess.STDOUT).strip() == 'true' - - try: - logging.debug('board is %s' % _BOARD) - logging.debug('fetching %s...' % url) - - context = ssl._create_unverified_context() - - response = urllib2.urlopen(url, timeout=settings.REMOTE_REQUEST_TIMEOUT, context=context) - releases = json.load(response) - - versions = [] - for release in releases: - if release.get('prerelease') and not want_prereleases: - continue - - for asset in release.get('assets', []): - if not re.match('^motioneyeos-%s-\d{8}\.img.gz$' % _BOARD, asset['name']): - continue - - versions.append(release['name']) - - logging.debug('available versions: %(versions)s' % {'versions': ', '.join(versions)}) - - return sorted(versions) - - except Exception as e: - logging.error('could not get versions: %s' % e, exc_info=True) - - return [] - - -def compare_versions(version1, version2): - version1 = re.sub('[^0-9.]', '', version1) - version2 = re.sub('[^0-9.]', '', version2) - - def int_or_0(n): - try: - return int(n) - - except: - return 0 - - version1 = [int_or_0(n) for n in version1.split('.')] - version2 = [int_or_0(n) for n in version2.split('.')] - - len1 = len(version1) - len2 = len(version2) - length = min(len1, len2) - for i in xrange(length): - p1 = version1[i] - p2 = version2[i] - - if p1 < p2: - return -1 - - elif p1 > p2: - return 1 - - if len1 < len2: - return -1 - - elif len1 > len2: - return 1 - - else: - return 0 - - -# updating - -def download(version): - url = _DOWNLOAD_URL % {'version': version, 'board': _BOARD} - - try: - logging.info('downloading %s...' % url) - - shutil.rmtree(_DOWNLOAD_DIR, ignore_errors=True) - os.makedirs(_DOWNLOAD_DIR) - subprocess.check_call(['/usr/bin/wget', url, '--no-check-certificate', '-O', _DOWNLOAD_FILE_NAME]) - - except Exception as e: - logging.error('could not download update: %s' % e) - - raise - - try: - logging.info('decompressing %s...' % _DOWNLOAD_FILE_NAME) - - subprocess.check_call(['/bin/gunzip', _DOWNLOAD_FILE_NAME]) - - except Exception as e: - logging.error('could not decompress archive: %s' % e) - - raise - - extracted_file_name = _DOWNLOAD_FILE_NAME.replace('.gz', '') - - try: - logging.info('reading partiton table...') - - output = subprocess.check_output(['/sbin/fdisk', '-l', extracted_file_name]) - lines = [l.strip().replace('*', ' ') for l in output.split('\n') if l.startswith(extracted_file_name)] - boot_info = lines[0].split() - root_info = lines[1].split() - - boot_start, boot_end = int(boot_info[1]), int(boot_info[2]) - root_start, root_end = int(root_info[1]), int(root_info[2]) - - except Exception as e: - logging.error('could not read partition table: %s' % e) - - raise - - try: - logging.info('extracting boot.img...') - - subprocess.check_call(['/bin/dd', 'if=' + extracted_file_name, 'of=' + os.path.join(_DOWNLOAD_DIR, 'boot.img'), - 'bs=2048', 'skip=' + str(boot_start / 4), 'count=' + str((boot_end - boot_start + 1) / 4)]) - - except Exception as e: - logging.error('could not extract boot.img: %s' % e) - - raise - - try: - logging.info('extracting root.img...') - - subprocess.check_call(['/bin/dd', 'if=' + extracted_file_name, 'of=' + os.path.join(_DOWNLOAD_DIR, 'root.img'), - 'bs=2048', 'skip=' + str(root_start / 4), 'count=' + str((root_end - root_start + 1) / 4)]) - - except Exception as e: - logging.error('could not extract root.img: %s' % e) - - raise - - -def perform_update(version): - logging.info('updating to version %(version)s...' % {'version': version}) - - logging.info('killing motioneye init script...') - os.system('kill $(pidof S85motioneye)') - - logging.info('stopping netwatch init script...') - os.system('/etc/init.d/S41netwatch stop') - - download(version) - - logging.info('backing up /boot/config.txt') - if os.system('/bin/cp /boot/config.txt /tmp/config.txt'): - logging.error('failed to backup /boot/config.txt') - - raise Exception('failed to backup /boot/config.txt') - - logging.info('unmounting boot partition...') - if os.system('/bin/umount /boot'): - logging.error('failed to unmount boot partition') - - raise Exception('failed to unmount boot partition') - - try: - logging.info('installing boot image...') - boot_img = os.path.join(_DOWNLOAD_DIR, 'boot.img') - - subprocess.check_call(['/bin/dd', 'if=' + boot_img, 'of=/dev/mmcblk0p1', 'bs=1M']) - - except Exception as e: - logging.error('could not install boot image: %s' % e) - - raise - - logging.info('mounting boot partition read-write...') - if os.system('/bin/mount -o rw /dev/mmcblk0p1 /boot'): - logging.error('failed to mount boot partition') - - raise Exception('failed to mount boot partition') - - logging.info('restoring up /boot/config.txt') - if os.system('/bin/cp /tmp/config.txt /boot/config.txt'): - logging.error('failed to restore /boot/config.txt') - - raise Exception('failed to restore /boot/config.txt') - - logging.info('preparing to boot in fwupdate mode...') - try: - config_lines = [c.strip() for c in open('/boot/config.txt', 'r').readlines() if c.strip()] - - except Exception as e: - logging.error('failed to read /boot/config.txt: %s' % e, exc_info=True) - - raise - - config_lines.append('initramfs fwupdater.gz') - - try: - with open('/boot/config.txt', 'w') as f: - for line in config_lines: - f.write(line + '\n') - - except Exception as e: - logging.error('failed to write /boot/config.txt: %s' % e, exc_info=True) - - raise - - logging.info('rebooting...') - - if os.system('/sbin/reboot'): - logging.error('failed to reboot') - logging.info('hard rebooting...') - open('/proc/sysrq-trigger', 'w').write('b') # reboot -