Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

297 lines (228 sloc) 9.072 kb
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
# Copyright (c) 2010 Citrix Systems, Inc.
# Copyright (c) 2011 Piston Cloud Computing, Inc
# Copyright (c) 2011 OpenStack LLC
#
# 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.
import os
import random
from nova import exception
from nova import flags
from nova import utils
from nova.virt import images
FLAGS = flags.FLAGS
def execute(*args, **kwargs):
return utils.execute(*args, **kwargs)
def get_iscsi_initiator():
"""Get iscsi initiator name for this machine"""
# NOTE(vish) openiscsi stores initiator name in a file that
# needs root permission to read.
contents = utils.read_file_as_root('/etc/iscsi/initiatorname.iscsi')
for l in contents.split('\n'):
if l.startswith('InitiatorName='):
return l[l.index('=') + 1:].strip()
def create_image(disk_format, path, size):
"""Create a disk image
:param disk_format: Disk image format (as known by qemu-img)
:param path: Desired location of the disk image
:param size: Desired size of disk image. May be given as an int or
a string. If given as an int, it will be interpreted
as bytes. If it's a string, it should consist of a number
with an optional suffix ('K' for Kibibytes,
M for Mebibytes, 'G' for Gibibytes, 'T' for Tebibytes).
If no suffix is given, it will be interpreted as bytes.
"""
execute('qemu-img', 'create', '-f', disk_format, path, size)
def create_cow_image(backing_file, path):
"""Create COW image
Creates a COW image with the given backing file
:param backing_file: Existing image on which to base the COW image
:param path: Desired location of the COW image
"""
execute('qemu-img', 'create', '-f', 'qcow2', '-o',
'backing_file=%s' % backing_file, path)
def get_disk_size(path):
"""Get the (virtual) size of a disk image
:param path: Path to the disk image
:returns: Size (in bytes) of the given disk image as it would be seen
by a virtual machine.
"""
out, err = execute('qemu-img', 'info', path)
size = [i.split('(')[1].split()[0] for i in out.split('\n')
if i.strip().find('virtual size') >= 0]
return int(size[0])
def get_disk_backing_file(path):
"""Get the backing file of a disk image
:param path: Path to the disk image
:returns: a path to the image's backing store
"""
out, err = execute('qemu-img', 'info', path)
backing_file = None
for line in out.split('\n'):
if line.startswith('backing file: '):
if 'actual path: ' in line:
backing_file = line.split('actual path: ')[1][:-1]
else:
backing_file = line.split('backing file: ')[1]
break
if backing_file:
backing_file = os.path.basename(backing_file)
return backing_file
def copy_image(src, dest):
"""Copy a disk image
:param src: Source image
:param dest: Destination path
"""
# We shell out to cp because that will intelligently copy
# sparse files. I.E. holes will not be written to DEST,
# rather recreated efficiently. In addition, since
# coreutils 8.11, holes can be read efficiently too.
execute('cp', src, dest)
def mkfs(fs, path, label=None):
"""Format a file or block device
:param fs: Filesystem type (examples include 'swap', 'ext3', 'ext4'
'btrfs', etc.)
:param path: Path to file or block device to format
:param label: Volume label to use
"""
if fs == 'swap':
execute('mkswap', path)
else:
args = ['mkfs', '-t', fs]
if label:
args.extend(['-n', label])
args.append(path)
execute(*args)
def ensure_tree(path):
"""Create a directory (and any ancestor directories required)
:param path: Directory to create
"""
execute('mkdir', '-p', path)
def write_to_file(path, contents, umask=None):
"""Write the given contents to a file
:param path: Destination file
:param contents: Desired contents of the file
:param umask: Umask to set when creating this file (will be reset)
"""
if umask:
saved_umask = os.umask(umask)
try:
with open(path, 'w') as f:
f.write(contents)
finally:
if umask:
os.umask(saved_umask)
def chown(path, owner):
"""Change ownership of file or directory
:param path: File or directory whose ownership to change
:param owner: Desired new owner (given as uid or username)
"""
execute('chown', owner, path, run_as_root=True)
def create_snapshot(disk_path, snapshot_name):
"""Create a snapshot in a disk image
:param disk_path: Path to disk image
:param snapshot_name: Name of snapshot in disk image
"""
qemu_img_cmd = ('qemu-img',
'snapshot',
'-c',
snapshot_name,
disk_path)
# NOTE(vish): libvirt changes ownership of images
execute(*qemu_img_cmd, run_as_root=True)
def delete_snapshot(disk_path, snapshot_name):
"""Create a snapshot in a disk image
:param disk_path: Path to disk image
:param snapshot_name: Name of snapshot in disk image
"""
qemu_img_cmd = ('qemu-img',
'snapshot',
'-d',
snapshot_name,
disk_path)
# NOTE(vish): libvirt changes ownership of images
execute(*qemu_img_cmd, run_as_root=True)
def extract_snapshot(disk_path, source_fmt, snapshot_name, out_path, dest_fmt):
"""Extract a named snapshot from a disk image
:param disk_path: Path to disk image
:param snapshot_name: Name of snapshot in disk image
:param out_path: Desired path of extracted snapshot
"""
qemu_img_cmd = ('qemu-img',
'convert',
'-f',
source_fmt,
'-O',
dest_fmt,
'-s',
snapshot_name,
disk_path,
out_path)
execute(*qemu_img_cmd)
def load_file(path):
"""Read contents of file
:param path: File to read
"""
with open(path, 'r+') as fp:
return fp.read()
def file_open(*args, **kwargs):
"""Open file
see built-in file() documentation for more details
Note: The reason this is kept in a separate module is to easily
be able to provide a stub module that doesn't alter system
state at all (for unit tests)
"""
return file(*args, **kwargs)
def file_delete(path):
"""Delete (unlink) file
Note: The reason this is kept in a separate module is to easily
be able to provide a stub module that doesn't alter system
state at all (for unit tests)
"""
return os.unlink(path)
def get_open_port(start_port, end_port):
"""Find an available port
:param start_port: Start of acceptable port range
:param end_port: End of acceptable port range
"""
for i in xrange(0, 100): # don't loop forever
port = random.randint(start_port, end_port)
# netcat will exit with 0 only if the port is in use,
# so a nonzero return value implies it is unused
cmd = 'netcat', '0.0.0.0', port, '-w', '1'
try:
stdout, stderr = execute(*cmd, process_input='')
except exception.ProcessExecutionError:
return port
raise Exception(_('Unable to find an open port'))
def get_fs_info(path):
"""Get free/used/total space info for a filesystem
:param path: Any dirent on the filesystem
:returns: A dict containing:
:free: How much space is free (in bytes)
:used: How much space is used (in bytes)
:total: How big the filesystem is (in bytes)
"""
hddinfo = os.statvfs(path)
total = hddinfo.f_frsize * hddinfo.f_blocks
free = hddinfo.f_frsize * hddinfo.f_bavail
used = hddinfo.f_frsize * (hddinfo.f_blocks - hddinfo.f_bfree)
return {'total': total,
'free': free,
'used': used}
def fetch_image(context, target, image_id, user_id, project_id):
"""Grab image"""
images.fetch_to_raw(context, image_id, target, user_id, project_id)
Jump to Line
Something went wrong with that request. Please try again.