Commit 33de0d60 authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Sanitize compute.py

parent c9ff8e9b
# Copyright (C) 2012-2013 GRNET S.A.
# Copyright (C) 2012-2016 GRNET S.A.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -15,23 +15,20 @@
from snfOCCI.config import SERVER_CONFIG
from snfOCCI.extensions import snf_addons
from kamaki.clients import ClientError
from occi.backend import ActionBackend, KindBackend, MixinBackend
from occi.core_model import Mixin
from occi.extensions import infrastructure
from occi.exceptions import HTTPError
from base64 import b64encode, b64decode
import json, yaml
import yaml
# Compute Backend for snf-occi-server
class MyBackend(KindBackend, ActionBackend):
# Updating and Replacing compute instances not supported by Cyclades
"""Update and Replace compute instances not supported by Cyclades"""
def update(self, old, new, extras):
raise HTTPError(501, "Update is currently no applicable")
......@@ -46,12 +43,10 @@ class SNFBackend(MixinBackend, ActionBackend):
class ComputeBackend(MyBackend):
'''
Backend for Cyclades/Openstack compute instances
'''
"""Backend for Cyclades/Openstack compute instances"""
def create(self, entity, extras):
# Creating new compute instance
"""Create new compute instance"""
try:
snf_network = extras['snf_network']
......@@ -66,212 +61,147 @@ class ComputeBackend(MyBackend):
flavor = mixin
flavor_id = mixin.attributes['occi.core.id']
kwargs = dict(
project_id=extras.get('snf_project', None),
personality=[])
vm_name = entity.attributes['occi.core.title']
user_data = None
user_pub_key = None
meta_json = None
personality = []
if entity.attributes.has_key('org.openstack.compute.user_data'):
user_data = b64decode(entity.attributes['org.openstack.compute.user_data'])
# user_data = entity.attributes['org.openstack.compute.user_data']
if entity.attributes.has_key('org.openstack.credentials.publickey.data'):
user_pub_key = entity.attributes['org.openstack.credentials.publickey.data']
# Implementation for the meta.json file to use the respective NoCloud cloudinit driver
# if user_data and user_pub_key:
# meta_json = json.dumps({'dsmode':'net','public-keys':user_pub_key,'user-data': user_data}, sort_keys=True,indent=4, separators=(',', ': ') )
# elif user_data:
# meta_json = json.dumps({'dsmode':'net','user-data': user_data}, sort_keys=True,indent=4, separators=(',', ': ') )
# elif user_pub_key:
# meta_json = json.dumps({'dsmode':'net','public-keys':user_pub_key}, sort_keys=True,indent=4, separators=(',', ': ') )
# if meta_json:
# print "!!!!!!!!!!!!!!!!!!!!!!!!!!!! CONTEXTUALIZATION!!!!!!!!!!!!!!!!!!!!!!"
# personality.append({'contents':b64encode(meta_json),
# 'path':' /var/lib/cloud/seed/config_drive/meta.js'})
# info = snf.create_server(vm_name, flavor_id, image_id,personality=personality)
# else:
# info = snf.create_server(vm_name, flavor_id, image_id)
key = 'org.openstack.compute.user_data'
cont = key in entity.attributes
user_data = b64decode(entity.attributes[key]) if cont else None
if user_data:
#userDataDict = dict([('user-data', user_data)])
#userData = yaml.dump(userDataDict)
userData = user_data
print "Prepare to inject user data to VM"
kwargs['personality'].append({
'contents': b64encode(user_data),
'path': '/var/lib/cloud/seed/nocloud-net/user-data'})
key = 'org.openstack.credentials.publickey.data'
cont = key in entity.attributes
user_pub_key = entity.attributes[key] if cont else None
if user_pub_key:
pub_keyDict = dict([('public-keys',user_pub_key)])
pub_key = yaml.dump(pub_keyDict)
# kwargs = dict(project_id='6d9ec935-fcd4-4ae1-a3a0-10e612c4f867')
kwargs = dict(project_id=extras.get('snf_project', None))
if user_data and user_pub_key:
print "!!!!!!!!!!!!!!!!!!!!!!!!!!!! CONTEXTUALIZATION - USER DATA & PUBLIC KEY!!!!!!!!!!!!!!!!!!!!!!"
personality.append({'contents':b64encode(userData),
'path':'/var/lib/cloud/seed/nocloud-net/user-data'})
personality.append({'contents':b64encode(pub_key),
'path':'/var/lib/cloud/seed/nocloud-net/meta-data'})
info = snf.create_server(vm_name, flavor_id, image_id,personality=personality, **kwargs)
elif user_data:
print "!!!!!!!!!!!!!!!!!!!!!!!!!!!! CONTEXTUALIZATION - USER DATA!!!!!!!!!!!!!!!!!!!!!!"
personality.append({'contents':b64encode(userData),
'path':'/var/lib/cloud/seed/nocloud-net/user-data'})
info = snf.create_server(vm_name, flavor_id, image_id,personality=personality, **kwargs)
elif user_pub_key:
print "!!!!!!!!!!!!!!!!!!!!!!!!!!!! CONTEXTUALIZATION - PUBLIC KEY!!!!!!!!!!!!!!!!!!!!!!"
personality.append({'contents':b64encode(pub_key),
'path':'/var/lib/cloud/seed/nocloud-net/meta-data'})
for retries in range(2):
try:
info = snf.create_server(vm_name, flavor_id, image_id,personality=personality, **kwargs)
except ClientError as ce:
if ce.status in (409, ):
print 'ce, create an IP and retry'.format(ce=ce)
snf_network.create_floatingip(**kwargs)
else:
raise ce
else:
print 'Create a server with some attributes...'
for retries in range(2):
try:
info = snf.create_server(vm_name, flavor_id, image_id, **kwargs)
break
except ClientError as ce:
if ce.status in (409, ):
print '{ce}, create an IP and retry'.format(ce=ce)
snf_network.create_floatingip(**kwargs)
else:
raise ce
entity.attributes['occi.compute.state'] = 'inactive'
entity.attributes['occi.core.id'] = str(info['id'])
entity.attributes['occi.compute.architecture'] = SERVER_CONFIG['compute_arch']
entity.attributes['occi.compute.cores'] = flavor.attributes['occi.compute.cores']
entity.attributes['occi.compute.memory'] = flavor.attributes['occi.compute.memory']
print "Prepare to inject public key to VM"
pub_key = yaml.dump({'public-keys': user_pub_key})
kwargs['personality'].append({
'contents': b64encode(pub_key),
'path': '/var/lib/cloud/seed/nocloud-net/meta-data'})
print 'Create a server...'
vm_name = entity.attributes['occi.core.title']
for retries in range(2):
try:
info = snf.create_server(
vm_name, flavor_id, image_id, **kwargs)
break
except ClientError as ce:
if ce.status in (409, ):
print '{ce}, create an IP and retry'.format(ce=ce)
snf_network.create_floatingip(**kwargs)
else:
raise ce
entity.attributes.update((
('occi.compute.state', 'inactive'),
('occi.core.id', str(info['id'])),
('occi.compute.architecture', SERVER_CONFIG['compute_arch']),
(
'occi.compute.cores',
flavor.attributes['occi.compute.cores']),
(
'occi.compute.memory',
flavor.attributes['occi.compute.memory']), ))
entity.actions = [
infrastructure.STOP,
infrastructure.SUSPEND,
infrastructure.RESTART]
# entity.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':info['id']}
info['adminPass']= ""
print info
networkIDs = info['addresses'].keys()
#resource.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':int(key)}
if len(networkIDs)>0:
entity.attributes['occi.compute.hostname'] = str(info['addresses'][networkIDs[0]][0]['addr'])
else:
entity.attributes['occi.compute.hostname'] = ""
except (UnboundLocalError, KeyError) as e:
raise HTTPError(406, 'Missing details about compute instance')
info['adminPass'] = ""
print 'info: {0}'.format(info)
networkIDs, addr = info['addresses'].keys(), ''
if networkIDs:
addr = str(info['addresses'][networkIDs[0]][0]['addr'])
entity.attributes['occi.compute.hostname'] = addr
except (UnboundLocalError, KeyError):
raise HTTPError(406, 'Missing details about compute instance')
def retrieve(self, entity, extras):
#Triggering cyclades to retrieve up to date information
"""Triggering cyclades to retrieve up to date information"""
snf = extras['snf']
vm_id = int(entity.attributes['occi.core.id'])
vm_info = snf.get_server_details(vm_id)
vm_state = vm_info['status']
status_dict = {'ACTIVE' : 'active',
'STOPPED' : 'inactive',
'REBOOT' : 'inactive',
'ERROR' : 'inactive',
'BUILD' : 'inactive',
'DELETED' : 'inactive',
'UNKNOWN' : 'inactive'
}
status_dict = dict(
ACTIVE='active', STOPPED='inactive', REBOOT='inactive',
ERROR='inactive', BUILD='inactive', DELETED='inactive',
UNKNOWN='inactive', )
entity.attributes['occi.compute.state'] = status_dict[vm_state]
if vm_state == 'ERROR':
raise HTTPError(500, 'ERROR building the compute instance')
if vm_state in ('ERROR', ):
raise HTTPError(500, 'ERROR building the compute instance')
else:
if entity.attributes['occi.compute.state'] == 'inactive':
entity.actions = [infrastructure.START]
if entity.attributes['occi.compute.state'] == 'active':
entity.actions = [infrastructure.STOP, infrastructure.SUSPEND, infrastructure.RESTART]
entity.actions = [
infrastructure.STOP,
infrastructure.SUSPEND,
infrastructure.RESTART]
def delete(self, entity, extras):
#Deleting compute instance
"""Deleting compute instance"""
snf = extras['snf']
vm_id = int(entity.attributes['occi.core.id'])
snf.delete_server(vm_id)
print "Deleting VM" + str(vm_id)
def get_vm_actions(self, entity ,vm_state):
def get_vm_actions(self, entity , vm_state):
actions = []
status_dict = {'ACTIVE' : 'active',
'STOPPED' : 'inactive',
'REBOOT' : 'inactive',
'ERROR' : 'inactive',
'BUILD' : 'inactive',
'DELETED' : 'inactive',
'UNKNOWN' : 'inactive'
}
status_dict = dict(
ACTIVE='active', STOPPED='inactive', REBOOT='inactive',
ERROR='inactive', BUILD='inactive', DELETED='inactive',
UNKNOWN='inactive', )
if vm_state in status_dict:
entity.attributes['occi.compute.state'] = status_dict[vm_state]
if vm_state == 'ACTIVE':
if vm_state in ('ACTIVE', ):
actions.append(infrastructure.STOP)
actions.append(infrastructure.RESTART)
elif vm_state in ('STOPPED'):
elif vm_state in ('STOPPED', ):
actions.append(infrastructure.START)
return actions
else:
raise HTTPError(500, 'Undefined status of the VM')
def action(self, entity, action, attributes, extras):
#Triggering action to compute instances
"""Triggering action to compute instances"""
client = extras['client']
snf = extras['snf']
vm_id = int(entity.attributes['occi.core.id'])
vm_info = snf.get_server_details(vm_id)
vm_state = vm_info['status']
# Define the allowed actions depending on the state of the VM
entity.actions = self.get_vm_actions(entity,vm_state)
entity.actions = self.get_vm_actions(entity, vm_state)
if vm_state == 'ERROR':
raise HTTPError(500, 'ERROR building the compute instance')
else:
if action not in entity.actions:
raise AttributeError("This action is currently no applicable in the current status of the VM (CURRENT_STATE = " + str(vm_state)+ ").")
raise AttributeError(
"Action not applicable for VM with status {0}".format(
vm_state))
elif action == infrastructure.START:
print "Starting VM" + str(vm_id)
print "Starting VM {0}".format(vm_id)
client.start_server(vm_id)
elif action == infrastructure.STOP:
print "Stopping VM" + str(vm_id)
print "Stopping VM {0}".format(vm_id)
client.shutdown_server(vm_id)
elif action == infrastructure.RESTART:
print "Restarting VM" + str(vm_id)
print "Restarting VM {0}".format(vm_id)
snf.reboot_server(vm_id)
elif action == infrastructure.SUSPEND:
raise HTTPError(501, "This actions is currently no applicable")
raise HTTPError(501, "Actions not applicable")
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment