Fedora 20 on a Macbook Air

Update 3/24/2014: Suspend working well, moving to mba-fixes RPM

Update 3/23/2014: Removing RPM version of backlight also added some attempts at avoiding wakeups

Update 2/17/2014: Added tip on reloading the wireless module

Update 2/5/2014: Added instructions for a shared partition and better backlight driver installation

With Fedora 20 out, it was time to refresh my Macbook Air (model 6,2) installation and see what I could get working.  You might have seen my earlier post using Fedora 19 but this time around, things went much smoother.  I’ve also tried to cover the initial installation with a little more detail, so hopefully that will help out someone just getting going.

Step 0 – Uninstall rEFIt

If you had previously installed Fedora on your Macbook like myself, you probably installed rEFIt as your bootloader.  Since that project is no longer maintained, you’ll want to uninstall it and move to the newer Refind bootloader.  I uninstalled Refit using their instructions and it worked fine. After uninstalling, I made sure I could boot into OSX by just rebooting and it worked.

Step 1 – Install Refind

I followed the Refind Mac OSX Instructions and while it was a few steps of pasting things into the terminal, it went very smoothly.  Since I have the MBA 6,2 model, I kept the 64 bit binary and drivers.  Also, the instructions mention that you can remove drivers to optimize boot time but I only removed the HFS driver.

Step 2 – Build Fedora 20 USB Key

First I downloaded the Fedora 20 ISO and followed these instructions to build a USB key.  I followed the Mac OSX section and used the dd program to create the key.  Worked like a charm.

Step 3 – Install

With the newly created USB key plugged in, you’ll want to restart and immediately hold down the Option key on your Mac.  That will pull up the boot device options and you can select the ‘Fedora Media’ option.

Note – I wasn’t able to successfully check the media.  When I tried, I received errors about a devmapper device not being present.  Continuing without checking worked fine for me.

Important - I’m going to describe how to do a clean install as that is what I normally do.  This is going to delete any existing Fedora installation you might have.  Also, if you mess up partitions, it could delete some of your Mac data as well.  This is the point where you need to triple check that you have all your stuff backed up.  I don’t claim this installation is fool-proof nor do I want anyone accidentally reformatting their machine as a part of this effort.  Make sure if that happens, that you aren’t going to permanently lose anything.

Step 3.1 – Partitions

Since I had Fedora 19 installed on encrypted partitions, it was a little confusing for me at first how to make sure the Fedora 20 partitions were created properly.  The following steps did the trick for me:

    • Select the encrypted partitions and unencrypt ALL of them
      • At this point, you should see the Fedora 19 partitions recognized, including swap
    • Delete all of the Fedora 19 partitions.  Remember – clean install being described
    • Click the link to auto-create the Fedora 20 partitions
    • Apply the changes

Sharing a partition with OSX

I wanted to share some data and documents between my OSX instance and my Fedora setup.  To do this, I actually changed the mount point of the /home partition in the Fedora 20 list to /mnt/shared (I had left enough space on the / partition).  I also changed the filesystem to Linux HFS+.  I assume that is just a non-journaled HFS+ partition.  Anyway, it created on install and mounts up on Linux.  The only thing I had to do was sync the UID of my Linux user with my already existing Mac user of the same name.  To do that, I switched to runlevel 1 and just ran (replace the contents in the braces with your values):

sudo init 1
# Put in root password
usermod -u <MAC_UID> <LINUX_USER>
chown -R <LINUX_USER> /home/<LINUX_USER>

After doing this, I was successfully able to read and write files when booted into Linux or Mac OSX.  I symlinked most of my directories like ~/Documents to that share.

At this point, you’ll let the install proceed as normal and you’ll create your users, root password, etc.  From this point on, I’ll assume you are running these steps from your newly installed Fedora machine.

Step 4 – Update

First odd thing I hit was that after the installation, PackageKit was telling me everything was up to date, so I had to run yum at the command line:

sudo yum update

That worked fine and applied a few hundred updates.  Reboot to get the new kernel.

Step 5 – RPM Fusion (extra packages)

You’ll want to install RPM Fusion to get the wireless drivers among other things.  You can either following the RPM Fusion docs or following these condensed steps:

  • Click this link on your Fedora machine and install it (free repo)
  • Click this link on your Fedora machine and install it (non-free repo).

Step 6 – Wireless

Now with the RPM Fusion repos, you can just install the broadcom wireless drivers:

 sudo yum install kernel-devel akmod-wl

Reloading the wireless module

After updating my kernel, the wireless module didn’t load automatically for me.  I’m fairly new to akmods so I’m not sure if the new akmod wasn’t built, loaded or what.  However, here is what I did to fix

# Make sure the module built for your kernel
sudo akmods

# See if the module is loaded (if no results, it's not)
sudo lsmod | grep wl

# Manually load the module
sudo modprobe wl

Step 7 – Backlight

Once of the most annoying things for me with Fedora 19 on my Macbook was that the backlight would always go to 100% after a resume.  Luckily Patrik Jakobsson came to the rescue and implemented a new kernel module specifically for the Macbook Air 6,2.  The source of his driver is located here.  To build it, simply follow the instructions on his repository.  You’ll need to rebuild and install the driver on each kernel update.

For the X11 configuration file, I just create a file in /etc/X11/xorg.conf.d/01-backlight.conf with his suggested X11 configuration specifying the driver.  It works great.

Why did I give up on the RPM?  Well, I tried to hack around actually learning how to build a kmod RPM and the results just weren’t consistent.  Without calling ‘make modules’ and ‘make modules_install’ properly, the module wouldn’t always get loaded properly.  If there are any volunteers that are willing to put the mba6x_bl driver in a kmod RPM, I’m happy to host it.

Step 8 – SSD errors and Keyboard mapping

The next things I hit were some sporadic SSD errors.  In this thread, I found that I was able to set a queue depth to 1 and my errors largely went away.  Also, the tilde is mapped improperly so you need to apply a fix for that.  I’ve bundled both of these fixes as systemd service and a udev rule that will run at startup.

Step 8.1 – Add MattOnCloud Repository

I’ve created a yum repository that contains a built version of this code for Fedora as well as some of the other fixes below.  I’m keeping the source on GitHub and pull requests are definitely appreciated.  This was my first attempt at a package that would automatically rebuild with kernel updates so install at your own risk…  To install my repository, run:

sudo rpm -Uvh https://files-oncloud.rhcloud.com/yum/RPMS/x86_64/oncloud-repo-0.4-1.fc20.x86_64.rpm

To apply the fixes, then run:

sudo yum install mba-fixes

Wakeups after Suspend

I found the following blog which describes a way to avoid wakeups after suspending.  This is a bit of a pain for me since I’ll suspend at night only to have it wakeup after I’m asleep and drain the battery.  I’ve created a systemd script that runs each startup and disables XHC1 and LID0 from waking the machine up.  This means that after closing the lid to suspend, you need to open the lid and push the power button to wake the machine up.  This is now installed by the mba-fixes RPM.

Random Items

I went ahead and ran Fedy to setup a bunch of other random things, including the better IO scheduler for a SSD.  I would probably recommend doing that – there are a couple of options, but Fedy is pretty nice.

End Result

The end result with Fedora 20 is an impressive setup.  Mini-display to VGA projection actually works this time around which was a huge win for me.  Sound also works right out of the box.  Performance seems solid and I’ll be tracking battery life and updating.

I’ll keep you updated!

The Evolution of PaaS

Having spent three years now working on OpenShift, the lesson I’ve learned from working in the cloud space is that if you aren’t evolving, you are doing something wrong.  PaaS isn’t a static solution but a constantly progressing set of technologies to enable a better approach to building and running applications.  But at Red Hat, the open source way is a critical aspect of how we work.  To us, that means finding the best technology and best communities out there and working with them instead of against them.  That is why we created OpenShift Origin with the mission of being able to experiment along with other communities to find the best solutions for our users.  With that mission in mind, we are always looking for those adjacent communities and determining if they are a good fit.  Looking ahead to next year, I see a couple of exciting community developments on the horizon, one centered around Linux Containers and the other centered around OpenStack.
 
 
First, let’s talk about Linux Containers.  Personally, I think Linux Containers is one of the most exciting developments in the Linux kernel today.  The combination of kernel namespace capabilities, coupled with Linux Control groups and a strong security model is changing how users think about isolating applications running on the same machine.  But much like PaaS, Linux Containers isn’t a static solution.  There are a lot of options that can be utilized to strike the right balance of isolation versus overhead.  On OpenShift, we’ve been using our own variant of Linux Containers since day one.  But there is a lot of community activity around containers and a few months ago, we noticed Docker.  Docker introduced an innovative approach to container isolation and packaging which had the potential to both simplify our cartridges in OpenShift and increase user application portability.  But a lot of stuff looks interesting on the surface.  We wanted to really dive in (i.e. start hacking) to see if this would be a good fit.  We had a great experience working with the leads behind Docker and were able to close many of the initial gaps we hit to make Docker run seamlessly on the platforms critical to us, Fedora and RHEL, to enable us to start utilizing it on OpenShift.  During that same time period, Docker was accepted as a Nova driver to the OpenStack project.  With that foundation, we are getting ever closer to having a consistent portable container layer across the operating system (e.g. RHEL), IaaS (e.g. OpenStack) and PaaS (e.g. OpenShift).  Better still is that we are able to take our experience with containers and work with hundreds of other community members to come up with the best approach going forward.
 
 
But as excited as we are about the evolution of containers and better portability of applications, we also know the operational experience is equally critical.  And more and more, that operational experience is centered around OpenStack.  While we can run OpenShift very well on OpenStack and are even enabling better integration through projects like Heat and Neutron, we’ve had the feeling that there is a more fundamental set of capabilities in our platform today that could be native to OpenStack itself.  And in doing that, we could drastically improve the operational experience.
 
 
But I think it helps to talk through some of those operational challenges.  An example of this is the visibility of containers in OpenStack.  Almost every PaaS on the market right now uses some form of Linux containers.  Arguably, it’s what makes a PaaS so efficient – this highly elastic mesh of containers that form your applications.  However, if that PaaS doesn’t natively integrate with OpenStack, your operations team isn’t going to see those containers.  They are just going to see the virtual machines in OpenStack and not have deeper visibility.  But if that PaaS was natively integrated into OpenStack, things get interesting.  The containers themselves could be managed in OpenStack, opening up full visibility to the operations team.  They wouldn’t just see a virtual machine that is working really hard, they would see exactly why.  It would enable them to start using projects like Ceilometer to monitor those resources, Heat to deploy them, etc.  In other words they could start leveraging more of OpenStack to do their jobs better.  But where do you draw that line?  Should OpenStack know about the applications themselves or just containers?  In looking for those answers, we wanted to embrace the OpenStack community to help us draw that line, just like we did with Linux Containers.
 
 
OpenStack has a tremendous community and various areas where we could have started  - Nova, Neutron, Heat, Ceilometer, Keystone, etc.  At the end of the day, we were going to need to interact with all of them.  That led to the Solum project.  You might have seen the announcement today around the new community project.  We will be working with a group of like minded companies and individuals to figure out the approach that makes the most sense for OpenStack.  While OpenStack is a fast moving space, we have a lot of experience with it and believe that there is tremendous potential to align our PaaS approach with this project.  Being Red Hat, we love community driven innovation, and we’re excited to jump in and help move this effort forward.
 
I think 2014 is going to be the most exciting year for PaaS to date.  There is great traction in the market, developer expectations are starting to solidify and we’re seeing more and more traction in production.  I believe the next advancements will come as much in the operational experience as with the developer experience.  And I’m excited to find healthy and vibrant communities looking to solve the same problem.  The end result will be that OpenShift users benefit from greater portability as well as deeper integration with OpenStack.  This has been one of those moments that just crystallizes why I love working in open source.
 
 
If you are interested in finding out more, follow our progress at OpenShift Origin or get involved with the Solum project directly.  And I’m sure there will be a lot of activity at the OpenStack Design Summit, so If you are going to be there, come find us at one of our talks and we can hack on this together!

An application built from… cartridges?

Background

What are these things called cartridges in OpenShift and why are they so important?  Well, let’s take a step back and look at a typical application.  While some might argue the specifics, most applications are still multi-tier applications and utilize multiple technologies with some separation between them.  A classic case is a web application and a database.  While some of the databases might be experimenting with NoSQL backends, the general pattern largely holds.  And maybe you throw in a caching tier in there or something more exotic, but at the end of the day, very few applications I’ve seen get very far with just a web application runtime and nothing else.

Composition

So if you’re still with me and not yet posting to the comments about that initial claim being ridiculous, let’s talk about how that process often plays out.  When building an application, many developers think from a technology standpoint.  They might think of Ruby and want to use Mongo for storage.  Despite claims that the most effective route is to focus on the use cases first (e.g. I’m building a coupon generating web application that has to store large amount of redundant data), at the end of the day, the technology decision is often a major factor.  I often operate this way myself – half of the time, an idea I’m pursuing is as driven by getting to try out some new technology as it is on a successful and fast implementation.  Engineers like to learn and new technology is a great vehicle for that.

But while the learning curve around new technology has some benefits, it also has many disadvantages.  It’s hard for me to argue that learning to wire up a MySQL database to a Ruby application server versus a Java application server has any practical benefit.  It’s just something I need to do.  I need a database driver for the language I’m using, authentication details and endpoints.  It’s the same in theory but just different enough in every language and runtime to be a major pain.  And databases are well know.  The newer the technology gets, the more time is often wasted on the mundane aspects of integration.  But don’t give up on being a developer yet because this is what cartridges in OpenShift eliminate.

The cartridge model in OpenShift is all about enabling choice in technology and language while also reducing the effort around the integration portions that can be automated.  If you have an application that consists of a JBoss cartridge and a MySQL cartridge, the two are automatically wired together.  You don’t need to know or care about what MySQL driver is being used in JBoss or how the data source is setup.  You can just get down to writing code and queries.  This is beneficial in both development and production.  In development, this gives engineers the ability to trial a lot of different software to find the best solution to their problem.  They can spend more time on the analysis and not the administrivia of learning the setup environment of each technology.  But that same approach and power also extends to production.  Cartridges don’t only automate things like wiring up different components, they also can implement functionality like scaling.  For example, the JBoss cartridge has auto-scaling built in so that when the application is getting more load than it can handle, it will spin up new instances automatically.  And for those who might be wondering, clustering is automatically setup as well – new instances automatically join the cluster.  The goal of the cartridge model is to capture these capabilities in a standardized, easily consumable format that bring benefits throughout the entire lifecycle of application development.

The Technology

OpenShift cartridges have an amazing amount of functionality but there are two capabilities that are my favorite:

  • Providing a first class way to interact with each other, even across multiple machines
  • Giving the cartridges the ability to influence their deployment topology (i.e. can they run embedded with other cartridges or do they scale differently)

Publish / Subscribe

Let’s talk about the interaction model first.  By interaction model, I simply mean having multiple cartridges communicate with each other.  That sounds incredibly simple but it’s also amazingly powerful, especially as you consider building applications from many cartridges.  The concept is that a cartridge like MySQL can publish information about itself that other cartridges might want to know.  For example, when a new MySQL instance is created, you probably need to know the username, password and JDBC URL – all of that information can be published.  That process is described with the cartridge in a file that we call a manifest.  Here is an example of how MySQL actually publishes its connection information in it’s manifest:

Publishes:
  publish-db-connection-info:
    Type: ENV:NET_TCP:db:connection-info
That command will invoke a script called publish-db-connection-info that will publish a collection of environment variables of type ENV:NET_TCP:db:connection-info.  You can think of the type as an arbitrary string that can be used by consumers to filter out what they may or may not support.  This published information can then be consumed by any other cartridge that subscribes to a matching type.  For example, in the JBoss cartridge, you’ll see the following section in it’s manifest:
Subscribes:
  set-env:
    Type: ENV:*
      Required: false
This instructs the JBoss cartridge to listen to all environment variables set by publishing events that start with the string ENV.  More restrictive matching can also be done in cases where you might have a cartridge that is only compatible with a certain class of published information (e.g. subscribing to ENV:NET_TCP:db:connection-info instead of ENV:*).  Either way, if the publish and subscribe string match, the JBoss cartridge has access to the published MySQL information.  With that information, the JBoss cartridge is then able to automatically wire up a datasource definition in standalone.xml by using those values:
<datasource jndi-name="java:jboss/datasources/MysqlDS" 
...
<connection-url>
  jdbc:mysql://${env.OPENSHIFT_MYSQL_DB_HOST}:${env.OPENSHIFT_MYSQL_DB_PORT}/${env.OPENSHIFT_APP_NAME}
</connection-url>
<driver>mysql</driver>
<security>
  <user-name>${env.OPENSHIFT_MYSQL_DB_USERNAME}</user-name>
  <password>${env.OPENSHIFT_MYSQL_DB_PASSWORD}</password>
</security>
...
</datasource>

While this is just a simple example, hopefully the beauty of it to a developer is apparent.  Just the act of adding a MySQL cartridge to your JBoss application will automatically wire up your application to it.  Adding Mongo would do the same thing, as would Postgres, etc, etc.  And this isn’t limited to databases either.  It also works with monitoring cartridges, metrics cartridges, caching, and many others – the possibilities are limitless.

Deployment Topology

The second capability isn’t about the development process as much as it is about production.  We all know that different application technologies scale differently.  You might have a Ruby application whose throughput is determined by the number of Passenger instances that are running.  If it starts slowing down, you need to add more.  However, if this same application depends on a database, you probably need to scale the data tier independently.  You don’t want to add another MySQL instance every time you add a new Passenger instance.  Not only is that unnecessary and expensive, it most likely wouldn’t even work.  When scaling your web tier, you need to think about session affinity, connection persistence, stateless / stateful behavior and similar concepts.  However, when scaling MySQL, you need to think about your master / slave model, how many to add of each and what type of query patterns you are using.  In OpenShift, since these are different cartridges, each cartridge can approach scaling in a unique manner.

From the cartridge standpoint, the Ruby cartridge is going to respond to a scaling events very differently than MySQL.  While this requires real work and thought from the cartridge authors, it captures the complexity in a model that is easily leveraged by developers.  Developers are able to specify how they want scaling to occur (e.g. automatically or manually) and also put limits around how many of their resources they want each cartridge to be able to consume.  They might want their Ruby tier to always start with pre-allocated resources (called gears in OpenShift) but still limit the maximum number of resources it could consume.  Using the OpenShift command line tools, that would be as simple as:

rhc scale-cartridge ruby -a myapp --min 5 --max 10

In my application, that would always start the Ruby cartridge with 5 gears and never consume more than 10.  The best part though is that the cartridges themselves can also influence what sort of scaling is possible so that you aren’t blindly adding resources to a cartridge that can’t use them.  The default Ruby cartridge supports scaling but the default MySQL cartridge can only run standalone.  The MySQL cartridge is able to express limitation this by setting the scaling options to a single gear in the manifest:

Scaling:
  Min: 1
  Max: 1

The end result is that when you are creating a scaled application, the Ruby runtimes and MySQL runtimes will get created on separate gears to give the maximum amount of resources to each tier, but the MySQL cartridge and Ruby cartridges will implement their own unique scaling approach.

At the end of the day, this is really about separation of concerns.  Cartridges in OpenShift are used to describe lifecycle characteristics of the technology they represent as well as integration options with other cartridges.  Since the OpenShift cartridge format is completely open, it’s easy for commercial vendors as well as open source users to create cartridges.  For developers, that means they get to access a broad choice of technologies, both commercial and community.  But in addition to choice, the most value comes from allowing developers to spend more time doing the thing they do best – coding.

Fedora 19… on a Macbook Air (2013 Model)!

Update 02-04-2014 – this blog has been updated with Fedora 20.  Fedora 20 works much better so I would highly recommend following the instructions there.

Warning – This information is now out of date and replaced with the blog entry on Fedora 20

 

Update 07-29-2013 - the new kernel supports the touchpad out of the box.  Getting better every day!

This is a slight deviation from my traditional posts but I’m a techie at heart and when a Linux guy gets a new Macbook, he’s gotta try putting on Fedora.  Anderson Silva was my primary inspiration since he got this working on a mid-2012 model Macbook Air (http://anderson.the-silvas.com/?p=605).  However, when deploying on a 2013 model, I hit a couple of bumps in the road.  The good news is that I was able to fix everything but it took me a while to track down all the fixes.  Warning – if you aren’t interested in building some packages, it’s probably just better to wait a couple of months.  However, if you are impatient like myself, read on!

Step 1 – Building RPM’s

You are going to need to build some RPM’s here so you’ll need some development tools installed.

sudo yum install @development-tools
rpmdev-setuptree

Step 2 – Wireless

The new Macbooks ship a BCM4360 wireless chipset which isn’t supported today in Fedora or available via RPMFusion.  However, the RPMFusion guys are working on it and you can build your own RPM with the latest driver to get this working.  You can track the progress at https://bugzilla.rpmfusion.org/show_bug.cgi?id=2721.

# Download and build the source RPM's
cd ~/rpmbuild/SRPMS
wget http://dl.dropboxusercontent.com/u/25699833/rpmfusion/bug2721/broadcom-wl-6xx-6.30.223.30-1.fc20.src.rpm
wget http://dl.dropboxusercontent.com/u/25699833/rpmfusion/bug2721/wl-6xx-kmod-6.30.223.30-1.fc20.src.rpm
rpm -Uvh *.src.rpm
cd ~/rpmbuild/SPECS
rpmbuild -ba wl-6xx-kmod.spec
rpmbuild -ba broadcom-wl-6xx.spec

# Install those RPM's
cd ~/rpmbuild/RPMS
sudo yum install RPMS/`uname -i`/akmod-wl-6xx* RPMS/`uname -i`/kmod-wl-6xx* RPMS/noarch/broadcom-wl-6xx*

Step 3 – Touchpad support (e.g. two finger scroll, two finger click)

Update: You used to have to build a custom kernel but now that 3.10 is out, this works out of the box!

Issues

1. Light sensor / backlight – after a reboot, I can adjust screen brightness with the correct steps / increments using the hot keys. However, after suspend / resume, I can still use the hot keys but it’s either max / min brightness. Not the end of the world, but a bit of a pain.  I’ve opened the following bug to track – https://bugzilla.redhat.com/show_bug.cgi?id=989555

2. Internal speakers.  I can’t seem to get the internal speakers to work.  Headphones work fine but I went ahead and opened a bug to track – https://bugzilla.redhat.com/show_bug.cgi?id=989582

3. 15-30 second hangs.  This seems to be somewhat CPU / IO related but every once in a while, my machine will hang for 15 or 30 seconds.  Nothing more than an annoyance but I’m going to try adding libata.force=1:noncq to my kernel boot parameters and see if that helps based on this article (https://bbs.archlinux.org/viewtopic.php?pid=1295212#p1295212).

# Edit the default grub file
sudo vim /etc/default/grub

# Add 'libata.force=1:noncg' to the end of the GRUB_CMDLINE_LINUX parameter

# Regenerate the grub configurations
sudo grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cf

Please comment on the bugs if you are experiencing the same issues or if you have fixes!

Developing in the Clouds

I’ve seen a lot of interesting evolutionary changes in our development practices over the last 10 years or so and I actually don’t think there have been many revolutionary changes.  Until now, that is.  The power of cloud technologies has introduced a new twist in what development teams can utilize – infinite resources.  Yeah, yeah, I know there really is a capacity limit and I know someone still pays the bill at the end of the day but it’s still fundamentally different than what we are used to.  Without even realizing it, we have built development processes around resource constraints – everything from how developers code, to our QE, to our release processes.  But that doesn’t have to be the case anymore and it doesn’t have to break the bank either.  On OpenShift, we decided early on to build our development process entirely around the concept of using as many volatile resources as we needed to see how productive we could be.  I’ll let you judge for yourself, but to me, the results have been astounding.  Not only is our team more productive than any development team I’ve worked with before, but we are shockingly more cost effective as well.

Let’s take a trip down memory lane first to give you some context to my past experience.  If you roll back the clock 5 years or so, scaling development was painful.  Development essentially ran off desktops and the operations controlled environments were rigid and static.  On the development side, I was constantly struggling to get powerful enough desktops and enough of them to keep the development team productive.  Virtualization wasn’t that prominent yet, so often the developers needed two or three desktops to emulate multi-tier systems.  I spent as much time in purchasing and unpacking boxes as I did coding (and on the warranty calls when the things broke down).  We would constantly have power issues and stability issues as developers would inevitably start hosting shared services on their desktops like our test or continuous integration servers.  Power outages every few days would destabilize services and every once in a while kill a hard drive that wasn’t backed up.  On the other hand, our operations controlled environments that had stable power and redundant storage were ridiculously expensive and effectively static.  Those environments were essentially mirrors of production and expected to be as stable as production.  Developers needed agility so they stuck to their desktops.  It’s the classic development and operations divide and I’ve seen this same scenario play out time and time again.

When we started OpenShift, we wanted to approach it differently.  Sure, everyone still gets a laptop (or in some cases a desktop) for a personalized development environment but that is where physical resources stop.  Developers have the ability to spin up as many mini-environments and sync their local code to those environments.  They can use those mini-environments to kick off various suites of tests as well as do ad-hoc testing of their own.  They might only need a single environment if they are working on a single feature or they might need a dozen.  The focus for us was on ease of consumption – a single command and a 30 second wait is all they need to spin up a new environment of the latest stable build.  Another command synchronizes their local changes to that environment.  The most important thing is that there are no limits to the number of environments they can wield – whatever makes them productive.

But let’s talk cost effectiveness.  How can we provide something like this and not completely break the bank?  Well, this is where IaaS pricing can start benefiting the consumer.  Before you get there however, you have some challenges to solve.  The first challenge is the developer habit of keeping long running machines around.  Any time a developer wanted to test something, we wanted him to be able to spin up a new machine with his changes.  You have to make it easier to start with a new machine instead of keeping an old one around.  Our goal was to keep that entire operation to under a minute, providing easy access to various levels of the codebase and that did the trick for us.  Once you’ve broken the requirement of long running machines, you now start to take advantage of hourly pricing with most IaaS vendors.  If a developer can spin up a machine, run their tests and finish in an hour, you probably paid about $0.30 for that operation.  If they need 6 hours, you are paying less then $2.  To help reinforce this model, any machine that hasn’t been logged into in 6 hours in our environment automatically gets stopped.  The reality is that developers aren’t great at cleaning up, but once you get the model right, they don’t need resources for a long time.  If you get the habit formed around starting each time with a new VM, everything else starts to fall in place.

And yes, being Red Hat, we’ve also open sourced this work (https://github.com/openshift/origin-dev-tools) too.  While these tools are fairly specialized for OpenShift development, hopefully you might find a nugget or two in them that will help in your own process.  And we’re always up for suggestions so if you see a better way of doing something, please send us a pull request!

Next up, I’ll discuss how we expanded upon this to improve our code submission and review process.  As many readers will know, cutting and testing code is only one part of developer effectiveness.  We’ve been able to use these same techniques to fundamentally change how we look at code.  Ever wonder what that OpenShift GitHub Bot is all about commenting on pull requests (e.g. https://github.com/openshift/origin-server/pull/1238)?  If so then stay tuned!

The New Cloud Business Model – Fake Support

I’ve noticed a growing tend over the last year with companies that are providing exciting new enterprise software, the promise of support and no chance of being able to deliver on it.  And unfortunately, for consumers trying to sort through all the new offerings out there, it can sometimes be difficult to separate all the marketing glitz and glamour from the reality.  With OpenShift, Red Hat is able to stand behind the software that it distributes – they have deep expertise in every layer of the stack.  Given that, it frustrates me when I see others claim the same model without the expertise – that approach is just taking advantage of customers who don’t do their homework before buying.

Let’s think about what would happen if more industries took this same approach – the medical profession for example.  Imagine what the conversation might be after your yearly check-up.

Doctor: Well, I’ve got some good news and some bad news.  The good news is that you still look okay.  The bad news is that the is something going on under the surface that you are going to want to figure out.

You: Okay… what exactly do you mean by ‘under the surface’?  Also, when you say that ‘I’ will need to figure this out, what do you mean?

Doctor: I mean something is going on underneath your skin.  What happens under there is basically a mystery to us – it’s not something we support.  That said, whatever is going on probably needs to be fixed so you’ll want to find someone that can do that.  We could try but we really don’t have any better odds than you in fixing the problem…

If a conversation like this is so unacceptable in other disciplines, why do we so readily accept it in software?  Let’s take Platform as a Service (PaaS) for example.  PaaS is platform positioned to be the core application foundation in your company.  It is tightly integrated with both the operating system (OS) and your application platforms.  Those that say otherwise are either dreaming or trying to deceive you.  That tight integration is what lets the PaaS platform do things so that you don’t have to.  But many of the PaaS vendors in the market have limited experience across the OS and the application stacks.  In almost all cases, the PaaS providers are going to have to rely on a separate company for the operating system distribution.  In many cases, they are going to have to do the same for the application stacks.

What are these companies going to do when their customers hit issues in area outside of the core PaaS software?  Most of these guys aren’t active in the open source versions of the software so I doubt they are going to do the fixes themselves.  Don’t let them give you the ‘power of open source software’ unless they are involved enough to influence those changes.  Maybe they will proceed with the same awkward conversation as the above example…

Now, maybe these providers have the ability to support all the things they promise.  Maybe they have all the connections in the open source projects to maintain stable distributions themselves.  This is what Red Hat does but I don’t see too many others doing the same.  At a minimum, you should check because you might end up buying a product from a company whose business models is based on you not making that call for help…

Building an Open Source PaaS Deployment Model

To some, cloud is an excuse to introduce “black box” processes that lock users into their services.  But they can’t really come right out and say that.  Instead they distract from their approach with fanciful names and tell us that the cloud is full of magic and wonder that we don’t need to understand.  This type of innovation is exciting to some, but to me, combining innovation with a lock-in approach is depressing.  In the past, we’ve seen it at the operating system level and the hypervisor level.  We’ve also seen open source disrupt lock-in at both levels and we are going to see the same thing happen in the cloud.

When we started designing and building OpenShift, we wanted to provide more than just a good experience to end users that, in turn, locked them in to our service.  One of the early design decisions we made on OpenShift was to utilize standards as much as we could and to make interactions transparent at all levels.  We did want the user experience to be magical but also completely accessible to those wanted to dig in.  To demonstrate this, let’s walk through the deployment process in OpenShift - arguably the most magical part of the entire offering…

As we were designing a PaaS service, focused on developers, our first goal was to make the deployment process as natural as possible for developers.  For most developers, their day to day process goes something like code, code, code, commit.  For those questioning this process already let me speak on behalf of the developer in question by saying

Tests?! Of course I’ve already written the tests!  They were in the third ‘code’!

Anyway, we wanted to plug into that process and to do that we chose git.  The reason for selecting git over more centralized source code management tools like subversion was that the distributed nature of git allowed the user to have full control over their data.  The user always had access to their entire historical repository and as developers, we thought that was a critical requirement.  Given that, we standardized on git as the main link between our users’ code and OpenShift.

Now let’s look at what that development process might look like in practice.  First, you start off with the code, code, commit part:

vi <file of your choice>
# make earth shattering changes
git commit -a -m "My earth shattering comment"

The next part of the process for those familiar with git is the publish process.  You run a ‘push’ command to move your code from your local repository to your distributed clones.  So when you run:

git push

Your code is transferred to OpenShift and automatically deployed to your environment.  Regardless of whether code needs to be compiled, tests need to be run, dependencies need to be downloaded, a specific packaging spec needs to be built – it all happens on the server side with this one command.  To do this we utilize a git hook to kick off the deployment process.  Wait – I know what you are thinking…

What?!  Just a git hook?!  This is the cloud baby!  Shouldn’t this be custom compiling my code into a Zeus Hammer to perform a magical Cloud Nuclear transfer?!!

If you ask us, a git hook works just fine because it’s what you would probably do yourself.  We simply map the post-receive git hook to a post_receive_app.sh script.  That script invokes a series of scripts (called hooks) representing various steps in the deployment process.  Some of the hooks are provided by the cartridge that your application is using and some of the scripts are provided by the application itself.  This approach let’s the cartridge provide base functionality that can be further customized by the application.

First let’s talk about the cartridge hooks.  Having cartridge specific hooks is important because each cartridge needs to do different things in their deployment process.  For example, when a Java cartridge detects a deployment, we want to do a Maven build, but when a Ruby cartridge detects a deployment, it should execute Bundler.  The cool part is that each individual cartridge can override anything it needs to in the default process.

Let’s look at how the Ruby cartridge implements this.  We can look at the ruby-1.9 cartridge’s overridden build.sh script to see how it calls bundler.  When you use the Java cartridge, it leverages Maven in the build process using the same technique.  You can implement the pieces that are right for your cartridge where it makes sense and still utilize the generic process everywhere else.  In isolation, each individual script is really quite simple.  In aggregate though, all those extensions can become extremely powerful and do much of the heavy lifting on behalf of the users.

But, what if you want to change the default behavior for a specific application?  No problem!  You have a collection of action hooks that are provided with each application instance in their repository.  You could put your own code in pre_build, build, deploy, post_deploy or wherever else it makes sense.These are found in your application in ~/.openshift/action_hooks.  They are invoked just like the cartridge hooks as part of the deployment process.  For example, you can see how the pre_build.sh script is called before we run the build.  What you choose to do with these hooks is your decision.  Put some code in them and they will get called at each step in the deployment process.  This let’s you not only leverage the power of a customized cartridge, but also let’s you tweak and tune so things are just right for your application.

At the end of the day, harnessing the power of the cloud doesn’t need to lock you into a vendor.  At OpenShift, we believe that transparency, standards and extensibility will make a process that lasts the test of time.  I hope this has provided some visibility to how the OpenShift deployment model works and also has given you some insight into navigating the codebase.  And if this has peaked your interested and you find yourself digging through more and more code, please reach out and get involved.