2013-05-03 14:00:57 +02:00

185 lines
6.5 KiB
Python

# coding=utf-8
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2012, Intel Performance Learning Solutions Ltd.
#
# 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.
"""
The compute resource backend for OpenStack.
"""
#pylint: disable=W0232,R0201
import logging
from occi_os_api.extensions import os_mixins
from occi_os_api.extensions import os_addon
from occi_os_api.nova_glue import vm
from occi_os_api.nova_glue import storage
from occi.backend import KindBackend, ActionBackend
from occi.extensions import infrastructure
LOG = logging.getLogger(__name__)
class ComputeBackend(KindBackend, ActionBackend):
"""
The compute backend.
"""
def create(self, entity, extras):
"""
Create a VM.
"""
LOG.debug('Creating an Virtual machine')
# ignore some attributes - done via templating
if 'occi.compute.cores' in entity.attributes or \
'occi.compute.speed' in entity.attributes or \
'occi.compute.memory' in entity.attributes or \
'occi.compute.architecture' in entity.attributes:
raise AttributeError('There are unsupported attributes in the '
'request.')
# create the VM
context = extras['nova_ctx']
instance = vm.create_vm(entity, context)
uid = instance['uuid']
entity.identifier = '/compute/' + uid
# set some attributes
entity.attributes['occi.compute.hostname'] = instance['hostname']
entity.attributes['occi.compute.architecture'] = \
storage.get_image_architecture(uid, extras['nova_ctx'])
entity.attributes['occi.compute.cores'] = str(instance['vcpus'])
entity.attributes['occi.compute.speed'] = str(0.0) # N/A in instance
value = str(float(instance['memory_mb']) / 1024)
entity.attributes['occi.compute.memory'] = value
entity.attributes['occi.compute.state'] = 'inactive'
# set valid actions
entity.actions = [infrastructure.STOP,
infrastructure.SUSPEND,
infrastructure.RESTART]
# Tell the world that is is an VM in OpenStack...
entity.mixins.append(os_addon.OS_VM)
def retrieve(self, entity, extras):
"""
Retrieve a VM.
"""
uid = entity.attributes['occi.core.id']
context = extras['nova_ctx']
instance = vm.get_vm(uid, context)
LOG.debug('Retrieving an Virtual machine: ' + repr(uid))
# set state and applicable actions!
state, actions = vm.get_occi_state(uid, context)
entity.attributes['occi.compute.state'] = state
entity.actions = actions
# set up to date attributes
entity.attributes['occi.compute.hostname'] = instance['hostname']
entity.attributes['occi.compute.architecture'] =\
storage.get_image_architecture(uid, extras['nova_ctx'])
entity.attributes['occi.compute.cores'] = str(instance['vcpus'])
entity.attributes['occi.compute.speed'] = str(0.0) # N/A in instance
value = str(float(instance['memory_mb']) / 1024)
entity.attributes['occi.compute.memory'] = value
def update(self, old, new, extras):
"""
Update an VM.
"""
context = extras['nova_ctx']
uid = old.attributes['occi.core.id']
LOG.debug('Updating an Virtual machine: ' + repr(uid))
# for now we will only handle one mixin change per request
if len(new.mixins) != 1:
raise AttributeError('Only updates with one mixin in request are'
' currently supported')
mixin = new.mixins[0]
if isinstance(mixin, os_mixins.ResourceTemplate):
flavor_id = mixin.res_id
vm.resize_vm(uid, flavor_id, context)
old.attributes['occi.compute.state'] = 'inactive'
# now update the mixin info
old.mixins.append(mixin)
elif isinstance(mixin, os_mixins.OsTemplate):
image_href = mixin.os_id
vm.rebuild_vm(uid, image_href, context)
old.attributes['occi.compute.state'] = 'inactive'
# now update the mixin info
old.mixins.append(mixin)
else:
msg = 'Unrecognized mixin. %s' % str(mixin)
LOG.error(msg)
raise AttributeError(msg)
def replace(self, old, new, extras):
"""
XXX:not doing anything - full updates are hard :-)
"""
pass
def delete(self, entity, extras):
"""
Remove a VM.
"""
msg = 'Removing representation of virtual machine with id: %s' %\
entity.identifier
LOG.info(msg)
context = extras['nova_ctx']
uid = entity.attributes['occi.core.id']
vm.delete_vm(uid, context)
def action(self, entity, action, attributes, extras):
"""
Perform an action.
"""
# As there is no callback mechanism to update the state
# of computes known by occi, a call to get the latest representation
# must be made.
context = extras['nova_ctx']
uid = entity.attributes['occi.core.id']
# set state and applicable actions - so even if the user hasn't done
# a GET het can still the most applicable action now...
state, actions = vm.get_occi_state(uid, context)
entity.attributes['occi.compute.state'] = state
entity.actions = actions
if action not in entity.actions:
raise AttributeError("This action is currently not applicable.")
elif action == infrastructure.START:
vm.start_vm(uid, context)
elif action == infrastructure.STOP:
vm.stop_vm(uid, context)
elif action == infrastructure.RESTART:
if not 'method' in attributes:
raise AttributeError('Please provide a method!')
method = attributes['method']
vm.restart_vm(uid, method, context)
elif action == infrastructure.SUSPEND:
vm.suspend_vm(uid, context)