More permanent stuff at http://www.dusbabek.org/~garyd
Showing posts with label mythtv. Show all posts
Showing posts with label mythtv. Show all posts

22 February 2009

Restoring Myth Programs Whilst Maintaining Sanity

My MythTv system has been running continually, more or less, since October 2006. Not too long, but long enough. Long enough, in fact, for cruft to creep in. I discovered this on Saturday when I went to restore data to the replacement for the myth drive affectionately known as "xfs2" that died about a month ago.

That drive had a capacity of 250GB. My myth data is important to me, but not that important. I had it set to back up once a month to another computer in the house via rsync. I didn't pay too close attention to the way I used rsync though--instead of removing the remote files that had been removed locally, they just stayed there. In other words, unneeded data on the backup never went away, even when I deleted shows on the myth system.

So when I went to copy 274GB of data to a drive that would only hold 238GB, things went haywire.

Thankfully, I am a programmer. I am equipped for these kinds of situations.

I needed to figure out which shows missing locally that were present on the backups. These are the files that needed to be restored. After that, I figured it would be gravy if I could remove the orphans that were in the database but not on any file system, be it local or backup.

It turns out that python is incredibly easy to use with MySQL. I created a simple program that would restore from my backup and also give me a list of orphaned programs.

Seems easy, right? The complexity comes when both local and backup storage are strewn across different drives, directories and hosts. I made it simpler by using smbmount to mount the backup system so it appeared more or less local. After that it became a matter of letting the script run* and then cleaning up the orphans with a simple sql statement.

Source code for myth.py is at the bottom of this post.

* This turned out to be tricky. Something on my myth host causes it to intermittently hang when copying files to or from a remote host. It could be my router for all I know. I do know that *any* keystroke received by the myth system causes it to wake up and start accepting traffic again. Meanwhile, the system clock thinks nothing has happened and starts up again at the same tick where it fell asleep--so the clock is off. This problem first started when I decided to upgrade to Ubuntu 8.10 and MythTv 0.21 on the same day. Truly disturbing, I know. I circumvent this by bandwidth-limiting scp to 2Mbit for the transfer. Transfers take longer, but at least they complete. And yes, I am retiring this system in a few weeks. :)


import MySQLdb as db
import os
import sys

existing_video_dirs = ["/xfs1/myth/video", "/xfs2/myth/video"]
# If you use scp, backup_video_dirs and backup_scp_paths need to be maintained
# in parallel. For sure though, backup_video_dirs need to be locally mounted.
backup_video_dirs = ["/mnt/remote_backups/myth_backup/xfs1/myth/video", "/mnt/remote_backups/myth_backup/xfs2/myth/video"]
backup_scp_paths = ["garyd@child:/mnt/xfs3/myth_backup/xfs1/myth/video", "garyd@child:/mnt/xfs3/myth_backup/xfs2/myth/video"]
backup_info_dict = zip(backup_video_dirs, backup_scp_paths)
possible_file_extensions = ["mpg", "nuv"]

# this is the place video gets copied to.
restore_path = "/xfs2/myth/video/"

# connect to the database and get the list of shows.
con = db.connect(host="localhost", user="root", passwd="root", db="mythconverg")
cur = con.cursor()
cur.execute("select chanid, starttime, title from recordedprogram order by chanid, starttime")
rows = cur.fetchall()

# keep track of the number that are there or not.
there = 0
not_there = 0
restored = 0

for row in rows:
# name of the file is based on row values, plus a file extension.
fname = "%d_%s" % (row[0], row[1].strftime("%Y%m%d%H%M%S"))
# see if the file exists in the local myth dirs. If it does, there is no
# action.
exists = False
for dir in existing_video_dirs:
for ext in possible_file_extensions:
path = os.path.join(dir, fname + "." + ext)
if os.path.exists(path):
exists = True
if exists:
there += 1
else:
# if the file does not exist locally, look at the backup directories to
# see if it is there.
not_there += 1
backup_exists = False
backup_at = None # path of backup file.
backup_scp = None # scp path of backup file.
#for tup in backup_info_dict:
for dir, scp in backup_info_dict:
for ext in possible_file_extensions:
path = os.path.join(dir, fname + "." + ext)
if os.path.exists(path):
# found a backup! use wild cards so that the video file
# and its preview get copied.
backup_at = path + "*"
backup_scp = scp + "/" + fname + "." + ext + "*"
backup_exists = True
if not backup_exists:
print "No backup for %s" % (fname)
else:
# move the backup to the live system. use cp or scp depending on
# your preference.
cmd = "cp %s %s" % (backup_at, restore_path)
# something on my system is jacked. I need to bandwidth limit scp
# or else the myth server stalls.
cmd = "scp -l16000 %s %s" % (backup_scp, restore_path)
print cmd
os.popen(cmd)
restored += 1

# output the stats.
print "there:%d not_there:%d restored:%d" % (there, not_there, restored)


Update: fixed tabbing in code. Should have used pastebin.

02 February 2009

Superbowl Notes, 2009

I had taken pains to make sure watching the super bowl would be simple and painless. This included having dinner ready by 4:30 (we get home from church at 4), cookie dough (for snacks) already made, and Mythtv set to record the whole thing starting at 4.

We were done with dinner at 5. I took my time cleaning up, even though Gavan was chomping at the bit, unable to wait for us to start watching the game. I started a batch of cookies and went downstairs to start watching with Gavan.

I'll interject here and say that I'm not a huge TV sports fan. I was in my early years, but those tendencies seem to have left me about the same time fatherhood arrived. (I'm not sure if there is a connection or not.) The truth is, I would have peeked in on the game at intervals, watching for perhaps five minutes at a time. In the mean time, Gavan would be riveted to the sofa, basking in every moment of it. Such is youth.

None of it was to be though. Our one-year old, while Nicole was retrieving some items from the crawlspace, where the myth server is kept, managed to press the exact sequence of keys required to send the machine into hibernate. While it was recording. The super bowl.

If you follow this blog, you know that we've had a few problems with our MythTv setup lately. Apparently, this was too much for the system. Bringing the machine out of hibernate while in the middle of a write (recording the show), and a read (we were watching it on the MVP) was a Very Bad Thing, at least to the poor XFS filesystem that received the battering. I had no choice but to bring the system down. In the process of bringing the system back up again, I was informed by fsck that my disk was in bad shape and that I wouldn't be using it until I personally rectified the situation. Ouch. That is two of two disks down for the count.

All I really wanted to do was watch a few minutes of football with my son.

I grabbed the nearest piece of long coax, intending to connect it from the dish receiver--in the crawlspace, to the television--in the basement. I was angry. And not just a little bit angry. My daughter's Hello Kitty kick-ball was the nearest object I thought I could kick without injuring anybody, so I took a swing at it. And when I say "took a swing at it," I really mean to say is that I kicked at it like it was the last kick an unreformed kicking addict would ever kick because it was the last kickable object left in the universe. I put my heart, soul and body into it.

I mostly missed the ball. And mostly kicked the door. Ouch. I'm not doing good here. My foot throbbing and turing grurple (green+purple) in spots, I connected the coax, made sure the game was on, and then let Gavan know to come downstairs.

It was halftime at this point. I retreated to a bathroom to let some cold water run over my foot. I helped some. I was sure I had broke something.

The pain subsiding, and firmly in control of myself again, I sat down at the console to take a look at the Myth system. I set up a temporary space to hold shows and brought it back up, sans 500BG of storage. Ugh. But at least it was recording. I switched the coax back and all was right and sane again.

I'm kind of glad I missed the first half because the second half was 30 minutes of the best football I had ever watched in my life. Coming back from 13 points behind is difficult enough. In fact, the only thing more difficult, I'd say, is coming back after letting a 13 point lead slip away. And I saw both of those things last night. Truly remarkable. In my heart, I was silently rooting for Arizona, the underdogs. I was elated as I watched Larry Fitzgerald streak 80 yards down the field to put Arizona up. And then a few minutes later, in awe as I saw a Steelers team, firmly in control, take the ball 99 yards down the field and score on Santonio Holmes pass. One of the best super bowls ever.

30 January 2009

Return of the Clone

Any time you can mash-up references from Star Wars into a blog entry title that actually applies to the content, it is a Good Thing.

Over the Thanksgiving holiday I did a lot of infrastructure work on the computers that run in the house. Part of that work involved setting up a computer to be used by the kids that would also double as a file store for backups (1.5TB disk), upgrading the MythTv server to 0.21 and doubling its storage capacity to 500GB.

While I was at it, and since I had the space, I decided to set up a weekly rsync to clone ("mirror" is probably more appropriate) the myth video drives to the backup machine. I'm thankful for that now, as one of the myth drives died last night (250GB Western Digital). The drive was 3 years old and had spun more or less continually over that time. I figured its time had come.

I've ordered a replacement drive which should arrive early next week. Restoring things should be a simple (gosh, I hope!) as putting in the drive, formatting it, making sure fstab is happy, and then a reverse rsync. In the meantime, Myth is clipping along using what space is left on the remaining drive. It had to expire A LOT of stuff, but is doing fine now, except that it still tries to expire shows on the missing drive. (I wanted to make "phantom" reference here.)

I did go through the pains of removing the path of the broken drive from its storage group, as myth has a tendency to start recording shows in odd places if it can't find an intended storage group path. I had to drop down into sql to do this--I couldn't find a way using the UI that didn't involve deleting the entire storage group.

22 December 2008

Myth listings

One of the ancillary things that broke when I upgraded my MythTv systems last month was my listings page that gets pushed from MythWeb daily.

In 0.20.x, the listings page was a simple php app that output plain html. I had a few bash/sed/awk scripts that grabbed the prime-time listing, cleaned up the HTML to remove references to my system, fix relative links, etc; and then scp to my web host.

Those scripts stopped working in 0.21 because the listings page is now a fancy AJAX application that doesn't use simple HTTP GET operations. I had two options: figure out their AJAX API to get the scraping done, or write some dirty PHP to query the database for the daily listings.

I chose the latter, even though I am a nasty PHP hack. It is straightforward stuff. The result can be found at listing.php. Most of my time was spent figuring how to get dates into and out of my PHP queries.

When I am more inclined, I will go back and fix the table HTML for shows that do not start or begin on the hour or half-hour, and also exclude the radio and other channels I don't watch.

10 December 2008

In the Year 2000...

Dear Lazyweb,

I have a lot of ripped CDs and DVDs; I use MythTv and I have a mac.


And I want to access them all using Frontrow *and* Mythfrontend.


Thanks,
Gary

This is one of those problems where the pieces are all 99% there, but not enough people want the solution bad enough (myself included) to put them all together.

Firefly can take a collection of mp3s and serve them up to iTunes/Frontrow. It can even handle video to an extent (must be mov or m4v). That is 50% of the problem, leaving only a way to get at the Myth TV shows.

There are several ways this could probably be handled. To me, the path of least resistance would be this:
1. A vlc setup to transcode and stream the MPEG-2 Myth tv shows into something iTunes can swallow. This is already doable.
2. A plugin for Firefly that will a) query mythtv using either the database or UPnP and then b) stream the video from vlc. There will be a little bit of glue that is needed to map items exported by the database/UPnP to urls for vlc.

I have two weeks off at Christmas. Maybe it's time to get my hands dirty and give something back to the community I've enjoyed for so long.

06 December 2008

Upgrading Mythtv

Our children had been using a very old 200Mhz PII as their computer for the last 6 months or so. They aren't too demanding yet, but the biggest drawback for them was that the machine could not act as a front end to our MythTv system. That was my main motivation for setting up a MediaMVP as an SD front end for myth (still working well, btw!). So, to have another front end and a few other reasons, I decided that a new computer would was needed.

I put together a simple system on Newegg (Atom processor, 1.5TB drive, 2G RAM). I opted for a big hard drive because I planned to use the machine as a network file store for backups (this is the 'few other reasons' part).

I threw Xubuntu 8.10 on the new kids computer and tried to build a mythfrontend from source (0.20.2) but ran into too many problems with dependencies that weren't backward compatible. I briefly contemplated throwing on an older version of Mythbuntu (like 7.10) but ruled that out as well--it didn't seem right to do that to new hardware.

The decision was made: it was time for me to upgrade my Myth systems. The new machine for the kids and the myth server would both get shiny new copies of Mythbuntu 8.10 installed on them. I figured the timing was good since I had the week of Thanksgiving off from work. This meant that I would have time to focus on any problems that might crop up. In other words: I kind of expected the crap to fly.

Installing Mythbuntu 8.10 on the kids new hardware was a piece of cake. No problems there.

Things were different when it came to my existing backend though. My initial plan was to take the current machine, remove the hard drives, put in a spare blank hard drive temporarily, install Mythtv 0.21 using Mythbuntu 8.10 to make sure there were no problems. If that test proved it would work, I would back up the existing system, wipe the disks and recreate the system. If it didn't work, I would just put the old drives back end and figure out what to do next--nothing lost. (Given that I had such a hard time with lirc the last time around, I didn't want to take chances patching the existing system up to 0.21.)

I'm glad I did it that way. Mythbuntu wasn't going to have it on my hardware. Ubiquity managed to crash at the hardware detection phase of the install. Code-diving didn't help much either. I installed Mythbuntu so much over the span of two days, I wore out the cylinder hole of the CD I burned it on. Eventually, I realized that it just wasn't going to work. Xubuntu disc in hand, I went to work.

Xubuntu went on the old myth server smoothly. I decided to install myth from source, rather than use apt-get. It will make things easier if I need to patch later on, as I did previously when I needed to get the schedulesdirect updates.

My first happy discovery was that ivtv was baked into 8.10. One less thing to tinker with. I apt-got the tools, enabled ivtv in /etc/modules and was excited to see video getting dumped.

Next was lirc. Getting lirc to work the first time around was difficult for two reasons: the blaster tip on my Hauppauge blaster cable wasn't blasting, and it seems that lirc doesn't care much for the Hauppauge blaster hardware at a very fundamental level. Fortunately, my faulty blaster is a thing of past due to my handy soldering skills (I replaced the LED). Fortunately, for the second problem Mark at Mark's Braindump had patched the lirc source to make it happy with the Hauppauge. Thanks Mark!

Building myth was simple. Nothing outside of the readme. Configuring it turned into a bit of a chore though.

I verified it could record a program and that my macbook could show it. All was good there. Next, I had to figure out how to restore my old database and video files. For the video, I decided to save myself time and just use the old disks as-is, and remove all non-video files from them. That way, I wouldn't have to wait the several hours it would take to copy 200GB+ of video files from my backup.

I restored my myth database using the process outlined on the myth wiki. Then I set up the storage groups to point to the drives where I would be storing data. (+1 for the storage groups feature. I was forever limited in the past to 250GB of shows, but no more. I have two drives for 500GB of storage dedicated to myth videos and can add more drives when the time comes.)

I ran into a problem where a show would display the first time I tried to play it, but if I escaped out of the show and tried to access it again through the recordings menu, myth would complain that it could not find the file. Ouch.

The source of the problem should have occurred to me much earlier, but it didn't. I had changed the hostname for the server when I put 8.10 on it. The hostname is used in several critical database tables that I restored. Simple sql to update those tables with the right hostname solved that problem.

All is good again. The family is happily watching old shows, new shows and generally too much TV again.

There are still a few things I would like to do. I moved all my ripped movies from one of the 250GB drives now dedicated for myth shows and stuck them on the 1.5TB behemoth in the kids computer. I want to get that directory exported as a read-only nfs share that my various frontends can mount and use mythvideo to watch movies from. Also, it would be nice to find time to set up a vlc server on either the myth server or the kids computer to use for streaming movies to the MediaMVP. Then I need to re-backup my MP3s on the kids computer and turn mt-daapd on so that all my songs are available to any computer running iTunes. All that, and I'll be happy.

15 October 2008

MediaMVP + DD-WRT + MythTV

Two years ago this month I set up our MythTV system. At first, we kept in in our living room where the computer was. We watched tv on a 22-inch flatscreen monitor. Nothing fancy, but it served us just fine.

About a year ago, we did some renovations on our main level that turned our long living room into a smaller living room plus an office for Nicole. The computer had to go. We stuck it downstairs in the basement family room and stuck the monitor in Nicole's new office. No more myth, at least not connected directly to the server.

For the last year, we've been watching TV primarily on our computers--either a 15-inch MacBook Pro, or a 13-inch MacBook. Again, nothing fancy, and it would be fine for us, except that we don't trust our kids to fire up Mythfrontend on our laptops. We know what they're capable of.

Without a doubt--I had to make it so the kids could watch Mythtv on the TV in the basement, while minimizing the likelihood of them damaging any equipment.

My first attempt was to mod an first gen XBox and install Linux. I ended up ruining a mod chip and probably ruining the xbox too. I put it back together yet to see if it still works.

Last week I bought a Hauppauge MediaMVP for about $70. After a non-trivial amount a tweaking, I managed to make it talk to my Myth system (thanks to mvpmc). It handles SD TV just fine and has component and S-video out. Perfect for our needs. The kids are going to be quite happy.

Minor gripe: I need to figure out how to change the font used by the on screen display. Our TV is 27 inches and I have a hard time reading the OSD.

For the technically inclined, here is what had to happen to make it all work:

1. On the backend, enable tftpd:
sudo apt-get install xinetd tftpd tftp

2. Create /etc/xinit.d/tftp and then restart xinetd.

service tftp
{
protocol = udp
port = 69
socket_type = dgram
wait = yes
user = nobody
server = /usr/sbin/in.tftpd
server_args = /tftpboot
disable = no
}

3. Create /tftpboot and place dongle.bin.mvpmc and dongle.bin.mvpmc.config there.
dongle.bin.mvpmc.config is:
mvpmc -s 10.10.2.32 -u mythtv -p mythtv -y 10.10.2.32 \
-T mythconverg --startup mythtv &

(yes, you now know my mythtv host, user and password!)

4. Create a dhcp boot environment. I use DD-WRT. The solution is to services > services and add some DNSMasqu otpions:
dhcp-boot=dongle.bin.mvpmc,,10.10.2.32
The IP address is the IP of the tftp server.

That's it. When I get enough motivation, I'll write up a set of proper steps and add it to my MythTV instructions.