Files
nova/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance
2010-12-30 11:26:21 -06:00

133 lines
4.1 KiB
Python

#!/usr/bin/env python
# Copyright (c) 2010 Citrix Systems, Inc.
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# XenAPI plugin for putting images into glance
#
import base64
import errno
import hmac
import httplib
import os
import os.path
import pickle
import sha
import subprocess
import time
import urlparse
import XenAPIPlugin
#FIXME(sirp): should this use pluginlib from 5.6?
from pluginlib_nova import *
configure_logging('glance')
CHUNK_SIZE = 8192
FILE_SR_PATH = '/var/run/sr-mount'
def put_vdis(session, args):
params = pickle.loads(exists(args, 'params'))
vdi_uuids = params["vdi_uuids"]
image_name = params["image_name"]
glance_host = params["glance_host"]
glance_port = params["glance_port"]
sr_path = get_sr_path(session)
#FIXME(sirp): writing to a temp file until Glance supports chunked-PUTs
tmp_file = "%s.tar.gz" % os.path.join('/tmp', image_name)
tar_cmd = ['tar', '-zcf', tmp_file, '--directory=%s' % sr_path]
paths = [ "%s.vhd" % vdi_uuid for vdi_uuid in vdi_uuids ]
tar_cmd.extend(paths)
logging.debug("Bundling image with cmd: %s", tar_cmd)
subprocess.call(tar_cmd)
logging.debug("Writing to test file %s", tmp_file)
put_bundle_in_glance(tmp_file, image_name, glance_host, glance_port)
return "" # FIXME(sirp): return anything useful here?
def put_bundle_in_glance(tmp_file, image_name, glance_host, glance_port):
size = os.path.getsize(tmp_file)
basename = os.path.basename(tmp_file)
bundle = open(tmp_file, 'r')
try:
headers = {
'x-image-meta-store': 'file',
'x-image-meta-is_public': 'True',
'x-image-meta-type': 'raw',
'x-image-meta-name': image_name,
'x-image-meta-size': size,
'content-length': size,
'content-type': 'application/octet-stream',
}
conn = httplib.HTTPConnection(glance_host, glance_port)
#NOTE(sirp): httplib under python2.4 won't accept a file-like object
# to request
conn.putrequest('POST', '/images')
for header, value in headers.iteritems():
conn.putheader(header, value)
conn.endheaders()
chunk = bundle.read(CHUNK_SIZE)
while chunk:
conn.send(chunk)
chunk = bundle.read(CHUNK_SIZE)
res = conn.getresponse()
#FIXME(sirp): should this be 201 Created?
if res.status != httplib.OK:
raise Exception("Unexpected response from Glance %i" % res.status)
finally:
bundle.close()
def get_sr_path(session):
sr_ref = find_sr(session)
if sr_ref is None:
raise Exception('Cannot find SR to read VDI from')
sr_rec = session.xenapi.SR.get_record(sr_ref)
sr_uuid = sr_rec["uuid"]
sr_path = os.path.join(FILE_SR_PATH, sr_uuid)
return sr_path
#TODO(sirp): both objectstore and glance need this, should this be refactored
#into common lib
def find_sr(session):
host = get_this_host(session)
srs = session.xenapi.SR.get_all()
for sr in srs:
sr_rec = session.xenapi.SR.get_record(sr)
if not ('i18n-key' in sr_rec['other_config'] and
sr_rec['other_config']['i18n-key'] == 'local-storage'):
continue
for pbd in sr_rec['PBDs']:
pbd_rec = session.xenapi.PBD.get_record(pbd)
if pbd_rec['host'] == host:
return sr
return None
if __name__ == '__main__':
XenAPIPlugin.dispatch({'put_vdis': put_vdis})