185 lines
6.5 KiB
Python
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)
|