Adds support for creating GCE persistent disks from snapshots

This commit is contained in:
Chris Conway 2014-04-11 15:45:56 -07:00
parent 0b45b1256d
commit d227330a55
6 changed files with 183 additions and 7 deletions

View file

@ -39,6 +39,9 @@ cloud_cleanup: amazon_cleanup rackspace_cleanup
amazon_cleanup:
python cleanup_ec2.py -y --match="^$(CLOUD_RESOURCE_PREFIX)"
gce_setup:
python setup_gce.py "$(CLOUD_RESOURCE_PREFIX)"
gce_cleanup:
python cleanup_gce.py -y --match="^$(CLOUD_RESOURCE_PREFIX)"
@ -57,7 +60,8 @@ amazon: $(CREDENTIALS_FILE)
exit $$RC;
gce: $(CREDENTIALS_FILE)
ansible-playbook gce.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make gce_setup ; \
ansible-playbook gce.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
RC=$$? ; \
CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make gce_cleanup ; \
exit $$RC;

View file

@ -98,6 +98,12 @@ if __name__ == '__main__':
try:
# Delete matching instances
delete_gce_resources(gce.list_nodes, 'name', opts)
# Delete matching snapshots
def get_snapshots():
for volume in gce.list_volumes():
for snapshot in gce.list_volume_snapshots(volume):
yield snapshot
delete_gce_resources(get_snapshots, 'name', opts)
# Delete matching disks
delete_gce_resources(gce.list_volumes, 'name', opts)
except KeyboardInterrupt, e:

View file

@ -0,0 +1,51 @@
import collections
import os
import yaml
try:
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
_ = Provider.GCE
except ImportError:
print("failed=True " + \
"msg='libcloud with GCE support (0.13.3+) required for this module'")
sys.exit(1)
def add_credentials_options(parser):
default_service_account_email=None
default_pem_file=None
default_project_id=None
# Load details from credentials.yml
if os.path.isfile('credentials.yml'):
credentials = yaml.load(open('credentials.yml', 'r'))
default_service_account_email = credentials['gce_service_account_email']
default_pem_file = credentials['gce_pem_file']
default_project_id = credentials['gce_project_id']
parser.add_option("--service_account_email",
action="store", dest="service_account_email",
default=default_service_account_email,
help="GCE service account email. Default is loaded from credentials.yml.")
parser.add_option("--pem_file",
action="store", dest="pem_file",
default=default_pem_file,
help="GCE client key. Default is loaded from credentials.yml.")
parser.add_option("--project_id",
action="store", dest="project_id",
default=default_project_id,
help="Google Cloud project ID. Default is loaded from credentials.yml.")
def check_required(opts, parser):
for required in ['service_account_email', 'pem_file', 'project_id']:
if getattr(opts, required) is None:
parser.error("Missing required parameter: --%s" % required)
def get_gce_driver(opts):
# Connect to GCE
gce_cls = get_driver(Provider.GCE)
return gce_cls(
opts.service_account_email, opts.pem_file, project=opts.project_id)

View file

@ -161,3 +161,60 @@
- 'result.changed'
- 'result.name == "{{ instance_name }}"'
- 'result.state == "absent"'
# ============================================================
- name: test snapshot given (state=present)
gce_pd:
name: "{{ instance_name }}"
snapshot: "{{ instance_name }}-snapshot"
service_account_email: "{{ service_account_email }}"
pem_file: "{{ pem_file }}"
project_id: "{{ project_id }}"
state: present
register: result
- name: assert image given (state=present)
assert:
that:
- 'result.changed'
- 'result.name == "{{ instance_name }}"'
- 'result.snapshot == "{{ instance_name }}-snapshot"'
- 'result.state == "present"'
# ============================================================
- name: test snapshot given (state=absent)
gce_pd:
name: "{{ instance_name }}"
snapshot: "{{ instance_name }}-snapshot"
service_account_email: "{{ service_account_email }}"
pem_file: "{{ pem_file }}"
project_id: "{{ project_id }}"
state: absent
register: result
- name: assert image given (state=absent)
assert:
that:
- 'result.changed'
- 'result.name == "{{ instance_name }}"'
- 'result.state == "absent"'
# ============================================================
- name: test both image and snapshot given
gce_pd:
name: "{{ instance_name }}"
image: "debian-7"
snapshot: "{{ instance_name }}-snapshot"
service_account_email: "{{ service_account_email }}"
pem_file: "{{ pem_file }}"
project_id: "{{ project_id }}"
state: present
register: result
ignore_errors: true
- name: assert image given (state=present)
assert:
that:
- 'result.failed'
- 'result.msg == "Cannot give both image (debian-7) and snapshot ({{ instance_name }}-snapshot)"'

View file

@ -0,0 +1,40 @@
'''
Create GCE resources for use in integration tests.
Takes a prefix as a command-line argument and creates a persistent disk
named ${prefix}-base and a snapshot of it named ${prefix}-snapshot.
prefix will be forced to lowercase, to ensure the names are legal GCE
resource names.
'''
import sys
import optparse
import gce_credentials
def parse_args():
parser = optparse.OptionParser(
usage="%s [options] <prefix>" % (sys.argv[0],), description=__doc__)
gce_credentials.add_credentials_options(parser)
parser.add_option("--prefix",
action="store", dest="prefix",
help="String used to prefix GCE resource names (default: %default)")
(opts, args) = parser.parse_args()
gce_credentials.check_required(opts, parser)
if not args:
parser.error("Missing required argument: name prefix")
return (opts, args)
if __name__ == '__main__':
(opts, args) = parse_args()
gce = gce_credentials.get_gce_driver(opts)
prefix = args[0].lower()
try:
base_volume = gce.create_volume(
size=10, name=prefix+'-base', location='us-central1-a')
gce.create_volume_snapshot(base_volume, name=prefix+'-snapshot')
except KeyboardInterrupt, e:
print "\nExiting on user command."