Blog

One of the courses we teach in school is Administration and IT. This is a Business Studies course that covers many of the regular office (and Office) skills that students might need in the future.

The course doesn't explicitly require that you use Windows Office but in practice it does. The exams are set by people who use Windows and the exams are marked by people who expect to see the output of Microsoft Office....so.

So I had the problem of having to somehow provide a Windows environment to our iOS devices. There's no way I'm buying and maintaining a legacy Windows lab for this course, so what to do?

There's also no way I'm getting into enterprise software land with services like Citrix. It's one of my basic rules that if the price isn't on the website, it's unlikely to be a price I'm happy to pay.

Enter Amazon Workspaces.

Amazon Workspaces is basically a virtualised Windows environment that you can connect to from iOS, Mac, etc. Best of all, you just click a button and you get a service - no salesmen involved.

We also have an Office 365 service set up for pupils taking this class. We don't have a general Microsoft license, so we're paying about £1.15 per pupil per month for this.

One of the things with all of Amazon Web Services is that you need to understand both the technical aspect and the pricing model - and you really, really, have to understand your own usage model.

For us, we use the VMs during class and rarely outside of class. For the Higher class, that's 5 hours per week. For the lower-level classes, it's 2 hours per week. It's quite a minimal amount of usage, so you can understand my reluctance to commit a lot of capital to this.

Workspaces has two pricing models: monthly and hourly. For the basic "Value" bundle, which is all we need, the monthly price is $27/month. The hourly pricing model for WorkSpaces is a basic $8/user/month to have the VM set up and then it's $0.23 per hour that the workspace is active.

So you can see that for us, where our usage is quite sparse across a week, the hourly pricing is a huge win.

WorkSpaces also provides a bundle where you can get Office 2013 built into the bundle and set up. What I didn't understand going into this, though, is that there is additional pricing for having Office installed in the bundle. That extra is $15/bundle/month. Considering we were already paying for Office 365, this was a huge waste of money.

My first deployment model was to put out the pre built Amazon "Value Plus" bundle. That was very easy to do but adding on an additional $15/user/month was too expensive. I didn't realise this until the first bill came in but once I did, it was time to make a change!

As part of the rebuild, I decided to create a custom image to create the student images from. I simply followed the tutorial steps and built a bundle that included the Google Drive sync app, Google Chrome, Office 2016 and Acrobat DC. I had previously led pupils through building their own setups but, as the number of pupils has increased, this is increasingly impractical.

Once I created these images for each student, all the student had to do was sign into Google Drive and sign into their Office 365 account.

Additionally, I tagged each instance with a tag named "class", so that I could identify the images associated with each class group. Essentially, the script enumerates all the workspaces with a specific tag and then sends them a start or stop command, depending on the parameters sent to the script.

Imaging

None of the pre-built Amazon images are ideal for what we want. In particular, we wanted to have Google Drive, Chrome, Acrobat Reader and the latest version of Office installed.

So I followed a fairly simple tutorial to create a custom bundle for our students that included those packages. All the student had to do to make a bundle work for them was to sign into Google Drive and Office and they're ready to go.

This custom image should also make it easier to delete and recreate the workspaces. To save money, I will endeavor to find some months in the school year where we don't need to have those Workspaces in operation and delete and recreate them. I haven't done that yet, but it's more of an option now that setup is much faster.

Scheduling

This is where things start to get fun. When a user tries to connect to a stopped instance, the instance will automatically start but this can take up to 5 minutes. This ain't exactly what you want when trying to get a class started, so I decided to try and figure out a different way to do it.

First, I wrote a python script that would start or stop each class group of workspaces on demand. This script lived on a unix machine we have in school. That was helpful - as long as I remembered to run it before class.

Of course I rarely remembered to run it before class. Remembering to do things is a computer's job, so let's get the computer to do it.

AWS provides a service called Lambda. Lambda allows you to run a Python script in the cloud without having to worry about anything to do with the server or the underlying operating system. It's basically "scripts in the cloud" and very helpful for small self-contained scripts like this script that starts and stops groups of Workspaces.

So I wrote this script and set it up as an AWS Lambda script. The question then was how to schedule it to run. Turns out, AWS has another tool for that: CloudWatch.

Cloudwatch is the monitoring and logging component of AWS. In general, the primary use case for CloudWatch is to monitor your AWS workloads and take action. For example, if your response times are getting long, CloudWatch would notice and run a Lambda script to spin up more servers.

CloudWatch also contains an option to execute Lambda functions on a schedule. There are options for running them on set frequencies (once every X minutes) or on a Cron schedule. This latter option is perfect for my application.

I didn't want to write different scripts for each class group or for starting and stopping workspaces. Instead, these needed to be arguments passed to the script. CloudWatch scheduled rules allow you to send parameters to a Lambda function in the form of a JSON dictionary.

So I set up each rule to spin up the Workspaces 20 minutes before the class starts and stop them 10 minutes after it ends. This was a bit of a hassle, as it requires two rules to be scheduled for each period - one to start the servers and another to stop. Still, at least it was only a matter of changing the Cron expression and the parameters sent to the Lambda function.

The only major wrinkle here was that CloudWatch scheduled rules always run on UTC and there's no way to express a local time zone. This is a pain as I now have to both adjust all of my CloudWatch triggers when the UK reverts from BST to GMT and, worse, remember to do it.

So, in summary, the chain of events goes like this: CloudWatch executes on a Cron schedule to run a Lambda function which causes AWS Workspaces to start or stop.