135 lines
5.2 KiB
Python
135 lines
5.2 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright (c) 2010 Citrix Systems, Inc.
|
|
#
|
|
# 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.
|
|
|
|
"""
|
|
Management class for VM-related functions (spawn, reboot, etc).
|
|
"""
|
|
|
|
import logging
|
|
|
|
from twisted.internet import defer
|
|
|
|
from nova import db
|
|
from nova import context
|
|
from nova.auth.manager import AuthManager
|
|
from nova.virt.xenapi.network_utils import NetworkHelper
|
|
from nova.virt.xenapi.vm_utils import VMHelper
|
|
|
|
XenAPI = None
|
|
|
|
|
|
class VMOps(object):
|
|
"""
|
|
Management class for VM-related tasks
|
|
"""
|
|
def __init__(self, session):
|
|
global XenAPI
|
|
if XenAPI is None:
|
|
XenAPI = __import__('XenAPI')
|
|
self._session = session
|
|
|
|
def list_instances(self):
|
|
""" List VM instances """
|
|
return [self._session.get_xenapi().VM.get_name_label(vm) \
|
|
for vm in self._session.get_xenapi().VM.get_all()]
|
|
|
|
@defer.inlineCallbacks
|
|
def spawn(self, instance):
|
|
""" Create VM instance """
|
|
vm = yield VMHelper.lookup(self._session, instance.name)
|
|
if vm is not None:
|
|
raise Exception('Attempted to create non-unique name %s' %
|
|
instance.name)
|
|
|
|
bridge = db.project_get_network(context.get_admin_context(),
|
|
instance.project_id).bridge
|
|
network_ref = \
|
|
yield NetworkHelper.find_network_with_bridge(self._session, bridge)
|
|
|
|
user = AuthManager().get_user(instance.user_id)
|
|
project = AuthManager().get_project(instance.project_id)
|
|
vdi_uuid = yield VMHelper.fetch_image(self._session,
|
|
instance.image_id, user, project, True)
|
|
kernel = yield VMHelper.fetch_image(self._session,
|
|
instance.kernel_id, user, project, False)
|
|
ramdisk = yield VMHelper.fetch_image(self._session,
|
|
instance.ramdisk_id, user, project, False)
|
|
vdi_ref = yield self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
|
|
vm_ref = yield VMHelper.create_vm(self._session,
|
|
instance, kernel, ramdisk)
|
|
yield VMHelper.create_vbd(self._session, vm_ref, vdi_ref, 0, True)
|
|
if network_ref:
|
|
yield VMHelper.create_vif(self._session, vm_ref,
|
|
network_ref, instance.mac_address)
|
|
logging.debug('Starting VM %s...', vm_ref)
|
|
yield self._session.call_xenapi('VM.start', vm_ref, False, False)
|
|
logging.info('Spawning VM %s created %s.', instance.name,
|
|
vm_ref)
|
|
|
|
@defer.inlineCallbacks
|
|
def reboot(self, instance):
|
|
""" Reboot VM instance """
|
|
instance_name = instance.name
|
|
vm = yield VMHelper.lookup(self._session, instance_name)
|
|
if vm is None:
|
|
raise Exception('instance not present %s' % instance_name)
|
|
task = yield self._session.call_xenapi('Async.VM.clean_reboot', vm)
|
|
yield self._session.wait_for_task(task)
|
|
|
|
@defer.inlineCallbacks
|
|
def destroy(self, instance):
|
|
""" Destroy VM instance """
|
|
vm = yield VMHelper.lookup(self._session, instance.name)
|
|
if vm is None:
|
|
# Don't complain, just return. This lets us clean up instances
|
|
# that have already disappeared from the underlying platform.
|
|
defer.returnValue(None)
|
|
# Get the VDIs related to the VM
|
|
vdis = yield VMHelper.lookup_vm_vdis(self._session, vm)
|
|
try:
|
|
task = yield self._session.call_xenapi('Async.VM.hard_shutdown',
|
|
vm)
|
|
yield self._session.wait_for_task(task)
|
|
except XenAPI.Failure, exc:
|
|
logging.warn(exc)
|
|
# Disk clean-up
|
|
if vdis:
|
|
for vdi in vdis:
|
|
try:
|
|
task = yield self._session.call_xenapi('Async.VDI.destroy',
|
|
vdi)
|
|
yield self._session.wait_for_task(task)
|
|
except XenAPI.Failure, exc:
|
|
logging.warn(exc)
|
|
try:
|
|
task = yield self._session.call_xenapi('Async.VM.destroy', vm)
|
|
yield self._session.wait_for_task(task)
|
|
except XenAPI.Failure, exc:
|
|
logging.warn(exc)
|
|
|
|
def get_info(self, instance_id):
|
|
""" Return data about VM instance """
|
|
vm = VMHelper.lookup_blocking(self._session, instance_id)
|
|
if vm is None:
|
|
raise Exception('instance not present %s' % instance_id)
|
|
rec = self._session.get_xenapi().VM.get_record(vm)
|
|
return VMHelper.compile_info(rec)
|
|
|
|
def get_console_output(self, instance):
|
|
""" Return snapshot of console """
|
|
# TODO: implement this to fix pylint!
|
|
return 'FAKE CONSOLE OUTPUT of instance'
|