Track a Tech
What happens when you put a tech, a Mac and a cat together?-
iOS full screen vs. .NET 4.0
Posted on May 15th, 2013 No commentsOur database software runs on Microsoft’s .NET platform. The newest version of that software switched to .NET 4.0. While we have not yet updated to that version another church using the same software did last week. They also use the same children’s check-in software that we do. Everything went pretty smooth for them except for one problem that only cropped up after the upgrade on the production server – Check-in no longer worked. Minor issue when you have 800 kids going to be checked in over the weekend services.
The issues were basically weird things were happening. Via some debugging we found that it was being caused by the AJAX script not being included by IIS. Some googleing around on that revealed that was caused by IIS believing the browser did not support Javascript. Obviously the browser does support it so it was just a matter of why IIS was believing that. All the solutions online required us to modify the .aspx page, but everything we work with is .ascx user controls, we don’t have control over the .aspx page code, so we needed a better solution not just a bandaid.
Long story short, we worked through various tests and google results and came up with 2 causes for the problem.
Issue #1 – Microsoft thinks all UserAgent strings are short.
This may have been a change in .NET 4 or it may have always been this way, not sure. But in .NET 4 at-least IIS assumes all UserAgent strings will be shorter than 64 characters. We were very confused because the “windowed” Safari (i.e. tapping Safari and browsing) would usually work, but randomly would stop working. The full-screen Safari (going to a web-page and then adding it to the home-screen) would usually not work, but randomly would work. This was caused by the fact that IIS (also possibly new in .NET 4.0) caches the browser capabilities based on the UserAgent string given by the browser. Here is the catch. That is by default limited to 64 characters. So if two different browsers have 2 different UserAgent strings but the differences are AFTER the first 64 characters, they will be treated the same. Take a look at this website for a list of browser strings through the years, going all the way back to the days of AOL. UserAgent strings have always been longer than 64 characters, Microsoft really dropped the ball on this one.
The fix for this was to add <browserCaps userAgentCacheKeyLength=”256″ /> inside the <system.web> section of the web.config file for the website. This increases the cached key from 64 characters up to 256, which is long enough to store all browser strings. Really 128 would probably have been enough, but why risk it? After this fix was in place we got consistent results from windowed Safari and full-screen Safari. The former always worked, the latter never worked. So the caching of browser capabilities is what was causing things to be intermittent. We were then able to move on to fixing the real problem: full-screen Safari not being treated as a Javascript capable browser.
Issue #2 – Apple things full-screen Safari should not have a version number.
Say what? Yes. The UserAgent string for Safari when in full-screen mode (maybe embedded browsers too, not sure) does not include a Version number or Safari build number. Here are samples of the two strings:
Regular Safari: Mozilla/5.0 (iPad; CPU OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B329 Safari/8536.25
Full-screen Safari: Mozilla/5.0 (iPad; CPU OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B329You may also note that character 64, where the UserAgent was being truncated to for caching purposes, is inside the “536.26″ version number of the AppleWebKit, before the point at which it would realize they are different. Prior to .NET 4.0, Microsoft’s browser matching had a much simpler browser detection which detected the Full-screen Safari as a generic “smart” browser. The new detection code is much more specific and detects Full-screen Safari as, essentially, the first web-browser ever created. Meaning completely feature-less. Basically it doesn’t match anything so it gets thrown into the “default” browser match.
What we had to do was build a pattern match that would detect Full-screen Safari and treat it as a real browser. Because we don’t have specific version numbers to test against we treat then all as Safari version 3. In .NET 4.0 Safari 3, 5 and 6 are all treated as Safari 3 browsers. Safari 4 is treated as Safari 4 (but only bumps one capability version number from 1.6 to 1.7), so we played it safe and went with Safari 3 since that is what current versions of Safari are treated as anyway. Here is what we had to do. In the folder that contains your web.config you need to add a App_Browsers folder and then drop the browser file in there for it to be used by IIS. The file can be named anything as long as it ends with .browser though we named ours safari_mobile_fullscreen.browser.
Once we dropped the below code into that folder, the second problem was resolved which solved everything. They reported perfect success on the weekend children’s check-in system.
<browsers> <!-- Mozilla/5.0 (Macintosh; U; PPC Mac OS X; fr-ch) AppleWebKit/125.5.5 (KHTML, like Gecko) Safari/125.12 --> <!-- Prior to Safari 3, the Safari user-agent string did not include a version number --> <browser id="SafariMobileFS" parentID="Mozilla"> <identification> <userAgent match="AppleWebKit" /> <userAgent nonMatch="Chrome" /> <userAgent nonMatch="Safari" /> </identification> <capture> <userAgent match="AppleWebKit/(?'layoutVersion'\d+)" /> </capture> <capabilities> <capability name="layoutEngine" value="WebKit" /> <capability name="layoutEngineVersion" value="${layoutVersion}" /> <capability name="browser" value="Safari" /> <capability name="type" value="Safari" /> <capability name="version" value="3" /> <capability name="majorversion" value="3" /> <capability name="minorversion" value="0" /> <capability name="type" value="SafariFS" /> <capability name="ecmascriptversion" value="3.0" /> <capability name="javascript" value="true" /> <capability name="javascriptversion" value="1.6" /> <capability name="w3cdomversion" value="1.0" /> <capability name="tagwriter" value="System.Web.UI.HtmlTextWriter" /> <capability name="cookies" value="true" /> <capability name="frames" value="true" /> <capability name="javaapplets" value="true" /> <capability name="supportsAccesskeyAttribute" value="true" /> <capability name="supportsCallback" value="true" /> <capability name="supportsDivNoWrap" value="false" /> <capability name="supportsFileUpload" value="true" /> <capability name="supportsMaintainScrollPositionOnPostback" value="true" /> <capability name="supportsMultilineTextBoxDisplay" value="true" /> <capability name="supportsXmlHttp" value="true" /> <capability name="tables" value="true" /> </capabilities> </browser> </browsers> -
Anime Review: Love Live! School Idol Project, Sword Art Online, Girls und Panzer
Posted on April 12th, 2013 No commentsLove Live! School Idol Project
So, you would think with an anime about a bunch of school girls in skimpy dress dancing on a stage that they would be taking every opportunity to show off some inappropriate cloths or body parts. Surprisingly this show has completely clean. There was some “chest grabbing” by one of the girls as a method of getting people to talk, but it really is not in a provocative or erotic way. More of a ”talk or i’ll squeeze harder and cause pain” sort of thing.
Nothing really stands out about the show. It has a decent plot, at-least it starts decent. Three friends find out their school is going to close if it doesn’t get enough interest from prospective students since their enrollment has been declining. They don’t like that one bit so they (rather the main protagonist Honoka) decide they are going to do something about. (I don’t remember if they said it was a girls only school, but I don’t remember seeing any boys.) So of course, how do you get girls interested in going to a girls school? You put girls on stage in flashy costumes… Uhh, yeah, I guess, maybe… possibly.. that works.. It would kind of make more sense to me if it was a bunch of young boys in the audience jumping up and down; but what do I know I’m not a teenage schoolgirl from Japan. Like I said, the plot starts good but that is about as far as it goes, it doesn’t really develop into anything further.
Much like the plot, everything else about the show is decent, but doesn’t really go anywhere. This is one of those shows which I enjoyed watching, but will honestly probably never watch again. Entertaining once, but without a plot that develops it’s kind of hard to have re-watch appeal.
Summary: Good show. Nothing spectacular. Decent story of girls trying to save their school from closing.
Seasons: 1
Season length: 13 episodes
Episode length: 22 minutes
Content: Clean.
Language: Japanese with English subtitlesSword Art Online
This is one of those shows that kind of pisses me off at the end. Not because they bring somebody back to life at the end just to make a happy ending or anything like that. But because it is a great, clean show right up until the end and then they throw in some garbage just, well, because. I know it probably sounds odd to put it this way, but I get when a show puts garbage and nudity up front: because they want to get people hooked who will hope for more later. I don’t get when they do that at the end because it really doesn’t serve any purpose. Everything is clean for 23 episodes and then on episode 24 they put in some junk. Really? What just to make some shmuck happy and feel like he didn’t waste 6 hours of his life “for nothing”? Bah, whatever. </rant>That being said, I absolutely loved this show. It did a great job on story line, plot development, comedy, developing characters, pretty much everything. The story revolves around a virtual reality MMORPG (Massive Multiplayer Online Role Playing Game) where people hook up to a virtual reality system so that they can be fully immersed in the game universe. However, something goes wrong shortly after the launch of the latest game. The players are all trapped in the game and will not be allowed to disconnect from the system until somebody beats the game – but that could take months! In the mean time, if you die in the game, you die in the real world so it quickly becomes a dog-eat-dog world with players fighting to survive, literally.
Kirito is a skilled swordsman who has been playing these games for a long time. Does he have the skill to complete the game and beat the final boss? His friends think he might, but he is too afraid of making a mistake and getting people killed. Especially another player that has become very important to him. Can he manage to beat the game, and save this newbie girl that has become the center of his life? Will his skill be good enough to save everyone or will he have to sacrifice people along the way to ensure his own survival?
Back to episode 24. About half way through the episode one of the female characters is being held hostage. The antagonist rips her top off rendering her exposed for I would guess about 5 minutes of the show. Most, if not nearly all, of the time the camera angle is from the back or mostly obscured by hair from the side. At-least one time, however, it pretty much does a full frontal shot from a medium distance. While technically a few strands of hair block things, there is not much left to the imagination of the viewer. If the studio every re-edited this scene to remove that part of obscure things more I would have called this a perfect show.
At the time of writing, this was an extremely popular show on the streaming sites. There are multiple manga volumes, a video game, 2 light novel story arcs (over 13 volumes between the two) and of course the anime. It has been licensed for release in North America with an English dub. And this story did not even begin until mid 2009, with most everything starting late 2010. The primary light novel driving everything has 12 volumes so far. The first 2 is the Aincrad story arc and the next 2 are the Fairy Dance story arc, both of which are covered by this anime. There are another 4 or 5 story arcs covered by the light novels meaning there is an ability for another season of the anime, and indeed there are rumors of a continued show. I say continued show instead of a season number because there is debate on wether or not Fairy Dance was season 2 or part of season 1 (there was no break and indeed it is listed as episodes 14-25 I believe). Anyway the next story arc would likely be Gun Gale Online if you want to try and find definitive information on it.
Did I enjoy the show? Yes, despite the junk in episode 24. Will I watch more of the show if they make new seasons? Definitely.
Summary: Great show and story line. Would watch it again! Lots of action without taking over the story completely.
Seasons: 1
Season length: 25 episodes
Episode length: 22 minutes
Content: Clean with the exception of episode 24.
Language: Japanese with English subtitles (English dub, probably summer 2013)Girls und Panzer
This is another show I was really surprised at. Let’s face it, much like Love Live! this is a show about a girls-only high-school. I fully expected to shut it off after the first or second episode from an obscene amount of underwear and skin being flashed around. As I said, I was surprised. There was absolutely nothing improper in the show (as always, take this with a grain of salt – who knows if something happened while I looked away, but going through 12 episodes and never seeing anything is a good sign). The worse I ever saw is part of one of the episodes has most of the girls in their swim-suits washing the tanks to get them all cleaned up and ready for operation.Girls und Panzer, that is Girls and Tanks, centers around a group of girls trying to save their school. Sound familiar? Seriously though, this story has absolutely no connection to Love Live! and a completely different story line. In Love Live! the issue was the school didn’t have enough students so unless they can get more prospective students interested, the school gets shut down. With Girls und Panzer, the school is going to be shut down – period. Basically the girls get the powers that be to agree that if they can win a tankery competition the school can stay open. Winning means beating every single other school participating, and oh yeah, they haven’t had a tankery program at their school in years.
What is tankery? Well, some schools have tennis, some have soccer, some have baseball and some? Well some have tankery! Tankery is the “sport” of tank warfare and learning to be proper girls through that sport. Uhh, okay. So aside from that, the idea is pretty cool. You get two schools together with a bunch of tanks on each side manned by school kids. They go around a practice field (which includes the town, too bad if your shop gets blown up!) trying to disable the flag-tank of the other team. And yes, they use live rounds! Seriously though, there is no way tankery could actually exist without 80% of the participants dying each round. Even still, it’s kind of like paintball wars but with tanks. I’m thinking that would be a cool game to play!
That is basically the story. Can the girls manage to get all the way to the top and win? Beyond that, they build the characters up pretty well. The primary plot doesn’t develop much, but there are a few side plots that develop pretty nicely. In addition to that, they do some pretty cool “special effects” (if you can call it that in animation) in regards to the tanks, points of view, and creative ways of fighting tank vs. tank. I thoroughly enjoyed the show even though it felt pretty short (12 episodes). I think there are actually 15, but 3 of them are “.5″ episodes where they just rehash the past few episodes and introduce some of the new characters in more detail.
Summary: Fun, clean show. Good entertainment with a creative idea driving it all (tankery).
Seasons: 1
Season length: 12 episodes
Episode length: 22 minutes
Content: Very clean.
Language: Japanese with English subtitles -
Manage your Macs with a Munki!
Posted on March 26th, 2013 No commentsIf you are not familiar with Munki you need to go take a look right now. It is possibly one of the easiest software management tools I have ever seen. It works on the same principal as Apple’s own Software Update system. You build a catalog of packages that you want installed on computers and it makes sure that software is installed and kept up to date. What munki provides beyond that is the ability to have each computer have it’s on manifest of software. A manifest tells it what software to install and what catalogs to pull from (i.e. production, testing, development, etc.).
Recently I spent some time getting our setup ironed out and better designed, and here is what I came up with. I’m not going to go through a step-by-step process for everything I did as this is a more open-ended install setup. Managing computers like this requires a bit more knowledge of the product itself. So you really should take a look at some of the munki documentation, particularly the getting started guide, as that will give you some understanding of the terms I will be using.
Setting up the munki repository
First off, I built a VM to run all this in. It is a simple Fedora 18 install with no GUI. You can use any *nix flavor you want, but I am most familiar with Fedora. The server is named munki and has a few DNS aliases pointing to it as well, which I will get to in a moment. First off I installed netatalk to provide a few AFP shares, but for this use I primarily use it for a single share: the munki repository. I need to be able to manage the repository from my desktop Mac as that is where the command line tools are installed. Sadly there are no tools for managing the munki repository on *nix, only Mac. Since *nix does not have (good) support for things like Apple’s .pkg format, or .dmg even, it would be more trouble than it is probably worth to try and go for a pure *nix setup.
Anyway, I created a /var/www/munki/html folder that will store the repository and shared it with netatalk to just our “staff admin” users. This folder is also shared by apache under the hostname munki.mydomain.com. Next mount the share on the Mac and initialize the repository (or in my case, copy my existing repository to this location). For this I use MunkiAdmin, which provides a nice GUI for working with the munki repository. Now with your repository created you can start building up your packages, catalogs, manifests, etc. I can’t help you with that specifically, but later on I will give you an idea of how we structure our manifests.
One thing to note with this is that I put the /var/www/munki/html folder as it’s own hard disk volume in the VM. Currently my repository is 5.7GB, so to give myself some growing room I created the hard disk as an LVM of 15GB. Doing an LVM means I can increase the size of the hard disk without rebuilding everything.
Setting up your web interface
The same guy who wrote munki also wrote munkiwebadmin, which is a web interface to munki. Primarily it is for monitoring and seeing status information, but you can do some basic manifest editing. That is handy for moving something from one manifest to the other, but since you can’t upload new packages you will probably do most of your true admin stuff in MunkiAdmin. However, I found munkiwebadmin (yes I know, sorry for the confusing names here) to be most powerful in its reporting abilities. I followed the install instructions here with a few minor changes. I created my virtual environment in /var/www/munki, so the final path became /var/www/munki/munkiwebadmin_env. You will also be pointing your repository to /var/www/munki/html so it can find everything. In Apache I setup a new virtual host of munkiadmin.mydomain.com that will handle the WSGI stuff and access to the website and obviously also setup a DNS alias to point to the server.
For the install I used MySQL instead of the default SQLite. The reason for this is that I also installed phpMyAdmin so that I can get CSV exports of the inventory data from munkiwebadmin. We only keep computers for 5 years and then they get sold off, usually to staff at the going eBay price minus a little. Using this list lets me sort the computers by how old they are and then take the bottom 1/5 of the list as the computers to be replaced this year. I can do the same in an SQLite database, just not as easily since that requires logging in and running some command line commands and then copying files across the network.
I also had to make 2 small changes to the source code with you can find here and here. Hopefully by the time anybody works on this these two issues will be fixed. Basically those two changes make it so the manifest list does not include the files created by netatalk and also addresses an issue when using MySQL as your database.
Finally, I built a package that contains the 3 scripts from munkiwebadmin. For building custom packages I use an app called Packages, it is simple and quick. The reason I build a separate package (which I called munkiscripts version 1.0) is that it lets me easily go back and update just the scripts. For example if I decide that I want to have munki do some other pre/post-flight operations I can push out a new munkiscripts package with those updated scripts. In fact I have considered doing this to have the postflight script scan the console log for disk I/O error messages and notify me and potential hard drive failures. Anyway, all I have to do is bump the version number and import it into munki and munki will install the new scripts on the next run. So yes, you will want to add this package to your repository.
Setting up your own SUS server
The last thing I wanted to do was have this server manage all software updates. Currently I have a Mac server doing this, and wasting a ton of disk space at the same time. There is an “application” called reposado that is basically a few linux scripts that handle downloading software updates from Apple and mirroring them locally on your server. I basically followed the getting started instructions. I created a new set of folders for reposado in /var/www/reposado/html and /var/www/reposado/metadata and pointed the configure command at those 2 folders.
I also created a 3rd hard drive in the VM and mounted it in /var/www/reposado. While the munki repository you could have as part of your room VM disk, I recommend the SUS volume be a separate disk for one very specific reason. It’s big and can be downloaded again. At the time of writing this my entire SUS repository is 100G and will only get bigger as time moves on. The disk that backs this volume is set to not be backed up in VMware. If I lose it, I just run the sync command again.
So anyway back to reposado, basically follow the instructions and create an apache share for /var/www/reposado/html. In my case I created yet another virtual host of reposado.mydomain.com to handle these requests and setup the DNS alias. I tend to do things this way as it makes it easier to migrate things from one server to another. For example if I later decide to move reposado off the munki server I just have to update the DNS entry, not every client. Once reposado is setup, run the sync tool and go get a coffee, or lunch, or if you have a slow internet connection maybe a weekend. Like I said, 100GB.
Configuring Clients
We have all this great stuff happening on our server, but nothing is talking to our server just yet. Three things need to happen to get all your clients integrated happily.
First we need to get munki installed on each client workstation. The software needs to be installed (which is pretty straight forward) and it then needs to be configured to point to your repository. You can do the latter any way you want. You can run a terminal command to set the properties, managed preferences, whatever. I use managed preferences so that I can easily change settings per-client. Munki install docs talk about various ways to do this. Your repository URL will be something like http://munki.mydomain.com.
Second we need to run munki so that it downloads all initial software, including the scripts. This will either happen after about an hour or you can use a terminal command to have it check now. I recommend doing a “check now” on a few clients just to be sure everything is working the way you expect, that way you are not waiting for hours to find out something was configured wrong.
Finally you need to update the software update catalog URL used by Apple. Reposado has some examples of URLs you will be using, yours will be something along the line of http://reposado.mydomain.com/content/catalogs/others/index-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog for Mountain Lion (others will be similar). I use a modified script that runs as a login-hook I found here. Scroll down a few comments to one by the user feyd, that is the one you want (at-least as a starting point).
Reboot just to make sure everything is picked up. Wait a little bit and you should start seeing data populate in munkiwebadmin. Also you can verify that your clients are pulling from your SUS because the Software Update app (or App Store) will tell you where it got the update from, so it should have your reposado URL listed.
Example manifest structure
So the way munki handles everything is by manifest. You can either set a specific manifest or let munki use a default one (computer name, serial number, “site-default”, etc.). But each manifest references packages to be installed/updated/remove as well as catalogs to pull those packages from. It can take some work to get things sorted out in an order that works well. I can’t say what I have is best but it works for me.
First, the reason I ended up with this layout. We have basically 4 different computer groups. Realistically 95% of our workstations are in 2 of those groups. We have a standard install group that every computer gets (this would include computers that are head-less, or otherwise non-user centric). Then we have a staff group that is basically office computers which have people sitting at them. On top of that we have 2 speciality groups: Communications/Graphics/Video Department and Teaching Pastors. Each of those last 2 exist for one very specific reason. The first gets the latest version of the Adobe suite while the others get an older version (saves us some money doing it this way). The latter group get a different set of installed modules for some Bible software we use, so the staff gets the packaged version and those 4 computers (currently) get a manually installed version.
Now, a quick bit of understanding for how manifests work. A manifest references catalogs to determine which version of the package to install. So you might have a production catalog and a testing catalog. You put the upgrade in the testing, roll it out to your “early adopters” group and then when you are satisfied there are no problems move it to your production catalog. A manifest can also include other manifests, however, if an included manifest references any catalogs those catalogs will be search first. So for example, my early adopters manifest is called infotech and everybody else uses staff. The infotech manifest includes staff. infotech also references the testing catalog. If the staff manifest references the production catalog then the production catalog will always be checked first, even if the software is mentioned directly in the infotech catalog.
What I have adopted to resolve this is a “split manifest” system. So these are the manifests I currently have:
- standard_software – Lists all the software, but no catalogs.
- standard – Includes standard_software and references the production catalog.
- office_software – Lists all the software for office computers, but no catalogs.
- staff – Includes the office_software and standard_software manifests, references production catalog.
- infotech – Includes office_software and standard_software manifests, references testing and production catalogs.
- graphics – Includes office_software and standard_software manifests, references graphics and production catalogs. (graphics catalog has the newer version of the Adobe suite)
- teaching – Includes office_software and standard_software manifests, references teaching and production catalogs. (teaching catalog has the different version of the Bible software)
Using managed preferences, it is fairly easy and straightforward to assign computers to various manifests and change them back and forth, though bear in mind munki may get confused by changing people’s manifests dramatically. i.e. if I install a computer as a teaching computer and then switch it to a staff computer, it will stick with the advanced version of the Bible software unless I manually remove it and then munki will re-install the correct version.
So basically ,when I say “split manifest” above what I mean is one manifest to hold the package names and another manifest that the computers point to. So all the *_software manifests are what contain the software, but the computers point to standard, staff, infotech, and graphics. That allows me to easily create a graphics_testing manifest that one computer points to which includes the same child manifests but references the testing catalog first so it gets the updated version.
Apple Software Updates
One other thing munki can do is install Apple Software Updates as well. This is useful if your users do not have admin accounts on the computer, and thus are unable to install the updates themselves. I have not yet rolled this out. It seems like it is not 100% stable from watching the discussion mailing lists. I do not mean stuff is broken and computers break, just that the update process is based upon a “apple does their own thing, we think we have figured it out” principal. So occasionally Apple releases an update that behaves strangely because it doesn’t fit into the mold of “we have figured it out” just yet and the mold has to be slightly modified. I think the worse I have seen is updates that keep showing up over and over again.
There is lots of documentation for how to turn this on (and off) so it may be worth your attention. I will be looking at it again once I have more time, but for us it is not a critical issue since most of our users have admin access on their computers so they install their own updates. As we move forward and (possibly) take that away this will be a bigger issue so we will look into it more.
-
Caching results in SQL Server
Posted on March 6th, 2013 No commentsI have a few SQL scripts that provide data to be displayed on our home page. These queries calculate data over the past 4 months and display as a chart for the users to get a quick overview of the information. The problem is these queries take over 10 seconds to run. Obviously this would be a problem. The usual way to deal with this is create a table that has the data you want displayed (the cache) and you update the table in a background process, such as a SQL agent job. When searching for a way to do this online this was the solution everybody recommended and ended up using. My problem is I didn’t want to create a whole bunch of tables to hold the cached data for each one. I needed a way to basically have a “cache” table that holds the results for various queries, each with different types of data (different column types/values, etc.).
What I ended up using was a combination of the FOR XML and OPENXML commands and a single “blob” table to store the data with a timestamp for when it was last updated. Since it will probably be easier to just see an example I will give a short example of how to go about doing this.
DECLARE @Results TABLE (Ordering INT, Campus VARCHAR(30), RealDate DATETIME, HeadCount INT) DECLARE @guid UNIQUEIDENTIFIER SET @guid = '00000000-0000-0000-0000-000000000000' -- Check for cached data, only use it if it is less than 2 hours old. IF EXISTS (SELECT * FROM util_cache WHERE [guid] = @guid AND date_modified >= DATEADD(HOUR, -2, GETDATE())) BEGIN DECLARE @doc AS INT DECLARE @xdoc AS nvarchar(max) SELECT @xdoc = blob FROM util_cache WHERE [guid] = @guid EXEC sp_xml_preparedocument @doc OUTPUT, @xdoc SELECT * FROM OPENXML(@doc, N'/root/Result') WITH (Ordering INT, Campus VARCHAR(30), RealDate DATETIME, HeadCount INT) EXEC sp_xml_removedocument @doc RETURN END -- No cache found, populate @Results with the data that takes awhile to build... INSERT INTO @Results ... -- Save in cache BEGIN TRY BEGIN TRANSACTION IF NOT EXISTS (SELECT * FROM util_cache WHERE [guid] = @guid) BEGIN INSERT INTO util_cache ([guid], date_modified, blob) VALUES (@guid, GETDATE(), (SELECT * FROM @Results FOR XML RAW ('Result'), ROOT)) END ELSE BEGIN UPDATE util_cache SET date_modified = GETDATE() ,blob = (SELECT * FROM @Results FOR XML RAW ('Result'), ROOT) WHERE [guid] = @guid END COMMIT TRANSACTION END TRY BEGIN CATCH END CATCH -- Select data for display SELECT * FROM @ResultsSo what we are doing is declaring in in-memory table and GUID to use. The in-memory table is what is used to build the actual data if the cache is not valid. The GUID is used to uniquely identify this cache object.
First we check the util_cache table to see if a valid entry for our guid exists. If it does, we take the nvarchar(max) value and throw it into the XML code to convert it back to a SQL result set. The sp_xml_preparedocument stored procedure basically opens the XML stream and parses it into something that OPENXML can use. The sp_xml_removedocument stored procedure closes the XML stream and frees up memory. In the middle is the OPENXML function which takes the XML document and an XML query for which data to return, in our case we want all the Result records under the root element. The WITH clause tells it how to format the data, in this case we just match the table format that we used to store it.
So if the cache data was not found or was expired, we need to build new results. The reason I do everything inside a TRY/CATCH block is so that if something goes wrong with query instead of getting an error page the user just gets and empty result set (i.e. a blank graph). Then the reason I do it in a transaction is to lock the util_cache table (if I understand how things work) so we don’t have 2 threads trying to INSERT at the same time. Converting data into XML is as simple as adding the FOR XML RAW (‘RecordName‘), ROOT clause to the end of the SELECT statement. RecordName is the name of the node to generate for each record, this needs to match what you use in the OPENXML statement.
In reality the setup I have is pretty similar to the above except that everything is inside a stored procedure that accepts a parameter for how old the cached data can be before it is considered stale. In my code that runs on the homepage I use 36 hours (the data doesn’t change that often, so this is fine). Then I have a SQL agent job run every 24 hours that calls the same stored procedure with and passes it a value of 0 which forces the data to be re-build immediately. So the user should never notice a delay, but if the sql job fails to run a single user might notice a 10 second delay once a day.
-
Anime Review: Kokoro Connect, Sands of Destruction, The Cat Returns
Posted on February 18th, 2013 No commentsKokoro Connect
Five students who don’t know each other and don’t really care what they do when they enter High School end up joining the same, non-existant, school club called the Culture Society – which consists of them just sitting around talking and having fun. When we join the story they have all since become friends through the club. Things begin to go wrong for them when an unknown entity decides it is board and starts to play games with their lives, beginning by making them randomly swap bodies. The club members fight their way through this bizarre phenomenon as they learn to deal with their individual pasts and problems. Finally things seem to be going better for them after the entity tells them they will no longer be swapping bodies – but things are only just getting started.The show is technically clean. I have found that it is easy for me to dismiss certain things by telling myself you see the same thing at the beach, or on TV commercials, or even now-days at the supermarket check-out stand. This show has, that I can recall, two incidents in which nothing is technically shown but falls into that category of “nothing bad really happens but still shouldn’t be approved of”. One incident involves one of the ladies partially undressing and crawling over a table. The other incident (I don’t want to ruin the story so just go with me on the assumption that nothing naughty is going on during this scene) is with a different girl “coming to” without wearing anything up top, the shot of her as she stands up has her covering herself with her arms and is very brief.
Kokoro Connect introduces some interesting concepts into what is essentially a high-school comedy/romance story. What makes a person a person? To paraphrase one of the characters in the story: A person, the essence of who they are, is defined as a combination of their unseen self. Their soul, personality, past events in their life. Yet we identify individuals by physical attributes. When we think of a person we think of their physical appearance, not their intangible attributes that make them who they are. So if those unseen characteristics are removed from one body and placed in another body, who is that person? Are they still the same person or are they somebody else?
A different concept proposed by the kids in this story is specifically to do with one’s past. When something important happens, wether good or bad, to us as people it is fresh in our memory and hearts. We remember vivid details about what physically happened and we feel very strongly about the emotions caused by that event. As we grow older and “move away” from the event, those memories and feelings dull and fade, but they still color our future choices and actions. Someone may fall in love with another person because that person reminds them, on some unconscious level, of a childhood sweetheart they once had. What if this person is returned to his youth for a brief period of time, a time when his feelings for this sweetheart were at their strongest. When he then returns to his current age all those feelings would be once again fresh in his mind, and in his heart. Does he really love this new person in his life, or is it just because she reminds him of someone else? What if the latter is true, what then…?
I enjoyed this show because it brought in some of these interesting discussions as part of the story. It didn’t present them as a “sit down and listen to us talk philosophy” but rather worked them into the story of their lives as they try to cope with these strange events. While the show itself covers things like love, fear of others and things of that nature, the same conversations can be applied to our faith. To my own faith. When I accepted Christ all those feelings and emotions were strong and front-most in my mind. Over the years they have dulled and paled as I have grown older. How would my life change, how would I change my life, rather, if for 3 hours I was returned to that point in time where I had just accepted Christ and then came back to my current self with all those memories and feelings fresh?
Summary: Enjoyed the show, wish it had been longer to explore in more detail some of these (somewhat) philosophical ideas.
Seasons: 1
Season length: 13 episodes (I just checked and 4 more episodes were released 3 months after the series “ended”, but I have not yet watched #14-17)
Episode length: 22 minutes
Content: Mostly clean, see full description for the discussion of the “unclean” parts.
Language: Japanese with English subtitlesSands of Destruction
In a world where men serve beasts. In a world where beasts rule as men. In a world devoid of hope. This is the world Kyrie lives in. This is the world Kyrie survives in. He is a human who poses as a beast in order to survive and live peacefully, and that is all he wants is to live peacefully. Morte, also a human, is bent on destroying the world. Not just ridding the world of beasts, but ridding the world of everything. Complete and utter destruction. She believes that the world is such a terrible place that it does not deserve to exist anymore. Morte, the sole member of the World Destruction Committee, accidentally exposes Kyrie’s beastman disguise while trying to escape from the World Salvation Committee. Kyrie has no choice but to flee with Morte rather than be killed by the beastmen, as such he is labelled as a member of the World Destruction Committee and unable to return to his peaceful life.
Shortly after, they meet Taupy, a dwarf bear (teddy bear) who happens to be a bounty hunter, who ends up joining with them because of a misunderstanding as well. Neither Kyrie nor Taupy want to activate the Destruct Code, which has the power to destroy everything, but they join with Morte in an attempt to keep themselves alive as well as to try and reason with Morte and dissuade her from destroying the world.
Through their adventures they make some friends and make some enemies. They all are exposed to people who give them reason to want to activate the Destruct Code as well as some people who give them reason to want to save the world instead. Will Taupy and Kyrie be able to change Morte’s mind, or will they finally come to agree with her and together destroy the world?
As recommended by reader Devin, Sands of Destruction is a pretty good show. It is completely clean with the most risqué part of the show an episode where Morte’s dress rips slightly (showing absolutely nothing) and both Kyrie and Taupy spend the episode trying to repair it and keep it from ripping more, as Morte is un-aware her dress is ripped. There are a handful of “soft” curse words. The show itself is a little on the slow side, but not so much as to be boring. It is really a matter of taste. It is an action-adventure story, however. If you are expecting the kind of action that Fairy Tail brings every episode you will be disappointed. If you are expecting a good wholesome show with action sequences instead of all “story”, you should enjoy this show quite a bit.
Summary: Good clean show that offers 13 entertaining episodes with a story following 3 people who are trying(?) to destroy the world.
Seasons: 1
Season length: 13 episodes
Episode length: 22 minutes
Content: Completely clean, I always hesitate to recommend anything for kids without parents watching first, but I think it is clean enough to do so.
Language: EnglishThe Cat Returns
Haru is a young girl that is bored with life. And like all school girls, at-least all school girls in movies, she has a crush on the most popular boy in her class. While walking home from school she sees a cat that is about to be hit by a truck and manages to save him. To Haru’s surprise he stands up and thanks her for rescuing her, and promises to repay her shortly after he has completed an important errand which he is currently on. Her life is about to get much more interesting.Haru shortly learns that the cat she saved is the prince of the Cat Kingdom, and his father insists on thanking her by having her join his kingdom: by marrying the prince. Haru must escape the kingdom and return home before sunrise or she will be forced to remain a cat forever, but does she really want to go back home? Her only hope of escape is a cat figurine come to life called The Baron as well as his overweight friend Muta.
While obviously a kids’ story, this actually had a lot of fun moments that I think adults would enjoy as well. The story is well done and provides kids with “that’s funny” scenes while at the same time hinting at some more inside jokes that adults will appreciate as well. I really enjoyed the movie. For the most part I have been happy with the Studio Ghibli films and TV shows, there have been a few that I turned off but that seems to be the exception rather than the rule with them. I have more on order in my Netflix queue from them. For those that are familiar with the Miyazaki film Whisper of the Heart, you will find that The Baron is a familiar character. In fact Whisper of the Heart was so successful that fans wanted another movie that centered around the cat character, with this being the result.
Summary: Clean movie for kids with enough entertainment for adults as well.
Movie length: 75 minutes
Content: Completely clean, another kid movie that is very appropriate to watch with the kids.
Language: English -
Migrate Snow Leopard Server to Lion or Mountain Lion
Posted on December 28th, 2012 No commentsI have a Snow Leopard server running, obviously, 10.6.8. It does too many things. It serves AFP, OD, iCal, AddressBook, Wiki, RADIUS, Software Updates, and a few other things. That is just too much stuff on one server that goes down every time I do a little maintenance. What I wanted to do is setup a new Mac Mini server on Mountain Lion and migrate the collaboration services (iCal, AddressBook and Wiki) from the old server to the new one. Easier said than done. It seems all the public documentation is for how to migrate the entire server, not piecemeal.
I did some digging and found some useful scripts in the Server.app. Fire up Terminal and take a look in the /Applications/Server.app/Contents/ServerRoot/System/Library/ServerSetup/MigrationExtras folder. There are various Python, Perl and Ruby scripts to migrate various service information. A few of the ones you might be interested in:
- FTP
- VPN
- Web Config
- Wiki
- Calendar (also does Address Book/Contacts)
- RADIUS
I will give an example of what I did. I found simple instructions on Apple’s website for how to migrate the Wiki information from 10.6 to 10.7/10.8. I also needed to migrate the Calendar/Contacts information. I did this as a dry run to test and make sure these steps would work so I can test the new server and then I will setup the server clean again and do the final process and go live.
First I mounted the time machine volume for the old Snow Leopard server. From the command line I ran the following:
- cd /Applications/Server.app/Contents/ServerRoot/System/Library/ServerSetup/MigrationExtras
- sudo ./70_calendarmigrator.py –sourceRoot /Volumes/Time\ Machine\ Backups/Backups.backupdb/augustine/Latest/Augustine\ HD/ –sourceVersion “10.6.8″
- sudo chmod -R -a# 0 /Library/Server/Calendar\ and\ Contacts/Data
This ran for about 5 minutes before it finished. You should probably make sure your Calendar and Contacts services are not running, I realized Calendar was running half way through and turned it off. Luckily everything still seemed to work. When the process finished it starts up the Calendar and Contacts services. There were a few things more I had to do to get everything working properly. So I will give an overview of the whole process.
- Use the 70_calendarmigrator.py script to migrate the settings and data.
- Use the Server app to select the appropriate Certificate for the Calendar service (it was set to none which caused proxy errors).
- Use the Server app to give users (or groups) permissions to use the Calendar and Contacts services (by default nobody has access even though they already have calendars).
- Restart the entire server. Technically you can just restart all the various services, but after a migration like this I would just restart the server to make sure all is well.
- Update DNS to point to the new server. (For testing I edited the /etc/hosts file of a client to simulate the DNS update and everything just worked)
Finally, a few caveats I ran into trying to get things to work:
- I ran into an issue with an “CalDAVAccountRefreshQueueableOperation error 500″ in iCal client and “Data Corruption Detected” in the caldav error.log. Once I checked the error.log I found that there was a Geo-location based reminder on my calendar (actually 4) that was causing issues for some reason. I’m not sure why. I had to use the psql command line tool to log into the PostgreSQL database and delete the offending entries from calendar_object table.
- My user works fine in iCal but has an issue in the WebCal interface. I have 2 calendars, but the WebCal interface shows duplicates on the sidebar, though it does not duplicate the actual calendar data. Furthermore, when I try to edit the calendar it says I don’t have permission. This may be related to the issue I ran into above or it may not. Because this was a test server I believe I had already logged into the WebCal client before I imported the data so I may have really fouled things up on my own username. I checked a few other users and none of them have any problems. I was able to delete one of the “ghost” calendars, and I can create events on the real calendar of that pair, but the other 2 calendars (one real, one ghost) neither one shows that I can delete and I’m a little. I tried a full server restart but that did not fix. Again, I think this is just because I used a previously used system before instead of a clean system.
Overall the process was super easy and only took me about 2 hours to figure out and, transfer the data, fix a few issues and be back up on running on the sandbox server. The key to the whole process was finding those migration scripts so I could migrate individual service data.
Update 1/2/2013
Here are some tips for getting things fixed if you run into similar Calendar issues. Just for the record, only my personal user account had issues with the Geo-location TODO items. Other users have Geo-location TODO items and they seem to work fine; what the difference is I don’t know. Anyway some tips on how to get into PostgreSQL to fix this. First, to actually login to PostgreSQL run this command:
psql -h /Library/Server/PostgreSQL\ For\ Server\ Services/Socket -U _postgres -d caldav
To find the offending records (in my case, they all had the street name of “Jenkins” so I was able to search on that):
select resource_id from calendar_object where icalendar_text like ‘%Jenkins%’;
You should see it spit back a handful of records. If you see a large number of rows returned, you may want to try and fine-tune your query a bit. Once you have the query down, change the “select resource_id” to “delete” like this to delete those same rows:
delete from calendar_object where icalendar_text like ‘%Jenkins%’;
Once this is done I recommend restarting the Calendar service just to be safe.
-
Building a stateless Linux kiosk browser
Posted on December 17th, 2012 No commentsLinux is a great system for some tasks. One of these tasks is a simple kiosk browser. That is, a computer that does nothing but pull up a web page and display the contents and, in my case, attach to a touch-screen to allow the user to interact with the web page. The downside is that these things are hard to keep in a working state. The power goes out and the system shuts off unexpectedly and damages the filesystem which must now be repaired. Somebody somehow manages to change a setting and you have no idea what they changed. There are other issues that come up but they are all related to the fact that whatever you change in the OS is saved through to the next boot.
That is where stateless comes into play. With a stateless system in place the hard drive is never mounted in a read-write mode, it always stays read-only which means that the power can shut off, you can change whatever you want, it doesn’t matter. The system will always come back up the same way. It took some work to find all the information on setting up a Fedora box to be stateless, with the information scattered over various parts of the Internet. So here will be some documentation on installing Linux on a 4GB flash drive, get it up and running to browse web pages and then turn it into a stateless machine.
For reference, I am installing Fedora 16 32-bit on a DN2800MT ($109) motherboard in a Morex T-1620 ($50) fanless case. This gives me a computer that is slightly smaller footprint than the aluminum Mac Mini (by about 1/2 inch) and about 1/4 inch taller than the same Mac Mini. It has a 2GB memory chip ($10) and a 4GB Thumbdrive I had laying around ($5, be sure you get a quality thumb drive. If you end up with a USB1.1 or even a USB2 that is slow, you will be sorry). That is it for the computer. Right now it is hooked up to a Monoprice touch-screen monitor because it was available for testing, for our final product we are looking at other monitor options (such as a Lilliput USB-powered touch-monitor). For reference, this machine as it is running now takes up 12watts. It peaks at 13w. With the 10″ USB-powered touch monitor (4.8watts) this puts me at about 17 watts which is too much for our standard PoE switches, but withing the 24watts available on PoE+ switches… hint hint hint. By the way, Fedora 16 is what I had available at the time, I could have used 17 but happened to have 16 already downloaded. The m/b is actually 64-bit but I think there must be a firmware glitch or something because they do not officially support ANY 64-bit OS. Linux works fine in 64-bit up until it tries to switch the video mode and then the video shuts off (the system still works, but that doesn’t help me as a display kiosk).
Install and configure the system
- Begin installing Fedora and set your root password.
- On the “disk setup” screen select Use All Space, turn off Use LVM and turn on Review and Modify Partitioning Layout. (this will erase existing partitions, so make sure you only have your blank thumb drive plugged in)
- It created 4 partitions for me, but I didn’t care for the sizes it came up with so we are going to customize it (note by default it puts swap first but I move it to be last):
- sda1 – 1MB – (blank) – BIOS Boot
- sda2 – 500MB – /boot – ext4
- sda3 – 2500MB – / – ext4
- sda4 – 800MB – (blank) – swap
- Free – 33MB (I intentionally left a little free in case other thumb drives are slightly smaller than this one)
- Confirm the boot loader location as /dev/sda.
- Set the installation type to Minimal and turn on the Fedora 16 – i386 – Updates repository (this will make sure your system is fully up to date after it is installed), and set to Customize Now.
- On the customize screen turn on Xfce under the Desktop Environmentsgroup. Then go into the Optional packages and make sure the following (and only the following) are selected:
- NetworkManager-gnome
- Terminal
- gdm
- gtk-xfce-engine
- leafpad
- polkit-gnome
- xfce4-icon-theme
- xfce4-mixer
- xfce4-power-manager
- xfce4-session-engines
- xfwm4-theme-nodoka
- Next go into the Base System group and turn on the X Window System item and select (only) the following optional packages:
- desktop-backgrounds-basic
- firstboot
- gdm
- plymouth-system-theme
- xorg-x11-utils
- Continue with the installation and then reboot. You will probably get a warning about a missing dependency for mtdev, just ignore it. We will fix it after the reboot.
- You should be greeted by a “Welcome” GUI screen. Move forward through the process (Agree to license, set date/time (you will not yet be able to use NTP) and create a user. I used the following information for the new user:
- Full Name – User
- Username – user
- Password – password (we are going to setup auto login anyway…)
- Switch to a text terminal (CTRL-ALT-F3) and login as root so we can do some more setup. Run the following commands once you are logged in.
- systemctl disable sendmail.service
- yum install firefox nano ntp xorg-x11-apps xinput_calibrator
- systemctl enable ntpd.service
- The following commands setup DHCP to also retrieve a variable called “site-url”, which we will use to auto-populate the Firefox homepage.
- cd /etc/dhcp
- nano dhclient-em0.conf (“em0″ (zero) is the name of the network interface, check with ifconfig to see if yours is different).
- There should already be a line beginning with “send vendor-…” at the top. Add the following information below this line:
- option site-url code 224 = text;
- request subnet-mask, broadcast-address, routers, domain-name, domain-name-servers, host-name, site-url;
- Use CTRL-X to save and quit.
- Switch back to the GUI terminal (CTRL-ALT-F2) and login as “user”.
- You should get a dialog that asks what kind of panel you want, select Use default config.
- Go to the Applications Menu -> Settings -> Settings Manager
- Select Appearance.
- Select the Icons tab.
- Click HighContrast and then click GNOME. This will toggle the icon settings so all the icons start working.
- Click the Overview button to go back.
- Select Power Manager
- Under General, set the power button action to Shutdown.
- Under On AC, select the Monitor tab and set the display sleep and switch off display to Never.
- Click Overview button to go back.
- Switch back to the Text terminal (CTRL-ALT-F3).
- cd /etc/gdm
- nano custom.conf
- Find the [daemon] section and add these two lines in that section:
- AutomaticLoginEnable = true
- AutomaticLogin = user (this is the username we created above, which I told you to make ‘user’).
- CTRL-X to save and quit.
- logout
- Switch back to the GUI terminal one more time (CTRL-ALT-F2).
- Press the power button to ensure that the computer shuts down properly. It should do so immediately without asking you anything.
- Wait for the computer to power down and then turn it back on and ensure that it auto-logs in to the GUI.
- Run Firefox once to initialize the preferences folder.
- Set the default homepage to whatever you want (this is basically the fallback homepage if the proper per-computer homepage cannot be found).
- Open the Tools menu and select Add-ons.
- Search for R-Kiosk and install it from the list, as of writing it is version 0.9.0 date 9/22/2011.
- Close Firefox and re-launch, ensure that you are now running in fullscreen mode.
- Use Alt-F4 to close Firefox.
- To start Firefox in safe-mode so you can get the menu’s back, use Alt-F2 to open the Run Program dialog and enter:
- firefox –safe-mode
- Switch to the Text terminal (CTRL-ALT-F3).
- Login as root so we can run a few more config commands.
- cd /usr/local/bin
- nano xinit.sh
- Insert the following lines in this new file, then save and exit:
- #!/bin/sh
- #
- This file will be executed at login, so you can put any GUI login initialization in here. For example, the touch-screen I was testing with had the X-axis inverted, so I needed to use the xinput command to fix that at each login.
- Insert the following lines in this new file, then save and exit:
- chmod a+x xinit.sh
- ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target (this switches us to Text only boot)
- cd /etc/rc.d
- nano rc.local
- Paste the following lines into this new file and then save and exit:
#!/bin/sh # # # Run everything in the background so normal startup continues. # ( # # Give the nework a chance to settle. # while true; do ADDR=`/sbin/ifconfig | grep "inet addr" | grep -v "127.0.0.1"` if [ -n "$ADDR" ]; then break; fi sleep 10 done # # Get the URL from the DHCP client and put it in the firefox prefs. # URL=`cat /var/lib/dhclient/*.lease | grep site-url | tail -n1 | awk '{print $3}' | sed 's/[\";]//g'` PROFILE=`ls -d1 /home/user/.mozilla/firefox/*.default` if [ -n "$URL" ]; then echo "user_pref(\"browser.startup.homepage\", \"$URL\");" >$PROFILE/user.js else echo "No URL found" >>/tmp/rc.local.txt fi # # Kill the getty on TTY2 and start up the GUI on TTY2. # systemctl stop getty\@tty2.service ( while true; do /etc/X11/prefdm -nodaemon; done ) ) &- chmod a+x rc.local
- This script we just created will wait for the DHCP to pick up an IP address. Then it will pull out the site-url from the DHCP response and, if it existed, put the URL into the homepage of the user’s Firefox profile. Then it will switch to GUI mode. Basically once we update Firefox we then switch to GUI so that Firefox doesn’t load before the network is ready. This is why we set our default boot mode to Text above.
- cd /etc/rwtab.d
- nano user
- Enter a single line the following and then save and quit (this makes the user’s home folder stateless once we enable stateless mode):
- files /home/user
- logout
- Once more, switch back to the GUI to set the run-at-login commands (ALT-CTRL-F2)
- Go to the Application Menu -> Settings -> Session and Startup
- Select the Application Autostart tab.
- Click Add and enter the following information:
- Name – Firefox
- Description – Firefox Kiosk
- Command – firefox (all lower case)
- Click Add again and enter the following information:
- Name – xinit.sh
- Description – Init Scripts
- Command – /usr/local/bin/xinit.sh
- Click Close
- Reboot (you can use the Power button if you want since that is setup).
- Go to the Application Menu -> Settings -> Session and Startup
- Wait for the computer to boot up. It should auto-login into the GUI and open Firefox to the “fallback” page you entered previously.
- At this point you can do any other final configuration you wish before we switch to stateless. For example, if you need to use the xinput command to configure a touch-screen device or something like that you can do so. Another thing you can do is setup a script to run every night at midnight to turn off the screen (e.g. xset dpms force off) and another to run at 6am to turn the screen back on (xset dpms force on).
- When you are ready to enable stateless mode, move on to the next section.
Enable Stateless Mode
There are only a few things you need to do to switch to stateless mode. Since you have to do some parts in single user mode we will just do everything that way. Boot the machine and at the GRUB menu hit the ‘e‘ key to edit the boot commands. Go down to the long linux line and add single to the end of that line. Then you can hit F10 to continue booting. When it is finished booting you should be already logged in at a command line.
- mount -o remount,rw / (Remount the filesystem read-write)
- mount -o remount,rw /boot
- cd /etc
- nano grub2.cfg
- Find the (first) menuentry and append readonlyroot to the end of the linux line. Save and quit.
- nano fstab
- There are 3 UUID= lines in this file. The first two are for / and /boot. Put a # at the beginning of those 2 lines to comment them out. Save and quit. This prevents the system from remounting the filesystem(s) in read-write mode.
- cd /home/user/.mozilla/firefox
- cd *.default
- rm -f user.js
- reboot
If you ever need to boot back into “full” mode you will have to essentially undo the above. Basically edit the grub boot command again and replace readonlyroot with single, then run the undo the edits to grub2.cfg and fstab. Then you can reboot and be back in “normal” mode.
Once the computer reboots you should now have a fully functional stateless system. This means you can pull the plug as many times as you want and never corrupt the file system. You can also at this point image off your 4GB thumb drive and duplicate it onto other thumb drives for use on various computers. For bonus points you can zero the swap partition and then compress the whole image to make it smaller for storage, but really it is only 4GB…
Configure DHCP server to send site-url’s
Now we have all these computers booting up, but they are all displaying the fall-back URL instead of their own individual URLs. This is pretty simple. I will document how to do this with the ISC dhcpd server that comes with Linux, but Windows’ DHCP server should be able to do the same. If you are using a special device that provides DHCP and you can’t create custom DHCP options to send you can always make your “fall-back” URL point to a PHP or ASPX script and use server-side code to detect what system this is by IP and redirect to the final site. All we are doing is defining DHCP code 224 as a text string and associating a value on a per-MAC basis.
Anyway, on your Linux DHCP server:
- cd /etc/dhcp
- nano dhcpd.conf
- Add a new line near the top, before your subnet declarations:
- option site-url code 224 = text;
- Go into your subnet declaration or specific host declaration and add the following:
- option site-url “http://myserver.fqdn/index.html”;
- Save the file and restart DHCP and then reboot your new kiosk browser appliance and it should now go to this defined URL.
-
Building a Home for Dragons
Posted on November 22nd, 2012 No comments
Following on my post about hating manufactured homes, here is the final outcome. Everything started about 6 months ago with wanting to retrofit one of the spare bedrooms in my house. I live in a 3-bedroom house all by myself, so the extra 2 bedrooms are, well, extra. One I have setup as a spare bedroom for guests – not that I really have any – and the other I setup as kind of a, umm, to be honest I’m not sure what to call it. I use it for storing many of my books (I’ve always had an interest in dragons and many of the books I have been buying the past few years have been dragon themed). I use it as a place to practice playing piano, or more specifically keyboard. I also use it as my display room to show the various trinkets I have purchased over the past few years, also nearly all dragon-themed.
So this room has officially become my “dragon room” since nearly everything in there follows a dragon theme; books, pictures, figurines, etc. It was a very pretty room before. And I don’t mean that in a good way. It didn’t fit the theme of dragons.
Not that all dragon-themed stuff has to be dark and gothic, but it was just too pretty and flowery. There were some other things that I didn’t like about the room. The light switch was wired to a plug on the wall so the ceiling fan had to be strung across the ceiling and down the wall to get it to work. The fan they ran actual in-wall electricity too, but not the light switch.
What is with that? I didn’t like how much space the closet took up. It wasn’t a big room to begin with and if it was going to be more of an office than a bedroom it really wouldn’t need a closet – and if I ever change my mind I can go buy a stand-up closet at Ikea.So, with that in mind I decided to remodel the room. Since I was going to be doing that I (poorly) decided to replace all the windows in my house with new double-pane windows. As I said, that was a bad idea to try and do both projects at the same time; which is why it is now 6 months later and I am just now finishing everything. Because of how poorly designed the house was, and my own stupidity at times, I had to not only replace the windows but rebuild the window sills and trim around all the windows as well. As I said, some of that was my own stupidity and not the houses fault, but I will blame the house anyway.
I gutted the room. And I do mean gutted. I stripped the walls down to the studs. Stripped the floor down to the, well, floor. Scraped the ceiling of all the popcorn so I could cut a strip out for new wiring and retexture later. I ripped out the closet, the door frame, carpet, everything.
They say tearing stuff out is easier than putting stuff back in. Not true with a mobile home. It takes much longer to rip out all those stupid staples and scrape all the glue off the studs to get things back to a point where you can actually work with them.And thus I began to install new stuff in the room. New electrical wiring and plugs. New ethernet wiring and plugs (every house needs ethernet).
New texture on walls and ceiling. New laminate wood flooring. New door frame. New baseboards, door trim and window trim. All in all it was an enjoyable experience. Sometimes frustrating. Sometimes smack-my-forhead-and-say-doh at my own stupidity and then redo what I just did. Sometimes joyful to look at my accomplishment and be satisfied.
In the end I was left with a completely transformed room. A room that fit better with dragons. I will admit the wall color didn’t come out like I had hoped. It was supposed to be more of a silver color but once I put it on the wall it turned out to be closer to a blue. Oh well. I can live with that. It actually fits pretty decently with the darker-colored wood stuffs in the room. The room is now complete in terms of the construction. I still have some wall-ledges to put up and a few pictures to hang, but those are things that I am going to take time with so I don’t fill my brand new walls with holes while I move things around until I find a good place for everything to sit. I also might replace the ceiling fan/light with something else later. It is frankly too dim. It doesn’t provide enough light and would like a darker set of fan-blades instead of the bright-white ones it currently has.Here is a final panorama of the room.
-
Anime Review: Vandread, Toradora!, Angel Beats!
Posted on November 6th, 2012 No commentsVandread
Space is vast; space is dark; and space is empty. In space, no one can hear the cries of 3 men trapped on a ship full of women. Whats worse, those three men have never met a woman before and have always been raised to hate and despise women. In the distant future, the genders live on separate planets. Men on one planet, and women on another… Yes, there are some obvious oddities in the pro-creation department, some kind of strange cloning or something, whatever, it isn’t important. What is important is that the genders don’t live together and are in-fact mortal enemies.
Hibiki, a low ranking mechanic; Duelo a medical doctor; and Bart, a navigator, are all trapped onboard the Nirvana. A ship that has become a sort of living creature by two separate ships, one a male’s ship and the other a female’s ship, having been fused together by the Paksis. They are essentially captured by the women, who are pirates. Shortly after the Nirvana is flung to a distant part of the galaxy to save it from destruction from a missile attack. With none of the women able to pilot the new ship, having no doctor of their own and no-one other than Hibiki to pilot the Vanguard mecha, the two genders must learn to work together while traveling back to their own solar system.
The series had a pretty good story line and plot. It was entertaining to watch and easily leaves you wondering what happens in the next episode. Character development is paced, meaning it isn’t slow in that you get bored but they don’t tell you everything about everyone all at once. Over the course of the series you learn more and more about each character, who they are and about their past. The usual romance ensues with Dita wanting to meet an “alien” (man) and following Hibiki around the ship trying to “learn more about him”. Hibiki isn’t interested in “that crazy woman” and just wants to be left alone. While there are some occasional “near misses” when it comes to the cleanliness of the content I would have to say overall it is pretty decent. Honestly I would say the worst is the season 1 opening (or maybe it was the end credits) which has some suggestive content made. The dress of the female characters is rather sparse for some of them, but unlike many shows that is as far as it goes. The clothes stay on. I would call it “beach safe”, meaning you are going to see worse at the beach… or depending on where you leave you might see worse at your local mall or grocery store.
Summary: Really enjoyed it. Good story and character development throughout the show. A welcome change from the usual “High School Anime”.
Seasons: 2
Season length: 13 episodes
Episode length: 22 minutes
Content: Mostly clean, call it teen safe.
Language: EnglishToradora!
Wow what a great show! All I can say is this is totally worth watching. Like nearly all Anime shows it is has a plot that follows your usual boy and girl should get together and everybody knows it. But they took that plot and spun it into an incredible story that will leave you laughing, confused, thinking “yea, thats something stupid I would do/did”, frustrated and sorry for various characters, screaming “why!?”, and sometimes just downright dumbfounded at what is going on.
The story follows Ryūji and Taiga, two misfits in school. Neither one has very many friends. Ryūji is seen as a scary guy do to his face; and Taiga, known as the “Palmtop Tiger”, lives up to her name as a short girl with the tenacity of a tiger. A handful of friends joins them throughout the show as they help each other find happiness, and sometimes torment each other just because they can. To say that this show includes a love triangle would not do it justice… I’m not entirely sure which geometric shape is the right one, maybe a hexagon? As I said, there are episodes that will end and just leave you thoroughly confused because you don’t have a clue as to what is going on anymore.
There is one episode which has a short questionable dream sequence that lasts about 15 seconds. Nothing is actually shown, in the dream Taiga is holding a towel or blanket or something over her body but leaving her sides exposed. Again nothing is ever actually shown. The whole team did a good job on this one of not taking the liberty to do any quick fan service even though they could easily have slipped some things in.
If you enjoy Anime that makes you laugh a lot at various antics or even downright stupidity you should enjoy this one. Clannad was a great show for telling a solid story. While Toradora! (loosely translated as Tiger Dragon!) has a pretty solid story it’s truely charming aspects come from its ability to build up a lot of tension and then suddenly let it lose with somebody doing something stupid, or just showing up at the most inopportune time. The show itself did not make much use of music inside the show, at-least nothing that leaves a memory, the opening and ending themes (there are 2 each) are pretty catchy. In addition to the episodes in the main plot, there is one OVA and 4 “shorts” that I have yet to watch, meaning I cannot attest to their cleanliness – though based on the main episodes I don’t imagine them to contain anything bad.
Summary: Good plot that develops throughout the entire shows run. Lots of laughs the whole way through.
Seasons: 1
Season length: 25 episodes
Episode length: 22 minutes
Content: Very clean
Language: Japanese with English subtitlesAngel Beats!
Imagine a world that has been created especially for kids who never got to life a full life. Imagine a world designed specifically for kids to get a chance to life that full life. Imagine a world with no adults. Imagine a world full of dead teenagers who are not yet ready to be reborn into the real world. A world where they can life a normal life. A world where they can be the kids they never got to be when they were alive. That world exists. That world is governed by Angel. And that world. That world has rebels. Youths who have rejected that they must live a “normal life” and then get obliterated from that world. Youths who have decided to stay there forever. Youths who are rebels against the God.
No, I don’t believe in reincarnation, nor do I believe that such a world exists. But this show proposes an interesting concept. What if there were an in-between world that helped us come to grips with never having had a chance to really live life as a kid when we were alive? What would we do with that chance? What if we didn’t know what would happen to us when we vanished from that world? Would we want to leave or do anything we could to stay? Would we fight against an Angel? Would we fight against a God whom we believe has turned his back on us?
This is not a philosophical show. It does not set out to really explore those possibilities, nor do I believe it sets out with an agenda to alter any beliefs you may have. It sets out with a premise and a few assumptions and creates a world. A world in which they can tell a story. A story that will make you laugh. There is not a lot of sadness in this story. There are a lot of “oh no that did not just happen” moments. It’s a clean show with a good plot. I mentioned Clannad above and I will mention it again here. Clannad is probably my single most favorite Anime thus far. I would have to put Angel Beats! in a close second. It is, sadly, short. Too short at only 13 episodes. But it tells a great story.
I will say while the content is clean it isn’t exactly child safe. Remember I mentioned the whole rebels against the God thing earlier? Well this story revolves around a group of kids who have decided they are not going to just be good kids and get obliterated from this world. They are going to fight back. Nobody actually dies (heck, they are already dead right?) and they don’t really do anything gruesome… okay well scratch that. They don’t really do anything over-the-top bloody gruesome. The first episode probably has the most gruesome thing happen that is visualized on screen, which a sword through the gut. I don’t have kids so I can’t really say how I would feel about my kids watching it if they were young, but I would again say teenagers no problem. They probably has seen more gruesome stuff at their friends houses or at the movie theatre.
Summary: Absolutely awesome. Good comedy that makes you laugh at the absurdity of it all while still telling a story of people trying to figure out who they are.
Seasons: 1
Season length: 13 episodes
Episode length: 22 minutes
Content: Sexually clean, has a few gory scenes
Language: English -
Why I hate manufactured homes
Posted on September 22nd, 2012 No commentsWhy would I have anything to say about manufactured homes? Well I live in one first of all. Secondly, I’m not the kind of person who just sits in a house and says “oh well, I wish it had such and such but it doesn’t so I guess I’ll just live without it.” My house doesn’t have networking, so I want to put it in. My house doesn’t have a wood burning stove, so I put it in. My house doesn’t have light switches that work properly, so I’m going to work on fixing them.
In my time of doing work on my house, most recently the past couple weeks while trying to retrofit a room, I have decided that I absolutely despise manufactured homes. One of my rooms, which I have nicknamed the “dragon room” due to all the dragon figurines and other dragon-themed stuff in it, is undergoing a complete retrofit. I’m pulling out all the drywall, carpet, ripping the popcorn off the ceiling, putting in network boxes as well as some other things. I’ve discovered a number of troubling things.
- They don’t have real drywall. What they have is drywall whose paper surface is wallpaper. This means you can’t just cut into it, do some work, and patch the hole back up. How the heck are you supposed to plaster over flowery wall paper and expect it to match even a little bit?
- The drywall isn’t screwed in. I didn’t really expect it to be screwed in properly, but I also didn’t expect what I found. First off, it is stapled in with a staple gun. I don’t mean they just used staples every foot or so instead of screws, I mean they put staples about every 2-3 inches. And not just one staple. Usually about 3-4 staples in every location. Secondly, as if all those staples were not enough to hold it in place, all the drywall is glued to the 2x3s as well. And not just a little bit of glue, in some places I will have to scrape it off the studs so that it will be flat for the new drywall.
- Yes, I said 2x3s. The walls are made out of 2x3s instead of 2x4s. So the walls are only 3 inches deep instead of 4. Not only does this mean I would have to custom cut some wood (I’m sure Lowe’s carries tons of 2x3s for all the idiots who don’t know how to built proper walls) if I ever needed to replace something, it also means all my wall-boxes have to be shallower, which means they are also harder to find.
- Some of the perimeter walls also have 1/8″ plywood underneath the drywall. Again, they glued and then stapled the 1/8″ plywood every few inches. And because it is so thin it just shreds when you try to peel it off the studs. And by the way, this means there is twice as many staples to pull out later because they stapled the 1/8″ plywood and then stapled the drywall over the top of it.
- Let’s also talk about insulation. While not quite as bad as I first feared when I saw how it was setup, it’s still pretty bad. The insulation on the perimeter walls isn’t blow in, but it isn’t attached to the paper. You see the paper is just 4×8 foot sheets of paper glued to the studs (are we seeing a theme here? Now I know why insurance companies are always so freaked about your manufactured home burning down, it has a few gallons of flammable glue everywhere). The insulation is basically “paperless” and just pushes up against the paper they glued in.
- No attic. I don’t mean an attic that is really hard to crawl through, I mean none what-so-ever. This means your only other choice of running cable is to go below the house. Which is about 14″ of usable crawl space through dirt filled with garbage they left behind when putting the house on it’s foundation (including razor blades) and a few thousand spider webs. Oh, and all the piping and ducting that you have to crawl over, under and around. Let’s also talk about the fact that there is about 18″ of “sub floor” to get through, including insulation, to get to the actual floor, at which point you just have to kind of guess where the wall is you want to put a hole in. Because lets face it, with flower pattern covered walls it’s not like I can cut a hole big enough to put a drill in and drill down. Not to mention some of the heating ducts run inside this “sub floor” area. I accidentally shoved a coat hanger right through the middle of the heating duct (since it is a “soft” duct instead of metal) while trying to find the electrical I had to pull down.
- Electrical that doesn’t make sense. I decided to rip out the closet from the dragon room since it was just wasting 2 feet of space in a 10×12′ room. Well, after I ripped into the temporary wall I discovered that the electrical in that wall goes down through the middle of the floor instead going over 1 foot to the permanent wall and then down through the floor. For that matter, why does all the electrical from every box go down through the floor? Why not just chain through the walls like a normal house so it’s easy to see what is linked to what? That would be too easy, so lets make it difficult and have all the electrical linked in the boxes and then go down below the floor so I just have to kind of guess which way the power is traveling.
- Since we are talking about electrical, you know those stupid light switches that turn on and off electrical outlets? The ones they used to use in the 1950s before they invented ceiling fans? Yeah they still use those. So I will be cutting out a piece of the ceiling to run electrical the proper way to the ceiling fan so the light switch actually works the way anybody would expect. And this is where I found the blow in insulation, as it fell all over me after pulling out the piece of drywall.
- Cathedral ceilings. Yea, maybe they look great. But guess what, when you have to drywall those it’s a pain. The walls in this room vary in height from 7.5′ to 8.5′. Which means no matter what I will be custom cutting every piece of drywall I put in. And because it goes over the normal 8′ height I will have to plaster a horizontal line on 3 of the 4 walls as well.
- Wood floors. No I don’t mean hard wood, or even laminate floors. I mean the actual floor that the floor is installed on is wood. And not a hard wood, it’s like some kind of particle board that doesn’t hold staples well. Yes staples is what they used to hold the base floor down. Which means now that it is 20 years later I have to go back and re-screw down the floor because it squeaks like mad since none of the staples are holding tight and all the wood panels are at varying heights now.
- Wood trim over joints instead of actually finishing up the drywall. I can’t describe how much trim I pulled out of that one room, but you can see the picture below (sorry it’s so blurry). That is all out of this 10×12′ room.
I hate manufactured homes.










