forked from shaba/openuds
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:
parent
643d8b40e1
commit
f0049cb826
61
server/src/uds/core/util/xml2dict.py
Normal file
61
server/src/uds/core/util/xml2dict.py
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 user’s resources - -2: All resources - -1: Connected user’s and his group’s resources - > = 0: UID User’s 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)
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
'''
|
||||
|
Loading…
Reference in New Issue
Block a user