Removing oca python module and using xmlrpc to access opennebula (we have found problems with oca python accesing OpenNebula 5.0)

This commit is contained in:
Adolfo Gómez García 2016-07-11 03:44:38 +02:00
parent 643d8b40e1
commit f0049cb826
5 changed files with 148 additions and 24 deletions

View File

@ -0,0 +1,61 @@
'''
Created on Jul 11, 2016
@author: dkmaster
'''
# -*- coding: utf-8 -*-
#
# Copyright (c) 2013 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from __future__ import unicode_literals
from collections import defaultdict
from xml.etree import cElementTree
def etree_to_dict(t):
d = {t.tag: {} if t.attrib else None}
children = list(t)
if children:
dd = defaultdict(list)
for dc in map(etree_to_dict, children):
for k, v in dc.items():
dd[k].append(v)
d = {t.tag: {k:v[0] if len(v) == 1 else v for k, v in dd.items()}}
if t.attrib:
d[t.tag].update(('@' + k, v) for k, v in t.attrib.items())
if t.text:
text = t.text.strip()
if children or t.attrib:
if text:
d[t.tag]['#text'] = text
else:
d[t.tag] = text
return d
def parse(xml_string):
return etree_to_dict(cElementTree.XML(xml_string)) # @UndefinedVariable

View File

@ -50,7 +50,7 @@ import six
# Python bindings for OpenNebula
import oca
__updated__ = '2016-04-25'
__updated__ = '2016-07-11'
logger = logging.getLogger(__name__)
@ -129,7 +129,7 @@ class Provider(ServiceProvider):
@property
def api(self):
if self._api is None:
self._api = oca.Client('{}:{}'.format(self.username.value, self.password.value), self.endpoint)
self._api = on.OpenNebulaClient(self.username.value, self.password.value, self.endpoint)
return self._api

View File

@ -38,12 +38,10 @@ import re
import logging
import six
from defusedxml import minidom
import xmlrpclib
from uds.core.util import xml2dict
# Python bindings for OpenNebula
import oca
__updated__ = '2016-02-25'
__updated__ = '2016-07-11'
logger = logging.getLogger(__name__)
@ -61,3 +59,79 @@ from . import template
from . import vm
from . import storage
# Decorator
def ensureConnected(fnc):
def inner(*args, **kwargs):
args[0].connect()
return fnc(*args, **kwargs)
return inner
# Result checker
def checkResult(lst, parseResult=True):
if lst[0] == False:
raise Exception('OpenNebula error {}: "{}"'.format(lst[2], lst[1]))
if parseResult:
return xml2dict.parse(lst[1])
else:
return lst[1]
def asList(element):
if isinstance(element, (tuple, list)):
return element
return (element,)
class OpenNebulaClient(object):
def __init__(self, username, password, endpoint):
self.username = username
self.password = password
self.endpoint = endpoint
self.connection = None
@property
def sessionString(self):
return '{}:{}'.format(self.username, self.password)
def connect(self):
if self.connection is not None:
return
self.connection = xmlrpclib.ServerProxy(self.endpoint)
@ensureConnected
def enumStorage(self, storageType=0):
storageType = six.text_type(storageType) # Ensure it is an string
# Invoke datastore pools info, no parameters except connection string
result = self.connection.one.datastorepool.info(self.sessionString)
result = checkResult(result)
for ds in asList(result['DATASTORE_POOL']['DATASTORE']):
if ds['TYPE'] == storageType:
yield(ds['ID'], ds['NAME'], ds['TOTAL_MB'], ds['FREE_MB'])
@ensureConnected
def enumTemplates(self):
# Invoke templates pools info, with this parameters:
# 1.- Session string
# 2.- Filter flag - < = -3: Connected users resources - -2: All resources - -1: Connected users and his groups resources - > = 0: UID Users Resources
# 3.- When the next parameter is >= -1 this is the Range start ID. Can be -1. For smaller values this is the offset used for pagination.
# 4.- For values >= -1 this is the Range end ID. Can be -1 to get until the last ID. For values < -1 this is the page size used for pagination.
result = self.connection.one.templatepool.info(self.sessionString, -3, -1, -1)
result = checkResult(result)
for ds in asList(result['VMTEMPLATE_POOL']['VMTEMPLATE']):
yield(ds['ID'], ds['NAME'], ds['TEMPLATE']['MEMORY'])
@ensureConnected
def templateInfo(self, templateId, extraInfo=False):
'''
Returns a list
first element is a dictionary (built from XML)
second is original XML
'''
result = self.connection.one.template.info(self.sessionString, int(templateId), extraInfo)
res = checkResult(result)
return (res, result[1])
@ensureConnected
def cloneImage(self, srcId, name, datastoreId=-1):
result = self.connection.one.image.clone(self.sessionString, int(srcId), name, int(datastoreId))
return checkResult(result, parseResult=False)

View File

@ -32,11 +32,9 @@
'''
import logging
import six
import oca
__updated__ = '2016-02-09'
__updated__ = '2016-07-11'
logger = logging.getLogger(__name__)
@ -44,9 +42,4 @@ def enumerateDatastores(api, datastoreType=0):
'''
0 seems to be images datastore
'''
datastores = oca.DatastorePool(api)
datastores.info()
for ds in datastores:
if ds.type == datastoreType:
yield (ds.id, ds.name)
return api.enumStorage(datastoreType)

View File

@ -39,20 +39,16 @@ from defusedxml import minidom
# Python bindings for OpenNebula
from .common import sanitizeName
__updated__ = '2016-02-09'
__updated__ = '2016-07-11'
logger = logging.getLogger(__name__)
def getTemplates(api, force=False):
logger.debug('Api: {}'.format(api))
templatesPool = oca.VmTemplatePool(api)
templatesPool.info()
for t in templatesPool:
if t.name[:4] != 'UDSP':
yield (t.id, t.name)
for t in api.enumTemplates():
if t[1][:4] != 'UDSP': # 0 = id, 1 = name
yield t
def create(api, fromTemplateId, name, toDataStore):
'''