forked from shaba/openuds
Fixed opennebula provider for python 3.7 && updated setting to nonpersistant (moved to end of image clone process)
This commit is contained in:
parent
7d66d92f85
commit
54110f5425
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -30,16 +30,16 @@
|
|||||||
"""
|
"""
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
"""
|
"""
|
||||||
|
import pickle
|
||||||
|
import logging
|
||||||
|
import typing
|
||||||
|
|
||||||
from uds.core.services import UserDeployment
|
from uds.core.services import UserDeployment
|
||||||
from uds.core.util.State import State
|
from uds.core.util.State import State
|
||||||
from uds.core.util import log
|
from uds.core.util import log
|
||||||
|
|
||||||
from . import on
|
from . import on
|
||||||
|
|
||||||
import pickle
|
|
||||||
import logging
|
|
||||||
|
|
||||||
__updated__ = '2019-02-07'
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -47,7 +47,6 @@ opCreate, opStart, opSuspend, opRemove, opWait, opError, opFinish, opRetry = ran
|
|||||||
|
|
||||||
NO_MORE_NAMES = 'NO-NAME-ERROR'
|
NO_MORE_NAMES = 'NO-NAME-ERROR'
|
||||||
|
|
||||||
|
|
||||||
class LiveDeployment(UserDeployment):
|
class LiveDeployment(UserDeployment):
|
||||||
"""
|
"""
|
||||||
This class generates the user consumable elements of the service tree.
|
This class generates the user consumable elements of the service tree.
|
||||||
@ -59,10 +58,18 @@ class LiveDeployment(UserDeployment):
|
|||||||
The logic for managing ovirt deployments (user machines in this case) is here.
|
The logic for managing ovirt deployments (user machines in this case) is here.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# : Recheck every six seconds by default (for task methods)
|
# : Recheck every six seconds by default (for task methods)
|
||||||
suggestedTime = 6
|
suggestedTime = 6
|
||||||
|
|
||||||
|
#
|
||||||
|
_name = ''
|
||||||
|
_ip = ''
|
||||||
|
_mac = ''
|
||||||
|
_vmid = ''
|
||||||
|
_reason = ''
|
||||||
|
_queue: typing.List[int] = []
|
||||||
|
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self._name = ''
|
self._name = ''
|
||||||
self._ip = ''
|
self._ip = ''
|
||||||
@ -86,11 +93,11 @@ class LiveDeployment(UserDeployment):
|
|||||||
pickle.dumps(self._queue, protocol=0)
|
pickle.dumps(self._queue, protocol=0)
|
||||||
])
|
])
|
||||||
|
|
||||||
def unmarshal(self, str_):
|
def unmarshal(self, data):
|
||||||
"""
|
"""
|
||||||
Does nothing here also, all data are keeped at environment storage
|
Does nothing here also, all data are keeped at environment storage
|
||||||
"""
|
"""
|
||||||
vals = str_.split(b'\1')
|
vals = data.split(b'\1')
|
||||||
if vals[0] == b'v1':
|
if vals[0] == b'v1':
|
||||||
self._name = vals[1].decode('utf8')
|
self._name = vals[1].decode('utf8')
|
||||||
self._ip = vals[2].decode('utf8')
|
self._ip = vals[2].decode('utf8')
|
||||||
@ -139,7 +146,7 @@ class LiveDeployment(UserDeployment):
|
|||||||
:note: This IP is the IP of the "consumed service", so the transport can
|
:note: This IP is the IP of the "consumed service", so the transport can
|
||||||
access it.
|
access it.
|
||||||
"""
|
"""
|
||||||
logger.debug('Setting IP to {}'.format(ip))
|
logger.debug('Setting IP to %s', ip)
|
||||||
self._ip = ip
|
self._ip = ip
|
||||||
|
|
||||||
def getUniqueId(self):
|
def getUniqueId(self):
|
||||||
@ -204,7 +211,7 @@ class LiveDeployment(UserDeployment):
|
|||||||
|
|
||||||
def notifyReadyFromOsManager(self, data):
|
def notifyReadyFromOsManager(self, data):
|
||||||
# Here we will check for suspending the VM (when full ready)
|
# Here we will check for suspending the VM (when full ready)
|
||||||
logger.debug('Checking if cache 2 for {0}'.format(self._name))
|
logger.debug('Checking if cache 2 for %s', self._name)
|
||||||
if self.__getCurrentOp() == opWait:
|
if self.__getCurrentOp() == opWait:
|
||||||
logger.debug('Machine is ready. Moving to level 2')
|
logger.debug('Machine is ready. Moving to level 2')
|
||||||
self.__popCurrentOp() # Remove current state
|
self.__popCurrentOp() # Remove current state
|
||||||
@ -235,7 +242,7 @@ class LiveDeployment(UserDeployment):
|
|||||||
self._queue = [opCreate, opStart, opWait, opSuspend, opFinish]
|
self._queue = [opCreate, opStart, opWait, opSuspend, opFinish]
|
||||||
|
|
||||||
def __checkMachineState(self, chkState):
|
def __checkMachineState(self, chkState):
|
||||||
logger.debug('Checking that state of machine {} ({}) is {}'.format(self._vmid, self._name, chkState))
|
logger.debug('Checking that state of machine %s (%s) is %s', self._vmid, self._name, chkState)
|
||||||
state = self.service().getMachineState(self._vmid)
|
state = self.service().getMachineState(self._vmid)
|
||||||
|
|
||||||
# If we want to check an state and machine does not exists (except in case that we whant to check this)
|
# If we want to check an state and machine does not exists (except in case that we whant to check this)
|
||||||
@ -254,13 +261,13 @@ class LiveDeployment(UserDeployment):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def __getCurrentOp(self):
|
def __getCurrentOp(self):
|
||||||
if len(self._queue) == 0:
|
if not self._queue:
|
||||||
return opFinish
|
return opFinish
|
||||||
|
|
||||||
return self._queue[0]
|
return self._queue[0]
|
||||||
|
|
||||||
def __popCurrentOp(self):
|
def __popCurrentOp(self):
|
||||||
if len(self._queue) == 0:
|
if not self._queue:
|
||||||
return opFinish
|
return opFinish
|
||||||
|
|
||||||
res = self._queue.pop(0)
|
res = self._queue.pop(0)
|
||||||
@ -279,14 +286,14 @@ class LiveDeployment(UserDeployment):
|
|||||||
Returns:
|
Returns:
|
||||||
State.ERROR, so we can do "return self.__error(reason)"
|
State.ERROR, so we can do "return self.__error(reason)"
|
||||||
"""
|
"""
|
||||||
logger.debug('Setting error state, reason: {0}'.format(reason))
|
logger.debug('Setting error state, reason: %s', reason)
|
||||||
self.doLog(log.ERROR, reason)
|
self.doLog(log.ERROR, reason)
|
||||||
|
|
||||||
if self._vmid != '': # Powers off & delete it
|
if self._vmid != '': # Powers off & delete it
|
||||||
try:
|
try:
|
||||||
self.service().removeMachine(self._vmid)
|
self.service().removeMachine(self._vmid)
|
||||||
except:
|
except Exception:
|
||||||
logger.debug('Can\t set machine state to stopped')
|
logger.debug('Can\'t set machine state to stopped')
|
||||||
|
|
||||||
self._queue = [opError]
|
self._queue = [opError]
|
||||||
self._reason = str(reason)
|
self._reason = str(reason)
|
||||||
@ -371,7 +378,7 @@ class LiveDeployment(UserDeployment):
|
|||||||
if state == on.VmState.ACTIVE: # @UndefinedVariable
|
if state == on.VmState.ACTIVE: # @UndefinedVariable
|
||||||
subState = self.service().getMachineSubstate(self._vmid)
|
subState = self.service().getMachineSubstate(self._vmid)
|
||||||
if subState < 3: # Less than running
|
if subState < 3: # Less than running
|
||||||
logger.info('Must wait before remove: {}'.format(subState))
|
logger.info('Must wait before remove: %s', subState)
|
||||||
self.__pushFrontOp(opRetry)
|
self.__pushFrontOp(opRetry)
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -457,7 +464,6 @@ class LiveDeployment(UserDeployment):
|
|||||||
(No matter wether it is for cache or for an user)
|
(No matter wether it is for cache or for an user)
|
||||||
"""
|
"""
|
||||||
self.__debug('finish')
|
self.__debug('finish')
|
||||||
pass
|
|
||||||
|
|
||||||
def moveToCache(self, newLevel):
|
def moveToCache(self, newLevel):
|
||||||
"""
|
"""
|
||||||
@ -529,8 +535,8 @@ class LiveDeployment(UserDeployment):
|
|||||||
}.get(op, '????')
|
}.get(op, '????')
|
||||||
|
|
||||||
def __debug(self, txt):
|
def __debug(self, txt):
|
||||||
logger.debug('_name {0}: {1}'.format(txt, self._name))
|
logger.debug('_name %s: %s', txt, self._name)
|
||||||
logger.debug('_ip {0}: {1}'.format(txt, self._ip))
|
logger.debug('_ip %s: %s', txt, self._ip)
|
||||||
logger.debug('_mac {0}: {1}'.format(txt, self._mac))
|
logger.debug('_mac %s: %s', txt, self._mac)
|
||||||
logger.debug('_vmid {0}: {1}'.format(txt, self._vmid))
|
logger.debug('_vmid %s: %s', txt, self._vmid)
|
||||||
logger.debug('Queue at {0}: {1}'.format(txt, [LiveDeployment.__op2str(op) for op in self._queue]))
|
logger.debug('Queue at %s: %s', txt, [LiveDeployment.__op2str(op) for op in self._queue])
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -30,16 +30,11 @@
|
|||||||
"""
|
"""
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
"""
|
"""
|
||||||
|
import logging
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
from uds.core.services import Publication
|
from uds.core.services import Publication
|
||||||
from uds.core.util.State import State
|
from uds.core.util.State import State
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
__updated__ = '2019-02-07'
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -51,6 +46,11 @@ class LivePublication(Publication):
|
|||||||
|
|
||||||
suggestedTime = 2 # : Suggested recheck time if publication is unfinished in seconds
|
suggestedTime = 2 # : Suggested recheck time if publication is unfinished in seconds
|
||||||
|
|
||||||
|
_name = ''
|
||||||
|
_reason = ''
|
||||||
|
_templateId = ''
|
||||||
|
_state = ''
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
"""
|
"""
|
||||||
This method will be invoked by default __init__ of base class, so it gives
|
This method will be invoked by default __init__ of base class, so it gives
|
||||||
@ -76,7 +76,7 @@ class LivePublication(Publication):
|
|||||||
"""
|
"""
|
||||||
deserializes the data and loads it inside instance.
|
deserializes the data and loads it inside instance.
|
||||||
"""
|
"""
|
||||||
logger.debug('Data: {0}'.format(data))
|
logger.debug('Data: %s', data)
|
||||||
vals = data.decode('utf8').split('\t')
|
vals = data.decode('utf8').split('\t')
|
||||||
if vals[0] == 'v1':
|
if vals[0] == 'v1':
|
||||||
self._name, self._reason, self._templateId, self._state = vals[1:]
|
self._name, self._reason, self._templateId, self._state = vals[1:]
|
||||||
@ -93,7 +93,7 @@ class LivePublication(Publication):
|
|||||||
self._templateId = self.service().makeTemplate(self._name)
|
self._templateId = self.service().makeTemplate(self._name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._state = 'error'
|
self._state = 'error'
|
||||||
self._reason = six.text_type(e)
|
self._reason = str(e)
|
||||||
return State.ERROR
|
return State.ERROR
|
||||||
|
|
||||||
return State.RUNNING
|
return State.RUNNING
|
||||||
@ -109,7 +109,7 @@ class LivePublication(Publication):
|
|||||||
self._state = 'ok'
|
self._state = 'ok'
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._state = 'error'
|
self._state = 'error'
|
||||||
self._reason = six.text_type(e)
|
self._reason = str(e)
|
||||||
|
|
||||||
if self._state == 'error':
|
if self._state == 'error':
|
||||||
return State.ERROR
|
return State.ERROR
|
||||||
@ -124,7 +124,6 @@ class LivePublication(Publication):
|
|||||||
"""
|
"""
|
||||||
In our case, finish does nothing
|
In our case, finish does nothing
|
||||||
"""
|
"""
|
||||||
pass
|
|
||||||
|
|
||||||
def reasonOfError(self):
|
def reasonOfError(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -30,17 +30,16 @@
|
|||||||
"""
|
"""
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
"""
|
"""
|
||||||
from django.utils.translation import ugettext_noop as _, ugettext
|
import logging
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_noop as _
|
||||||
from uds.core.transports import protocols
|
from uds.core.transports import protocols
|
||||||
from uds.core.services import Service, types as serviceTypes
|
from uds.core.services import Service, types as serviceTypes
|
||||||
|
from uds.core.ui import gui
|
||||||
|
|
||||||
from .LivePublication import LivePublication
|
from .LivePublication import LivePublication
|
||||||
from .LiveDeployment import LiveDeployment
|
from .LiveDeployment import LiveDeployment
|
||||||
|
|
||||||
from uds.core.ui import gui
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
__updated__ = '2018-08-20'
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -186,7 +185,7 @@ class LiveService(Service):
|
|||||||
Returns:
|
Returns:
|
||||||
Id of the machine being created form template
|
Id of the machine being created form template
|
||||||
"""
|
"""
|
||||||
logger.debug('Deploying from template {0} machine {1}'.format(templateId, name))
|
logger.debug('Deploying from template %s machine %s', templateId, name)
|
||||||
# self.datastoreHasSpace()
|
# self.datastoreHasSpace()
|
||||||
return self.parent().deployFromTemplate(name, templateId)
|
return self.parent().deployFromTemplate(name, templateId)
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -28,29 +28,18 @@
|
|||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Created on Jun 22, 2012
|
|
||||||
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||||
'''
|
'''
|
||||||
from __future__ import unicode_literals
|
import logging
|
||||||
|
|
||||||
from django.utils.translation import ugettext_noop as _
|
from django.utils.translation import ugettext_noop as _
|
||||||
from uds.core.services import ServiceProvider
|
from uds.core.services import ServiceProvider
|
||||||
from uds.core.ui import gui
|
from uds.core.ui import gui
|
||||||
from uds.core.util import validators
|
from uds.core.util import validators
|
||||||
from defusedxml import minidom
|
|
||||||
|
|
||||||
from .LiveService import LiveService
|
from .LiveService import LiveService
|
||||||
from . import on
|
from . import on
|
||||||
|
|
||||||
import logging
|
|
||||||
import six
|
|
||||||
|
|
||||||
# Python bindings for OpenNebula
|
|
||||||
# import oca
|
|
||||||
|
|
||||||
__updated__ = '2018-08-20'
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -119,7 +108,7 @@ class Provider(ServiceProvider):
|
|||||||
|
|
||||||
if values is not None:
|
if values is not None:
|
||||||
self.timeout.value = validators.validateTimeout(self.timeout.value, returnAsInteger=False)
|
self.timeout.value = validators.validateTimeout(self.timeout.value, returnAsInteger=False)
|
||||||
logger.debug('Endpoint: {}'.format(self.endpoint))
|
logger.debug('Endpoint: %s', self.endpoint)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def endpoint(self):
|
def endpoint(self):
|
||||||
@ -130,7 +119,7 @@ class Provider(ServiceProvider):
|
|||||||
if self._api is None:
|
if self._api is None:
|
||||||
self._api = on.OpenNebulaClient(self.username.value, self.password.value, self.endpoint)
|
self._api = on.OpenNebulaClient(self.username.value, self.password.value, self.endpoint)
|
||||||
|
|
||||||
logger.debug('Api: {}'.format(self._api))
|
logger.debug('Api: %s', self._api)
|
||||||
return self._api
|
return self._api
|
||||||
|
|
||||||
def resetApi(self):
|
def resetApi(self):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -32,16 +32,16 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# pylint: disable=maybe-no-member
|
# pylint: disable=maybe-no-member
|
||||||
|
import types
|
||||||
import six
|
import xmlrpc.client
|
||||||
|
|
||||||
from uds.core.util import xml2dict
|
from uds.core.util import xml2dict
|
||||||
|
|
||||||
from . import storage
|
from . import storage
|
||||||
from . import template
|
from . import template
|
||||||
from . import vm
|
from . import vm
|
||||||
# Import submodules
|
# Import submodules
|
||||||
from .common import *
|
from .common import *
|
||||||
import types
|
|
||||||
|
|
||||||
__updated__ = '2017-03-28'
|
__updated__ = '2017-03-28'
|
||||||
|
|
||||||
@ -72,14 +72,14 @@ def checkResult(lst, parseResult=True):
|
|||||||
raise Exception('OpenNebula error {}: "{}"'.format(lst[2], lst[1]))
|
raise Exception('OpenNebula error {}: "{}"'.format(lst[2], lst[1]))
|
||||||
if parseResult:
|
if parseResult:
|
||||||
return xml2dict.parse(lst[1])
|
return xml2dict.parse(lst[1])
|
||||||
else:
|
|
||||||
return lst[1]
|
return lst[1]
|
||||||
|
|
||||||
|
|
||||||
def asList(element):
|
def asList(element):
|
||||||
if isinstance(element, (tuple, list)):
|
if isinstance(element, (tuple, list)):
|
||||||
return element
|
return element
|
||||||
return element,
|
return (element,)
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyShadowingNames
|
# noinspection PyShadowingNames
|
||||||
@ -95,7 +95,7 @@ class OpenNebulaClient(object):
|
|||||||
def sessionString(self):
|
def sessionString(self):
|
||||||
return '{}:{}'.format(self.username, self.password)
|
return '{}:{}'.format(self.username, self.password)
|
||||||
|
|
||||||
@property
|
@property # type: ignore
|
||||||
@ensureConnected
|
@ensureConnected
|
||||||
def version(self):
|
def version(self):
|
||||||
if self.cachedVersion is None:
|
if self.cachedVersion is None:
|
||||||
@ -108,11 +108,11 @@ class OpenNebulaClient(object):
|
|||||||
if self.connection is not None:
|
if self.connection is not None:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.connection = six.moves.xmlrpc_client.ServerProxy(self.endpoint) # @UndefinedVariable
|
self.connection = xmlrpc.client.ServerProxy(self.endpoint) # @UndefinedVariable
|
||||||
|
|
||||||
@ensureConnected
|
@ensureConnected
|
||||||
def enumStorage(self, storageType=0):
|
def enumStorage(self, storageType=0):
|
||||||
storageType = six.text_type(storageType) # Ensure it is an string
|
storageType = str(storageType) # Ensure it is an string
|
||||||
# Invoke datastore pools info, no parameters except connection string
|
# Invoke datastore pools info, no parameters except connection string
|
||||||
result = self.connection.one.datastorepool.info(self.sessionString)
|
result = self.connection.one.datastorepool.info(self.sessionString)
|
||||||
result = checkResult(result)
|
result = checkResult(result)
|
||||||
@ -129,8 +129,7 @@ class OpenNebulaClient(object):
|
|||||||
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.
|
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.
|
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, -1, -1, -1)
|
result = checkResult(self.connection.one.templatepool.info(self.sessionString, -1, -1, -1))
|
||||||
result = checkResult(result)
|
|
||||||
for ds in asList(result['VMTEMPLATE_POOL']['VMTEMPLATE']):
|
for ds in asList(result['VMTEMPLATE_POOL']['VMTEMPLATE']):
|
||||||
try:
|
try:
|
||||||
yield(ds['ID'], ds['NAME'], ds['TEMPLATE']['MEMORY'])
|
yield(ds['ID'], ds['NAME'], ds['TEMPLATE']['MEMORY'])
|
||||||
@ -182,7 +181,7 @@ class OpenNebulaClient(object):
|
|||||||
return checkResult(result, parseResult=False)
|
return checkResult(result, parseResult=False)
|
||||||
|
|
||||||
@ensureConnected
|
@ensureConnected
|
||||||
def updateTemplate(self, templateId, template, updateType=0):
|
def updateTemplate(self, templateId, templateData, updateType=0):
|
||||||
"""
|
"""
|
||||||
Updates the template with the templateXml
|
Updates the template with the templateXml
|
||||||
1.- Session string
|
1.- Session string
|
||||||
@ -190,7 +189,7 @@ class OpenNebulaClient(object):
|
|||||||
3.- The new template contents. Syntax can be the usual attribute=value or XML.
|
3.- The new template contents. Syntax can be the usual attribute=value or XML.
|
||||||
4.- Update type. 0 replace the whole template, 1 merge with the existing one
|
4.- Update type. 0 replace the whole template, 1 merge with the existing one
|
||||||
"""
|
"""
|
||||||
result = self.connection.one.template.update(self.sessionString, int(templateId), template, int(updateType))
|
result = self.connection.one.template.update(self.sessionString, int(templateId), templateData, int(updateType))
|
||||||
return checkResult(result, parseResult=False)
|
return checkResult(result, parseResult=False)
|
||||||
|
|
||||||
@ensureConnected
|
@ensureConnected
|
||||||
@ -208,6 +207,7 @@ class OpenNebulaClient(object):
|
|||||||
@ensureConnected
|
@ensureConnected
|
||||||
def deleteTemplate(self, templateId):
|
def deleteTemplate(self, templateId):
|
||||||
"""
|
"""
|
||||||
|
Deletes the template (not images)
|
||||||
"""
|
"""
|
||||||
result = self.connection.one.template.delete(self.sessionString, int(templateId))
|
result = self.connection.one.template.delete(self.sessionString, int(templateId))
|
||||||
return checkResult(result, parseResult=False)
|
return checkResult(result, parseResult=False)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -37,8 +37,6 @@ import re
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
__updated__ = '2016-02-09'
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
module = sys.modules[__name__]
|
module = sys.modules[__name__]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -34,8 +34,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
__updated__ = '2016-07-11'
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def enumerateDatastores(api, datastoreType=0):
|
def enumerateDatastores(api, datastoreType=0):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -32,17 +32,14 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import six
|
|
||||||
|
|
||||||
from defusedxml import minidom
|
from defusedxml import minidom
|
||||||
# Python bindings for OpenNebula
|
# Python bindings for OpenNebula
|
||||||
from .common import sanitizeName
|
from .common import sanitizeName
|
||||||
|
|
||||||
__updated__ = '2017-05-05'
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def getTemplates(api, force=False):
|
def getTemplates(api, force=False):
|
||||||
|
|
||||||
for t in api.enumTemplates():
|
for t in api.enumTemplates():
|
||||||
@ -76,13 +73,13 @@ def create(api, fromTemplateId, name, toDataStore):
|
|||||||
|
|
||||||
info = api.templateInfo(templateId)[1]
|
info = api.templateInfo(templateId)[1]
|
||||||
template = minidom.parseString(info).getElementsByTagName('TEMPLATE')[0]
|
template = minidom.parseString(info).getElementsByTagName('TEMPLATE')[0]
|
||||||
logger.debug('XML: {}'.format(template.toxml()))
|
logger.debug('XML: %s', template.toxml())
|
||||||
|
|
||||||
counter = 0
|
counter = 0
|
||||||
for dsk in template.getElementsByTagName('DISK'):
|
for dsk in template.getElementsByTagName('DISK'):
|
||||||
counter += 1
|
counter += 1
|
||||||
imgIds = dsk.getElementsByTagName('IMAGE_ID')
|
imgIds = dsk.getElementsByTagName('IMAGE_ID')
|
||||||
if len(imgIds) == 0:
|
if not imgIds:
|
||||||
fromId = False
|
fromId = False
|
||||||
try:
|
try:
|
||||||
node = dsk.getElementsByTagName('IMAGE')[0].childNodes[0]
|
node = dsk.getElementsByTagName('IMAGE')[0].childNodes[0]
|
||||||
@ -99,19 +96,17 @@ def create(api, fromTemplateId, name, toDataStore):
|
|||||||
node = imgIds[0].childNodes[0]
|
node = imgIds[0].childNodes[0]
|
||||||
imgId = node.data
|
imgId = node.data
|
||||||
|
|
||||||
logger.debug('Found {} for cloning'.format(imgId))
|
logger.debug('Found %s for cloning', imgId)
|
||||||
|
|
||||||
# if api.imageInfo(imgId)[0]['IMAGE']['STATE'] != '1':
|
# if api.imageInfo(imgId)[0]['IMAGE']['STATE'] != '1':
|
||||||
# raise Exception('The base machines images are not in READY state')
|
# raise Exception('The base machines images are not in READY state')
|
||||||
|
|
||||||
# Now clone the image
|
# Now clone the image
|
||||||
imgName = sanitizeName(name + ' DSK ' + six.text_type(counter))
|
imgName = sanitizeName(name + ' DSK ' + str(counter))
|
||||||
newId = api.cloneImage(imgId, imgName, toDataStore) # api.call('image.clone', int(imgId), imgName, int(toDataStore))
|
newId = api.cloneImage(imgId, imgName, toDataStore) # api.call('image.clone', int(imgId), imgName, int(toDataStore))
|
||||||
# Ensure image is non persistent
|
|
||||||
api.makePersistentImage(newId, False)
|
|
||||||
# Now Store id/name
|
# Now Store id/name
|
||||||
if fromId is True:
|
if fromId is True:
|
||||||
node.data = six.text_type(newId)
|
node.data = str(newId)
|
||||||
else:
|
else:
|
||||||
node.data = imgName
|
node.data = imgName
|
||||||
|
|
||||||
@ -119,9 +114,9 @@ def create(api, fromTemplateId, name, toDataStore):
|
|||||||
# api.call('template.update', templateId, template.toxml())
|
# api.call('template.update', templateId, template.toxml())
|
||||||
api.updateTemplate(templateId, template.toxml())
|
api.updateTemplate(templateId, template.toxml())
|
||||||
|
|
||||||
return six.text_type(templateId)
|
return str(templateId)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('Creating template on OpenNebula: {}'.format(e))
|
logger.exception('Creating template on OpenNebula')
|
||||||
try:
|
try:
|
||||||
api.deleteTemplate(templateId) # Try to remove created template in case of fail
|
api.deleteTemplate(templateId) # Try to remove created template in case of fail
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -143,11 +138,11 @@ def remove(api, templateId):
|
|||||||
|
|
||||||
info = api.templateInfo(templateId)[1]
|
info = api.templateInfo(templateId)[1]
|
||||||
template = minidom.parseString(info).getElementsByTagName('TEMPLATE')[0]
|
template = minidom.parseString(info).getElementsByTagName('TEMPLATE')[0]
|
||||||
logger.debug('XML: {}'.format(template.toxml()))
|
logger.debug('XML: %s', template.toxml())
|
||||||
|
|
||||||
for dsk in template.getElementsByTagName('DISK'):
|
for dsk in template.getElementsByTagName('DISK'):
|
||||||
imgIds = dsk.getElementsByTagName('IMAGE_ID')
|
imgIds = dsk.getElementsByTagName('IMAGE_ID')
|
||||||
if len(imgIds) == 0:
|
if not imgIds:
|
||||||
try:
|
try:
|
||||||
node = dsk.getElementsByTagName('IMAGE')[0].childNodes[0]
|
node = dsk.getElementsByTagName('IMAGE')[0].childNodes[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
@ -157,17 +152,16 @@ def remove(api, templateId):
|
|||||||
node = imgIds[0].childNodes[0]
|
node = imgIds[0].childNodes[0]
|
||||||
imgId = node.data
|
imgId = node.data
|
||||||
|
|
||||||
logger.debug('Found {} for cloning'.format(imgId))
|
logger.debug('Found %s for cloning', imgId)
|
||||||
|
|
||||||
# Now delete the image
|
# Now delete the image
|
||||||
api.deleteImage(imgId) # api.call('image.delete', int(imgId))
|
api.deleteImage(imgId) # api.call('image.delete', int(imgId))
|
||||||
|
except Exception:
|
||||||
except:
|
logger.exception('Removing image')
|
||||||
logger.exception('Exception cloning image')
|
|
||||||
|
|
||||||
api.deleteTemplate(templateId) # api.call('template.delete', int(templateId))
|
api.deleteTemplate(templateId) # api.call('template.delete', int(templateId))
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.error('Removing template on OpenNebula: {}'.format(e))
|
logger.error('Removing template on OpenNebula')
|
||||||
|
|
||||||
def deployFrom(api, templateId, name):
|
def deployFrom(api, templateId, name):
|
||||||
"""
|
"""
|
||||||
@ -182,7 +176,7 @@ def deployFrom(api, templateId, name):
|
|||||||
Id of the machine being created form template
|
Id of the machine being created form template
|
||||||
"""
|
"""
|
||||||
vmId = api.instantiateTemplate(templateId, name, False, '', False) # api.call('template.instantiate', int(templateId), name, False, '')
|
vmId = api.instantiateTemplate(templateId, name, False, '', False) # api.call('template.instantiate', int(templateId), name, False, '')
|
||||||
return six.text_type(vmId)
|
return str(vmId)
|
||||||
|
|
||||||
def checkPublished(api, templateId):
|
def checkPublished(api, templateId):
|
||||||
"""
|
"""
|
||||||
@ -193,11 +187,11 @@ def checkPublished(api, templateId):
|
|||||||
|
|
||||||
info = api.templateInfo(templateId)[1]
|
info = api.templateInfo(templateId)[1]
|
||||||
template = minidom.parseString(info).getElementsByTagName('TEMPLATE')[0]
|
template = minidom.parseString(info).getElementsByTagName('TEMPLATE')[0]
|
||||||
logger.debug('XML: {}'.format(template.toxml()))
|
logger.debug('XML: %s', template.toxml())
|
||||||
|
|
||||||
for dsk in template.getElementsByTagName('DISK'):
|
for dsk in template.getElementsByTagName('DISK'):
|
||||||
imgIds = dsk.getElementsByTagName('IMAGE_ID')
|
imgIds = dsk.getElementsByTagName('IMAGE_ID')
|
||||||
if len(imgIds) == 0:
|
if not imgIds:
|
||||||
try:
|
try:
|
||||||
node = dsk.getElementsByTagName('IMAGE')[0].childNodes[0]
|
node = dsk.getElementsByTagName('IMAGE')[0].childNodes[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
@ -207,13 +201,16 @@ def checkPublished(api, templateId):
|
|||||||
node = imgIds[0].childNodes[0]
|
node = imgIds[0].childNodes[0]
|
||||||
imgId = node.data
|
imgId = node.data
|
||||||
|
|
||||||
logger.debug('Found {} for checking'.format(imgId))
|
logger.debug('Found %s for checking', imgId)
|
||||||
|
|
||||||
state = api.imageInfo(imgId)[0]['IMAGE']['STATE']
|
state = api.imageInfo(imgId)[0]['IMAGE']['STATE']
|
||||||
if state in ('0', '4'):
|
if state in ('0', '4'):
|
||||||
return False
|
return False
|
||||||
elif state != '1': # If error is not READY
|
if state != '1': # If error is not READY
|
||||||
raise Exception('Error publishing. Image is in an invalid state. (Check it and delete it if not needed anymore)')
|
raise Exception('Error publishing. Image is in an invalid state. (Check it and delete it if not needed anymore)')
|
||||||
|
# Ensure image is non persistent. This may be invoked more than once, but idoes not matters
|
||||||
|
api.makePersistentImage(imgId, False)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception('Exception checking published')
|
logger.exception('Exception checking published')
|
||||||
raise
|
raise
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
# Copyright (c) 2012-2019 Virtual Cable S.L.
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -32,14 +32,12 @@
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import six
|
|
||||||
# import oca
|
# import oca
|
||||||
|
|
||||||
from defusedxml import minidom
|
from defusedxml import minidom
|
||||||
# Python bindings for OpenNebula
|
# Python bindings for OpenNebula
|
||||||
from .common import VmState
|
from .common import VmState
|
||||||
|
|
||||||
__updated__ = '2018-08-20'
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -61,7 +59,7 @@ def getMachineState(api, machineId):
|
|||||||
# return vm.state
|
# return vm.state
|
||||||
return api.getVMState(machineId)
|
return api.getVMState(machineId)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Error obtaining machine state for {} on OpenNebula: {}'.format(machineId, e))
|
logger.error('Error obtaining machine state for %s on OpenNebula: %s', machineId, e)
|
||||||
|
|
||||||
return VmState.UNKNOWN
|
return VmState.UNKNOWN
|
||||||
|
|
||||||
@ -73,7 +71,7 @@ def getMachineSubstate(api, machineId):
|
|||||||
try:
|
try:
|
||||||
return api.getVMSubstate(machineId)
|
return api.getVMSubstate(machineId)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Error obtaining machine state for {} on OpenNebula: {}'.format(machineId, e))
|
logger.error('Error obtaining machine substate for %s on OpenNebula: %s', machineId, e)
|
||||||
|
|
||||||
return VmState.UNKNOWN
|
return VmState.UNKNOWN
|
||||||
|
|
||||||
@ -91,7 +89,7 @@ def startMachine(api, machineId):
|
|||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
api.VMAction(machineId, 'resume')
|
api.VMAction(machineId, 'resume')
|
||||||
except Exception as e:
|
except Exception:
|
||||||
# MAybe the machine is already running. If we get error here, simply ignore it for now...
|
# MAybe the machine is already running. If we get error here, simply ignore it for now...
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -108,7 +106,7 @@ def stopMachine(api, machineId):
|
|||||||
try:
|
try:
|
||||||
api.VMAction(machineId, 'poweroff-hard')
|
api.VMAction(machineId, 'poweroff-hard')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Error powering off {} on OpenNebula: {}'.format(machineId, e))
|
logger.error('Error powering off %s on OpenNebula: %s', machineId, e)
|
||||||
|
|
||||||
|
|
||||||
def suspendMachine(api, machineId):
|
def suspendMachine(api, machineId):
|
||||||
@ -123,7 +121,7 @@ def suspendMachine(api, machineId):
|
|||||||
try:
|
try:
|
||||||
api.VMAction(machineId, 'suspend')
|
api.VMAction(machineId, 'suspend')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Error suspending {} on OpenNebula: {}'.format(machineId, e))
|
logger.error('Error suspending %s on OpenNebula: %s', machineId, e)
|
||||||
|
|
||||||
|
|
||||||
def resetMachine(api, machineId):
|
def resetMachine(api, machineId):
|
||||||
@ -138,7 +136,7 @@ def resetMachine(api, machineId):
|
|||||||
try:
|
try:
|
||||||
api.VMAction(machineId, 'reboot-hard')
|
api.VMAction(machineId, 'reboot-hard')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Error reseting {} on OpenNebula: {}'.format(machineId, e))
|
logger.error('Error reseting %s on OpenNebula: %s', machineId, e)
|
||||||
|
|
||||||
|
|
||||||
def removeMachine(api, machineId):
|
def removeMachine(api, machineId):
|
||||||
@ -155,8 +153,9 @@ def removeMachine(api, machineId):
|
|||||||
# vm.delete()
|
# vm.delete()
|
||||||
api.deleteVM(machineId)
|
api.deleteVM(machineId)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('Error removing machine {} on OpenNebula: {}'.format(machineId, e))
|
err = 'Error removing machine {} on OpenNebula: {}'.format(machineId, e)
|
||||||
raise Exception('Error removing machine {} on OpenNebula: {}'.format(machineId, e))
|
logger.exception(err)
|
||||||
|
raise Exception(err)
|
||||||
|
|
||||||
|
|
||||||
def enumerateMachines(api):
|
def enumerateMachines(api):
|
||||||
@ -248,4 +247,3 @@ def getDisplayConnection(api, machineId):
|
|||||||
# <NIC_ID><![CDATA[2]]></NIC_ID>
|
# <NIC_ID><![CDATA[2]]></NIC_ID>
|
||||||
# <VLAN><![CDATA[NO]]></VLAN>
|
# <VLAN><![CDATA[NO]]></VLAN>
|
||||||
# </NIC>
|
# </NIC>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user