Byzantine Reality

Searching for Byzantine failures in the world around us

Cleaning Up in Google Compute Engine

Google Compute Engine provides an Infrastructure-as-a-Service offering similar to Amazon Web Services. We support it natively in AppScale, and one of the very nice perks with GCE is that you pay for instances on a per-minute basis (after a minimum of ten minutes), as opposed to AWS, which charges you on a per-hour basis. That means if you use ten minutes of machine time in GCE, you pay for ten minutes, but with AWS, you pay for a full hour.

So we do quite a bit of hacking on both GCE and AWS, which means we create a lot of extra resources that sometimes accidentally get left around. With that, I wrote a quick script to clean some of that stuff up in GCE – let’s take a look!

To run AppScale in GCE, we automatically create a network for you, make a firewall in it, and then run instances in that firewall. That means when we tear down AppScale, we have to:

  1. Terminate any running instances, resembling the gcutil deleteinstance command
  2. Get rid of the firewall we create, resembling gcutil deletefirewall
  3. Get rid of the network we create, resembling gcutil deletenetwork

We already do that for you automatically. However, when I develop AppScale on GCE, I sometimes mess things up (who knew?) and I leave networks, firewalls, and instances around. So here’s a quick script to clean all that crap up that you may find handy for your own GCE purposes. It requires gcutil to be installed and in your $PATH, and since I cache my project ID, you should either (1) run --cache_flag_values on a gcutil command to do the same, or add in --project=<project-id> to each gcutil command. Without further adieu, here it is!

cleanup_gce.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# First, blow away any running instances.
instance_info = `gcutil listinstances | grep RUNNING`
instances = []
instance_info.split("\n").each { |line|
  split_line = line.split("|")
  instances << split_line[1].strip
}

if instances.empty?
  Kernel.puts "No instances to delete."
else
  Kernel.puts "Deleting instances: #{instances.join(', ')}"
  Kernel.sleep(1)
  Kernel.puts `gcutil deleteinstance #{instances.join(' ')} --force`
end

# Next, blow away any firewalls.
# We grep for appscale here - change it to get rid of other firewalls, but
# be wary of accidentally deleting the default firewall or network.
firewall_info = `gcutil listfirewalls | grep appscale`
firewalls = []
firewall_info.split("\n").each { |line|
  split_line = line.split("|")
  firewalls << split_line[1].strip
}

if firewalls.empty?
  Kernel.puts "No firewalls to delete."
else
  Kernel.puts "Deleting firewalls: #{firewalls.join(', ')}"
  Kernel.sleep(1)
  Kernel.puts `gcutil deletefirewall #{firewalls.join(' ')} --force`
end

# Then, the same for networks.
# Note that AppScale names the network the same as the firewall.
if firewalls.empty?
  Kernel.puts "No networks to delete."
else
  Kernel.puts "Deleting networks: #{firewalls.join(', ')}"
  Kernel.sleep(1)
  Kernel.puts `gcutil deletenetwork #{firewalls.join(' ')} --force`
end

Of course, it’s got a bit more copy-pasta than I would like, but it’s quick and dirty and gets the job done, so what more can you ask of a throwaway script? Hope you find it as handy as I do!