diff options
author | James Meyer <james.meyer@operamail.com> | 2013-02-19 21:10:18 (GMT) |
---|---|---|
committer | James Meyer <james.meyer@operamail.com> | 2013-02-19 21:10:18 (GMT) |
commit | 2648e999d277eac5c3d331a3609bcc73fafbea71 (patch) | |
tree | 40951fb8e7fdbe28a0baa324ae615055203f1e2e /abs/core/LinHES-system | |
parent | c759b5e0c4aa6fc37412b4dee2cf9ad993fd376d (diff) | |
parent | 7e6f7ca174e1af67178dc5293a312a4a733eb095 (diff) | |
download | linhes_pkgbuild-2648e999d277eac5c3d331a3609bcc73fafbea71.zip linhes_pkgbuild-2648e999d277eac5c3d331a3609bcc73fafbea71.tar.gz linhes_pkgbuild-2648e999d277eac5c3d331a3609bcc73fafbea71.tar.bz2 |
Merge branch 'testing'
# By James Meyer (1091) and others
# Via James Meyer (5) and others
* testing: (1148 commits)
LinHES-config: during install don't kill off lirc. This keeps the remote active all the way to the finish
Change version numbers to 8.0 to match the release number. LinHES-conifg LinHES-system mythdb-initial runit-scripts supplemental-web
LinHES-conifig: mv_install.py for the last partition don't go all the way to the end. Gotta leave room for gpt tables.
xf86-video-ati: xorg ati driver.
LinHES-config: timezip.py add syncing up of parental lvl passwords and starting level with MBE.
LinHES-system: correct the logic for breaking out of the wmctrl loop. As written it would break out of the inner loop..but not the 60 iteration loop.
e16_theme_settings: remove slide-in prop for new windows. For whatever reason this was preventing mplayer from being positioned correctly for appletrailers.
LinHES-config, mythinstall: change case of hd_pvr and serial to all lower refs #902
zilog-firmware: firmware for TX support of the hdpvr and pvr-150 In general I can't recommend anybody using these transmitters but including the firmware just in case someone really wants to
linhes-udev-rules: added hdprv_lirc rule. All of these lirc rules are limited to exactly one device. If more then one device is present then only the last device in init will get the symlink
runit-scripts: fix logging for igdeamon, add support to remote init script so that the blaster is always the first device in the chain. added support specificly for hd_pvr
LinHES-system: add lh_system_restore and lh_system_backup. These scripts are called from the mythmenu. refs #900
iguanair: rebuild with python 2.7
LinHES-system: msg_daemon.py fix init and nasty bug related to timeout. In a nutshell timeout wouldn't work unless a msg without a timeout was called first.
linhes-udev-rules: add rules for mce,streamzap,serial lirc devices.
mythinstall: recompile for matching libs
mythtv: latest .25-fixes and change mythbackup/restore call lh_system_$op to replace mythbackup/mythrestore. mythbackup no longer works correctly with the new windowmanager
linhes-scripts: myth2mp3, myth2x264, myth2xvid: use mythutil to get cutlist
LinHES-config, supplimental-web: Fix proxy numbering for Ceton infiniTV
linhes-system: add additional stuff to the system backup and also introduced an exclude file. The exclude/include files are locate in /home/mythtv/backup_config/
...
Diffstat (limited to 'abs/core/LinHES-system')
46 files changed, 3380 insertions, 484 deletions
diff --git a/abs/core/LinHES-system/LinHES-profile.sh b/abs/core/LinHES-system/LinHES-profile.sh index 830b819..4035c30 100644 --- a/abs/core/LinHES-system/LinHES-profile.sh +++ b/abs/core/LinHES-system/LinHES-profile.sh @@ -1,3 +1,5 @@ #!/bin/bash export LinHES_ROOT=/usr/LH -export PATH=$PATH:/usr/LH/bin
\ No newline at end of file +export PATH=$PATH:/usr/LH/bin +#this enables airplay support +export MYTHTV_AIRPLAY="1"
\ No newline at end of file diff --git a/abs/core/LinHES-system/LinHES-session b/abs/core/LinHES-system/LinHES-session index 918406d..61405db 100755 --- a/abs/core/LinHES-system/LinHES-session +++ b/abs/core/LinHES-system/LinHES-session @@ -1,7 +1,15 @@ #!/bin/bash +MYTH_RUN_STATUS="1" . /etc/profile . /etc/systemconfig + +#set some defaults, then override from /etc/X11/WINDOWMANAGER +configdir="/usr/share/wm_data" +WM="e16 -P $configdir/e16_config_dir/" +STARTUP_STYLE=enhanced + + if [ -e /etc/X11/WINDOWMANAGER ] then . /etc/X11/WINDOWMANAGER @@ -13,6 +21,9 @@ xset -dpms s off export MALLOC_CHECK_=0 +MYTH_ARGS="-d --syslog local6" +[ -f /etc/conf.d/mythfrontend ] && . /etc/conf.d/mythfrontend + # # Run any scripting that applies to special hardware. These brand-specific commands that run @@ -46,25 +57,25 @@ export MALLOC_CHECK_=0 # font="-adobe-helvetica-bold-*-*-*-34-*-*-*-*-*-*-*" # } # -function delay_osd(){ - if [ x$STARTUP_STYLE = xmythvantage ] - then - cmd="ps -ef | grep -v grep | grep -q xmsg.py" - else - cmd="ps -ef | grep -v grep | grep -q osd_cat" - fi - - eval $cmd - - rc=$? - while [ $rc = 0 ] - do - eval $cmd - rc=$? - done - - - } +# function delay_osd(){ +# if [ x$STARTUP_STYLE = xenhanced ] +# then +# cmd="ps -ef | grep -v grep | grep -q xmsg.py" +# else +# cmd="ps -ef | grep -v grep | grep -q osd_cat" +# fi +# +# eval $cmd +# +# rc=$? +# while [ $rc = 0 ] +# do +# eval $cmd +# rc=$? +# done +# +# +# } # # function msg_osd(){ # echo -e "$1" | osd_cat --pos=middle --align=center --offset=200 --delay=5 --color=$color --outline=$outline --outlinecolour=$outlinecolour --shadow=$shadow --shadowcolour=$shadowcolour --font=$font @@ -75,18 +86,13 @@ function delay_osd(){ # } function msg(){ -# if [ x$STARTUP_STYLE = xmythvantage ] -# then -# msg_pyosd "$1" -# else -# msg_osd "$1" -# fi - /usr/LH/bin/lh_message.sh "$1" + #/usr/LH/bin/lh_message.sh "$1" + /usr/LH/bin/msg_client.py --msg "$1" } function unclutter(){ - if [ -e /etc/unclutter ] + if [ -e /etc/unclutter.cfg ] then . /etc/unclutter.cfg else @@ -94,7 +100,7 @@ function unclutter(){ jitter=200 fi - /usr/X11R6/bin/unclutter -root -idle $idle -jitter $jitter -noevents & + /usr/bin/unclutter -root -idle $idle -jitter $jitter -noevents & } function keylaunch(){ @@ -111,6 +117,31 @@ function keylaunch(){ } +function start_x11vnc(){ + if [ x$xvncenable = "x1" ] + then + if [ -e /etc/x11vnc.cfg ] + then + . /etc/x11vnc.cfg + x11vnc $x11vnc_options + else + x11vnc -rfbport 5902 --passwd $xvncpassword + fi + fi +} + + +function fluxbox_settings(){ + if [ ! -e $HOME/.fluxbox ] + then + echo "setting symlink fluxbox" + configdir=/usr/share/fluxbox_settings + ln -s $configdir $HOME/.fluxbox + fi + +} + + function load_nvidia_settings(){ lsmod |cut -f1 -d" " |grep -q nvidia @@ -180,12 +211,11 @@ function show_help_tip(){ if [ x$ShowTips = "x1" ] then - msg "Alt+h for help" & + msg "Alt+h for help" fi } function notify_scan(){ - delay_osd if [ -e /tmp/scan_report ] then msg "\nNew storage found. \nRun add_storage.py for details" @@ -193,6 +223,17 @@ function notify_scan(){ } +function auto_start(){ + asdir="/etc/X11/autostart" + for i in `ls $asdir/*` + do + if [ -x $i ] + then + echo "Starting $i" + $i & + fi + done + } function update_apple_trailers(){ #update apple trailers @@ -204,7 +245,7 @@ function update_apple_trailers(){ function first_configure(){ - if [ x$STARTUP_STYLE = xmythvantage ] + if [ ! x$STARTUP_STYLE = xlegacy ] then first_configure_mv else @@ -231,7 +272,6 @@ function first_configure_default(){ fi sudo sv stop mythbackend - /usr/LH/bin/dtheme.sh xterm -fn *18* -e sudo taskset -c 0 /usr/bin/mythtv-setup sudo sv start mythbackend sudo chown -R mythtv.mythtv /home/mythtv @@ -239,7 +279,13 @@ function first_configure_default(){ msg "Guide data is being loaded. \n Until this completes\n some shows will appear as unknown \n in the program guide." rm ~/.configure fi + else + if [ -f ~/.configure ] + then + rm -f ~/.configure + fi fi + } @@ -248,18 +294,24 @@ function first_configure_mv(){ then if [ -f ~/.configure ] then - msg "This is the first time starting MythTV.\nThe MythTV backend process will be stopped for setup." + msg "New install of LinHES; starting setup." #for now skip these #autocard.py -g & #MythVantage -b #0 yes #1 yes/autodetech #2 no + while [ -e '/var/run/autocard.lock' ] + do + msg "Waiting for capture card detection to complete" + sleep 5 + done STATUS=$? if [ ! $STATUS = 2 ] then /usr/MythVantage/bin/backend_control.sh stop BE 127.0.0.1 msg "MythTV setup is starting.\nPlease follow the steps for adding tuners and guide data." + run_wmctrl & /usr/bin/taskset -c 0 /usr/bin/mythtv-setup /usr/MythVantage/bin/backend_control.sh start BE 127.0.0.1 fi @@ -267,6 +319,11 @@ function first_configure_mv(){ msg "Guide data is being loaded. \nUntil this completes \nsome shows will appear as "unknown" \nin the program guide." rm -f ~/.configure fi + else + if [ -f ~/.configure ] + then + rm -f ~/.configure + fi fi } @@ -280,17 +337,28 @@ function start_myth() { then STARTCMD="/usr/bin/mythfrontend -d -l /var/log/mythtv/mythfrontend.log" else - STARTCMD="/usr/bin/mythfrontend -d --syslog local6" + STARTCMD="/usr/bin/mythfrontend $MYTH_ARGS" fi fi echo "=====================================================================" echo "Starting $STARTCMD" - firstboot.sh & + if [ "x$bewait" = "x1" ] + then + #do init check + /usr/LH/bin/be_check.py + rc=$? + while [ $rc -ne 0 ] + do + msg "Waiting for connection to MythBackend" + /usr/LH/bin/be_check.py + rc=$? + sleep 6 + done + fi #continue on with starting mythtv - - if [ x$STARTUP_STYLE = xmythvantage ] + if [ ! x$STARTUP_STYLE = xlegacy ] then start_myth_mv else @@ -299,6 +367,28 @@ function start_myth() { } +function run_wmctrl(){ + done="False" + for i in `seq 60` + do + for name in "MythTV Frontend" "MythTV Setup" "mythwelcome" + do + xwininfo -name "$name" >/dev/null + rcx=$? + if [ $rcx = 0 ] + then + wmctrl -r "$name" -b remove,fullscreen + done="True" + fi + done + if [ $done = "True" ] + then + break + fi + sleep 5 + done + +} function run_myth(){ if [ -f /tmp/nomfe ] @@ -315,8 +405,10 @@ function run_myth(){ killall -9 irexec /usr/bin/irexec -d - if [ x$STARTUP_STYLE = xmythvantage ] + if [ ! x$STARTUP_STYLE = xlegacy ] then + + run_wmctrl & $STARTCMD 2>&1 else $STARTCMD 2>&1 & @@ -340,39 +432,56 @@ function set_background() { echo "Setting the background" - } +} +# if [ x"$WM" = "xdefault" ] +# then +# # fluxbox > /var/log/fluxbox.log 2>&1 +# WM=fluxbox +# fi +# +# +# if [ x"$WM" = "x" ] +# then +# # fluxbox > /var/log/fluxbox.log 2>&1 +# WM=fluxbox +# fi +# -if [ x$WM = "x" ] +if [ $WM = "fluxbox" ] then -# fluxbox > /var/log/fluxbox.log 2>&1 - WM=fluxbox + fluxbox_settings fi + + #if using mythvantage style, start the WM right away # this is done so that starting mythtv can loop. $WM & pid=$! mouse_move keylaunch -set_background +start_x11vnc & +#set_background unclutter load_nvidia_settings run_tilda start_screensaver -show_help_tip notify_scan & +auto_start & update_apple_trailers first_configure +show_help_tip start_myth # wait for the windowmanger #This will make the session wait on the WM to exit. -if [ x$STARTUP_STYLE != xmythvantage ] +if [ x$STARTUP_STYLE = xlegacy ] then wait $pid fi +wmctrl -r "MythTV Frontend" -b remove,fullscreen diff --git a/abs/core/LinHES-system/LinHES-system.install b/abs/core/LinHES-system/LinHES-system.install new file mode 100644 index 0000000..f2185cd --- /dev/null +++ b/abs/core/LinHES-system/LinHES-system.install @@ -0,0 +1,12 @@ +## arg 1: the new package version +post_install() { + /usr/LH/bin/misc_status_config.py +} + +## arg 1: the new package version +## arg 2: the old package version +post_upgrade() { + /usr/LH/bin/misc_status_config.py +} + +# vim:set ts=2 sw=2 et: diff --git a/abs/core/LinHES-system/LinHES.install b/abs/core/LinHES-system/LinHES.install deleted file mode 100644 index c9950f2..0000000 --- a/abs/core/LinHES-system/LinHES.install +++ /dev/null @@ -1,104 +0,0 @@ -# This is a default template for a post-install scriptlet. You can -# remove any functions you don't need (and this header). - -# arg 1: the new package version -pre_install() { -/bin/true -} - -# arg 1: the new package version -post_install() { -MVDIR=/usr/LH/bin -# ln -s $MVDIR/backup_job /etc/cron.daily/backup_cron -# ln -s $MVDIR/update_system /etc/cron.daily/xupdate_system_cron -# ln -s $MVDIR/repo_sync.sh /etc/cron.daily/zrepo_sync.sh - if [ ! -e /etc/cron.daily/myth_mtc ] - then - ln -s $MVDIR/myth_mtc.sh /etc/cron.daily/myth_mtc - fi - if [ -e /etc/cron.daily/myth_mtc.sh ] - then - rm -f /etc/cron.daily/myth_mtc.sh - fi -#LINE="mythtv ALL = NOPASSWD: /sbin/sv stop mythbackend" -LINE="mythtv ALL=(ALL) NOPASSWD: ALL" -LINE1="%wheel ALL=(ALL) NOPASSWD: ALL" - - -for i in "$LINE" "$LINE1" "$LINE2" "$LINE3" "$LINE4" "$LINE5" "$LINE7" "$LINE8" "$LINE9" "$LINE10" "$LINE11" "$LINE12" "$LINE13" "$LINE14" "$LINE15" "$LINE16" -do - cp /etc/sudoers /etc/sudoers.bak - grep -q "$i" /etc/sudoers - if [ $? != 0 ] - then - echo "$i" >> /etc/sudoers - visudo -cf /etc/sudoers - if [ ! $? = 0 ] - then - cp /etc/sudoers.bak /etc/sudoers - echo $i - echo "Error adding files" - exit 1 - fi - fi -done - -REALTIME="session required pam_limits.so" -grep -q "pam_limits.so" /etc/pam.d/su - if [ $? != 0 ] - then - echo "$REALTIME" >> /etc/pam.d/su - - fi - -# Update mythtv's fluxbox keys files to use the tvterm.sh script to get -# an xterm. Then signal fluxbox to re-read the keys file. - -sed -i.orig 's/^Mod1 x :.*xterm.*$/Mod1 x :ExecCommand tvterm.sh/g' \ - ~mythtv/.fluxbox/keys -pkill -HUP fluxbox - - - - -} - -# arg 1: the new package version -# arg 2: the old package version -pre_upgrade() { - if [ -e /etc/cron.daily/backup_cron ] - then - rm -f /etc/cron.daily/backup_cron - fi - if [ -e /etc/cron.daily/xupdate_system_cron ] - then - rm -f /etc/cron.daily/xupdate_system_cron - fi - - if [ -e /etc/cron.daily/myth_mtc.py ] - then - rm -f /etc/cron.daily/myth_mtc.py - fi - - -} - -# arg 1: the new package version -# arg 2: the old package version -post_upgrade() { - post_install -} - -# arg 1: the old package version -pre_remove() { - /bin/true -} - -# arg 1: the old package version -post_remove() { - /bin/true -} - -op=$1 -shift -$op $* diff --git a/abs/core/LinHES-system/PKGBUILD b/abs/core/LinHES-system/PKGBUILD index 6881e3c..a049353 100644..100755 --- a/abs/core/LinHES-system/PKGBUILD +++ b/abs/core/LinHES-system/PKGBUILD @@ -1,30 +1,46 @@ pkgname=LinHES-system -pkgver=2 -pkgrel=52 -arch=('i686') +pkgver=8.0 +pkgrel=1 +arch=('i686' 'x86_64') MVDIR=$startdir/pkg/usr/LH BINDIR=$startdir/pkg/usr/bin -install=LinHES.install +install=system.install pkgdesc="scripts and things related to having an automated system" -depends=(linhes-sounds xdotool fluxbox tilda keylaunch python_aosd 'linhes-scripts>=7-24' 'runit-scripts>=2.1.1-43' 'udisks' 'LinHES-config>=2.3-59') +depends=(linhes-sounds xdotool tilda keylaunch python_aosd 'linhes-scripts>=7-24' 'udisks' 'LinHES-config>=2.3-59' 'sudo' 'python2-dbus' 'unclutter' 'wmctrl' 'archlinux-xdg-menu' 'ethtool') backup=(etc/modprobe.d/alsa-base) binfiles="LinHES-start optimize_mythdb.py myth_mtc.py myth_mtc.sh LinHES-run - firstboot.sh load-modules-mythvantage.sh + load-modules-mythvantage.sh unclutter-toggle.sh tvterm.sh mythfrontend-start set_windowmanager.sh myth_status.py myth_status.sh - xmsg.py install_supplemental_service.sh + install_supplemental_service.sh + lh_system_backup lh_system_backup_job lh_system_restore_job lh_system_host_update lh_system_all_host_update add_storage.py diskspace.sh - cacheclean lh_message.sh switch_web.sh" + cacheclean lh_backend_control.sh switch_web.sh + create_media_dirs.sh + msg_client.py msg_daemon.py + gen_is_xml.py gen_lib_xml.py gen_light_include.py gen_game_xml.py + misc_recent_recordings.pl + misc_status_config.py + misc_status_info.sh + misc_upcoming_recordings.pl + misc_which_recorder.pl + change_channel.sh change_channel_wrapper.sh + be_check.py" + +source=(LinHES-session + LinHES-profile.sh $binfiles + alsa-base myth_mtc.lr + diskspace cacheclean.cron + readme_is_xml readme_light add_storage.readme + system-sudo.rules ) -source=(LinHES-session LinHES-profile.sh $binfiles alsa-base myth_mtc.lr - diskspace smolt.cron cacheclean.cron) build() { cd $startdir/src install -m755 -D LinHES-session $startdir/pkg/etc/X11/Sessions/LinHES @@ -34,52 +50,82 @@ build() { do item=$i install -m755 -D $item $MVDIR/bin/$item - echo $item + echo "installing $item to $MVDIR" done - cd $startdir/bin - for i in * - do - item=$i - install -m755 -D $item $MVDIR/bin/$item - echo $item - done +# cd $startdir/bin +# for i in * +# do +# item=$i +# install -m755 -D $item $MVDIR/bin/$item +# echo "bin stuff: $item" +# done install -m644 -D $startdir/src/alsa-base $startdir/pkg/etc/modprobe.d/alsa-base.conf - install -m755 -D $startdir/src/smolt.cron $startdir/pkg/etc/cron.weekly/smolt.cron + install -m644 -D $startdir/src/readme_is_xml $startdir/pkg/etc/gen_is_xml.d/readme_is_xml + install -m644 -D $startdir/src/readme_is_xml $startdir/pkg/etc/gen_lib_xml.d/readme_gen_xml + install -m644 -D $startdir/src/readme_is_xml $startdir/pkg/etc/gen_game_xml.d/readme_gen_xml + install -m644 -D $startdir/src/readme_light $startdir/pkg/etc/gen_light_conf.d/readme_gen_light + install -m644 -D $startdir/src/add_storage.readme $startdir/pkg/etc/storage.d/readme + # install -m755 -D $startdir/src/smolt.cron $startdir/pkg/etc/cron.weekly/smolt.cron install -m755 -D $startdir/src/cacheclean.cron $startdir/pkg/etc/cron.weekly/cacheclean.cron install -m755 -D $startdir/src/diskspace $startdir/pkg/etc/cron.tenminutes/diskspace - mkdir $startdir/pkg/etc/logrotate.d - cp $startdir/myth_mtc.lr $startdir/pkg/etc/logrotate.d + install -m644 -D $startdir/src/myth_mtc.lr $startdir/pkg/etc/logrotate.d/myth_mtc + + + #sudo rules + mkdir -p $startdir/pkg/etc/sudoers.d/ + chmod 750 $startdir/pkg/etc/sudoers.d/ + chown -R root:root $startdir/pkg/etc/sudoers.d + install -o root -g root -m 0750 $startdir/src/system-sudo.rules $startdir/pkg/etc/sudoers.d/system_sudo + + } -md5sums=('d1a5963c5a440a608031c6d750232633' - '5881bdb43d578ec3a79d1f77ea58a3db' +md5sums=('08abf577578dd805bab7cd9eba90965a' + 'de32a1c50101265dd7f6ca5037f7a26a' 'a875ee97f86e46f34a741c2bc455f894' '76b2637cac0452b3acdbeeb4e8a5474b' - 'd1f27cb422010077c841376526fe46ea' - '2ef9f945e034119f77d9b6beb17e4fa5' + '781c977f8872543f033dad2caaf0458e' + '6f5b757524d905b5d2420519a88edc93' '4b4585ccba30595cf958d202997c57f7' - 'cbe4cba14fa9d01a62e2196edc1bd98b' 'dc3eef2a624754e16805d72bbe488b67' 'dc0be354ce77ba2b89868fc29b942c43' '542e670e78d117657f93141e9689f54d' - '48b763dba127aac6ab05c84643f83b71' - 'ba351b92e69bcaf26a9bf80417b09c3c' - '294e54209538018008323d164ce39fb3' + '41951459ea9d2b0567be521b67e6285a' + 'bb72ab230c7a71706285bd0f31a4fb1f' + '692563448cca1d49f45e7d1c8abcaa0c' '962a3e9eaba2d1466251b7ab0956705d' - 'd03aedeeeda0f5e9c1eb437411c88477' - '94ce8f1d5085c0db7b267db8c2e9a3ff' - '16a2a3347961517fe7d95a2956a091a6' - '9c2294ccfd5359583497a6b03d918a27' - '859a80ddb4c234506379c605114c1343' + '1758aed160de64abfafb28a3a8f3390e' + '3edef50a49a47694bf8add39cc160add' + '5e17e0786afd891550a660f646076308' + 'bc69a520add58ede9b060c73e67ace13' + '1be1d3dfc83f828eede93055713882ae' '47e093e8cfe4b5b96602358e1f540832' - '6faeba0aeb38e772121f751cabda8683' - '68e3e87571f3b0fa4a48a10df50dc220' - '9603b0ca6e090eff31e76482a3c335e7' - 'b798ee0796d1b760a2998f90eb8ce9cc' + 'a8e486f5d23913242b6edb862bf44c0e' + 'b9b0a8370f46f0b5e144a66897e8eefb' + '6519d209e151cdc39ae7e1091d189c3e' + '8f474e019d5fcb775497aca355d61b0b' '4a3cd8f9b33b2b86fdba47a8f1fa2859' + '16f079dab35dde6efd55bf6cf4e2fb2f' + '0e76cd8f320a852a162931450a1fb8b7' + '645297f5905e87eb99999d5a0f3f069a' + 'ea315f41dcd6c978e546c95fc05546cf' + 'ac61cc460d9e97ba1f5ef69e92cdfbe5' + 'f3502bb7c665750da0ecdf6918f7c838' + 'b7febd04f64fe21e8cfbb888219b0b31' + '06a628469051237943b7c874f2e29b8a' + '54ebcc024db2e0ebe8121305d8926767' + '45f46d1f9193c8dde18e56369ec29a1e' + 'a8edbe7bc37e9932e8749d9f5f89c16f' + '116b0f62ed4e8dd6e437930deeb6e49e' + '17f678d37187be0f12d67f64e40429c6' + 'bacc813b48bafcc6fe906e5969930501' + '8b0298f70f97cc1dc2a58b9a73c64bd3' 'eb879fee9603a05d5420d4ce8ed9e450' - 'f1870a9522c79e6b248fcbf81dec3280' + '6782771960c495aeb597893f37d1e5ee' '84492954db16740f949d795b74383189' - 'abe887472a170bd1a8e6da6a7b7e93e4' - '02c810c2f47b7c4495fdacaf54189473') + '02c810c2f47b7c4495fdacaf54189473' + '1e2ca4dd872a50df6b70528e06df558a' + '59d0602bac7e06f11abba1894acc8bb0' + 'da432d68962e109e09beb2b71c8c8571' + '366ccb097d1c221389709485c3b2d159') diff --git a/abs/core/LinHES-system/add_storage.py b/abs/core/LinHES-system/add_storage.py index 28d679c..1f166b1 100644 --- a/abs/core/LinHES-system/add_storage.py +++ b/abs/core/LinHES-system/add_storage.py @@ -11,40 +11,56 @@ import pickle import commands import sys,os import random, string +import ConfigParser +from ConfigParser import SafeConfigParser +import glob + from MythTV import MythDB, MythBE, Recorded, MythError from socket import timeout, gethostname +storage_dir = "/etc/storage.d" +pickle_file = "%s/storage.pkl" %storage_dir + -pickle_file="/usr/LH/etc/storage.pkl" +SG_MAP_BE={ 'Default' :'media/tv', +'LiveTV' :'media/tv/live', +'DB Backups' :'backup/mythtv_backups/', +'Streaming' :'media/streaming'} +SG_MAP_FE={ + 'Videos' :'media/video', + 'Trailers' :'media/video_stuff/trailers', + 'Coverart' :'media/video_stuff/coverart', + 'Fanart' :'media/video_stuff/fanart', + 'Banners' :'media/video_stuff/banners', + 'Screenshots':'media/video_stuff/screenshots', + } -SG_MAP={ 'Default' :'tv', - 'LiveTV' :'live_tv', - 'Videos' :'video', - 'Trailers' :'video/trailers', - 'Coverart' :'video/converart', - 'Fanart' :'video/fanart', - 'Banners' :'video/banners', - 'Screenshots':'video/screenshots', - 'DB Backups' :'db_backups'} -FS_LIST=[] -for key in SG_MAP.keys(): - FS_LIST.append(SG_MAP[key]) +FS_LIST_BE=[] +for key in SG_MAP_BE.keys(): + FS_LIST_BE.append(SG_MAP_BE[key]) +FS_LIST_FE=[] +for key in SG_MAP_FE.keys(): + FS_LIST_FE.append(SG_MAP_FE[key]) class disk_device: - def __init__(self,device): + def __init__(self,device,storage_dir): device_obj = bus.get_object("org.freedesktop.UDisks", device) device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE) + self.storage_dir = storage_dir + self.top_mount_dir = "/data/storage" + self.config = ConfigParser.RawConfigParser() self.fs_map = self.get_fsmap() self.is_device = self.get_is_device(device_props) self.vendor = self.get_vendor(device_props) self.model = self.get_model(device_props) - self.mount_path = self.get_mounts(device_props) + self.mmount = False + self.f = self.get_mounts(device_props) self.is_mounted = self.get_is_mounted(device_props) self.parition_size = self.get_partition_size(device_props) @@ -57,7 +73,18 @@ class disk_device: self.device_file_path = self.get_device_file_path(device_props) self.block_partition="%s1" %self.block_path self.in_use = self.get_in_use() + self.uuid='' + self.new_mount_point='' + self.disk_num='' + + def set_partition(self,partition): + self.block_partition = "%s%s" %(self.block_path,partition) + def set_mmount(self,flag): + self.mmount = flag + + def set_disk_num(self,num): + self.disk_num=num def get_is_device(self,device_props): return device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsDrive") @@ -74,6 +101,11 @@ class disk_device: def get_is_mounted(self,device_props): return device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsMounted") + def get_name(self): + filename="%s_%s" %(self.model.replace(' ',''), + self.serial_number.replace(' ','')) + return filename + def get_in_use(self): in_use = False for i in self.fs_map: @@ -82,7 +114,6 @@ class disk_device: break return in_use - def get_partition_size(self,device_props): return device_props.Get('org.freedesktop.UDisks.Device', "PartitionSize") @@ -150,8 +181,8 @@ class disk_device: return fs_map def find_fstype(self,moutpoint): - fstype="ext3" - mp=['/myth', '/data/media'] + fstype="xfs" + mp=['/myth', '/data/storage/disk0'] for i in self.fs_map: if i[1] in mp: fstype = i[2] @@ -164,9 +195,13 @@ class disk_device: #lookup format current_media_mount = self.find_options_type(fstab)[1] new_fstype = self.find_fstype(current_media_mount) - + #setting self.new_fstype so that it can be referenced when setting fstab + self.new_fstype = new_fstype #do format - cmd = "mkfs -t %s %s " %(new_fstype,self.block_partition) + if new_fstype == "xfs": + cmd = "mkfs -t %s -f %s " %(new_fstype,self.block_partition) + else: + cmd = "mkfs -t %s %s " %(new_fstype,self.block_partition) print " Formating %s with %s" %(self.block_partition,new_fstype) runcmd(cmd) return @@ -181,7 +216,7 @@ class disk_device: if uuid == '': print "Could not find a UUID for device: %s" %partition sys.exit(1) - + self.uuid = uuid.strip() return uuid.strip() def read_fstab(self): @@ -191,7 +226,7 @@ class disk_device: return fstab def find_options_type(self,fstab): - mp=['/myth', '/data/media'] + mp=['/myth', '/data/storage/disk0'] for i in fstab: split_line=i.split() try: @@ -206,24 +241,30 @@ class disk_device: return options,i - def add_fstab(self): + def add_fstab(self,bind=False): new_fstab_list=['UUID=', 'mount_point', 'auto', 'defaults', '0', '1'] fstab=self.read_fstab() + #determine mount_path - self.new_mount_point="/data/media/%s_%s" %(self.model.replace(' ',''),self.serial_number.replace(' ','')) + self.new_mount_point="%s/%s_%s" %(self.top_mount_dir,self.model.replace(' ',''),self.serial_number.replace(' ','')) + if bind: + new_fstab_list=["/data/storage/disk0" , self.new_mount_point , "none" , "rw,bind", '0', '0'] + uuid=self.find_uuid(self.block_partition) + else: #determine options - new_options = self.find_options_type(fstab)[0] - #find blkid - self.block_partition="%s1" %self.block_path - uuid=self.find_uuid(self.block_partition) + new_options = self.find_options_type(fstab)[0] + + #find blkid + #self.block_partition="%s1" %self.block_path + uuid=self.find_uuid(self.block_partition) - #construct new line - new_fstab_list[0]="UUID=%s" %uuid - new_fstab_list[1]=self.new_mount_point - new_fstab_list[3]=new_options + #construct new line + new_fstab_list[0]="UUID=%s" %uuid + new_fstab_list[1]=self.new_mount_point + new_fstab_list[3]=new_options new_fstab_line='\t'.join(new_fstab_list) new_fstab_line="%s\n" %new_fstab_line @@ -238,13 +279,14 @@ class disk_device: f.close() return - def mount_disk(self): + def mount_disk(self,no_mount=False): try: os.stat(self.new_mount_point) except: os.makedirs(self.new_mount_point) - cmd = "mount %s" %self.new_mount_point - runcmd(cmd) + if no_mount == False: + cmd = "mount %s" %self.new_mount_point + runcmd(cmd) return def mkdirs(self,FS_LIST): @@ -260,25 +302,77 @@ class disk_device: cmd="chmod -R 775 /%s" %self.new_mount_point runcmd(cmd) - def add_sg(self,DB,host,SG_MAP): - print " Adding to storage groups" + def add_sg(self,DB,host,SG_MAP,weight='0',install_call=False): + print " Adding storage groups" + sgweight=int(weight) for key in SG_MAP.iterkeys(): #print key," : ", SG_MAP[key] - #try: - gn=key - hn=host - dn="%s/%s" %(self.new_mount_point,SG_MAP[key]) - #print dn - #print gn - #print hn + gn=key + hn=host + dn="%s/%s" %(self.new_mount_point,SG_MAP[key]) + #print dn + #print gn + #print hn + if install_call == True : + print "Will write SG for stuff after the fact" + else: with DB as c: try: c.execute("""insert into storagegroup (groupname,hostname,dirname) values (%s,%s,%s)""",(gn,hn,dn)) print " Adding location: %s to storagegroup %s" %(dn,gn) except: - print " Error inserting %s into storage groups" %dn + print " *Error inserting %s into storage groups" %dn + + if sgweight > 0: + try: + #("SGweightPerDir:server2:/mnt/video", 99, "server2"); + sgw="SGweightPerDir:%s:%s" %(hn,dn) + #print sgw + #print sgweight + #print hn + + c.execute("""insert into settings (value,data,hostname) values (%s,%s,%s)""",(sgw,sgweight,hn)) + print " Adding storage group weight of %s for %s\n" %(sgweight,gn) + except: + print " *Error setting storage group weight %s for %s\n" %(sgweight,gn) + return + def write_config(self): + print " Writing out storage.d conf file" + self.config.add_section('storage') + self.config.set('storage','uuid',self.uuid) + self.config.set('storage','mountpoint',self.new_mount_point) + self.config.set('storage','shareable','True') + self.config.set('storage','mmount',self.mmount) + self.config.set('storage','disk_num',self.disk_num) + + + filename="%s_%s.conf" %(self.model.replace(' ',''), + self.serial_number.replace(' ','')) + + configfile="/etc/storage.d/%s" %filename + print " %s" %configfile + with open(configfile, 'wb') as configfile: + self.config.write(configfile) + return + + def symlink_disk(self): + print " Creating symlink for disk number" + disk_ln="%s/disk%s" %(self.top_mount_dir,self.disk_num) + cmd = "ln -s %s %s" %(self.new_mount_point,disk_ln) + print cmd + runcmd(cmd) + + def symlink(self): + pass + print " Creating symlink" + cmd = "ln -s %s/media /myth " %(self.new_mount_point) + runcmd(cmd) + + + +#end of class def runcmd(cmd): @@ -300,7 +394,7 @@ def scan_system(): ud_manager = dbus.Interface(ud_manager_obj, 'org.freedesktop.UDisks') current_drive_list=[] for dev in ud_manager.EnumerateDevices(): - drive = disk_device(dev) + drive = disk_device(dev,storage_dir) if drive.is_device and drive.device_size > 5000 and not drive.is_optical : current_drive_list.append(drive) @@ -333,7 +427,7 @@ def search_for_match(system_drive,known_drive_list): y_drive_hash = "%s_%s_%s" %(y.model,y.parition_size,y.device_file_path) if system_drive_hash == y_drive_hash : match_drive = True - print "No serial number was found, matched using hash method: %s" %system_drive.model + print "\n* No serial number was found, matched using hash method: %s" %system_drive.model break elif y.serial_number == system_drive.serial_number: @@ -344,10 +438,23 @@ def search_for_match(system_drive,known_drive_list): return match_drive -def prompt_to_add(current_drive): +def prompt_to_add(current_drive,destruction = True): loop = True + if destruction : + prompt = ''' + Adding the drive will remove all contents on the drive. + + Do you wish enable this drive for MythTV storage(Y/N)?: + ''' + else: + prompt = ''' + ** Preserving existing data ** + will not format or partition + + Do you wish enable this drive for MythTV storage(Y/N)?: + ''' while loop: - str1 = raw_input(" Adding the drive will remove all contents on the drive. \n\nDo you wish enable this drive for MythTV storage(Y/N)?:") + str1 = raw_input(prompt) if str1 in ['Y','N','y','n']: loop = False @@ -359,18 +466,96 @@ def prompt_to_add(current_drive): rc = False return rc +def prompt_to_continue(): + loop = True + #while loop: + print "\n\n\n\n" + str1 = raw_input("\n Ready to add additional storage!\n Press Y to continue, anything else to abort:") + + #if str1 in ['Y','N','y','n']: + # loop = False + # break + #print "\n" + if str1 == 'Y' or str1 == 'y': + rc = True + else: + rc = False + print "-----" + return rc + +def prompt_sg(dir_be_sg,dir_fe_sg): + #check for backend storage groups + if dir_be_sg != True: + loop = True + print "*" * 40 + prompt_string=''' + Backend Storage Groups are used for things like + TV Recordings and database backups. + + The content on these storage groups will + only be available while the system is online. + + Do you wish enable this system for Backend Storage Groups(Y/N)?:''' + + while loop: + str1 = raw_input(prompt_string) + if str1 in ['Y','N','y','n']: + loop = False + break + print "\n" + + if str1 == 'Y' or str1 == 'y': + dir_be_sg = True + print " ** Will add Backend Storage Groups!" + else: + print " ** Will NOT add Backend Storage Groups!" + dir_be_sg = False + + #now for frontend storage groups + if dir_fe_sg != True: + loop = True + print "+" * 20 + prompt_string=''' + Frontend Storage Groups are used for videos. + The content on these storage groups will + only be available while the system is online. + + Do you wish enable this system for Frontend Storage Groups(Y/N)?:''' + while loop: + str1 = raw_input(prompt_string) + if str1 in ['Y','N','y','n']: + loop = False + break + print "\n" + + if str1 == 'Y' or str1 == 'y': + dir_fe_sg = True + print " ** Will add Frontend Storage Groups!" + else: + dir_fe_sg = False + print " ** Will NOT add Frontend Storage Groups!" + + return dir_be_sg,dir_fe_sg + def remove_pickle(): try: - print "Resetting list of known drives." - + print "* Resetting list of known drives." os.remove(pickle_file) except: pass - +def last_disk_num(): + parser = SafeConfigParser() + num_list = [] + for conf_file in glob.glob('%s/*.conf' %storage_dir): + parser.read(conf_file) + disk_num = parser.get('storage', 'disk_num') + num_list.append(int(disk_num)) + num_list.sort() + return num_list[-1] #-------------------------------------------- -def main(scan_only): +def main(scan_only, destruction, no_mount, install_call , dir_fe_sg, dir_be_sg): global bus bus = dbus.SystemBus() @@ -378,7 +563,7 @@ def main(scan_only): known_drive_list=[] known_drive_list = read_known_list() process_list=[] - + no_process_list=[] for i in system_drive_list: @@ -390,22 +575,29 @@ def main(scan_only): #print "--" if search_for_match(i,known_drive_list) or i.in_use : - print " Storage is already in use or previously skipped: %s location: %s size: %s" %(i.model,i.block_path,i.device_size) + print "\n" + print " Storage is already in use or previously skipped:%s" %i.model + print " location: %s" %i.block_path + print " size: %s" %i.device_size continue else: - print "\n" if not scan_only: print "\n" print "-------------------------------------------------------------" + print " Found new hard drive: %s" %i.model + print " location: %s" %i.block_path + print " size: %s " %i.device_size - print "Found new hard drive: %s location: %s size: %s \n" %(i.model,i.block_path,i.device_size) - - if prompt_to_add(i) : - print "\nDisk will be added to the storage pool!" + if prompt_to_add(i,destruction) : + print "\n Disk will be added to the storage pool!" process_list.append(i) + else: + no_process_list.append(i) else: process_list.append(i) + print " End of scan" + print "---------------------------------------" if scan_only: if len(process_list) > 0: @@ -414,33 +606,319 @@ def main(scan_only): f.write("drive: %s , location: %s ,size: %s \n" %(i.model,i.block_path,i.device_size)) print "drive: %s , location: %s ,size: %s \n" %(i.model,i.block_path,i.device_size) f.close() - sys.exit(0) + for i in no_process_list: + system_drive_list.append(i) + + if len(process_list) > 0: DB = MythDB() host=gethostname() + for y in process_list: + system_drive_list.remove(y) + write_known_drive_list(system_drive_list) else: print "\nDid not find any new storage to add.\n" + write_known_drive_list(system_drive_list) #BE = MythBE(db=DB) #save new list to disk_device - write_known_drive_list(system_drive_list) + #write_known_drive_list(system_drive_list) + #disk_num = last_disk_num() - for i in process_list: - i.partition_disk() - i.format_disk() - i.add_fstab() - i.mount_disk() - i.mkdirs(FS_LIST) - i.add_sg(DB,host,SG_MAP) + + if len(process_list) > 0: + print " Will add %s disks to systems" %len(process_list) + + dir_be_sg , dir_fe_sg = prompt_sg(dir_be_sg,dir_fe_sg) + if prompt_to_continue() == True: + write_known_drive_list(system_drive_list) + disk_num = last_disk_num() + for i in process_list: + print " Drive: %s" %(i.get_name()) + disk_num = disk_num + 1 + if destruction == True: + i.partition_disk() + i.format_disk() + i.add_fstab() + i.mount_disk(no_mount) + #if destruction == True: + + if dir_fe_sg == True: + i.mkdirs(FS_LIST_FE) + if dir_be_sg == True: + i.mkdirs(FS_LIST_BE) + + i.set_disk_num(disk_num) + i.write_config() + system_drive_list.append(i) + write_known_drive_list(system_drive_list) + + i.symlink_disk() + + if dir_fe_sg == True: + i.add_sg(DB,host,SG_MAP_FE) + if dir_be_sg == True: + i.add_sg(DB,host,SG_MAP_BE) + + print "-----" + cmd = "systemconfig.py -m fileshare" + runcmd(cmd) + #i.add_sg(DB,host,SG_MAP) + +def myth_main(no_mount,install_call,dir_fe_sg): + global bus + bus = dbus.SystemBus() + #search for root + f = open('/etc/fstab', 'r') + fstab=f.readlines() + f.close() + for i in fstab: + split_line=i.split() + if not split_line: + continue + + try: + if split_line[1] == "/" : + uuid_device = split_line[0] + break + except: + print "Couldn't find / in fstab" + sys.exit(1) + if uuid_device.startswith("UUID"): + uuid_device = uuid_device.split("=")[1] + cmd = "blkid -U %s" %uuid_device + device = runcmd(cmd)[1] + else: + device = uuid_device.strip() + #should have something like /dev/sda1 + #remove all the digits + device = ''.join([letter for letter in device if not letter.isdigit()]) + + + system_drive_list = scan_system() + for i in system_drive_list: + if i.block_path == device: + break + else: + print "Couldn't find root device in block list" + sys.exit(1) + if not install_call == True: + DB = MythDB() + host=gethostname() + else: + DB = None + host=gethostname() + + + print " Drive: %s" %(i.get_name()) + i.set_mmount(True) + i.set_partition("7") + i.set_disk_num(0) + i.add_fstab(True) + #if not install_call: + i.mount_disk(no_mount) + i.write_config() + #no need to make the sub directories because the install process has taken care of it. + if dir_fe_sg == True: + i.add_sg(DB,host,SG_MAP_FE,'99',install_call) + if dir_be_sg == True: + i.add_sg(DB,host,SG_MAP_BE,'99',install_call) + + i.symlink() + cmd = "systemconfig.py -m fileshare" + runcmd(cmd) + +class reconstruct_path: + def __init__(self,conf_file): + self.conf_file = conf_file + parser = SafeConfigParser() + parser.read(self.conf_file) + + + self.uuid = parser.get('storage', 'uuid') + self.mount_point = parser.get('storage', 'mountpoint') + self.shareable = parser.get('storage', 'shareable') + self.myth_mount = parser.get('storage', 'mmount') + self.bind = self.myth_mount + self.disk_num = parser.get('storage', 'disk_num') + self.top_mount_dir = os.path.dirname(self.mount_point) + + def get_conf(self): + return self.conf_file + + def get_uuid(self): + return self.uuid + + def get_mount_point(self): + return self.mount_point + + def get_shareable(self): + return self.shareable + + def get_is_myth_mount(self): + return self.myth_mount + + def get_disk_num(self): + return self.disk_num + + def create_mount_point(self): + try: + os.stat(self.mount_point) + except: + os.makedirs(self.mount_point) + + def find_options_type(self,fstab): + mp=['/myth', '/data/storage/disk0'] + for i in fstab: + split_line=i.split() + try: + if split_line[1] in mp: + options = split_line[3] + break + else: + options = "defaults" + mount_point = i + except: + options = "defaults" + return options,i + + def read_fstab(self): + f = open('/etc/fstab', 'r') + fstab=f.readlines() + f.close() + return fstab + + def check_in_fstab(self,fstab,check_path): + + for line in fstab: + if line.find(check_path) > -1: + return True + return False + + def append_fstab(self,line): + new_fstab_line='\t'.join(line) + new_fstab_line="%s\n" %new_fstab_line + + f = open('/etc/fstab', 'a') + #f = open('/tmp/fstab', 'a') + f.write(new_fstab_line) + f.write("\n") + f.close() + + def symlink(self): + print " Creating symlink" + if not os.path.exists("/myth"): + cmd = "ln -s %s/media /myth " %(self.mount_point) + runcmd(cmd) + else: + print " Skipping symlink, path already present" + + def symlink_disk(self): + print " Creating symlink for disk number" + disk_ln="%s/disk%s" %(self.top_mount_dir,self.disk_num) + cmd = "ln -s %s %s" %(self.mount_point,disk_ln) + runcmd(cmd) + + + def add_fstab(self): + #new_fstab_list=['UUID=', 'mount_point', 'auto', 'defaults', '0', '1'] + new_fstab_list=['UUID=', 'mount_point', self.new_fstype, 'defaults', '0', '1'] + fstab=self.read_fstab() + + if self.bind == "True": + self.symlink() + + if self.check_in_fstab(fstab,self.uuid) == True: + print " Found storage in fstab, will not add it" + else: + print " Adding storage to fstab" + if self.bind == "True" : + print " Bind mount" + new_fstab_list=["/data/storage/disk0" , self.mount_point , "none" , "rw,bind", '0', '0'] + if self.check_in_fstab(fstab,self.mount_point) == False: + self.append_fstab(new_fstab_list) + else: + print " Found bind storage in fstab, will not add it" + + else: + #construct new line + new_options = self.find_options_type(fstab)[0] + new_fstab_list[0]="UUID=%s" %self.uuid + new_fstab_list[1]=self.mount_point + new_fstab_list[3]=new_options + self.append_fstab(new_fstab_list) + + def mount_disk(self,no_mount=False): + try: + os.stat(self.mount_point) + except: + os.makedirs(self.mount_point) + if no_mount == False : + cmd = "mount %s" %self.mount_point + runcmd(cmd) + return + +def reconstruct_mounts(no_mount): + print "Recreating devices based on contents of /etc/storage.d" + for conf_file in glob.glob('%s/*.conf' %storage_dir): + print "\n" + cf = reconstruct_path(conf_file) + + #print cf.get_conf() + #print cf.get_uuid() + print " %s" %cf.get_mount_point() + #print cf.get_shareable() + #print cf.get_is_myth_mount() + #print cf.get_disk_num() + + cf.create_mount_point() + cf.add_fstab() + cf.symlink_disk() + cf.mount_disk(no_mount) + + pass + + +def usage(): + help='''\n + Add storage is designed to find and setup new disks for mythtv usage. + It's a powerfull tool that could destroy data if not used correctly, so please be careful. + Normal operations include (in this order): + Partition the disk + Format the disk + Add disk to /etc/fstab + Mount the disk + Create the directory + Write out the config file to /etc/storage.d + Add new locations to mythtv storage groups + + options: + + --no_mount : Do not mount the disk, only add it to /etc/fstab and create the dir. + --no_destruction: Will not partition or format the disk. This can be used to import disks from other systems. + --new_init : Erase the list of new disks and rescan. + --report : will scan the disks and print out if it found new storage. + --add_fe_sg : Will only create the storage group dir for videos..excludes tv + --add_be_sg : Will only create the storage group dir for TV, backups, streaming + ''' + print help + sys.exit(0) if __name__ == "__main__": scan_only = False + myth_mount = False + no_mount = False + destruction = True + install_call = False + dir_fe_sg = False + dir_be_sg = False + reconstruct = False try: os.remove("/tmp/scan_report") except: @@ -449,13 +927,40 @@ if __name__ == "__main__": if not os.geteuid()==0: sys.exit("\nRoot access is required to run this program\n") + if "--help" in sys.argv: + usage() + + if "--install_call" in sys.argv: + install_call = True + + if "--no_mount" in sys.argv : + no_mount = True + + if "--no_destruction" in sys.argv: + destruction = False + if "--new_init" in sys.argv : remove_pickle() if "--report" in sys.argv : scan_only = True - main(scan_only) + if "--add_fe_sg" in sys.argv: + dir_fe_sg = True + + if "--add_be_sg" in sys.argv: + dir_be_sg = True + + + if "--reconstruct" in sys.argv: + reconstruct = True + + if "--double_myth" in sys.argv: + myth_main(no_mount,install_call,dir_fe_sg) + elif reconstruct == True: + reconstruct_mounts(no_mount) + else: + main(scan_only,destruction,no_mount, install_call, dir_fe_sg, dir_be_sg) diff --git a/abs/core/LinHES-system/add_storage.readme b/abs/core/LinHES-system/add_storage.readme new file mode 100644 index 0000000..226b14d --- /dev/null +++ b/abs/core/LinHES-system/add_storage.readme @@ -0,0 +1,3 @@ +Files here are autogenerated by add_storage.py. +They will be used by systemconfig to generate nfs,smb and mountpoint recovery. + diff --git a/abs/core/LinHES-system/be_check.py b/abs/core/LinHES-system/be_check.py new file mode 100644 index 0000000..3a13c56 --- /dev/null +++ b/abs/core/LinHES-system/be_check.py @@ -0,0 +1,35 @@ +#!/usr/bin/python2 +#simple program to check if mythbackend is up and running +#exit code of 0 is success, anything else means it can't connect +import sys +class Logger(object): + def __init__(self, filename="/tmp/Default.log"): + #self.terminal = sys.stdout + try: + self.log = open(filename, "a") + except: + pass + + def write(self, message): + try: + #self.terminal.write(message) + self.log.write(message) + except: + pass + +sys.stdout = Logger("/tmp/be_check.log") + + +from MythTV import MythBE,MythDB +#import datetime,time,sys,subprocess + + + + + +try: + be=MythBE() + db = MythDB() +except: + sys.exit(1) +sys.exit(0)
\ No newline at end of file diff --git a/abs/core/LinHES-system/bin/backupcommon b/abs/core/LinHES-system/bin/backupcommon index d112341..4305509 100644 --- a/abs/core/LinHES-system/bin/backupcommon +++ b/abs/core/LinHES-system/bin/backupcommon @@ -99,7 +99,7 @@ require file+r+x $AWK $BASH $BUNZIP2 $BZIP2 $CAT $CHMOD $CHOWN $EGREP $GREP \ require dir+r+w+x /tmp "$BACKUP_DIR" "$DATABASE_DIR" play_sound () { - ($PLAYER $SILENCE $SOUNDS/$1 >& /dev/null)& + ($PLAYER $SILENCE $SILENCE $SOUNDS/$1 >& /dev/null)& } # Filter against an exclude list like the black list or the ignore list above diff --git a/abs/core/LinHES-system/bin/mythbackup b/abs/core/LinHES-system/bin/mythbackup index 3b4edd4..905beeb 100755 --- a/abs/core/LinHES-system/bin/mythbackup +++ b/abs/core/LinHES-system/bin/mythbackup @@ -46,6 +46,20 @@ echo "Starting rollover of old backups, this may take a while..." backup_roller .19 .18 .17 .16 .15 .14 .13 .12 .11 .10 .9 .8 .7 .6 .5 .4 .3 .2 .1 '' echo "Rollover completed." +# Quit MythWelcome and MythFrontend if they are running. +MWRUNNING=0 +FERUNNING=0 +if [ "$(pidof mythwelcome)" ] +then + MWRUNNING=1 + killall mythwelcome +fi +if [ "$(pidof mythfrontend)" ] +then + FERUNNING=1 + killall mythfrontend +fi + osd "Checking the database..." 0 2 # Start with the database backup, first we make sure it's healthy, and # then we can dump it. @@ -110,4 +124,13 @@ start_mythbackend # Unlock the system again... unlock_myth +# Restart Mythwelcome or Mythfrontend if it was running. +if [ $MWRUNNING -eq 1 ] +then + exec su mythtv -c "/usr/bin/mythwelcome" > /dev/null 2>&1 +elif [ $FERUNNING -eq 1 ] +then + exec su mythtv -c "/usr/LH/bin/mythfrontend-start" > /dev/null 2>&1 +fi + exit $STATUS diff --git a/abs/core/LinHES-system/cacheclean b/abs/core/LinHES-system/cacheclean index d32d16b..cfc8d58 100755 --- a/abs/core/LinHES-system/cacheclean +++ b/abs/core/LinHES-system/cacheclean @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """cacheclean - a simple python script to clean up the /data/var/cache/pacman/pkg directory. More versatile than 'pacman -Sc' in that you can select how many old versions to keep. diff --git a/abs/core/LinHES-system/change_channel.sh b/abs/core/LinHES-system/change_channel.sh new file mode 100755 index 0000000..ff59834 --- /dev/null +++ b/abs/core/LinHES-system/change_channel.sh @@ -0,0 +1,176 @@ +#!/bin/bash +# Maintained by CommandIR Support mini at commandir.com - Comments / Suggestions Welcome. +# Modified for LinHES specifics + +echo $@ > /tmp/change_channel.log +. /etc/systemconfig +LOCKFILE=/tmp/lirclock +export PATH=/bin:/usr/bin:/usr/local/bin + +function post_channel(){ + if [ -f $MYTHHOME/post_channel_change ] + then + echo "CALLING $MYTHHOME/post_channel $TRANSMITTER" + $MYTHHOME/post_channel $TRANSMITTER + fi + + } + + + +function change_channel() { + touch $LOCKFILE + irsend SET_TRANSMITTERS $TRANSMITTER + sleep .15 + case $cmd in + [0-9]*) + for digit in $(echo $cmd | sed -e 's/./& /g') + do + irsend SEND_ONCE $REMOTE_NAME $digit + sleep $DELAY + done + if [ x$SENDKEY != "x" ] + then + irsend SEND_ONCE $REMOTE_NAME $SENDKEY + fi + + ;; + + *) + irsend SEND_ONCE $REMOTE_NAME $cmd + ;; + esac +} + +function showhelp(){ + echo "IR Control Script for LIRC + Includes support for CommandIR transmitter selection and lockfile. + The remote codes will be specific to the transmitter number and matched via /etc/systemconfig + Usage: + $0 -d delay -c channel -n transmitter_number -s Enter + + -d delay in tenths of a seconds - + -c channel or cmd + -n transmitter_number + -s Key to send after executing change channel command (optional) + + Sends an IR command or sequence of numbers using via emitter TRANSMITTER_NUM. + DELAY ( in 10th of seconds) is waited between sending IR commands. + + Example: Change to channel 123 using emitter 2 with a 0.3s pause between digits: + $0 -n1 -c123 -d3 + + " + exit 1 + + +} + +function testvars() { + if [ x$DELAY = "x" ] + then + tdelay="HostTransmitDelay_$TRANSMITTER" + d=${!tdelay} + DELAY=$(echo "scale=2; $d / 10" | bc) + fi + + + if [ x$cmd = "x" ] + then + echo "-c is mandatory" + exit 1 + fi + + + if [ x$TRANSMITTER = "x" ] + then + echo "-n is mandatory" + exit 1 + fi + echo "delay is $DELAY" + + +# echo "channel or button name is $cmd" +# echo "Using transmitter $TRANSMITTER" +# echo "Remote name is $REMOTE_NAME" +# echo "Will send key $SENDKEY after numbers" +} + + +#-----------------------------Main Program----------------------- + +while getopts ":d:c:n:hs:" opt; do + case $opt in + h) showhelp + ;; + d) DELAY=$(echo "scale=2; $OPTARG / 10" | bc) + ;; + + c) cmd=$OPTARG + ;; + + n) TRANSMITTER=$OPTARG + tname="HostTransmitproto_$TRANSMITTER" + REMOTE_NAME=${!tname} + if [ x$REMOTE_NAME = "xnone" ] + then + echo "Please define Transmitters in /etc/systemconfig" + exit 1 + fi + if [ x$REMOTE_NAME = "x" ] + then + echo "Please define Transmitters in /etc/systemconfig" + exit 1 + fi + + ;; + + s) SENDKEY=$OPTARG + ;; + + \?) + echo + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + :) + echo + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +testvars +while [ -f $LOCKFILE ] +do + echo "Waiting for change channel lock file..." + sleep .1 +done + +change_channel +post_channel +rm -f /tmp/lirclock + + + + + + + + + + + + + + + + + + + + + + + diff --git a/abs/core/LinHES-system/change_channel_wrapper.sh b/abs/core/LinHES-system/change_channel_wrapper.sh new file mode 100755 index 0000000..c84529a --- /dev/null +++ b/abs/core/LinHES-system/change_channel_wrapper.sh @@ -0,0 +1,2 @@ +#!/bin/bash +/usr/LH/bin/change_channel.sh $@ & diff --git a/abs/core/LinHES-system/create_media_dirs.sh b/abs/core/LinHES-system/create_media_dirs.sh new file mode 100644 index 0000000..9e64301 --- /dev/null +++ b/abs/core/LinHES-system/create_media_dirs.sh @@ -0,0 +1,71 @@ +#!/bin/bash +#script to create the media directories +#call it like so +#create_media_dirs.sh /top_level_path + +topdir=$1 + +if [ x$topdir = "x" ] +then + echo "Top level dir is empty" + exit 1 +fi + +if [ ! -d "$topdir" ] +then + echo "$topdir is not a dir or does not exist" + exit 2 +fi + + + +while read dirname +do + mkdir -p "${topdir}/${dirname}" + touch "${topdir}/${dirname}/.media" + chown mythtv:users "${topdir}/${dirname}" + chmod 775 "${topdir}/${dirname}" + chmod 775 "${topdir}/${dirname}/.media" +done <<EOF +media/tv +media/tv/live +media/gallery +media/music +media/games/nes/roms +media/games/nes/screens +media/games/nes +media/games/pc/screens +media/games/pc +media/games/snes/roms +media/games/snes/screens +media/games/snes +media/games/xmame/cabs +media/games/xmame/flyers +media/games/xmame/hiscores +media/games/xmame/history +media/games/xmame/roms +media/games/xmame/screens +media/games/xmame +media/games +media/video +media/tmp +media/archive +media/pretty +media/streaming +media/video_stuff/trailers +media/video_stuff/coverart +media/video_stuff/fanart +media/video_stuff/screenshots +media/video_stuff/banners +media/games/screenshots +media/games/fanart +media/games/boxart +backup +backup/system_backups +backup/system_backups +backup/user_backups +backup/mythtv_backups +EOF + +chown -R mythtv:users ${topdir} +chmod -R 775 ${topdir} diff --git a/abs/core/LinHES-system/diskspace.sh b/abs/core/LinHES-system/diskspace.sh index 2173c6e..635a972 100755 --- a/abs/core/LinHES-system/diskspace.sh +++ b/abs/core/LinHES-system/diskspace.sh @@ -11,12 +11,13 @@ ALERT=90 # free space percentage to trigger an alert # Static Binary Paths # DF='/bin/df' -GREP='/bin/grep' -AWK='/bin/awk' -CUT='/bin/cut' -HOSTNAME='/bin/hostname' +GREP='/usr/bin/grep' +AWK='/usr/bin/awk' +CUT='/usr/bin/cut' +HOSTNAME='/usr/bin/hostname' DATE='/bin/date' OSD_CAT='/usr/bin/osd_cat' +MSG_CLIENT='/usr/LH/bin/msg_client.py --msg' export DISPLAY=:0.0 # # Static System Variables @@ -72,7 +73,8 @@ $DF -HPl | $GREP -E "^/dev/" | $AWK '{ print $5 " " $6 " " $1 }' | while read OU else echo "WARNING: ${PARTITION} (${DEVICE}) is ${USED_PCENT}% full on ${THIS_HOST}." #| if [ $OSD = true ] && [ ${PARTITION} = / ]; then - echo "WARNING: The root (${PARTITION}) partition is ${USED_PCENT}% full on ${THIS_HOST}." | $OSD_CAT --pos=top --offset=40 --align=center --delay=10 --color=$color --outline=$outline --outlinecolour=$outlinecolour --shadow=$shadow --shadowcolour=$shadowcolour --font=$font & + #echo "WARNING: The root (${PARTITION}) partition is ${USED_PCENT}% full on ${THIS_HOST}." | $OSD_CAT --pos=top --offset=40 --align=center --delay=10 --color=$color --outline=$outline --outlinecolour=$outlinecolour --shadow=$shadow --shadowcolour=$shadowcolour --font=$font & + $MSG_CLIENT "WARNING: The root (${PARTITION}) partition is ${USED_PCENT}% full on ${THIS_HOST}." fi fi fi diff --git a/abs/core/LinHES-system/firstboot.sh b/abs/core/LinHES-system/firstboot.sh index c405df8..2b974a2 100755 --- a/abs/core/LinHES-system/firstboot.sh +++ b/abs/core/LinHES-system/firstboot.sh @@ -55,7 +55,7 @@ then fb_status=4 while [ $fb_status != 0 ] do - fix_lirc_socket +# fix_lirc_socket # try_smolt if [ $fb_status != 0 ] then diff --git a/abs/core/LinHES-system/gen_game_xml.py b/abs/core/LinHES-system/gen_game_xml.py new file mode 100644 index 0000000..e5d9afe --- /dev/null +++ b/abs/core/LinHES-system/gen_game_xml.py @@ -0,0 +1,117 @@ +#! /usr/bin/python2 +#Helper program that generates library.xml thats custom to linhes. +#Contents are read from /etc/gen_game_xml.d +#This script should be run everytime an entry is added or removed + + +import os, sys +import glob + +class Gen_lib_xml: + def __init__(self,snippit_dir,orig_theme_file): + self.snippit_dir = snippit_dir + self.orig_theme_file = orig_theme_file + self.xml_snippets=[] + self.orig_theme_xml=[] + self.new_xml=[] + + def get_new_xml(self): + return self.new_xml + def get_orig_xml(self): + return self.orig_theme_xml + def get_snippits(self): + return self.xml_snippets + + def read_snippets(self): + xml_snippets="" + try: + os.chdir(self.snippit_dir) + except: + print " gen_game_xml: Couldn't change dir to %s" %self.snippit_dir + print " Exiting" + sys.exit(0) + file_list=glob.glob("*.conf") + for conf_file in file_list: + try: + print " gen_game_xml: reading in %s" %conf_file + f=open(conf_file,'r') + lines=f.readlines() + f.close() + except: + print " gen_game_xml: Couldn't open %s for reading" %conf_file + print " Exiting" + sys.exit(0) + + if len(file_list) == 0: + print " gen_game_xml: no conf files found" + lines = [] + self.xml_snippets = lines + + def read_orig_xml(self): + try: + print " gen_game_xml: reading in %s" %self.orig_theme_file + f=open(self.orig_theme_file,'r') + lines=f.readlines() + f.close() + + except: + print " gen_game_xml: Couldn't open %s for reading" %self.orig_theme_file + print " Exiting" + sys.exit(2) + #print lines + for i in lines: + if i.strip() == "</mythmenu>": + lines.remove(i) + print " gen_game_xml: Removing /mythmenu tag " + break + self.orig_theme_xml=lines + + def make_new_xml(self): + self.new_xml = self.orig_theme_xml + self.xml_snippets + self.new_xml.append("</mythmenu>\n") + pass + + + + + + + + +def write_xml(xml,filename): + try: + f=open(filename, 'w') + except: + print " gen_game_xml: Couldn't open %s" %(filename) + print " Exiting" + sys.exit(2) + print " gen_game_xml: Writing %s" %(filename) + for i in xml: + f.write(i) + f.close() + +def main(): + sys.path.append('/usr/MythVantage/bin/') + config_file = "mv_config" + data_config = __import__(config_file, globals(), locals(), []) + + filename="%s/.mythtv/game.xml" %data_config.MYTHHOME + #filename="/tmp/library.xml" + orig_theme_file="/usr/share/mythtv/themes/defaultmenu/game.xml" + lib_xml_dir="/etc/gen_game_xml.d/" + + lib_xml = Gen_lib_xml(lib_xml_dir,orig_theme_file) + lib_xml.read_snippets() + lib_xml.read_orig_xml() + lib_xml.make_new_xml() + lib_xml.make_new_xml() + new_xml = lib_xml.get_new_xml() + + #a = lib_xml.get_new_xml() + #b = lib_xml.get_orig_xml() + #c = lib_xml.get_snippits() + + write_xml(new_xml,filename) + +if __name__ == "__main__": + main()
\ No newline at end of file diff --git a/abs/core/LinHES-system/gen_is_xml.py b/abs/core/LinHES-system/gen_is_xml.py new file mode 100755 index 0000000..c7525a1 --- /dev/null +++ b/abs/core/LinHES-system/gen_is_xml.py @@ -0,0 +1,56 @@ +#! /usr/bin/python2 +#Helper program that generates gen_is.xml thats custom to linhes. +#Contents of gen_is.xml are read from /etc/gen_is_xml.d +#This script should be run everytime a is.xml entry is added or removed + + +import os, sys +import glob + +def read_snippets(dir_name): + xml_snippets="" + try: + os.chdir(dir_name) + except: + print " gen_is_xml: Couldn't change dir to %s" %dir_name + print " Exiting" + sys.exit(0) + file_list=glob.glob("*.conf") + for conf_file in file_list: + try: + print " gen_is_xml: reading in %s" %conf_file + f=open(conf_file,'r') + lines=f.readlines() + f.close() + except: + print " gen_is_xml: Couldn't open %s for reading" %conf_file + print " Exiting" + sys.exit(1) + for line in lines: + xml_snippets+=line + if len(file_list) == 0: + print " gen_is_xml: no conf files found" + xml_snippets="" + + return xml_snippets + + +def write_xml(xml,filename): + try: + f=open(filename, 'w') + except: + print " gen_is_xml: Couldn't open %s" %(filename) + print " Exiting" + sys.exit(2) + f.write(xml) + f.close() + +def main(): + filename="/usr/share/mythtv/gen_is.xml" + is_xml_dir="/etc/gen_is_xml.d/" + xml_snippets=read_snippets(is_xml_dir) + xml='''<mythmenu name="Internet Steams">\n\n%s\n</mythmenu>\n''' %xml_snippets + write_xml(xml,filename) + +if __name__ == "__main__": + main()
\ No newline at end of file diff --git a/abs/core/LinHES-system/gen_lib_xml.py b/abs/core/LinHES-system/gen_lib_xml.py new file mode 100644 index 0000000..320a84d --- /dev/null +++ b/abs/core/LinHES-system/gen_lib_xml.py @@ -0,0 +1,117 @@ +#! /usr/bin/python2 +#Helper program that generates library.xml thats custom to linhes. +#Contents are read from /etc/gen_lib_xml.d +#This script should be run everytime an entry is added or removed + + +import os, sys +import glob + +class Gen_lib_xml: + def __init__(self,snippit_dir,orig_theme_file): + self.snippit_dir = snippit_dir + self.orig_theme_file = orig_theme_file + self.xml_snippets=[] + self.orig_theme_xml=[] + self.new_xml=[] + + def get_new_xml(self): + return self.new_xml + def get_orig_xml(self): + return self.orig_theme_xml + def get_snippits(self): + return self.xml_snippets + + def read_snippets(self): + xml_snippets="" + try: + os.chdir(self.snippit_dir) + except: + print " gen_lib_xml: Couldn't change dir to %s" %self.snippit_dir + print " Exiting" + sys.exit(0) + file_list=glob.glob("*.conf") + for conf_file in file_list: + try: + print " gen_lib_xml: reading in %s" %conf_file + f=open(conf_file,'r') + lines=f.readlines() + f.close() + except: + print " gen_lib_xml: Couldn't open %s for reading" %conf_file + print " Exiting" + sys.exit(0) + + if len(file_list) == 0: + print " gen_lib_xml: no conf files found" + lines = [] + self.xml_snippets = lines + + def read_orig_xml(self): + try: + print " gen_lib_xml: reading in %s" %self.orig_theme_file + f=open(self.orig_theme_file,'r') + lines=f.readlines() + f.close() + + except: + print " gen_lib_xml: Couldn't open %s for reading" %self.orig_theme_file + print " Exiting" + sys.exit(2) + #print lines + for i in lines: + if i.strip() == "</mythmenu>": + lines.remove(i) + print " gen_lib_xml: Removing /mythmenu tag " + break + self.orig_theme_xml=lines + + def make_new_xml(self): + self.new_xml = self.orig_theme_xml + self.xml_snippets + self.new_xml.append("</mythmenu>\n") + pass + + + + + + + + +def write_xml(xml,filename): + try: + f=open(filename, 'w') + except: + print " gen_lib_xml: Couldn't open %s" %(filename) + print " Exiting" + sys.exit(2) + print " gen_lib_xml: Writing %s" %(filename) + for i in xml: + f.write(i) + f.close() + +def main(): + sys.path.append('/usr/MythVantage/bin/') + config_file = "mv_config" + data_config = __import__(config_file, globals(), locals(), []) + + filename="%s/.mythtv/library.xml" %data_config.MYTHHOME + #filename="/tmp/library.xml" + orig_theme_file="/usr/share/mythtv/themes/defaultmenu/library.xml" + lib_xml_dir="/etc/gen_lib_xml.d/" + + lib_xml = Gen_lib_xml(lib_xml_dir,orig_theme_file) + lib_xml.read_snippets() + lib_xml.read_orig_xml() + lib_xml.make_new_xml() + lib_xml.make_new_xml() + new_xml = lib_xml.get_new_xml() + + #a = lib_xml.get_new_xml() + #b = lib_xml.get_orig_xml() + #c = lib_xml.get_snippits() + + write_xml(new_xml,filename) + +if __name__ == "__main__": + main()
\ No newline at end of file diff --git a/abs/core/LinHES-system/gen_light_include.py b/abs/core/LinHES-system/gen_light_include.py new file mode 100644 index 0000000..ce0ec6d --- /dev/null +++ b/abs/core/LinHES-system/gen_light_include.py @@ -0,0 +1,55 @@ +#! /usr/bin/python2 +#Helper program that generates gen_is.xml thats custom to linhes. +#Contents of gen_is.xml are read from /etc/gen_is_xml.d +#This script should be run everytime a is.xml entry is added or removed + + +import os, sys +import glob + +def read_snippets(dir_name): + conf_snippets="" + try: + os.chdir(dir_name) + except: + print " gen_light_conf: Couldn't change dir to %s" %dir_name + print " Exiting" + sys.exit(0) + file_list=glob.glob("*.conf") + for conf_file in file_list: + try: + print " gen_light_conf: reading in %s" %conf_file + f=open(conf_file,'r') + lines=f.readlines() + f.close() + except: + print " gen_light_conf: Couldn't open %s for reading" %conf_file + print " Exiting" + sys.exit(1) + for line in lines: + conf_snippets+=line + if len(file_list) == 0: + print " gen_light_conf: no conf files found" + conf_snippets="" + + return conf_snippets + + +def write_conf(conf,filename): + try: + f=open(filename, 'w') + except: + print " gen_light_conf: Couldn't open %s" %(filename) + print " Exiting" + sys.exit(2) + f.write(conf) + f.close() + +def main(): + filename="/etc/lighttpd/conf.include" + light_conf_dir="/etc/gen_light_conf.d/" + conf_snippets=read_snippets(light_conf_dir) + write_conf(conf_snippets,filename) + +if __name__ == "__main__": + main()
\ No newline at end of file diff --git a/abs/core/LinHES-system/install_supplemental_service.sh b/abs/core/LinHES-system/install_supplemental_service.sh index d33cb18..c474447 100644 --- a/abs/core/LinHES-system/install_supplemental_service.sh +++ b/abs/core/LinHES-system/install_supplemental_service.sh @@ -2,7 +2,8 @@ . /etc/systemconfig if [ $SystemType = Master_backend -o $SystemType = Standalone ] then - pacman -S --noconfirm supplemental-web + pacman -S --noconfirm xymonserver + pacman -S --noconfirm supplemental-web add_service.sh certmaster add_service.sh funcd add_service.sh xymon-server diff --git a/abs/core/LinHES-system/lh_backend_control.sh b/abs/core/LinHES-system/lh_backend_control.sh new file mode 100644 index 0000000..c116cdb --- /dev/null +++ b/abs/core/LinHES-system/lh_backend_control.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# This script is used to start stop the backend. +# Intended to be used via hotkeys. + + +MYTH_RUN_STATUS="1" +. /etc/profile +. /etc/systemconfig + + +if [ -e /etc/X11/WINDOWMANAGER ] +then + . /etc/X11/WINDOWMANAGER +fi + +MV_BEC="/usr/MythVantage/bin/backend_control.sh" + +case $1 in + stop) + if [ x$STARTUP_STYLE = xenhanced ] + then + #/usr/MythVantage/bin/mythbeselect -stop + if [ -e $MV_BEC ] + then + $MV_BEC stop $dbhost + else + msg_client.py --msg "Stopping backend" + sudo sv stop mythbackend + fi + else + #linhes style + sudo sv stop mythbackend + fi + ;; + + start) + if [ x$STARTUP_STYLE = xenhanced ] + then + #/usr/MythVantage/bin/mythbeselect -stop + if [ -e $MV_BEC ] + then + $MV_BEC start $dbhost + else + msg_client.py --msg "Starting backend" + sudo sv start mythbackend + fi + else + #linhes style + sudo sv start mythbackend + fi + ;; + + restart) + if [ x$STARTUP_STYLE = xenhanced ] + then + #/usr/MythVantage/bin/mythbeselect -stop + if [ -e $MV_BEC ] + then + $MV_BEC restart $dbhost + else + msg_client.py --msg "Restarting backend" + sudo sv restart mythbackend + fi + else + #linhes style + sudo sv restart mythbackend + fi + ;; + + *) echo "options are: stop start restart" + ;; + +esac + + diff --git a/abs/core/LinHES-system/lh_message.sh b/abs/core/LinHES-system/lh_message.sh deleted file mode 100644 index 203d127..0000000 --- a/abs/core/LinHES-system/lh_message.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash -MYTH_RUN_STATUS="1" -. /etc/profile -. /etc/systemconfig - - -if [ -e /etc/X11/WINDOWMANAGER ] -then - . /etc/X11/WINDOWMANAGER -fi - - -. /etc/osd_cat.cfg || { - color=yellow - outline=2 - outlinecolour=black - shadow=0 - shadowcolour=black - font="-adobe-helvetica-bold-*-*-*-34-*-*-*-*-*-*-*" -} - -function delay_osd(){ - if [ x$STARTUP_STYLE = xmythvantage ] - then - cmd="ps -ef | grep -v grep | grep -q xmsg.py" - else - cmd="ps -ef | grep -v grep | grep -q osd_cat" - fi - - eval $cmd - - rc=$? - while [ $rc = 0 ] - do - eval $cmd - rc=$? - done - - - } - -function msg_osd(){ - DISPLAY=127.0.0.1:0 echo -e "$1" | DISPLAY=127.0.0.1:0 osd_cat --pos=middle --align=center --offset=200 --delay=5 --color=$color --outline=$outline --outlinecolour=$outlinecolour --shadow=$shadow --shadowcolour=$shadowcolour --font=$font -} - -function msg_pyosd(){ - DISPLAY=127.0.0.1:0 /usr/LH/bin/xmsg.py -m "$1" -} - -function msg(){ - if [ x$STARTUP_STYLE = xmythvantage ] - then - msg_pyosd "$1" - else - msg_osd "$1" - fi - -} - -if [ x"${@}" = x ] -then - print "nothing to display" -else - msg "${@}" -fi diff --git a/abs/core/LinHES-system/lh_system_backup b/abs/core/LinHES-system/lh_system_backup new file mode 100755 index 0000000..61a0ec3 --- /dev/null +++ b/abs/core/LinHES-system/lh_system_backup @@ -0,0 +1,30 @@ +#!/bin/bash +. /etc/systemconfig +msg_client.py --msg "Starting Backup" +#alert user the database will not be backed up +if [ $SystemType != Master_backend -a $SystemType != Standalone ] +then + msg_client.py --msg "This is not the Master backend.\n Skipping backup of database." +fi + +if [ $SystemType = Master_backend -o $SystemType = Standalone ] +then + backend_control.sh stop 127.0.0.1 +fi + +#do the backup +lh_system_backup_job 2>&1 > /var/run/backup.log +rc=$? +if [ $SystemType = Master_backend -o $SystemType = Standalone ] +then + backend_control.sh start 127.0.0.1 +fi + +if [ $rc = 0 ] +then + complete_message="Backup completed successfully" +else + complete_message="Backup failed!" +fi +msg_client.py --msg "$complete_message" + diff --git a/abs/core/LinHES-system/lh_system_backup_job b/abs/core/LinHES-system/lh_system_backup_job index 61b05d7..e095a97 100644 --- a/abs/core/LinHES-system/lh_system_backup_job +++ b/abs/core/LinHES-system/lh_system_backup_job @@ -1,65 +1,239 @@ #!/bin/bash #process that uses this system backup script # - myth_mtc.py -# - supplemental web, process.py backup -# -echo "#########################################################" -echo "Starting backup " +# - supplemental web, process.py backup linhes_backup_wrapper + +MYTH_RUN_STATUS="1" . /etc/profile . /etc/systemconfig -BACKUPDIR=/myth/system_backups +BACKUPDIR=/data/storage/disk0/backup/system_backups DELETE_DAYS=21 DATE=`date +%F_%H-%M` -mkdir -p $BACKUPDIR/$DATE +backup_status=0 +# -#backup db -pacman -Q mysql 2>/dev/null -if [ $? = 0 ] -then - mysqldump mythconverg > $BACKUPDIR/$DATE/mythconverg - mysqldump ncid > $BACKUPDIR/$DATE/ncid -fi +MYTHSHUTDOWN="/usr/bin/mythshutdown" -#backup etc -cp -rp /etc $BACKUPDIR/$DATE/etc -cp -rp /var/lib/oss $BACKUPDIR/$DATE/oss +function lock_myth(){ + $MYTHSHUTDOWN --lock +} -#backup func keys -cp -rp /data/srv/func $BACKUPDIR/$DATA/func +function unlock_myth(){ + $MYTHSHUTDOWN --unlock +} -#make_zip file -cd $BACKUPDIR -tar -zcvf $BACKUPDIR/backup.$DATE.tgz $DATE +function backup_status_check(){ + if [ $1 -ne 0 ] + then + backup_status=1 + fi +} -if [ -d $BACKUPDIR/$DATE ] -then - rm -rf $BACKUPDIR/$DATE -fi -if [ -f /data/srv/hobbit/server/ext/hbnotes.py ] -then - /data/srv/hobbit/server/ext/hbnotes.py - chown nobody:nobody /data/srv/httpd/htdocs/hobbit/notes/* 2> /dev/null >/dev/null -fi +function backup(){ -#remove old backups -find $BACKUPDIR/backup*.tgz -type f -mtime +$DELETE_DAYS -delete + echo "#######################################" + echo "Starting backup " + mkdir -p $BACKUPDIR/$DATE -#Remote copy -if [ x$RemoteBackup = x1 ] -then - localRemoteCheck=`echo $RemoteBackupDir | cut -d: -f1` - if [ x$localRemoteCheck = xdir ] + #backup database + if [ $SystemType = Master_backend -o $SystemType = Standalone ] then - localRemotedir=`echo $RemoteBackupDir | cut -d: -f2` - cmd="cp $BACKUPDIR/backup.$DATE.tgz $localRemotedir" - echo "copying$BACKUPDIR/backup.$DATE.tgz to $localRemotedir " + pacman -Q mysql 2>/dev/null + if [ $? = 0 ] + then + mysqldump -x mythconverg > $BACKUPDIR/$DATE/mythconverg + backup_status_check $? + + mysqldump -x ncid > $BACKUPDIR/$DATE/ncid + + #this is all the users + mysqldump -x mysql > $BACKUPDIR/$DATE/mysql_table + + #this is everything + mysqldump -x --all-databases > $BACKUPDIR/$DATE/all_databases + backup_status_check $? + + + + fi + fi + + #backup saved settings + if [ -e /usr/MythVantage/templates/settings ] + then + cp -rp /usr/MythVantage/templates/settings $BACKUPDIR/$DATE/settings + backup_status_check $? + fi + + #backup etc + cp -rp /etc $BACKUPDIR/$DATE/etc + if [ -e /var/lib/oss ] + then + cp -rp /var/lib/oss $BACKUPDIR/$DATE/oss + backup_status_check $? + fi + + #backup func keys + cp -rp /etc/pki $BACKUPDIR/$DATE/pki + + if [ ! -f $MYTHHOME/backup_config/backup_exclude.txt ] + then + mkdir -p $MYTHHOME/backup_config/ + echo ".mythtv/themecache" > $MYTHHOME/backup_config/backup_exclude.txt + echo "tmp" >> $MYTHHOME/backup_config/backup_exclude.txt + echo ".vnc/*log" >> $MYTHHOME/backup_config/backup_exclude.txt + echo ".vnc/*pid" >> $MYTHHOME/backup_config/backup_exclude.txt + chmod 777 $MYTHHOME/backup_config/backup_exclude.txt + fi + + tar -zcf $BACKUPDIR/$DATE/home_dir.tar.gz -X $MYTHHOME/backup_config/backup_exclude.txt $MYTHHOME /home/vncsvc /home/xymon + + if [ -f $MYTHHOME/backup_config/backup_include.txt ] + then + tar -zcf $BACKUPDIR/$DATE/other.tar.gz -T $MYTHHOME/backup_config/backup_include.txt + backup_status_check $? + fi + + #make_zip file + cd $BACKUPDIR + tar -zcvf $BACKUPDIR/backup.$DATE.tgz $DATE + backup_status_check $? + if [ -d $BACKUPDIR/$DATE ] + then + rm -rf $BACKUPDIR/$DATE + fi + + if [ -f /home/xymon/server/ext/hbnotes.py ] + then + /home/xymon/server/ext/hbnotes.py + chown nobody:nobody /data/srv/httpd/htdocs/hobbit/notes/* 2> /dev/null >/dev/null + fi + echo + echo "Created file:" + echo " $BACKUPDIR/backup.$DATE.tgz" + echo "########################################" +} + +function update_backup_status(){ + # Add Last backup status to menu item + #if description not in the backup xml file, add it + if [ $rc=0 ] + then + COMPLETE_MSG="Last backup completed on `date '+%D @ %-I:%M %p'`" + else + COMPLETE_MSG="Last backup FAILED on `date '+%D @ %-I:%M %p'`" + fi + + xmlfile="/usr/share/mythtv/themes/defaultmenu/mythbackup.xml" + + grep -q "<description>" $xmlfile >/dev/null + desc_check=$? + + if [ $desc_check = 0 ] + then + sed -i "s_\<description\>.*\<description\>_description\>$COMPLETE_MSG\<\/description_" $xmlfile + else + sed -i " /NONE/ i\ \<description\>$COMPLETE_MSG\<\/description\>" $xmlfile + fi +} + +function remove_old_backups(){ + #remove old backups + find $BACKUPDIR/backup*.tgz -type f -mtime +$DELETE_DAYS -delete +} + + +function remote_backup(){ + #Remote copy + if [ x$RemoteBackup = x1 ] + then + localRemoteCheck=`echo $RemoteBackupDir | cut -d: -f1` + if [ x$localRemoteCheck = xdir ] + then + localRemotedir=`echo $RemoteBackupDir | cut -d: -f2` + echo "copying $BACKUPDIR/backup.$DATE.tgz to $localRemotedir " + cp $BACKUPDIR/backup.$DATE.tgz $localRemotedir + else + /usr/bin/func ${RemoteBackupDir} ping| grep -q "FAILED" + rc=$? + if [ $rc = 0 ] + then + #this is here to mark failed copy of the backup. + #There is a cron.hourly job that will attempt to retransfer the file + echo "Remote backup failed to ${RemoteBackupDir}" + echo backup.$DATE.tgz >> $BACKUPDIR/remote_backup_failed.txt + else + echo "copying $BACKUPDIR/backup.$DATE.tgz to ${RemoteBackupDir}:$BACKUPDIR/MBE_$DATE.tgz" + /usr/bin/func ${RemoteBackupDir} copyfile -f $BACKUPDIR/backup.$DATE.tgz --remotepath $BACKUPDIR/MBE_$DATE.tgz + fi + fi + fi +} + +function remote_transfer(){ + transfer_file=${1} + echo $transfer_file + /usr/bin/func ${RemoteBackupDir} ping| grep -q "FAILED" + rc=$? + if [ $rc = 0 ] + then + #this is here to mark a failed copy of the backup. + #There is a cron.hourly job that will attempt to retransfer the file + echo "Remote backup failed to ${RemoteBackupDir}" + echo $transfer_file >> $BACKUPDIR/remote_backup_failed.txt else - /usr/bin/func ${RemoteBackupDir} copyfile -f $BACKUPDIR/backup.$DATE.tgz --remotepath $BACKUPDIR/backup.$DATE.tgz - - echo "copying$BACKUPDIR/backup.$DATE.tgz to ${RemoteBackupDir}:/data/database_backup/" + echo "copying $BACKUPDIR/$transfer_file to ${RemoteBackupDir}:$BACKUPDIR/MBE_$transfer_file" + /usr/bin/func ${RemoteBackupDir} copyfile -f $BACKUPDIR/$transfer_file --remotepath $BACKUPDIR/MBE_$transfer_file + fi +} + +function add_link(){ + if [ -f $BACKUPDIR/remote_backup_failed.txt ] + then + RETRYFILE="/etc/cron.hourly/lh_backup_retry.sh" + echo "#!/bin/bash" > $RETRYFILE + echo "#This file was autogenerated and will be removed by lh_system_backup_job" >> $RETRYFILE + echo "MYTH_RUN_STATUS=1">> $RETRYFILE + echo ". /etc/profile">> $RETRYFILE + echo "lh_system_backup_job retry">> $RETRYFILE + chmod 755 $RETRYFILE + fi +} + +function remove_link(){ + RETRYFILE="/etc/cron.hourly/lh_backup_retry.sh" + if [ ! -f $BACKUPDIR/remote_backup_failed.txt ] + then + rm -f $RETRYFILE + fi +} + + +#------------------------------------ +lock_myth +if [ "x$1" = "x" ] +then + remove_old_backups + backup + update_backup_status + remote_backup + add_link +else + #this is where we attempt to transfer again as part of the cronjob + if [ -f $BACKUPDIR/remote_backup_failed.txt ] + then + mv -f $BACKUPDIR/remote_backup_failed.txt /tmp + while read line + do + echo $line + remote_transfer $line + done < /tmp/remote_backup_failed.txt + rm -f /tmp/remote_backup_failed.txt fi - $cmd + remove_link fi +unlock_myth +echo $backup_status > /var/run/systembackup.rc +exit $backup_status -echo "#########################################################" diff --git a/abs/core/LinHES-system/lh_system_host_update b/abs/core/LinHES-system/lh_system_host_update index 1a4d714..75fe548 100644 --- a/abs/core/LinHES-system/lh_system_host_update +++ b/abs/core/LinHES-system/lh_system_host_update @@ -4,6 +4,7 @@ # supplemental web echo "#####################################################" echo "Starting update" +MYTH_RUN_STATUS="1" . /etc/profile if [ x$1 = x ] diff --git a/abs/core/LinHES-system/lh_system_restore b/abs/core/LinHES-system/lh_system_restore new file mode 100755 index 0000000..99082ff --- /dev/null +++ b/abs/core/LinHES-system/lh_system_restore @@ -0,0 +1,32 @@ +#!/bin/bash +. /etc/systemconfig +BACKUPDIR=/data/storage/disk0/backup/system_backups + + +#find last backup +cd $BACKUPDIR +restore_file=`ls -t backup.*|head -1` +cd - + +if [ $SystemType != Master_backend -a $SystemType != Standalone ] +then + msg_client.py --msg "This is not the Master backend.\n Skipping restore of database." +fi + +#do the backup +msg_client.py --msg "Restoring from:\n$restore_file" +lh_system_restore_job $restore_file 2>&1 > /var/run/restore.log +rc=$? + +if [ $rc = 0 ] +then + complete_message="Restore completed successfully" +else + complete_message="Restore failed!" +fi + +msg_client.py --msg "$complete_message" + + + +#don't try to restore DB if not master diff --git a/abs/core/LinHES-system/lh_system_restore_job b/abs/core/LinHES-system/lh_system_restore_job index 9c66e2a..da7dbca 100644 --- a/abs/core/LinHES-system/lh_system_restore_job +++ b/abs/core/LinHES-system/lh_system_restore_job @@ -2,8 +2,16 @@ # This script is used to perform a quick restore of a database that was backed up via the nightly system backup # The restore only does the database it does NOT restore system files (even if they are in the backup file) # -BACKUPDIR=/myth/system_backups +# - supplemental web, process.py , lh_system_restore + +. /etc/systemconfig +BACKUPDIR=/data/storage/disk0/backup/system_backups +RESTOREDIR=$BACKUPDIR/restore backupfile=$1 +restore_status=0 + +MYTH_RUN_STATUS="1" +. /etc/profile function usage(){ echo "------------------------------------------------------" @@ -12,65 +20,223 @@ function usage(){ echo "Files are expected to be in the $BACKUPDIR" echo "usage:" echo "" - echo "lh_system_restore_job \$filename [yes]" + echo "lh_system_restore_job \$filename [cleanup partial]" echo "" echo "example: lh_system_restore_job backup.2011-12-22_15-34.tgz " echo "" echo "" - echo "If the script is passed a second argument, it will not cleanup the the restore dir." + echo "If the script is called with cleanup, it will cleanup the the restore dir." + echo "If the script is called with restore, it will restore the dir, and then copy back some settings." + echo " It's intended to be used with restoring R7 databases only" echo "------------------------------------------------------" exit 1 - } +} +function restore_status_check(){ + if [ $1 -ne 0 ] + then + restore_status=1 + fi +} -if [ x$backupfile = x ] -then - usage -fi +function run_cleanup(){ + echo "Cleaning up the restore dir" + rm -rf $RESTOREDIR/$DIR + rm -f $RESTOREDIR/$backupfile +} -. /etc/profile +function expand_restore_file(){ + mkdir -p $RESTOREDIR + DIR=`echo $backupfile |cut -d. -f2` + cp $BACKUPDIR/$backupfile $RESTOREDIR + cd $RESTOREDIR && tar -xf $backupfile && cd $DIR + restore_status_check $? +} -RESTOREDIR=$BACKUPDIR/restore -DIR=`echo $backupfile |cut -d. -f2` -CSQL="create database mythconverg;" -DSQL="drop database mythconverg; " -MYSQL="mysql -u mythtv -pmythtv" +function restore_db(){ + CSQL="create database mythconverg;" + DSQL="drop database mythconverg; " + MYSQL="mysql -u mythtv -pmythtv" + if [ -f mythconverg ] + then + #drop the db + $MYSQL -e "$DSQL" + #create the db + $MYSQL -e "$CSQL" + #restore the database_backup + echo "Restoring database $DIR" + $MYSQL mythconverg < mythconverg + rc=$? + restore_status_check $rc + if [ $rc = 0 ] + then + echo "Restore of mythconverg complete" + else + echo "An error occurred restoring mythconverg" + fi -mkdir -p $RESTOREDIR -cp $BACKUPDIR/$backupfile $RESTOREDIR -cd $RESTOREDIR && tar -xf $backupfile && cd $DIR + else + echo "Couldn't find file mythconverg to restore" + restore_status=1 + fi -if [ -f mythconverg ] -then - #drop the db - $MYSQL -e "$DSQL" - #create the db - $MYSQL -e "$CSQL" - #restore the database_backup - echo "Restoring the database $DIR" - $MYSQL mythconverg < mythconverg - if [ $? = 0 ] +} + +function restore_ncid(){ + CSQL="create database ncid;" + DSQL="drop database ncid; " + MYSQL="mysql -u root " + + if [ -f ncid ] then - echo "Done" + #drop the db + $MYSQL -e "$DSQL" + #create the db + $MYSQL -e "$CSQL" + #restore the database_backup + echo "Restoring database $DIR" + $MYSQL ncid < ncid + rc=$? + #restore_status_check $rc + + if [ $rc = 0 ] + then + echo "Restore of ncid complete" + else + echo "An error occurred restoring ncid" + fi + + else + echo "Couldn't find file ncid to restore" + fi + +} + + +function run_prestore(){ + echo "Partial restore of database" + echo "---------------------------------" + echo + #save settings to group + echo " Saving current database settings for selective import" + mythutil --export-settings --outfile $RESTOREDIR/pre_db.exports.xml --tablelist settings --generic 2> /dev/null >> /tmp/prestore.out + + #save storage groups + mysqldump mythconverg storagegroup > $RESTOREDIR/sg.sql + + #stop mythbackend + echo " Stopping mythbackend" + lh_backend_control.sh stop + + # restore mythconverg + restore_db + mysqldump mythconverg storagegroup > $RESTOREDIR/backupfile_sg.sql + mysql mythconverg -e "truncate storagegroup;" + + restore_ncid + # restore exported settings + echo " Importing previous settings into settings_pre_db" + mythutil --import-settings --infile $RESTOREDIR/pre_db.exports.xml --hostname `hostname` 2>/dev/null >> /tmp/prestore.out + + # restore storage_groups + mysql mythconverg < $RESTOREDIR/sg.sql + + #start mythbackend + echo " Starting mythbackend" + lh_backend_control.sh start + + echo + echo "Partial restore complete." + echo "All data for `hostname` has been restored except:" + echo "* storage groups definitions" + echo "* service menu settings" + + +} + +function run_full_restore(){ + echo "Full restore" + echo "---------------------------------" + echo + cp -f etc/systemconfig /etc/systemconfig + + if [ $SystemType = Master_backend -o $SystemType = Standalone ] + then + #stop mythbackend + echo " Stopping mythbackend" + lh_backend_control.sh stop + echo + + # restore mythconverg + restore_db + echo + restore_ncid + echo + + #start mythbackend + echo " Starting mythbackend" + lh_backend_control.sh start + echo + else - echo "An error occured" + # didn't restore the database, so restore FE settings + if [ -e settings ] + then + rsync -arvp settings/* /usr/MythVantage/templates/settings/ + fi + + if [ -e /usr/MythVantage/templates/settings/syssettings ] + then + myth_settings_wrapper.sh -c restore -t syssettings + restore_status_check $? + else + echo "Couldn't find syssettings file" + fi fi - else - echo "Couldn't file a file to restore" + systemconfig.py -m all + echo "Restore complete" +} + +#-----------------------Main program -------------------------- + +if [ x$backupfile = x ] +then + usage fi +prestore="false" +cleanup="false" + +for i in $*; do + #echo $i + if [ $i = "cleanup" ] + then + cleanup="true" + fi + + if [ $i = "partial" ] + then + prestore="true" + fi +done + +expand_restore_file -#cleanup -if [ x$2 = x ] +if [ $prestore = "true" ] then - echo "Cleaning up the restore dir" - rm -rf $RESTOREDIR/$DIR - rm -f $RESTOREDIR/$backupfile + run_prestore else - echo "Not doing a cleanup of $RESTOREDIR" + run_full_restore fi + +if [ $cleanup = "true" ] +then + run_cleanup +fi + +exit $restore_status diff --git a/abs/core/LinHES-system/misc_recent_recordings.pl b/abs/core/LinHES-system/misc_recent_recordings.pl new file mode 100755 index 0000000..92dda8a --- /dev/null +++ b/abs/core/LinHES-system/misc_recent_recordings.pl @@ -0,0 +1,194 @@ +#!/usr/bin/perl -w +# +# Outputs information about the most-recently-recorded shows. +# +# Automatically detects database settings. +# + +# Includes + use DBI; + use Getopt::Long; + use MythTV; + +# Some variables we'll use here + our ($num_recordings, $live, $heading, $plain_text, $text_format, $usage); + our ($hours, $minutes, $seconds); + our ($dnum_recordings, $dheading, $dtext_format); + our ($dhours, $dminutes, $dseconds); + our ($status_text_format, $status_value_format); + our ($dstatus_text_format, $dstatus_value_format); + +# Default number of recent recordings to show + $dnum_recordings = 5; +# Default period in which to show recordings + $dhours = -1; + $dminutes = -1; + $dseconds = -1; +# Default status output heading + $dheading='Recent Recordings:\n'; +# Default format of plain-text output + $dtext_format='%n/%j, %g:%i %A - %cc\n%T - %S\n%R\n\n'; +# Default format of status output display text + $dstatus_text_format= '<a href="javascript:void(0)">%n/%j %g:%i %A - %cc - %T - %S<br />'. + '<span><strong>%T</strong> %n/%j, %g:%i %A<br />'. + '<em>%S</em><br /><br />%R<br /></span></a><hr />'; +# Default format of status output value + $dstatus_value_format = '%n/%j, %g:%i %A - %T - %S'; + +# Provide default values for GetOptions + $num_recordings = $dnum_recordings; + $hours = $dhours; + $minutes = $dminutes; + $seconds = $dseconds; + $heading = $dheading; + $text_format = $dtext_format; + $status_text_format = $dstatus_text_format; + $status_value_format = $dstatus_value_format; + +# Load the cli options + GetOptions('num_recordings|recordings=s' => \$num_recordings, + 'hours|o=i' => \$hours, + 'minutes=i' => \$minutes, + 'seconds|e=i' => \$seconds, + 'live' => \$live, + 'heading=s' => \$heading, + 'plain_text' => \$plain_text, + 'text_format=s' => \$text_format, + 'status_text_format=s' => \$status_text_format, + 'status_value_format=s' => \$status_value_format, + 'usage|help' => \$usage + ); + +# Print usage + if ($usage) { + print <<EOF; +$0 usage: + +options: + +--recordings [number of recordings] + + Outputs information on the last [number of recordings] shows recorded by + MythTV. To output information on all recordings, specify -1. + + default: $dnum_recordings + +--hours [number of hours] + + Outputs information on recordings that occurred within [number of hours]. + This option may be specified in conjunction with --minutes and --seconds. + To output information on all matching recordings regardless of start time, + specify -1 for --hours, --minutes, and --seconds. + + default: $dhours + +--minutes [number of minutes] + + Outputs information on recordings that occurred within [number of minutes]. + This option may be specified in conjunction with --hours and --seconds. + To output information on all matching recordings regardless of start time, + specify -1 for --hours, --minutes, and --seconds. + + default: $dminutes + +--seconds [number of seconds] + + Outputs information on recordings that occurred within [number of seconds]. + This option may be specified in conjunction with --hours and --minutes. + To output information on all matching recordings regardless of start time, + specify -1 for --hours, --minutes, and --seconds. + + default: $dseconds + +--live + Include information on recent LiveTV recordings. + +--heading [heading] + Output the [heading] before printing information about recordings. + + default: \'$dheading\' + +--plain_text + Output information in plain text format (i.e. for inclusion in an e-mail + notification). + +--text_format [format] + Use the provided [format] to display information on the recordings. The + format should use the same format specifiers used by mythlink.pl, but + may also use \\r and/or \\n for line breaks. This option is ignored + if --plain_text is not used. + + default: \'$dtext_format\' + +--help + + Show this help text. + +EOF + exit; + } + +# Determine the period of interest + my $now = time(); + my $start_after = $now; + $start_after = $start_after - ($hours * 3600) if ($hours > 0); + $start_after = $start_after - ($minutes * 60) if ($minutes > 0); + $start_after = $start_after - $seconds if ($seconds > 0); + $start_after = 0 if (!($start_after < $now)); + +# Fix the heading. + if (defined($plain_text)) { + $heading =~ s/\\r/\r/g; + $heading =~ s/\\n/\n/g; + } + else { + # Remove line break format specifiers from heading for status output + $heading =~ s/(\\r|\\n)//g; + } + +# Connect to mythbackend + my $Myth = new MythTV(); + +# Get the list of recordings + my $count = 0; + my %rows = $Myth->backend_rows('QUERY_RECORDINGS Delete'); + our $show; + foreach my $row (@{$rows{'rows'}}) { + last unless (($count < $num_recordings) || ($num_recordings < 0)); + $show = new MythTV::Program(@$row); + # Skip LiveTV recordings? + next unless (defined($live) || $show->{'recgroup'} ne 'LiveTV'); + # Within the period of interest? + last if (($start_after) && ($show->{'recstartts'} < $start_after)); + # Print the recording information in the desired format + if (defined($plain_text)) { + text_print($count); + } + else { + status_print($count); + } + $count++; + } + +# Print the output for use in the backend status page. + sub status_print { + my $count = shift; + my $text = $show->format_name($status_text_format, ' ', ' ', 1, 0 ,1); + my $value = $show->format_name($status_value_format, ' ', ' ', + 1, 0 ,1); + print("$heading<div class=\"schedule\">") if ($count == 0); + print("$text"); + print("</div>") if ($count == ($num_recordings - 1)); + print("[]:[]recording$count"); + print("[]:[]$value\n"); + } + +# Print the output in plain text format + sub text_print { + my $count = shift; + my $text = $show->format_name($text_format, ' ', ' ', 1, 0 ,1); + $text =~ s/\\r/\r/g; + $text =~ s/\\n/\n/g; + print("$heading") if ($count == 0); + print("$text"); + } diff --git a/abs/core/LinHES-system/misc_status_config.py b/abs/core/LinHES-system/misc_status_config.py new file mode 100755 index 0000000..cc82534 --- /dev/null +++ b/abs/core/LinHES-system/misc_status_config.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python2 + +# This script will configure the myth db to use the misc_status_info scripts + +from socket import gethostname +from MythTV import MythDB +mythdb = MythDB() +localhostname = gethostname() + +# Function to set db setting. This setting is set in mythtv-setup. +def dbSettingChange(): + if mythdb.settings[localhostname].MiscStatusScript == u'': + mythdb.settings[localhostname].MiscStatusScript = u'/usr/LH/bin/misc_status_info.sh' + print 'The MythTV database setting MiscStatusScript was updated to /usr/LH/bin/misc_status_info.sh.' + else: + print 'The MythTV database setting MiscStatusScript is already set and will not be updated.' + return + +#taken from systemconfig.py +#this is how you populate the dict +systemconfig = {} +file_name = "/etc/systemconfig" +try: + config_file = open(file_name) +except: + logging.critical("%s could not be opened", file_name) + sys.exit(1) + +for line in config_file: + line = line.strip() + if line and line[0] is not "#" and line[-1] is not "=": + var, val = line.rsplit("=", 1) + val = val.strip('"') + systemconfig[var.strip()] = val.strip() + +#this is how you reference a value from mv_hostype.py +if (systemconfig.get("SystemType") == "Standalone"): + dbSettingChange() +elif systemconfig.get("SystemType") == "Master_backend": + dbSettingChange() diff --git a/abs/core/LinHES-system/misc_status_info.sh b/abs/core/LinHES-system/misc_status_info.sh new file mode 100755 index 0000000..14a972c --- /dev/null +++ b/abs/core/LinHES-system/misc_status_info.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Show all upcoming conflicts +/usr/LH/bin/misc_upcoming_recordings.pl --recordings -1 \ + --no_show_scheduled \ + --heading '<h3>Recording Conflicts</h3>' \ + --no_conflicts_message '<h3>No Recording Conflicts</h3>' + +# Show all the shows recorded today +/usr/LH/bin/misc_recent_recordings.pl --recordings=-1 --hours=24 \ + --heading '<h3>Shows Recorded In The Last 24 Hours</h3>' + +# Get Encoder that was used for recordings from the backend log +firstrun=1 +loglist=`find /var/log/ -name *_mythbackend.*.log*` +for i in `ls -t $loglist` +do + if [ $firstrun -eq 1 ]; then + echo "<h3>Encoder Information</h3><div class=\"schedule\"" + firstrun=0 + fi + /usr/LH/bin/misc_which_recorder.pl --noheader $i +done diff --git a/abs/core/LinHES-system/misc_upcoming_recordings.pl b/abs/core/LinHES-system/misc_upcoming_recordings.pl new file mode 100755 index 0000000..377c2dc --- /dev/null +++ b/abs/core/LinHES-system/misc_upcoming_recordings.pl @@ -0,0 +1,328 @@ +#!/usr/bin/perl -w +# +# Provides notification of upcoming recordings. +# +# Automatically detects database settings. +# + +# Includes + use DBI; + use Getopt::Long; + use MythTV; + +# Some variables we'll use here + our ($num_recordings, $heading, $plain_text, $text_format, $usage); + our ($hours, $minutes, $seconds, $no_conflicts_message); + our ($scheduled, $duplicates, $deactivated, $conflicts); + our ($dnum_recordings, $dheading, $dtext_format); + our ($dhours, $dminutes, $dseconds, $dno_conflicts_message); + our ($dscheduled, $dduplicates, $ddeactivated, $dconflicts); + our ($status_text_format, $status_value_format); + our ($dstatus_text_format, $dstatus_value_format); + +# Default number of upcoming recordings to show + $dnum_recordings = 5; +# Default period in which to show recordings + $dhours = -1; + $dminutes = -1; + $dseconds = -1; +# Default recording status types to show + $dscheduled = 1; + $dduplicates = 0; + $ddeactivated = 0; + $dconflicts = 1; +# Default status output heading + $dheading='Upcoming Recordings:\n'; +# Default format of plain-text output + $dtext_format='%rs\n%n/%j, %g:%i %A - %cc\n%T - %S\n%R\n\n'; +# Default "no conflicts" message + $dno_conflicts_message='No conflicts.\n'; +# Default format of status output display text + $dstatus_text_format= '<a href="javascript:void(0)">%rs - %n/%j %g:%i %A - %cc - '. + '%T - %S<br />'. + '<span><strong>%T</strong> %n/%j, %g:%i %A<br />'. + '<em>%S</em><br /><br />%R<br /></span></a><hr />'; +# Default format of status output value + $dstatus_value_format = '%n/%j %g:%i %A - %T - %S'; + +# Provide default values for GetOptions + $num_recordings = $dnum_recordings; + $hours = $dhours; + $minutes = $dminutes; + $seconds = $dseconds; + $scheduled = $dscheduled; + $duplicates = $dduplicates; + $deactivated = $ddeactivated; + $conflicts = $dconflicts; + $heading = $dheading; + $text_format = $dtext_format; + $no_conflicts_message = $dno_conflicts_message; + $status_text_format = $dstatus_text_format; + $status_value_format = $dstatus_value_format; + +# Load the cli options + GetOptions('num_recordings|recordings=s' => \$num_recordings, + 'hours|o=i' => \$hours, + 'minutes=i' => \$minutes, + 'seconds|s=i' => \$seconds, + 'show_scheduled|_show_scheduled|scheduled|_scheduled|e!' + => \$scheduled, + 'show_duplicates|_show_duplicates|duplicates|_duplicates|p!' + => \$duplicates, + 'show_deactivated|_show_deactivated|deactivated|_deactivated|v!' + => \$deactivated, + 'show_conflicts|_show_conflicts|conflicts|_conflicts!' + => \$conflicts, + 'heading=s' => \$heading, + 'plain_text' => \$plain_text, + 'text_format=s' => \$text_format, + 'no_conflicts_message=s' => \$no_conflicts_message, + 'status_text_format=s' => \$status_text_format, + 'status_value_format=s' => \$status_value_format, + 'usage|help' => \$usage + ); + +# Print usage + if ($usage) { + # Make default "--show_*" options readable + $dscheduled = ($dscheduled ? '--show_scheduled' : + '--no_show_scheduled'); + $dduplicates = ($dduplicates ? '--show_duplicates' : + '--no_show_duplicates'); + $ddeactivated = ($ddeactivated ? '--show_deactivated' : + '--no_show_deactivated'); + $dconflicts = ($dconflicts ? '--show_conflicts' : + '--no_show_conflicts'); + print <<EOF; +$0 usage: + +options: + +--recordings [number of recordings] + + Outputs information on the next [number of recordings] shows to be recorded + by MythTV and that match the criteria specified for --scheduled, + --duplicates, --deactivated, and --conflicts. To output information on all + matching recordings, specify -1. + + default: $dnum_recordings + +--hours [number of hours] + + Outputs information on recordings starting in the next [number of hours] + and that match the criteria specified for --scheduled, --duplicates, + --deactivated, and --conflicts. This option may be specified in + conjunction with --minutes and --seconds. To output information on all + matching recordings regardless of start time, specify -1 for --hours, + --minutes, and --seconds. + + default: $dhours + +--minutes [number of minutes] + + Outputs information on recordings starting in the next [number of minutes] + and that match the criteria specified for --scheduled, --duplicates, + --deactivated, and --conflicts. This option may be specified in + conjunction with --hours and --seconds. To output information on all + matching recordings regardless of start time, specify -1 for --hours, + --minutes, and --seconds. + + default: $dminutes + +--seconds [number of seconds] + + Outputs information on recordings starting in the next [number of seconds] + and that match the criteria specified for --scheduled, --duplicates, + --deactivated, and --conflicts. This option may be specified in + conjunction with --hours and --minutes. To output information on all + matching recordings regardless of start time, specify -1 for --hours, + --minutes, and --seconds. + + default: $dseconds + +--show_scheduled|--no_show_scheduled + + Outputs information about scheduled recordings. Scheduled recordings are + those that MythTV plans to actually record. + + default: $dscheduled + +--show_duplicates|--no_show_duplicates + + Outputs information about duplicate recordings. Duplicate recordings are + those that will not be recorded because of the specified duplicate matching + policy for the rule. + + default: $dduplicates + +--show_deactivated|--no_show_deactivated + + Outputs information about deactivated recordings. Deactivated recordings + are those that MythTV will not record because the schedule is inactive, + because the showing was set to never record, because the show is being + recorded in an earlier or later showing, because there are too many + recordings or not enough disk space to allow the recording, or because + the show you\'ve specified for recording is not listed in the timeslot + specified. + + default: $ddeactivated + +--show_conflicts|--no_show_conflicts + + Outputs information about conflicts (those shows that MythTV cannot record + because of other higher-priority scheduled recordings). + + default: $dconflicts + +--heading [heading] + Output the [heading] before printing information about recordings. + + default: \'$dheading\' + +--plain_text + Output information in plain text format (i.e. for inclusion in an e-mail + notification). + +--text_format [format] + Use the provided [format] to display information on the recordings. The + format should use the same format specifiers used by mythlink.pl, but + may also use \\r and/or \\n for line breaks and %rs for recording status. + This option is ignored if --plain_text is not used. + + default: \'$dtext_format\' + +--no_conflicts_message [message] + Use the provided [message] to specify there are no conflicts. This option + is used when only information about conflicts is requested and there are + no conflicts. I.e. it is only used with the combination of show_* + options --show_conflicts, --no_show_scheduled, --no_show_deactivated, + and --no_show_duplicates . + + default: \'$dno_conflicts_message\' + +--help + + Show this help text. + +EOF + exit; + } + +# Determine the period of interest + my $now = time(); + my $start_before = $now; + $start_before = $start_before + ($hours * 3600) if ($hours > 0); + $start_before = $start_before + ($minutes * 60) if ($minutes > 0); + $start_before = $start_before + $seconds if ($seconds > 0); + $start_before = 0 if (!($start_before > $now)); + +# Fix the heading. + if (defined($plain_text)) { + $heading =~ s/\\r/\r/g; + $heading =~ s/\\n/\n/g; + } + else { + # Remove line break format specifiers from heading for status output + $heading =~ s/(\\r|\\n)//g; + } + +# Connect to mythbackend + my $Myth = new MythTV(); + +# Get the list of recordings + my $count = 0; + my %rows = $Myth->backend_rows('QUERY_GETALLPENDING', 2); + my $has_conflicts = $rows{'offset'}[0]; + if ((!$has_conflicts) && + (($conflicts) && + (!(($scheduled) || ($duplicates) || ($deactivated))))) { + $no_conflicts_message =~ s/\\r/\r/g; + $no_conflicts_message =~ s/\\n/\n/g; + print "$no_conflicts_message"; + exit 0; + } + my $num_scheduled = $rows{'offset'}[1]; + our $show; + foreach my $row (@{$rows{'rows'}}) { + last unless (($count < $num_recordings) || ($num_recordings < 0)); + $show = new MythTV::Program(@$row); + last if (($start_before) && ($show->{'recstartts'} > $start_before)); + next if ((!$scheduled) && (is_scheduled($show->{'recstatus'}))); + next if ((!$duplicates) && (is_duplicate($show->{'recstatus'}))); + next if ((!$deactivated) && (is_deactivated($show->{'recstatus'}))); + next if ((!$conflicts) && (is_conflict($show->{'recstatus'}))); + + # Print the recording information in the desired format + if (defined($plain_text)) { + text_print($count); + } + else { + status_print($count); + } + $count++; + } + +# Returns true if the show is scheduled to record + sub is_scheduled { + my $recstatus = (shift() or 0); + return (($MythTV::recstatus_willrecord == $recstatus) || + ($MythTV::recstatus_recorded == $recstatus) || + ($MythTV::recstatus_recording == $recstatus)); + } + +# Returns true if the show is a duplicate + sub is_duplicate { + my $recstatus = (shift() or 0); + return (($MythTV::recstatus_repeat == $recstatus) || + ($MythTV::recstatus_previousrecording == $recstatus) || + ($MythTV::recstatus_currentrecording == $recstatus)); + } + +# Returns true if the recording is deactivated + sub is_deactivated { + my $recstatus = (shift() or 0); + return (($MythTV::recstatus_inactive == $recstatus) || + ($MythTV::recstatus_toomanyrecordings == $recstatus) || + ($MythTV::recstatus_cancelled == $recstatus) || + ($MythTV::recstatus_deleted == $recstatus) || + ($MythTV::recstatus_aborted == $recstatus) || + ($MythTV::recstatus_notlisted == $recstatus) || + ($MythTV::recstatus_dontrecord == $recstatus) || + ($MythTV::recstatus_lowdiskspace == $recstatus) || + ($MythTV::recstatus_tunerbusy == $recstatus) || + ($MythTV::recstatus_neverrecord == $recstatus) || + ($MythTV::recstatus_earliershowing == $recstatus) || + ($MythTV::recstatus_latershowing == $recstatus)); + } + +# Returns true if the show cannot be recorded due to a conflict + sub is_conflict { + my $recstatus = (shift() or 0); + return ($MythTV::recstatus_conflict == $recstatus); + } + +# Print the output for use in the backend status page. + sub status_print { + my $count = shift; + my $text = $show->format_name($status_text_format, ' ', ' ', 1, 0 ,1); + $text =~ s/%rs/$MythTV::RecStatus_Types{$show->{'recstatus'}}/g; + my $value = $show->format_name($status_value_format, ' ', ' ', + 1, 0 ,1); + $value =~ s/%rs/$MythTV::RecStatus_Types{$show->{'recstatus'}}/g; + print("$heading<div class=\"schedule\">") if ($count == 0); + print("$text"); + print("</div>") if ($count == ($num_recordings - 1)); + print("[]:[]recording$count"); + print("[]:[]$value\n"); + } + +# Print the output in plain text format + sub text_print { + my $count = shift; + my $text = $show->format_name($text_format, ' ', ' ', 1, 0 ,1); + $text =~ s/%rs/$MythTV::RecStatus_Types{$show->{'recstatus'}}/g; + $text =~ s/\\r/\r/g; + $text =~ s/\\n/\n/g; + print("$heading") if ($count == 0); + print("$text"); + } diff --git a/abs/core/LinHES-system/misc_which_recorder.pl b/abs/core/LinHES-system/misc_which_recorder.pl new file mode 100755 index 0000000..6952b3f --- /dev/null +++ b/abs/core/LinHES-system/misc_which_recorder.pl @@ -0,0 +1,107 @@ +#!/usr/bin/perl -w +# +# Parses the backend log file and includes information on which encoder was used to record shows. + +my ($time, $title, $subtitle, $chanid, $cardid, $sourceid); +my $index = 0; + +sub print_text +{ + print "$time - $title"; + print ": $subtitle" if ($subtitle); + print "\n"; + print " - Encoder ID: $cardid\n"; + print " - Video Source ID: $sourceid\n"; + print " - Channel ID: $chanid\n"; +} + +sub print_xml +{ + print "<a href=\"javascript:void(0)\">$time - $title"; + print ": $subtitle" if ($subtitle); + print " - Encoder: $cardid<br />". + "<span><strong>$title</strong> $time<br />"; + print "<em>$subtitle</em><br />" if ($subtitle); + print "<br />Channel ID: $chanid<br />Encoder ID: $cardid<br />". + "Video Source ID: $sourceid<br /></span></a><hr />"; + # For XML parsers + print "[]:[]capture_info$index\[]:[]time='$time':title='$title'". + ":subtitle='$subtitle':chanid='$chanid':cardid='$cardid'". + ":sourceid='$sourceid'\n"; +} + +my $mode = shift; +my $log_file = shift; + +if (($mode ne "--text") && ($mode ne "--noheader")) +{ + $log_file = $mode; +} + +if ($log_file =~ m/^--.*/i) +{ + die ("Only one option can be used at a time.\n"); +} + +if ($log_file =~ /\.gz$/) +{ +# read top down +# open($fh, "gunzip -c $log_file |") or die "Unable to open log file '$log_file', stopping:"; + open($fh, "gunzip -c $log_file |tac |") or die "Unable to open log file '$log_file', stopping:"; +} +else +{ +# read top down +# open($fh, "<$log_file") or die "Unable to open log file '$log_file', stopping:"; + open($fh, "tac $log_file |") or die "Unable to open log file '$log_file', stopping:"; +} + +while (<$fh>) +{ +# Myth .24 regex to find start of recording +# if (/^(.*)(?:\d(?: I )?|I.* -) (?:Started|Tuning) recording: (.*): channel (\d+) on cardid (\d+), sourceid (\d+)/) +# Myth .25 regex to find start of recording for digital and analog MPEG + if (/^(\d+-\d+-\d+T\d+\:\d+\:\d+)(?:.*) (?:Started|Tuning) recording: (.*): channel (\d+) on cardid (\d+), sourceid (\d+)/ || /^(\d+-\d+-\d+T\d+\:\d+\:\d+)(?:.*) \(UpdateRecStatus\) Updating status for (.*)() on cardid (\d+) \(Will Record => Recording\)()/) + { + if ($mode eq "--noheader") + { + print "<div class=\"schedule\">" + if (($index == 0) && ($mode ne "--text")); + } + else + { + print "<h3>Encoder Information</h3><div class=\"schedule\">" + if (($index == 0) && ($mode ne "--text")); + } + $index++; + + ($time, $title, $chanid, $cardid, $sourceid) = ($1, $2, $3, $4, $5); + $time =~ s/T/' '/; + $time = `date -d $time +%a' '%m/%d' '%l:%M' '%p`; + chomp ($time); + if (($title =~ /"?(.+)"?:"?(.*)"?/) || ($title =~ /(.+) "(.*)"/)) + { + $title = $1; + $subtitle = $2; + } + else + { + $subtitle = ''; + } + $title =~ s/^"//; + $subtitle =~ s/^"//; + $title =~ s/"$//; + $subtitle =~ s/"$//; + if ($mode eq "--text") + { + print_text; + } + else + { + print_xml; + } + } +} +print "</div>" if (($index > 0) && ($mode ne "--text")); + +close $fh; diff --git a/abs/core/LinHES-system/msg_client.py b/abs/core/LinHES-system/msg_client.py new file mode 100755 index 0000000..54c2e54 --- /dev/null +++ b/abs/core/LinHES-system/msg_client.py @@ -0,0 +1,102 @@ +#!/usr/bin/python2 +#client for msg_daemon + +import socket +import sys +import argparse +import pickle +import time +# Create a UDS socket +sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + +# Connect the socket to the port where the server is listening +server_address = '/run/msg_socket' +def send_message(message): + #print >>sys.stderr, 'connecting to %s' % server_address + try: + sock.connect(server_address) + except socket.error, msg: + print >>sys.stderr, msg + sys.exit(1) +#try: + sock.sendall(message) + #amount_received = 0 + #amount_expected = len(message) + print "Waiting for response..." + data = sock.recv(1024) + print data + +#finally: + #print >>sys.stderr, 'error occured closing socket' + + sock.close() +def usage(): + line = ''' + Help screen: + msg_client.py is used to add,remove, or list items in the queue of messages that + will be displayed on screen. Optionaly messages can be given an identifier or "tag". + This identifier does not have to be unique. + + Items are processed in the order they arrive, based off their slot number. + The lowest slot number will be displayed first. + After the message is displayed it is removed from the queue. + + + ADD: + To add items to the queue: + msg_client.py --msg "My first message" --tag "tag1" + + REMOVE: + Removing items are based off the tag. + To remove all items from the queue that match the tag "tag1": + msg_client.py --clear --tag tag1 + + To remove all items from the queue: + msg_client.py --clear + + + Listing items in the queue or to get the total count: + msg_client.py --print_list + > ------------- + > msg : slot 1 + > slot : 1 + > cmd : msg + > tag : None + > timeout : None + + + To immediately stop displaying the current message, use the kill command. + msg_client.py --kill + + ''' + print line + sys.exit(0) +if __name__ == "__main__": + parser = argparse.ArgumentParser() + + parser.add_argument('--tag', action='store', dest='tag',help='message tag') + parser.add_argument('--timeout', action='store', dest='timeout',help='time to display message') + action = parser.add_mutually_exclusive_group(required=True) + action.add_argument('--msg', action='store', dest='msg', help='Add message to the queue') + action.add_argument('--clear', action='store_true', help='Remove message from queue that match tag') + action.add_argument('--kill', action='store_true', help='Kill current msg thats displayed') + action.add_argument('--print_list', action='store_true', help='Print current queue') + action.add_argument('--usage', action='store_true', help='Print help screen') + + results = parser.parse_args() + resultsdict = vars(results) + + if results.msg : + cmd = "msg" + elif results.clear: + cmd = "clear" + elif results.kill: + cmd = "kill" + elif results.print_list: + cmd = "list" + elif results.usage: + usage() + + arg_dict = {'cmd':cmd , 'msg':resultsdict['msg'] , 'tag':resultsdict['tag'] , 'timeout':resultsdict['timeout']} + send_message(pickle.dumps(arg_dict)) + #sys.exit(0) diff --git a/abs/core/LinHES-system/msg_daemon.py b/abs/core/LinHES-system/msg_daemon.py new file mode 100755 index 0000000..cd0465b --- /dev/null +++ b/abs/core/LinHES-system/msg_daemon.py @@ -0,0 +1,363 @@ +#!/usr/bin/python2 +#MythVantage osd message deamon. +#Use the client to send messages to localhost +import socket +import sys +import os +import pickle +import operator +import threading +import time +import aosd +import ConfigParser +import multiprocessing +import subprocess,signal + +sys.path.append('/etc') + +server_address = '/run/msg_socket' +class msg_aosd(): + def scroll(self,osd, width, height, display_time,position): + pos = position + step = 1 + + osd.set_position(pos, width, height) + (x, y, _, _) = osd.get_geometry() + osd.set_position_offset(width, height) + osd.show() + + x -= 1 + y += height - 1; + for i in range(1, height + 1, step): + osd.loop_for(5) + y -= step + osd.set_geometry(x, y, width, i) + + osd.set_position(pos, width, height) + osd.set_position_offset(-1, -1) + (x, y, _, _) = osd.get_geometry() + #time to display + osd.loop_for(display_time) + for i in range(height, 0, -step): + y += step + osd.set_geometry(x, y, width, i); + osd.loop_for(1); + + osd.hide(); + + def setup(self,font_color,font_type): + osd = aosd.AosdText() + osd.set_transparency(aosd.TRANSPARENCY_COMPOSITE) + if osd.get_transparency() != aosd.TRANSPARENCY_COMPOSITE: + osd.set_transparency(aosd.TRANSPARENCY_NONE) + + osd.geom_x_offset = 10 + osd.geom_y_offset = 0 + + osd.back_color = "white" + osd.back_opacity = 50 + + osd.shadow_color = "black" + osd.shadow_opacity = 127 + osd.shadow_x_offset = 2 + osd.shadow_y_offset = 2 + + osd.fore_color = font_color + osd.fore_opacity = 255 + + osd.set_font(font_type) + osd.wrap = aosd.PANGO_WRAP_WORD_CHAR + osd.alignment = aosd.PANGO_ALIGN_LEFT + osd.set_layout_width(osd.get_screen_wrap_width()) + return osd + + def set_string(self, osd, text): + osd.set_text(text) + return osd.get_text_size() + + def setup_config(self): + module_config = ConfigParser.RawConfigParser() + try: + module_config.read('/usr/MythVantage/etc/msg.cfg') + except: + pass + return module_config + + + + def display (self,flags,display_time=-1): + """ + parse the msg for display. + """ + try: + text,config_section=flags.split("|") + if config_section == '': + config_section="default" + except: + text=flags + config_section="default" + + module_config = self.setup_config() + + position=6 + font_color="green" + font_type="Times New Roman Italic 36" + + if display_time <= 0 : + try: + display_time = int(module_config.get(config_section,"display_time")) + except: + display_time = 5000 + pass + try: + position = int(module_config.get(config_section,"position")) + except: + pass + try: + font_color = module_config.get(config_section,"font_color") + except: + pass + try: + font_type = module_config.get(config_section,"font_type") + except: + pass + + #this bit of code converts a \n to EOL/BREAK + textline=text.split('\\n') + try: + textline.remove(' ') + except: + pass + text=chr(10).join(textline) + + #cmd = sub_process.Popen("/usr/bin/wall %s" % text,stdout=sub_process.PIPE,shell=True) + #data = cmd.communicate()[0] + osd = self.setup(font_color, font_type) + width, height = self.set_string(osd, text) + self.scroll(osd, width, height, display_time, position) + + return ("Message delivered") + + +class msg_xosd(): + """Crude wrapper for xosd_cat""" + def __init__ (self): + pass + + def set_default_values(self): + self.color="yellow" + self.outline="2" + self.outlinecolour="black" + self.shadow="0" + self.shadowcolour="black" + self.font="-adobe-helvetica-bold-*-*-*-34-*-*-*-*-*-*-*" + return + + def set_parameters(self): + xosd_cfg={} + file_name = "/etc/osd_cat.cfg" + try: + config_file = open(file_name) + except: + set_default_values() + return + + for line in config_file: + line = line.strip() + if line and line[0] is not "#" and line[-1] is not "=": + var, val = line.rsplit("=", 1) + val = val.split("#")[0] + val = val.strip('"') + xosd_cfg[var.strip()] = val.strip() + self.color = xosd_cfg['color'] + self.outline = xosd_cfg['outline'] + self.outlinecolour = xosd_cfg['outlinecolour'] + self.shadow = xosd_cfg['shadow'] + self.shadowcolour = xosd_cfg['shadowcolour'] + self.font = xosd_cfg['font'] + + def display(self,msg,display_time): + self.set_parameters() + cmd = "echo -e \"%s\" | DISPLAY=127.0.0.1:0 osd_cat --pos=middle --align=center --offset=200 --delay=%s --color=%s --outline=%s --outlinecolour=%s --shadow=%s --shadowcolour=%s --font=\"%s\"" %(msg,display_time,self.color,self.outline,self.outlinecolour,self.shadow,self.shadowcolour,self.font) + #set a process group on the OS, so that the kill gets them all. No one survives or becomes a zombie + self.p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,preexec_fn=os.setsid) + self.processID = self.p.pid + stdout,stderr = self.p.communicate() + + def kill(self): + try: + os.killpg(self.processID,signal.SIGTERM) + except: + pass + +class Msg_Queue(): + def __init__(self): + self.msglist=[] + self.msg_slot = 0 + + def get_msg(self): + return self.msglist.pop(0) + pass + + def add_msg(self,cmddict): + #print "Adding msg to msg queue" + self.inc_last_msg_slot() + cmddict['slot'] = self.msg_slot + self.msglist.append(cmddict) + + + def clear_msg(self,msg_tag): + #print "Clearing out list of %s" %msg_tag + #loop over list in reverse + for i in xrange(len(self.msglist) - 1, -1, -1): + #access list by index, look at the key tag + if self.msglist[i]['tag'] == msg_tag: + del self.msglist[i] + + def clear(self): + #print "Clearing out entire queue" + del self.msglist[:] + + def sort(self,keyvalue): + self.msglist.sort(key=operator.itemgetter(keyvalue)) + + def search(self,key,value): + pass + + def get_queue(self): + return self.msglist + + def get_last_msg_slot(self): + return self.msg_slot + + def inc_last_msg_slot(self): + self.msg_slot = self.msg_slot + 1 + + +class msg_queue_runner(threading.Thread): + """Threaded Queue runner for testing things""" + def __init__(self, msg_queue): + threading.Thread.__init__(self) + self.msg_queue = msg_queue + self.out_msg = msg_aosd() + self.out_xosd = msg_xosd() + + def get_current_style(self): + style = "enhanced" + if os.path.exists('/etc/X11/WINDOWMANAGER'): + command = ['bash', '-c', 'source /etc/X11/WINDOWMANAGER && echo $STARTUP_STYLE'] + proc = subprocess.Popen(command, stdout = subprocess.PIPE) + #default + for line in proc.stdout: + if line.strip() == "": + style = "enhanced" + else: + style = line.strip() + break + proc.communicate() + else: + #default + style = "enhanced" + return style + + + def kill_current(self): + style = self.get_current_style() + #print "Killing current display" + if style == "enhanced": + self.p.terminate() + elif style == "legacy": + #self.p.terminate() + self.out_xosd.kill() + + def run(self): + while True: + display_time = None + try: + msgdict = self.msg_queue.get_msg() + style = self.get_current_style() + if msgdict['timeout'] == None: + display_time = 3 + else: + display_time = msgdict['timeout'] + # display message here + msgtext = msgdict['msg'] + if style == "enhanced": + display_time = int(display_time) * 1000 + self.p = multiprocessing.Process(target=self.out_msg.display, args=(msgtext,display_time)) + self.p.start() + self.p.join() + elif style == "legacy": + #display_time = int(msgdict['timeout']) + self.out_xosd.display(msgtext,display_time) + + except: + time.sleep(1) + continue + + +msg_queue = Msg_Queue() + + +if __name__ == "__main__": + # Make sure the socket does not already exist + try: + os.unlink(server_address) + except OSError: + if os.path.exists(server_address): + raise + # Create a UDS socket + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + # Bind the socket to the port + #print >>sys.stderr, 'starting up on %s' % server_address + sock.bind(server_address) + #change permissions of socket + os.chmod(server_address,0777) + + # Listen for incoming connections + sock.listen(2) + #start msg display thread + msgthread = msg_queue_runner(msg_queue) + msgthread.setDaemon(True) + msgthread.start() + + #main loop that reads in the cmddict, never exits + while True: + # Wait for a connection + connection, client_address = sock.accept() + try: + #sf = connection.makefile("r+b", bufsize=0) + data = connection.recv(1024) + cmddict = (pickle.loads(data)) + connection.send(" Server acknowledged client \n") + if cmddict['cmd'] == "msg": + #add to msg_queue + msg_queue.add_msg(cmddict) + + elif cmddict['cmd'] == 'clear': + if cmddict['tag'] == '' or cmddict['tag'] == None : + msg_queue.clear() + else: + msg_queue.clear_msg(cmddict['tag']) + + elif cmddict['cmd'] == 'kill': + msgthread.kill_current() + + elif cmddict['cmd'] == 'list': + q = msg_queue.get_queue() + for i in q: + line="-------------\n" + connection.send(line) + for k,v in i.iteritems(): + line=" %s : %s\n" %(k,v) + connection.send(line) + line = "Number of messages in queue: %s \n" %(len(q)) + connection.send(line) + #connection.send(pickle.dumps(q)) + + + finally: + # Clean up the connection + connection.close() + + diff --git a/abs/core/LinHES-system/xmsg.py b/abs/core/LinHES-system/msg_osd.py index 669a796..669a796 100644 --- a/abs/core/LinHES-system/xmsg.py +++ b/abs/core/LinHES-system/msg_osd.py diff --git a/abs/core/LinHES-system/myth_mtc.lr b/abs/core/LinHES-system/myth_mtc.lr index 23f8711..2b2fbba 100644 --- a/abs/core/LinHES-system/myth_mtc.lr +++ b/abs/core/LinHES-system/myth_mtc.lr @@ -1,7 +1,7 @@ /var/log/mythtv/myth_mtc.log { copytruncate daily - size 10M + #size 1M missingok rotate 7 compress diff --git a/abs/core/LinHES-system/myth_mtc.py b/abs/core/LinHES-system/myth_mtc.py index 6fd53a7..a5f02a0 100755 --- a/abs/core/LinHES-system/myth_mtc.py +++ b/abs/core/LinHES-system/myth_mtc.py @@ -1,6 +1,4 @@ -#!/usr/bin/python - - +#!/usr/bin/python2 import sys, subprocess import optparse import re @@ -8,8 +6,6 @@ import socket import os import datetime,time - - try: from MythTV import MythBE mythtv = MythBE() diff --git a/abs/core/LinHES-system/myth_mtc.sh b/abs/core/LinHES-system/myth_mtc.sh index 12486c4..7899daa 100755 --- a/abs/core/LinHES-system/myth_mtc.sh +++ b/abs/core/LinHES-system/myth_mtc.sh @@ -1,7 +1,9 @@ #!/bin/bash +MYTH_RUN_STATUS=1 . /etc/profile -logFile='/var/log/mythtv/myth_mtc.log' + date=`date +%Y-%m-%d` +logFile="/var/log/$date/myth_mtc.log" MYTHCONFDIR=/usr/share/mythtv myth_mtc.py > $logFile 2>&1 if [ $? = 0 ] diff --git a/abs/core/LinHES-system/myth_status.py b/abs/core/LinHES-system/myth_status.py index 4637b90..2e48024 100644 --- a/abs/core/LinHES-system/myth_status.py +++ b/abs/core/LinHES-system/myth_status.py @@ -5,7 +5,7 @@ try: be=MythBE() db = MythDB() except: - print "Couldn't connect to MythTV service for status" + print "\nCouldn't connect to MythTV service for status" sys.exit(1) cursor = db.cursor() @@ -60,13 +60,15 @@ for i in a: type = results[0][0] hostname = results[0][1] id = i - c=be.getCurrentRecording(i) - if c.title == None: - current_recording = "Idle" - else: - current_recording = "Recording %s" %c.title - print " Tuner %s (%s) on %s : %s " %(id, type, hostname, current_recording) - + try: + c=be.getCurrentRecording(i) + if c.title == None: + current_recording = "Idle" + else: + current_recording = "Recording %s" %c.title + print " Tuner %s (%s) on %s : %s " %(id, type, hostname, current_recording) + except: + print " Tuner %s (%s) on %s : %s " %(id, type, hostname, "Tuner Error") print "" print "Upcoming Recordings (Next %s scheduled):" %(num_upcoming) @@ -90,14 +92,13 @@ print "" print "Conflicted Recordings:" print "----------------------" a=be.getConflictedRecordings() -try: - if len(a) == 0: - print " No conflicts" - else: - for i in a: - title_chan="%s (%s)" %(i.title, i.channame) - print " %s - %-50s " %(i.starttime,title_chan) -except: +c=0 +for i in a: + title_chan="%s (%s)" %(i.title, i.channame) + print " %s - %-50s " %(i.starttime,title_chan) + c=c+1 + +if c == 0: print " No conflicts" print "" diff --git a/abs/core/LinHES-system/mythfrontend-start b/abs/core/LinHES-system/mythfrontend-start index 1f48449..5cfc9b7 100755 --- a/abs/core/LinHES-system/mythfrontend-start +++ b/abs/core/LinHES-system/mythfrontend-start @@ -19,10 +19,10 @@ then fi question="There $diagtext running. Do you really want to start another one?" - mythvantage -q "${question}" + mythvantage -Q "${question}" if [ $? = 16 ] then - $STARTCMD 2>&1 + $STARTCMD 2>&1 fi else $STARTCMD 2>&1 diff --git a/abs/core/LinHES-system/readme_is_xml b/abs/core/LinHES-system/readme_is_xml new file mode 100644 index 0000000..d2af0f6 --- /dev/null +++ b/abs/core/LinHES-system/readme_is_xml @@ -0,0 +1 @@ +Files ending in .conf will be read by gen_is_xml.py or gen_lib_xml.py and output xml as appropriate diff --git a/abs/core/LinHES-system/readme_light b/abs/core/LinHES-system/readme_light new file mode 100644 index 0000000..0f35b19 --- /dev/null +++ b/abs/core/LinHES-system/readme_light @@ -0,0 +1 @@ +Files ending in .conf will be read by gen_light and rewrite /etc/lighttpd/conf.include diff --git a/abs/core/LinHES-system/set_windowmanager.sh b/abs/core/LinHES-system/set_windowmanager.sh index 3d0cdb2..4cb7a1c 100644 --- a/abs/core/LinHES-system/set_windowmanager.sh +++ b/abs/core/LinHES-system/set_windowmanager.sh @@ -5,6 +5,7 @@ # windowmanager="$1" style="$2" +configdir=/usr/share/wm_data function outmsg(){ @@ -16,6 +17,76 @@ function stylemsg(){ echo "Startup path will use $1 style" } +function set_wm(){ + case ${windowmanager} in + + fluxbox) + outmsg "fluxbox" + outline="fluxbox" + echo "fluxbox" > /etc/X11/WINDOWMANAGER + ;; + + enlightenment|default) + outmsg "enlightenment" + outline="e16 -P $configdir/e16_config_dir/" + ;; + + windowmaker) + outmsg "window maker" + outline_2="export GNUSTEP_USER_ROOT=$configdir/GNUstep" + outline="wmaker" + ;; + + *) + outline=$windowmanager + outmsg "$outline" + ;; + + esac + + + + case ${style} in + + legacy) + STYLE="$style" + stylemsg "Default" + HSTYLE=0 + ;; + + enhanced|*) + STYLE="enhanced" + HSTYLE="1" + stylemsg enhanced + myth_settings_wrapper.sh -c load -t custom 1 HOSTSupplemental + ;; + +# *) +# if [ x$style != x ] +# then +# stylemsg "** Unknown style..using default" +# STYLE="" +# else +# STYLE="$style" +# stylemsg "Default" +# fi +# HSTYLE=0 +# ;; + esac + + + + echo WM=\"${outline}\" > /etc/X11/WINDOWMANAGER + echo "STARTUP_STYLE=$STYLE" >> /etc/X11/WINDOWMANAGER + echo ${outline_2} >> /etc/X11/WINDOWMANAGER + + myth_settings_wrapper.sh -c load -t custom "${windowmanager}" HostWindowManager + myth_settings_wrapper.sh -c load -t custom "${HSTYLE}" HostEnhancedWMStyle + + + } + + if [ x$windowmanager = x ] then echo @@ -30,13 +101,14 @@ then echo " place_custom_startup_here" echo echo "Valid STARTUP_STYLE options are:" - echo " default" - echo " mythvantage" + echo " legacy" + echo " enhanced" echo echo "If STARTUP_STYLE is not given, then the default will be used." + echo " default is currently set as enlightenment enhanced" echo echo "Example: " - echo " set_windowmanager.sh enlightenment mythvantage" + echo " set_windowmanager.sh enlightenment enhanced" echo echo " " echo "if using enlightenment or windowmaker, please ensure that the alt_wm group is installed" @@ -45,55 +117,32 @@ then exit 0 fi +set_wm -case ${windowmanager} in +# if [ x$outline = "xdefault" ] +# then +# exit 0 +# fi - default) - outmsg "default/fluxbox" - outline="fluxbox" - echo "" > /etc/X11/WINDOWMANAGER - exit 0 - ;; - - enlightenment) - outmsg "enlightenment" - outline="e16 -P /data/e16_config_dir/" - ;; - - windowmaker) - outmsg "window maker" - outline_2="export GNUSTEP_USER_ROOT=/data/GNUstep" - - outline="wmaker" - ;; - - *) - outline=$windowmanager - outmsg "$outline" - ;; - -esac +WM_CHECK=`echo $outline|cut -d" " -f1 |tr -dc '[:alnum:]'` +which $WM_CHECK 2>/dev/null +rc=$? +if [ $rc != 0 ] +then + echo " ***Window manager $WM_CHECK does not look like it is present" + echo " ***setting windowmanger to windowmaker" + echo " " + windowmanager="windowmaker" + set_wm +fi -case ${style} in - mythvantage) - STYLE="mythvantage" - stylemsg MythVantage - ;; - *) - STYLE="$style" - stylemsg "Default" - ;; -esac -echo WM=\"${outline}\" > /etc/X11/WINDOWMANAGER -echo "STARTUP_STYLE=$STYLE" >> /etc/X11/WINDOWMANAGER -echo ${outline_2} >> /etc/X11/WINDOWMANAGER diff --git a/abs/core/LinHES-system/system-sudo.rules b/abs/core/LinHES-system/system-sudo.rules new file mode 100644 index 0000000..86e1b72 --- /dev/null +++ b/abs/core/LinHES-system/system-sudo.rules @@ -0,0 +1 @@ +mythtv ALL=(ALL) NOPASSWD: ALL diff --git a/abs/core/LinHES-system/system.install b/abs/core/LinHES-system/system.install new file mode 100644 index 0000000..662e271 --- /dev/null +++ b/abs/core/LinHES-system/system.install @@ -0,0 +1,47 @@ +# This is a default template for a post-install scriptlet. You can +# remove any functions you don't need (and this header). + +# arg 1: the new package version +pre_install() { + /bin/true +} + +# arg 1: the new package version +post_install() { + MVDIR=/usr/LH/bin + #add myth_mtc to cron list + if [ ! -e /etc/cron.daily/myth_mtc ] + then + ln -s $MVDIR/myth_mtc.sh /etc/cron.daily/myth_mtc + fi + + # Add db entry for misc status in MythWeb + # not needed in R8 because it's in the DB, may be removed + #/usr/LH/bin/misc_status_config.py +} + +# arg 1: the new package version +# arg 2: the old package version +pre_upgrade() { + /bin/true +} + +# arg 1: the new package version +# arg 2: the old package version +post_upgrade() { + post_install +} + +# arg 1: the old package version +pre_remove() { + /bin/true +} + +# arg 1: the old package version +post_remove() { + /bin/true +} + +op=$1 +shift +$op $* |