133 lines
4.1 KiB
Python
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})
|