set_trace 2015-08-12T05:31:13Z/blog/atom.xml/API Goodness with Mailgun, Trello, and gspreadTim Freund2015-08-12T00:45:00Z2015-08-12T00:45:00Z/blog/mailgun-trello-and-gspread.html
<p>We’re about to open registration for <a href="https://wiki.openstack.org/wiki/OpenStack_Upstream_Training">OpenStack Upstream
Training</a>,
and we needed to glue together Google Spreadsheets, Trello, and email
to streamline the registration process.</p>
<p>The <a href="https://github.com/burnash/gspread">gspread</a> and
<a href="https://pypi.python.org/pypi/trello">Trello</a> APIs were easy to use, as expected.</p>
<p>I had my doubts about Mailgun, because there was no suggested Mailgun
library. Instead, the docs recommended developers just install
<a href="http://www.python-requests.org/en/latest/">Requests</a>. I expected to
write some boilerplate as a result, but they proved me wrong.</p>
<p>Check out the <a href="https://documentation.mailgun.com/user_manual.html#sending-via-api">Mailgun docs for sending an
email</a>.
Examples in 6 languages and curl, and the examples update with your
<span class="caps">API</span> endpoints and auth data if you’re logged in. That’s some
<a href="https://www.twilio.com/docs/api/rest/making-calls">Twilio</a> level
documentation, and I’m now a huge fan.</p>
<p>If you want to see how we tie the systems together, check out the
<a href="https://github.com/timfreund/openstack-upstream-registrar">openstack-upstream-registrar</a>
code. I’d like to morph that short script into a small web application
that will guide developers through the <span class="caps">ATC</span> process. Reach out if you’d
like to help!</p>
<p>Back on the topic of the training itself: we’re always looking for
more in-class mentors and assistants! If you’ll be in Tokyo on
October 25th and 26th, please consider <a href="http://goo.gl/forms/fczq3NZ16g">registering as an
assistant</a>.</p> ceph-libvirt-clustererTim Freund2015-07-20T01:45:00Z2015-07-20T01:45:00Z/blog/ceph-libvirt-clusterer.html
<p>I’m thinking about getting in to <a href="http://ceph.com">Ceph</a> development,
and so I’m thinking about how to quickly provision and destroy and
reprovision tiny Ceph clusters at home.</p>
<p>For love of blinking lights, I’ll probably build a cluster with
<a href="http://www.bananapi.org/">Banana Pi</a> boards in the future, but for
now I’m just using libvirt and <span class="caps">KVM</span>.</p>
<p><a href="https://github.com/timfreund/ceph-libvirt-clusterer">Ceph-libvirt-clusterer</a>
lets me clone a template virtual machine and attach as many <span class="caps">OSD</span> disks
as I’d like in the process. I’m really happy with the tool
considering that I only have a day’s worth of work in it, and I got to
learn some details of the libvirt <span class="caps">API</span> and python bindings in the process.</p>
<p><img src="/media/images/articles/cephlvc-running-machines.png"/></p>
<p>On the road map:</p>
<ul>
<li>Add and remove disks from running machines</li>
<li>Build a command line interface</li>
</ul> Build Virtual Machines for Multiple Hypervisors with Jenkins and PackerTim Freund2015-04-19T00:05:00Z2015-04-19T00:05:00Z/blog/build_vms_for_multi_hypervisor_with_jenkins_and_packer.html
<p>Building a virtual machine image for one target hypervisor probably
doesn’t cut it anymore. If your organization is like most today, you
run VMware in production, and you’re investigating <span class="caps">AWS</span> or OpenStack
for burstability or a full blown migration, and your developers all
run VirtualBox on their laptops. Except for Marvin. Marvin runs <span class="caps">KVM</span>
because he’s a contributor to the project.</p>
<p>We can define cross-hypervisor machine definitions with
<a href="https://packer.io/">Packer</a>.</p>
<p>We can run Packer on a variety of machines to provide full hypervisor
coverage with <a href="https://jenkins-ci.org/">Jenkins</a>.</p>
<p>Packer and Jenkins make a great team. They’re like peanut butter and
chocolate. Or coffee and chocolate. Or pastry and chocolate.</p>
<p>/me grabs a chocolate bar from his drawer and gets back on track.</p>
<p>Many organizations use a single Jenkins server to run continuous
integration builds, but Jenkins supports any number of slave nodes to
distribute load. Further, we can assign labels to those nodes that
define capabilities or other characteristics (host <span class="caps">OS</span>, installed
software, special hardware architecture, etc).</p>
<p>Jobs can be pinned to nodes with specific labels, and the <a href="https://wiki.jenkins-ci.org/display/JENKINS/NodeLabel+Parameter+Plugin">NodeLabel
Parameter
Plugin</a>
lets us use node labels as a parameter when building a job.</p>
<p>I give each of my build nodes a label of packer-${builder-name}, then
I can build any machine in my <a href="https://github.com/timfreund/packer-opensource-appliances">Packer Open Source
Appliances</a>
repository on all of my available local hypervisors and cloud
accounts. My personal list includes qemu, docker, virtualbox-iso, and
openstack (with Rackspace).</p>
<p>I’m pretty excited about this, and I’ll share more details and
possible next steps in a future post. Until then, you can snag
the <a href="https://github.com/timfreund/packer-opensource-appliances/blob/master/jenkins-builder-job.xml">job definition from my repository</a>.</p> Better Storytelling and Positive DeviancyTim Freund2015-01-04T11:55:00Z2015-01-04T11:55:00Z/blog/better.html
<p>I mark passages in books while I read, and then I return to the books
later and copy the marked passages into my personal notes.</p>
<p>Among other interesting snippets, I marked and starred four whole
pages in <a href="http://www.amazon.com/Better-A-Surgeons-Notes-Performance/dp/0312427654">Atul Gawande’s Better</a>. I think that people who highlight
entire pages just don’t quite understand the concept of highlighting,
so my left eyebrow instinctively rose while I attempted to figure out
what the hell I was thinking when I marked such a large passage.</p>
<p>It talks about the difference between 99.5% and 99.95% health rates,
and I’m already very familiar with that difference since they come
up in service level agreements all the time, but this passage doesn’t
recite facts. It tells the story of 99.5% versus 99.95% with a
fantastic narrative that left me with a little lump in my stomach,
and those four pages are enough for me to recommend the whole book,
but you can <a href="http://www.npr.org/templates/story/story.php?storyId=10944103">read that excerpt right now thanks to <span class="caps">NPR</span></a>.</p>
<p>Atul could replace those four pages with a brief exposition of facts:
the difference between being 99.5% and 99.95% successful with a
treatment regimen sums up to a 16% chance or 83% of making it through a year
without complications. Instead he tells a story in four pages that
made me stop, think, and mutter “damn.”</p>
<p>And the impact of a good story isn’t just a momentary pause. Stories
help us retain information. That’s why I thought of Shlemiel the
Painter while full grown adults bickered about string encoding in C
today. Joel Spolsky wrote <a href="http://www.joelonsoftware.com/articles/fog0000000319.html">Back to Basics</a> in 2001, and I still
remember the story of Shlemiel.</p>
<p><a href="https://www.flickr.com/photos/chberge/9381228298" title="Street Lines by Chris-Håvard Berge, on Flickr"><img src="https://farm6.staticflickr.com/5448/9381228298_7a4ec6ffd2.jpg" width="500" height="244" alt="Street Lines"></a></p>
<p><a href="http://www.inc.com/magazine/20081201/how-hard-could-it-be-my-style-of-servant-leadership.html">Learning to clean toilets even makes a great story when Joel tells the tale.</a></p>
<p>Returning to Better before I close out this post, I want to share two
paragraphs from the Afterword (Becoming a Positive Deviant)</p>
<blockquote>
<p>Wherever doctors gather - in meeting rooms, in conference halls,
in hospital cafeterias - the natural pull of conversational gravity
is toward the litany of woes all around us.</p>
<p>But resist it. It’s boring, it doesn’t solve anything, and it will
get you down. You don’t have to be sunny about everything. Just be
prepared with something else to discuss: an idea you read about, an
interesting problem you came across — even the weather if that’s all
you’ve got. See if you can keep the conversation going.</p>
</blockquote> A Review of My Life in AdvertisingTim Freund2014-08-11T01:55:00Z2014-08-11T01:55:00Z/blog/my_life_in_advertising.html
<p><a href="https://www.flickr.com/photos/dok1/5158259855" style="float: right;" title="Pepsodent Ad by Don O'Brien, on Flickr"><img src="https://farm2.staticflickr.com/1209/5158259855_dc02e1a566.jpg" width="201" height="500" alt="Pepsodent Ad"></a></p>
<p><a href="http://www.amazon.com/Life-Advertising-Scientific-Classics-Library-ebook/dp/B00AMUHY70">My Life in Advertising</a>
is the autobiography of
<a href="http://en.wikipedia.org/wiki/Claude_C._Hopkins">Claude Hopkins</a>.
It’s out of copyright, so you can also get a legitimate copy from
<a href="https://archive.org/details/mylifeinadverti00unkngoog">The Internet Archive</a>.
Everyone reading this post is in sales and marketing, and so everyone
reading this post can gain something from this freely available book.</p>
<p>Three themes repeat throughout the book:</p>
<ol>
<li>Know your customer, show them value, get the sale.</li>
<li>Trace your advertising efforts through the sale.</li>
<li>Work is play, if framed correctly.</li>
</ol>
<p>I hosted a
<a href="/blog/book_discussion_power_of_habit.html">book discussion on The Power of Habit</a>.
If you’ve read that book, Claude’s work on Pepsodent will sound
familiar. Charles Duhigg wrote about Claude’s work on Pepsodent
that helped usher in an age of tooth brushing in America.</p>
<p>Internet marketers pat themselves on the back for A/B testing. Claude
did that in print, and with real, physical product on the line.
Everything old is new again.</p> What Every Web Developer Should Know about HTTPTim Freund2014-07-27T21:55:00Z2014-07-27T21:55:00Z/blog/know_about_http.html
<p><a href="http://www.amazon.com/Every-Developer-Should-OdeToCode-Programming-ebook/dp/B0076Z6VMI">What Every Web Developer Should Know About
<span class="caps">HTTP</span></a>
has a long title, but it’s a pretty short read. I didn’t time my
reading, but my Kindle tells me that 30 minutes remain in the book if
I open to the first page.</p>
<p>I bought this book because I’ve considered writing something similar
concerning other topics like <span class="caps">DNS</span> or <span class="caps">SSL</span>, and I can report that it’s a
decent tour through <span class="caps">HTTP</span>.</p>
<p>If you’ve never made a <span class="caps">HTTP</span> request by running telnet against a web
server, or never reviewed requests and responses in Wireshark or a
developer console, this book is for you. If you have a junior
developer on the team that’s just learning about web programming, send
them a copy of this to get them started. Examples are in C#, so stay
away if you hate C# and you’re too shallow of a programmer to look
past that choice (and consider yourself judged for that shallowness).</p> Kallithea CI Service ProposalTim Freund2014-07-08T08:55:00Z2014-07-08T08:55:00Z/blog/kallithea_ci_proposal.html
<p><a href="https://kallithea-scm.org/">Kallithea</a> is a new source code
management system based on the <span class="caps">GPL</span> origins of RhodeCode. The project
needs a continuous integration service running in the open to
sufficiently test incoming patches across a matrix of configuration
variables. I’ve started looking into adding <span class="caps">SSH</span> authentication
capabilities, so solid automated testing platform is personally interesting.</p>
<p>I am building a Jenkins server for this purpose. The server build
process is automated with <a href="http://packer.io">Packer</a> and
<a href="http://puppetlabs.com/">Puppet</a> so that we can easily host the
system in a large variety of environments.</p>
<p>Builds will run in Docker containers through the <a href="https://wiki.jenkins-ci.org/display/JENKINS/Docker+Plugin">Jenkins Docker
Plugin</a>.
<a href="http://blogs.nuxeo.com/development/2014/02/docker-jenkins-cloud-provider/">The plugin makes Docker hosts look like a cloud provider to
Jenkins</a>.
Since Docker now supports nested containers, each Jenkins slave
container can launch any number of other containers to orchestrate
multi-node tests.</p>
<p><img src="/media/images/articles/kallithea-ci-server.png"/></p>
<p>This approach offers at least three benefits:</p>
<ul>
<li>The system can start on a single host</li>
<li>We can build rich single use test environments that launch quickly</li>
<li>The system can grow as our testing needs grow</li>
</ul>
<p>At the least I imagine test jobs to run the following:</p>
<ul>
<li>Unit tests</li>
<li>Integration tests with various infrastructure components (for instance: sqlite, MySQL, PostgreSQL)</li>
<li>Application upgrade tests</li>
</ul>
<p>I’m happy to pay for the hosting of the <span class="caps">CI</span> service, but the open and
automated deployment definitions will allow anyone to build and run
their own system as well.</p>
<p>The first scraps of configuration are in the following two repositories:</p>
<ul>
<li><a href="https://github.com/timfreund/puppet-kallitheaci">puppet-kallitheaci</a></li>
<li><a href="https://github.com/timfreund/packer-template-kallithea-ci">packer-template-kallithea-ci</a></li>
</ul>
<p>Please let me know if you have any thoughts, questions, or concerns.
In addition to the mailing list, you can find me in the #kallithea <span class="caps">IRC</span>
channel as timfreund.</p> Review - Becoming a Change ArtistTim Freund2014-06-25T00:55:00Z2014-06-25T00:55:00Z/blog/becoming_a_change_artist.html
<p><a href="http://www.amazon.com/Becoming-Change-Artist-Quality-Software-ebook/dp/B004SCRVIK">Becoming a Change
Artist</a>
is not bad, but it’s also not in the top three books that I’d
recommend from Gerald Weinberg.</p>
<p>Read it if you have three to four hours to spare, and you’re
interested in the dynamic of change in an organization. Don’t read
it if you’ve heard great things about Mr. Weinberg and want to see
what all the fuss is about.</p>
<p>Start instead with <a href="http://www.amazon.com/Becoming-Technical-Leader-Gerald-Weinberg-ebook/dp/B004J4VV3I">Becoming a Technical
Leader</a>
or <a href="http://www.amazon.com/Secrets-Consulting-Giving-Getting-Successfully-ebook/dp/B004J35LHQ">The Secrets of
Consulting</a>.
You don’t need to be an official consultant to benefit from The
Secrets of Consulting. Most of consulting involves facilitating
work among groups of humans, and that’s probably a big part of your
job even if you don’t want to admit it.</p> Notes for Enterprises Investigating OpenStack from eNovanceTim Freund2014-06-02T01:25:00Z2014-06-02T01:25:00Z/blog/notes_for_enterprises_investigating_openstack_from_enovance_in_atlanta.html
<p><a href="http://techs.enovance.com/author/nijaba">Nick Barcet</a> of
<a href="http://www.enovance.com/">eNovance</a> gave two presentations at
the OpenStack Summit in Atlanta that resonated with me as we
investigate running OpenStack at work.</p>
<p><a href="https://www.openstack.org/summit/openstack-summit-atlanta-2014/session-videos/presentation/are-enterprises-ready-for-the-openstack-transformation">Are Enterprises Ready for the OpenStack Transformation?</a>
<a href="http://www.slideshare.net/NicolasBarcet/are-enterprises-ready-for-the-openstack-transformation?qid=820a4433-69b2-47e6-b28b-51af2f5a4535&v=default&b=&from_search=1">slides</a></p>
<p>Key points:</p>
<ul>
<li>Vanilla OpenStack is a framework, not a product. It will never be
ready out of the box.</li>
<li>Licensing alone isn’t reason enough to use open source: people,
hardware, and power still make up the lion’s share of data center budgets.</li>
<li>OpenStack provides agility with infrastructure to enable rapid
application deployment and iteration.</li>
<li>This agility is worthless if the business doesn’t capitalize on
it by shifting mindsets and accelerating cycle times.</li>
<li>Start with new apps in a small scale at first to get practice with the
shift. No need for everything to move all at once.</li>
</ul>
<p><a href="https://www.openstack.org/summit/openstack-summit-atlanta-2014/session-videos/presentation/delivering-openstack-clouds-as-a-factory">Delivering OpenStack Clouds as a Factory</a></p>
<p>Key points:</p>
<ul>
<li>Remember the agility in the last presentation? Part of that
includes the platform itself: OpenStack releases every 6 months.</li>
<li>No cloud platform is simple: lots of moving parts.</li>
<li>OpenStack runs a sophisticated continuous integration system with Jenkins</li>
<li>eNovance runs a duplicate <span class="caps">CI</span> infrastructure chained from the OpenStack <span class="caps">CI</span> system.</li>
<li>eNovance also runs a duplicate <span class="caps">CI</span> infrastructure chained from their
corporate <span class="caps">CI</span> systems in customer cites.</li>
<li>They’ve built tooling to allow progressive upgrades and rollbacks of
installed clouds: rack by rack, for instance.</li>
<li>They often run as little as two weeks behind the stable branch.</li>
</ul>
<p>As a counterpoint to this, I met with someone who was struggling with
an upgrade for over 6 months. They installed OpenStack’s Diablo
release years ago, and they’ve given up on the idea of smoothly
migrating to Havana (released in November of 2013). Instead, they’re
dropping in a new cloud on new hardware. If you don’t stay up to
date, you’ll get into a treadmill of invasive installations and migrations.</p> OpenStack Upstream TrainingTim Freund2014-06-01T22:05:00Z2014-06-01T22:05:00Z/blog/openstack_upstream_training.html
<p>I grabbed one of the last tickets to the <a href="https://wiki.openstack.org/wiki/OpenStack_Upstream_Training">OpenStack Upstream
Training</a>
that ran the weekend before the Atlanta OpenStack Summit.</p>
<p>I’ve used open source for longer than I care to remember, and I’ve
even submitted a few patches along the way, but I’ve never become a
member of a project. I felt a little under- and over-qualified
simultaneously. How could I feel overqualified if I had never become
a repeat contributor? I know how to program, but contribution is a
lot more than programming. See if any of the phrases sound familiar:</p>
<ul>
<li>I just need to sit down and figure it out. (repeated weekly)</li>
<li>I’m going to work on bug $X tomorrow. (repeated weekly)</li>
<li>I hope I do this right, I don’t want to look stupid.</li>
</ul>
<p>Here’s a hint: “I just need to sit down and figure it out” repeated
more than once is code for “I don’t really want to do this” or “I have
no idea where to start, and I could use a little guidance.” In my
case, it was the latter.</p>
<p>The size and sophistication of OpenStack intimidated me. I’m no
stranger to code review, continuous integration, and automated
testing, but OpenStack is big. There are more hosts running or ready
to run automated tests for OpenStack than we use to service our
biggest application at $<span class="caps">DAYJOB</span>. (Check out the “Job Stats” graph on
the <a href="http://status.openstack.org/zuul/">Zuul Status Page</a> to see a live
count of hosts.)</p>
<p>My biggest problem was a people problem: I was convinced that while
navigating the OpenStack build and review environment for the first
time I’d make a mistake, and people would think I’m stupid. In
retrospect, that was stupid of me. Of course I’d make mistakes, but
the people and the processes exist to help us build a better product,
accounting for the possibility of mistakes along the way. OpenStack
doesn’t get built in large chunks of caffeine fueled code tossed over
a wall. We build it one small, well reviewed, well tested patch at a time.</p>
<p>The OpenStack Upstream Training broke down into three major components:</p>
<ul>
<li>The Training Class</li>
<li>The Design Summit</li>
<li>The Mentoring</li>
</ul>
<p><strong> The Training Class </strong></p>
<p>Scheduled in the two days prior to the Summit, we soaked in the
technical and social processes of OpenStack, and we didn’t have time
forget it all before the Summit began.</p>
<p>The bulk of our classroom training focused on the people and the
social processes in open source, and specifically OpenStack. Behind
every patch and every review comment there is a human being with
hopes, goals, stress, problems, and dreams. We all want to build a
great system, and we’re all constrained to 168 hours each week. The
<span class="caps">PTL</span> that doesn’t respond to an email isn’t ignoring you on purpose,
she’s drowning in email and constantly trying to dig out. Gerald
Weinberg reminds us in his writing that “no matter how it looks,
everyone is trying to be helpful.” We can never go wrong with empathy.</p>
<p>Even if you don’t attend Upstream Training, you should definitely read
<a href="http://www.amazon.com/Communication-Close-Dorset-House-eBooks-ebook/dp/B00DY3KQI6">Communication Gaps and How to Close Them</a>.</p>
<p><strong> The Design Summit </strong></p>
<p>Summits are more than just a traditional conference. Design
discussions to shape the next release fill more than half of the week.
Upstream students’ most important assignment for Summit week was to
find and meet the team members that would review our chosen work.</p>
<blockquote>
<p><span class="dquo">“</span>Introduce yourself, tell them what you’re interested in working on,
and how much time you will commit each week. They are busy, they will
love you.”</p>
</blockquote>
<p>I met a large chunk of the Designate team, and I learned how little I
know about running <span class="caps">DNS</span> at scale. That’s <span class="caps">OK</span>, though, I’ll learn more
as I go, and the team will help along the way.</p>
<p><strong> The Mentoring </strong></p>
<p>The class followed by the summit made for an exhausting week. It
would have been easy to fly home, sleep for a day, and get lost in
$<span class="caps">DAYJOB</span> work for a week trying to catch up. “I’ll do some OpenStack
work next week once I’ve caught up on home and work.”</p>
<p>Wrong. The habit of OpenStack contribution isn’t yet built, and
taking a week off will destroy any momentum. The program includes
weekly mentoring sessions to keep students moving forward.
<a href="http://dachary.org/">Loic</a> set aside valuable time on Wednesdays and
Saturdays to check in on students and keep them moving toward their
goal, and it was vital for my success. I stayed up until 4:00 <span class="caps">AM</span> the
night before my first mentoring session because I didn’t want to let
him down, and I wasn’t happy with my progress thus far.</p>
<p>I now have one patch merged, one under review, and one in work. I’m
also working on improving the automated testing for Designate, and I
suspect I’ll work on documentation in coming months as well.</p>
<p><strong> Should you attend? </strong></p>
<p>You, too, should attend OpenStack Upstream Training if you feel
capable but stuck when considering open source contribution. The
training will give you the social and process knowledge to succeed,
and the encouragement to keep moving forward until you build up your
own momentum. It’s hard work, but it’s fun work.</p>
<p>The Upstream University training changed the trajectory of my career.
I’ll forgive you for dismissing that as hyperbole since I’m still so
early in the process, but I already feel addicted to the scale of
OpenStack and the hum of hundreds of sharp developers and operators
improving it one patch at a time.</p> King Leopold's SoliloquyTim Freund2014-04-13T22:15:00Z2014-04-13T22:15:00Z/blog/king_leopolds_soliloquy.html
<p>King Leopold <span class="caps">II</span> was a cold bastard. Let’s assume he was one tenth the
bastard that Mark Twain makes him out to be <a href="https://archive.org/details/kingleopoldssol00twaigoog">King Leopold’s
Soliloquy</a>.
That’s still one cold and messed up dude.</p>
<p>The book is short. I spent an hour with it. I caught myself
scrunching my face into a look of disgust several times in that hour.
The following is from the <a href="http://en.wikipedia.org/wiki/Congo_Free_State">Congo Free State Wikipedia page</a>, but try it out for disgust:</p>
<blockquote>
<p>They also burned recalcitrant villages, and above all, took
human hands as trophies on the orders of their officers to
show that bullets hadn’t been wasted. (As officers were
concerned that their subordinates might waste their ammunition
on hunting animals for sport, they required soldiers to submit
one hand for every bullet spent.)</p>
</blockquote>
<p>One hand per bullet spent. If soldiers shot an animal for food,
they’d pick a random native and chop off his hand to pay for the bullet.</p>
<p>Damn.</p> Communication Gaps - Over and UnderTim Freund2014-03-24T00:15:00Z2014-03-24T00:15:00Z/blog/communication_gaps_over_and_under_communicating.html
<p>Imagine we’re fighting a problem, and a weird one at that. Now we
have two problems: the real problem needs to be solved, and the
customer needs to know what’s going on, even if we have no idea what’s
going on. “It’ll be done when it’s done,” and “I’ll tell you when I
know something” leave customers unsettled.</p>
<p>We work magic as far as outsiders know, and often no outward
appearance of progress appears until things just start working again.
Our work is the blackest of black boxes to a non-technical customer.</p>
<p>Over- and under-communication can both be problematic, but customers
can curtail the former with a quick request to scale back as long as
the project is on track.</p>
<p>There’s no such thing as over-communication when a project has gone
off the rails. The project probably fell off the rails because
serious under-communication led up to an “oh crap” moment.
Under-communication produces stress in a customer as they wait for
news. If customers need to reach out to you for an update, you’re not
providing enough effective updates. A handful of loony customers will
never be happy with the quantity or quality of updates, but most
customers are well adjusted humans with families and friends and
hobbies. Start a project over-communicating, and you and the customer
can settle in to a rhythm that’s just right without inducing stress.</p>
<p><a href="http://www.flickr.com/photos/blmiers2/6104829628/" title="Ketchikan, Alaska by blmiers2, on Flickr"><img src="http://farm7.staticflickr.com/6065/6104829628_2275f38268.jpg" width="500" height="333" alt="Ketchikan, Alaska"></a></p>
<p>In the absence of external stimuli, our minds fill in the blanks. In
the case of a project, that usually involves a litany of worst case
scenarios. “I haven’t seen or heard from the developer in over a
week. I hope he didn’t die in a house fire when he accidentally left
an old coffee pot plugged in while working through the night on this
bug. I hope he didn’t take my money and move to Ketchikan. I hope
I hear from him soon. This is really starting to freak me out.” It’s
always nice when a customer hopes that you <em>didn’t</em> die in a fire, but
why put them through that in the first place? Just call them and let
them know what’s going on, even if you’re still scrambling like mad to
figure out what’s going on.</p>
<blockquote>
<p>If customer satisfaction is important to you, periodically ask yourself:<br/>
- Who is expecting a follow up call from me?<br/>
- Who is waiting for information that’s important to them?<br/>
- Who has submitted a request and wants to know its status?<br/>
<br/>
You could also ask,<br/>
- Who would appreciate receiving status information, even if they’re
not actively waiting for it?<br/>
— Communication Gaps and How to Close them, Chapter 9</p>
</blockquote>
<p>Readers, if you’re still on the fence about the benefits of
<em>Communication Gaps and How To Close Them</em>, then take this really
short questionnaire that will determine if it will hold three or more
interesting insights into your work and your relationships at work:</p>
<ol>
<li>Do you work in some kind of <span class="caps">IT</span> type role? Programmer,
administrator, project manager? Help desk tech? Tape jockey?</li>
<li>Do you work with other people?</li>
</ol>
<p>If you answered both in the affirmative, it’s a near guaranteed hit. Only
one “yes” still makes it a pretty safe bet. Two negative answers means
you’re a troll or a robot, in which case you should really get back to
human overload overthrow or bridge guarding, respectively.</p> Nihilism Doesn't Mean What You Think it Means.Tim Freund2014-03-23T23:55:00Z2014-03-23T23:55:00Z/blog/nihilism_that_word_doesnt_mean_what_you_think_it_means.html
<p><img src="/media/images/articles/nihilism-header.png"/></p>
<p>Nihilism. He keeps using that word. I do not think it means what he
thinks it means. George is either singularly focused on cash
or a quite subtle satirist. He’s willing to call himself a Mobile
Maverick, so I assume that subtlety is out of the question.</p>
<p><img src="/media/images/articles/nihilism-no_attempt_to_make_money.png"/></p>
<p>Yes, yes, for the love of all things holy, how can someone turn down
web advertising, especially with the high cost of page hosting on GitHub?</p>
<p><img src="/media/images/articles/nihilism-ze_money.jpg"/></p>
<p>George seems to narrowly derive existential meaning from commercial
success. If a game isn’t commercially successful or at least written
with the intent of commercial success, it isn’t worthy of existence
because it may detract from the commercial success of others. He
actually goes further than that. It’s <span class="caps">OK</span> to rip off a general concept
created by someone else if the ripoff is geared toward making mad
stacks of cash most efficiently. Free market, baby.</p>
<p><img src="/media/images/articles/nihilism-filling_pockets.png"/></p>
<p>Let’s review. Some things with no existential value:</p>
<ul>
<li>Recreational programming.</li>
<li>Open source software.</li>
<li>Playing games that are fun and freely offered.</li>
</ul>
<p>Things with existential value:</p>
<ul>
<li>Monetization strategies.</li>
</ul>
<p>This all comes from someone in the game development industry. A guy
who writes games for people to play when they could instead spend a
few extra hours tending their
<a href="http://en.wikipedia.org/wiki/Backyard_furnace">backyard furnace</a>.
Why should his users play games rather than monetize their lives?
Does he believe that users inhabit some lower rung of the
evolutionary ladder, where people derive meaning from purchasing apps,
clicking ads, and making in game purchases?</p>
<p>We’re living in the future. We actually don’t need to tend backyard
furnaces, or sow our own seeds, or grind our own grain. We enjoy
extra time to pursue creative acts that bring us each joy and
fulfillment. Not only that, but we’re all connected in a way that
allows us to share and collaborate with the world rather than our
immediate friends and neighbors. Clay Shirky makes the case for this
cognitive surplus, and argues that any form of creativity is a sign of
human progress.</p>
<iframe width="560" height="315" src="//www.youtube.com/embed/Z0msKMRxFNw" frameborder="0" allowfullscreen></iframe>
<p>I enjoy playing 2048, but I enjoy seeing the near endless stream of
2048 clones even more. We’re living in a future where people have the
time and skill to write and release useful, fun, entertaining software
for free just because they enjoy the act.</p>
<p>I hope that more people turn to creation rather than consumption to
pass time and find meaning. I’d rather see 2048 people proudly
posting clones of 2048 that they wrote than 2048 people posting
screenshots of their high score in 2048 or Threes.</p>
<p>Find meaning in making.</p> My Failures as a StudentTim Freund2014-02-23T21:35:00Z2014-02-23T21:35:00Z/blog/my_failures_as_a_student.html
<p>During my junior year of high school I was such a terrible student of
English that I’m pretty sure Mrs. Reynolds sighed with disappointment
when I passed the <span class="caps">AP</span> English test through brute force and luck. Two
years later my sister failed one of her quizzes with Mrs. Reynolds,
and it came back “F - Don’t be like your brother.”</p>
<p>During my senior year of high school I was such a terrible student of
English that Mrs. Wareham sent a letter home to my mom asking her to
remind me that if I failed English, I failed high school. I still
remember the look of disappointment when Mr. Steinberg asked if he’d
see me at the spring play audition and I told him I couldn’t because I
wasn’t doing well in English. The play went on without me, of course.
I imagine he thought “damn, kid, high school is just the beginning.
Don’t screw it up already,” while shaking his head.</p>
<p>In both cases, I failed to read the material in a serious way. I
decided that I wasn’t interested in the books, and I wasn’t interested
in serious study of fiction writing, so I shrugged off the work and
did as little as possible. I remember discussing the audacity of
English teachers assigning us 50 pages of reading a night. I remember
jealously learning that the non-honors students were creating grammar
puzzles for homework while we were reading or pretending to read 50
pages a night.</p>
<p>The same thing happened with a political science course in college.
<a href="http://www.amazon.com/Truman-David-McCullough-ebook/dp/B000FC0VVQ">Truman</a>
couldn’t be a realistic expectation for someone with serious math and
computer science studies. It was obviously an assignment to each us
how to creatively fulfill coursework requirements without actually
doing the coursework.</p>
<p>In all three cases, I skated by on previously earned aptitude and
racked up a bit of intellectual debt. Just like we can build technical
debt into software projects, I did the same with my education.</p>
<p>Years later, I’m paying off that debt by reading a great deal across a
number of subjects. The variety expands my mind in new directions and
simply makes me a better reader for the next book to land on my desk.</p>
<p>Aside from the Amazon marketplace and Kindle books, I can find a
treasure trove of great material at the sales put on by the Friends of
the Library. I browsed the selection three separate times this week
and walked away with books each time. Everything in the picture
below rang up to about $20</p>
<p><a href="http://www.flickr.com/photos/timfreund/12735074694/"
title="My haul from the library book sale by timfreund, on
Flickr"><img
src="http://farm8.staticflickr.com/7378/12735074694_403598be73.jpg"
width="500" height="375" alt="My haul from the library book sale"></a></p>
<p>I wish I could have the years back in which I shrugged off so much
reading. I’ve reversed my position on it because so many of the
people that I respect and admire read voraciously, and it is no coincidence.</p>
<p>If you’re in Lancaster, <a href="http://www.lancaster.lib.pa.us/support/booksales-and-donations/">mark your calendar</a>.</p> Communication Gaps - Horrible HollyTim Freund2014-02-09T20:35:00Z2014-02-09T20:35:00Z/blog/communication_gaps_horrible_holly.html
<iframe src="http://rcm-na.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=ren-20&o=1&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=B00DY3KQI6" style="width:120px;height:240px;float: right;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>Initiating a new team member requires two different flavors of
education: technical background that they need to accomplish good
work, and social background that helps them fit in to the company.
Often the latter happens through stories: the oral history of the
company, and often the most interesting and amusing of those stories
are the tales of terrible customers.</p>
<p>Amusing and correct are always synonymous.</p>
<blockquote>
<p>Once you label someone as a “difficult customer,” you are likely
to see that customer as difficult thereafter. You’ll be quicker to
find evidence of difficult behavior to support your label, rather than
evidence to support more positive attributes. You’ll also be more
likely to describe that person to others as a difficult customer
rather than as a person with whom you have had a difficult
interaction.</br>
— Communication Gaps and How To Close Them, Chapter 7</p>
</blockquote>
<p>Not only does this sour a potential friendship between new techs and
old customers, it’s likely a matter of misplaced blame. Is Horrible
Holly really so horrible, or is she just stressed out because the
system sucks, and she doesn’t receive a vital report on schedule about
half of the time, and the ticketing system doesn’t tell her if anyone
saw her request, and asking for an updated status often results in a
tech snapping at her?</p>
<p><a href="http://www.flickr.com/photos/tshirbert/4046768036/" title="Verizon loves you! by t.shirbert, on Flickr"><img src="http://farm3.staticflickr.com/2475/4046768036_8f9073440d.jpg" width="321" height="500" alt="Verizon loves you!"></a></p>
<blockquote>
<p>The team members decided to modify their own responses to Holly,
agreeing to give her the freedom to tout her ideas and vent her
problems… Over time, her aggressiveness diminished, and then
vanished; in addition, she started becoming attentive to the pressures
they were facing and, for the first time, empathized with their
challenges.</br>
— Communication Gaps and How To Close Them, Chapter 4</p>
</blockquote>
<p>Maybe you aren’t yet ready to read <em>Communication Gaps and How to
Close Them.</em> We’ll dig in a little more next time, and I’ll provide a
two question quiz that’ll help you determine if it’s a good fit for you.</p> Computing for Data AnalysisTim Freund2014-02-04T22:07:00Z2014-02-04T22:07:00Z/blog/computing_for_data_analysis.html
<p>Two mathematical shames haunt me from my college days. I never
<em>really</em> understood calculus as much as I understood how to make
Mathematica solve calculus problems, and I never took a class in
probability and statistics.</p>
<p>I’ve been working on that second shame source over the last few weeks.
In addition to self study through
<a href="http://www.amazon.com/gp/product/0393970833/">Statistics</a>, I stumbled
by chance upon
<a href="https://www.coursera.org/course/compdata">Computing for Data Analyis</a>
shortly before the last session began. From there I also picked up
<a href="http://www.amazon.com/gp/product/0387989668/">S Programming</a>, but
let’s talk about the course rather than the books.</p>
<p>The course does not explicitly cover statistics as some had hoped. It
provides a solid introduction to many aspects of the R programming
language that is often used for statistical analysis. Even without any
statistics experience, I kept up without any trouble, and my
R experience will help as I dive deeper into stats in the coming weeks.</p>
<p>The course is short, and they estimate an average of 3-5 hours per
week. Their estimate was spot on for me, but I already have a couple
of programming languages under my belt, so this was incremental
learning. People with limited software development experience
struggled considerably with the programming assignments and spent more
than the estimated time on the course. The last assignment involved
extracting data from an ugly <span class="caps">HTML</span> file with regular expressions: it
was like an easy day at the office for me, but only because I’ve
extracted data from uglier files with. Your mileage may vary.</p>
<p>As I started to learn R during the class and thus started talking
about it trying to recruit friends to join, Tal Yarkoni published
<a href="http://www.r-bloggers.com/the-homogenization-of-scientific-computing-or-why-python-is-steadily-eating-other-languages-lunch/">The homogenization of scientific computing, or why Python is steadily eating other languages’ lunch</a></p>
<p>A Python guy learning R while an R guy blogged about Python taking
over his programming toolbox amused my friends. I preach frequently
about picking tools and sticking with them to increase the velocity
with which interesting solutions find their way into users’ lives, but
this was study time, not work time. R transitions quite easily from
an interactive language to a “traditional” programming language, and
the language design aids that continuous transition. For instance,
most programmers spend a considerable amount of time working within
the confines of a “for” loop, but “for” loops get ugly in an
interactive environment. The vectorized nature of data and functions
in R mean that, although occasionally useful, writing “for” loops is
usually unnecessary and stylistically improper.</p>
<p>If you’d like to learn more along these lines, there’s a new
<a href="https://www.coursera.org/specialization/jhudatascience/1">Data Science Specialization offered by Johns Hopkins through Coursera</a>.
The course that I just finished is replaced with the “R Programming”
course and you can mix and match classes if you aren’t interested in
the certificate at the end.</p>
<p>If instead you’d just like to click a link to a new tool, check out
<a href="http://yihui.name/knitr/">knitr</a>. It’s sort of like the
<a href="http://ipython.org/notebook.html">IPython Notebook</a>, but it feels
like document creation may be a little more natural, and knitr
supports multiple languages. I’ve only casually used both, so I’d
welcome more enlightened opinions on them.</p> Book Discussion - The Power of HabitTim Freund2014-01-30T10:35:00Z2014-01-30T10:35:00Z/blog/book_discussion_power_of_habit.html
<p><a href="http://www.flickr.com/photos/whatsthatpicture/7970160692/" title="Portrait of a nun by whatsthatpicture, on Flickr"><img src="http://farm9.staticflickr.com/8435/7970160692_d90a8520d3.jpg" width="390" height="500" alt="Portrait of a nun"></a></p>
<p>Habits. Not just for nuns.</p>
<iframe src="http://rcm-na.amazon-adsystem.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=ren-20&o=1&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=081298160X" style="width:120px;height:240px;float: right;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>Join me and a few other people as we discuss
<a href="http://www.amazon.com/dp/B0055PGUYU">The Power of Habit: Why We Do What We Do in Life and Business</a>
by Charles Duhigg. The Kindle edition is $10 and anyone can read it
through the Cloud Reader even without a Kindle device. It’ll be an
open discussion, and I’ll provide notes and additional resources once
we’re done.</p>
<p>Our tentative time is <span class="caps">4PM</span> Central on February 19th via Google
Hangouts. Let me know if you’re interested and I’ll add you to the
invite. <a href="https://plus.google.com/+TimFreund">Find me on Google+</a>
since that’s where the discussion is going to happen.</p>
<p>If you’re not convinced that habits warrant any attention, check out
<a href="http://bjfogg.com/"><span class="caps">BJ</span> Fogg</a>‘s work on the subject, including
<a href="http://tinyhabits.com/">Tiny Habits</a> and a
<a href="http://www.youtube.com/watch?v=AdKUJxjn-R8">talk he did on the subject</a></p>
<p>And if you’d like a light hearted introduction to habit that got me
interested in the subject years ago, you can always check out
<a href="http://gilesbowkett.blogspot.com/2010/07/secrets-of-superstar-programmer_13.html">this video on habits by Giles Bowkett</a>.</p>
<p><a href="https://plus.google.com/+TimFreund">Find me on Google+</a>, and I will see you February 19th!</p> PhotoFUSETim Freund2014-01-25T16:03:00Z2014-01-25T16:03:00Z/blog/photofuse.html
<p>The key to taking great photos is taking a lot of photos. Most of
them will suck, but that’s how it goes.</p>
<p>My photos break down into the following buckets</p>
<ul>
<li>9165 photos total</li>
<li>424 rated 3+</li>
<li>95 rated 3+ with the tag Dog</li>
<li>3 rated 4+</li>
</ul>
<p>I want to see the good photos on a regular basis without maintaining a
separate list or directory of the good stuff. I use xscreensaver’s
photopile program, and it likes to read photos from directories.</p>
<p><a href="https://github.com/timfreund/PhotoFUSE">PhotoFUSE</a> uses
<a href="http://fuse.sourceforge.net/"><span class="caps">FUSE</span></a> and
<a href="https://github.com/terencehonles/fusepy">fusepy</a> along
with <a href="https://pypi.python.org/pypi/PIL"><span class="caps">PIL</span></a> to expose a
subset of my photo collection as a virtual directory,
filtered by rating and tags.</p>
<p>I’ve already found and fixed a leaky file handles bug, so
you won’t surprise me if you find other issues.</p> Enter the NovitiateTim Freund2014-01-25T12:25:00Z2014-01-25T12:25:00Z/blog/novitiate.html
<p><img src="/media/images/articles/novitiate.png"/></p>
<p>Our culture discounts the novitiate for any activity. Maybe it’s
machismo, maybe its decades of jumping straight to expert mode in our
video games, where resets and continues keep us alive. By skipping
straight into advanced play, we rob ourselves of personal development
and learn bad habits that will later hinder our growth into expert practitioners.</p>
<p>One prescribed path for novice motorcycle riders has just three steps:</p>
<ol>
<li>Buy gear first, and wear it whenever you’re on the bike.</li>
<li>Take the <span class="caps">MSF</span> class.</li>
<li>Start small, start used. You’re going to drop it,
and it’s just your first, not your last.</li>
</ol>
<p>Uttering these three guidelines is the motorcycling equivalent of
calling Beetlejuice three times. A frat bro will arrive on scene to
let everyone know that he started on a brand new supersport liter
bike, and feeling the wind at <span class="caps">95MPH</span> is too incredible to pass up for
the sake of safely wearing a helmet.</p>
<p>Anybody can get lucky. People make safety conscious recommendations
because of statistics.</p>
<p><a href="http://www.flickr.com/photos/chrisyarzab/9030367465/" title="Motorcycle 013 by Chris Yarzab, on Flickr"><img src="https://farm4.staticflickr.com/3821/9030367465_9a7dc43c0f.jpg" width="500" height="266" alt="Motorcycle 013"></a>
<br/>
<a href="http://www.flickr.com/photos/johnbullas/3038267217/" title="ATT00003 car bike crash by DrJohnBullas, on Flickr"><img src="http://farm4.staticflickr.com/3032/3038267217_aa9abf57d9.jpg" width="500" height="375" alt="ATT00003 car bike crash"></a>
<br/>
<a href="http://www.flickr.com/photos/23562295@N00/344717006/" title="Motorcycle rider down by 7mary3, on Flickr"><img src="http://farm1.staticflickr.com/128/344717006_8a0d932778.jpg" width="500" height="375" alt="Motorcycle rider down"></a>
<br/>
<a href="http://www.flickr.com/photos/blodulv/217515168/" title="P1010005 by Beau Gunderson, on Flickr"><img src="http://farm1.staticflickr.com/86/217515168_ca3d3ae03e.jpg" width="500" height="375" alt="P1010005"></a>
<br/></p>
<p>It’s true that a new rider, wet behind the ears, can put the shiny
side down just as easily on a used <span class="caps">EX</span>-250 as they can on a new R6, but
accidentally jamming the throttle open on one or the other will
produce two entirely different accidents. And even if it isn’t the
rider’s fault at all, there’s still something terribly depressing
about laying a beautiful <span class="caps">FZ6</span> to rest only 3000 miles into its life.
(Gear literally saved my ass, and shoulder, and feet, and arms, even
on a hot day when the wind would have felt sublime.)</p>
<p><a href="http://www.flickr.com/photos/timfreund/5879818648/" title="Bike Damage by timfreund, on Flickr"><img src="http://farm6.staticflickr.com/5236/5879818648_1fc1e44e6d.jpg" width="500" height="375" alt="Bike Damage"></a></p>
<h3>What if there’s just pride on the line?</h3>
<p>I ran cross country in high school, and I had a passing familiarity
with the weight room between the team’s Tuesday and Thursday weight
workouts and gym class. When I got tired of buying bigger jeans in my
adult life, I decided that strength training would be one part of my
waistline recovery process. I needed a solid program, so I turned to
Amazon. The fact that I last seriously trained for anything over 15
years prior didn’t enter into my calculations. I skipped right over
the novice materials and bought into
<a href="http://www.amazon.com/Maximum-Strength-Strongest-Ultimate-Weight-Training-ebook/dp/B004ZY13F8/">Eric Cressey’s Maximum Strength</a>
and
<a href="http://www.amazon.com/Practical-Programming-Strength-Training-Rippetoe/dp/0982522754/ref=dp_ob_title_bk">Rippetoe’s Practical Programming</a>.
It made sense because I’m a smart guy and I’ve worked out before.</p>
<p>Except that in this case I was an idiot with zero real life weight
training aptitude. Deadlifts frightened me, I wore my running shoes
while weight lifting, and I didn’t even face the right direction in
the squat rack. Ever see someone doing something so wrong that you
didn’t even have the heart to tell ‘em how wrong they were? That was me.</p>
<p>After a round of burn out and a year long hiatus, I actually started
at the beginning and had a lot of fun while not hurting myself with
<a href="http://www.amazon.com/Starting-Strength-Mark-Rippetoe-ebook/dp/B006XJR5ZA">Starting Strength</a></p>
<h3>Is it <span class="caps">OK</span> to reset?</h3>
<p>It’s <span class="caps">OK</span> to live the novice life more than once. I mentioned cross
country running above. I loved distance days. Our coach maxed us out
at about six miles, and I could run those six miles every day and not
once grow tired of it. We were free to choose any number of routes
through Roeland Park and Prairie Village, and it was beautiful in the
fall. On speed training days our warm up runs would typically be
about 2 miles.</p>
<p>I didn’t keep up the habit after high school. How do you think I would
start a running program as an adult after last seriously running in
high school and realizing that my calorie burn rate wasn’t keeping up
with my burrito consumption rate?</p>
<ul>
<li>at age 21?</li>
<li>at age 23?</li>
<li>at age 26?</li>
<li>at age 28?</li>
<li>at age 30?</li>
</ul>
<p><a href="http://www.flickr.com/photos/nate_c/1200238692/" title="fat lane - galway by Nate C, on Flickr"><img src="http://farm2.staticflickr.com/1273/1200238692_eafde82d7d.jpg" width="500" height="333" alt="fat lane - galway"></a></p>
<p>If you said “start running just like it was 1998 again, and then take
a day off after three agonizing days, and then pretend like running
never happened two weeks later” then you’re absolutely correct. If I
were so smart I would embrace the fact that I had regressed back to a
running novice. Maybe I’d still be running today. There’s a reason why
<a href="http://www.coolrunning.com/engine/2/2_3/">Couch-to-5K</a> is a real and
popular thing.</p>
<h3>Does anyone do this novice stuff right?</h3>
<p>Monks respect the novitiate. The novitiate is such a big deal that
proto-brothers can’t even ask for admission as a novice until they
spend weeks, months, or even years contemplating monastic life as a
postulant. That’s right, there’s a level below novice among many
religious orders. The Benedictines don’t even make things official at
the end of the novitiate: a monk in training will then take temporary
vows for three years before finally professing life long vows. The
Jesuits don’t even give a firm timeline for taking final vows, but it
looks like final vows might happen a decade or more after entering
into the novitiate and growing through several additional stages of
study that includes a month long experiment with homelessness.</p>
<blockquote>
<p>Ora et labora, erryday.<br/>
— Benedict of Nursia</p>
</blockquote>
<p><a href="http://www.flickr.com/photos/mariya_umama_wethemba_monastery/3667833337/" title="St. Benedict detail in fresco - plain version by Randy OHC, on Flickr"><img src="http://farm3.staticflickr.com/2574/3667833337_20808df61d.jpg" width="500" height="375" alt="St. Benedict detail in fresco - plain version"></a></p>
<p>South Korean archers also respect the novitiate. That’s why <a href="http://en.wikipedia.org/wiki/List_of_Olympic_medalists_in_archery#Women.27s_events">they dominate
the sport</a></p>
<blockquote>
<p>First they spend months learning the proper stance. Then it’s months
learning to raise one arm, then both arms for a couple of months…
Those kids have six months intensive training before they shoot their
first arrow. <br/>
<a href="http://www.reuters.com/article/2012/07/27/oly-arch-kor-coaching-day-idUSL3E8I107020120727">Olympics-Archery-Get me a Korean … any Korean!</a></p>
</blockquote>
<p>Meanwhile, some other countries were so racist and eager to jumpstart their
own archery programs that they hired South Korean coaches with zero
experience in archery. As if their love of kimchi was the secret to bow
handling success.</p>
<h3>Novice gains from novice pains</h3>
<p>Part of a successful novitiate in any endeavor is the pain of slowing down
enough to ensure that a strong foundation of successful habits form so that
more advanced skills and techniques can grow in the future.</p> Force Shotwell to Rewrite MetadataTim Freund2014-01-19T23:05:00Z2014-01-19T23:05:00Z/blog/force_shotwell_to_rewrite_metadata.html
<p><a href="http://www.yorba.org/projects/shotwell/">Shotwell</a> is the first photo
organizer that hasn’t made me angry. I’m not a huge photographer, but
I’m pretty picky about tools, so that’s saying a lot.</p>
<p>Photos can be tagged and rated, and for a long time those tags and
ratings were stored exclusively in the Shotwell database, but the
application now allows users to store metadata in Exif and <span class="caps">IPTC</span> tags
within the photo files for use by other applications. I checked the
button, but it looks like shotwell doesn’t automatically go back and
write that data for older files.</p>
<p>Shotwell uses SQLite for its metadata storage, so it’s easy to force
an update of all your files. Quit Shotwell if it is running, and
follow along:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="nv">$ </span><span class="nb">pwd</span><br />/home/tim/.local/share/shotwell/data<br /><span class="nv">$ </span><span class="nb">cd</span> ~/.local/share/shotwell/data<br /><span class="nv">$ </span>cp photo.db photo.db-justincase<br /><span class="nv">$ </span>sqlite3 photodb<br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="n">sqlite</span><span class="o">></span> <span class="k">select</span> <span class="k">count</span><span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="k">from</span> <span class="n">phototable</span> <span class="k">where</span> <span class="n">metadata_dirty</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span><br /><span class="mi">0</span><br /><span class="n">sqlite</span><span class="o">></span> <span class="k">update</span> <span class="n">phototable</span> <span class="k">set</span> <span class="n">metadata_dirty</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span><br /><span class="n">sqlite</span><span class="o">></span> <span class="k">select</span> <span class="k">count</span><span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="k">from</span> <span class="n">phototable</span> <span class="k">where</span> <span class="n">metadata_dirty</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span><br /><span class="mi">7917</span><br /></pre></div><br /><figcaption><span class="caps">SQL</span></figcaption></figure></div>
<p>Of course the counts will vary depending on the size of your photo
collection. Next time you start Shotwell you’ll see it updating
metadata: there will be a progress bar displayed below the pane
that shows your folders and tags.</p> Seiki SE39UY04 for Development on LinuxTim Freund2014-01-15T10:05:00Z2014-01-15T10:05:00Z/blog/seiki_se39uy04_and_linux.html
<p>I’m not a gamer or an artist. I’m a software developer and system
administrator. I use linux on the desktop, and below you’ll read how
I decided to gamble on
the <a href="http://www.amazon.com/gp/product/B00DOPGO2G/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00DOPGO2G&linkCode=as2&tag=ren-20">Seiki
<span class="caps">SE39UY04</span></a><img src="http://ir-na.amazon-adsystem.com/e/ir?t=ren-20&l=as2&o=1&a=B00DOPGO2G"
width="1" height="1" border="0" alt="" style="border:none !important;
margin:0px !important;" /></p>
<p>I was just about to pull the trigger on two new 1080p monitors when
the <span class="caps">SE39UY04</span> dropped in price to $499. That would give me 2x the
resolution I would get out of the 2 1080p monitors at a price I
couldn’t ignore.</p>
<p>Gamer friends cringed at the 30hz refresh rate. I swore of games
years ago because of the terrible things that Unreal Tournament and
StarCraft did to my bed time. My cursor blinks about once per second,
and i3 doesn’t offer much in the way of fancy desktop window
animations. Seeing the desktop animation in the following video made
me feel like it’d be entirely comfortable for the type of work that I do:</p>
<iframe width="560" height="315" src="//www.youtube.com/embed/i1O9bdQ_AyY" frameborder="0" allowfullscreen></iframe>
<p>Garrett does a great video review as well:</p>
<iframe width="560" height="315" src="//www.youtube.com/embed/_-MarXCiXg8" frameborder="0" allowfullscreen></iframe>
<p>He talks a bit about the monitor powering off. There’s a setting in
the service menu that disables the four hour power off function. The
sparkle that he talks about around 3:15 is definitely an issue with
some gradients.</p>
<p>Here are two other reasonable reviews on the web that I considered:</p>
<ul>
<li><a href="http://simpleprogrammer.com/2013/11/11/seiki-se39uy04-39-inch-4k-ultra-hd-review-3840-x-2160/">Simple Programmer’s review</a></li>
<li><a href="http://tiamat.tsotech.com/seiki-4k">Seiki’s Okay Four K</a></li>
</ul>
<p>Photographer friends cringed at the color fidelity prospects. I
understand. I would rather enjoy silence than listen to poorly
reproduced music, but I am not a visual artist and I don’t do any work
that demands accurate color reproduction. <a href="http://www.reddit.com/r/photography/comments/1s8zea/editing_large_at_4k_for_500_a_seiki_39_4k_tv/">/u/trackpete’s
Editing Large at 4k</a>
was a fantastic resource for seeing first hand
exactly how the color fidelity played out in real life. He includes
side by side photos that will show the difference in color
reproduction assuming that you’re viewing the images on something
other than the subpar Seiki.</p>
<p>My emacs theme doesn’t look much like a sunset, so I felt like I could
live with the situation. I’m not dead yet, so I guess I was right.</p>
<p>Getting the monitor running with linux was my only remaining concern,
and fortunately there’s a guy named houkouonchi that made me confident
enough to make the purchase. He wrote a <a href="http://www.amazon.com/review/R1R4ZEWGCLUSRT">detailed review of the
device</a> and its bigger
sibling on Amazon, and he provided detailed information about
configuring the <a href="http://ubuntuforums.org/showthread.php?t=2164924">Nvidia driver and X to send a 4k signal to the
Seiki</a>.</p>
<p>It’s not a perfect monitor, but it’s the most value for my hardware
dollar since building the Q6600 workstation that served me for years
and upgrading to an <span class="caps">SSD</span> in my subsequent workstation. I’ll happy
when 4K displays with wide color gamut and fast refresh rates are both
common and affordable, but I’ll enjoy this bargain basement display
until then.</p> We Reserve The Right to Refuse ServiceTim Freund2014-01-05T21:55:00Z2014-01-05T21:55:00Z/blog/we_reserve_the_right_to_refuse_service.html
<p>I made the mistake of reading blog comments while finding a link to
<a href="http://www.iwillteachyoutoberich.com/blog/the-briefcase-technique-to-earn-thousands-of-dollars/">Ramit Sethi’s briefcase technique video</a>
and other Earn1K introductory
material. In the original version of the post Ramit advertised a one
night only first come first served webinar.</p>
<p>Two commenters showed how seemingly arbitrary rules can help filter out
the people that will just waste your time and theirs: Alfonso asked for
a recording because the live event was at <span class="caps">4AM</span> in his part of the world.
Ramit said “no”, and Alfonso decided to set his alarm to make the event.</p>
<p>Meanwhile, check out Adam’s response.</p>
<p><img src="/media/images/articles/right_to_refuse-briefcase.png"></p>
<p>Damn, Adam. Walk down the block to Osco Drug and purchase a <span class="caps">VHS</span>
cassette to record Lost since <span class="caps">DVR</span> technology is a foreign concept for
you. Or just stop watching Lost and get on with your life — you’re
on a personal finance blogger and entrepreneur’s site inquiring about
ways to earn more money. Step one is to stop watching television on
television’s schedule. Step two is to learn a desirable skill or
trade. Step three is to produce some real work. Ramit’s scheduling
barrier meant that he didn’t need to listen to Adam whining later.</p>
<p>Along the same vein, Merlin mentioned email as a way of weeding out
customers that were out of his league on an <a href="http://5by5.tv/b2w/61">old episode of Back to Work</a></p>
<blockquote>
<p>If somebody wants to hire me to talk about productivity stuff,
and they can’t schedule a phone call, then they may need more help
than I can give them.</p>
</blockquote>
<p>I recently had a repeat encounter with a help vampire, and it made me
wonder if I was too easy to approach with problems. Maybe I can be
too eager to help at times? I like being helpful, and I try not to be
a jerk even though I am some of the time. Here’s the rub: being too
helpful can do just as much long term damage as shunning all requests
for help. Helpful people everywhere want to grow their community and
nurture novices into journeymen and seasoned experts. Coddling stunts
growth and encourages new community members to turn into help
vampires. Spoon feeding answers to full grown professionals is a
little like feeding chicken to Mogwai after midnight.</p>
<iframe width="560" height="315" src="//www.youtube.com/embed/CnBEKAWKqOM" frameborder="0" allowfullscreen></iframe>
<p>Refreshers for people on both sides of the help equation:</p>
<ul>
<li><a href="http://www.catb.org/~esr/faqs/smart-questions.html">How To Ask Questions the Smart Way</a></li>
<li><a href="http://slash7.com/2006/12/22/vampires/">Help Vampires: A Spotter’s Guide</a></li>
<li><a href="http://jasonwryan.com/blog/2012/03/17/vampires/">A Taxonomy of Help Vampires</a></li>
</ul>
<p>Be helpful. Be pleasant. Know that refusing to help can be the most
helpful solution of all.</p> Get ActionTim Freund2013-12-28T13:55:00Z2013-12-28T13:55:00Z/blog/getaction.html
<p>Theodore Roosevelt was an unstoppable force of nature. He transformed
from a scrawny child to an amateur boxer. He was a taxidermist, a bird
expert, a renowned author of The Naval War of 1812, all before graduating
from Harvard.</p>
<p>He chased three men who stole his boat down an icy river for three
days after first building a makeshift boat to start the journey. He
then spent over a week escorting the men to prison rather than hanging
them on the spot.</p>
<p>He led the change up San Juan Hill, and he was a politician with
theatrical flair. He entertained himself with judo lessons and stick
fights between appointments in the White House.</p>
<p>He voraciously read, often during appointments if his guest couldn’t
hold his attention.</p>
<p>… and I’m not even done reading his three part biography by Edmund
Morris. At some point I’ll read about him getting shot and giving a speech
before seeking medical attention.</p>
<p>Roosevelt didn’t tolerate idle time. During a patience trying time of his
presidency he admonished a Rough Rider colleague to “Get action. Do things;
be sane; don’t fritter away your time; create, act, take a place wherever
you are and be somebody; get action.”</p>
<p>That sort of quote sounded like wallpaper material to me, so I put one
together and made it my default browser home page. It greets me when I
open a new tab and steers me toward interesting work rather than trivial distractions.</p>
<p><a href="/media/images/wallpaper-getaction.jpg"><img src="/media/images/wallpaper-getaction-small.jpg"/></a></p>
<p>You can grab the <a href="/media/images/wallpaper-getaction.jpg">full sized jpeg</a> or the <a href="/media/images/wallpaper-getaction.xcf">original <span class="caps">XCF</span> file</a>.</p>
<p>If you’d like to read more about Roosevelt, I can’t stress how much I’ve
enjoyed the first half of the following trilogy:</p>
<ul>
<li><a href="http://www.amazon.com/Theodore-Roosevelt-Modern-Library-Nonfiction-ebook/dp/B004DEPH3E">The Rise of Theodore Roosevelt</a></li>
<li><a href="http://www.amazon.com/Theodore-Rex-Modern-Library-Paperbacks-ebook/dp/B004DEPH0M">Theodore Rex</a></li>
<li><a href="http://www.amazon.com/Colonel-Roosevelt-Edmund-Morris-ebook/dp/B003EY7IQI">Colonel Roosevelt</a></li>
</ul> Customize Your Customer ServiceTim Freund2013-11-23T16:15:00Z2013-11-23T16:15:00Z/blog/customize_your_customer_service.html
<p>Have you considered purchasing over seven hundred customer service
numbers? <a href="http://twilio.com">Twilio</a> rents toll numbers for a single
dollar a month, and toll-free numbers only cost a single dollar more.
Twilio’s great, but they aren’t even the lowest cost provider. At
those prices, can you afford to not own seven hundred customer
service numbers?</p>
<p>That’s what the developers at <a href="http://www.hotels.com/">Hotels.com</a> did
to help customer service agents quickly identify why a customer was
calling and what they could do to help:</p>
<blockquote>
<p>The company even created separate phone numbers (more than
seven hundred in total) that dynamically appeared based on the
page and how the customer got to it, so that when customers
called a certain number, it would be obvious where they encountered
problems. <br/>
<a href="http://www.amazon.com/gp/product/B004OC07BW/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B004OC07BW&linkCode=as2&tag=ren-20">Analytics at Work</a><img src="http://ir-na.amazon-adsystem.com/e/ir?t=ren-20&l=as2&o=1&a=B004OC07BW" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, chapter 8, page 142</p>
</blockquote>
<p>A casual inspection of the site shows that this program was successful,
because it’s still in use:</p>
<p><img src="/media/images/articles/customize_your_customer_service.png"></p>
<p>You can check it out yourself by watching the number in the upper left
corner of the screen change as you first visit the site, search for a
hotel, and click on a hotel for additional details.</p>
<p>How can you use data to customize customer service?</p>
<p>Anonymously collecting and aggregating it is a good first step. If
you aren’t tracking usage of your sites and applications, you’re
ignoring valuable data. There is a major <span class="caps">US</span> based website that was
localized for countries across the globe, and their Japanese site had
conversion rates significantly lower than any other location. Were
there cultural differences at play? Analytics reports for their
multi-page sales form showed that 90% of their customers bounced
between two specific steps. Analysts found that the bounce inducing
page was never translated from English to Japanese.</p>
<p>You may know about the <span class="caps">DRY</span> principle. Some programmers live and die
by this one single acronym: don’t repeat yourself. Don’t make your
customers repeat themselves, either. Ask for confirmation that the
number on their account is the number their calling from, ending in
1234, rather than making them punch in the whole thing.</p>
<p>Allow users to opt-in to deeper data collection. If something goes
wrong, don’t just show them an error page and apologize.Allow them to
file a support request from the error page and automatically associate
it with their account and bundle a log of the activities they were
trying to accomplish with the ticket.</p>
<p>Just don’t be creepy. You probably remember Target taking all of this
a little too far when it <a href="http://www.forbes.com/sites/kashmirhill/2012/02/16/how-target-figured-out-a-teen-girl-was-pregnant-before-her-father-did/">announced a teen daughter’s pregnancy before
she did</a>.</p> Sad Sweetheart of the RodeoTim Freund2013-11-22T13:10:00Z2013-11-22T13:10:00Z/blog/sad_sweetheart_of_the_rodeo.html
<p>John Roderick walks on to stage, plugs in, and thumps the bass. It’s
the first time he’s ever heard the bass growl through an amplifier,
and he’s only played bass for a day. Not that bass, any bass. Five
seconds later, he is playing bass, with Harvey Danger, on national
television, and rocking it.</p>
<iframe width="420" height="315" src="//www.youtube.com/embed/l_lhJSLvlQc" frameborder="0" allowfullscreen></iframe>
<p>Check out the bass amp behind him: “Get well Aaron.” The real bass
player flew home sick and went straight to the hospital. Rather than
cancel the show, John stepped up to the bass after playing keyboard in
the band.</p>
<p>I’ve played bass for half of my life, pretty seriously for a good
chunk of that half, and I <em>still</em> can’t sing and play at the same time.</p>
<p>I heard John’s story in <a href="http://www.merlinmann.com/roderick/ep-24-the-wrong-mustache.html">Episode 24 of Roderick on the Line, The Wrong
Mustache</a>,
check it out for more details and more crazy stories. And go do
something awesome.</p> Python XPath Namespaces and No MatchesTim Freund2013-11-17T22:10:00Z2013-11-17T22:10:00Z/blog/python_xpath_namespaces_and_no_matches.html
<p>Scenario: You’re running XPath expressions on a document or element
parsed with Python’s ElementTree module, and you can’t find the
expected results. It’s like there are no elements in the tree.
Weirder still, iterating over all elements proves that there are
elements in the tree.</p>
<p><span class="caps">TL</span>;<span class="caps">DR</span>: Namespaces. Use them in your queries.</p>
<p>Python’s ElementTree module makes <span class="caps">XML</span> processing pretty tolerable,
most of the time. I don’t like digging through <span class="caps">XML</span> documents, but I
don’t hate it when I’m using ElementTree and XPath to do the dirty work.</p>
<p>My latest project takes government data provided in Excel spreadsheets
and loads them into a database where I can then serve up the data as
<span class="caps">JSON</span> and JavaScript visualizations. The files looked like Excel 2010
spreadsheets on the surface, but they weren’t vanilla. They were
generated with <span class="caps">SAS</span>, and uploaded as raw <span class="caps">XML</span> documents:</p>
<pre>
$ file coalpublic1983.xls
coalpublic1983.xls: XML document text
</pre>
<p>That’s weird for an Excel spreadsheet. Normally they’re zip files with
the <span class="caps">XML</span> tucked inside along with various metadata files. Here’s that
same file after opening and saving in LibreOffice:</p>
<pre>
$ file coalpublic1983.xlsx
coalpublic1983.xlsx: Zip archive data, at least v2.0 to extract
</pre>
<p>Since they weren’t proper Excel spreadsheets, openpyxl couldn’t read
them. Since they were <span class="caps">XML</span>, ElementTree could, but the findall method
returned no elements. A bit of sleuthing showed that the
ElementTree element names included the relevant <span class="caps">XML</span> schemas, so rather than</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">tree</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s">'.//Row'</span><span class="p">):</span><br /> <span class="k">pass</span><br /></pre></div><br /><figcaption>Python</figcaption></figure></div>
<p>I did this instead:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">tree</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s">'.//{urn:schemas-microsoft-com:office:spreadsheet}Row'</span><span class="p">);</span><br /> <span class="k">pass</span><br /></pre></div><br /><figcaption>Python</figcaption></figure></div>
<p>Just rolls right off the tongue, doesn’t it?</p> Tracking Habits is a Habit worth HavingTim Freund2013-11-03T12:55:00Z2013-11-03T12:55:00Z/blog/habitrpgchains.html
<p>Tracking habits is a habit worth having. My favorite tool is
<a href="http://habitrpg.com">HabitRPG</a>, but it doesn’t provide an easy way to view all of my
progress (yet). To cement the knowledge in <a href="http://tim.freunds.net/blog/interactive_data_visualization_for_the_web.html">Interactive Data
Visualization for the
Web</a>
I created <a href="http://habitrpgchains.freunds.net/">HabitRPG Chains</a>.</p>
<p>Through the magic of cross domain <span class="caps">AJAX</span> and HabitRPG’s <span class="caps">API</span>, the page
renders all of your recent daily habit activity. Green is good, red
is bad, light gray is a day off, and dark gray is missing from the database.</p>
<p>There’s a demo account if you’re not a HabitRPG user.
<a href="http://habitrpgchains.freunds.net/">Check it out</a>
and let me know what you think.</p> Interactive Data Visualization for the WebTim Freund2013-10-27T22:15:00Z2013-10-27T22:15:00Z/blog/interactive_data_visualization_for_the_web.html
<p>A very concise explanation of callbacks and scope in JavaScript care
of <a href="http://shop.oreilly.com/product/0636920026938.do">Interactive Data Visualization for The Web</a>:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="nx">d3</span><span class="p">.</span><span class="nx">json</span><span class="p">(</span><span class="s2">"someFile.json"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">json</span><span class="p">)</span> <span class="p">{</span><br /> <span class="c1">//Put things here that depend on the <span class="caps">JSON</span> loading</span><br /><span class="p">});</span><br /> <br /><span class="c1">//Only put things here that can operate independently of the <span class="caps">JSON</span></span><br /><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"I like cats."</span><span class="p">);</span><br /></pre></div><br /><figcaption>JavaScript</figcaption></figure></div>
<p>I just finished the book, and I took my time, working through all of
the examples by hand.</p>
<p>Modern JavaScript isn’t anything like the stuff people of my
generation churned out in the days of <span class="caps">IE</span> and Netscape Navigator 4. I
think my previous attempts at grokking D3 were sidelined by my rush to
skim through to the neat stuff. If you’ve had the same experience,
please slow down and do the homework. I absolve you from chapters 1
through 3, but start paying attention in chapter four even when you
don’t think it’s necessary.</p>
<p>O’Reilly gives you the option to read it
right now for free (ctrl+f “Read Online Now!”), so no excuses if you
want to learn D3.</p>
<p>Scott provides a full list of additional resources, both tutorials and
examples. One of the experts is <a href="http://vallandingham.me">Jim
Vallandingham</a>, and Jim also produces
<a href="http://viskc.com/">VisKC</a>. That site should interest about 100% of
my regular readers.</p> Emacs Prelude Terminal Arrow KeysTim Freund2013-10-25T23:55:00Z2013-10-25T23:55:00Z/blog/emacs_prelude_terminal_arrow_keys.html
<p>New <a href="http://www.amazon.com/gp/product/B00E3W1726/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00E3W1726&linkCode=as2&tag=ren-20">Samsung
840 <span class="caps">EVO</span>
<span class="caps">SSD</span></a><img src="http://ir-na.amazon-adsystem.com/e/ir?t=ren-20&l=as2&o=1&a=B00E3W1726"
width="1" height="1" border="0" alt="" style="border:none !important;
margin:0px !important;" />. <a href="http://releases.ubuntu.com/saucy/">Fresh Ubuntu installation</a>. Happy days.</p>
<p><a href="https://github.com/bbatsov/prelude">Prelude</a> made the cut since I was
starting fresh anyway. It worked well until I opened <code>emacsclient</code>
and found that the arrow keys produced <code>A</code> <code>B</code> <code>C</code> and <code>D</code> rather than
cursor movement. It smacks of <code>vi</code> on some of our older and crappier
systems at work. This is a deal breaker.</p>
<p>The <a href="https://groups.google.com/forum/#!msg/ergoemacs/KdqwDR_gqPQ/55bd8UqIthQJ">ErgoEmacs user list solved the issue</a>.</p>
<p>The ErgoEmacs team received a bug report that matched my own, and another
Prelude user even beat me there. Mapping <code>M-o</code> and <code>M-O</code> kills arrow
key behavior when running Emacs in a terminal, and Prelude does just that.</p>
<p>To stop this behavior, open <code>~/.emacs.d/core/prelude-mode.el</code> and comment
out the following two key definitions:</p>
<pre><code>;; (define-key map (kbd "M-o") 'prelude-smart-open-line)
;; (define-key map (kbd "M-O") 'prelude-smart-open-line-above)
</code></pre>
<p>Feel free to send me angry email explaining why I shouldn’t use the arrow keys
at all. I’ll think fondly of you and your zeal as I delete the message without
a second thought.</p> Succumbing to NIH is a RiskTim Freund2013-10-15T11:25:00Z2013-10-15T11:25:00Z/blog/succumbing_to_nih_is_a_risk.html
<p>I’m evaluating <a href="http://www.openstack.org/">OpenStack</a> commercial
partners, and I’m interested in their ability to blend with our
current infrastructure. One vendor touted their automatic
provisioning and configuration management system, and I wondered if it
was just a re-brand of something like <a href="http://puppetlabs.com/">Puppet</a> or <a href="http://www.opscode.com/chef/">Chef</a> under the
covers. Puppet would be fantastic since we’re invested in that
technology already.</p>
<p>Google pointed me to a clarifying article:</p>
<blockquote>
<p>… [<span class="caps">PRODUCT</span>] doesn’t rely on third-party products such as Puppet or
Chef to handle deployments. He claimed there was risk involved with using
such tools, especially with Puppet’s ties to VMWare, and suggested the
learning curve was higher using them than with his company’s package. </p>
</blockquote>
<p><a href="http://www.flickr.com/photos/pontodeak/3331006405/" title="tango lessons by Andre Deak, on Flickr"><img src="http://farm4.staticflickr.com/3585/3331006405_e27f3c62f0.jpg" width="500" height="339" alt="tango lessons"></a></p>
<p>Risk happens. We dance with risk all day every day. With no more
specific information regarding the risks inherent in using an existing
provisioning and configuration management system, I must assume those
same risks are present using their home grown system. Nobody from
Puppet Labs will stop by the home office of this vendor and demand
exclusive use of VMWare hypervisors. The vendor is still free to
write their own Puppet modules for managing their OpenStack
implementations. The vendor is free to ignore Puppet all together
while still choosing a completely competent and capable configuration
management tool already in use by the community.</p>
<p>Concerning the learning curve problem, there’s only one explanation
that makes sense to me. I think he left out some words. I think he
meant something like “… the learning curve [for him and his <span class="caps">PRODUCT</span>
team] was higher using them than with his company’s package.” That
makes much more sense to me. It’s a tale as old as software
development. I’ve seen it in my own lifetime more than I care to
remember. It’s called <a href="http://en.wikipedia.org/wiki/Not_invented_here"><span class="caps">NIH</span> Syndrome</a>, and it goes a little something
like this: “we don’t have time to learn [<span class="caps">INDUSTRY</span> <span class="caps">STANDARD</span> <span class="caps">PACKAGE</span>],
so we’re going to write our own instead.” </p>
<p>Because ignoring thousands of person hours worked by experts in the field
of that tiny portion of the domain will surely pay off in the long run
when your small team of generalists attacks the same problem for two weeks. </p>
<p>I’ve also heard trust arguments against existing components. “We
didn’t write it ourselves, so how can we trust it?” Right. A package
in use all over the world is obviously untrustworthy. That’s why I
write most of my software on a custom home built computer that I
soldered together myself. We’re going to need to make a bulk
transistor order from Radio Shack so I can build enough equipment to
run at scale. <a href="http://cm.bell-labs.com/who/ken/trust.html">It’s the only way to be certain</a>.</p> Digital Speedometer just like KITTTim Freund2013-10-13T20:55:00Z2013-10-13T20:55:00Z/blog/digital_speedometer_just_like_kitt.html
<p><a href="http://en.wikipedia.org/wiki/KITT"><span class="caps">KITT</span></a> captured my imagination when
I was four years old. If you weren’t a child of the 80’s, you may not
know the depths of <span class="caps">KITT</span>’s awesomeness. Gaze carefully at his
<a href="http://en.wikipedia.org/wiki/KITT#Features">feature list</a> and try to
control the swell of emotions that stir deep within you. A “Molecular
Bonded Shell”, a “Third Stage Aquatic Synthesizer”, “Passive Laser
Restraint System”, a built-in <span class="caps">ATM</span>, and an artificially intelligent
personality voiced by
<a href="http://en.wikipedia.org/wiki/William_Daniels">Mr. Feeny</a>. I wanted a
Firebird or Trans Am for years after seeing <span class="caps">KITT</span> in action.</p>
<p>Around the same time that <span class="caps">KITT</span> was on television, my dad was shopping
for a new vehicle to replace his incredibly crappy Buick Skylark.
Although he eventually purchased a totally plain and perfectly
suitable Dodge Ram pickup truck, he considered a couple of different
options before signing on any dotted lines. I’m fairly certain he
test drove a Dodge Daytona, and it mesmerized me. It had a bright,
digital dashboard reminiscent of <span class="caps">KITT</span>’s. The steering apparatus was a
totally boring wheel, but I was willing to overlook it. Not every car
can have a yoke.</p>
<p>Decades later I rented a car with a digital dashboard. Once the
novelty wore off, I was disappointed with the utility of it all. The
two digit speed display required reading. I couldn’t keep tabs on my
speed with my peripheral vision quite like I could in cars with
analog dials.</p>
<p>An analog gauge, whether physically analog or digitally rendered, provides
the moment in time value along with the context of expected and potential
ranges. For instance, the tachometer below shows a potential range
of 0 through 16 thousand <span class="caps">RPM</span>, but the area between 14K and 16K are clearly
marked to indicate potential trouble from running within that range:</p>
<p><a href="http://www.flickr.com/photos/maniya/3971946491/" title="Second Innings by ~FreeBirD®~, on Flickr"><img src="http://farm4.staticflickr.com/3522/3971946491_125de6231f_m.jpg" width="240" height="137" alt="Second Innings"></a></p>
<p>Sidney Dekker talks about this briefly in chapter 14 of <a href="http://www.amazon.com/gp/product/B00BL0OZ0E/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00BL0OZ0E&linkCode=as2&tag=ren-20">The Field Guide to Understanding Human Error</a><img src="http://ir-na.amazon-adsystem.com/e/ir?t=ren-20&l=as2&o=1&a=B00BL0OZ0E" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />. He claims that numeric digital readouts
“can hide interesting changes and events, or system anomalies.”</p>
<p>Why is it, then, that I have produced so many monitoring scripts that
produce little more than a two, or three, or four digit number as
output? The raw numbers are necessary but not sufficient for use in a
production support situation. The numbers must feed into a system
that will graphically provide context over time.</p>
<p>One last thing. It’s <span class="caps">OK</span> if you got a little misty eyed when <a href="http://www.youtube.com/watch?v=YTUuGK7xIUM"><span class="caps">KITT</span> was
dropped into a pit of acid</a>.</p> Buttons and a CollarTim Freund2013-10-05T00:50:00Z2013-10-05T00:50:00Z/blog/buttons_and_a_collar.html
<p>A younger developer complained about our project managers and business
analysts. They never took his ideas seriously, but those same
ideas were golden when spoken by respected team leader. To add a
bit of insult, they usually talked to the team leader immediately
after discounting his input.</p>
<p>He sat across the lunch table, clothed in a bacon themed t-shirt,
flabbergasted by their mistrust of his judgment.</p>
<p><span class="dquo">“</span>Have you considered wearing a shirt with buttons and a collar,
leather shoes, and a matching belt?” </p>
<p>Three eyebrows raised, one each on him and our two comparably young
lunch companions.</p>
<p><span class="dquo">“</span>Like it or not, people judge each other based on looks, and if you
dress like a college kid with virtually zero professional experience,
that’s the way people are going to treat you. Two options spring to
mind: change the way you look or thoroughly destroy their preconceived
notions through stellar results. And not just good results, but
consistent and stunningly fantastic results that can’t be attributed
to luck. Please, perform at that level. But consider getting some
khakis and oxford shirts, because they’ll start working their magic
tomorrow while you build your stunningly fantastic track record over
the coming weeks and months.”</p>
<p><a href="http://www.flickr.com/photos/robie06/4957084370/" title="Order the Dress Shirt by Roberto_Ventre, on Flickr"><img src="http://farm5.staticflickr.com/4106/4957084370_ba30cd38f6_n.jpg" width="320" height="213" alt="Order the Dress Shirt" style="float: right;"></a></p>
<p>I then shared how tragically uncool I was while working my first
internship. Baby-faced and a full 20 years younger than the average
employee in our division, I knew my looks could easily work against
me. I grew a collection of pleated khaki pants, dress shirts,
and polos. It was a bit like my uniform from Bishop Miege High
School, but I also wore a belt and leather shoes that didn’t come with
a swoosh or reflective panels stitched in.</p>
<p>A case study examining the power of clothes appears in
<a href="http://www.amazon.com/gp/product/B002BD2UUC/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B002BD2UUC&linkCode=as2&tag=ren-20">Robert Cialdini’s Influence</a><img src="http://ir-na.amazon-adsystem.com/e/ir?t=ren-20&l=as2&o=1&a=B002BD2UUC" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />:
There’s a guy who violates the law by crosses the street against the
traffic light. Half of the time in a freshly pressed suit, and half
of the time in dirty cotton trousers and a faded t-shirt. </p>
<blockquote>
<p>Like the children of Hamelin who crowded after the Pied Piper,
three and a half times as many people swept into traffic behind
the suited jaywalker.</p>
<p>Influence, Chapter 6, Robert Cialdini</p>
</blockquote>
<p>We haven’t evolved beyond instinctive human nature. Much of our trust
in looks is wrapped up with the tribe mentalities that kept us alive for
thousands of years. You can read more about that in chapter 7 of <a href="http://www.amazon.com/gp/product/B005GSZZ24/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B005GSZZ24&linkCode=as2&tag=ren-20">Olivia Fox Carbane’s The Charisma Myth</a><img src="http://ir-na.amazon-adsystem.com/e/ir?t=ren-20&l=as2&o=1&a=B005GSZZ24" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />.</p>
<p>Note that clothing is a double edged sword in <span class="caps">IT</span>. Some programmers
may refuse to acknowledge your skills if you’re dressed too nicely,
but if you’re just upgrading to buttons and a collar you should be
fairly safe.</p>
<p>What signals are your clothes sending?</p> Graceful UpgradesTim Freund2013-09-22T22:55:00Z2013-09-22T22:55:00Z/blog/graceful_upgrades.html
<p>Dear reader, I’m going to make some educated guesses about you. You
are a software developer, maybe with a bit of operations experience.
You buy computer gear, gadgets, and assorted electronic appliances as
much for fun as for work and utility. You know how much <span class="caps">RAM</span> is in
your computer and how fast it is. You enjoy most upgrades because
upgrades bring new features and fix old bugs.</p>
<p>You are not like your users. Most of your users tolerate computers
and software because managing life without them is tough today. They
buy computers only when they must, and they upgrade software only when
the upgrade is automatic, or when their accountant mentions that the
old version of Quick Books Pro won’t automatically calculate payroll
tax correctly after the first of the month. They are writing,
calculating, and analyzing under deadlines. They may have learned
about skeuomorphic design in the New York Times, but the concept did
little more than raise their eyebrow and elicit a shrug.</p>
<p>Your users organize their lives and work with our software. They
learned to use our systems cautiously, but they’ve grown confident
over time. They trust our software and us by extension. Don’t betray
that trust by radically redesigning a user interface without including
a way to guide users through the changes. If your software includes a
“new user orientation” feature, you’re already ahead of the crowd.
Consider showing that to all of your user after a major upgrade. You,
I, and our friends will quickly swat it away without a second thought,
but our more cautious and careful users will appreciate a hand held
tour of the new interface they’ll command.</p> F5's BIGIP HTTP Health MonitorTim Freund2013-09-17T00:40:00Z2013-09-17T00:40:00Z/blog/f5_bigip_http_monitor.html
<p>There’s a <code>http</code> monitor in F5’s <span class="caps">BIGIP</span> Local Traffic Managers.
Common opinion around the office said that any request returning
<code>200 OK</code> was successful in the eyes of the monitor. We found out
this isn’t the case today.</p>
<p>We deployed a blank index.html file at the root of the web server
since our application runs under a different context, and the health
monitor started to fail. Once we put some content in the file (the
text “Nothing to see here” in our case), everything turned green again.</p>
<p>This information is probably in the docs. I’m publishing it here
mainly for the sake of my own memory.</p> Veewee for Ruby RubesTim Freund2013-09-15T18:10:00Z2013-09-15T18:10:00Z/blog/veewee_for_ruby_rubes.html
<p>Let’s talk about installing Veewee to build virtual machines on
multiple platforms from templates with little to no ruby background.
Ruby professionals will probably do just fine with the <a href="https://github.com/jedi4ever/veewee/blob/master/doc/requirements.md">install
instructions</a>
provided by the project. Stick around if you’re a system
administrator, operations engineer, or non-ruby developer interested
in installing veewee. </p>
<p>We’re going to follow along with veewee’s installation instructions,
but I’m also going to provide some commentary and direction as I
received it from <a href="http://lostapathy.com/">someone who writes software with ruby on a daily
basis</a>.</p>
<p>After installing required operating system packages we come to the
first fork in the road. Two options with a silent third option
exist for managing our Ruby environment:</p>
<ol>
<li><a href="http://rvm.io"><span class="caps">RVM</span></a> (preferred by Veewee)</li>
<li><a href="https://github.com/sstephenson/rbenv">rbenv</a> (preferred by Joe)</li>
<li>No environment management (preferred by no one sane)</li>
</ol>
<p>Number three is an option in the technical sense only. Don’t think
it’s a wise idea to stink up the system Ruby installation with
custom gems. You’re entering a world of pain.</p>
<p><span class="caps">RVM</span> felt a little weird to me, but I chalked that up to being a Ruby
rube. Joe told me that he dropped <span class="caps">RVM</span> years ago for rbenv and hasn’t
looked back. Those two factors pushed me to switch to rbenv, but your
mileage may vary. For the python folks in the room, you can equate
(<span class="caps">RVM</span> || rbenv) + <a href="http://bundler.io/">Bundler</a> to virtualenv + pip. </p>
<p>I followed the rest of the
<a href="https://github.com/jedi4ever/veewee/blob/master/doc/installation.md">installation</a>,
<a href="https://github.com/jedi4ever/veewee/blob/master/doc/commands.md">command
options</a>,
and
<a href="https://github.com/jedi4ever/veewee/blob/master/doc/basics.md">basics</a>
pages. Everything worked, and I created several virtual machines using
the <span class="caps">KVM</span> plugin, but it didn’t quite feel right. I didn’t see anywhere in
the docs an explanation of how to separate my work from their work.<br />
Templates and definitions lived inside of the veewee source directory,
and “bundle exec veewee” only worked within that directory. </p>
<p>Aside from the ugliness of polluting a directory full of upstream
source with my own stuff that I never intended to contribute back, I
really wanted a nice way to manage separate repositories of templates
and definitions for my personal use and work use. </p>
<p>I saw reference to Veeweefiles in the docs, but not much information
on how to use them to customize runtime configuration. Digging in to
the code, environment.rb specifically, there was a reference to a
VEEWEE_DIR environment variable. Setting that allowed me to run
<code>bundle exec veewee</code> from the veewee source directory, but use
templates, definitions, and isos in a separate directory. Excited
about this new development, I shared the news with some folks in <span class="caps">IRC</span>.</p>
<p>Joe again stepped in to let me know that I was just barely catching
up to the crowd, and not even in a very ideal way. </p>
<p><span class="dquo">“</span>make a gemfile that includes veewee, run bundle it, then the above
command [works in your personal directory for templates and definitions]”</p>
<p>I ended up with a directory structure like so:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre>tim@gauss:~/src/veewee-freund<span class="nv">$ </span><span class="nb">pwd</span><br />/home/tim/src/veewee-freund<br />tim@gauss:~/src/veewee-freund<span class="nv">$ </span>find . <br />.<br />./definitions<br />./definitions/custom-ubuntu-definition<br />./definitions/custom-ubuntu-definition/base.sh<br />./definitions/custom-ubuntu-definition/chef.sh<br />./definitions/custom-ubuntu-definition/cleanup.sh<br />./definitions/custom-ubuntu-definition/definition.rb<br />./definitions/custom-ubuntu-definition/preseed.cfg<br />./definitions/custom-ubuntu-definition/puppet.sh<br />./definitions/custom-ubuntu-definition/ruby.sh<br />./definitions/custom-ubuntu-definition/vagrant.sh<br />./definitions/custom-ubuntu-definition/virtualbox.sh<br />./definitions/custom-ubuntu-definition/vmfusion.sh<br />./definitions/custom-ubuntu-definition/vmtools.sh<br />./definitions/custom-ubuntu-definition/zerodisk.sh<br />./Gemfile<br />./Gemfile.lock<br />./iso<br />./templates<br />./templates/ubuntu-12.04.2-server-amd64<br />./Veeweefile<br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<p>With a very short Gemfile:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="n">source</span> <span class="s2">"http://rubygems.org"</span><br /> <br /><span class="n">gem</span> <span class="s2">"veewee"</span><br /><span class="n">gem</span> <span class="s2">"ruby-libvirt"</span><br /></pre></div><br /><figcaption>Ruby</figcaption></figure></div>
<p>And a minimal Veeweefile</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="ss">Veewee</span><span class="p">:</span><span class="ss">:Config</span><span class="o">.</span><span class="n">run</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span><br /> <br /> <span class="c1"># Initialize convenience vars</span><br /> <span class="n">cwd</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="bp">__FILE__</span><span class="p">)</span><br /> <span class="n">env</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">veewee</span><span class="o">.</span><span class="n">env</span><br /> <br /> <span class="c1"># These env settings will override default settings</span><br /> <span class="c1">#env.cwd = cwd</span><br /> <span class="c1">#env.definition_dir = File.join(cwd, 'definitions')</span><br /> <span class="n">env</span><span class="o">.</span><span class="n">template_path</span> <span class="o">=</span> <span class="o">[</span><span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cwd</span><span class="p">,</span> <span class="s1">'templates'</span><span class="p">)</span><span class="o">]</span><br /> <span class="c1">#env.iso_dir = File.join(cwd, 'iso')</span><br /> <span class="c1">#env.validation_dir = File.join(cwd, 'validation')</span><br /> <span class="c1">#env.tmp_dir = "/tmp"</span><br /> <br /><span class="k">end</span><br /></pre></div><br /><figcaption>Ruby</figcaption></figure></div>
<p>And it seems to all work. Just to be clear: </p>
<ol>
<li>Create a new directory for your veewee work.</li>
<li>Drop the Gemfile and Veeweefile above in the directory.</li>
<li>Run bundle install</li>
<li>Optionally alias veewee=”bundle exec veewee”</li>
<li>Create templates and define boxes to your heart’s content.</li>
</ol> Weird Ruby behavior somewhat explainedTim Freund2013-09-12T23:01:00Z2013-09-12T23:01:00Z/blog/weird_ruby_behavior_semi_explained.html
<p>The djsd binary wasn’t installed with the executable bit set when I
installed it from the
<a href="https://github.com/glenbot/dotjs-ubuntu.git">dotjs-ubuntu</a>
repository. I’m running Ubuntu 12.04 on my desktop. Before
submitting a drive by pull request I tested 13.04, and it worked fine.
At this point I assumed it was either a version difference or
something wonky in my environment. </p>
<p>Testing on a clean 12.04 virtual machine pointed directly at my
environment. What was the difference? The machines that worked were
using the system provided ruby interpreter. The machine that didn’t
was using an <span class="caps">RVM</span> supplied ruby interpreter. I’m sure there’s more to
it than that, but as an infrequent ruby coder that’s all I needed to
know before deleting my dotjs-ubuntu fork and calling off the hounds.</p>
<p>And if you aren’t using dotjs, well, you should. It’s awesome. You
can inject javascript on a site by site basis. For instance, here’s
what keeps me from spending stupid amounts of time browsing imgur:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="nx">$</span><span class="p">(</span><span class="s1">'.post a'</span><span class="p">).</span><span class="nx">css</span><span class="p">(</span><span class="s1">'visibility'</span><span class="p">,</span> <span class="s1">'hidden'</span><span class="p">);</span><br /><span class="nx">$</span><span class="p">(</span><span class="s1">'div.jcarousel ul li a'</span><span class="p">).</span><span class="nx">css</span><span class="p">(</span><span class="s1">'visibility'</span><span class="p">,</span> <span class="s1">'hidden'</span><span class="p">);</span><br /></pre></div><br /><figcaption>JavaScript</figcaption></figure></div>
<p>That file lives at ~/.js/imgur.com.js, and it removes links to
other images on any page served by the site. </p>
<p>It’s a compromise: In the past I’d block the site in my hosts file,
but friends would send me links to images. I’d oblige by removing the
host entry to view the link then regret that decision later. Will
power is a finite resource, and I can’t click on links that aren’t visible.</p> Link - Great Technical TalksTim Freund2013-09-06T01:45:00Z2013-09-06T01:45:00Z/blog/link_great_technical_talks.html
<p>I stumbled on to <a href="http://blog.testdouble.com/posts/2013-08-29-great-technical-talks.html">Great Technical
talks</a>
just a day before discussing a preliminary tech conference topic
outline with a few teammates.</p>
<p>We’re stressing over content and time constraints. Four guys and two
major configuration management stacks just don’t fit gracefully into
one hour if we’re measuring success by facts stated and demos
executed. Perhaps instead we need a story that will interest the
attendees enough to dig deeper into our small mountain of facts and
demos once they travel back to their respective offices.</p>
<p>We need life cycle management for our technical talk.</p>
<p>Between now and the conference we can</p>
<ol>
<li>Gather a list of people planning on attending our talk</li>
<li>Ask them if they have any particularly dramatic and shareable success or failure stories.</li>
<li>Build resources in the form of documents, demos, and perhaps even
hands on labs</li>
<li>Craft a narrative around the stories from step 2 and our own experiences</li>
<li>Create a survey to gather feedback: in return for an email address
and one to three questions concerning their reaction to the presentation
we then provide links to the supplemental material created in step 3.</li>
</ol>
<p>The presentation then becomes significantly less stressful. We can spend
time practicing a relatively brief story and delivering it well, with
plenty of time left over to field questions and discuss the state of the
art with the audience. They’ll pick up links to the survey on the way
out the door and in return they’ll have a clear list of next actions.</p>
<p>With survey results and email addresses in hand, we can then keep the
conversation moving and help our participants pick up and maintain
momentum. Without this crucial post-conference activity we’ll need
to give the same talk all over again next year.</p>
<p>That’s my theory, at least.</p> I Bet He Got His Bug FixedTim Freund2013-08-22T23:00:00Z2013-08-22T23:00:00Z/blog/i_bet_he_got_his_bug_fixed.html
<p>Gather around kids, and listen to a story about a user looking for
help. Years ago there was a bug report submitted to the MPlayer
project reporting a crash. The user gave a large amount of data to
increase the chances of finding a fix. He gave so much data, in fact,
that his bug report garnered 15 minutes of Internet fame because of
some explicit detail. <a href="http://www.imdb.com/title/tt0307453/">A Shark’s
Tale</a> was on his play list, and
if that wasn’t embarrassing enough, he also had some extremely <span class="caps">NSFW</span>
material right next to it.</p>
<p>MPlayer’s bugzilla installation migrated to a new host years ago, and
I suspect they consciously chose to remove or hide the blush-worthy
bug. I also suspect that once the childish giggling died down that
guy got his bug fixed. Why? Because he provided detail for
examination by the developers.</p>
<p><strong>What happens when a bug or support request arrives without enough detail?</strong></p>
<p>I received a vague bug report this afternoon that didn’t contain
enough detail to recreate. Over the course of 20 minutes we extracted
enough information to solve the problem, but this was only after the
ambiguous bug spent the better part of a month in queue with everyone
raising an eyebrow, shrugging, and moving on to more fertile debugging pastures.</p>
<p>There’s hardly a thing as too much detail when submitting support
requests. Providing sufficient detail sends two signals:</p>
<ol>
<li>
<p>You’ve put forth effort to fix things yourself, and, short of that,
collect data for the people that will fix things.</p>
</li>
<li>
<p>You value the time of others. The experts assisting you will know
which bits to ignore, but they can’t even get started if they don’t
get enough info in the first place.</p>
</li>
</ol>
<p>And if you insist on seeing the forum threads reporting on the crazy
MPlayer bug report, just search for: mplayer bug report Sharks Tale.
But not at work. Or really ever. It’s silly Internet shenannigans.</p> Redshift Delayed Dimming HackTim Freund2013-08-21T23:15:00Z2013-08-21T23:15:00Z/blog/redshift_hack.html
<p><a href="http://jonls.dk/redshift/">Redshift</a> automatically winds down the
color of my display as day turns to night. I don’t know if it helps
me sleep as the experts say it will, but it cuts down on eye strain
significantly. I only have one gripe: my display gets really red
really early in the evening. That’s not even a fault of the
application. My schedule and the sun share equal blame in the
premature dimming of my screen.</p>
<p>I choose to toggle Redshift off if I’m editing images or styles since
colors matter for those tasks, but I often forget to toggle it on once
I’m done. I wanted a way to make sure that Redshift was enabled an
hour before I go to bed on most nights so that I’d know to wind down.</p>
<p><a href="http://www.freedesktop.org/wiki/Software/dbus/">D-Bus</a> provides a
great conduit for that sort of runtime inter-process communication and
configuration, but Redshift doesn’t yet come with a D-Bus interface.</p>
<p>Three factors join forces that allow me to schedule Redshift display
dimming in a less ideal way:</p>
<ol>
<li>
<p>Redshift listens for <code>USR1</code> signals and toggles dimming on receipt.</p>
</li>
<li>
<p><code>xrandr</code> displays current gamma information (and Redshift dims the display by altering the gamma)</p>
</li>
<li>
<p>Cron scripts run by my user account have access to my XAuthority credentials.</p>
</li>
</ol>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="c">#!/usr/bin/env bash</span><br /> <br /><span class="nb">export </span><span class="nv"><span class="caps">DISPLAY</span></span><span class="o">=</span>:0<br /><span class="nv">current_gamma</span><span class="o">=</span><span class="sb">`</span>xrandr --current --verbose | grep -i gamma | awk <span class="s1">'{print $2}'</span> | head -1<span class="sb">`</span><br /> <br /><span class="k">if</span> <span class="o">[</span> <span class="nv">$current_gamma</span> !<span class="o">=</span> <span class="s1">'1.0:1.0:1.0'</span> <span class="o">]</span><br /><span class="k">then</span><br /><span class="k"> </span><span class="nb">echo</span> <span class="s2">"Redshift is enabled"</span><br /><span class="k">else</span><br /><span class="k"> if</span> <span class="o">[</span> <span class="sb">`</span>ps -ef | grep /usr/bin/redshift | grep -v grep | wc -l<span class="sb">`</span> -eq 0 <span class="o">]</span><br /> <span class="k">then</span><br /><span class="k"> </span><span class="nb">echo</span> <span class="s2">"Redshift isn't running"</span><br /> nohup gtk-redshift 1>/dev/null 2>/dev/null &<br /> <span class="k">else</span><br /><span class="k"> </span><span class="nb">echo</span> <span class="s2">"Redshift is running but toggled off"</span><br /> killall -s <span class="caps">USR1</span> /usr/bin/redshift<br /> <span class="k">fi</span><br /><span class="k">fi</span><br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<p>In an ideal world I’d add D-Bus support to Redshift for a more elegant
solution and a fun bit of C programming. It’s on my “someday maybe”
list for a time when I can afford to fumble with a language I last
used around 2004. In the meantime, this inelegant shell script does
the job and gets me back to work on more pressing projects. Maybe
it’ll work for you, too.</p> LDAP Authentication for Pyramid Web ApplicationsTim Freund2013-08-18T20:21:00Z2013-08-18T20:21:00Z/blog/ldap_auth_for_pyramid.html
<p>This is a brain dump of the state of <span class="caps">LDAP</span> authentication for Pyramid
web applications as best I can discern. Send corrections and additions
my way.</p>
<p>There are two ways of authenticating against an <span class="caps">LDAP</span> source referenced
directly and indirectly in the Pyramid docs. </p>
<ul>
<li><a href="http://code.gustavonarea.net/repoze.who.plugins.ldap/">repoze.who.plugins.ldap</a> via <a href="http://docs.repoze.org/who/2.0/">repoze.who</a> and <a href="http://docs.pylonsproject.org/projects/pyramid_who/en/latest/">pyramid_who</a></li>
<li><a href="http://docs.pylonsproject.org/projects/pyramid_ldap/en/latest/">pyramid_ldap</a></li>
</ul>
<h4>repoze.who.plugins.ldap via repoze.who and pyramid_who</h4>
<p>There’s no explicit mention of <span class="caps">LDAP</span> support in the <code>pyramid_who</code>
documentation, but a search for “repoze.who ldap” comes up with the
<code>repoze.who.plugins.ldap module</code>.</p>
<p>The last public commit on the <code>repoze.who.plugins.ldap</code> module was
over <a href="https://code.launchpad.net/repoze.who.plugins.ldap">three years ago on July 22, 2010</a>, and the requirements listed for
the development branch explicitly request versions of <code>repoze.who</code>
greater than or equal to 1.0.6 and less than 2.0dev. The
<code>repoze.who</code> library’s latest release is 2.2, so there’s probably a
bit of work to bring the <span class="caps">LDAP</span> plugin into the present. </p>
<p>The other end of the requirements chain is <code>pyramid_who</code> itself.
This is the glue layer that wires <code>repoze.who</code> into Pyramid web
applications, and it was last updated on April 2, 2012. Not quite
abandonware in the same way as the <span class="caps">LDAP</span> plugin, but the
<a href="https://github.com/Pylons/pyramid_who/commits/master">last two commit messages are “hail mary” and “endless-piss-me-the-!@#$-off”</a>.
It may still work, but I suspect it won’t be updated as Pyramid
continues to evolve.</p>
<h4>pyramid_ldap</h4>
<p>Initial investigation looks promising for <code>pyramid_ldap</code>. It’s working
for user authentication against our Unix <span class="caps">LDAP</span> directory and our <span class="caps">MS</span>
Active Directory instances in the office. </p>
<p>A coworker had some trouble with group retrieval against our Active
Directory, but that wasn’t the library’s fault. Our distinguished
names look something like <code>CN=Freund,
Timothy,OU=Employees,DC=example,DC=com</code>. That comma in our names is
the tricky bit. I don’t see many references to escaping inline commas,
so I suspect we’re in the minority for using <code>CN</code> in our
distinguished names. </p>
<p>If you’re struggling with the same issue, here are two takes on it:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre>ldapsearch -D my_service_account@example.com <span class="se">\</span><br /> -w <span class="s1">'my_awesome_password'</span> <span class="se">\</span><br /> -h adhost01.example.com -p 3268 <span class="se">\</span><br /> -s sub -b <span class="s1">'<span class="caps">DC</span>=nicusa,<span class="caps">DC</span>=com'</span> <span class="se">\</span><br /> <span class="s1">'(&(objectCategory=group)(member=<span class="caps">CN</span>=Freund\\, Timothy,<span class="caps">OU</span>=Employees,<span class="caps">DC</span>=example,<span class="caps">DC</span>=com))'</span><br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="c"># The double backslash gives us one backslash</span><br /><span class="c"># once python's internal escaping mechanism runs,</span><br /><span class="c"># and that single backslash in front of 5C, the </span><br /><span class="c"># hex code for a backslash, ensures that the </span><br /><span class="c"># following comma is escaped in the <span class="caps">LDAP</span> query.</span><br /><span class="nb">filter</span> <span class="o">=</span> <span class="s">'(&(objectCategory=group)(member=<span class="caps">CN</span>=Freund</span><span class="se">\\</span><span class="s">5C, Timothy,<span class="caps">OU</span>=Employees,<span class="caps">DC</span>=example,<span class="caps">DC</span>=com))'</span><br /></pre></div><br /><figcaption>Python</figcaption></figure></div>
<h4><a href="http://pythonhosted.org/django-auth-ldap/">Django Authentication Using <span class="caps">LDAP</span></a></h4>
<p><span class="caps">LDAP</span> authentication in Pyramid is the topic at hand. How does <code>django-auth-ldap</code>
enter into the mix at all? Because the Django folks look like they
have a really nice library for <span class="caps">LDAP</span> authentication.</p>
<p>The <a href="https://bitbucket.org/psagers/django-auth-ldap/commits/all">commit log is active</a>.</p>
<p>The <a href="http://pythonhosted.org/django-auth-ldap/index.html">docs look comprehensive</a>.</p>
<p>They <a href="http://pythonhosted.org/django-auth-ldap/groups.html">are aware of the multitude of <span class="caps">LDAP</span> group schemas</a>.</p>
<p>A cursory look at the project shows that the <span class="caps">LDAP</span> code is fairly well
abstracted from the Django code. If <code>pyramid_ldap</code> lets you down,
<code>django-auth-ldap</code> may be a great place to find a solution to your problem.</p> Outsourced Password HashingTim Freund2013-08-16T00:45:00Z2013-08-16T00:45:00Z/blog/password_hashing.html
<p>The <a href="http://pythonhosted.org/passlib/new_app_quickstart.html">PassLib New Application Quickstart
Guide</a>
reveals more information about password hashing than I knew at all
before reading the page. Hashing and cryptography are two different
things, but, as with crypto code, it’s best to leave password hashing
to someone who knows the subject front and back.</p>
<p>I spent some time reading through the hashing routine in an old
application to build an administrative password reset tool. We salt,
and we use a decent hashing algorithm, but the code isn’t nearly as
sophisticated as what we’d get with the default context provided by PassLib. </p>
<p>Here’s a preferential order of password storage algorithms:</p>
<p><strong>-2.</strong> Passwords stored in plain text<br/>
<strong>-1.</strong> Passwords reversibly encrypted<br/>
<strong>0.</strong> Passwords naively hashed with a weak algorithm<br/>
<strong>1.</strong> Passwords salted and hashed<br/>
<strong>2.</strong> Passwords salted and hashed with a carefully chosen algorithm and procedure<br/></p>
<p>Users will reuse passwords in your application. Storing weakly
hashed or encrypted passwords opens your users’ email, social media,
shopping, and banking accounts to fraud and abuse should your
application ever be compromised. Users hate that. Don’t let
your users hate you over something so easy to do well with the
help of open source libraries.</p> Get a Routed KVM Network Talking to the Internet with DD-WRT and NATTim Freund2013-08-08T09:25:00Z2013-08-08T09:25:00Z/blog/kvm-routed-network-dd-wrt.html
<p>Today we configure a <span class="caps">DD</span>-<span class="caps">WRT</span> router to allow servers on a <span class="caps">KVM</span>
virtual routed network access to the local network and the internet.</p>
<p>If you’ve found entry #3 in <a href="http://wiki.libvirt.org/page/Guest_can_reach_host,_but_can't_reach_outside_network#3.29_The_libvirt_network_has_.3Cforward_mode.3D.27route.27.2F.3E_and_the_outside_network_doesn.27t_have_a_route_to_reach_libvirt.27s_virtual_network">this libvirt networking <span class="caps">FAQ</span></a> and you’re now
searching for the solution, you may be close.</p>
<p>First, we need to let the <span class="caps">DD</span>-<span class="caps">WRT</span> router know about the new network.
This is under Setup -> Advanced Routing on my Buffalo device, and
hopefully not far from there on your device.</p>
<p>Under “Static Routing” fill in appropriate values:</p>
<ul>
<li>Route Name: your choice</li>
<li>Destination <span class="caps">LAN</span> <span class="caps">NET</span>: the network address of your <span class="caps">KVM</span> virtual routed network.</li>
<li>Subnet Mask: Probably 255.255.255.0, but you’ll know better if it isn’t.</li>
<li>Gateway: The <span class="caps">LAN</span> address of the host that runs your <span class="caps">KVM</span> virtual routed network.</li>
<li>Interface: <span class="caps">LAN</span> <span class="amp">&</span> <span class="caps">WLAN</span></li>
</ul>
<p><img src="/media/images/articles/routed-kvm-and-ddwrt-routing.png"/></p>
<p>Save and apply those settings, then try to ping the router from a
virtual machine on the virtual network and vice versa. Assuming both
pings work, we’re ready for phase two.</p>
<p>Anything on the <span class="caps">LAN</span> can now talk to anything else on the <span class="caps">LAN</span>, but the
virtual machines on the routed virtual network can’t talk to the
Internet yet. Any attempts will time out. This assumes your <span class="caps">DD</span>-<span class="caps">WRT</span>
router does <span class="caps">NAT</span> (Network Address Translation) for hosts on your <span class="caps">LAN</span>
when they access the internet, but you’ll know better if it doesn’t and
you probably wouldn’t be reading this right now.</p>
<p>The <span class="caps">DD</span>-<span class="caps">WRT</span> router knows to apply <span class="caps">NAT</span> to any traffic heading to the
internet originating from the local network configured in the “Setup”
-> “Basic Setup” -> “Network Setup” -> “Router <span class="caps">IP</span>” configuration area.<br />
It does not apply <span class="caps">NAT</span> rules to any traffic originating on any other
network that happens to come its way. </p>
<p>That configuration happens in the “Administration” -> “Commands” area
of the administrative interface.</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre>iptables -I FORWARD -s YOUR.KVM.NETWORK.ADDRESS/24 -j ACCEPT<br />iptables -t nat -A <span class="caps">POSTROUTING</span> -j <span class="caps">SNAT</span> --source <span class="caps">YOUR</span>.<span class="caps">KVM</span>.<span class="caps">NETWORK</span>.<span class="caps">ADDRESS</span>/24 --to-source <span class="caps">YOUR</span>.<span class="caps">WAN</span>.<span class="caps">IP</span>.<span class="caps">ADDRESS</span><br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<p><img src="/media/images/articles/routed-kvm-and-ddwrt-natconfig.png"/></p>
<p>Click “Save Firewall” so the commands will run after each reboot, and
click “Run Commands” to execute the commands immediately. Once
complete, log in to one of your virtual machines and try to access any
site on the Internet. With any luck it now works. I’m perhaps a bit
lucky because I have a static <span class="caps">IP</span> address at home. I’m not sure how to
dynamically update that command to include the correct <span class="caps">WAN</span> <span class="caps">IP</span> if you
use <span class="caps">DHCP</span>. I’ll offer up the following bit of shell scripting in case
it helps:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre>netstat -nr | grep ^0.0.0.0 | sed -e <span class="s1">'s/0.0.0.0 //'</span> -e <span class="s1">'s/ .*//'</span><br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<p>That dumps the routing table and extracts the default gateway for the
device. I’ll update this post if you can tell me a better way to get
that information.</p> Asking Questions, January 1870 EditionTim Freund2013-08-01T23:14:00Z2013-08-01T23:14:00Z/blog/asking_questions.html
<p>Asking good questions is a learned trait, and asking bad questions
is not a modern phenomenon brought on by Google or Bing, especially
not Bing. </p>
<p>Want proof that this is an age old problem? Check out the January
1870 edition of the Manufacturer and Builder. On page 183 there’s a
12 point article wrapped in a likely fictional story about a guy named
John Smith
named <a href="http://books.google.com/books?id=XPciAQAAMAAJ&lpg=PA183&ots=uEIoIFz5T_&dq=the%20art%20of%20asking%20questions%20%22lazy%20questions%22&pg=PA183#v=onepage&q&f=false">Asking Questions</a></p>
<p>This small dose of history comes from <a href="http://blog.lostartpress.com/2013/07/31/the-art-of-asking-questions-2/">The Art of Asking Questions on the Lost Art Press Blog</a>.</p>
<p>(And if you’re interested in building a sturdy desk or bench, check out <a href="http://blog.lostartpress.com/2013/08/01/instead-of-wrangling-sawstop-comments/">this beast</a>.)</p> devpi For Fast Python Package InstallationTim Freund2013-07-29T00:21:00Z2013-07-29T00:21:00Z/blog/devpi.html
<h3>(I just upgraded to 1.2.1, and I’m updating this doc accordingly)</h3>
<p>Getting <a href="http://tim.freunds.net/blog/apt-cacher-ng.html">Apt-Cacher <span class="caps">NG</span></a>
installed with such little fanfare and such huge payoff put me in a
mood to cache more stuff.</p>
<p>We have an embarrassment of riches when it comes to caching PyPi packages
for a network of hosts. I found four contenders, and I didn’t look very hard.
The long activity history as well as the well written
documentation pushed me toward <a href="http://doc.devpi.net/1.2.1/">devpi</a>.</p>
<p>It’s working so well that I feel no need to try the alternatives. It
installed in a virtualenv, and it behaves under upstart management.</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="c"># /etc/init/devpi.conf</span><br />description <span class="s2">"devpi"</span><br /> <br />setuid www-data<br />setgid www-data<br /> <br />start on runlevel <span class="o">[</span>2345<span class="o">]</span><br />stop on runlevel <span class="o">[</span>!2345<span class="o">]</span><br />respawn<br /> <br /><span class="nb">exec</span> /opt/devpi/bin/devpi-server --host 0.0.0.0 --refresh 3600 --datadir /opt/devpi/data --secretfile /opt/devpi/.secret<br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<p>Then update your pip.conf file:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="c1"># ~/.pip/pip.conf</span><br /><span class="k">[global]</span><br /><span class="na">index-url</span><span class="o">=</span><span class="s">http://your_cache_server:3141/root/pypi/+simple/</span><br /></pre></div><br /><figcaption><span class="caps">INI</span></figcaption></figure></div>
<p>And your .pydistutils.cfg file:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="c1"># ~/.pydistutils.cfg</span><br /><span class="k">[easy_install]</span><br /><span class="na">index_url</span> <span class="o">=</span> <span class="s">http://your_cache_server:3141/root/pypi/+simple/</span><br /></pre></div><br /><figcaption><span class="caps">INI</span></figcaption></figure></div>
<p>(You can run this on your workstation. I have it running on a
separate cache server <span class="caps">VM</span> because I have several hosts that make use of it.)</p> Apt-Cacher NG For Fast Package InstallationTim Freund2013-07-28T14:21:00Z2013-07-28T14:21:00Z/blog/apt-cacher-ng.html
<p>Disposable systems eliminate the variability and cruft that
accumulates over time. I look at some of the long lived dev and test
systems at work, and I cringe because a parade of developers has each
left their mark, and each special touch pushes those environments
further from production. I did it too, and we’re making things
better. Please don’t throw stones at my glass house.</p>
<p><span class="caps">CERN</span>’s Tim Bell put it best when he compared long lived systems to pets
and disposable systems to cattle.</p>
<iframe width="560" height="315" src="//www.youtube.com/embed/-Ykb2j2ojYU" frameborder="0" allowfullscreen></iframe>
<p>To make the disposable cattle model work, the orchestration system
must create and configure new systems in less time than it’d take to
retrofit a long lived pet machine. We won’t wait for new machines
just like we won’t wait for a slow unit test suite to run.</p>
<p><a href="https://www.unix-ag.uni-kl.de/~bloch/acng/">Apt-Cacher <span class="caps">NG</span></a> sits on the
local network and silently proxies and caches requests for Debian or
Ubuntu packages. The first installation of a package will go as quickly
as the Apt-Cacher’s connection to the upstream mirror, but subsequent
installations will run as quickly as the local network link. That’s
typically an order of magnitude or three in throughput.</p>
<p>Apt-Cacher <span class="caps">NG</span> is included in the default repositories for Ubuntu, and
installation is ridiculously easy. Once it is running, client
configuration is also ridiculously easy.</p>
<p>People who use preseed.cfg files (VeeWee, Foreman, or other automatic system
provisioning tools) should add or update the following line:</p>
<pre><code>choose-mirror-bin mirror/http/proxy string http://<your_apt_cacher_ng_server:3142/
</code></pre>
<p>If an existing system nees to be reconfigured, place the following in <code>/etc/apt/apt.conf.d/01proxy</code>:</p>
<pre><code>Acquire::http::Proxy "http://<your_apth_cacher_ng_server>:3142";
</code></pre>
<p>Two notes on alternatives:</p>
<p>I did not pick Apt-Cacher <span class="caps">NG</span> over Apt-Cacher just because of the <span class="caps">NG</span>
designation. My first cache server attempt was <a href="https://help.ubuntu.com/community/Apt-Cacher-Server">Apt-Cacher as laid
out in the Ubuntu community
docs</a>. It
installed easily, but it locked up hard when I tried to run <code>apt-get
update</code> against it.</p>
<p>I knew of but chose to ignore <a href="http://apt-mirror.github.io/">apt-mirror</a>
because I use a very tiny subset of packages. Apt-mirror may be the way
to go if you’re supporting a wide range of systems and use cases.</p> Twelve Factor AppTim Freund2013-07-27T12:30:00Z2013-07-27T12:30:00Z/blog/twelve_factor_app.html
<p>I stumbled on to <a href="http://12factor.net/">The Twelve-Factor App</a>
while reading <a href="http://blog.appfog.com/docker-and-the-future-of-the-paas-layer/">Docker and the Future of the Paas
Layer</a>.
It contains 12 steps to guide the development of a robust application
that can gracefully transition between servers and deployment environments.</p>
<p>It’s not perfect. It’s not a gospel. But it is pretty solid. Spend
the 10 to 20 minutes it will take you to read if deploying code
induces cold sweats.</p>
<p>Maybe once you’re done you can convince me that sending all logs to
<code>stdout</code> is the right thing to do as outlined in <a href="http://12factor.net/logs">Factor
11</a>. It advocates offloading log management
to an external process, and I don’t understand the benefit of that
over a mature logging framework built in to the application. I’m not
convinced, but I’m not unconvincable.</p> Daemonizing while dropping privilegesTim Freund2013-07-22T10:40:00Z2013-07-22T10:40:00Z/blog/daemonizing_while_dropping_privs.html
<p>We <a href="http://tim.freunds.net/blog/daemonizing_with_chroot_jails.html">talked about chroot jails</a>
the last time daemonization came up. This time we’re talking about
privileges and what it means to drop them.</p>
<p><a href="http://www.flickr.com/photos/24905220@N00/3145162135/" style="float: right;" title="Animal Farm by Ben Templesmith, on Flickr"><img src="http://farm4.staticflickr.com/3211/3145162135_9a9492b1b5.jpg" width="321" height="500" alt="Animal Farm"></a></p>
<p>All users are equal, but some users are more equal than others. If
something can be done, root can do it, and some actions can only be
done by root. Root is the only user that can bind to any port under
1024 on a unix or linux host. Apache, or Nginx, or AOLServer can only
bind to port 80 and 443 for the sake of serving web pages if the
processes start as the root user.</p>
<p>Running a webserver as root is fine until someone finds a remote
exploit in the ancient version of Apache that serves your site because
patching is lame and it hurts your uptime. At that point a remote
exploit will take over the root owned web server process and
have practically unlimited access to the system.</p>
<p>That’s why dropping privileges is a thing we can do. A process can
start with root privileges, do just the things that require root
privileges, then immediately give up those privileges and
switch to an unprivileged account. Now a remote exploiter will only
have control of a process running as an unprivileged account, and they’ll
need to put time into finding a root escalation attack rather than jumping
right in to pilfering data from the system.</p>
<p>One note: users can belong to as many groups as the system
administrator sees fit. Run the <code>groups</code> command right now to see
what groups you belong to::</p>
<pre><code>$ groups
tim adm audio video libvirtd admin
</code></pre>
<p>A process that starts life as a root owned process and drops
privileges may not make it through to the other side in all of those
groups. For instance, processes daemonized with the
<a href="https://github.com/zedshaw/python-lust">Python-<span class="caps">LUST</span></a>
toolkit will only belong to the group explicitly specified in the
daemon configuration file. If your process uses resources belonging
to multiple groups in development, you may find that it stops working
when deployed to production and daemonized as a process that drops
privileges during start up.</p>
<p>And just for the record, there’s no excuse for not patching.</p> Monitoring Nuclear Weapons TestsTim Freund2013-07-14T20:00:00Z2013-07-14T20:00:00Z/blog/monitoring_nuclear_weapons_tests.html
<blockquote>
<p>But every increase in sensitivity resulted in a large increase in the
expected number of false alarms. The designers did not understand
that in the monitoring of a test ban treaty, a high false-alarm rate
would be far more troublesome politically than a low detection rate.</p>
<p>… This is the paradox: too much verification may be as bad as too little.</p>
<p>— <cite><a href="http://www.amazon.com/gp/product/0060390395/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0060390395&linkCode=as2&tag=ren-20">Weapons and Hope</a><img src="http://ir-na.amazon-adsystem.com/e/ir?t=ren-20&l=as2&o=1&a=0060390395" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, p.175</cite></p>
</blockquote>
<iframe width="420" height="315" src="//www.youtube.com/embed/cmCKJi3CKGE" frameborder="0" allowfullscreen></iframe>
<p>Scientists and engineers worked on the technical implementation of a
nuclear test ban treaty with little regard for politics. These
professionals made up the top echelon of thought across their areas of
expertise, and they aimed for accuracy. No expense would be spared in
the quest for accurate detection of nuclear blasts regardless of their
size or location.</p>
<p>The rapid escalation inherent in nuclear conflict raised the cost of
inaccurate blast detection to such a level that missing a blast would
actually be preferable to accidentally classifying an earthquake or
other natural event as a blast. Exponentially so if the detection
system was ever wired in to a rapid response system, automated or not.</p>
<p>How rapid is rapid escalation? Most of the people reading this grew
up in the United States. Think back to grade school. Do you remember
the nuclear shelter area in your school if there was one at all? At
Queen of the Holy Rosary grade school it was the 400 square foot art
classroom. It was in the basement, and there were no windows, but
there was also no seal on the door, and no ventilation system, and no
stockpile of food or water. It was a tight fit for art class, and
there were only 21 kids in my grade. That fallout shelter checked a
box on a long and meticulously designed civil defense form, but it
sure as hell wasn’t going to provide any shelter from fallout for the
160 kids and 20 staff members in the building if the need arose.</p>
<p>That ridiculously undersized and understocked basement room wasn’t an
oversight or a corrupt attempt to save money. It was a conscious
decision driven by the strategies and attitudes of the Cold War.</p>
<blockquote>
<p>Shelters are perceived to be futile because the assured destruction
strategy demands that they be ineffective. [Capable] Shelters are
perceived to be threatening because they suggest an intention to make
the operation of assured destruction unilateral.</p>
<p>—<cite><a href="http://www.amazon.com/gp/product/0060390395/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0060390395&linkCode=as2&tag=ren-20">Weapons and Hope</a><img src="http://ir-na.amazon-adsystem.com/e/ir?t=ren-20&l=as2&o=1&a=0060390395" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></a>, Chapter 8, p. 90</cite></p>
</blockquote>
<p><span class="dquo">“</span>A strange game. The only winning move is not to play.”</p>
<iframe width="420" height="315" src="//www.youtube.com/embed/NHWjlCaIrQo" frameborder="0" allowfullscreen></iframe>
<p>Monitoring enterprise <span class="caps">IT</span> beats us all down at times, but no one dies
in the course of our experimentation. Tweet about how much
#monitoringsucks all you want. Get it out of your system and then
recall that we have the power and time to make things better without
killing most of the human population.</p>
<p>Small changes made frequently makes monitoring suck less, so make
some changes. Just don’t kill anyone.</p> Daemonizing with chroot jailsTim Freund2013-07-09T00:08:00Z2013-07-09T00:08:00Z/blog/daemonizing_with_chroot_jails.html
<p><a href="https://bitbucket.org/timfreund/diffenbach">Diffenbach</a> runs in two
modes: debug mode, where it stays attached to the current session and
terminal, and daemon mode, where it detaches and runs silently in the
background. Now it does, at least. </p>
<p>Until a week ago it only ever ran in debug mode in a tmux
session. That’s pretty lame. The daemonization with
<a href="https://github.com/zedshaw/python-lust">Python-<span class="caps">LUST</span></a> was “done” in
that hand wavy sense that some developers use. I had written the
code, but I hadn’t tested it and worked out all of the kinks.
<a href="http://www.julython.org/teams/kcshoptalk/">Julython</a> came to the
rescue, and the Python-<span class="caps">LUST</span> integration started working five
commits later.</p>
<p>Python-<span class="caps">LUST</span> defaults to dropping processes into a <a href="http://en.wikipedia.org/wiki/Chroot">chroot
jail</a>. This restricts the
running process to a tiny slice of the entire file system defined in
the process’s configuration file, and it limits several attack vectors
including path traversal and exploitation of local binaries.</p>
<p>File descriptors that are opened before the chroot call are carried into
the chroot environment. Any files or commands that are needed at any
time during the execution of the program must either be opened before the
chroot call or be available within the limited chroot environment.</p>
<p>This includes log files, python modules, output directories, and
external commands called through the os.system interface, and anything
that isn’t opened ahead of time or available within the chroot will
result in a thrown exception.</p>
<p>I decided to forgo the chroot capabilities of the Python-<span class="caps">LUST</span> library
for two reasons:</p>
<ol>
<li>
<p>Diffenbach makes explicit use of external binaries that require
additional shared libraries. The footprint of the chroot environment
gets big enough to negate many of the benefits of running within a
chroot environment. I could compile a static binary of gphoto2 if
I really wanted to run Diffenbach in a chroot environment.</p>
</li>
<li>
<p>Diffenbach is the only custom daemon running on its server, and it
doesn’t run arbitrary code or commands fed to it via remote interfaces.
That significantly lowers the threat level.</p>
</li>
</ol>
<p>I also learned a bit about how dropping privileges works, but I’ll
save that for my next post.
<a href="http://tim.freunds.net/blog/atom.xml">Subscribe</a> if you’re interested
in learning more.</p> Dev and Test, Paste and GunicornTim Freund2013-07-07T10:41:00Z2013-07-07T10:41:00Z/blog/dev_and_test_paste_and_gunicorn.html
<p>I’ve been working under an assumption: <span class="caps">WSGI</span> abstracts away all of the
details of serving up a python web application so well that <span class="caps">WSGI</span> web
server implementations are totally interchangeable without thought or worry. </p>
<p><span class="caps">WSGI</span> is awesome, but not quite that awesome. Abstractions are leaky,
<a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">it’s a law</a>.</p>
<p><a href="https://bitbucket.org/timfreund/ironblogger">IronBlogger</a> development
has picked back up thanks to <a href="http://www.julython.org/">Julython</a>, and
the deployment went as planned until I restarted the process. It got
stuck in an infinite loop of restarting itself, with exceptions thrown
in the database initialization code.</p>
<p>I used the <code>pip freeze</code> command to dump lists of installed software in
each host, and gunicorn was the only additional bit of code in the
production environment. And, sensibly, the only difference outside of
turning off live debugging was the gunicorn configuration:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="k">[server:main]</span><br /><span class="na">use</span> <span class="o">=</span> <span class="s">egg:Paste#http</span><br /><span class="na">host</span> <span class="o">=</span> <span class="s">0.0.0.0</span><br /><span class="na">port</span> <span class="o">=</span> <span class="s">6543</span><br /></pre></div><br /><figcaption><span class="caps">INI</span></figcaption></figure></div>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="k">[server:main]</span><br /><span class="na">use</span> <span class="o">=</span> <span class="s">egg:gunicorn#main</span><br /><span class="na">host</span> <span class="o">=</span> <span class="s">0.0.0.0</span><br /><span class="na">port</span> <span class="o">=</span> <span class="s">6543</span><br /><span class="na">workers</span> <span class="o">=</span> <span class="s">2</span><br /><span class="na">proc_name</span> <span class="o">=</span> <span class="s">ironblogger</span><br /></pre></div><br /><figcaption><span class="caps">INI</span></figcaption></figure></div>
<p>I haven’t figured out exactly what the problem is, but I’m getting close. This
is primarily a public service announcement: test your code with the same server
software that it’ll run on in production. Abstractions are leaky, and it
may work for a while, but one day it won’t.</p> Back Behind the KeyboardTim Freund2013-06-30T23:41:00Z2013-06-30T23:41:00Z/blog/back_behind_the_keyboard.html
<p>I’m back behind the keyboard after a month long sabbatical.<br />
<a href="http://blog.thejwal.com/">Josh Waldron</a> kept us going over at <a href="http://ironblogger.freunds.net/kc/activity">Iron Blogger</a>, and I thank him for his service.</p>
<p>I have no excuse for letting my writing habit fall apart while I
burned some vacation time in Kansas City with home renovation work,
but the time was well spent. The first week was 100% physical labor
any time the sun was up, and I spent the following two weeks juggling
office time and physical labor. I can’t recall the last time that I
slept so well. </p>
<p>We took a worn and tired garage from this:</p>
<p><a href="http://www.flickr.com/photos/timfreund/9181114290/" title="IMG_1378-20130601-090315 by timfreund, on Flickr"><img src="http://farm8.staticflickr.com/7321/9181114290_3d253d41b8.jpg" width="500" height="375" alt="IMG_1378-20130601-090315"></a></p>
<p>Through this:</p>
<p><a href="http://www.flickr.com/photos/timfreund/9178904481/" title="IMG_1392-20130602-181957 by timfreund, on Flickr"><img src="http://farm4.staticflickr.com/3800/9178904481_baccff25fe.jpg" width="500" height="375" alt="IMG_1392-20130602-181957"></a></p>
<p>To this:</p>
<p><a href="http://www.flickr.com/photos/timfreund/9178905803/" title="IMG_1401-20130615-162931 by timfreund, on Flickr"><img src="http://farm6.staticflickr.com/5488/9178905803_ddbf308580.jpg" width="500" height="375" alt="IMG_1401-20130615-162931"></a></p>
<p>And I ate some of these in the process:</p>
<p><a href="http://www.flickr.com/photos/timfreund/9181119280/" title="IMG_1407-20130619-114326 by timfreund, on Flickr"><img src="http://farm8.staticflickr.com/7333/9181119280_4a46b70d17.jpg" width="500" height="375" alt="IMG_1407-20130619-114326"></a></p>
<p>(More on those tasty hunks of pork later!)</p> Steak and LobsterTim Freund2013-05-31T10:41:00Z2013-05-31T10:41:00Z/blog/steak_and_lobster.html
<p>I’ve never cruised before. I don’t get excited about beaches, boats,
or the ocean, so cruises cost a lot of money for 24x7 access to food
and quiet time to read. I caught a thread on reddit concerning the
<a href="http://www.reddit.com/r/technology/comments/1f0trx/how_the_smartphone_killed_the_threeday_weekend/">death of nights and weekends for tech
workers</a>.
A few tech workers commented that cruises were the only way they found
peace on vacation, because most problems can be solved by
the crew in the office if it costs $10/minute to talk to the guy
vacationing on a boat. Concerning food, “either/or” was not a part of
the lexicon, but “and” was:</p>
<p><img src="/media/images/articles/steak_and_lobster-reddit.png"/></p>
<p>I’m tempted to catch an off season deal and embark while wearing old
man style pants with elastic waistbands just for the sport of it all. </p>
<p>We have our own steak and lobster moments. Python or Ruby? Both.
Emacs or vim? Both. Java or C#? Both. Debian or Red Hat? Both.
MySQL or Postgres? Postgres.</p>
<p>If there are zero additional constraints or prejudices coloring such a
question, the best options are to flip a coin and get busy working or
run a small experiment with both to form a stronger foundation for a
real decision. We aren’t getting married to any technology, and each
choice is both excellent and terrible depending on the problem at hand. </p>
<blockquote>
<p>Should I learn Python or Ruby for freelancing? </p>
</blockquote>
<p>Both. Or neither. Clients either have a technology in mind already
or they will be confused and scared that specific technologies come up
in the proposal process at all. The Rails shop that needs an extra
hand wants a coder that knows Rails. The dentist that needs an
appointment reminder system does not care about programming and
programming languages as long as his missed appointment ratio looks
better by the end of the quarter.</p>
<p>Most importantly, recall that my opinion in this matter is worth
very little.</p>
<blockquote>
<p>My opinion about barbell rows is as follows: **** barbell
rows. Really. **** them. Stop wasting time worrying about barbell rows
and get your deadlift up to 500. By then you’ll have your own opinion
and you won’t have to worry about mine.</p>
<p>— Mark Rippetoe</p>
</blockquote> The Office Powerball PoolTim Freund2013-05-19T23:00:00Z2013-05-19T23:00:00Z/blog/office_powerball.html
<p>My dad has played Powerball twice a week since it entered the state of
Kansas. I don’t ask about how much he’s won over the years, because
I’m certain that I don’t want to know. The game wouldn’t exist if it
payed out more than it brought in, so it just doesn’t make much sense. </p>
<p><span class="dquo">“</span>But someone’s gotta win, and it might be me.” </p>
<p>I make one exception, and that’s the office Powerball pool that starts
up once the jackpot gets fairly high. Even then, I don’t play because
I think we’ll win. I play just in case we win as an insurance premium
on being left behind. I don’t want to be the guy left behind when
half of the technical team is no longer financially obligated to show
up every day.</p>
<p><a href="http://www.investinged.com/100-invested-in-100-1-lottery-tickets/#axzz2TnNGwojn">$100 Invested in 100 $1 Lottery Tickets</a> made it to the front page of Hacker News the
other day. I read it, thinking the whole time my dad’s experience
with the lottery. And then I recalled our latest office pool stats:</p>
<ul>
<li>29 people</li>
<li>$5 each (+ an extra dollar from the pool leader to get us an even number)</li>
<li>Two runs at the jackpot at $146 each.</li>
<li>$26 in winnings. </li>
</ul>
<p>Any money won in one drawing is rolled into the next “until we hit the
big one.” We’ve developed a system for efficiently turning any sum of
money into zero dollars. The more we lose, the more it feels like the
insurance premium that it is. I keep paying, and I’ll probably never
use it, but I dread facing the on-call rotation while we ramp up staff
if the pool ever hits.</p> If you want to be a great developerTim Freund2013-05-09T22:55:00Z2013-05-09T22:55:00Z/blog/if_you_want_to_be_a_great_developer.html
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=ren-20&o=1&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=0471281395" style="float:right;width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<blockquote>
<p>If you want to be a well-paid copywriter, please your client.</p>
<p>If you want to be an award winning copywriter, please yourself.</p>
<p>If you want to be a great copywriter, please your reader.</p>
<p>— Steve Hayden, found in chapter 2, page 21 of Hey Whipple, Squeeze This</p>
</blockquote>
<p>The software guys and ad guys don’t often mingle in most companies,
but that small piece of copy writing advice fits us well. Don’t build
a resume builder. Don’t build a portfolio piece. Build a project
that pleases the user and the other trappings of success will follow.</p>
<p>We can dazzle our peers with patterns, No-<span class="caps">SQL</span> databases, and the
latest JavaScript <span class="caps">MVC</span> technology, but our success will ring hollow if
the users don’t understand the damn thing. No user has once
complimented me on my choice of data access technology, despite the
ridiculous number of hours that I’ve spent fighting those components
through the years. They just want the data to arrive quickly and
correctly. Likewise, our clients aren’t impressed by thorough testing
and deployment procedures, but they are impressed by rapid turnaround
on bugs and feature requests.</p>
<p>Stepping back for a moment, why is a software guy burning time with a
classic book in the advertising industry? I don’t know what got me
started, but I’m glad I finished. Something somewhere on the Internet
pointed me toward this book years ago, and I just found it while
unpacking boxes after a move. Sixty-two notes and excerpts later, I
recommend it to any developer looking to expand their education beyond
a single threaded focus on technology. Old editions are still
available for the cost of shipping, and there’s a new edition that is
available for the Kindle.</p>
<p>Here’s one more of my six excerpts from chapter 2:</p>
<blockquote>
<p>They’ll quickly find you boring or irrelevant if all you can speak
about with authority is nginx configurations and WebSockets. Your
grasp of the client’s technology situation has to be as well versed as
any project manager’s. There are no shortcuts. Know the client.
Know their product. Know their market. It will pay off.</p>
<p>— Chapter 2, Hey Whipple, Squeeze This</p>
</blockquote>
<p>Wait, sorry, I copied that wrong. Can you make the following substitutions?</p>
<ul>
<li>s/nginix configurations and WebSockets/Century Italic/</li>
<li>s/technology situation/marketing situation/</li>
<li>s/project manager’s/account executive’s/</li>
</ul>
<p>Universal stuff. It just takes a little bit of mental search and replace.</p> Books and NotesTim Freund2013-05-07T00:10:00Z2013-05-07T00:10:00Z/blog/books_and_notes.html
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=ren-20&o=1&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=0671212095" style="width:120px;height:240px;float: right;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>Take notes in and around the books you read, or you’ll lose most
of the interesting bits in a very short period of time. (And please
don’t tell me that you “aren’t a reader.” It’ll just make me sad.)</p>
<p>There’s a book called How to Read a Book. It’s thick. The authors
had serious intentions of improving the quality of reading. I respect
that, but with a single eyebrow raised, I first thought “learn how to
read a book so you can learn how to read a book from the book Learn
How to Read a Book.” Childish of me. I hope they had some fun during
the editing process with a dummy draft:</p>
<blockquote>
<p><em>How to Read a Book</em>
You’re doing it now. Keep going!
[page break]
Excellent, you’ve found us over here. That’s about it: left
to right, top to bottom.</p>
</blockquote>
<p>In fact, that’s the problem they’re trying to solve. Most of us
measure reading skill in speed from start to finish with little
attention paid to comprehension or retention.</p>
<p>Someone much smarter convinced me to pick up a copy in 2010 despite my
initial skepticism. Of all the tips, techniques, and suggestions,
taking notes changed my retention and comprehension the most. Marking
notes in the margins felt criminal at first, but it’s now so
fundamental to my process that I rarely read anything if I don’t have
a pencil.</p>
<p>Amazon’s used marketplace is a great source of deals that keeps my
reading habit below the expense reporting radar in our family budget.
Through this informal research channel, I know that people fall
into two camps with notes and markings: either no marks at all, or
everything is underlined haphazardly, often with a yellow highlighter
or ink pen. </p>
<p>One interesting fact about the over-enthusiastic underliners: their
notes often stop entirely by chapter 3, and that means they missed
most of the good stuff. I’ve also learned that some Amazon sellers
don’t share my definition of “Used - Like New”, but that’s a different
soap box rant.</p>
<p>For the sake of note-free readers and over-highlighting readers alike,
here are just a few tips that have served me well.</p>
<h3>Use a Pencil</h3>
<p>Pencil is erasable. That may come in handy. </p>
<h3>Underline judiciously.</h3>
<p>Underlining entire paragraphs is a complete waste of time. Quit it.
Is the entire paragraph really profound? Will it be worth reading
again in its entirety when skimming the book in the future?</p>
<p>Are the underlined words key words that require definition, or are
they just words that you happen to recognize and you get swept up in
the excitement? I owned a book where the previous owner was probably
a “Data Manager” because every occurrence of the words “Data Manager”
in the first three chapters was circled. Not helpful.</p>
<p><img src="/media/images/articles/books_and_notes-stupid_word_highlight.JPG"/></p>
<p>Concisely underline the interesting and the new. </p>
<h3>Use vertical lines to highlight paragraphs</h3>
<p>Maybe there’s a passage that only makes sense in the context of one or
more full paragraphs, and you want to find it again on your next time
through the book. Use vertical lines in the margin to highlight those
paragraphs rather than tediously underlining everything. Think about
the time it would take to draw a vertical line next to this paragraph
rather than underlining everything within the paragraph:</p>
<p><img src="/media/images/articles/books_and_notes-whole_page.JPG"/></p>
<p>Now, go read a book.</p> Build Application Packages with FPMTim Freund2013-05-01T01:55:00Z2013-05-01T01:55:00Z/blog/build_application_packages_with_fpm.html
<p><a href="https://github.com/jordansissel/fpm"><span class="caps">FPM</span></a> changed the way I think
about packaging. I wrote so many lines of custom deployment code just
to skip packaging our in-house application in the past, and it was
completely justifiable given my previous experience with packaging tools</p>
<p>I mentioned <a href="http://tim.freunds.net/blog/disble_dhcp_in_a_qemu_network.html">last time</a>
that we’re living in the future. Things have changed for the better.</p>
<p>We now use <a href="https://puppetlabs.com/">Puppet</a> for provisioning and
configuration management, and that extends to our in-house
applications running on those servers. We also have internal package
repositories. Packaging pain kept us from fully using this
infrastructure for our in-house applications, but <span class="caps">FPM</span> changes that.</p>
<p>Say we have a custom application to package. This isn’t an official
release, it’s just a build triggered by the latest commit, and we have
it laid out on disk just like it should be deployed. Easy:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="nv">timestamp</span><span class="o">=</span><span class="sb">`</span>date +%Y%m%d%H%M<span class="sb">`</span><br /><span class="nv">version</span><span class="o">=</span><span class="sb">`</span>git rev-parse --short <span class="caps">HEAD</span><span class="sb">`</span><br /> <br />fpm -s dir -t rpm -p ~/ourawesomeappliation-0.9.<span class="k">${</span><span class="nv">timestamp</span><span class="k">}</span>git<span class="k">${</span><span class="nv">version</span><span class="k">}</span>.rpm <span class="se">\</span><br /> --name ourawesomeapplication -v 0.9.<span class="k">${</span><span class="nv">timestamp</span><span class="k">}</span>git<span class="k">${</span><span class="nv">version</span><span class="k">}</span> <span class="se">\</span><br /> --prefix /the/place/to/deploy/it --exclude <span class="s1">'*/.git/*'</span> --verbose <span class="se">\</span><br /> --debug .<br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<p>The time stamp ensures that the system can compare versions correctly
since git version hashes aren’t alphabetically ordered.</p>
<p>And for the Mercurial projects out there:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="nv">timestamp</span><span class="o">=</span><span class="sb">`</span>date +%Y%m%d%H%M<span class="sb">`</span><br /><span class="nv">version</span><span class="o">=</span><span class="sb">`</span>hg log . | head -1 | sed -e <span class="s1">'s/.* //'</span> -e <span class="s1">'s/:.*//'</span><span class="sb">`</span><br /> <br />fpm -s dir -t rpm -p ~/ourawesomeappliation-0.9.<span class="k">${</span><span class="nv">timestamp</span><span class="k">}</span>hg<span class="k">${</span><span class="nv">version</span><span class="k">}</span>.rpm <span class="se">\</span><br /> --name ourawesomeapplication -v 0.9.<span class="k">${</span><span class="nv">timestamp</span><span class="k">}</span>git<span class="k">${</span><span class="nv">version</span><span class="k">}</span> <span class="se">\</span><br /> --prefix /the/place/to/deploy/it --exclude <span class="s1">'*/.hg/*'</span> --verbose <span class="se">\</span><br /> --debug .<br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<p>Note that we’re creating <span class="caps">RPM</span> packages above. Also note that the <code>-t</code>
argument defines the OUTPUT_TYPE or target. Swap in <code>deb</code> for <code>rpm</code>
to get a Debian themed party started. Solaris packages are an option,
too. That’s right, some people still deploy more than just Oracle
products on Solaris machines.</p> Disable DHCP on a QEMU/libvirt/KVM NetworkTim Freund2013-04-27T19:25:00Z2013-04-27T19:25:00Z/blog/disble_dhcp_in_a_qemu_network.html
<p><a href="http://libvirt.org/">Libvirt</a> + <span class="caps">QEMU</span> + <span class="caps">KVM</span> allows easy virtualization
on Linux. Virtual machines are placed on a virtual network that comes
complete with a <span class="caps">DHCP</span> server and <span class="caps">DNS</span> forwarder. There’s no reason to
give up these default conveniences until your work involves building
and configuring <span class="caps">DNS</span> and <span class="caps">DHCP</span> servers. Running two <span class="caps">DHCP</span> servers on the
same virtual network is a recipe for frustration.</p>
<p>The configuration files for libvirt are stored in <code>/etc/libvirt</code> by
default, but pretend like they aren’t even there. Read any of the files
and you’ll find a warning:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="c"><!--</span><br /><span class="c"><span class="caps">WARNING</span>: <span class="caps">THIS</span> <span class="caps">IS</span> <span class="caps">AN</span> <span class="caps">AUTO</span>-<span class="caps">GENERATED</span> <span class="caps">FILE</span>. <span class="caps">CHANGES</span> <span class="caps">TO</span> <span class="caps">IT</span> <span class="caps">ARE</span> <span class="caps">LIKELY</span> <span class="caps">TO</span> <span class="caps">BE</span> </span><br /><span class="c"><span class="caps">OVERWRITTEN</span> <span class="caps">AND</span> <span class="caps">LOST</span>. Changes to this xml configuration should be made using:</span><br /><span class="c"> virsh net-edit devservers</span><br /><span class="c">or other application using the libvirt <span class="caps">API</span>.</span><br /><span class="c">--></span><br /></pre></div><br /><figcaption><span class="caps">XML</span></figcaption></figure></div>
<p>They aren’t kidding. Don’t change these files. There’s one other trick:<br />
Running the net-edit command alone won’t really do anything either if the network
is already running. The following operations will do the trick:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre>root@host <span class="c"># virsh</span><br />virsh <span class="c"># net-destroy yournetwork</span><br />virsh <span class="c"># net-edit yournetwork</span><br /><span class="o">[</span>remove the <dhcp></dhcp> element, save, <span class="nb">exit</span><span class="o">]</span><br />virsh <span class="c"># net-start yournetwork</span><br /></pre></div><br /><figcaption>Bash</figcaption></figure></div>
<p>Rumor has it that later versions of the <code>virt-manager</code> <span class="caps">GUI</span> support
these operations, but this info will come in handy if you’re still on
a <span class="caps">LTS</span> system.</p>
<p>Reconnect any hosts that were on the virtual network, because they
aren’t anymore. Configure your own <span class="caps">DHCP</span> server or configure all hosts
with static interfaces as well. Remember that you’re on your own for
<span class="caps">DNS</span> resolution in addition to <span class="caps">DHCP</span> at this point. An easy solution is
to set <code>domain-name-servers</code> in your <code>dhcpd.conf</code> file to your router
or access point.</p>
<p>Now that we’ve wrapped up our business here, I’d like to take a minute
to tell you how happy all this stuff makes me. I’m running a small
colony of machines on my middle of the line desktop computer, and I
can practice the exact same work that happens in real data centers.
Back when I was a newbie every machine was a real, physical machine,
and <span class="caps">PXE</span> booting required careful hardware selection. </p>
<p>We’re living in the future. We just need the Hoverboard design team to
catch up.</p>
<p><a href="http://www.flickr.com/photos/popculturegeek/6039241743/" title="San Diego Comic-Con 2011 - Marty's Back to the Future II hoverboard (Profiles in History booth) by Pop Culture Geek, on Flickr"><img src="http://farm7.staticflickr.com/6070/6039241743_34df9f5637_n.jpg" width="320" height="240" alt="San Diego Comic-Con 2011 - Marty's Back to the Future II hoverboard (Profiles in History booth)"></a></p> Call in the NightTim Freund2013-04-15T01:55:00Z2013-04-15T01:55:00Z/blog/call_in_the_night.html
<p>I learned about <a href="http://callinthenight.com/">Call in the Night</a>
earlier today.</p>
<p>A few years ago I thought it’d be cool to practice dream recall and
eventually start lucid dreaming. With approximately one third of our
lives spent asleep, it seemed like a fun way to pass the time. In the
end, I didn’t think it was fun enough to really change my sleep habits. </p>
<p>The Call in the Night project looks a little interesting just because
it’d be a way to tap into dream recall without waking up and
immediately remembering to journal everything possible, but that’s not
really what struck me the most.</p>
<p>If we’re writing software with a root cause of waking people up, we should
use that power for good. This is obvious, and it’s probably been done:
use <a href="http://twilio.com">Twilio Voice + <span class="caps">SMS</span></a> to send a wake up call. </p>
<ol>
<li>Sleeper receives phone call.</li>
<li>Sleeper hears inspirational text, important business info, personal performance metrics, whatever.</li>
<li>Sleeper receives a random code number and a question, like “what project will receive most of your time today.”</li>
<li>Sleeper texts code number and answer to the wake up service to disable the snooze feature (repeat calls).</li>
</ol>
<p>Or I could just get out of bed on the first alarm. Because just doing
that has worked so well so far. (I’m a 2-3 snoozer, but that can
extend if it’s a weekend and particularly chilly. Rationally I know
this is stupid, but ask me again after a few hours of sleep.)</p> Book - Lead With a StoryTim Freund2013-04-04T12:41:00Z2013-04-04T12:41:00Z/blog/book_lead_with_a_story.html
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=ren-20&o=1&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=B008Z2D5LQ" style="width:120px;height:240px;float:right;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>This book almost lost me several times. Paul told stories. I wanted
tactical advice on crafting great stories. Paul kept telling stories.
There were just enough tactical nuggets throughout the book that I
kept reading. </p>
<p>I read so many uplifting stories about Procter and Gamble that I
momentarily doubted my own career path. Is this a part of a P&G
propaganda machine? The <a href="http://www.manager-tools.com/">Manager Tools</a> and
<a href="http://www.advancedsellingpodcast.com/">Advanced Selling Podcast</a> crews both
have experience with P&G as well. Am I missing out? </p>
<p>Stories are persuasive. Got it. </p>
<p>Paul recommends putting any surprise element at the end of a story to
cement the story into the audience’s memory. In the very last
chapter he got me. My consternation over writing my own stories
melted away as I read:</p>
<blockquote>
<p>The richest source of stories you’ll ever have are the stories you
hear other people tell. There’s only one of you, but about 7 billion
other people in the world. Even if you never create a single personal
story of your own, you can have an endless supply of great stories by
just paying attention to the stories you hear from others.</p>
</blockquote>
<p>All of those stories that were stealing stage time from tactical tips?
They really were the meat of the book. I have a cache of effective
stories now. I should still write my own stories, but I don’t need to
write every story I tell.</p>
<p>Chapter 30 also provided a number of solid tips and lists for getting
started. The tips and lists I craved, but I would have never acted
upon them had I devoured them on their own.</p> SQLAlchemy + ORA-014161Tim Freund2013-04-03T18:55:00Z2013-04-03T18:55:00Z/blog/sqlalchemy_ora-014161.html
<h2>Python, SQLAlchemy and “<span class="caps">ORA</span>-01461: can bind a <span class="caps">LONG</span> value only for insert into a <span class="caps">LONG</span> column”</h2>
<p>If you’re on this page you either read all of my entries regardless of
content (thank you!) or you have the error above.</p>
<p>Look through just about every <span class="caps">ORM</span> and you’ll find special case
handling for Oracle’s large objects. If there’s no special case
handling in the <span class="caps">ORM</span> itself, then you will write some special case code yourself.</p>
<p>SQLAlchemy’s special case handling of Oracle’s large objects is to
automatically load the large objects when retrieving rows from the
database and convert them to strings. This means the database results
object isn’t tethered to the database cursor while you work. It’s
pretty handy, and if you’re just pulling data from the database it
means you may never need to think about how weird Oracle large objects
are compared to “regular” data.</p>
<p>I was reading and writing large objects between two schemas when the
<span class="caps">ORA</span>-014161 surfaced. Since this was a one-time ad-hoc deal, I just
hand crafted some <span class="caps">SQL</span>, and the script looked a little like this:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sqlkeyring</span><br /> <br /><span class="n">sql_keyring</span> <span class="o">=</span> <span class="n">sqlkeyring</span><span class="o">.</span><span class="n">SQLKeyring</span><span class="p">()</span><br /> <br /><span class="n">targetdb</span> <span class="o">=</span> <span class="n">sql_keyring</span><span class="o">.</span><span class="n">get_engine</span><span class="p">(</span><span class="s">'targetdb'</span><span class="p">)</span><br /><span class="n">sourcedb</span> <span class="o">=</span> <span class="n">sql_keyring</span><span class="o">.</span><span class="n">get_engine</span><span class="p">(</span><span class="s">'sourcedb'</span><span class="p">)</span><br /> <br /><span class="n">interesting_results</span> <span class="o">=</span> <span class="n">sourcedb</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">"select * from the_interesting_table"</span><span class="p">)</span><br /><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">interesting_results</span><span class="o">.</span><span class="n">fetchall</span><span class="p">():</span><br /> <span class="n">column_names</span> <span class="o">=</span> <span class="n">row</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span><br /> <span class="n">column_names</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span><br /> <br /> <span class="n">names</span> <span class="o">=</span> <span class="s">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">column_names</span><span class="p">)</span><br /> <span class="n">values</span> <span class="o">=</span> <span class="s">', :'</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">column_names</span><span class="p">)</span><br /> <br /> <span class="n">params</span> <span class="o">=</span> <span class="p">{}</span> <br /> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">row</span><span class="o">.</span><span class="n">items</span><span class="p">():</span><br /> <span class="n">params</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span><br /> <br /> <span class="n">sql</span> <span class="o">=</span> <span class="s">"insert into the_interesting_table(</span><span class="si">%s</span><span class="s">) values(:</span><span class="si">%s</span><span class="s">)"</span> <span class="o">%</span> <span class="p">(</span><span class="n">names</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span><br /> <span class="n">targetdb</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">)</span><br /></pre></div><br /><figcaption>Python</figcaption></figure></div>
<p>And that failed terribly with the following:</p>
<pre><code>"ORA-01461: can bind a LONG value only for insert into a LONG column"
</code></pre>
<p>Of course it did, otherwise we wouldn’t be here now. Since the
values came out of the source database and were converted to strings,
SQLAlchemy then attempted to drop them into the target database as strings.</p>
<p>SQLAlchemy is smart enough to coerce types correctly if we give it
some information about our schema, either explicitly or by asking it
to autoload table metadata. A few changes to the script above and we
were in business without manually hacking together <span class="caps">SQL</span>:</p>
<div class="codebox"><figure class="code"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sqlkeyring</span><br /> <br /><span class="n">sql_keyring</span> <span class="o">=</span> <span class="n">sqlkeyring</span><span class="o">.</span><span class="n">SQLKeyring</span><span class="p">()</span><br /> <br /><span class="n">targetdb</span> <span class="o">=</span> <span class="n">sql_keyring</span><span class="o">.</span><span class="n">get_engine</span><span class="p">(</span><span class="s">'targetdb'</span><span class="p">)</span><br /><span class="n">targetdb_md</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">()</span><br /><span class="n">targetdb_md</span><span class="o">.</span><span class="n">bind</span> <span class="o">=</span> <span class="n">targetdb</span><br /><span class="n">sourcedb</span> <span class="o">=</span> <span class="n">sql_keyring</span><span class="o">.</span><span class="n">get_engine</span><span class="p">(</span><span class="s">'sourcedb'</span><span class="p">)</span><br /> <br /><span class="n">the_interesting_table</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">'the_interesting_table'</span><span class="p">,</span> <span class="n">targetdb_md</span><span class="p">,</span> <span class="n">autoload</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><br /> <br /><span class="n">interesting_results</span> <span class="o">=</span> <span class="n">sourcedb</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">"select * from the_interesting_table"</span><span class="p">)</span><br /><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">interesting_results</span><span class="o">.</span><span class="n">fetchall</span><span class="p">():</span><br /> <span class="n">params</span> <span class="o">=</span> <span class="p">{}</span> <br /> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">row</span><span class="o">.</span><span class="n">items</span><span class="p">():</span><br /> <span class="n">params</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span><br /> <br /> <span class="n">sql</span> <span class="o">=</span> <span class="n">the_interesting_table</span><span class="o">.</span><span class="n">insert</span><span class="p">()</span> <br /> <span class="n">targetdb</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">)</span><br /></pre></div><br /><figcaption>Python</figcaption></figure></div>
<p>About the same number of lines, but less hacky and it actually works
by letting SQLAlchemy do more heavy lifting for us. Since SQLAlchemy
has metadata information for the target table, it knows that any input
for the large object columns will need to be properly converted. </p>
<p>Any tool that successfully abstracts away Oracle large objects is a
good tool in my book.</p> Distractions and Truth In My Shell PromptTim Freund2013-04-02T23:00:00Z2013-04-02T23:00:00Z/blog/distraction_and_shell_prompts.html
<p>My shell prompt doesn’t lie. </p>
<p>I’m a bash user, so I can set <code>$PS1</code> to contain a variety of useful
information, and my prompt will vary depending on where I’m at. We
have enough servers and services at <code>$DAYJOB</code> that the following makes a
lot of sense:</p>
<pre><code>\u@\h (\t) $
</code></pre>
<p>That prints:</p>
<pre><code>USERNAME@HOSTNAME (TIMESTAMP) $
</code></pre>
<p>You can learn all about <a href="http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/bash-prompt-escape-sequences.html">the various bash shell escape sequences</a> if you’d like.</p>
<p>People tell me that showing the time is silly. I like it because
there are times when I run a long running process and walk away while
it churns. It’s often helpful to know how long something took, and
having timestamps on each line let me know.</p>
<p>It’s helpful to me personally as well. There are many times when I’m
drawn away from scheduled work into an urgent support situation, and
I’ll leave my scheduled work as-is and work the urgent situation in a new
terminal tab or window. That’s exactly what happened today, and I was
a little shocked at the story the timestamps had to tell:</p>
<pre><code>tfreund@somehost (10:28:15) $ the_last_command_i_ran_that_you_dont_care_about.sh
tfreund@somehost (10:28:20) $ the_first_command_i_ran_after_getting_back_at_it.sh
tfreund@somehost (14:38:31) $
</code></pre>
<p>Over four hours. I’ll admit that wasn’t all urgent support. I ate
lunch and checked email, too. It took a look at my important task
list to jog my memory back to the work I was doing at 10:28. “Oh,
right, that’s what I really need to finish today.”</p>
<p>Working for 8 solid hours is an illusion. It’s not going to happen.
Unless work happens in a cabin off the grid away from civilization,
interruptions will wreck your day. Almost every day. More important
than blocking off 8 solid hours is to put in place systems to
continually nudge ourselves toward the important tasks once the storms
of unavoidable urgent work have passed.</p>
<p>My favorites include:</p>
<ul>
<li>Pomodoro timers (<a href="http://tim.freunds.net/blog/chronoflow.html">I wrote one</a>, it’s big, and color coded)</li>
<li>Tasks lists (<a href="http://orgmode.org/">org-mode</a>, <a href="https://www.rememberthemilk.com">Remember The Milk</a>, or your favorite flavor)</li>
<li>Liberal use of my calendar to schedule and track work</li>
<li><a href="http://tim.freunds.net/blog/cheap_sound_experiments.html">Audio that cues me</a> back to the first two items on the list (<a href="http://www.amazon.com/gp/product/B0035KMNRK/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B0035KMNRK&linkCode=as2&tag=ren-20">or a Mountain Stream</a><img src="http://www.assoc-amazon.com/e/ir?t=ren-20&l=as2&o=1&a=B0035KMNRK" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, <a href="http://www.amazon.com/gp/product/B00171GPSW/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00171GPSW&linkCode=as2&tag=ren-20">or Golden Bowls</a><img src="http://www.assoc-amazon.com/e/ir?t=ren-20&l=as2&o=1&a=B00171GPSW" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />)</li>
</ul> Erasers are DeepTim Freund2013-04-01T02:35:00Z2013-04-01T02:35:00Z/blog/erasers_are_deep.html
<p><a href="http://www.flickr.com/photos/kristinnador/7640361202/" title="Pink Pearl Eraser by KristinNador, on Flickr"><img style="float: right;" src="http://farm9.staticflickr.com/8423/7640361202_dde90aa2ae_n.jpg" width="320" height="211" alt="Pink Pearl Eraser"></a></p>
<p>Here’s my problem with Amazon Prime: it’s 2:00 <span class="caps">AM</span> and I’m reading
about erasers. There are so many options, but they’re all
multi-packs. I’m stuck with my choice for a while, so I’d better
choose carefully.</p>
<p>I can’t make a bad decision with the Internet on my side. A kind
fellow at Pencil Talk <a href="http://www.penciltalk.org/2008/03/erasers-the-pink-pearl-the-staedtler-mars-plastic-and-others">experimented with 64 combinations of paper,
pencil, and eraser</a> to set the record straight. The
<a href="http://www.amazon.com/gp/product/B00006IFAN/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00006IFAN&linkCode=as2&tag=ren-20">Mars plastic eraser</a><img src="http://www.assoc-amazon.com/e/ir?t=ren-20&l=as2&o=1&a=B00006IFAN" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> was a clear winner. </p>
<p>I’m sad about the years of wasted erasing potential spent toiling
with the clearly inferior
<a href="http://www.amazon.com/gp/product/B00094H4LU/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B00094H4LU&linkCode=as2&tag=ren-20">Pink Pearl</a><img src="http://www.assoc-amazon.com/e/ir?t=ren-20&l=as2&o=1&a=B00094H4LU" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />. </p>
<p>But I’m still curious about the
<a href="http://www.amazon.com/gp/product/B001Q4HQVU/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B001Q4HQVU&linkCode=as2&tag=ren-20">Pentel Hi-Polymer</a><img src="http://www.assoc-amazon.com/e/ir?t=ren-20&l=as2&o=1&a=B001Q4HQVU" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />. It looks a lot
like the Mars plastic, and it seems to rank well on Amazon. Dave from
Dave’s Mechanical Pencils has a
<a href="http://davesmechanicalpencils.blogspot.com/2008/07/pentel-hi-polymer-zes-08-eraser-review.html">head to head review of the Mars and Pentel varieties</a>. They’re virtually equivalent, so it largely comes
down to availability.<br />
<a href="http://apenchantforpaper.blogspot.com/2012/07/great-eraser-review-pentel-hi-polymer.html">A Penchant for Paper does a similar review</a>, and
throws a private label into the mix. The private label doesn’t live
up to the reputation of the name brands in this case.</p>
<p>It’s exciting to live in a time where we have such cognitive surplus
that we can devote brain power to eraser effectiveness. We’re not so
many years removed from times when our predecessors would have
obsessed over the effectiveness of grain production and storage.
Erasers are a sideline hobby while civilization figures out quantum
mechanics and space exploration.</p> Hand Washing and ChecklistsTim Freund2013-03-24T14:35:00Z2013-03-24T14:35:00Z/blog/hand_washing_and_checklists.html
<p><a href="http://en.wikipedia.org/wiki/Ignaz_Semmelweis"><img style="float: right;" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Hand_desinfection_test_with_blood_agar_plate.jpg/180px-Hand_desinfection_test_with_blood_agar_plate.jpg"></a></p>
<p>Ignaz Semmelweis, the doctor that recommended hand washing between
patients in 1847, died in an asylum. His fellow doctors were appalled
that anyone would think they were dirty. They were educated
gentlemen. How rude of him to imply that they could contribute to
ailments and disease. They were the cure, not the cause!</p>
<p>We’re 166 years out from Dr. Semmelweis’s revolutionary research, and
we’re all better off for it. Every desk in my office has a bottle of
hand santizer on it. It’s in grocery stores near the dirty, filthy
carts. Moms carry it in purses. Yet just 6 months ago the following
was published:</p>
<blockquote>
<p><a href="http://www.reuters.com/article/2012/09/04/us-hand-washing-reminders-idUSBRE88312D20120904">Not all doctors want hand-washing reminders</a></p>
<p><span class="dquo">“</span>There will be a day when it will be so automatic for health care
workers to clean their hands,” Pittet said. “It will be a lot easier
at that time for patients, in case health care workers forgot, to
remind them.”</p>
</blockquote>
<p>A third of doctors surveyed did not want patients reminding them to
wash up. If they were so smart they wouldn’t be sick.</p>
<p>Good thing that smug arrogance is an isolated incident limited to
personal cleanliness. Oh, right, cholera:</p>
<blockquote>
<p>In 1854 London physician Dr John Snow discovered that [cholera] was
transmitted by drinking water contaminated by sewage after an epidemic
centered in Soho, but this idea was not widely accepted.</p>
</blockquote>
<p>That’s from a Wikipedia article named <a href="http://en.wikipedia.org/wiki/Great_Stink">Great
Stink</a>. The name alone
warrants a quick skim, and you’ll also read about more doctors
ignoring research.</p>
<p>For instance, <a href="http://en.wikipedia.org/wiki/Filippo_Pacini">Filippo
Pacini</a> discovered the
bacteria that causes cholera in the same year that Dr. Snow theorized
that transmission was via sewage, but nobody cared. Physicians knew
beyond doubt that cholera wasn’t caused by bacteria, but instead by
miasma. That’s bad air for those of us living with bacterial
awareness in 2013.</p>
<p><a href="http://en.wikipedia.org/wiki/Robert_Koch"><img style="float: right;" src="/media/images/articles/hand_washing_the_great_stink_and_checklists-robert_koch.jpg"/><a></p>
<p>The same bacteria was rediscovered 30 years later by <a href="http://en.wikipedia.org/wiki/Robert_Koch">Robert Koch</a>. He
also isolated the bacteria behind tuberculosis. I suspect other
physicians only took him seriously because he looked like a man that
you shouldn’t screw with.</p>
<p>At least now we’re more data driven. With the systematic cost conscious
approaches pioneered by modern health management organization, surely now
data and procedures rule.</p>
<p>Let’s talk central lines. A central venous catheter as it is called
in terms more complex than I commonly use when discussing health and
medicine. A patient in need of a central line is in rough shape.
Complications from a botched or infected central line spread rapidly
by the very nature of the procedure and equipment. Oh, right, central lines.</p>
<p><a href="http://en.wikipedia.org/wiki/Peter_Pronovost">Dr. Pronovost</a>
instituted a checklist for the care and maintenance of central lines.
In the broad scope of modern medicine, it’s a relatively simple
procedure. Go read it. There are 5 steps. Most of which boil down to
“be clean.” </p>
<p>The checklist focused on proper sterilization procedures, and it was
so effective that they had to extend the trial period just to believe
the results. At the end of the experiment, the hospital estimated
that 43 infections and 8 deaths were avoided, to the tune of two
million dollars in savings.</p>
<p>This is the stuff that medicine is all about. Sterile drapes and
thorough hand washing aren’t sexy like a new <span class="caps">MRI</span> machine or remote
robotic surgery device, but it saves lives, pain and money. </p>
<blockquote>
<p>Despite his initial checklist results, takers were slow to come.
…
There were various reasons. Some physicians were offended by the
suggestion that they needed checklists. Others had legitimate doubts
about Pronovost’s evidence.
(From <a href="http://www.amazon.com/gp/product/0312430000/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0312430000&linkCode=as2&tag=ren-20">The Checklist Manifesto</a><img src="http://www.assoc-amazon.com/e/ir?t=ren-20&l=as2&o=1&a=0312430000" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />)</p>
</blockquote>
<p>Doctors and staff can’t be the cause of trouble, especially if
it boils down to cleanliness. They trained to long to make such
simple mistakes.</p>
<p>Damn it. </p>
<p><a href="http://en.wikipedia.org/wiki/B-17_Flying_Fortress"><img style="float: right;" src="/media/images/articles/hand_washing_the_great_stink_and_checklists-b17.jpg"/></a></p>
<p>Pilots get this stuff right. They’re creatures of checklist habit,
and they’re always, <em>always</em> improving those lists and procedures.
Over 12000 B-17 Flying Fortress aircraft were produced, and they
played a major part in Allied operations during World War <span class="caps">II</span>. This is
an amazing accomplishment for a plane that many deemed too complex to
fly. Airmen began the process of building and using checklists
because of the B-17, and because of the checklists the B-17 became a
powerful, flyable, weapon of war.</p>
<p>Why can’t doctors behave methodically like pilots? Is it because
pilots put themselves on the line and adherence to methodology is the
only thing that brings them back alive?</p>
<p>And why can’t we, the software developers and sysadmins, get it right?
Our systems lend themselves to checklists. Scratch that, our systems
lend themselves to fully automated checklists in which we should only
need to fix the outliers and amend the list. There is a thrill to being
a code hero that must outweigh the simple joy of consistently shipping
software in a reliable and reportable fashion. At some point that thrill
of riding in to save the day cowboy style loses its charm.</p>
<p>We’re getting better, but we’re still more doctor than pilot in our
ego and methods.</p> The Programmer's Data Has No RepositoryTim Freund2013-03-17T23:55:00Z2013-03-17T23:55:00Z/blog/programmers_data_has_no_repo.html
<blockquote>
<p><span class="dquo">“</span>The cobbler’s children have no shoes.” </p>
</blockquote>
<p>I’ve tracked various habits and metrics about myself since 2009 in a
spreadsheet. Perfect example of using a hack to get started rather than
fretting over a system and procrastinating, but I started to yearn for a
bit more flexibility and automation. </p>
<p><img src="/media/images/articles/habits_spreadsheet.png"/></p>
<p>Don’t judge me for tracking my flossing activity. Did you floss every day
this week? Do judge me for not exercising. My barbell is four feet away,
and I have endless miles of sidewalk to run on. There is no excuse. </p>
<p>I looked up open source solutions to the problem because I want to be
in control of my data. I don’t want it on my phone or in the cloud
with no backup or export functionality. That’s what pushed me into
the spreadsheet in the first place.</p>
<p><a href="https://habitrpg.com/">HabitRPG</a> was near the top of the list, but
the links were to a hosted app and a Kickstarter campaign, so I assumed
it was proprietary. It is not. It’s an open business that has code
and business direction discussions out in public <a href="https://github.com/lefnire/habitrpg/">on github</a>.</p>
<p>Oh, and <a href="https://github.com/lefnire/habitrpg/wiki/API">there’s an <span class="caps">API</span></a>.</p>
<p>I’ll be playing with this one for a while to see if I can finally give
my spreadsheet some rest.</p> Throw it All AwayTim Freund2013-03-05T14:40:00Z2013-03-05T14:40:00Z/blog/throw_it_all_away.html
<iframe width="640" height="360" src="http://www.youtube.com/embed/R37zkizucPU?feature=player_detailpage" frameborder="0" allowfullscreen></iframe>
<p>Louis <span class="caps">C. K.</span> cranks out fresh comedy like it’s his job. Probably
because it is his job. It wasn’t always his job, though. He spent 15
years churning through a crappy, awful routine that he hated. </p>
<p>His words, not mine, I’ve never seen that material.</p>
<p>George Carlin inspired Louis to get into comedy in the first place, and it
was George again who inspired Louis to level up his comedy chops.</p>
<blockquote>
<p>Well I just decided every year I’d be working on this year’s special
and I’d do the special, and I’d just chuck out the material, and I’d
start again with nothing. [George Carlin, as told by Louis C.K.]</p>
</blockquote>
<p>The same Louis that makes us laugh with fresh, new material sat in his
car after hearing George’s methodology, and “it made me literally cry,
that I could never do that. I was telling the same jokes for 15 years.”</p>
<h2>Do you have 15 years of experience, or 1 year of experience 15 times over?</h2>
<p>Or ten, or five? How does intern you pale in comparison to senior
software developer you? We don’t ever throw away all of our old
skills, but we must constantly build upon them and selectively throw
out the tired and broken tools that sustained us in the past. </p>
<p>I know people that cut their teeth building DBase applications, but
they aren’t building DBase applications anymore. </p>
<p>What are you proud of this year that didn’t exist last year?</p> Rare Steak and Raw FishTim Freund2013-02-24T15:00:00Z2013-02-24T15:00:00Z/blog/rare_steak_and_raw_fish.html
<p>I was 15 years old when I first went
to <a href="https://plus.google.com/103800442535310245183/about?gl=us&hl=en">Jun’s
in Kansas City</a>. We ate there before the Sadie Hawkins dance, so
the ladies of the group had decided on our dinner venue. Mustering
all of my culinary fortitude, I ordered the Teriyaki Chicken. So brave.</p>
<p>Our family ate fish during Lent, and only after it was battered and
fried. Raw fish wasn’t really food in our world, and it took seven
more years before I was ready to try sushi. People I trust told me it
was delicious. Who was I to question raw food when my steak isn’t
much more than raw?</p>
<p>It’s wonderful, and I only regret waiting so long to try it. </p>
<p>Steak lovers look with disgust while people with lesser palates drown
dry and gray chunks of beef with steak sauce, or worse, ketchup. I
imagine sushi aficionados feel the same about some of the elaborate
deep fried creations that we submerge completely in soy sauce.</p>
<p>Months ago I sat down to relax with a movie. Netflix kept my top
recommendation slot filled with “Jiro Dreams of Sushi” because it
knows I love food and food related things. I’d surely learn something
about great sushi, and I’d bump Jiro out of the top spot for a new recommendation.</p>
<p>It’s wonderful, and I only regret waiting so long to watch it. </p>
<iframe width="560" height="315" src="http://www.youtube.com/embed/I1UDS2kgqY8" frameborder="0" allowfullscreen></iframe>
<p>This is not a movie about sushi. This is a movie about excellence
that uses sushi as a vehicle.</p>
<p>Even for those who don’t like sushi in the least, this movie is
fantastic for anyone that wants to achieve excellence in their chosen
work. I’m not a dancer, but the words of Twyla Tharp
in <a href="http://www.amazon.com/gp/product/B000SEOWBG/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B000SEOWBG&linkCode=as2&tag=ren-20">The
Creative
Habit</a><img src="http://www.assoc-amazon.com/e/ir?t=ren-20&l=as2&o=1&a=B000SEOWBG"
width="1" height="1" border="0" alt="" style="border:none !important;
margin:0px !important;" /> still rang true. Jiro’s words, too, will
ring true:</p>
<blockquote>
<p>Once you decide on your occupation, you must immerse yourself in your
work. You have to fall in love with your work. Never complain about
your job. You must dedicate your life to mastering your skill. That’s
the secret of success and is the key to being regarded honorably.</p>
</blockquote>
<p>Netflix and Amazon Prime members, you can watch this movie for free as
a part of your subscription.</p> Learning how I LearnTim Freund2013-02-18T00:55:00Z2013-02-18T00:55:00Z/blog/learning_how_I_learn.html
<p>I never expected to shoot for a sociology minor. Not a single bit of
the “Intro to Sociology” class sounded interesting to me. “Social
Stratification in America”, though, sounded very interesting. It was
an evening class, and I could get a full day in at the bomb factory,
and I’d get a social science credit without taking a ridiculous intro class.</p>
<p>For three hours each week Dr. Carroll would lecture a rushing river of
sociological consciousness. She’d glance at notes, but only
occasionally. Each and every week. A couple of other facts: she was
known in the department as a brutal tester, and there was no text
book. I rebuilt my atrophied note taking muscles in record time.</p>
<p>The rumors of her tests were true. Only my abstract algebra class
compared. She handed back the first test, and I deflated. “Shit!
65%! So much for an easy social science credit!” But I was in luck,
because I had set the curve in a room full of social science majors.
My notes made it all possible.</p>
<p>Fast forward to today. I can tell you which books I’ve read in the
last few years. I can also tell you if I liked them. I <em>can’t</em> tell
you much beyond that in many cases. There’s knowledge buried in my
subconscious, I hope, but I can’t confirm it. </p>
<p>I know reading is important, and I love reading. It just felt like
I was missing out on most of the fruits of it. </p>
<p>I started an experiment in December, and I can report that things are
turning around. I heard the <a href="http://http://www.manager-tools.com/">Manager
Tools</a> crew talk about reading
one hundred books in a year, and I decided I should do at least half
of that. And if I was going to get through one hundred books, I
should take notes during the process.</p>
<p>In addition to the great stuff in the books, I’ve (re)learned how I
learn: through writing notes. I’ve become a bit obsessive about
having a notebook or text editor nearby at all times, and I’m
better for it already. </p>
<p>If I’m reading to learn, I’m also taking notes. </p>
<p>If I’m listening to learn, I’m also taking notes.</p>
<p>If I’m watching to learn, I’m also taking notes. </p>
<p>Feel like you could use a nudge in the right direction regarding notes
and books? Recall that the Manager Tools guys have a cast about
everything, including <a href="http://manager-tools.com/2011/10/how-read-a-book">How to Read a Book</a>.</p>
<p>I appreciate you humoring me if all of this is common sense to you.<br />
If you have all of this figured out already, I’d love to hear what
comes next. I promise I’ll take notes.</p> Three Sets of Chisels FollowupTim Freund2013-02-12T00:05:00Z2013-02-12T00:05:00Z/blog/three_sets_of_chisels_followup.html
<p>I had a great followup to <a href="http://tim.freunds.net/blog/three_sets_of_chisels.html">yesterday’s post</a>
that happened over <span class="caps">IM</span> today. </p>
<blockquote>
<p>I was wondering what command you’d use to grep through .xls file on linux?</p>
</blockquote>
<p>That’s a moment where my knowledge of my favorite tools helped me to
eliminate those tools quickly from consideration. The text processing
tools of the unix shell are terrible for searching through binary
files like Excel spreadsheets.</p>
<p>If I had a single Excel spreadsheet with a ton of data to extract, I
might convert it to a <span class="caps">CSV</span> file to then manipulate it further in my
shell, but even then I’d probably just open it with Libre Office or
Gnumeric and call it a day. </p>
<p>What if there were tens or hundreds of spreadsheets to sift through? </p>
<ol>
<li>
<p>I’d talk to one of my Windows + .Net friends to see if PowerShell
would work.</p>
</li>
<li>
<p>or ask them about C# APIs to do the same if PowerShell failed us.</p>
</li>
<li>
<p>or as a very last resort look to use an open source tool to
do the necessary <span class="caps">ETL</span> work. </p>
</li>
</ol>
<p>It’s strange writing open source and last resort in the same sentence.
I’m the weirdo that kept my music collection encoded with Ogg Vorbis
for most of a decade, and I haven’t played a commercial computer game
since Unreal Tournament ran on my old Gentoo desktop. Maybe it’s old
age that’s moving me from zealous to pragmatic, but I think I’ve
realized that work isn’t about software for the sake of
software. It’s about software for the sake of getting shit done.</p> Three Sets of ChiselsTim Freund2013-02-10T15:45:00Z2013-02-10T15:45:00Z/blog/three_sets_of_chisels.html
<blockquote>
<p>I was pissed (with myself) that I had three sets of chisels to
maintain. Three sets to store. Three sets that would set me back in my
efforts to master one set of chisels.
—<cite>Christopher Schwarz from <a href="http://blog.lostartpress.com/2013/01/04/tools-are-a-burden/">Tools are a Burden</a></cite></p>
</blockquote>
<p>We moved from a fairly modern 2000 square foot suburban home to a 900
square foot 1928 bungalow in 2008, and the drastic reduction in square
footage quickly cured me of my hardware pack rat habit. My new office
didn’t allow for my <a href="http://h18002.www1.hp.com/alphaserver/workstations/retired/auseries/index.html"><span class="caps">DEC</span> Alphastation</a>,
my <a href="http://en.wikipedia.org/wiki/SGI_Indigo"><span class="caps">SGI</span> Indigo Iris</a>, or my
<a href="http://www.obsolyte.com/sun_ipx/">Sun <span class="caps">IPX</span></a>, nor my stack of obsolete x86 carcasses. </p>
<p>The silliest part? I bought those classics long after they were past
their prime. I used the <span class="caps">IPX</span> as a router at my parents’ house for a
while, but for the most part the systems were there for the sake of
coolness or nostalgia for unix years past. </p>
<p>Another move and easier access to virtualized hardware at home, work,
and “in the cloud” further cured me of my desire to hoard hardware.
Hardware today is so powerful that I’ve even removed myself from the
6-12 month upgrade treadmill.</p>
<p>I wish I was equally discerning with my software tools, but I’m prone
to excitement over the latest and greatest. The professional cabinet
maker can bet that one trunk of quality tools will last a lifetime,
but we don’t have that luxury in the quickly changing field of
software. Despite this, there are some tools that get called into
action more often than others, and they tend to be long lasting cross
platform tools that only get faster and more capable with years of
practice: unix, emacs, python. </p>
<p>With a small set of default tools that are nearly ubiquitous, I can
solve most problems fairly quickly, and I’ll quickly know if I need
to use different tools all together for a given problem. </p>
<blockquote>
<p>If construction (not collecting) is your goal, find some way to
limit yourself - a tool chest is one way - so you can be a better
builder than you are a consumer.
—<cite>Christopher Schwarz from <a href="http://blog.lostartpress.com/2013/01/04/tools-are-a-burden/">Tools are a Burden</a></cite></p>
</blockquote> Not a Diet, a Lifestyle ChangeTim Freund2013-02-04T00:45:00Z2013-02-04T00:45:00Z/blog/lifestyle_diet_change.html
<p>I’m down about 15+ pounds since moving to Lancaster, <span class="caps">PA</span>. I knew I was
down a bit because my face doesn’t look quite so fat in the mirror, but
my progress surprised me. I was not consciously trying to lose my lard.<br />
I wasn’t even tracking my weight, because we haven’t set up our Wii Fit yet. </p>
<p>I didn’t go on a diet. I changed my lifestyle. Just like every sensible
weight loss program says in the fine print.</p>
<p>I stopped or seriously cut back on stuff like:</p>
<ul>
<li>Eating lunch out with the guys 5 days a week</li>
<li>Eating dinner out with Kate 2-4 times a week</li>
<li>Eating two chocolate-iced originals at Lamar’s 2-3 times a week</li>
<li>Eating Soft Batch cookies from the company kitchen 2-3 times a week</li>
</ul>
<p>And I started some new habits as well:</p>
<ul>
<li>Walking most places</li>
<li>Buying (and cooking) fresh fruit and veggies from the central market 2-3 times a week (after walking there).</li>
<li>Cooking simple and delicious food</li>
<li>Eating a small lunch of home cooked food</li>
</ul>
<p>Buying and cooking fresh produce is a huge part of my week now. I
don’t have a commute when I’m done with work, so I cook to demarcate
the separation between work and home life. The guys are 1000+ miles
away. I’m jealous at times of their lunchtime adventures, but it’s
just not an option. I still eat snacks, but I skip the Soft Batch
cookies when shopping for myself. </p>
<p><a href="http://photos.freunds.net.s3.amazonaws.com/custom/201208/9737ee-IMG_2073-20120821-124635_960x180.jpg">I didn’t even give up all of my terrible habits.</a></p> Death by SmorgasbordTim Freund2013-01-14T00:55:00Z2013-01-14T00:55:00Z/blog/smorgasbord.html
<p><a href="http://eater.com/archives/2010/05/19/gastric-bypass-discount-shady-maple-smorgasboard.php#more">Get Gastric Bypass Surgery, Get 50% Smorgasbord Discount</a></p>
<p>If you don’t hear from me Tuesday or beyond, I may have been killed by
the <a href="http://www.shady-maple.com/smorgasbord/specials/">Shady Maple Smorgasbord</a>.</p>
<p>If I survive, I’ll gladly accompany you to any of their following
future events:</p>
<ul>
<li>Shrimp and Grilled Fish Weekend</li>
<li>Pork Bonanza</li>
<li>Beef Bonanza</li>
</ul>
<p>… I’m not a big prime rib guy, but you could twist my arm on that
one as well.</p>
<p>These are the same people that bring the famed maple bacon long johns
to the Lancaster Central Market. I love them. And hate them.</p>
<p><img alt="Maple Bacon, Baby!" src="http://photos.freunds.net.s3.amazonaws.com/custom/201208/9737ee-IMG_2073-20120821-124635_870x550.jpg" /></p> dnsmasq and External Resolution of Internal AddressesTim Freund2013-01-06T04:55:00Z2013-01-06T04:55:00Z/blog/dnsmasq_and_external_resolution_of_internal_addresses.html
<p>The <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> program
is used on many linux computers and devices to handle <span class="caps">DNS</span> and <span class="caps">DHCP</span>.
If you’re connected to the Internet through a Buffalo router of any
recent vintage, you’re using dnsmasq right now unless you’ve
thoroughly fiddled with the configuration, in which case you probably
already know everything I’m about to write.</p>
<p>The —stop-dns-rebind option (or “No <span class="caps">DNS</span> Rebind” in the Buffalo <span class="caps">DD</span>-<span class="caps">WRT</span>
<span class="caps">GUI</span>) throws away any <span class="caps">DNS</span> resolution responses from external name
servers that contain <span class="caps">IP</span> addresses within the private address spaces.
This prevents a class of attacks where bad dudes use short <span class="caps">DNS</span> <span class="caps">TTL</span>
settings to make browsers give up internal network secrets. Zone
administrators that publish private <span class="caps">IP</span> addresses within the public <span class="caps">DNS</span>
space are usually either mistaken, dumb, or nefarious, and their
results should be ignored whenever possible.</p>
<p>I really wrote myself into a corner with that last sentence, because
<em>I</em> have a zone that responds with private <span class="caps">IP</span> addresses within the
public <span class="caps">DNS</span> space. I am testing some fun and completely above board
things with <a href="http://aws.amazon.com/route53/">Amazon’s Route 53</a>
service, and the quickest way to do so was to copy an internal zone
from within the Freund Data Center Complex out to the cloud.</p>
<p>How do we fix it? If you’re using a recent version of dnsmasq,
there’s a —rebind-domain-ok option that places provided domains on a
white list. If your router doesn’t support that option, then
you can always disable the behavior entirely.</p> Book - On Writing WellTim Freund2013-01-03T18:55:00Z2013-01-03T18:55:00Z/blog/book_on_writing_well.html
<p><span class="dquo">“</span>But is it done, done?” </p>
<p>I hate that phrase. I prefer nails on a chalkboard to that phrase.
Two reasons: it sounds so dumb and condescending, and it’s so
important to the software development life-cycle.</p>
<p>Developer: “<span class="caps">OK</span>, I’ve checked in the new payment processing code.
It’s done.”</p>
<p>Project Manager: “So it’s done, done? Everything works, and it’s
tested? Payments, refunds, all of it?”</p>
<p>Developer: ”…”</p>
<p>Project Manager: “How about you double check your test cases before
we mark this as complete.”</p>
<p>Developer: “Probably a good idea.” </p>
<p>Writing feels a lot like software development. It’s a solo process, just an
author and his tools. A piece may look done, but it isn’t really finished
until the author rewrites it once, twice, or more, just as developers send
code through unit testing, alpha testing and beta testing. </p>
<p>Another similarity: “Few people realize how badly they write.” </p>
<p>William Zinsser wrote that line in <a href="http://www.amazon.com/Writing-Well-30th-Anniversary-Nonfiction/dp/0060891548">On Writing
Well</a>,
but it could have easily found its way into any number of our classic
software development books. </p>
<p>His book marches through many facets of
the craft: principles, methods, forms, and attitudes. I collected a
windfall of practical advice without minutia burying my desire to
write. It’s the <a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X">Pragmatic
Programmer</a>
for writing.</p> Link - Inspiration is for AmateursTim Freund2013-01-02T23:55:00Z2013-01-02T23:55:00Z/blog/link_inspiration_is_for_amateurs.html
<p><a href="http://www.brainpickings.org/index.php/2012/12/27/chuck-close-on-creativity/">Chuck Close on Creativity, Work Ethic, and Problem-Solving vs. Problem-Creating</a></p>
<p><span class="dquo">“</span>Inspiration is for amateurs - the rest of us just show up and get to work.”</p>
<p>That stings. We’re <a href="http://batesandmetzger.com/">renovating a house</a>,
and I’ve already put quite a bit of thought into my office sanctuary,
despite it sitting at the very end of our project list. </p>
<p>Keyboards, monitors, desks and chairs come up in conversation at least
once a month in my circle of friends. <a href="http://lostapathy.com/blog">Joe</a> and I have both built custom
desks, and our current desks won’t be our last. <a href="http://www.steelcase.com/en/products/category/seating/task/leap/pages/overview.aspx">My chair</a> was a steal
on ebay, but I would gladly pay full price if necessary. </p>
<p>Does that make me an amateur? </p>
<p>I hope not. I don’t think so after reading Chuck’s perspective a
second time. We obsess over our tools, not our spaces. Our spaces
get attention only as a tool of noise reduction and focus improvement.
Wall color is not a hot topic, but sound insulation is. My butt has
paid the price for cheap chairs, and my wrists for cheap keyboards.<br />
I make no apologies for my snobbery. </p>
<p><span class="dquo">“</span>A poor craftsman blames his tools”, but a great craftsman picks and
cares for great tools.</p> Fact Driven DevelopmentTim Freund2013-01-01T19:23:00Z2013-01-01T19:23:00Z/blog/fact_driven_development.html
<p>Six groups of four students huddled around their respective lab
tables, waiting for their dissection subject. A cat. A kitty. A
dead, dyed, and preserved Felix catus domestica. Some kids hid their
anxiety behind smiles, others gaped in silence. Cat dissection was the
big deal in Biology <span class="caps">II</span> at Bishop Miege High School. Everyone
experienced it, even if they never took the class. Formaldehyde
wafted through the halls, following Bio <span class="caps">II</span> students through the rest
of their day.</p>
<p><a href="http://www.flickr.com/photos/40964293@N07/3786012365/" title="Cat Dissection by biologycorner, on Flickr"><img src="http://farm3.staticflickr.com/2550/3786012365_003d929f46.jpg" width="500" height="375" alt="Cat Dissection"></a></p>
<p>(The photo is from Flickr. Not my class, or my school, or even my decade…)</p>
<p>I wielded the scalpel about half of the time in my group. I’m not
sure if they were conscientious objectors or just grossed out by the
smell, but two of our four did as little cutting as possible. As the
blade dug through tissue while we traced the route of blood vessels
heading to the kidneys, a thought flashed through my mind: “Holy shit!
We’re hacking the crap out of this cat, and we have the benefit of
dyed blood vessels. Doctors do this to real people? And they live?!”
I never had a strong desire to become a doctor, but that cut crossed
it off my list for good. I liked my science exact, thank you very much.</p>
<p>Little surprise that I ended up slinging bytes for fun and money.
Boolean logic is so orderly, and everything always lines up along
powers of 2 or groups of 8. Unambiguous facts lead us through
problems and root causes as long as we watch closely. Even the
deepest and most difficult problems can be reasoned through with facts
derived from direct observation, although we may retreat from the hunt
with a sigh and a reboot at times.</p>
<p>There’s a downside to all this exactitude for people who play fast and
loose while interacting with tech workers. “All of the processes
restarted” is a verifiable statement, trivially so. Don’t think the
sysadmin won’t check. “Every transaction is failing” will win no
friends within the support ranks once they see that 2 out of 3
transactions are successful. The <span class="caps">ISP</span> support line operator knows when
you’ve been bad or good, so reboot your modem for goodness sake. </p>
<p>Facts drive the growth and maintenance of technical projects and
infrastructure. Gather data, analyze it, and act upon it to move
forward. Running on gut feel works only as long as your gut is right.</p> Signs and Travel AdvisoriesTim Freund2012-12-19T04:07:00Z2012-12-19T04:07:00Z/blog/signs_and_travel_advisories.html
<p>Blinders, blinkers, and winkers are three names for the same class of
horse gear. Coming in various shapes and sizes, they all keep horses
focused on the road ahead by blocking out distractions. </p>
<p>Humans, though, are different. We’re so smart that we don’t need to
put blinders on to completely ignore the obvious information at our
periphery, even when it’d do us some serious good. Our intent and
determination can blind us to even the most obvious signs of disaster,
and more subtle clues can be missed even when we’re carefully searching.</p>
<p><a href="http://www.flickr.com/photos/38194075@N05/4430503343/" title="Way Wrong Wrong Way by valleygirl_tka, on Flickr"><img src="http://farm3.staticflickr.com/2526/4430503343_2809a2bc72.jpg" width="500" height="344" alt="Way Wrong Wrong Way"></a></p>
<p>I use the Oracle Instant Client on a number of systems, and I’ve
always used a <span class="caps">URL</span> format similar to that of Oracle’s Java thin client
connections. From within Python’s <a href="http://www.sqlalchemy.org/">SQLAlchemy</a> toolkit, the <span class="caps">URL</span> format
looks like:</p>
<pre><code>oracle://user:password@hostname:port/database_sid
</code></pre>
<p>Systems with <span class="caps">TNS</span> configurations can alternatively use the following format:</p>
<pre><code>oracle://user:password@tnsname
</code></pre>
<p>I was feeling a bit sorry for myself, because I was using the Instant
Client rather than the full blown Oracle client complete with a
tnsnames.ora definition file. This meant manually updating connection
strings for a number of schemas that had migrated to another data
center. While doing the updates, I tried to use the Oracle service name
rather than database <span class="caps">SID</span>, as that would be one less thing to change after
future migrations, but I couldn’t see a way to use a service name rather
than <span class="caps">SID</span> name through SQLAlchemy’s configuration mechanism.</p>
<p>SQLAlchemy and <a href="http://cx-oracle.sourceforge.net/">cx_Oracle</a> are both open source. This could be a fun
thing to fix! With a fresh virtual environment and dependencies
downloading, I filled the download time by reading the Instant Client
<span class="caps">FAQ</span>. Right in the middle was this gem::</p>
<pre><code>Naming methods that require TNS_ADMIN to locate configuration files
continue to work if the TNS_ADMIN environment variable is set.
</code></pre>
<p>Oh. So I can set a <code>TNS_ADMIN</code> environment variable just like with
a full client install? So I’m done? No code change needed. I could
have avoided all of this trouble in the first place had I read through
the documentation more carefully when I started using the Instant Client.</p>
<p>There’s a happy balance between immediately jumping into action and
hunkering down with documentation and research. I struggle with
finding that middle path. I live at both ends of the spectrum
depending on the subject. </p>
<p>For instance, technology and programming challenges ahead? Let’s get
to work! We’ll figure it out as we go!</p>
<p>Meanwhile, when I should write a landing page to gather interest in a
course I’d like to offer, I stall. “Not yet”, I say, “I need to read
these 27 books on marketing and adult learning.”</p>
<p>Are you blowing past helpful signs and travel advisories on your way
to a goal, or have you spent so much time studying the atlas that
you’re still right where you started?</p> First Impressions of MezzanineTim Freund2012-12-16T00:30:00Z2012-12-16T00:30:00Z/blog/first_impressions_of_mezzanine.html
<p>If you personally know me, you probably know that Kate and I moved to
Lancaster, <span class="caps">PA</span> this past summer. We’ve got a lot of renovation and
exploration ahead of us, and that means we need some new web
infrastructure. For the impatient or non-technical among us, our new
site is called <a href="http://batesandmetzger.com">Bates and Metzger</a> as a
tip of the hat to the original two families that owned our place.</p>
<p>I run this blog with <a href="http://hyde.github.com/">Hyde</a>. It’s great, and I get a static <span class="caps">HTML</span>
site out of it with each commit to my repository, but I wanted something
with a friendly web interface to encourage Kate’s participation in
writing posts. </p>
<p>I knew I wanted something written in Python. After checking out many
of the available options, it looked like something based on
<a href="https://www.djangoproject.com/">Django</a> would be the way to go, and
<a href="http://mezzanine.jupo.org/">Mezzanine</a> looked both nice and active.</p>
<p>Installation was easy, the admin interface is friendly, and customization
has been surprisingly quick. It definitely assumes that site admins and
developers will have Django experience, but I’m faking that part well enough.</p> ChronoFlow, My Custom Work TimerTim Freund2012-11-25T21:07:00Z2012-11-25T21:07:00Z/blog/chronoflow.html
<p>I’m a huge fan of the <a href="http://www.pomodorotechnique.com/">Pomodoro
Technique</a>, but I kinda hate every
single timer that I’ve ever used to facilitate it, and I’ve tried
quite a lot. Web timers, <span class="caps">OSX</span> timers that hang out in the menu bar,
fat client applications, Android apps. They’re all uniquely irritating.</p>
<p>This is classic <a href="http://projects.csail.mit.edu/gsb/old-archive/gsb-archive/gsb2000-02-11.html">yak shaving</a>,
and if I weren’t a programmer by trade I’d just pick the most decent existing
solution and get on with life. </p>
<p>Here’s my simple but specific requirement list:</p>
<ul>
<li>Scalable. I have a lot of screen real estate, and it’s nice to have
a big timer as a constant reminder when space allows it.</li>
<li>Colorful. Not beautiful, necessarily, just green and red.</li>
<li>Nice Sounds. I’m a musician, and ugly alerts and alarms upset me
more than they rationally should. </li>
</ul>
<p>I don’t need task tracking capabilities. I have emacs for that. </p>
<p>Easy, right? Actually, yes. 161 lines of code later, and it times my
work iterations on half of monitor #4. The following tools made it
remarkably simple:</p>
<ul>
<li><a href="http://www.pygtk.org/">PyGTK</a> for windows and widgets</li>
<li><a href="http://www.cairographics.org/pycairo/">PyCairo</a> for drawing</li>
<li><a href="http://www.pygame.org/news.html">pygame</a> for sound support</li>
</ul>
<p><img src="../media/images/chronoflow.png"/></p>
<p>Right now this is a “works on my machine” project, but you can still
<a href="https://bitbucket.org/timfreund/chronoflow">find it on Bitbucket</a>. I’m
going to live with it as-is for a while to see how I like it, and then
I’ll investigate the following options:</p>
<ul>
<li>Replicate the same code with <a href="http://developer.ubuntu.com/get-started/">Quickly</a> </li>
<li>Hook into <a href="https://developer.pidgin.im/wiki/DbusHowto">Pidgin with DBus</a> to
control my status when starting and stopping work iterations. </li>
<li>Use <a href="http://www.hydrogen-music.org/hcms/">Hydrogen</a> and
<a href="http://qsynth.sourceforge.net/qsynth-index.html">QSynth</a> to make some
nice alarm sounds.</li>
</ul> Before Your Morning CoffeeTim Freund2012-11-15T18:00:00Z2012-11-15T18:00:00Z/blog/before_your_morning_coffee.html
<p><a href="http://news.ycombinator.com/item?id=4781372">Folks are talking</a> about
Raymond Chen patching the <span class="caps">MS</span> Money binary
because <a href="http://blogs.msdn.com/b/oldnewthing/archive/2012/11/13/10367904.aspx">Money crashes during import of account transactions</a>. </p>
<p><a href="http://www.flickr.com/photos/selma90/3693798571/" title="Coffee by Selma90, on Flickr"><img src="http://farm3.staticflickr.com/2551/3693798571_c9b4a794d9_n.jpg" width="240" height="320" alt="Coffee"></a></p>
<p>There’s a lot of love in the air for that old, end-of-life, product.
There’s also a lot of love for Raymond walking through the debugging
and patching process. It takes a lot of knowledge and skill to
patch a compiled software program without any special access to the
source code, and the article is worth a read if you’re into that sort
of activity. </p>
<p>But I’m not really interested in all that. At least not today. </p>
<p>I want to talk about what you do before your morning coffee. See,
down at the bottom of Raymond’s post there’s a little section called
“Bonus chatter”, and at the bottom of “Bonus chatter” we get this gem:</p>
<blockquote>
<p>Specifically, I said, “I feel like Jeff, who does this sort of thing
before his morning coffee.”</p>
<p>Jeff corrected me. “If this was something I used to do before coffee,
that probably meant I was up all night. Persistence >= talent.”</p>
</blockquote>
<p><strong>Persistence >= talent.</strong> That is the passage to note. Nobody is
born with an innate talent for software development. Or writing. Or
painting. Or auto body restoration. It takes persistence. </p>
<p>I’m going to admit something about myself that I’m not sure I’m happy
about. I’m quick to judge <span class="caps">IT</span> folks who say they want to be programmers. </p>
<blockquote>
<p>A quick tangent: I love the idea of running and finishing a marathon.
Sounds exhilarating.</p>
<p>I <strong>hate</strong> the idea of training for a marathon. I’d much rather code, or
cook, or build than run 5+ days a week for months at a time. I’m at
peace with this. I don’t tend to divulge my love of the idea of
marathon running much since I know I won’t put forth the effort to
actually do it.</p>
</blockquote>
<p>Point an <span class="caps">IT</span> guy or gal at well written and tested material, and they
should be programming in very little time. Basic stuff at first,
sure, but everyone starts there. Most often, though, their true
desire to <em>be</em> a programmer without learning to program shines through.</p>
<p>Programming. It’s not hard. But it’s not easy, either. It’s easy to
sit down one day to learn how to program, but you won’t get far. It’s
hard to do that every single day for months at a time.</p>
<p><a href="http://www.flickr.com/photos/gavin_rice/5699549955/" title="IMG_2099 by gavin rice, on Flickr"><img src="http://farm3.staticflickr.com/2647/5699549955_258817159e.jpg" width="500" height="333" alt="IMG_2099"></a></p>
<p>If you need help learning how to program, or clean a carburetor, or
ice a cake, or anything else, find a potential mentor and bring your
work with you. It gives the mentor something to work with, and it
shows your dedication to the topic. Partial credit isn’t some relic
of math classes long forgotten. It still works to your benefit. Show
your work and get partial credit. Show no work for no credit. Be
persistent and succeed.</p> Contact CallsTim Freund2012-11-08T01:11:00Z2012-11-08T01:11:00Z/blog/contact_calls.html
<p>Animals communicate with each other. Shocking, right? Birds, in
particular, enjoy communicating outside of my window while I’m trying
to sleep in. (First world problem, I know.)</p>
<p><a href="http://www.flickr.com/photos/jaymiles/4613847146/" title="Coyotes in Jasper by JayMilesPhotography, on Flickr"><img src="http://farm4.staticflickr.com/3300/4613847146_8ea025752f.jpg" width="500" height="289" alt="Coyotes in Jasper"></a></p>
<p>Animals don’t chatter for the sake of noise. They have points to
make. I recently read <a class="reference external" href="http://www.americanscientist.org/issues/id.15840,y.2012,no.4,content.true,page.1,css.print/issue.aspx">Vocal Matching in Animals</a>
in <a class="reference external" href="http://www.americanscientist.org">American Scientist</a>
Magazine. The author provided a succinct overview of animal contact
calls, calls used to establish, maintain, or regain contact among
groups of animals. I couldn’t stop thinking about text editors
while I read.</p>
<blockquote class="epigraph">
<p>the finding that vocal matching of contact calls often occurs
among members of social groups that work together, or among members of
mated pairs that rear young together, corroborates the idea that vocal
matching specifically facilitates cooperative, mutually beneficial interactions.</p>
<p>First, matched calls present an efficient way to identify group
members, particularly in large groups when not all individuals are
familiar with one another. Because matched calls emerge through the
process of imitative learning, which often requires sustained social
contact, they reflect the social experiences of the signaler and
effectively encode aspects of that individual’s social
background. Thus, matched calls might provide listeners with
information about individuals within their larger social network with
whom they are less familiar, permitting listeners to quickly determine
whether another animal has experience with, and therefore belongs to,
their social group. This idea is known as the badge, or password, hypothesis.</p>
<p class="attribution">—Kendra Sewall, <a class="reference external" href="http://www.americanscientist.org/issues/id.15840,y.2012,no.4,content.true,page.1,css.print/issue.aspx">Vocal Matching in Animals</a></p>
</blockquote>
<p>Different social groups within our large technical community have different
matched calls used to claim and confirm group membership. Many groups have
multiple matched calls that can be used for identification purposes.</p>
<p>Programmers size each other up to establish dominance across a number
of qualities and preferences. Ralph might ask John for his preference
in version control systems, and Ralph will judge John based on his
answer along a specturm like the following:</p>
<dl class="docutils">
<dt>"Huh?"</dt>
<dd>Is John an intern? If so, we can mold him. If not, he’s an idiot.</dd>
<dt>"I don’t really see the point."</dt>
<dd>Definitely an idiot.</dd>
<dt><span class="caps">CVS</span>, Subversion, Source Safe, any other last gen system</dt>
<dd><span class="caps">OK</span>, he has a brain. Kinda old school, maybe.</dd>
<dt><span class="caps">GIT</span>, Mercurial, <span class="caps">TFS</span>, any other current gen system, and here’s why.</dt>
<dd>He paid attention during the last decade. Good sign.</dd>
</dl>
<p><a href="http://www.flickr.com/photos/edwardrooks/6844871959/" title="A pod of Orcas near our ship by edward_rooks, on Flickr"><img src="http://farm8.staticflickr.com/7152/6844871959_6927455fcc.jpg" width="500" height="333" alt="A pod of Orcas near our ship"></a></p>
<p>(Most) Unix guys won’t actually shun someone for answering the classic
"emacs or vi" question "incorrectly". The incorrect answer is "none
of the above". Using either emacs or vi means that someone is familiar
with the common editing tools on a unix machine, and that means "they
might be one of us". A unix sysadmin candidate who starts rambling
through the process of downloading files to his Windows <span class="caps">ME</span> desktop
with <span class="caps">FTP</span> and editing them in Notepad will never, ever, ever be a
unix sysadmin in any reasonable organization.</p>
<p>I have no idea what sort of matched calls a group of Oracle DBAs or
Cisco Network Engineers would use to judge one another.</p>
<p>It’s <span class="caps">OK</span> to remain ignorant of a group’s matched calls if you’re
legitimately not in or interested in their group. These are secret
handshakes, and you don’t need to know ‘em if you don’t need to use
‘em. Try to weasel your way in to a group with brute force and
dumb luck, on the other hand, and you’ll commit credibility suicide.</p>
<p><a href="http://www.flickr.com/photos/usfws_alaska/5390772958/" title="Walrus Cows and Yearlings on Ice by USFWSAlaska, on Flickr"><img src="http://farm6.staticflickr.com/5058/5390772958_b19fbc7af7.jpg" width="500" height="350" alt="Walrus Cows and Yearlings on Ice"></a></p>
<p>Interviewing always consumes a huge amount of time and generally makes
everyone involved hate life for a while when done poorly. On top of
that, most organizations stretch out the firing process such a long
time, often approaching infinity. You’re better off saying no to the
occasional good candidate if it means never hiring a terrible
candidate in an organization that is slow to fire, so the interview
process is all about finding reasons to say "no".</p>
<p>Interviewers don’t know they’re mimicking the animal kingdom, but the
first few questions after a round of pleasantries cut to the heart of
a candidate’s experience. A candidate’s chances die a quick death if
those matched calls don’t get answered appropriately. For example,
here’s one of my least favorite interviewing experiences:</p>
<blockquote>
<p><strong>Me</strong>: "I see you have experience with <span class="caps">AOP</span>. That’s great, not many people
have that. I used it on my last project and loved it. What
implementation did you use, what kind of aspects were you writing, and
at what point cuts would you apply them?"</p>
<p><strong>Her</strong>: "… [silence] … I didn’t really write the <span class="caps">AOP</span> parts, but I was
familiar with them in the project."</p>
<p><strong>Me</strong>: "Ah, I see. Well, we’ve got a whiteboard here. Can you draw or
talk about the concepts that make <span class="caps">AOP</span> interesting? Maybe some of the
classic example use cases, or how they were used in your app?"</p>
<p><strong>Her</strong>: "… [uncomfortable silence] … I don’t really know anything about <span class="caps">AOP</span>."</p>
</blockquote>
<p>I didn’t throw her resume into the air and walk her out the door
immediately. I wanted to, but that would be rude, and that’s not good for
anybody. For all I know, her sister, cousin, neighbor, or college
friend would be a great fit at the company, and I don’t need anyone
hating us, even if they are personally a terrible fit for the group.
Even still, the interview was effectively over in the first two
minutes. She failed the first matched call question in such an over
the top way that no amount of stellar answers could bring her back
into the hire column.</p>
<p>(And if you want to read more about <a class="reference external" href="http://www.joelonsoftware.com/articles/SortingResumes.html">sorting resumes</a>
and <a class="reference external" href="http://www.joelonsoftware.com/articles/GuerrillaInterviewing3.html">interviewing</a>,
click those links to read what a real pro has to say about those topics.)</p> Link - Adam Savage Builds a Doc Ock CostumeTim Freund2012-10-31T23:45:00Z2012-10-31T23:45:00Z/blog/link_adam_savage_doc_ock_costume.html
<p><span class="dquo">“</span>… once you understand the structure of something, everything else is just cutting parts to size…”</p>
<p><a href="http://www.tested.com/videos/449774-inside-adam-savages-cave-making-patton-oswalts-doc-ock-costume/"><span class="caps">INSIDE</span> <span class="caps">ADAM</span> <span class="caps">SAVAGE</span>’S <span class="caps">CAVE</span>: <span class="caps">MAKING</span> <span class="caps">PATTON</span> <span class="caps">OSWALT</span>’S <span class="caps">DOC</span> <span class="caps">OCK</span> <span class="caps">COSTUME</span></a></p>
<p>Most recently I rediscovered this while building some diagrams to
document processes for work. Previously I’d open up
<a href="http://www.inkscape.org/">Inkscape</a> right
away and start to draw, but it was a tedious process. Lining stuff up
just right, then realizing that steps are missing, then re-lining
stuff up just right, then listening to coworkers explain other steps
that are missing, then crying softly in a corner. It’s a tiring process.</p>
<p>We love our computers, but use the right tool for the job. Buy
a <a href="http://www.amazon.com/gp/product/B003BLC7FG/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=B003BLC7FG&linkCode=as2&tag=ren-20">pencil</a> and a
<a href="http://www.amazon.com/gp/product/B0052XQEMS/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=B0052XQEMS&linkCode=as2&tag=ren-20">notebook</a>. Figure out what needs to happen on paper. Then do it.</p> Link - Sell Without Selling OutTim Freund2012-10-30T00:07:00Z2012-10-30T00:07:00Z/blog/link_sell_without_selling_out.html
<p>Andrew Zahn write about how to
<a href="http://zahndrew.com/sell-without-selling-out">Sell Without Selling Out</a>.</p>
<p>I’m linking to it for two reasons:</p>
<ol>
<li>It’s true, you can do just that, and it’s important.</li>
<li>Muppets!!!</li>
</ol>
<p>Go for the Muppet video, stay for the article. It’s muppetry like I had
never seen before. Muppets selling people on muppets.</p> Hill WorkTim Freund2012-10-21T15:07:00Z2012-10-21T15:07:00Z/blog/hill-work.html
<p>I ran cross country for a couple of years in high school. Not well,
but I did it. I’ve since learned that diet and consistent training
outside of the season would have greatly improved my chances of
success, but that’s water under the bridge.</p>
<p>Every Monday afternoon we’d warm up, jog past the school
entrance, down Reinhardt Drive, and assemble at the corner of Howe and
52nd Place. For a group of kids that normally measured progress in
one mile increments, we were in for a particularly rough work out
measured not in miles, but in hills.</p>
<p>Hill work breaks down pretty neatly: </p>
<ol>
<li>Sprint up the biggest hill available to you</li>
<li>Jog back down at an easy pace. Don’t run, don’t walk.</li>
<li>If not dead, go to 1</li>
</ol>
<p>I exited that loop before dying, but we’ve already established that I
wasn’t a fantastic team member. </p>
<p><img alt="not the actual hill we used..." src="/media/images/articles/hills.jpg" title="A massive hill" /></p>
<p>There was a bit of good cop/bad cop dynamic going on with our coaches.
The head coach would scowl his scowl of disapproval (your mom was
right when she said your face can freeze that way) and occasionally
yell that we needed to push up the hill hard. Coach Anderson was much
more likely to tell us to take it easy on the way back down.</p>
<p>Why the emphasis on an easy jog back down the hill? Wasn’t this a
work day? Sure, but we were pegging our ability to move oxygen
through our body and convert it to energy, and the run up the hill is
where we would get the most benefit. Better to really rest on the way
down and go all out on the way up than to do both poorly.</p>
<p>Recent studies concerning interval and Tabata training
claim that regular short sessions of intense work punctuated by even
shorter rest periods are, minute for minute, far more effective at
keeping us healthy and growing our capability for converting oxygen
into work than equally regular long sessions of distance and endurance training.</p>
<p>I’ve long felt the same way about work. Work hard when you’re
working, and rest when you’re not. Don’t fool yourself into thinking
that a 12 hour day 5 days a week with “easy” 4 to 8 hour days on the
weekend are doing you and your company a comparatively amazing amount
of good. The burden of proof is certainly on you if you insist that
hours equal productivity. Track how much time you’re <em>really</em>
working, how many bugs you’re writing. I’d love a real time widget
that would pop up when my typos per minute rose significantly above
average, as that’s a pretty good indicator of fatigue for me.</p>
<p>The 40 hour work week came into fashion for a scientifically studied
reason, and it wasn’t for your comfort.</p>
<h2>Sprint</h2>
<p>Work hard when you’re working. </p>
<p>I recently had a self imposed 12 hour work day spent developing some
lab material for a workshop. I’d been making decent progress in fits
and starts, but the workshop was coming up quick, so I applied caffeine
liberally and cranked through a ton of work in short order. The work
was good, and I felt fantastic about my progress. I had grand plans
of an early bedtime so I’d be effective the next day. </p>
<p>A bit of misfortune changed those plans, and I ended up working
through most of that next night. It was intense. It was focused. It
was fruitful. It got a little stupid toward the end. Typos shot
through the roof, as did hardcoding values, as did copy and paste
coding. A younger me would have plowed through, bestowing upon the
team a pile of code that would be trouble.</p>
<p>I was done. Caffeine had extracted my maximum sustained effort. I
sprinted up the hill as long as I could, and it was time for a gentle descent.</p>
<h2>Jog. Don’t Run, Don’t Walk</h2>
<p>Work hard when you’re working. Rest when you’re not. Rest well, rest
actively. Plowing through the better half of a bag of Reese Peanut
Butter Cups and vegging out in front of Arrested Development is
probably not the rest you deserve, even if it is the rest you want,
and even if I’ve done this very thing and other things like it several
times in my life.</p>
<p>Sleep well and make time for activities away from the keyboard to give
your subconscious time to do what it does best: work on tricky problems
without you. Solitary real world activities seem to work best for me:
painting a room, plumbing, building stuff like desks and shelves, and
even cooking. (It’s the eating of things cooked where I’m at risk of
overdoing it…)</p>
<p>You’re probably different. Maybe it’ll be yoga, meditation, wrenching
on cars, or practicing music. Find your non-programming activity that
keeps your brain active while giving your programming muscles a rest.</p>
<p>I went home after my two day sprint, and I landed in bed for a long
time. I didn’t play video games, and I didn’t surf reddit. I slept.
It was gloriously comfortable, and I felt recharged when I woke up.
After a day of cutting in paint around the house I was ready to get
back into emacs and create.</p>
<h2>Acknowledgments</h2>
<p>I’m very happy to work in an <a href="http://www.egov.com">organization that values effectiveness</a> over hours clocked.<br />
It’s almost like the lessons of <a href="http://www.amazon.com/Peopleware-Productive-Projects-Teams-ebook/dp/B003I84OIU">Peopleware</a> have
made their way into the subconscious of managers so many years after
its publication.</p>
<p>I’d also like to thank <a href="http://www.flickr.com/photos/minnellium/">Dave Haygarth</a> for posting his photos under
a <span class="caps">CC</span> license. The photo I used in this post is available under the
title <a href="http://www.flickr.com/photos/minnellium/2582983687/">Knowle Hill fell race</a>.</p> Scheduled Job Anti-Patterns - We Don't Need Version ControlTim Freund2012-10-13T16:43:00Z2012-10-13T16:43:00Z/blog/sjap_version_control.html
<p>Scheduled jobs tend to suck a bit. They’re usually written after they’re
needed and dropped into place with little testing and no plans for fixing
them when things go pear-shaped. </p>
<p>This is the third in the series. Here’s the full list that we’ll cover:</p>
<ul>
<li><a href="http://tim.freunds.net/blog/sjap_everything_is_important.html">Everything is important, email all results</a></li>
<li><a href="http://tim.freunds.net/blog/sjap_nothing_will_break.html">Nothing will break, so why worry</a></li>
<li><a href="http://tim.freunds.net/blog/sjap_workflow_orchestration_through_cron.html">Workflow orchestration with cron</a></li>
<li>It’s just a script, we don’t need version control</li>
</ul>
<h1>It’s just a script, we don’t need version control</h1>
<p>If you ever say these words to me as I’m cleaning up a mess caused by
you making a “non-impacting change” to a scheduled job that isn’t
under version control, then you’re going to see a look come across my
face. Behind that look, my brain is calmly keeping my hands from
reaching for the nearest blunt object while mentally filing you away
as “someone who’s lucky to have a job in <span class="caps">IT</span>” and trying to figure out
how to best extract ourselves from the mess we’re in. My brain’s
multitasking just isn’t good enough to do those things and maintain a
poker face. Sorry.</p>
<p>This is what happens when you say that version control isn’t necessary.</p>
<pre><code>-rwxr-xr-x 1 jobsuser jobsuser 6805 Mar 7 2012 sales_prod_export.pl
-rwxr-xr-x 1 jobsuser jobsuser 7.6K Jul 10 2010 sales_prod_export_maint2_2.pl
-rwxr-xr-x 1 jobsuser jobsuser 7.7K Jun 16 2010 sales_prod_export_maint2.pl
-rwxr-xr-x 1 jobsuser jobsuser 7.7K Jun 1 2010 sales_prod_export_maint.pl
-rwxr-xr-x 1 jobsuser jobsuser 2270 Mar 10 2010 sales_prod_export_work.pl
-rwxr-xr-x 1 jobsuser jobsuser 15043 Mar 24 2012 sales_prod_force_send.pl
-rwxr-xr-x 1 jobsuser jobsuser 12564 Aug 26 04:24 sales_prod_verify.pl
-rwxr-xr-x 1 root root 15659 Jul 19 19:52 sales_prod_verify.pl.bkp
-rwxr-xr-x 1 jobsuser jobsuser 12568 Sep 12 20:32 sales_prod_verify_maint.pl
-rwxr-xr-x 1 jobsuser jobsuser 16K Sep 3 2010 sales_prod_verify_maint2.pl
-rwxr-xr-x 1 jobsuser jobsuser 14K Jun 30 22:02 sales_prod_verify_maint_new_20120629.pl
-rwxr-xr-x 1 jobsuser jobsuser 16K Jun 30 21:55 sales_prod_verify_maint_new.pl
-rwxr-xr-x 1 root root 16K Mar 1 2012 sales_prod_verify_maint_tim_just_this_once_20110809.pl
-rwxr-xr-x 1 jobsuser jobsuser 16K Aug 10 2011 sales_prod_verify_maint_tim_since_that_is_the_fashionable_thing_to_do.pl
-rwxr-xr-x 1 root root 16K Jan 29 2011 sales_prod_verify_maint_variable.pl
-rwxr-xr-x 1 jobsuser jobsuser 13K Jun 29 2011 sales_prod_verify_maint_vsmith.pl
-rwxr-xr-x 1 jobsuser jobsuser 16207 Aug 13 15:34 sales_prod_verify-yesterday.pl
</code></pre>
<p>There are 17 copies of this one script. That’s dumb. This is a fictionalized
real world example, so I’m going to stand up straight and take credit for these
two here:</p>
<ul>
<li><code>sales_prod_verify_maint_tim_just_this_once_20110809.pl</code></li>
<li><code>sales_prod_verify_maint_tim_since_that_is_the_fashionable_thing_to_do.pl</code></li>
</ul>
<p>The sarcasm was lost on this system’s maintainer. Either that, or his
brain’s multitasking managed to keep a straight face while he
pondered the quickest way to punch me in the nuts and get away with it.</p>
<h2>Version Control is too Easy</h2>
<p>Version control is too easy not to use for the scripts and
configurations that keep your shop humming. You may not trust that
statement if your last encounter with version control involved <span class="caps">CVS</span> or,
to a lesser extent, Subversion, but I swear to you that it is true. </p>
<p>Distributed version control systems let you set up repositories on a
local system without ever interacting with a central server. You
don’t need to request a new repository from the version control
gatekeepers, you just need to <code>init</code> a new repository in place. For
bonus points you’re going to back this repository up to a remote
location, but that’s outside of our scope here today.</p>
<p>Right now you just need to pick one of the two following tools:</p>
<ul>
<li><a href="http://git-scm.com>">Git</a> (<a href="http://git-scm.com/documentation">learn more about git</a>)</li>
<li><a href="http://mercurial.selenic.com/">Mercurial</a> (<a href="http://hginit.com/">learn more about mercurial</a>)</li>
</ul>
<p>They both work just about everywhere that matters today, and they behave
nearly identically for the stuff we’ll be doing. If you have developers
on staff or as friends, ask them what they use. Otherwise, flip a coin.</p>
<p>Once you have the binaries installed, you’re only a few commands away
from version controlled bliss. We’ll walk through creating a
repository, seeing the status of the repository, committing unsaved
changes, and reviewing the change log below.</p>
<p>With mercurial:</p>
<pre><code>$ hg init
$ hg status
? really_important_script.sh
$ hg add
adding really_important_script.sh
$ hg commit -m "Committing really_important_script.sh so we don't lose changes like last time."
$ hg log
changeset: 0:0d058a3f5c18
tag: tip
user: Tim Freund <tim@freunds.net>
date: Sat Oct 13 16:09:06 2012 -0500
summary: Committing really_important_script.sh so we don't lose changes like last time.
</code></pre>
<p>And with git:</p>
<pre><code>$ git init
Initialized empty Git repository in /Users/tim/src/dvcsdemo/git/.git/
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# really_important_script.sh
nothing added to commit but untracked files present (use "git add" to track)
$ git add really_important_script.sh
$ git commit -m "Committing really_important_script.sh so we don't lose changes like last time."
[master (root-commit) 9d9f3d1] Committing really_important_script.sh so we don't lose changes like last time.
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 really_important_script.sh
$ git log
commit 9d9f3d12eaa3d56a9bf0e12364c411baafed2753
Author: Tim Freund <tim@freunds.net>
Date: Sat Oct 13 16:10:02 2012 -0500
Committing really_important_script.sh so we don't lose changes like last time.
</code></pre>
<p>And that’s really all there is to it. Every time you make a change to
your scripts, simply commit the changes before you move on to your
next task. You’ll eventually want to learn how to revert to previous
versions and share your repositories with others, but just doing what
we’ve worked through today will set you up for success when making
changes to scripts.</p> Scheduled Job Anti-Patterns - Workflow Orchestration with CronTim Freund2012-10-04T01:07:00Z2012-10-04T01:07:00Z/blog/sjap_workflow_orchestration_through_cron.html
<p>Scheduled jobs tend to suck a bit. They’re usually written after they’re
needed and dropped into place with little testing and no plans for fixing
them when things go pear-shaped. </p>
<p>This is the third in the series. Here’s the full list that we’ll cover:</p>
<ul>
<li><a href="http://tim.freunds.net/blog/sjap_everything_is_important.html">Everything is important, email all results</a></li>
<li><a href="http://tim.freunds.net/blog/sjap_nothing_will_break.html">Nothing will break, so why worry</a></li>
<li>Workflow orchestration with cron</li>
<li>It’s just a script, we don’t need version control</li>
</ul>
<h2>Workflow Orchestration with Cron</h2>
<p>I’m going to show you a small file built primarily for generating support
tickets. There’s a crontab file on <code>appserver01</code> that looks like this:</p>
<pre><code>05 0 * * 1-5 /home/vrichards/salesdb/make_the_ach_file.pl 31 > /dev/null 2>&1
25 0 * * 1-5 /home/vrichards/salesdb/edit_the_ach_file.pl 31 > /dev/null 2>&1
27 0 * * 1-5 /home/vrichards/salesdb/copy_the_ach_file.pl 31 > /dev/null 2>&1
</code></pre>
<p>Sad yet? No? What if I told you there were 30 other sets of such
jobs? Still not sad? What about when you log in to <code>appserver02</code> and find:</p>
<pre><code>30 0 * * 1-5 /home/vrichards/salesdb/send_the_ach_file.pl 31 > /dev/null 2>&1
</code></pre>
<p>Gah!!! On the surface these crontab files are built to generate a file and transmit
it to a bank, but each of the following made me die a little bit on the inside:</p>
<ul>
<li>Scripts running out of a developer’s home directory</li>
<li>Magic number parameters (“Tim!”, you yell, “the command
has a help function and it’s up to date. That parameter is obvious
and self documenting!” You’re a dirty liar, and I hate you)</li>
<li><a href="http://tim.freunds.net/blog/sjap_nothing_will_break.html">Redirecting all output to /dev/null</a></li>
<li>Running one process across multiple hosts without justification when all steps could run on one host</li>
</ul>
<p>Gross. All of it. We aren’t even here to talk about any of the above,
but you should get in touch if you’d like to know why any of the above
are terrible ideas.</p>
<p>We’re here to talk about trying to orchestrate a complex work flow
with individually scheduled cron jobs. We are <strong>not</strong> here to talk about
orchestrating a complex work flow with individually scheduled cron
jobs, because that’s not really possible in any realistic way. We are
here to discuss trying (and failing) to do the same.</p>
<h3>The road to Hell is paved with good intentions</h3>
<p>Our completely fictionalized developer, Victor Richards, means well.
He really wants to be helpful and write things in a way that makes
problem solving easy. Much like breaking up a monster function that
spans pages of editor space into multiple easily composed functions,
he’s broken up the creation and transmission of
<a href="https://www.nacha.org/"><span class="caps">ACH</span></a> files into discrete steps. That’s
legitimately thoughtful. It allows the ops team to retransmit a file
if the bank’s <span class="caps">FTP</span> server was down without regenerating it from scratch.</p>
<p>He’s built all the individual components required to make a fairly
robust system that will churn out bank files each business day, but
gluing them together with cron is a recipe for pain and an active
support queue. </p>
<h3>Turning up the heat</h3>
<p>Victor’s good intentions turn Hellish toward the end of the month.
Website traffic and orders go through the roof. It’s not unusual to
double typical order volume at month end, and quarter and year end
gets even crazier.</p>
<p>That first job in the chain, <code>make_the_ach_file.pl</code>, gets a full 20
minutes to run in the cron schedule. It’s a pretty beastly script
that pulls all of yesterday’s orders out of the database to generate a
bank file, and the queries used aren’t optimized all that well. The
20 minute window usually provides a 5 minute cushion before the next
job, <code>edit_the_ach_file.pl</code> starts to run, at least until the
calendar creeps up to the end of a month. The larger month end order
volume means that the file generation either just barely completes in
time or is late, and the multi-car pile up begins.</p>
<p><a href="http://www.flickr.com/photos/lianza/1810648348/" title="Donate Your Car by tlianza, on Flickr"><img src="http://farm3.staticflickr.com/2077/1810648348_32bb811d8b.jpg" width="500" height="223" alt="Donate Your Car"></a></p>
<h3>Traffic Control</h3>
<p>We have three jobs that are tightly related, with each subsequent job
being completely dependent on the job that runs before it. What we
need is some way to ensure that the jobs run serially instead of
achieving accidental parallelism when one of the jobs runs longer than
expected. That turns out to be so easy that you’ll be forgiven for
missing the obvious. It just takes one script:</p>
<pre><code>#!/usr/bin/env bash
customer_id=$1
/home/vrichards/salesdb/make_the_ach_file.pl $customer_id
/home/vrichards/salesdb/edit_the_ach_file.pl $customer_id
/home/vrichards/salesdb/copy_the_ach_file.pl $customer_id
</code></pre>
<p>Then our crontab file on <code>appserver01</code> looks like:</p>
<pre><code>05 0 * * 1-5 /home/vrichards/salesdb/ach_file_suite.sh 31 > /dev/null 2>&1
</code></pre>
<p>As a bonus, we still have the individual scripts available for use
during troubleshooting exercises should they be necessary. </p>
<p>This is still the poor man’s form of process orchestration, but we’ve
eliminated an entire class of support issues by ensuring that all the
individual jobs run in the correct sequence, regardless of how long
any of those individual jobs takes to complete.</p>
<h3>But wait! There’s more!</h3>
<p>This is third in the series.
<a href="http://tim.freunds.net/blog/atom.xml">Subscribe</a> or come back
tomorrow to see more.</p> Scheduled Job Anti-Patterns - Nothing Will Break, so Why WorryTim Freund2012-10-01T00:07:00Z2012-10-01T00:07:00Z/blog/sjap_nothing_will_break.html
<p>Scheduled jobs tend to suck a bit. They’re usually written after they’re
needed and dropped into place with little testing and no plans for fixing
them when things go pear-shaped. </p>
<p>This is the second in the series. Here’s the full list that we’ll cover:</p>
<ul>
<li><a href="http://tim.freunds.net/blog/sjap_everything_is_important.html">Everything is important, email all results</a></li>
<li>Nothing will break, so why worry</li>
<li>Workflow orchestration with cron</li>
<li>It’s just a script, we don’t need version control</li>
</ul>
<h2>Nothing Will Break, so Why Worry?</h2>
<p>If you’ve spent any time at all running unix systems, you’ve seen the
following pattern:</p>
<pre><code>26 * * * * /usr/local/bin/fixStaleJobStatus.pl 2>&1 > /dev/null
</code></pre>
<p>Regardless of the return code or output of that script, you’ll never
see a peep from it. All the output is dumped squarely into the bitbucket. </p>
<p>How do jobs end up configured like this? They’re usually written,
tested, and watched closely for some period of time: a week, a month,
or more. Once the author is convinced that the job is invincible, she
gets tired of seeing the output in her inbox each day, so she adds
the redirection to make things easy for herself.</p>
<p>Only marginally better are the admins that set up an elaborate maze
of mail rules to filter any and all output from scheduled jobs into
some rarely read folder. Sure, the output is there, but it may as
well not be there if it’s getting ignored completely. Yes, it’s
nice to be able to confirm the user error reports that will start
to trickle in, sometimes weeks after the problem started, but it’s
not exactly the professional way to handle things. </p>
<p>I suppose one step beyond that is the admin that rolls into the office
at 10:45, opens Outlook, hits <span class="caps">CTRL</span>+A then Delete, and then gets up to
retrieve his morning cup of joe. Cron output problems <b><span class="caps">AND</span></b> user
problems solved all in one quick key chord. Shameful, but that dude is
so far off the reservation that I’m sure he’s not here among us. Right?</p>
<h3>So how do we dodge this?</h3>
<ol>
<li>Find a cron wrapper script that only notifies the team on errors.
<a href="http://habilis.net/cronic/">Cronic</a> makes this super easy to pull
off. It’s a shell script, so it should run just about anywhere
that matters without compiling anything.</li>
<li>Edit jobs to write their results to a centralized location for
intelligent monitoring and notifications. This has its merits, but
you’re going to need some additional infrastructure and development
time. A big enough shop will justify this. Email can only scale
so far. </li>
<li>Wait for the users to call. They know when the important stuff isn’t
happening. If a job fails in the server room and no one complains,
does it really need to be fixed?</li>
</ol>
<p>The astute among you will notice that we’re reusing the same list from
our last installment. Two serious suggestions and one suggestion that
is unfortunately in use in far too many places. These two
anti-patterns really are identical twins that were separated at birth. Some
might even combine the two into one, but let’s consider them both
separately lest we over-correct from one straight into the other.</p>
<h3>But wait! There’s more!</h3>
<p>This is the second in the series.
<a href="http://tim.freunds.net/blog/atom.xml">Subscribe</a> or come back
tomorrow to see more.</p> Scheduled Job Anti-Patterns - Everything is ImportantTim Freund2012-09-24T02:07:00Z2012-09-24T02:07:00Z/blog/sjap_everything_is_important.html
<p>Scheduled jobs tend to suck a bit. They’re usually written after they’re
needed and dropped into place with little testing and no plans for fixing
them when things go pear-shaped. </p>
<p>This is the first in the series. Here’s the full list that we’ll cover:</p>
<ul>
<li>Everything is important, email all results</li>
<li><a href="http://tim.freunds.net/blog/sjap_nothing_will_break.html">Nothing will break, so why worry</a></li>
<li>Workflow orchestration with cron</li>
<li>It’s just a script, we don’t need version control</li>
</ul>
<h2>Everything is important, email all the results</h2>
<p>The tricky thing about configuring a scheduled job for the first time
is making sure it actually works. The job is going to run in the dark
recesses of the machine, and you’re going to wonder if it’s really
working at first. Email’s a super easy solution to that problem.</p>
<p>Or the sales and refunds processing jobs didn’t run for three days
last week because a disk was full. Customers are angry, and all of
that bile and vitriol is landing right on top of your boss. These
broken jobs are the most important problem in the world right now on
the second floor of Spacely Sprockets, and the sternly worded
interoffice memo makes that painfully clear through exuberant use of
exclamation points and terrible grammar.</p>
<p>Marching orders in hand, every single scheduled job in the environment
is configured to send an email upon completion or failure.</p>
<p>The only thing that progresses faster than the email notification
configuration is a set of corresponding email rules blazing through
the systems and operations group to filter all of that crap out of
their inboxes.</p>
<p>Oh, look, we’re back to square one! As my manager likes to say: if
everything is important, then nothing is important. </p>
<h3>So how do we dodge this?</h3>
<ol>
<li>Find a cron wrapper script that only notifies the team on errors.
<a href="http://habilis.net/cronic/">Cronic</a> makes this super easy to pull
off. It’s a shell script, so it should run just about anywhere
that matters without compiling anything.</li>
<li>Edit jobs to write their results to a centralized location for
intelligent monitoring and notifications. This has its merits, but
you’re going to need some additional infrastructure and development
time. A big enough shop will justify this. Email can only scale
so far. </li>
<li>Dedicate full time staff to sift through email boxes full of cron
notifications and manually re-trigger jobs. There are people
that actually do this. And if you think it’s a sound solution, then
you’re probably in the wrong job. There’s probably a bank someplace
that would love to hire you as a computer operator. </li>
</ol>
<h3>What if the notification systems break? Or the scheduler just stops?</h3>
<p>Oh, they’ll break. Give it time. They’ll break spectacularly.</p>
<p>The big problem with any job monitoring system is watching the
watchmen. Your people or machines have the ability to completely go
off the rails and fail at their jobs for an innumerable number of
reasons. That’s what sent us down this path of notifying on
everything in the first place, remember? People take sick days, and
machines have hard drives that fill up. <span class="caps">OK</span>, the hard drives shouldn’t
fill up, but if you’re so smart, then why are you sending emails from
every single one of your scheduled jobs? </p>
<p>Whatever system we use to notify the team of job failures, we also need
to ensure that the scheduled job runner and notifications systems have a
snug and warm place carved out in the <span class="caps">NOC</span>’s monitoring system. </p>
<p>Any decent method for sorting the wheat from chaff plus solid monitoring
of the servers that do the grinding should set the course for a sane
scheduled job environment. </p>
<h3>But wait! There’s more!</h3>
<p>This is just the first in the series.
<a href="http://tim.freunds.net/blog/atom.xml">Subscribe</a> or come back
tomorrow to see more.</p> Iron Blogger UpdateTim Freund2012-09-16T23:31:00Z2012-09-16T23:31:00Z/blog/iron_blogger_update.html
<p>This one is slightly meta. Blogging about software about blogging.</p>
<p>A few of us read about this <a href="http://mako.cc/copyrighteous/20120709-00">Iron Blogger</a> thing, and we
decided we’d give it a go. I downloaded the provided software, poked
around a bit, and thought I’d try to make something that non-technical
folks could use just as easily.</p>
<p>I didn’t even link to the work in progress last week, as it was pretty
terrible. I was able to manually configure our group, only to have
multiple timezone issues bite us when processing posts.</p>
<p>In the past week I was able to steal away enough time to do the following:</p>
<ul>
<li>Fix the scoring issues caused by timezone differences</li>
<li>Squash a number of other silly bugs</li>
<li>Automate the deployment with <a href="http://jenkins-ci.org/">Jenkins</a></li>
<li>Publish the <a href="https://bitbucket.org/timfreund/ironblogger">IronBlogger repository on BitBucket</a>. </li>
</ul>
<p>During the upcoming week I’d like to tackle the following:</p>
<ul>
<li>Back fill some decent testing. The <a href="https://bitbucket.org/timfreund/ironblogger/changesets">commit log</a> is downright shameful in this regard.</li>
<li>Clean up the default template a bit - lots of default links that don’t work.</li>
<li>Provide clear links to Atom feeds and <span class="caps">OPML</span> downloads.</li>
<li>Allow people to sign up. Right now it’s a read only web app, and thus kinda lame.</li>
</ul>
<p>Once it’s respectably working, I’d also like to reach out to
<a href="http://mako.cc/">Benjamin Mako Hill</a> to see if he has any input on
licensing. I’m heavily borrowing concepts from his <a href="http://projects.mako.cc/source/?p=iron-blogger">Iron Blogger repo</a>, so I’d like to respect his wishes with regard to licensing. Judging from his other work, I’m
guessing it’ll land somewhere in the <span class="caps">GPL</span> family.</p>
<p>With all of that preamble out of the way, feel free to check out our progress so far:</p>
<ul>
<li><a href="http://ironblogger.freunds.net/kc/activity/2012-09-03">Our first official week</a></li>
<li><a href="http://ironblogger.freunds.net/kc/activity">The last week to be scored</a></li>
</ul> A Quick Note About TimezonesTim Freund2012-09-10T01:59:00Z2012-09-10T01:59:00Z/blog/quick_note_about_timezones.html
<p>Some of you lead programming lives that involve 3D graphics, or
physics simulations, or <span class="caps">DNA</span> sequencing. You’re so deep into these
domains that you’ve never had to deal with such mundane things as
dates and times in your code. Bravo. I’m jealous. Skip the rest
of this post and go make something cool.</p>
<p>Two people stopped reading, and the rest of us poor saps are left
to talk a bit about time zones. Don’t worry, this’ll be quick.</p>
<p>Make sure your code is aware of timezones. Do you have a
timestamp/date/datetime field in your database anywhere? Is your
database smart enough to note the timezone of its clients? Is your
software aware enough to know that it may be running code on behalf of
users that are in a different timezone than itself? Are your servers
running in the same timezone as your development machine? </p>
<p>I can’t answer yes to all of those questions, so I’ve gotta go work
on some code…</p> F5 BigIP Standby Warning User ScriptTim Freund2011-03-20T23:08:00Z2011-03-20T23:08:00Z/blog/f5_bigip_standby_script.html
<p><img src="/media/images/articles/f5_standby.png"/></p>
<p><p><a href="/media/files/greasemonkey/standby_warning.user.js">This
Greasemonkey user script</a> inspects the state of an F5 BigIP
device and makes the state text large and red if the device is in
<span class="caps">STANDBY</span> mode.</p></p>
<p><p>You’ll want to edit the script so that it will activate when you browse
to the BigIP devices in your environment.</p></p>
<p><p>Why is this important? I’ve made changes to a device in <span class="caps">STANDBY</span>
mode one too many times, and I suspect I’m not the only one.</p></p> Don't Break The Chain ExporterTim Freund2010-09-25T09:53:00Z2010-09-25T09:53:00Z/blog/dont_break_the_chain_exporter.html
<p><img src="/media/images/articles/dbtc.png" align="right">
Giles Bowkett emphasizes the importance of picking tools that have
export formats in his
<a href="http://gilesbowkett.blogspot.com/2010/08/secrets-of-superstar-programmer.html">Time
Management for Alpha Geeks</a> video. I can’t agree more. Web
connected make my data available most everywhere I go, but I get
nervous when I can’t back up with a local copy. Web services come,
and web services go.</p>
<p>
I have used Don’t Break The Chain for 9 months. It
tracks 9 different habits for me, and I hope it continues to run for
a very long time. To ensure that I will never lose my data regardless
of <span class="caps">DBTC</span>’s continued operation, I wrote an export script. It logs in
to the service and outputs chain data as a <span class="caps">CSV</span>. It will optionally
export to <span class="caps">JSON</span> as well.</p>
<p>If you use <a href="http://dontbreakthechain.com">Don’t Break The
Chain</a>, you should download
my <a href="http://github.com/timfreund/dbtc_exporter">dbtc_exporter</a>
to save a local copy of your chains.</p> SVG + CSV = IMGTim Freund2010-09-22T22:56:00Z2010-09-22T22:56:00Z/blog/svgcsvimg.html
<p>I pushed a new project up to github. It is
called <a href="http://github.com/timfreund/svgcsvimg">svgcsvimg</a>,
and it generates a series of <span class="caps">PNG</span> images from an <span class="caps">SVG</span> template and data
provided in a <span class="caps">CSV</span> file. </p>
<p>I built this tool because I was too lazy to manually create intro
slides for a series of videos. I made the slide template, put all
of the video metadata into a csv file, and then spent two hours hacking
out this little project. It’s true: I could have manually created
all of those slides in that time, but then I wouldn’t have this code
to give away.</p>
<p>My general rule of thumb is to do something manually once. If it comes
up a second time, I will manually complete the task and write down the
steps with an eye toward repeatable automation. Then I’m ready to write
up code when that third time comes around. I had twenty slides to produce,
so I jumped straight to step three for this project.</p>
<p>I used <a href="http://inkscape.org/">Inkscape</a> to create the template,
and the <span class="caps">SVG</span> rendering was done with a combination of <a href="http://cairographics.org/pycairo/">Pycairo</a> and <a href="http://library.gnome.org/devel/rsvg/stable/"><span class="caps">RSVG</span></a>. You do not have any LADSPA effects plugins installedTim Freund2010-09-05T14:20:00Z2010-09-05T14:20:00Z/blog/ladspa_and_jokosher.html
<p>Using Jokosher? Are you getting the error message “You do not have
any <span class="caps">LADSPA</span> effects plugins installed” when attempting to add effects
to an instrument?</p>
<p>Do this:</p>
<p><code>rm -rf ~/.gstreamer-0.10/registry*</code></p>
<p>If you want more information, you can find
it <a href="http://www.gstreamer.net/wiki/FAQ#IinstallednewLADSPAmodules.2BAC8-libvisualpluginsbutthecorrespondingGStreamerelementsdonotshowup.2Cwhat.27sgoingon.3F">in
the GStreamer <span class="caps">FAQ</span></a>. The bug is now closed, but this is still an
issue in Ubuntu 10.04. Once Ubuntu updates their GStreamer packages
this post should be obsolete.</p> PyTexas 2010 AfterglowTim Freund2010-08-30T21:12:00Z2010-08-30T21:12:00Z/blog/pytexas_2010.html
<p>I drove to Waco, <span class="caps">TX</span> for <a href="http://pytexas.org/">PyTexas 2010</a> this weekend. It was
fantastic, and that’s even accounting for the 20 hours I spent behind
the wheel. We had a great turn out, and a lot of good talks.</p>
<p>A huge “thank you” to Bill Chipman and Josh Marshall for
volunteering their time, talents, and gear to the recording effort.
In typical fashion I figured I’d lug a bunch of gear down I-35 and
things would just work out, but it wouldn’t have gone nearly as well
if I had to tackle three rooms all by myself.</p>
<p>A hard drive with the raw files will ship to Bill later this week, and I
think we can get them ready for upload within the next week or two.
Stay tuned for more updates!</p> Configure Postfix to Authenticate with Courier and SASLauthdTim Freund2010-08-21T00:12:00Z2010-08-21T00:12:00Z/blog/ubuntu_postfix_courier_auth_smtp.html
<p>Once upon a time I had Postfix configured to authenticate incoming
<span class="caps">SMTP</span> connections with Courier’s authdaemond. Then I moved servers, it
stopped working, and I never was able to figure out why it failed due to
a rather generic error message. I worked through my options and arrived
at the following:</p>
<ul>
<li>Postfix authenticates with saslauthd</li>
<li>saslauthd authenticates with Courier’s <span class="caps">IMAP</span> server</li>
<li>Courier’s <span class="caps">IMAP</span> server authenticates with Postgresql</li>
</ul>
<p>Courier and most of Postfix were configured a long time ago, so I’m going
to focus on the changes I made this evening while they are fresh.</p>
<h3>Configure saslauthd</h3>
<p>Open /etc/default/saslauthd and change the following:</p>
<ul>
<li><span class="caps">START</span>=yes</li>
<li><span class="caps">MECHANISMS</span>=”rimap”</li>
<li>MECH_OPTIONS=”localhost -r”</li>
</ul>
<p>That last option tells it to connect to the <span class="caps">IMAP</span> server running on localhost
and pass in the realm (domain) of the user. You will most likely need that -r
option if you are hosting multiple domains.</p>
<p>Now start saslauthd: /etc/init.d/saslauthd start</p>
<h3>Configure smtpd.conf</h3>
<ul>
<li>pwcheck_method: saslauthd</li>
<li>mech_list: <span class="caps">PLAIN</span> <span class="caps">LOGIN</span></li>
</ul>
<p>Restart postfix: /etc/init.d/postfix restart</p>
<p>Postfix now authenticates against my <span class="caps">IMAP</span> server, and I can forget that I
wrote this until the next time I execute a server migration.</p> The 7:00 AM Phone CallTim Freund2010-07-08T00:18:00Z2010-07-08T00:18:00Z/blog/seven_am_phone_call.html
<p><a href="http://www.flickr.com/photos/rickharris/394848744/" title="Booths by Яick Harris, on Flickr"><img src="http://farm1.static.flickr.com/186/394848744_1091e535c2_m.jpg" width="240" height="180" alt="Booths" style="float: left;"></a></p>
<p>I much prefer the infamous 3:00 <span class="caps">AM</span> phone call to any 7:00 <span class="caps">AM</span> phone
call. I don’t particularly enjoy either, but I appreciate the gravity
of any situation that warrants a phone call at 3:00 <span class="caps">AM</span>.</p>
<p>7:00 <span class="caps">AM</span> phone calls are often prompted by something strange that
the early guy spots after getting in to the office long
before anyone else. Although the situation usually warrants
attention, it most often does not warrant waking anyone.</p>
<p>Three people on my team were called at 7:00 <span class="caps">AM</span> today because a
scheduled report didn’t run at the normal time because of heavy load
on our reporting server. Transactions were still processing. and the
report was eventually delivered. My team was up late last night doing
scheduled maintenance long after normal business hours to reduce
impact and provide a high level of customer service. We were all a
little perturbed to get wake up calls over a relatively minor issue
after a long night.</p>
<p>Some folks are night owls because they get their best work done at
night. Others are night owls because their work can only be done at
night. The early birds can keep their worms, I only ask that they
consider the night owl’s schedule before picking up the phone at 7:00 <span class="caps">AM</span>.</p> Python DNS ServerTim Freund2010-07-06T21:58:00Z2010-07-06T21:58:00Z/blog/python_dns_server.html
<p>I’ve spent a few hours over the last week working on a Python <span class="caps">DNS</span>
server that uses a database to store name records. Reactions to this
probably come in one of two flavors: “Cool!” or “Seriously, <span class="caps">WTF</span>, use
an existing solution!”</p>
<p>If you immediately like the
idea, <a href="http://bitbucket.org/timfreund/nomenpy">download the
source</a> from bitbucket.</p>
<p>Still here? I guess I have some explaining to do.</p>
<h3>I need a dynamic <span class="caps">DNS</span> server at home</h3>
<p>Either a proper dynamic <span class="caps">DNS</span> server or at least a <span class="caps">DNS</span> server with
some form of <span class="caps">API</span> will do. I work on some sysadmin software and other
software that makes use of network services.</p>
<h3>I never have fully grasped Twisted’s deferred model</h3>
<p>Sure, I’ve written some code that uses Twisted, but it is ugly,
and it never feels quite right or natural to me. I’d like to really
wrap my head around that style of code.</p>
<p>The <a href="http://bitbucket.org/timfreund/nomenpy">NomenPy</a>
project is my attempt to satisfy both of those needs. Twisted
comes with a fully baked <span class="caps">DNS</span> implementation. This allows me to build
out a programmable database backed <span class="caps">DNS</span> server as a thin veneer over
a Twisted foundation. I can see real results while working on a real
problem and learning a new style of programming.</p>
<p>With all of that said, understand that I’m a complete noob
when writing code to fit Twisted’s model. If the code is an atrocious
misuse of Twisted, please let me know what I did wrong. Much thanks
in advance!</p> Success with LifeTim Freund2010-06-23T20:35:00Z2010-06-23T20:35:00Z/blog/life_success.html
<p>Last time around I talked a little bit about my
<a href="/blog/articles/package_signed_incorrectly.html">Game
of Life</a> wallpaper.</p>
<p>It has been a week. In that time I’ve had a small bit of success, and I
am quite happy with the results.</p>
<p><img src="/media/images/articles/life_success.png"/></p>
<p>35 people have software that I wrote on their phones, and one of
them was even kind enough to give me a five star rating. It probably
sounds like I’m making a big deal over 35 people, and I am. I write
software all day long that people use due to contractual obligation.
I’ve never been good at marketing. The Android Market provides a
ready built distribution channel that beats any of my previous
attempts at software distribution, and that has me genuinely excited.</p> Android Package Not Signed CorrectlyTim Freund2010-06-16T22:58:00Z2010-06-16T22:58:00Z/blog/package_signed_incorrectly.html
<p><img style="float: right;" src="/media/images/android/lifewallpaper/lifewallpaper.png"/></p>
<p>I finally rounded off enough of the rough edges in my
<a href="/android/lifewallpaper.html">Game of Life</a> wallpaper
that I decided to put it in to the Android Market this afternoon. Publishing
the application was easy enough, and seeing the application appear immediately
in my search results was fun, but my heart sank when I tried to install the
application on my Nexus One.</p>
<h3>Package file was not signed correctly</h3>
<p>I pulled the application back out of the marketplace to debug it by
installing from a local web server. I tried recreating my signing certificate
9 different ways, all of them resulting the same failed installation. Finally
I decided to start fresh, and I deleted the application before attempting to
reinstall. That did the trick, and it worked for each of the 9 cert variations
I had created.</p>
<p>Be forewarned, this might not solve your problem. It looks like there are
a number of issues that can cause this error message or ones like it. If you
are still having trouble, I’d recommend watching the output of logcat while
running through the installation process.</p>
<p>And in the unlikely even that you came here to learn more about my
<a href="/android/lifewallpaper.html">Game of Life wallpaper</a>, check out the video below:</p>
<p><object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=12624122&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=12624122&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><p><a href="http://vimeo.com/12624122">Game of Life Android Wallpaper</a> from <a href="http://vimeo.com/user3420576">Tim Freund</a> on <a href="http://vimeo.com">Vimeo</a>.</p></p> Emacs Animate Birthday PresentTim Freund2010-06-15T22:09:00Z2010-06-15T22:09:00Z/blog/emacs_animate_birthday.html
<p>Emacs holds features that I would have never imagined. Ever. Some
elisp hacker must have been under the gun to produce something, <em>anything</em>,
for a friend’s birthday to produce <code>animate-birthday-present</code>.</p>
<p>It was a pleasant diversion on my way to correctly
typing <code>ansi-term</code>. Maybe it is just a silly Easter egg, where both
the writing and execution of the function was a pleasant diversion.</p> Fifty State Project ActivityTim Freund2010-06-07T22:07:00Z2010-06-07T22:07:00Z/blog/fifty_states_montana.html
<p>There is something a little bit dirty about screen scraping. In
this modern day and age, isn’t there some sort of RESTful <span class="caps">JSON</span> based
<span class="caps">API</span> for all of the important data? Well, no. But the guys at the
<a href="http://fiftystates-dev.sunlightlabs.com/">Fifty State
Project</a> are trying their best to change that for as much of the
state legislation that they can get.</p>
<p>I spent some time over the last three weeks working on the
legislation scraper for the state of Montana. I picked up
where <a href="http://github.com/TheRealFalcon/fiftystates">another
programmer left off</a>, and most of the heavy lifting was done in a
few days. James really laid down a good foundation, and I was glad
that he was happy to see the work continued, even if it wasn’t by him.
The bulk of my time was spent working out all of the little special
cases that crop up in systems like these. For instance, since the
data is stored in a directory on a web server, folks could put other
stuff out there in addition to legislation, like letters from the
governor. I didn’t think to put a “governor_letter_check” method in
my code until I had scraped 90% of all of the available bills and run
in to this one rogue case.</p>
<p>The work isn’t done yet. Special sessions aren’t yet parsed because
they seem to use an entirely different system, and some meta data
about bills that are only published in <span class="caps">PDF</span> format get missed. I’m taking
a little bit of a break while the guys bang out the ‘newapi’ branch
of the project, but I hope to get back at it soon.</p> Cheap Sound ExperimentsTim Freund2010-05-21T01:12:00Z2010-05-21T01:12:00Z/blog/cheap_sound_experiments.html
<p><img src="/media/images/articles/cheap_sound_experiments-neuropop_overload.jpg" align="right">
The guys at <a href="http://www.neuropop.info/">NeuroPop</a> use
neurosensory algorithms to get in to the heads of their listeners. I
heard about their work on <span class="caps">NPR</span>’s Here and Now show, and I was immediately
intrigued. I work in an open environment, and large portions of my
job involve serious concentration if I ever hope to get anything done.
My noise abatement activities range from simply putting on my headphones
without any music, to <a href="http://www.ninjatune.net/solidsteel/">the
Solid Steel Podcast</a>, to brown noise and rain tracks.</p>
<p>If the NeuroPop guys think they’ve hit upon a combination of sounds
that will encourage the listener to focus, and they are willing to sell
the track for only $0.99, I’m definitely up for some experimentation.</p>
<p>The verdict? It’s neat. It definitely does <em>something</em>, but
I think I am still focusing on the track rather than focusing on the work
that needs to be done. It’ll stay in my rotation, but I’m just as likely
to get into the code zone with a podcast from <span class="caps">DK</span> as I am when listening
to NeuroPop’s focus track.</p>
<p>And for the record, the NeuroPop tracks definitely benefit from
good headphones. I use <a href="http://www.google.com/search?hl=en&q=Sennheiser+HD+265&aq=f&aqi=g5&aql=&oq=&gs_rfai=">Sennheiser <span class="caps">HD</span> 265</a>s at work, and the track
sounds incredible. At home I’m using the <a href="http://www.amazon.com/Sennheiser-RS-170-Wireless-Headphone/dp/B002TLT10I/ref=sr_1_7?ie=UTF8&s=electronics&qid=1274508543&sr=8-7">Sennheiser <span class="caps">RS</span> 170</a>s, and the
track just sounds good.
<p>But that’s not what I really wanted to talk about today. I was
a little shocked at the reaction I got from coworkers when discussing
these NeuroPop tracks. I was asked why I bother with such experiments
when I could just not bother. I got the same reaction when I built
a standing desk at home, and when I went from two monitors to four. I’d
rather run an experiment that fails than always wonder if there was
something to a crazy idea that I heard on the radio. And remember,
we aren’t talking about a lot of money. I spent more driving home
from the office today than I did on this music track. </p>
<p>Failure to experiment sounds terribly dull when compared to the
possibilities locked away in experiments that could fail.</p> Stupid Productivity TrickTim Freund2010-05-18T20:07:00Z2010-05-18T20:07:00Z/blog/stupid_productivity_trick.html
<h3>Or how I keep myself from wasting hours on news.yc and reddit</h3>
<p>I use <a href="https://addons.mozilla.org/en-US/firefox/addon/4476/">LeechBlock</a>
to keep myself from wasting hours of my life on reddit and news.yc.
I have time scheduled in to the day when I can browse to whatever
I want, but for the bulk of my day I have the time wasters blocked.</p>
<p>But that’s not the productivity trick I’m going to write about today.</p>
<p>Since I’m a geek, I have a few browsers installed, and so I have
reflexively learned that when LeechBlock presents me with a blank white
screen, I should open Galeon instead. No productivity gained there,
and it is unfortunate, because I’m often browsing to avoid thinking.</p>
<p>Short of implementing any of the <span class="caps">DNS</span> tricks to block time wasters, I’ve
symlinked the offending browser commands to a script that contains the following:</p>
<p><code>
notify-send -u critical "Get back to work" "Do you really need $0 right now?"
</code></p>
<p>The symlinked look-alike is ahead of the real applications in my
path, so it gets picked up and executed. Most of the time that is
enough to jolt me out of distraction, and in truly dire circumstances
I can always manually execute the full path to the time sucking browser
that I desire.</p> The Joy of ForkingTim Freund2010-05-16T22:30:00Z2010-05-16T22:30:00Z/blog/joy_of_forking.html
<p>The thing I love the most about distributed version control systems is
not my ability to work on a plane, even though that is an oft-cited reason
to use a <span class="caps">DVCS</span>. I am not often on planes, and when I am, I try to sleep
through the experience. The joy of forking is what I most love about any
of the <span class="caps">DVCS</span> systems in use today. Developers are expected to own and
operate their own branch of any given code base if they want to contribute
back to the project, and both forking and merging are made easy to support
this notion.</p>
<p>This is especially helpful in the open source community because it reduces
one of the major risks of small open source projects: maintainer abandonment.
Many small projects have a bus factor of one, and if that one maintainer
has better things to do, the project is guaranteed to stall if the source
code is locked away in a traditional version control system.</p>
<p>Another nice side effect of easy branching and merging is increased
collaboration. I saw a great example of this when I inquired about writing
a state scraper for the
<a href="http://fiftystates-dev.sunlightlabs.com/">Fifty States Project</a>:
a developer was able to give me a jump start by pushing incomplete code up
to GitHub. This allowed me to pull his code, and no one using the canonical
repository was impacted. It was a heck of a lot easier than emailing patch
files, and it saved me a ton of work.</p> Growlish, a growlnotify cloneTim Freund2010-05-10T22:45:00Z2010-05-10T22:45:00Z/blog/growlish.html
<p><img src="/media/images/articles/growlish.jpg" align="right">
<a href="http://ringce.com/hyde">Hyde</a> has optional support for growl
notifications. I was interested to see how Hyde used the growl notifications,
but I no longer own an <span class="caps">OS</span> X machine, so I have no copies of growl.</p>
<p>Ubuntu has a notification system, complete with a command line interface
named <code>notifiy-send</code>, but the options are different than those provided by
<code>growlnotify</code>. I
wrote <a href="https://launchpad.net/growlish">growlish</a> to fill
the gap.</p>
<p>There is probably more boilerplate than code in the project. The pynotify
<span class="caps">API</span> is very easy to use, so the actual notification implementation is tiny.
Never the less, I thought it might be useful to someone, so have at it. I
saw that someone else had posted a similar utility a couple of years ago, but
the code was missing, so I reinvented this particular wheel.</p> SSL Cert SupportTim Freund2010-05-06T21:48:00Z2010-05-06T21:48:00Z/blog/cert_support.html
<p>Just heard about someone complaining that an <span class="caps">SSL</span> certificate was incompatible with
their application server. It turns out that their application server is really, really
old, but somehow this wasn’t the problem. The guys who procured
the fancy new cert for the third party service were obviously at fault.</p>
<p>The real problem is that people will pay $20K+ per <span class="caps">CPU</span> for an application server because
it comes with support, and then they realize when it is too late that their support dollars
don’t really buy them much in the way of assistance when things don’t work out right, so
then the suckers with the support contract need to pawn off all of their problems on to
third parties that are just trying to efficiently run a service.</p>
<p>It doesn’t help that the $20K+ per <span class="caps">CPU</span> application server is such a monster to install
and maintain that no one really wants to upgrade until they absolutely must. The folks
in question were running said application server under Java 1.4, and that was <span class="caps">EOL</span>’ed in 2008,
so I can only imagine how old the application server is. I can’t understand how such a
situation is at all preferable to running something open source and up to date. The money
spent on licensing can be better spent on people who can actually solve real problems as
they come up.</p> First PostTim Freund2010-05-02T22:19:00Z2010-05-02T22:19:00Z/blog/first_post.html
<p><img src="/media/images/articles/first_post-JekyllHyde1931.jpg" align="left"> I did it again. I changed the way I blog. I don’t want to go too
far meta, but I would like to point out that the guys
behind <a href="http://ringce.com/hyde">Hyde</a> have created a nice
little static website generator.</p> Tim Freund2010-01-01T00:00:00Z2010-01-01T00:00:00Z/blog/archive.html