From fecd304798973c11234359a23352672b48eedc49 Mon Sep 17 00:00:00 2001 From: swuest Date: Thu, 7 May 2015 14:51:29 +0200 Subject: [PATCH 001/132] Added new load balancing functionality to the host.py. Also added a migrate function to elements for migrating them from one host to a new host. (Not finished) --- backend/tomato/elements/generic.py | 40 ++++++++++++++++++++ backend/tomato/host.py | 59 ++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 385db34dc..bd5b3aa6d 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -238,6 +238,46 @@ def after_upload_use(self): self.custom_template = True self.save() + def checkMigrate(self): + #We only migrate if element is prepared + if self.state in ["prepared"]: + return True + return False + + def action_migrate(self,host): + if self.checkMigrate(self): + + UserError.check(host, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) + + + + + attrs = self._remoteAttrs() + attrs.update({ + "template": self._template().name, + }) + attrs.update(self._profileAttrs()) + + #Create identical element on new host + new_el = host.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) + + + #Neues element soll template uploaden (action_grant_upload) + #Neues element soll template nutzen (action_grant_upload_use) + + #Kill old element on old host + self.element.action("destroy") + + #Set new element and save it + self.element = new_el + self.save() + for iface in self.getChildren(): + iface._create() + self.element.action("prepare") + self.element.action("") + self.setState(ST_PREPARED, True) + + def upcast(self): return self diff --git a/backend/tomato/host.py b/backend/tomato/host.py index f8540efa2..658284cc3 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -23,6 +23,7 @@ from lib.error import TransportError, InternalError, UserError, Error from .lib import anyjson as json from auth import Flags +from .elements import Element from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys @@ -1008,6 +1009,64 @@ def create(name, site, attrs=None): return host +def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): + if not sitePrefs: sitePrefs = {} + if not hostPrefs: hostPrefs = {} + if not networkKinds: networkKinds = [] + if not connectionTypes: connectionTypes = [] + if not elementTypes: elementTypes = [] + pref = 0.0 + pref -= host.componentErrors * 25 # discourage hosts with previous errors + pref -= host.getLoad() * 100 # up to -100 points for load + if host in hostPrefs: + pref += hostPrefs[host] + if host.site in sitePrefs: + pref += sitePrefs[host.site] + return pref + +def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None): + if not sitePrefs: sitePrefs = {} + if not hostPrefs: hostPrefs = {} + if not networkKinds: networkKinds = [] + if not connectionTypes: connectionTypes = [] + if not elementTypes: elementTypes = [] + all_ = Host.getAll(site=site) if site else Host.getAll() + hosts = [] + for host in all_: + if host.problems(): + continue + if set(elementTypes) - set(host.elementTypes.keys()): + continue + if set(connectionTypes) - set(host.connectionTypes.keys()): + continue + if set(networkKinds) - set(host.getNetworkKinds()): + continue + hosts.append(host) + UserError.check(hosts, code=UserError.INVALID_CONFIGURATION, message="No hosts found for requirements") + prefs = dict([(h, getHostValue(h, site, elementTypes, connectionTypes, networkKinds, hostPrefs, sitePrefs)) for h in hosts]) + hosts.sort(key=lambda h: prefs[h], reverse=True) + return hosts[0], prefs[hosts[0]] + +def reallocate(): + + #needs to be redifined at a better place + THRESHOLD = 20 + #Walk through all elements and think about reallocating them. + for el in Element: + if el.activ: + continue + hostPref, sitePref = el.getLocationPrefs() + prev,prevScor = getHostValue(el.host,el.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) + best,bestScor = getHostValue(el.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) + + #Compare best host with preference host and migrate to better one if possible + if prev != best: + if bestScor - prevScor > THRESHOLD: + if el.canMigrate(): + el.migrate(best) + + + def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): # STEP 1: limit host choices to what is possible if not sitePrefs: sitePrefs = {} From d1571495ab04a909b91c6a9c7e1601a6d7fd8b37 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 12:36:53 +0200 Subject: [PATCH 002/132] created a function to migrate an element from one host to another. Added an unaccessary api call --- backend/tomato/api/elements.py | 23 ++++++++++++++++ backend/tomato/elements/generic.py | 44 ++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/backend/tomato/api/elements.py b/backend/tomato/api/elements.py index 86fa539a8..fc4e8ddf4 100644 --- a/backend/tomato/api/elements.py +++ b/backend/tomato/api/elements.py @@ -299,6 +299,29 @@ def element_usage(id): #@ReservedAssignment el = _getElement(id) return el.totalUsage.info() +def element_migrate(id,hst): #@ReservedAssignment + """ + Migrates an element to a new host + + + Parameter *id*: + The parameter *id* identifies the element by giving its unique id. + + Parameter *host*: + The parameter *host* identifies the new host by giving its unique id. + + Return value: + Returns the host name to confirm the + + """ + from host import _getHost + + el = _getElement(id) + ho = _getHost(hst) + el.migrate(ho) + return el.info() + + from .. import elements, currentUser from topology import _getTopology from ..lib.error import UserError diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index bd5b3aa6d..2ccca00f8 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -14,7 +14,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see - +import rpc, urllib from django.db import models from .. import elements, resources, host from ..resources import profile as r_profile, template as r_template @@ -245,12 +245,13 @@ def checkMigrate(self): return False def action_migrate(self,host): - if self.checkMigrate(self): + if self.checkMigrate(self) and self.element.host.name != host: UserError.check(host, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) - + #Download template. Receive download_grant from template and save it to a tempfile? + urllib.urlretrieve(self.element.action("download_grant"), "/tmp_image.tar.gz") attrs = self._remoteAttrs() attrs.update({ @@ -262,8 +263,9 @@ def action_migrate(self,host): new_el = host.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) - #Neues element soll template uploaden (action_grant_upload) - #Neues element soll template nutzen (action_grant_upload_use) + upload(new_el.action("upload_grant)"),"/tmp_image.tar.gz") + new_el.action("upload_use") + #Kill old element on old host self.element.action("destroy") @@ -278,6 +280,8 @@ def action_migrate(self,host): self.setState(ST_PREPARED, True) + + def upcast(self): return self @@ -343,7 +347,35 @@ def readyToConnect(self): def upcast(self): return self - +def upload (url, file, name="upload"): + import httplib, urlparse, os + parts = urlparse.urlparse(url) + conn = httplib.HTTPConnection(parts.netloc) + req = parts.path + if parts.query: + req += "?" + parts.query + conn.putrequest("POST", req) + filename = os.path.basename(file) + filesize = os.path.getsize(file) + BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$' + CRLF = '\r\n' + prepend = "--" + BOUNDARY + CRLF + 'Content-Disposition: form-data; name="%s"; filename="%s"' % ( + name, filename) + CRLF + "Content-Type: application/data" + CRLF + CRLF + append = CRLF + "--" + BOUNDARY + "--" + CRLF + CRLF + conn.putheader("Content-Length", len(prepend) + filesize + len(append)) + conn.putheader("Content-Type", 'multipart/form-data; boundary=%s' % BOUNDARY) + conn.endheaders() + conn.send(prepend) + fd = open(file, "r") + data = fd.read(8192) + while data: + conn.send(data) + data = fd.read(8192) + fd.close() + conn.send(append) + resps = conn.getresponse() + data = resps.read() + class ConnectingElement: def getLocationData(self, maxDepth=3): """ From 5cb20fe3ac26dcd38fcd214d7663218d2b94152c Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 12:56:39 +0200 Subject: [PATCH 003/132] Removed unnecessary import --- backend/tomato/host.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 658284cc3..f4317b8f8 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -23,7 +23,6 @@ from lib.error import TransportError, InternalError, UserError, Error from .lib import anyjson as json from auth import Flags -from .elements import Element from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys From 12807440a034e87f0a89d0aca771defcc052d335 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 13:41:16 +0200 Subject: [PATCH 004/132] bugfix --- backend/tomato/elements/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/tomato/elements/__init__.py b/backend/tomato/elements/__init__.py index 44035b5d3..6518ec0ad 100644 --- a/backend/tomato/elements/__init__.py +++ b/backend/tomato/elements/__init__.py @@ -27,6 +27,7 @@ from ..lib.decorators import * from ..lib.cache import cached #@UnresolvedImport from ..lib.error import UserError, InternalError +from builtins import True TYPES = {} REMOVE_ACTION = "(remove)" @@ -468,6 +469,8 @@ def fetchInfo(self): mel = self.mainElement() if mel: mel.updateInfo() + + def updateUsage(self): self.totalUsage.updateFrom([el.usageStatistics for el in self.getHostElements()] From 83387f001108e2b65f298a3c511b83cf0e15bb3c Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 13:45:14 +0200 Subject: [PATCH 005/132] bugfix --- backend/tomato/elements/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/tomato/elements/__init__.py b/backend/tomato/elements/__init__.py index 6518ec0ad..62433d0e4 100644 --- a/backend/tomato/elements/__init__.py +++ b/backend/tomato/elements/__init__.py @@ -27,7 +27,6 @@ from ..lib.decorators import * from ..lib.cache import cached #@UnresolvedImport from ..lib.error import UserError, InternalError -from builtins import True TYPES = {} REMOVE_ACTION = "(remove)" From 5bcead1b5e5fee34d75f095cf7a9f9e40653e186 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 13:46:05 +0200 Subject: [PATCH 006/132] bugfix --- backend/tomato/elements/generic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 2ccca00f8..5127bc76d 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -14,14 +14,14 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see -import rpc, urllib from django.db import models from .. import elements, resources, host from ..resources import profile as r_profile, template as r_template from ..lib.attributes import Attr, attribute #@UnresolvedImport -from ..lib import attributes #@UnresolvedImport +from ..lib import attributes,rpc #@UnresolvedImport from ..lib.error import UserError, InternalError import time +import urllib ST_CREATED = "created" ST_PREPARED = "prepared" From c8521a52368fccbdcf48e2adfb0a46fbbeec1d9f Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 14:01:20 +0200 Subject: [PATCH 007/132] bugfix --- backend/tomato/api/elements.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/api/elements.py b/backend/tomato/api/elements.py index fc4e8ddf4..5334d9be6 100644 --- a/backend/tomato/api/elements.py +++ b/backend/tomato/api/elements.py @@ -318,7 +318,7 @@ def element_migrate(id,hst): #@ReservedAssignment el = _getElement(id) ho = _getHost(hst) - el.migrate(ho) + el.action_migrate(ho) return el.info() From 7d094cff261bad7694b37be02f3dcf5013529c4a Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 14:03:07 +0200 Subject: [PATCH 008/132] bugfix --- backend/tomato/elements/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 5127bc76d..a040b3169 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -245,7 +245,7 @@ def checkMigrate(self): return False def action_migrate(self,host): - if self.checkMigrate(self) and self.element.host.name != host: + if self.checkMigrate() and self.element.host.name != host: UserError.check(host, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) From 86a577cf9e3810d660704de356a0d8ddf1cabdc0 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 14:10:30 +0200 Subject: [PATCH 009/132] bugfix --- backend/tomato/elements/generic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index a040b3169..6a7b2710c 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -251,7 +251,7 @@ def action_migrate(self,host): #Download template. Receive download_grant from template and save it to a tempfile? - urllib.urlretrieve(self.element.action("download_grant"), "/tmp_image.tar.gz") + urllib.urlretrieve(self.element.action("download_grant"), "tmp_image.tar.gz") attrs = self._remoteAttrs() attrs.update({ @@ -263,7 +263,7 @@ def action_migrate(self,host): new_el = host.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) - upload(new_el.action("upload_grant)"),"/tmp_image.tar.gz") + upload(new_el.action("upload_grant)"),"tmp_image.tar.gz") new_el.action("upload_use") From ab95a63ecb77ba3c973ad49cf47c6f352ab41afa Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 14:36:14 +0200 Subject: [PATCH 010/132] bugfix --- backend/tomato/elements/generic.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 6a7b2710c..1770b8a94 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -250,23 +250,31 @@ def action_migrate(self,host): UserError.check(host, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) + print('Host gefunden \n') #Download template. Receive download_grant from template and save it to a tempfile? urllib.urlretrieve(self.element.action("download_grant"), "tmp_image.tar.gz") + + print('Download erfolgreich \n') + attrs = self._remoteAttrs() attrs.update({ "template": self._template().name, }) attrs.update(self._profileAttrs()) + print('Erzeuge Element auf neuem host \n') + #Create identical element on new host new_el = host.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) + print('Lade template hoch \n') upload(new_el.action("upload_grant)"),"tmp_image.tar.gz") new_el.action("upload_use") + print('Zerstöre altes Element \n') #Kill old element on old host self.element.action("destroy") From ea407d5452ee39edeb79256e9c385580d00bbfe2 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 14:46:38 +0200 Subject: [PATCH 011/132] bugfix --- backend/tomato/elements/generic.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 1770b8a94..aee2bb03f 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -251,8 +251,10 @@ def action_migrate(self,host): print('Host gefunden \n') + + #Download template. Receive download_grant from template and save it to a tempfile? - urllib.urlretrieve(self.element.action("download_grant"), "tmp_image.tar.gz") + urllib.urlretrieve(self.host.hostElement.action("download_grant"), "tmp_image.tar.gz") print('Download erfolgreich \n') From 5522995aacc7bc0795d01d650fde6fce8d25bcdb Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 14:47:58 +0200 Subject: [PATCH 012/132] bugfix --- backend/tomato/elements/generic.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index aee2bb03f..431741e71 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -252,9 +252,11 @@ def action_migrate(self,host): print('Host gefunden \n') + tmp = self.host.hostElement.action("download_grant") + print(tmp) #Download template. Receive download_grant from template and save it to a tempfile? - urllib.urlretrieve(self.host.hostElement.action("download_grant"), "tmp_image.tar.gz") + urllib.urlretrieve(tmp, "tmp_image.tar.gz") print('Download erfolgreich \n') From 7cb90b92a4a13e7c114566d894c64d9c43bb1d7f Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 14:53:11 +0200 Subject: [PATCH 013/132] bugfix --- backend/tomato/elements/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 431741e71..5f8cbc151 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -252,7 +252,7 @@ def action_migrate(self,host): print('Host gefunden \n') - tmp = self.host.hostElement.action("download_grant") + tmp = host.host.HostElement.action("download_grant") print(tmp) #Download template. Receive download_grant from template and save it to a tempfile? From a8350dcac7de6d5bc85d3cf1790c273be1474fba Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 14:54:33 +0200 Subject: [PATCH 014/132] bugfix --- backend/tomato/elements/generic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 5f8cbc151..ab267b059 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -252,7 +252,8 @@ def action_migrate(self,host): print('Host gefunden \n') - tmp = host.host.HostElement.action("download_grant") + + tmp = host.HostElement.action("download_grant") print(tmp) #Download template. Receive download_grant from template and save it to a tempfile? From c879beaf0e33771574259b5643a76ef41d4c3ffd Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 14:55:58 +0200 Subject: [PATCH 015/132] bugfix --- backend/tomato/elements/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index ab267b059..799a6487f 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -253,7 +253,7 @@ def action_migrate(self,host): print('Host gefunden \n') - tmp = host.HostElement.action("download_grant") + tmp = self.host.HostElement.action("download_grant") print(tmp) #Download template. Receive download_grant from template and save it to a tempfile? From eda963036988f1cb24c0f1860c84b254313cb046 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 15:12:49 +0200 Subject: [PATCH 016/132] bugfix --- backend/tomato/elements/generic.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 799a6487f..73c16f03e 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -244,16 +244,16 @@ def checkMigrate(self): return True return False - def action_migrate(self,host): + def action_migrate(self,hst): if self.checkMigrate() and self.element.host.name != host: - UserError.check(host, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) + UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) print('Host gefunden \n') - tmp = self.host.HostElement.action("download_grant") + tmp = host.HostElement.action("download_grant") print(tmp) #Download template. Receive download_grant from template and save it to a tempfile? @@ -271,7 +271,7 @@ def action_migrate(self,host): print('Erzeuge Element auf neuem host \n') #Create identical element on new host - new_el = host.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) + new_el = hst.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) print('Lade template hoch \n') From 2491f5b6c766be88dbb83578a7de81e91cf7f086 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 11 May 2015 15:14:08 +0200 Subject: [PATCH 017/132] bugfix --- backend/tomato/elements/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 73c16f03e..942be094b 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -253,7 +253,7 @@ def action_migrate(self,hst): print('Host gefunden \n') - tmp = host.HostElement.action("download_grant") + tmp = host.HostElement.action(host.HostElement,"download_grant") print(tmp) #Download template. Receive download_grant from template and save it to a tempfile? From 3a0fa1be012794951cfe76fba6cf6480a066524a Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 10:51:23 +0200 Subject: [PATCH 018/132] bugfix --- backend/tomato/elements/generic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 942be094b..52016a660 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -245,7 +245,7 @@ def checkMigrate(self): return False def action_migrate(self,hst): - if self.checkMigrate() and self.element.host.name != host: + if self.checkMigrate() and self.element.host.name != hst: UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) @@ -253,7 +253,7 @@ def action_migrate(self,hst): print('Host gefunden \n') - tmp = host.HostElement.action(host.HostElement,"download_grant") + tmp = self.action("download_grant") print(tmp) #Download template. Receive download_grant from template and save it to a tempfile? From fe3f37cb53b4788d2ef2e4f815b3fbc38621046a Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 11:35:07 +0200 Subject: [PATCH 019/132] bugfix --- backend/tomato/elements/generic.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 52016a660..ad62d034d 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -253,11 +253,11 @@ def action_migrate(self,hst): print('Host gefunden \n') - tmp = self.action("download_grant") + #tmp = self.action("download_grant") - print(tmp) + #print(tmp) #Download template. Receive download_grant from template and save it to a tempfile? - urllib.urlretrieve(tmp, "tmp_image.tar.gz") + urllib.urlretrieve(host.grantUrl(self.action("download_grant"), "download"), "tmp_image.tar.gz") print('Download erfolgreich \n') From 4e02edc9526fec5ea6e199c8b8be2077befc9d12 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 11:36:53 +0200 Subject: [PATCH 020/132] bugfix --- backend/tomato/elements/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index ad62d034d..9cbd39212 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -257,7 +257,7 @@ def action_migrate(self,hst): #print(tmp) #Download template. Receive download_grant from template and save it to a tempfile? - urllib.urlretrieve(host.grantUrl(self.action("download_grant"), "download"), "tmp_image.tar.gz") + urllib.urlretrieve(self.element.host.grantUrl(self.action("download_grant"), "download"), "tmp_image.tar.gz") print('Download erfolgreich \n') From 4f531df21537ad41a5be45cc6ad8a2bd8d76f3d6 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 11:38:22 +0200 Subject: [PATCH 021/132] bugfix --- backend/tomato/elements/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 9cbd39212..728654e8c 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -275,7 +275,7 @@ def action_migrate(self,hst): print('Lade template hoch \n') - upload(new_el.action("upload_grant)"),"tmp_image.tar.gz") + upload(new_el.action("upload_grant"),"tmp_image.tar.gz") new_el.action("upload_use") From b3a471c55bfa0431bf99be48a5a44ee4d28e019b Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 11:43:52 +0200 Subject: [PATCH 022/132] bugfix --- backend/tomato/elements/generic.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 728654e8c..e4771386b 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -273,10 +273,7 @@ def action_migrate(self,hst): #Create identical element on new host new_el = hst.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) - print('Lade template hoch \n') - - upload(new_el.action("upload_grant"),"tmp_image.tar.gz") - new_el.action("upload_use") + print('Zerstöre altes Element \n') @@ -289,9 +286,14 @@ def action_migrate(self,hst): for iface in self.getChildren(): iface._create() self.element.action("prepare") - self.element.action("") + self.setState(ST_PREPARED, True) + print('Lade template hoch \n') + + upload(new_el.action("upload_grant"),"tmp_image.tar.gz") + new_el.action("upload_use") + From b5899bef8e52485944dd2720ad6d162acfe0a5a8 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 12:51:57 +0200 Subject: [PATCH 023/132] bugfix --- backend/tomato/elements/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index e4771386b..5a2fd64c4 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -291,7 +291,7 @@ def action_migrate(self,hst): print('Lade template hoch \n') - upload(new_el.action("upload_grant"),"tmp_image.tar.gz") + upload(hst.grantUrl(new_el.action("upload_grant"),"upload"),"tmp_image.tar.gz") new_el.action("upload_use") From f75875e949aa2cf8e13446a185f5f337e2126549 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 13:32:50 +0200 Subject: [PATCH 024/132] Added the migrate and checkMigrate function to every elementtyp. --- backend/tomato/elements/external_network.py | 25 ++++++++++++++++++++- backend/tomato/elements/generic.py | 23 ++++--------------- backend/tomato/elements/repy.py | 5 +++++ backend/tomato/elements/tinc.py | 23 +++++++++++++++++++ backend/tomato/elements/udp.py | 18 +++++++++++++++ 5 files changed, 74 insertions(+), 20 deletions(-) diff --git a/backend/tomato/elements/external_network.py b/backend/tomato/elements/external_network.py index ee53f4e8a..505d6c7a8 100644 --- a/backend/tomato/elements/external_network.py +++ b/backend/tomato/elements/external_network.py @@ -149,7 +149,7 @@ def init(self, *args, **kwargs): def mainElement(self): return self.element - def modify_name(self, val): + def modify_name(self, val):_host = host.select(elementTypes=["external_network"], networkKinds=[kind], hostPrefs=hPref, sitePrefs=sPref) self.name = val def modify_kind(self, val): @@ -192,6 +192,29 @@ def action_stop(self): self.element = None self.setState(ST_CREATED, True) + def checkMigrate(self): + #We only migrate if the external network is already started, otherwise we don't have to migrate + if self.state in [ST_STARTED]: + return True + return False + + def action_migrate(self,hst): + if checkMigrate(): + kind = self.getParent().network.kind if self.parent and self.getParent().samenet else self.kind + + UserError.check(host, code=UserError.NO_RESOURCES, message="No matching host found for element", + data={"type": self.TYPE}) + if self.parent and self.getParent().samenet: + self.network = r_network.getInstance(hst, self.getParent().network.kind) + else: + self.network = r_network.getInstance(hst, self.kind) + attrs = {"network": self.network.network.kind} + self.element.action("destroy") + self.element = hst.createElement("external_network", parent=None, attrs=attrs, ownerElement=self) + self.setState(ST_STARTED) + self.triggerConnectionStart() + + def readyToConnect(self): return bool(self.element) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 5a2fd64c4..9163dc7aa 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -239,8 +239,8 @@ def after_upload_use(self): self.save() def checkMigrate(self): - #We only migrate if element is prepared - if self.state in ["prepared"]: + #We only migrate if the element is prepared + if self.state in [ST_PREPARED]: return True return False @@ -249,34 +249,21 @@ def action_migrate(self,hst): UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) - - print('Host gefunden \n') - - - #tmp = self.action("download_grant") - - #print(tmp) + #Download template. Receive download_grant from template and save it to a tempfile? urllib.urlretrieve(self.element.host.grantUrl(self.action("download_grant"), "download"), "tmp_image.tar.gz") - print('Download erfolgreich \n') - attrs = self._remoteAttrs() attrs.update({ "template": self._template().name, }) attrs.update(self._profileAttrs()) - print('Erzeuge Element auf neuem host \n') #Create identical element on new host new_el = hst.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) - - - - - print('Zerstöre altes Element \n') + #Kill old element on old host self.element.action("destroy") @@ -289,8 +276,6 @@ def action_migrate(self,hst): self.setState(ST_PREPARED, True) - print('Lade template hoch \n') - upload(hst.grantUrl(new_el.action("upload_grant"),"upload"),"tmp_image.tar.gz") new_el.action("upload_use") diff --git a/backend/tomato/elements/repy.py b/backend/tomato/elements/repy.py index 0283d0880..b0bcb61f7 100644 --- a/backend/tomato/elements/repy.py +++ b/backend/tomato/elements/repy.py @@ -58,6 +58,11 @@ def action_destroy(self): self.element = None self.setState(generic.ST_CREATED, True) + + #TODO: integrate migration function and additional migrate the repy log + def checkMigrate(self): + return False + class Repy_Interface(generic.VMInterface): TYPE = "repy_interface" diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 6a56a50db..1e5b98f40 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -225,6 +225,11 @@ def action_start(self): self._parallelChildActions(self._childsByState()[ST_PREPARED], "start") self.setState(ST_STARTED) + def action_migrate(self,hst): + self.setState(ST_CREATED) + self._parallelChildActions(self._childsByState()[ST_CREATED], "migrate",hst) + self.setState(ST_PREPARED) + def upcast(self): return self @@ -335,6 +340,24 @@ def action_stop(self): self.element.action("stop") self.setState(ST_PREPARED, True) + def checkMigrate(self): + if self.state in [ST_PREPARED]: + return True + return False + + def action_migrate(self,hst): + if self.checkMigrate(): + UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) + attrs = self._remoteAttrs() + attrs.update({ + "mode": self.mode, + "peers": self.peers, + }) + self.element.action("destroy") + self.element = hst.createElement(self.remoteType(), parent=None, attrs=attrs, ownerElement=self) + self.save() + self.setState(ST_PREPARED, True) + def upcast(self): return self diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index 0431d8be3..5e587c327 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -20,6 +20,7 @@ from ..lib.attributes import Attr #@UnresolvedImport from generic import ST_CREATED, ST_PREPARED, ST_STARTED from ..lib.error import UserError +from builtins import True class UDP_Endpoint(elements.Element): element = models.ForeignKey(host.HostElement, null=True, on_delete=models.SET_NULL) @@ -111,6 +112,23 @@ def action_stop(self): self.element.action("stop") self.setState(ST_PREPARED, True) + def checkMigrate(self): + if self.state in [ST_PREPARED]: + return True + return False + + def action_migrate(self,hst): + if self.checkMigrate(): + UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) + attrs = self._remoteAttrs() + attrs.update({ + "connect": self.connect, + }) + self.element.action("destroy") + self.element = hst.createElement(self.remoteType(), parent=None, attrs=attrs, ownerElement=self) + self.save() + self.setState(ST_PREPARED, True) + def upcast(self): return self From d79b597feed4e5d5946e8e7a8b4755bdd5d8dc45 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 13:35:10 +0200 Subject: [PATCH 025/132] bugfix --- backend/tomato/elements/external_network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/external_network.py b/backend/tomato/elements/external_network.py index 505d6c7a8..9e7146fc7 100644 --- a/backend/tomato/elements/external_network.py +++ b/backend/tomato/elements/external_network.py @@ -149,7 +149,7 @@ def init(self, *args, **kwargs): def mainElement(self): return self.element - def modify_name(self, val):_host = host.select(elementTypes=["external_network"], networkKinds=[kind], hostPrefs=hPref, sitePrefs=sPref) + def modify_name(self, val): self.name = val def modify_kind(self, val): From f8f97a8d5e85126436c84cb591ce2aa43c590dcc Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 13:42:12 +0200 Subject: [PATCH 026/132] bugfix --- backend/tomato/elements/udp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index 5e587c327..5e6e06e11 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -20,7 +20,7 @@ from ..lib.attributes import Attr #@UnresolvedImport from generic import ST_CREATED, ST_PREPARED, ST_STARTED from ..lib.error import UserError -from builtins import True + class UDP_Endpoint(elements.Element): element = models.ForeignKey(host.HostElement, null=True, on_delete=models.SET_NULL) From 7ad17300b65858e795eae96a9d338d59a29b1925 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 13:49:25 +0200 Subject: [PATCH 027/132] bugfix --- backend/tomato/elements/tinc.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 1e5b98f40..a9c6318c5 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -341,19 +341,20 @@ def action_stop(self): self.setState(ST_PREPARED, True) def checkMigrate(self): - if self.state in [ST_PREPARED]: + if self.state in [ST_STARTED]: return True return False def action_migrate(self,hst): if self.checkMigrate(): + self.element("stop") + self.element.action("destroy") UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) attrs = self._remoteAttrs() attrs.update({ "mode": self.mode, "peers": self.peers, }) - self.element.action("destroy") self.element = hst.createElement(self.remoteType(), parent=None, attrs=attrs, ownerElement=self) self.save() self.setState(ST_PREPARED, True) From 11395b6d8d84812045dcf11b6692bbf03ee602b7 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 13:54:13 +0200 Subject: [PATCH 028/132] bugfix --- backend/tomato/elements/tinc.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index a9c6318c5..c5cc2dd31 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -226,9 +226,8 @@ def action_start(self): self.setState(ST_STARTED) def action_migrate(self,hst): - self.setState(ST_CREATED) - self._parallelChildActions(self._childsByState()[ST_CREATED], "migrate",hst) - self.setState(ST_PREPARED) + self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",hst) + self._parallelChildActions(self._childsByState()[ST_STARTED], "migrate",hst) def upcast(self): return self @@ -341,7 +340,7 @@ def action_stop(self): self.setState(ST_PREPARED, True) def checkMigrate(self): - if self.state in [ST_STARTED]: + if self.state in [ST_PREPARED, ST_STARTED]: return True return False From 9c67dc24ed0bfe9b185b1d5b5ef049ae7a834f5b Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 13:57:16 +0200 Subject: [PATCH 029/132] bugfix --- backend/tomato/elements/tinc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index c5cc2dd31..94592f654 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -346,7 +346,8 @@ def checkMigrate(self): def action_migrate(self,hst): if self.checkMigrate(): - self.element("stop") + if self.state in [St_STARTED]: + self.element("stop") self.element.action("destroy") UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) attrs = self._remoteAttrs() From b953a0e487711f4e144861a7ec4a5a57e13579cb Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 14:00:02 +0200 Subject: [PATCH 030/132] bugfix --- backend/tomato/elements/external_network.py | 1 + backend/tomato/elements/generic.py | 1 + backend/tomato/elements/tinc.py | 1 + backend/tomato/elements/udp.py | 1 + 4 files changed, 4 insertions(+) diff --git a/backend/tomato/elements/external_network.py b/backend/tomato/elements/external_network.py index 9e7146fc7..50d1fe050 100644 --- a/backend/tomato/elements/external_network.py +++ b/backend/tomato/elements/external_network.py @@ -36,6 +36,7 @@ class External_Network(elements.generic.ConnectingElement, elements.Element): CUSTOM_ACTIONS = { "start": [ST_CREATED], "stop": [ST_STARTED], + "migrate": [ST_STARTED], elements.REMOVE_ACTION: [ST_CREATED], } CUSTOM_ATTRS = { diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 9163dc7aa..ac7a43346 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -47,6 +47,7 @@ class VMElement(elements.Element): "prepare": [ST_CREATED], "destroy": [ST_PREPARED], "change_template": [ST_CREATED, ST_PREPARED], + "migrate": [ST_PREPARED], elements.REMOVE_ACTION: [ST_CREATED], } CUSTOM_ATTRS = { diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 94592f654..5543ef18a 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -34,6 +34,7 @@ class Tinc_VPN(elements.generic.ConnectingElement, elements.Element): "destroy": [ST_PREPARED], "start": [ST_PREPARED], "stop": [ST_STARTED], + "migrate": [ST_PREPARED,ST_STARTED], elements.REMOVE_ACTION: [ST_CREATED], } CUSTOM_ATTRS = { diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index 5e6e06e11..e96da3001 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -33,6 +33,7 @@ class UDP_Endpoint(elements.Element): "stop": [ST_STARTED], "prepare": [ST_CREATED], "destroy": [ST_PREPARED], + "migrate": [ST_PREPARED,ST_STARTED], elements.REMOVE_ACTION: [ST_CREATED], } CUSTOM_ATTRS = { From 5a6a5c96ac5f94e54b5ebecba81c21c2fede4e8d Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 14:05:24 +0200 Subject: [PATCH 031/132] bugfix --- backend/tomato/elements/tinc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 5543ef18a..7c84c8c40 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -254,6 +254,7 @@ class Tinc_Endpoint(elements.generic.ConnectingElement, elements.Element): "stop": [ST_STARTED], "prepare": [ST_CREATED], "destroy": [ST_PREPARED], + "migrate": [ST_PREPARED,ST_STARTED], elements.REMOVE_ACTION: [ST_CREATED], } CUSTOM_ATTRS = { From a0134e920584bc6ea526c0078f158a78d2c243e2 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 14:07:48 +0200 Subject: [PATCH 032/132] bugfix --- backend/tomato/elements/tinc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 7c84c8c40..a82db1657 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -227,8 +227,8 @@ def action_start(self): self.setState(ST_STARTED) def action_migrate(self,hst): - self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",hst) - self._parallelChildActions(self._childsByState()[ST_STARTED], "migrate",hst) + self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",{'hst':hst}) + self._parallelChildActions(self._childsByState()[ST_STARTED], "migrate",{'hst':hst}) def upcast(self): return self From f01b141e61bcebce23d86f2456549e0209de842a Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 14:24:56 +0200 Subject: [PATCH 033/132] bugfix --- backend/tomato/elements/tinc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index a82db1657..7c84c8c40 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -227,8 +227,8 @@ def action_start(self): self.setState(ST_STARTED) def action_migrate(self,hst): - self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",{'hst':hst}) - self._parallelChildActions(self._childsByState()[ST_STARTED], "migrate",{'hst':hst}) + self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",hst) + self._parallelChildActions(self._childsByState()[ST_STARTED], "migrate",hst) def upcast(self): return self From 53fbbcc97c3df37b925eee11c49072e3947f6fc9 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 14:25:53 +0200 Subject: [PATCH 034/132] bugfix --- backend/tomato/elements/tinc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 7c84c8c40..36e550404 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -348,7 +348,7 @@ def checkMigrate(self): def action_migrate(self,hst): if self.checkMigrate(): - if self.state in [St_STARTED]: + if self.state in [ST_STARTED]: self.element("stop") self.element.action("destroy") UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) From 9788101ad0cd8f987e2bd19058cadefb74994de8 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 14:28:20 +0200 Subject: [PATCH 035/132] bugfix --- backend/tomato/elements/tinc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 36e550404..335ba61ec 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -349,7 +349,7 @@ def checkMigrate(self): def action_migrate(self,hst): if self.checkMigrate(): if self.state in [ST_STARTED]: - self.element("stop") + self.element.action("stop") self.element.action("destroy") UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) attrs = self._remoteAttrs() From 7e5491fea1e39464a5a8bbdfd7c19a87d95cc9a4 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 14:29:42 +0200 Subject: [PATCH 036/132] bugfix --- backend/tomato/elements/tinc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 335ba61ec..da57b2d48 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -349,8 +349,8 @@ def checkMigrate(self): def action_migrate(self,hst): if self.checkMigrate(): if self.state in [ST_STARTED]: - self.element.action("stop") - self.element.action("destroy") + self.action("stop") + self.action("destroy") UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) attrs = self._remoteAttrs() attrs.update({ From baa3c3a552b2edffd349bf21485f192c2f4e18dd Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 14:50:20 +0200 Subject: [PATCH 037/132] bugfix --- backend/tomato/elements/external_network.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/elements/external_network.py b/backend/tomato/elements/external_network.py index 50d1fe050..49ca8421b 100644 --- a/backend/tomato/elements/external_network.py +++ b/backend/tomato/elements/external_network.py @@ -200,10 +200,10 @@ def checkMigrate(self): return False def action_migrate(self,hst): - if checkMigrate(): + if self.checkMigrate(): kind = self.getParent().network.kind if self.parent and self.getParent().samenet else self.kind - UserError.check(host, code=UserError.NO_RESOURCES, message="No matching host found for element", + UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) if self.parent and self.getParent().samenet: self.network = r_network.getInstance(hst, self.getParent().network.kind) From c59ec4061082bf192c191ddc8a2764ffa0aae6b4 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 15:22:12 +0200 Subject: [PATCH 038/132] Created a new allocation function as preparation for a new dynamic ressource allokation algorithm --- backend/tomato/host.py | 59 ++++++------------------------------------ 1 file changed, 8 insertions(+), 51 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index f4317b8f8..4ce31ee6f 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -24,6 +24,7 @@ from .lib import anyjson as json from auth import Flags from dumpmanager import DumpSource +import elements import time, hashlib, threading, datetime, zlib, base64, sys class RemoteWrapper: @@ -1036,7 +1037,7 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= continue if set(elementTypes) - set(host.elementTypes.keys()): continue - if set(connectionTypes) - set(host.connectionTypes.keys()): + if set(connectionTypes) - set(host.connectio .keys()): continue if set(networkKinds) - set(host.getNetworkKinds()): continue @@ -1047,11 +1048,10 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= return hosts[0], prefs[hosts[0]] def reallocate(): - - #needs to be redifined at a better place + #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. - for el in Element: + for el in elements.getAll(): if el.activ: continue hostPref, sitePref = el.getLocationPrefs() @@ -1067,58 +1067,15 @@ def reallocate(): def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): - # STEP 1: limit host choices to what is possible - if not sitePrefs: sitePrefs = {} - if not hostPrefs: hostPrefs = {} - if not networkKinds: networkKinds = [] - if not connectionTypes: connectionTypes = [] - if not elementTypes: elementTypes = [] - all_ = getAll(site=site) if site else getAll() - hosts = [] - for host in all_: - if host.problems(): - continue - if set(elementTypes) - set(host.elementTypes.keys()): - continue - if set(connectionTypes) - set(host.connectionTypes.keys()): - continue - if set(networkKinds) - set(host.getNetworkKinds()): - continue - hosts.append(host) - UserError.check(hosts, code=UserError.INVALID_CONFIGURATION, message="No hosts found for requirements") - # any host in hosts can handle the request - prefs = dict([(h, 0.0) for h in hosts]) - # STEP 2: calculate preferences based on host load - els = 0.0 - cons = 0.0 - for h in hosts: - prefs[h] -= h.componentErrors * 25 # discourage hosts with previous errors - prefs[h] -= h.getLoad() * 100 # up to -100 points for load - els += h.elements.count() - cons += h.connections.count() - avgEls = els / len(hosts) - avgCons = cons / len(hosts) - for h in hosts: - # between -30 and +30 points for element/connection over-/under-population - if avgEls: - prefs[h] -= max(-20.0, min(10.0 * (h.elements.count() - avgEls) / avgEls, 20.0)) - if avgCons: - prefs[h] -= max(-10.0, min(10.0 * (h.connections.count() - avgCons) / avgCons, 10.0)) - # STEP 3: calculate preferences based on host location - for h in hosts: - if h in hostPrefs: - prefs[h] += hostPrefs[h] - if h.site in sitePrefs: - prefs[h] += sitePrefs[h.site] - #STEP 4: select the best host - hosts.sort(key=lambda h: prefs[h], reverse=True) - logging.logMessage("select", category="host", result=hosts[0].name, + + host, prefs = getBestHost(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) + logging.logMessage("select", category="host", host.name, prefs=dict([(k.name, v) for k, v in prefs.iteritems()]), site=site.name if site else None, element_types=elementTypes, connection_types=connectionTypes, network_types=networkKinds, host_prefs=dict([(k.name, v) for k, v in hostPrefs.iteritems()]), site_prefs=dict([(k.name, v) for k, v in sitePrefs.iteritems()])) - return hosts[0] + return host @cached(timeout=3600, autoupdate=True) From 55efd91903ff86ad770658eb3ec8f9f49d11ca4d Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 15:25:02 +0200 Subject: [PATCH 039/132] bugfix --- backend/tomato/host.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 4ce31ee6f..ad4220562 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1069,7 +1069,8 @@ def reallocate(): def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): host, prefs = getBestHost(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) - logging.logMessage("select", category="host", host.name, + + logging.logMessage("select", category="host", result=host.name, prefs=dict([(k.name, v) for k, v in prefs.iteritems()]), site=site.name if site else None, element_types=elementTypes, connection_types=connectionTypes, network_types=networkKinds, From 79322afb482b1462755168bfa6e57411c6ba6153 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 15:27:11 +0200 Subject: [PATCH 040/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index ad4220562..6489b9075 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -24,7 +24,6 @@ from .lib import anyjson as json from auth import Flags from dumpmanager import DumpSource -import elements import time, hashlib, threading, datetime, zlib, base64, sys class RemoteWrapper: @@ -1048,6 +1047,7 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= return hosts[0], prefs[hosts[0]] def reallocate(): + import elements #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. From 708af4439b987ff970fc1ea9b8bc00a14be31bed Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 15:30:07 +0200 Subject: [PATCH 041/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 6489b9075..335ad963c 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1052,7 +1052,7 @@ def reallocate(): THRESHOLD = 20 #Walk through all elements and think about reallocating them. for el in elements.getAll(): - if el.activ: + if el.state in ["started"]: continue hostPref, sitePref = el.getLocationPrefs() prev,prevScor = getHostValue(el.host,el.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) From 94d3b4cf40152762fc65b6112cfa0d78740b4df7 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 15:32:34 +0200 Subject: [PATCH 042/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 335ad963c..f1f580884 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1029,7 +1029,7 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= if not networkKinds: networkKinds = [] if not connectionTypes: connectionTypes = [] if not elementTypes: elementTypes = [] - all_ = Host.getAll(site=site) if site else Host.getAll() + all_ = getAll(site=site) if site else getAll() hosts = [] for host in all_: if host.problems(): From cb09a640a5a055aa250ecaee9864464a6c2b69b8 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 15:33:51 +0200 Subject: [PATCH 043/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index f1f580884..161495177 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1036,7 +1036,7 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= continue if set(elementTypes) - set(host.elementTypes.keys()): continue - if set(connectionTypes) - set(host.connectio .keys()): + if set(connectionTypes) - set(host.connectionTypes.keys()): continue if set(networkKinds) - set(host.getNetworkKinds()): continue From 334e748deac88f559988a1ecc2c7757dd5c513bd Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 15:42:34 +0200 Subject: [PATCH 044/132] bugfix --- backend/tomato/host.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 161495177..ce0908d4e 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1023,7 +1023,7 @@ def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, netwo pref += sitePrefs[host.site] return pref -def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None): +def getHostList(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None): if not sitePrefs: sitePrefs = {} if not hostPrefs: hostPrefs = {} if not networkKinds: networkKinds = [] @@ -1043,6 +1043,10 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= hosts.append(host) UserError.check(hosts, code=UserError.INVALID_CONFIGURATION, message="No hosts found for requirements") prefs = dict([(h, getHostValue(h, site, elementTypes, connectionTypes, networkKinds, hostPrefs, sitePrefs)) for h in hosts]) + return hosts, prefs + +def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None): + hosts, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) hosts.sort(key=lambda h: prefs[h], reverse=True) return hosts[0], prefs[hosts[0]] @@ -1068,8 +1072,9 @@ def reallocate(): def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): - host, prefs = getBestHost(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) - + host, pref = getBestHost(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) + hosts, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) + logging.logMessage("select", category="host", result=host.name, prefs=dict([(k.name, v) for k, v in prefs.iteritems()]), site=site.name if site else None, element_types=elementTypes, connection_types=connectionTypes, From 486aa73b2c1fdd3d321833c701a45aac0b11399b Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 15:48:28 +0200 Subject: [PATCH 045/132] bugfix --- backend/tomato/host.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index ce0908d4e..02af3d367 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1071,6 +1071,11 @@ def reallocate(): def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): + if not sitePrefs: sitePrefs = {} + if not hostPrefs: hostPrefs = {} + if not networkKinds: networkKinds = [] + if not connectionTypes: connectionTypes = [] + if not elementTypes: elementTypes = [] host, pref = getBestHost(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) hosts, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) From 8a0000175b8e208f1f5b3edae30cbfd27785d193 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:01:23 +0200 Subject: [PATCH 046/132] added reallokation api call for tests --- backend/tomato/api/host.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/tomato/api/host.py b/backend/tomato/api/host.py index c455f7d79..2c52a4abf 100644 --- a/backend/tomato/api/host.py +++ b/backend/tomato/api/host.py @@ -178,6 +178,10 @@ def host_remove(name): h.remove() host_list.invalidate() +@checkauth +def host_reallokat(): + host.reallocate() + @checkauth def host_users(name): """ From ae150ed2f64941abf3bbdadc93a33ccd243e5461 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:03:47 +0200 Subject: [PATCH 047/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 02af3d367..79c851cd9 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1066,7 +1066,7 @@ def reallocate(): if prev != best: if bestScor - prevScor > THRESHOLD: if el.canMigrate(): - el.migrate(best) + el.action("migrate",best) From 62d2eb2325c63fc33100f4f45503c5e4220b263c Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:13:12 +0200 Subject: [PATCH 048/132] bugfix --- backend/tomato/host.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 79c851cd9..8c9a68e6d 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1056,16 +1056,16 @@ def reallocate(): THRESHOLD = 20 #Walk through all elements and think about reallocating them. for el in elements.getAll(): - if el.state in ["started"]: + if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() - prev,prevScor = getHostValue(el.host,el.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) + prev,prevScor = getHostValue(el.element.host,el.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) best,bestScor = getHostValue(el.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible if prev != best: if bestScor - prevScor > THRESHOLD: - if el.canMigrate(): + if el.checkMigrate(): el.action("migrate",best) From 83537e252e1c41b4c5f3377167faa11426732b61 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:21:16 +0200 Subject: [PATCH 049/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 8c9a68e6d..c2a0a0864 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1059,7 +1059,7 @@ def reallocate(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() - prev,prevScor = getHostValue(el.element.host,el.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) + prev,prevScor = getHostValue(el.element.host,el.attrs.host_info.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) best,bestScor = getHostValue(el.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible From bb60e5ac5acee924141392f61b23f370ccf397e6 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:23:26 +0200 Subject: [PATCH 050/132] bugfix --- backend/tomato/host.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index c2a0a0864..31fc5b2d9 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1059,8 +1059,8 @@ def reallocate(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() - prev,prevScor = getHostValue(el.element.host,el.attrs.host_info.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) - best,bestScor = getHostValue(el.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) + prev,prevScor = getHostValue(el.element.host,el.element.host.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) + best,bestScor = getHostValue(el.element.host.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible if prev != best: From 22b671c15b657a784cc36c8938ecbf94e39030e2 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:25:56 +0200 Subject: [PATCH 051/132] bugfix --- backend/tomato/host.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 31fc5b2d9..c4d00baa9 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1059,8 +1059,8 @@ def reallocate(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() - prev,prevScor = getHostValue(el.element.host,el.element.host.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) - best,bestScor = getHostValue(el.element.host.site,el.type,hostPrefs=hostPref,sitePrefs=sitePref) + prev,prevScor = getHostValue(host=el.element.host,site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) + best,bestScor = getBestHost(site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible if prev != best: From bf897c22f00b5344f0004ea03372058e461fe71b Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:39:25 +0200 Subject: [PATCH 052/132] bugfix --- backend/tomato/host.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index c4d00baa9..01a502eef 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1055,6 +1055,7 @@ def reallocate(): #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. + print(elements.getAll()) for el in elements.getAll(): if el.state in ["started","created"]: continue From e4fc7b370a0903587b6782813479f1954bdc0417 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:43:14 +0200 Subject: [PATCH 053/132] bugfix --- backend/tomato/host.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 01a502eef..d0a7b7e6b 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1055,8 +1055,8 @@ def reallocate(): #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. - print(elements.getAll()) - for el in elements.getAll(): + print(elements.getAll({})) + for el in elements.getAll({}): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() From 67364654d3eade6468e6e78f68ec021053b180ee Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:47:08 +0200 Subject: [PATCH 054/132] bugfix --- backend/tomato/host.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index d0a7b7e6b..01a502eef 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1055,8 +1055,8 @@ def reallocate(): #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. - print(elements.getAll({})) - for el in elements.getAll({}): + print(elements.getAll()) + for el in elements.getAll(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() From 98d66b09dec5712c667d4e0b86d487bbe9d0f702 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 12 May 2015 16:49:14 +0200 Subject: [PATCH 055/132] bugfix --- backend/tomato/host.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 01a502eef..7dccfe62e 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1055,8 +1055,7 @@ def reallocate(): #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. - print(elements.getAll()) - for el in elements.getAll(): + for el in list(elements.getAll()): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() From cb319a324a7a2367644227eaf14831713356f800 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 10:24:09 +0200 Subject: [PATCH 056/132] Bugfix --- backend/tomato/host.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 7dccfe62e..bc5d57a51 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1051,11 +1051,12 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= return hosts[0], prefs[hosts[0]] def reallocate(): - import elements + + from elements import * #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. - for el in list(elements.getAll()): + for el in elements.getAll(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() From de90005c239c66f0607c6077982cdbfa40b3b88d Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 10:37:56 +0200 Subject: [PATCH 057/132] Bugfix --- backend/tomato/host.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index bc5d57a51..a602fce52 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -25,6 +25,7 @@ from auth import Flags from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys +from tomato.elements import Element class RemoteWrapper: def __init__(self, url, host, *args, **kwargs): @@ -1052,11 +1053,12 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= def reallocate(): - from elements import * + from .elements import * #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. - for el in elements.getAll(): + + for el in Element.getAll(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() From 8a12e30dcde932f67b0f574c5270a0cba7a44383 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 10:41:37 +0200 Subject: [PATCH 058/132] Bugfix --- backend/tomato/host.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index a602fce52..cd416b97f 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -25,7 +25,6 @@ from auth import Flags from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys -from tomato.elements import Element class RemoteWrapper: def __init__(self, url, host, *args, **kwargs): @@ -1053,7 +1052,7 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= def reallocate(): - from .elements import * + from elements import * #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. From 8bab4dd6e4432e696e840c4252cd8b9309044253 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 10:44:44 +0200 Subject: [PATCH 059/132] Bugfix --- backend/tomato/host.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index cd416b97f..a7471b182 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1052,12 +1052,12 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= def reallocate(): - from elements import * + import elements #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. - for el in Element.getAll(): + for el in elements.getAll(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() From ca8eb8145161f7b25d48830bb1527426b6997979 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 10:47:22 +0200 Subject: [PATCH 060/132] Bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index a7471b182..01f8d4103 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1057,7 +1057,7 @@ def reallocate(): THRESHOLD = 20 #Walk through all elements and think about reallocating them. - for el in elements.getAll(): + for el in [elements.getAll()]: if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() From f85b7c5e342cc254ae7007a63021bb25a5440a45 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 10:49:24 +0200 Subject: [PATCH 061/132] Bugfix --- backend/tomato/host.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 01f8d4103..eeeab248f 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1056,12 +1056,17 @@ def reallocate(): #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. - - for el in [elements.getAll()]: + print("Beginn der Listeniteration") + element_liste = [elements.getAll()] + print(element_liste) + for el in element_liste: + print("Innerhalb der Liste") if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() + print("Aktuellen host bewerten") prev,prevScor = getHostValue(host=el.element.host,site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) + print("neuen host suchen") best,bestScor = getBestHost(site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible From 3c46741312b45532e62d4f14d49be7598a5cd5a2 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 10:56:50 +0200 Subject: [PATCH 062/132] Bugfix --- backend/tomato/host.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index eeeab248f..a5604d0f3 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1061,6 +1061,7 @@ def reallocate(): print(element_liste) for el in element_liste: print("Innerhalb der Liste") + print(el.state) if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() From 1d2e08e130dee8e92ed5ed16102e1bb20fd31d48 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 10:58:02 +0200 Subject: [PATCH 063/132] Bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index a5604d0f3..926f8344f 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1061,7 +1061,7 @@ def reallocate(): print(element_liste) for el in element_liste: print("Innerhalb der Liste") - print(el.state) + print(el) if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() From ade9eb417db1042e9f03e0151d5ee472c6bd4186 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 11:53:26 +0200 Subject: [PATCH 064/132] Bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 926f8344f..865d13c90 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1057,7 +1057,7 @@ def reallocate(): THRESHOLD = 20 #Walk through all elements and think about reallocating them. print("Beginn der Listeniteration") - element_liste = [elements.getAll()] + element_liste = []+elements.getAll() print(element_liste) for el in element_liste: print("Innerhalb der Liste") From 51e3a6a4bb63cbd804ea437a14cfeccef9a00567 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 11:55:44 +0200 Subject: [PATCH 065/132] Bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 865d13c90..707572df7 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1057,7 +1057,7 @@ def reallocate(): THRESHOLD = 20 #Walk through all elements and think about reallocating them. print("Beginn der Listeniteration") - element_liste = []+elements.getAll() + element_liste = list(elements.getAll()) print(element_liste) for el in element_liste: print("Innerhalb der Liste") From e3d436a1a0cf85bf8e65801b27b99008a537b6f5 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 12:05:39 +0200 Subject: [PATCH 066/132] Bugfix --- backend/tomato/host.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 707572df7..8c757185c 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1066,12 +1066,12 @@ def reallocate(): continue hostPref, sitePref = el.getLocationPrefs() print("Aktuellen host bewerten") - prev,prevScor = getHostValue(host=el.element.host,site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) + prevScor = getHostValue(host=el.element.host,site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) print("neuen host suchen") best,bestScor = getBestHost(site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible - if prev != best: + if el.element.host != best: if bestScor - prevScor > THRESHOLD: if el.checkMigrate(): el.action("migrate",best) From 7e5e389fd92dadcf1b3924e9bd00b82516b89bfe Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 12:11:26 +0200 Subject: [PATCH 067/132] Bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 8c757185c..47f9df65f 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1068,7 +1068,7 @@ def reallocate(): print("Aktuellen host bewerten") prevScor = getHostValue(host=el.element.host,site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) print("neuen host suchen") - best,bestScor = getBestHost(site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) + best,bestScor = getBestHost(site=el.element.host.site,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible if el.element.host != best: From 182657323a5232240facbf21b4fb32096dfed3ee Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 12:14:15 +0200 Subject: [PATCH 068/132] Bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 47f9df65f..78d912b16 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1074,7 +1074,7 @@ def reallocate(): if el.element.host != best: if bestScor - prevScor > THRESHOLD: if el.checkMigrate(): - el.action("migrate",best) + el.action("migrate",best.name) From 1cb6749fd28099f7d2b055038f9919423efa663a Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 12:16:28 +0200 Subject: [PATCH 069/132] Bugfix --- backend/tomato/host.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 78d912b16..82dd891bb 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1056,25 +1056,21 @@ def reallocate(): #needs to be redefined at a better place THRESHOLD = 20 #Walk through all elements and think about reallocating them. - print("Beginn der Listeniteration") - element_liste = list(elements.getAll()) - print(element_liste) - for el in element_liste: - print("Innerhalb der Liste") - print(el) + for el in list(elements.getAll()): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() - print("Aktuellen host bewerten") prevScor = getHostValue(host=el.element.host,site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) - print("neuen host suchen") best,bestScor = getBestHost(site=el.element.host.site,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible if el.element.host != best: + print("host != best") if bestScor - prevScor > THRESHOLD: + print("best besser als host") if el.checkMigrate(): - el.action("migrate",best.name) + print("migrate erlaubt") + el.action("migrate",best) From 34b7e23209cbb10f16986cf63176209a36fd9095 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 12:18:57 +0200 Subject: [PATCH 070/132] Bugfix --- backend/tomato/elements/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index ac7a43346..0a561cd75 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -246,7 +246,7 @@ def checkMigrate(self): return False def action_migrate(self,hst): - if self.checkMigrate() and self.element.host.name != hst: + if self.checkMigrate() and self.element.host.name != hst.name: UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) From e281527ec28afce91b5cf3621f977190c167ede5 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 12:21:14 +0200 Subject: [PATCH 071/132] Bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 82dd891bb..ebc58ad83 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1070,7 +1070,7 @@ def reallocate(): print("best besser als host") if el.checkMigrate(): print("migrate erlaubt") - el.action("migrate",best) + el.action_migrate(best) From a1f2b0ed332f071b44731bb0b8feda4ac65bdcaa Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 12:24:04 +0200 Subject: [PATCH 072/132] Bugfix --- backend/tomato/elements/generic.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 0a561cd75..c418a58d9 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -342,6 +342,9 @@ def _remove(self): self.element = None self.save() + def checkMigrate(self): + return False + def readyToConnect(self): return self.state == ST_STARTED From 27fd1fad55f6634c286643596324b8bb93b10169 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 12:30:27 +0200 Subject: [PATCH 073/132] Bugfix --- backend/tomato/elements/tinc.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index da57b2d48..673c7b750 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -226,6 +226,11 @@ def action_start(self): self._parallelChildActions(self._childsByState()[ST_PREPARED], "start") self.setState(ST_STARTED) + + def checkMigrate(self): + return self.state in self.CUSTOM_ACTIONS["migrate"] + + def action_migrate(self,hst): self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",hst) self._parallelChildActions(self._childsByState()[ST_STARTED], "migrate",hst) From f8da4d831b7bbb753d9de7972233aec90aab273b Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 12:55:03 +0200 Subject: [PATCH 074/132] Bugfix --- backend/tomato/elements/tinc.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 673c7b750..a9cac680c 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -347,9 +347,7 @@ def action_stop(self): self.setState(ST_PREPARED, True) def checkMigrate(self): - if self.state in [ST_PREPARED, ST_STARTED]: - return True - return False + return self.state in [ST_PREPARED, ST_STARTED] def action_migrate(self,hst): if self.checkMigrate(): From dfb467028be3de94728befb56769c35e6cc8124a Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 13:21:49 +0200 Subject: [PATCH 075/132] Bugfix --- backend/tomato/elements/tinc.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index a9cac680c..3d7a4709e 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -228,8 +228,7 @@ def action_start(self): def checkMigrate(self): - return self.state in self.CUSTOM_ACTIONS["migrate"] - + return self._childsByState()[ST_PREPARED] != [] or self._childsByState()[ST_STARTED] != [] def action_migrate(self,hst): self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",hst) From 6d9949aedd6f4e3977684f29ffb01972f65d71fb Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 13:22:39 +0200 Subject: [PATCH 076/132] Bugfix --- backend/tomato/host.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index ebc58ad83..c8be15494 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1060,8 +1060,8 @@ def reallocate(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() - prevScor = getHostValue(host=el.element.host,site=el.element.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) - best,bestScor = getBestHost(site=el.element.host.site,hostPrefs=hostPref,sitePrefs=sitePref) + prevScor = getHostValue(host=el.host,site=el.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) + best,bestScor = getBestHost(site=el.host.site,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible if el.element.host != best: From ea92a51b949f60588a507d5a03fa479a8ea7682b Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 13:25:29 +0200 Subject: [PATCH 077/132] Bugfix --- backend/tomato/host.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index c8be15494..d18bdc4c8 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1060,8 +1060,9 @@ def reallocate(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() - prevScor = getHostValue(host=el.host,site=el.host.site,elementTypes=el.type,hostPrefs=hostPref,sitePrefs=sitePref) - best,bestScor = getBestHost(site=el.host.site,hostPrefs=hostPref,sitePrefs=sitePref) + mainElement = el.mainElement() + prevScor = getHostValue(host=mainElement.host,site=mainElement.host.site,elementTypes=mainElement.type,hostPrefs=hostPref,sitePrefs=sitePref) + best,bestScor = getBestHost(site=mainElement.host.site,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible if el.element.host != best: From 63833e0708a9fda3833d7caf03a0472db942457a Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 13:33:53 +0200 Subject: [PATCH 078/132] Bugfix --- backend/tomato/host.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index d18bdc4c8..22a32ad48 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1060,7 +1060,9 @@ def reallocate(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() + print(el) mainElement = el.mainElement() + print(mainElement) prevScor = getHostValue(host=mainElement.host,site=mainElement.host.site,elementTypes=mainElement.type,hostPrefs=hostPref,sitePrefs=sitePref) best,bestScor = getBestHost(site=mainElement.host.site,hostPrefs=hostPref,sitePrefs=sitePref) From 007300596f36395525c885f406bc56dc2bc4bbeb Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 13:36:01 +0200 Subject: [PATCH 079/132] Bugfix --- backend/tomato/host.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 22a32ad48..af2e31b5e 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1063,8 +1063,9 @@ def reallocate(): print(el) mainElement = el.mainElement() print(mainElement) - prevScor = getHostValue(host=mainElement.host,site=mainElement.host.site,elementTypes=mainElement.type,hostPrefs=hostPref,sitePrefs=sitePref) - best,bestScor = getBestHost(site=mainElement.host.site,hostPrefs=hostPref,sitePrefs=sitePref) + if mainElement: + prevScor = getHostValue(host=mainElement.host,site=mainElement.host.site,elementTypes=mainElement.type,hostPrefs=hostPref,sitePrefs=sitePref) + best,bestScor = getBestHost(site=mainElement.host.site,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible if el.element.host != best: From e7d0e053e711615ccd9a7143ccf4930fcbf4f412 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 13:36:50 +0200 Subject: [PATCH 080/132] Bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index af2e31b5e..b09da6bb9 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1063,7 +1063,7 @@ def reallocate(): print(el) mainElement = el.mainElement() print(mainElement) - if mainElement: + if mainElement != None: prevScor = getHostValue(host=mainElement.host,site=mainElement.host.site,elementTypes=mainElement.type,hostPrefs=hostPref,sitePrefs=sitePref) best,bestScor = getBestHost(site=mainElement.host.site,hostPrefs=hostPref,sitePrefs=sitePref) From 064429b16a179dd2ee9e94d940849a88371f9bb5 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 13:39:43 +0200 Subject: [PATCH 081/132] Bugfix --- backend/tomato/host.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index b09da6bb9..9775d10c3 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1063,18 +1063,18 @@ def reallocate(): print(el) mainElement = el.mainElement() print(mainElement) - if mainElement != None: + if mainElement != None and el.element: prevScor = getHostValue(host=mainElement.host,site=mainElement.host.site,elementTypes=mainElement.type,hostPrefs=hostPref,sitePrefs=sitePref) best,bestScor = getBestHost(site=mainElement.host.site,hostPrefs=hostPref,sitePrefs=sitePref) - #Compare best host with preference host and migrate to better one if possible - if el.element.host != best: - print("host != best") - if bestScor - prevScor > THRESHOLD: - print("best besser als host") - if el.checkMigrate(): - print("migrate erlaubt") - el.action_migrate(best) + #Compare best host with preference host and migrate to better one if possible + if el.element.host != best: + print("host != best") + if bestScor - prevScor > THRESHOLD: + print("best besser als host") + if el.checkMigrate(): + print("migrate erlaubt") + el.action_migrate(best) From 1ec346a87d340a2d7ed2cb214719b13caba2a40c Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 14:20:23 +0200 Subject: [PATCH 082/132] bugfix --- backend/tomato/api/host.py | 2 +- backend/tomato/elements/tinc.py | 7 ++----- backend/tomato/elements/udp.py | 5 ++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/backend/tomato/api/host.py b/backend/tomato/api/host.py index 2c52a4abf..c84bf7165 100644 --- a/backend/tomato/api/host.py +++ b/backend/tomato/api/host.py @@ -179,7 +179,7 @@ def host_remove(name): host_list.invalidate() @checkauth -def host_reallokat(): +def host_reallocate(): host.reallocate() @checkauth diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 3d7a4709e..0986a71c1 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -228,11 +228,10 @@ def action_start(self): def checkMigrate(self): - return self._childsByState()[ST_PREPARED] != [] or self._childsByState()[ST_STARTED] != [] + return self._childsByState()[ST_PREPARED] != [] def action_migrate(self,hst): self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",hst) - self._parallelChildActions(self._childsByState()[ST_STARTED], "migrate",hst) def upcast(self): return self @@ -346,12 +345,10 @@ def action_stop(self): self.setState(ST_PREPARED, True) def checkMigrate(self): - return self.state in [ST_PREPARED, ST_STARTED] + return self.state in [ST_PREPARED] def action_migrate(self,hst): if self.checkMigrate(): - if self.state in [ST_STARTED]: - self.action("stop") self.action("destroy") UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) attrs = self._remoteAttrs() diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index e96da3001..922fa69c5 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -114,9 +114,8 @@ def action_stop(self): self.setState(ST_PREPARED, True) def checkMigrate(self): - if self.state in [ST_PREPARED]: - return True - return False + return self.state in [ST_PREPARED] + def action_migrate(self,hst): if self.checkMigrate(): From eecb9290763fb9c69d666f7b9db0912fd507426f Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 15:16:46 +0200 Subject: [PATCH 083/132] bugfix --- backend/tomato/host.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 9775d10c3..fe55155d9 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1046,10 +1046,32 @@ def getHostList(site=None, elementTypes=None, connectionTypes=None,networkKinds= return hosts, prefs def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None): - hosts, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) + hosts_all, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) + cand,cand_prefs = checkForHostDeactivation() + hosts = [] + for host in hosts_all: + if host not in cand: + hosts.append(host) hosts.sort(key=lambda h: prefs[h], reverse=True) return hosts[0], prefs[hosts[0]] +def checkForHostDeactivation(): + hosts, prefs = getHostList() + candidates = [] + candidates_prefs = [] + for host in hosts: + host_elements = host.getElements() + n = 0 + for el in host_elements: + if not el.state in ["started"]: + n+=1 + if n == 0: + candidates.append(host) + candidates_prefs.append((host, prefs[host])) + candidates.sort(key=lambda h: prefs[h], reverse=True) + candidates_prefs.sort(key=lambda h: prefs[h], reverse=True) + return candidates, candidates_prefs + def reallocate(): import elements @@ -1060,20 +1082,15 @@ def reallocate(): if el.state in ["started","created"]: continue hostPref, sitePref = el.getLocationPrefs() - print(el) mainElement = el.mainElement() - print(mainElement) if mainElement != None and el.element: prevScor = getHostValue(host=mainElement.host,site=mainElement.host.site,elementTypes=mainElement.type,hostPrefs=hostPref,sitePrefs=sitePref) best,bestScor = getBestHost(site=mainElement.host.site,hostPrefs=hostPref,sitePrefs=sitePref) #Compare best host with preference host and migrate to better one if possible if el.element.host != best: - print("host != best") if bestScor - prevScor > THRESHOLD: - print("best besser als host") if el.checkMigrate(): - print("migrate erlaubt") el.action_migrate(best) From 58348cb810c1711cff8874c40258eb4e95e37fad Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 15:18:50 +0200 Subject: [PATCH 084/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index fe55155d9..fe6fccfcf 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1060,7 +1060,7 @@ def checkForHostDeactivation(): candidates = [] candidates_prefs = [] for host in hosts: - host_elements = host.getElements() + host_elements = host.getElement().getElements() n = 0 for el in host_elements: if not el.state in ["started"]: From ae17b0cb03bfde980506878ff797c5809ca8a0b5 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 15:34:34 +0200 Subject: [PATCH 085/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index fe6fccfcf..cb31bc0b4 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1060,7 +1060,7 @@ def checkForHostDeactivation(): candidates = [] candidates_prefs = [] for host in hosts: - host_elements = host.getElement().getElements() + host_elements = host.elements n = 0 for el in host_elements: if not el.state in ["started"]: From bbd14fe1f238494af47927a991909319aa5e75ec Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 15:42:02 +0200 Subject: [PATCH 086/132] bugfix --- backend/tomato/host.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index cb31bc0b4..3b90e0ecb 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1050,7 +1050,10 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= cand,cand_prefs = checkForHostDeactivation() hosts = [] for host in hosts_all: + print("Gucken ob") + if host not in cand: + print("host nicht potentiell abgeschaltet werden kann") hosts.append(host) hosts.sort(key=lambda h: prefs[h], reverse=True) return hosts[0], prefs[hosts[0]] @@ -1060,12 +1063,15 @@ def checkForHostDeactivation(): candidates = [] candidates_prefs = [] for host in hosts: + print("Host wird überprüft") host_elements = host.elements n = 0 + for el in host_elements: if not el.state in ["started"]: n+=1 if n == 0: + print("Host der potentiell abgeschaltet werden kann") candidates.append(host) candidates_prefs.append((host, prefs[host])) candidates.sort(key=lambda h: prefs[h], reverse=True) From c1e30ecefa4f3ab8361683bd97da4808cf8cbd9c Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 15:44:03 +0200 Subject: [PATCH 087/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 3b90e0ecb..ea0ff6ea3 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1064,7 +1064,7 @@ def checkForHostDeactivation(): candidates_prefs = [] for host in hosts: print("Host wird überprüft") - host_elements = host.elements + host_elements = list(host.elements.getAll()) n = 0 for el in host_elements: From 7d6c7891a20db3b956d50ca9a00222929904fa72 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 16:13:56 +0200 Subject: [PATCH 088/132] bugfix --- backend/tomato/host.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index ea0ff6ea3..95be7abe8 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1059,12 +1059,15 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= return hosts[0], prefs[hosts[0]] def checkForHostDeactivation(): + + import elements + hosts, prefs = getHostList() candidates = [] candidates_prefs = [] for host in hosts: print("Host wird überprüft") - host_elements = list(host.elements.getAll()) + host_elements = list(elements.getAll({'host':host})) n = 0 for el in host_elements: From 124cce4b58d9483382fa8df1973b3d65623c37f4 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 16:15:37 +0200 Subject: [PATCH 089/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 95be7abe8..6be980d57 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1067,7 +1067,7 @@ def checkForHostDeactivation(): candidates_prefs = [] for host in hosts: print("Host wird überprüft") - host_elements = list(elements.getAll({'host':host})) + host_elements = list(elements.getAll(host)) n = 0 for el in host_elements: From dcf8ac277f20970fd3cfab0980ef8eed4d513d54 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 16:30:59 +0200 Subject: [PATCH 090/132] bugfix --- backend/tomato/host.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 6be980d57..8b928e848 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1065,9 +1065,9 @@ def checkForHostDeactivation(): hosts, prefs = getHostList() candidates = [] candidates_prefs = [] - for host in hosts: + for host_ in hosts: print("Host wird überprüft") - host_elements = list(elements.getAll(host)) + host_elements = list(elements.getAll(host=host_)) n = 0 for el in host_elements: @@ -1075,8 +1075,8 @@ def checkForHostDeactivation(): n+=1 if n == 0: print("Host der potentiell abgeschaltet werden kann") - candidates.append(host) - candidates_prefs.append((host, prefs[host])) + candidates.append(host_) + candidates_prefs.append((host_, prefs[host_])) candidates.sort(key=lambda h: prefs[h], reverse=True) candidates_prefs.sort(key=lambda h: prefs[h], reverse=True) return candidates, candidates_prefs From 9217957c4a6c705b0896a12fe49cfdb0451db9dd Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 16:33:09 +0200 Subject: [PATCH 091/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 8b928e848..a33982938 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1067,7 +1067,7 @@ def checkForHostDeactivation(): candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - host_elements = list(elements.getAll(host=host_)) + host_elements = list(host_.elements.getAll()) n = 0 for el in host_elements: From 4b2aaf6969a814950e7520888330e3459e8732db Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 16:36:27 +0200 Subject: [PATCH 092/132] bugfix --- backend/tomato/host.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index a33982938..67d891333 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1067,7 +1067,12 @@ def checkForHostDeactivation(): candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - host_elements = list(host_.elements.getAll()) + print(host_.elements) + + host_elements = list(host_.elements) + + print(list(host_.elements)) + n = 0 for el in host_elements: From f1f1efcc6c46d1df894995c1bccd82619418c6c8 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 18 May 2015 16:38:10 +0200 Subject: [PATCH 093/132] bugfix --- backend/tomato/host.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 67d891333..3f3310d5c 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1067,11 +1067,11 @@ def checkForHostDeactivation(): candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - print(host_.elements) + print(host_.elements.objects.all()) - host_elements = list(host_.elements) + host_elements = list(host_.elements.objects.all()) - print(list(host_.elements)) + print(list(host_.elements.objects.all())) n = 0 From 34d178b5ac9c34dcafc669e83e878e2a14ceafcc Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 19 May 2015 10:16:15 +0200 Subject: [PATCH 094/132] Bugfix --- backend/tomato/elements/generic.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index c418a58d9..4eb762a54 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -241,9 +241,7 @@ def after_upload_use(self): def checkMigrate(self): #We only migrate if the element is prepared - if self.state in [ST_PREPARED]: - return True - return False + return self.state in [ST_PREPARED] def action_migrate(self,hst): if self.checkMigrate() and self.element.host.name != hst.name: From 44fb5be9d4e7d021381bbb8cd540a3242f027c02 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 19 May 2015 11:44:15 +0200 Subject: [PATCH 095/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 3f3310d5c..2467ac9d6 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1067,7 +1067,7 @@ def checkForHostDeactivation(): candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - print(host_.elements.objects.all()) + print(elements.objects.filter(host=host_)) host_elements = list(host_.elements.objects.all()) From d3453fdfa5d237fceec48c3771e8cdce8eff6885 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 19 May 2015 11:54:59 +0200 Subject: [PATCH 096/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 2467ac9d6..dee673cd0 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1067,7 +1067,7 @@ def checkForHostDeactivation(): candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - print(elements.objects.filter(host=host_)) + print(host_.elements.getAll()) host_elements = list(host_.elements.objects.all()) From 6c9d0170c4e6cf63110af81ecea204ff02c55604 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 19 May 2015 11:58:41 +0200 Subject: [PATCH 097/132] bugfix --- backend/tomato/host.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index dee673cd0..965065191 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1067,7 +1067,8 @@ def checkForHostDeactivation(): candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - print(host_.elements.getAll()) + elements = host_.elements.Element(host = host_) + print(elements) host_elements = list(host_.elements.objects.all()) From e409bad6750dad974994737b7d6fd79badda6cab Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 13:11:04 +0200 Subject: [PATCH 098/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 965065191..d976cd87a 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1067,7 +1067,7 @@ def checkForHostDeactivation(): candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - elements = host_.elements.Element(host = host_) + elements = HostElement.objects.filter(host = host_) print(elements) host_elements = list(host_.elements.objects.all()) From 3b5eabe97048d601640ed82c6284c8f66049b209 Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 13:13:29 +0200 Subject: [PATCH 099/132] bugfix --- backend/tomato/host.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index d976cd87a..4815c457d 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1060,20 +1060,14 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= def checkForHostDeactivation(): - import elements hosts, prefs = getHostList() candidates = [] candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - elements = HostElement.objects.filter(host = host_) - print(elements) - - host_elements = list(host_.elements.objects.all()) - - print(list(host_.elements.objects.all())) - + host_elements = HostElement.objects.filter(host = host_) + print( host_elements) n = 0 for el in host_elements: From a15d2b62db68c39a125d6bebcfb10866a61cd01b Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 13:16:18 +0200 Subject: [PATCH 100/132] bugfix --- backend/tomato/host.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 4815c457d..fedd9b7ae 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1067,11 +1067,14 @@ def checkForHostDeactivation(): for host_ in hosts: print("Host wird überprüft") host_elements = HostElement.objects.filter(host = host_) - print( host_elements) + print(host_elements) n = 0 - + print("Überprüfe Elemente") for el in host_elements: - if not el.state in ["started"]: + print("State = started") + if el.state in ["started"]: + + print("Ja") n+=1 if n == 0: print("Host der potentiell abgeschaltet werden kann") From 469e9f1e3cf2fab57f07b3b5afbaed254b6533eb Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 13:17:22 +0200 Subject: [PATCH 101/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index fedd9b7ae..cb7cc0055 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1066,7 +1066,7 @@ def checkForHostDeactivation(): candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - host_elements = HostElement.objects.filter(host = host_) + host_elements = HostElement.filter(host = host_) print(host_elements) n = 0 print("Überprüfe Elemente") From 7def20d3f33d38e8f72d9fb356aec80e20b912fd Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 13:21:44 +0200 Subject: [PATCH 102/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index cb7cc0055..fedd9b7ae 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1066,7 +1066,7 @@ def checkForHostDeactivation(): candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") - host_elements = HostElement.filter(host = host_) + host_elements = HostElement.objects.filter(host = host_) print(host_elements) n = 0 print("Überprüfe Elemente") From 040b680d36575e9e365992d6c177054075283e3d Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 14:04:14 +0200 Subject: [PATCH 103/132] bugfix --- backend/tomato/host.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index fedd9b7ae..fd94416da 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1059,13 +1059,12 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= return hosts[0], prefs[hosts[0]] def checkForHostDeactivation(): - - hosts, prefs = getHostList() candidates = [] candidates_prefs = [] for host_ in hosts: print("Host wird überprüft") + print(host_) host_elements = HostElement.objects.filter(host = host_) print(host_elements) n = 0 @@ -1078,10 +1077,16 @@ def checkForHostDeactivation(): n+=1 if n == 0: print("Host der potentiell abgeschaltet werden kann") + print(candidates) + candidates.append(host_) + print("1.") candidates_prefs.append((host_, prefs[host_])) + print("2.") candidates.sort(key=lambda h: prefs[h], reverse=True) + print("3.") candidates_prefs.sort(key=lambda h: prefs[h], reverse=True) + print("4.") return candidates, candidates_prefs def reallocate(): From 447947bb7a5ec33e696fa9e9d07542f3003bf636 Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 14:10:57 +0200 Subject: [PATCH 104/132] bugfix --- backend/tomato/host.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index fd94416da..04a8fe09f 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1077,7 +1077,6 @@ def checkForHostDeactivation(): n+=1 if n == 0: print("Host der potentiell abgeschaltet werden kann") - print(candidates) candidates.append(host_) print("1.") @@ -1085,7 +1084,7 @@ def checkForHostDeactivation(): print("2.") candidates.sort(key=lambda h: prefs[h], reverse=True) print("3.") - candidates_prefs.sort(key=lambda h: prefs[h], reverse=True) + candidates_prefs.sort(key=lambda h: h[2], reverse=True) print("4.") return candidates, candidates_prefs From a20a2580e0299b601077ab968336b7c027d52662 Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 14:11:27 +0200 Subject: [PATCH 105/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 04a8fe09f..e58244da1 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1084,7 +1084,7 @@ def checkForHostDeactivation(): print("2.") candidates.sort(key=lambda h: prefs[h], reverse=True) print("3.") - candidates_prefs.sort(key=lambda h: h[2], reverse=True) + candidates_prefs.sort(key=lambda h: h[1], reverse=True) print("4.") return candidates, candidates_prefs From 0960c60b64e693cf56b1d58dbed1440fe6fcace5 Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 14:13:19 +0200 Subject: [PATCH 106/132] bugfix --- backend/tomato/host.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index e58244da1..5ddf348da 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1055,7 +1055,8 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= if host not in cand: print("host nicht potentiell abgeschaltet werden kann") hosts.append(host) - hosts.sort(key=lambda h: prefs[h], reverse=True) + if hosts != []: + hosts.sort(key= lambda h: prefs[h], reverse=True) return hosts[0], prefs[hosts[0]] def checkForHostDeactivation(): From c890b69957c2cb632177f010cc884b17c0781eae Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 14:15:12 +0200 Subject: [PATCH 107/132] bugfix --- backend/tomato/host.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 5ddf348da..da732c9d2 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1055,6 +1055,8 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= if host not in cand: print("host nicht potentiell abgeschaltet werden kann") hosts.append(host) + + hosts.append(hosts_all[0]) if hosts != []: hosts.sort(key= lambda h: prefs[h], reverse=True) return hosts[0], prefs[hosts[0]] From af55b3bdabb239ed81932013b011008773901220 Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 14:48:49 +0200 Subject: [PATCH 108/132] bugfix --- backend/tomato/host.py | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index da732c9d2..764e3b04c 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -282,6 +282,8 @@ class Host(attributes.Mixin, DumpSource, models.Model): availability = attributes.attribute("availability", float, 1.0) description_text = attributes.attribute("description_text", unicode, "") dump_last_fetch = attributes.attribute("dump_last_fetch", float, 0) + detachable = attributes.attribute("detachable", bool,False) + # connections: [HostConnection] # elements: [HostElement] # templates: [TemplateOnHost] @@ -1050,10 +1052,8 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= cand,cand_prefs = checkForHostDeactivation() hosts = [] for host in hosts_all: - print("Gucken ob") if host not in cand: - print("host nicht potentiell abgeschaltet werden kann") hosts.append(host) hosts.append(hosts_all[0]) @@ -1066,25 +1066,18 @@ def checkForHostDeactivation(): candidates = [] candidates_prefs = [] for host_ in hosts: - print("Host wird überprüft") - print(host_) - host_elements = HostElement.objects.filter(host = host_) - print(host_elements) - n = 0 - print("Überprüfe Elemente") - for el in host_elements: - print("State = started") - if el.state in ["started"]: + if host_.detachable: + print(host_) + host_elements = HostElement.objects.filter(host = host_) + print(host_elements) + n = 0 + for el in host_elements: + if el.state in ["started"]: + n+=1 + if n == 0: - print("Ja") - n+=1 - if n == 0: - print("Host der potentiell abgeschaltet werden kann") - - candidates.append(host_) - print("1.") - candidates_prefs.append((host_, prefs[host_])) - print("2.") + candidates.append(host_) + candidates_prefs.append((host_, prefs[host_])) candidates.sort(key=lambda h: prefs[h], reverse=True) print("3.") candidates_prefs.sort(key=lambda h: h[1], reverse=True) From 8d6ba7b690fae6178f942c00c50ed80a78695ece Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 14:51:07 +0200 Subject: [PATCH 109/132] bugfix --- backend/tomato/host.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 764e3b04c..87dba2aab 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1052,11 +1052,8 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= cand,cand_prefs = checkForHostDeactivation() hosts = [] for host in hosts_all: - if host not in cand: hosts.append(host) - - hosts.append(hosts_all[0]) if hosts != []: hosts.sort(key= lambda h: prefs[h], reverse=True) return hosts[0], prefs[hosts[0]] From 0e9d4de06a7a71e56742f7daaea9e90c2dd4f08c Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 14:56:15 +0200 Subject: [PATCH 110/132] bugfix --- backend/tomato/host.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 87dba2aab..a6562f712 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1049,7 +1049,7 @@ def getHostList(site=None, elementTypes=None, connectionTypes=None,networkKinds= def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None): hosts_all, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) - cand,cand_prefs = checkForHostDeactivation() + cand = checkForHostDeactivation() hosts = [] for host in hosts_all: if host not in cand: @@ -1063,23 +1063,20 @@ def checkForHostDeactivation(): candidates = [] candidates_prefs = [] for host_ in hosts: + print(".") + print(host_.detachable) if host_.detachable: - print(host_) host_elements = HostElement.objects.filter(host = host_) - print(host_elements) n = 0 for el in host_elements: if el.state in ["started"]: n+=1 if n == 0: - candidates.append(host_) candidates_prefs.append((host_, prefs[host_])) candidates.sort(key=lambda h: prefs[h], reverse=True) - print("3.") - candidates_prefs.sort(key=lambda h: h[1], reverse=True) - print("4.") - return candidates, candidates_prefs + print(".") + return candidates def reallocate(): From 70dc6f2e2087e7567bc2c3a01ae270aacde6ab79 Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 15:15:28 +0200 Subject: [PATCH 111/132] Added detachable flag for hosts --- backend/tomato/host.py | 2 -- hostmanager/tomato/config.py | 7 +++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index a6562f712..1e845f083 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1063,7 +1063,6 @@ def checkForHostDeactivation(): candidates = [] candidates_prefs = [] for host_ in hosts: - print(".") print(host_.detachable) if host_.detachable: host_elements = HostElement.objects.filter(host = host_) @@ -1075,7 +1074,6 @@ def checkForHostDeactivation(): candidates.append(host_) candidates_prefs.append((host_, prefs[host_])) candidates.sort(key=lambda h: prefs[h], reverse=True) - print(".") return candidates def reallocate(): diff --git a/hostmanager/tomato/config.py b/hostmanager/tomato/config.py index 2c2ad0c31..ccc540c2b 100644 --- a/hostmanager/tomato/config.py +++ b/hostmanager/tomato/config.py @@ -201,6 +201,13 @@ MAINTENANCE = os.environ.has_key('TOMATO_MAINTENANCE') + +""" +A Flag that informs the backend if a host is detachable or not +""" + +DETACHABLE = False + try: import sys for path in filter(os.path.exists, ["/etc/tomato/hostmanager.conf", os.path.expanduser("~/.tomato/hostmanager.conf"), "hostmanager.conf"]): From 10787a2931d64baa34702fbebd9ed531382d4f19 Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 20 May 2015 15:32:04 +0200 Subject: [PATCH 112/132] Added detachable flag into hostmanager config --- backend/tomato/host.py | 1 + hostmanager/tomato/api/host.py | 1 + 2 files changed, 2 insertions(+) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 1e845f083..3b0c3fc2f 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -327,6 +327,7 @@ def update(self): self.hostInfoTimestamp = (before + after) / 2.0 self.hostInfo["query_time"] = after - before self.hostInfo["time_diff"] = self.hostInfo["time"] - self.hostInfoTimestamp + self.detachable = self.hostInfo["detachable"] try: self.hostNetworks = self.getProxy().host_networks() except: diff --git a/hostmanager/tomato/api/host.py b/hostmanager/tomato/api/host.py index b432329cd..d2af3f8cb 100644 --- a/hostmanager/tomato/api/host.py +++ b/hostmanager/tomato/api/host.py @@ -141,6 +141,7 @@ def host_info(): "data": hostinfo.diskinfo(config.DATA_DIR), }, }, + "detachable":config.DETACHABLE, "uptime": hostinfo.uptime(), "system": hostinfo.system(), "dumps": dump.getCount() From 2cfc73154461be7b7a85ea5e092eeea03206c4a2 Mon Sep 17 00:00:00 2001 From: swuest Date: Thu, 21 May 2015 14:38:09 +0200 Subject: [PATCH 113/132] Modified the host value function and added weight for started elements to the rating --- backend/tomato/host.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 3b0c3fc2f..11cb88d06 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -705,6 +705,7 @@ def info(self): "host_info_timestamp": self.hostInfoTimestamp, "availability": self.availability, "description_text": self.description_text, + "detachable": self.detachable, "networks": [n for n in self.hostNetworks] if self.hostNetworks else None } @@ -1020,6 +1021,16 @@ def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, netwo pref = 0.0 pref -= host.componentErrors * 25 # discourage hosts with previous errors pref -= host.getLoad() * 100 # up to -100 points for load + if host.detachable: + host_elements = HostElement.objects.filter(host = host) + n = 0 + for el in host_elements: + if el.state in ["started"]: + n+=1 + pref += n*2 + else: + pref -= 50 + if host in hostPrefs: pref += hostPrefs[host] if host.site in sitePrefs: From b9b05ab830498482344131087195b541a8d2e0dd Mon Sep 17 00:00:00 2001 From: swuest Date: Thu, 21 May 2015 14:46:02 +0200 Subject: [PATCH 114/132] Balancing --- backend/tomato/host.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 11cb88d06..864b8c462 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1027,9 +1027,12 @@ def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, netwo for el in host_elements: if el.state in ["started"]: n+=1 - pref += n*2 + if n =< 10: + pref -= 50 + if n > 10: + pref += 25 else: - pref -= 50 + pref += 25 if host in hostPrefs: pref += hostPrefs[host] From aaa0831e5f7c84f94066ff814779985e14a5a360 Mon Sep 17 00:00:00 2001 From: swuest Date: Thu, 21 May 2015 14:50:23 +0200 Subject: [PATCH 115/132] Balancing --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 864b8c462..1fcecfa6f 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1027,7 +1027,7 @@ def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, netwo for el in host_elements: if el.state in ["started"]: n+=1 - if n =< 10: + if n <= 10: pref -= 50 if n > 10: pref += 25 From 21eaf053a6439ff7cdda6e9db1f3166f7a8d55c1 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 26 May 2015 11:37:37 +0200 Subject: [PATCH 116/132] Added a deactivated flag for each host. Also implemented an scheduled algorithm for host management. The backend is now able to activate and deactivate hosts on demand. --- backend/tomato/api/host.py | 10 ++++++ backend/tomato/host.py | 66 +++++++++++++++++++++++++++++++--- hostmanager/tomato/api/host.py | 3 ++ 3 files changed, 75 insertions(+), 4 deletions(-) diff --git a/backend/tomato/api/host.py b/backend/tomato/api/host.py index c84bf7165..3491d3fe3 100644 --- a/backend/tomato/api/host.py +++ b/backend/tomato/api/host.py @@ -169,6 +169,16 @@ def host_modify(name, attrs): host_list.invalidate() return h.info() +@checkauth +def host_deactivate(name): + """ + undocumented + """ + h = _getHost(name) + h.deactivate() + return h.info() + + @checkauth def host_remove(name): """ diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 1fcecfa6f..b974d917c 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -25,6 +25,7 @@ from auth import Flags from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys +from tomato.api.host import host_reallocate class RemoteWrapper: def __init__(self, url, host, *args, **kwargs): @@ -283,6 +284,7 @@ class Host(attributes.Mixin, DumpSource, models.Model): description_text = attributes.attribute("description_text", unicode, "") dump_last_fetch = attributes.attribute("dump_last_fetch", float, 0) detachable = attributes.attribute("detachable", bool,False) + detached = attributes.attribute("detached",bool, False) # connections: [HostConnection] # elements: [HostElement] @@ -705,8 +707,10 @@ def info(self): "host_info_timestamp": self.hostInfoTimestamp, "availability": self.availability, "description_text": self.description_text, - "detachable": self.detachable, - "networks": [n for n in self.hostNetworks] if self.hostNetworks else None + "detachable": self.detachable, + "detached": self.detached, + "networks": [n for n in self.hostNetworks] if self.hostNetworks else None, + } def __str__(self): @@ -740,7 +744,11 @@ def dump_set_last_fetch(self, last_fetch): def dump_get_last_fetch(self): return self.dump_last_fetch - + + def deactivate(self): + self.detached = True; + self.getProxy().host_deactivate(self.name) + class HostElement(attributes.Mixin, models.Model): host = models.ForeignKey(Host, null=False, related_name="elements") @@ -1057,6 +1065,8 @@ def getHostList(site=None, elementTypes=None, connectionTypes=None,networkKinds= continue if set(networkKinds) - set(host.getNetworkKinds()): continue + if host.deactivated: + continue hosts.append(host) UserError.check(hosts, code=UserError.INVALID_CONFIGURATION, message="No hosts found for requirements") prefs = dict([(h, getHostValue(h, site, elementTypes, connectionTypes, networkKinds, hostPrefs, sitePrefs)) for h in hosts]) @@ -1078,7 +1088,6 @@ def checkForHostDeactivation(): candidates = [] candidates_prefs = [] for host_ in hosts: - print(host_.detachable) if host_.detachable: host_elements = HostElement.objects.filter(host = host_) n = 0 @@ -1212,7 +1221,56 @@ def synchronizeComponents(): hel.synchronize() for hcon in HostConnection.objects.all(): hcon.synchronize() + +@util.wrap_task +def host_management(): + + AVG_MINIMUM = 0.4 + AVG_MAXIMUM = 0.8 + + import statistics + + avg = [] + for h in getHostList(): + avg.append(h.getLoad()) + + avg = statistics.mean(avg) + print(avg) + if avg < AVG_MINIMUM: + host_deactivation() + elif avg >= AVG_MAXIMUM: + host_allocation() + + +def host_deactivation(): + hosts = checkForHostDeactivation() + for host in hosts: + host_reallocate() + + for el in HostElement.objects.filter(host = host): + + new_hosts,new_hosts_pref = getHostList(site = host.site) + new_hosts.remove(host) + + new_hosts.sort(key=lambda h: new_hosts_pref[h], reverse=True) + el.action("migrate",new_hosts[0]) + + if not HostElement.objects.filter(host = host).exists(): + host.allow_deactivation() + +def host_allocation(): + hosts = [] + for host in Host.objects.filter(deactivated = True): + hosts.append((host,getHostValue(host))) + + if hosts.exists(): + hosts.sort(key=lambda h: h[1], reverse=True) + hosts[0][0].action('allocate') + #else: + #TODO: Do something to chose the best technology to allocate new hosts + scheduler.scheduleRepeated(config.HOST_UPDATE_INTERVAL, synchronize) # @UndefinedVariable scheduler.scheduleRepeated(3600, synchronizeComponents) # @UndefinedVariable +scheduler.scheduleRepeated(300, host_management) # @UndefinedVariable diff --git a/hostmanager/tomato/api/host.py b/hostmanager/tomato/api/host.py index d2af3f8cb..333d2f587 100644 --- a/hostmanager/tomato/api/host.py +++ b/hostmanager/tomato/api/host.py @@ -275,6 +275,9 @@ def host_networks(): res.append(data) return res +def host_deactivate(): + print("Deactivated") + from .. import dump, elements, connections, resources, config from ..lib.cmd import hostinfo, net, dhcp #@UnresolvedImport import time \ No newline at end of file From 2a0ab8f39a130a70a599fc42312bb5ade8c3f125 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 26 May 2015 11:44:23 +0200 Subject: [PATCH 117/132] bugfix --- backend/tomato/host.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index b974d917c..34d1301c2 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -25,7 +25,6 @@ from auth import Flags from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys -from tomato.api.host import host_reallocate class RemoteWrapper: def __init__(self, url, host, *args, **kwargs): @@ -1245,7 +1244,7 @@ def host_management(): def host_deactivation(): hosts = checkForHostDeactivation() for host in hosts: - host_reallocate() + host.reallocate() for el in HostElement.objects.filter(host = host): From 1dc720bd03dbdf2a854efdfe06dcb71f9f20088d Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 26 May 2015 12:51:01 +0200 Subject: [PATCH 118/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 34d1301c2..9de745dbf 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1221,7 +1221,7 @@ def synchronizeComponents(): for hcon in HostConnection.objects.all(): hcon.synchronize() -@util.wrap_task + def host_management(): AVG_MINIMUM = 0.4 From 90a284bc881cf032404b21430c40d0e445630222 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 26 May 2015 12:57:45 +0200 Subject: [PATCH 119/132] bugfix --- backend/tomato/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 9de745dbf..34d1301c2 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1221,7 +1221,7 @@ def synchronizeComponents(): for hcon in HostConnection.objects.all(): hcon.synchronize() - +@util.wrap_task def host_management(): AVG_MINIMUM = 0.4 From 9696943cec3581b869cb44c39fa51461bc369eb3 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 26 May 2015 13:01:48 +0200 Subject: [PATCH 120/132] bugfix --- backend/tomato/host.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 34d1301c2..993de0d5c 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1064,7 +1064,7 @@ def getHostList(site=None, elementTypes=None, connectionTypes=None,networkKinds= continue if set(networkKinds) - set(host.getNetworkKinds()): continue - if host.deactivated: + if host.detached: continue hosts.append(host) UserError.check(hosts, code=UserError.INVALID_CONFIGURATION, message="No hosts found for requirements") @@ -1259,7 +1259,7 @@ def host_deactivation(): def host_allocation(): hosts = [] - for host in Host.objects.filter(deactivated = True): + for host in Host.objects.filter(detached = True): hosts.append((host,getHostValue(host))) if hosts.exists(): From f054cb41f95bf9ff80c2d7eb39e9908ed929dd6f Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 1 Jun 2015 10:18:14 +0200 Subject: [PATCH 121/132] bugfixes --- backend/tomato/elements/external_network.py | 7 +++---- backend/tomato/elements/generic.py | 10 +--------- backend/tomato/elements/repy.py | 3 --- backend/tomato/elements/tinc.py | 2 +- backend/tomato/elements/udp.py | 2 +- 5 files changed, 6 insertions(+), 18 deletions(-) diff --git a/backend/tomato/elements/external_network.py b/backend/tomato/elements/external_network.py index 49ca8421b..baca8b7a8 100644 --- a/backend/tomato/elements/external_network.py +++ b/backend/tomato/elements/external_network.py @@ -23,6 +23,7 @@ from .. import currentUser from ..auth import Flags from ..lib.error import UserError +from tomato.elements.generic import ST_PREPARED class External_Network(elements.generic.ConnectingElement, elements.Element): name_attr = Attr("name", desc="Name") @@ -36,7 +37,7 @@ class External_Network(elements.generic.ConnectingElement, elements.Element): CUSTOM_ACTIONS = { "start": [ST_CREATED], "stop": [ST_STARTED], - "migrate": [ST_STARTED], + "migrate": [ST_PREPARED], elements.REMOVE_ACTION: [ST_CREATED], } CUSTOM_ATTRS = { @@ -195,9 +196,7 @@ def action_stop(self): def checkMigrate(self): #We only migrate if the external network is already started, otherwise we don't have to migrate - if self.state in [ST_STARTED]: - return True - return False + return self.state in [ST_PREPARED] def action_migrate(self,hst): if self.checkMigrate(): diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 4eb762a54..3bc043306 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -252,16 +252,8 @@ def action_migrate(self,hst): #Download template. Receive download_grant from template and save it to a tempfile? urllib.urlretrieve(self.element.host.grantUrl(self.action("download_grant"), "download"), "tmp_image.tar.gz") - - attrs = self._remoteAttrs() - attrs.update({ - "template": self._template().name, - }) - attrs.update(self._profileAttrs()) - - #Create identical element on new host - new_el = hst.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) + new_el = hst.createElement(self.TYPE, parent=None, attrs=self.attrs, ownerElement=self) #Kill old element on old host self.element.action("destroy") diff --git a/backend/tomato/elements/repy.py b/backend/tomato/elements/repy.py index b0bcb61f7..894203c74 100644 --- a/backend/tomato/elements/repy.py +++ b/backend/tomato/elements/repy.py @@ -59,9 +59,6 @@ def action_destroy(self): self.setState(generic.ST_CREATED, True) - #TODO: integrate migration function and additional migrate the repy log - def checkMigrate(self): - return False class Repy_Interface(generic.VMInterface): diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 0986a71c1..5d7be230a 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -348,7 +348,7 @@ def checkMigrate(self): return self.state in [ST_PREPARED] def action_migrate(self,hst): - if self.checkMigrate(): + if self.checkMigrate() and self.element.host.name != hst.name: self.action("destroy") UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) attrs = self._remoteAttrs() diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index 922fa69c5..f98649737 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -118,7 +118,7 @@ def checkMigrate(self): def action_migrate(self,hst): - if self.checkMigrate(): + if self.checkMigrate() and self.element.host.name != hst.name: UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) attrs = self._remoteAttrs() attrs.update({ From fd4741b502b74392cb5eeaed06e7beecbaf21635 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 2 Jun 2015 13:10:16 +0200 Subject: [PATCH 122/132] Stylefixes --- backend/tomato/api/elements.py | 5 +- backend/tomato/elements/external_network.py | 3 +- backend/tomato/elements/generic.py | 55 +++++++++++---------- backend/tomato/host.py | 3 +- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/backend/tomato/api/elements.py b/backend/tomato/api/elements.py index 5334d9be6..769e43935 100644 --- a/backend/tomato/api/elements.py +++ b/backend/tomato/api/elements.py @@ -299,7 +299,7 @@ def element_usage(id): #@ReservedAssignment el = _getElement(id) return el.totalUsage.info() -def element_migrate(id,hst): #@ReservedAssignment +def element_migrate(id,host): #@ReservedAssignment """ Migrates an element to a new host @@ -317,8 +317,7 @@ def element_migrate(id,hst): #@ReservedAssignment from host import _getHost el = _getElement(id) - ho = _getHost(hst) - el.action_migrate(ho) + el.action_migrate(host) return el.info() diff --git a/backend/tomato/elements/external_network.py b/backend/tomato/elements/external_network.py index baca8b7a8..b272e4e60 100644 --- a/backend/tomato/elements/external_network.py +++ b/backend/tomato/elements/external_network.py @@ -19,11 +19,10 @@ from .. import elements, resources, host from ..resources import network as r_network from ..lib.attributes import Attr #@UnresolvedImport -from generic import ST_CREATED, ST_STARTED +from generic import ST_CREATED, ST_STARTED, ST_PREPARED from .. import currentUser from ..auth import Flags from ..lib.error import UserError -from tomato.elements.generic import ST_PREPARED class External_Network(elements.generic.ConnectingElement, elements.Element): name_attr = Attr("name", desc="Name") diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 3bc043306..1e5d6a39b 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -243,33 +243,38 @@ def checkMigrate(self): #We only migrate if the element is prepared return self.state in [ST_PREPARED] - def action_migrate(self,hst): - if self.checkMigrate() and self.element.host.name != hst.name: - - UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element",data={"type": self.TYPE}) - + def action_migrate(self,host): - #Download template. Receive download_grant from template and save it to a tempfile? - urllib.urlretrieve(self.element.host.grantUrl(self.action("download_grant"), "download"), "tmp_image.tar.gz") - - #Create identical element on new host - new_el = hst.createElement(self.TYPE, parent=None, attrs=self.attrs, ownerElement=self) + from ..host import Host + + host = Host.objects.filter(name = host) + + UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) + UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) + UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) + + + #Download template. Receive download_grant from template and save it to a tempfile? + urllib.urlretrieve(self.element.host.grantUrl(self.action("download_grant"), "download"), self.name+"_tmp_image.tar.gz") + + #Create identical element on new host + new_el = host.createElement(self.TYPE, parent=None, attrs=self.attrs, ownerElement=self) - #Kill old element on old host - self.element.action("destroy") - - #Set new element and save it - self.element = new_el - self.save() - for iface in self.getChildren(): - iface._create() - self.element.action("prepare") - - self.setState(ST_PREPARED, True) - - upload(hst.grantUrl(new_el.action("upload_grant"),"upload"),"tmp_image.tar.gz") - new_el.action("upload_use") - + #Kill old element on old host + self.element.action("destroy") + + #Set new element and save it + self.element = new_el + self.save() + for iface in self.getChildren(): + iface._create() + self.element.action("prepare") + + self.setState(ST_PREPARED, True) + + upload(host.grantUrl(new_el.action("upload_grant"),"upload"),"tmp_image.tar.gz") + new_el.action("upload_use") + diff --git a/backend/tomato/host.py b/backend/tomato/host.py index a647199de..112115076 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1133,7 +1133,6 @@ def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None if not elementTypes: elementTypes = [] host, pref = getBestHost(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) - hosts, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) logging.logMessage("select", category="host", result=host.name, prefs=dict([(k.name, v) for k, v in prefs.iteritems()]), @@ -1255,7 +1254,7 @@ def host_deactivation(): new_hosts.remove(host) new_hosts.sort(key=lambda h: new_hosts_pref[h], reverse=True) - el.action("migrate",new_hosts[0]) + el.action("migrate",new_hosts[0].name) if not HostElement.objects.filter(host = host).exists(): host.allow_deactivation() From 3f8b79cc43b89a0d992138f3c2987f657ad8e91b Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 2 Jun 2015 13:39:29 +0200 Subject: [PATCH 123/132] Added ErrorChecks and fixed some little Issues --- backend/tomato/elements/external_network.py | 35 ++++++++++++--------- backend/tomato/elements/tinc.py | 26 ++++++++------- backend/tomato/elements/udp.py | 25 ++++++++------- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/backend/tomato/elements/external_network.py b/backend/tomato/elements/external_network.py index b272e4e60..5e5f4ea1d 100644 --- a/backend/tomato/elements/external_network.py +++ b/backend/tomato/elements/external_network.py @@ -197,21 +197,26 @@ def checkMigrate(self): #We only migrate if the external network is already started, otherwise we don't have to migrate return self.state in [ST_PREPARED] - def action_migrate(self,hst): - if self.checkMigrate(): - kind = self.getParent().network.kind if self.parent and self.getParent().samenet else self.kind - - UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", - data={"type": self.TYPE}) - if self.parent and self.getParent().samenet: - self.network = r_network.getInstance(hst, self.getParent().network.kind) - else: - self.network = r_network.getInstance(hst, self.kind) - attrs = {"network": self.network.network.kind} - self.element.action("destroy") - self.element = hst.createElement("external_network", parent=None, attrs=attrs, ownerElement=self) - self.setState(ST_STARTED) - self.triggerConnectionStart() + def action_migrate(self,host): + from ..host import Host + + host = Host.objects.filter(name = host) + + UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) + UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) + UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) + + kind = self.getParent().network.kind if self.parent and self.getParent().samenet else self.kind + + if self.parent and self.getParent().samenet: + self.network = r_network.getInstance(host, self.getParent().network.kind) + else: + self.network = r_network.getInstance(host, self.kind) + attrs = {"network": self.network.network.kind} + self.element.action("destroy") + self.element = host.createElement("external_network", parent=None, attrs=attrs, ownerElement=self) + self.setState(ST_STARTED) + self.triggerConnectionStart() def readyToConnect(self): diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 5d7be230a..d8936d7f3 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -347,18 +347,20 @@ def action_stop(self): def checkMigrate(self): return self.state in [ST_PREPARED] - def action_migrate(self,hst): - if self.checkMigrate() and self.element.host.name != hst.name: - self.action("destroy") - UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - attrs = self._remoteAttrs() - attrs.update({ - "mode": self.mode, - "peers": self.peers, - }) - self.element = hst.createElement(self.remoteType(), parent=None, attrs=attrs, ownerElement=self) - self.save() - self.setState(ST_PREPARED, True) + def action_migrate(self,host): + from ..host import Host + + host = Host.objects.filter(name = host) + + UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) + UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) + UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) + + self.action("destroy") + + self.element = host.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) + self.save() + self.setState(ST_PREPARED, True) def upcast(self): return self diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index f98649737..fe311583b 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -117,17 +117,20 @@ def checkMigrate(self): return self.state in [ST_PREPARED] - def action_migrate(self,hst): - if self.checkMigrate() and self.element.host.name != hst.name: - UserError.check(hst, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - attrs = self._remoteAttrs() - attrs.update({ - "connect": self.connect, - }) - self.element.action("destroy") - self.element = hst.createElement(self.remoteType(), parent=None, attrs=attrs, ownerElement=self) - self.save() - self.setState(ST_PREPARED, True) + def action_migrate(self,host): + + from ..host import Host + + host = Host.objects.filter(name = host) + + UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) + UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) + UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) + + self.element.action("destroy") + self.element = host.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) + self.save() + self.setState(ST_PREPARED, True) def upcast(self): return self From e7fcaecf2408014c7c504fae9bf2ccc3e49f92db Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 2 Jun 2015 14:24:05 +0200 Subject: [PATCH 124/132] Bugfix --- backend/tomato/host.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 112115076..d751cff9a 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1133,6 +1133,7 @@ def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None if not elementTypes: elementTypes = [] host, pref = getBestHost(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) + hosts, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) logging.logMessage("select", category="host", result=host.name, prefs=dict([(k.name, v) for k, v in prefs.iteritems()]), From ec33b8fdd6beb7111aeb39b09c70c5f7a37520b1 Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 3 Jun 2015 11:06:45 +0200 Subject: [PATCH 125/132] Changed migration of connection elements and added some score for host resources for the getHostValue function --- backend/tomato/elements/generic.py | 23 ++++++++++- backend/tomato/host.py | 64 ++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 1e5d6a39b..77ce8ac8c 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -266,8 +266,9 @@ def action_migrate(self,host): #Set new element and save it self.element = new_el self.save() + for iface in self.getChildren(): - iface._create() + iface.action("migrate",host) self.element.action("prepare") self.setState(ST_PREPARED, True) @@ -338,7 +339,25 @@ def _remove(self): self.save() def checkMigrate(self): - return False + return self.state in ST_PREPARED + + def action_migrate(self,host): + from ..host import Host + + host = Host.objects.filter(name = host) + + UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) + UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) + UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) + + parEl = self.getParent().element + assert parEl + attrs = self._remoteAttrs() + element = parEl.createChild(self.Type, attrs=attrs, ownerElement=self) + + self.element.remove() + self.element = element + self.save() def readyToConnect(self): return self.state == ST_STARTED diff --git a/backend/tomato/host.py b/backend/tomato/host.py index d751cff9a..0c4b63100 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1034,15 +1034,27 @@ def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, netwo if host.detachable: host_elements = HostElement.objects.filter(host = host) n = 0 + #Count all on this host deployed elements for el in host_elements: if el.state in ["started"]: n+=1 + #If we have less than 10, "mark" him as possible candidate for detaching if n <= 10: pref -= 50 - if n > 10: + elif n > 10: pref += 25 else: pref += 25 + + #We need to take a view on the given resources of an host + #Give the CPU's some points + pref += host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg']/1000 + + #Points for free disc space + pref += host.hostinfo['resources']['diskspace']['data']['free']/10000000 + + #Points for Memory + pref += host.hostinfo['resources']['diskspace']['memory']['total']/1000000 if host in hostPrefs: pref += hostPrefs[host] @@ -1083,23 +1095,38 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= hosts.append(host) if hosts != []: hosts.sort(key= lambda h: prefs[h], reverse=True) + else: + hosts = hosts_all.sort(key= lambda h: prefs[h], reverse=True) return hosts[0], prefs[hosts[0]] def checkForHostDeactivation(): hosts, prefs = getHostList() candidates = [] candidates_prefs = [] - for host_ in hosts: - if host_.detachable: - host_elements = HostElement.objects.filter(host = host_) - n = 0 - for el in host_elements: - if el.state in ["started"]: - n+=1 - if n == 0: - candidates.append(host_) - candidates_prefs.append((host_, prefs[host_])) - candidates.sort(key=lambda h: prefs[h], reverse=True) + + + + import statistics + + avg = [] + for h in getHostList(): + avg.append(h.getLoad()) + + avg = statistics.mean(avg) + + if avg < AVG_MINIMUM: + for host_ in hosts: + if host_.detachable: + host_elements = HostElement.objects.filter(host = host_) + n = 0 + for el in host_elements: + if el.state in ["started"]: + n+=1 + if n == 0: + candidates.append(host_) + candidates_prefs.append((host_, prefs[host_])) + candidates.sort(key=lambda h: prefs[h], reverse=True) + return candidates def reallocate(): @@ -1224,12 +1251,17 @@ def synchronizeComponents(): for hcon in HostConnection.objects.all(): hcon.synchronize() + + +#TODO: Maybe put into backend config file? +#AVG load needed for host deactivation +AVG_MINIMUM = 0.4 +AVG_MAXIMUM = 0.8 + + @util.wrap_task def host_management(): - AVG_MINIMUM = 0.4 - AVG_MAXIMUM = 0.8 - import statistics avg = [] @@ -1237,7 +1269,7 @@ def host_management(): avg.append(h.getLoad()) avg = statistics.mean(avg) - print(avg) + if avg < AVG_MINIMUM: host_deactivation() elif avg >= AVG_MAXIMUM: From 0ba95360eade88614d05869fc6cbe342ebcc112e Mon Sep 17 00:00:00 2001 From: swuest Date: Wed, 3 Jun 2015 16:33:20 +0200 Subject: [PATCH 126/132] Fixed different issues: - removed unnecessary api call for migration - changed action_migrate to try_migrate - there is no host parameter anymore - the element searches for a new host and migrates if necessary - changed checkForHostDeactivation - now it checks every 5 minutes if the system can handle the load of a host - it sets a fixedPref which affects the value of the host - renamed host_management to dynamic_allocation - it checks periodic if the system can allocate or detache hosts --- backend/tomato/api/elements.py | 21 ---- backend/tomato/elements/generic.py | 76 +++++-------- backend/tomato/elements/tinc.py | 25 ++-- backend/tomato/elements/udp.py | 16 +-- backend/tomato/host.py | 177 ++++++++++++----------------- hostmanager/tomato/api/host.py | 3 - shared/lib/util.py | 28 +++++ 7 files changed, 148 insertions(+), 198 deletions(-) diff --git a/backend/tomato/api/elements.py b/backend/tomato/api/elements.py index 769e43935..63d394160 100644 --- a/backend/tomato/api/elements.py +++ b/backend/tomato/api/elements.py @@ -298,27 +298,6 @@ def element_usage(id): #@ReservedAssignment """ el = _getElement(id) return el.totalUsage.info() - -def element_migrate(id,host): #@ReservedAssignment - """ - Migrates an element to a new host - - - Parameter *id*: - The parameter *id* identifies the element by giving its unique id. - - Parameter *host*: - The parameter *host* identifies the new host by giving its unique id. - - Return value: - Returns the host name to confirm the - - """ - from host import _getHost - - el = _getElement(id) - el.action_migrate(host) - return el.info() from .. import elements, currentUser diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 77ce8ac8c..6c18941a4 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -20,6 +20,7 @@ from ..lib.attributes import Attr, attribute #@UnresolvedImport from ..lib import attributes,rpc #@UnresolvedImport from ..lib.error import UserError, InternalError +from ..lib.util import upload import time import urllib @@ -241,24 +242,27 @@ def after_upload_use(self): def checkMigrate(self): #We only migrate if the element is prepared - return self.state in [ST_PREPARED] + return self.state in [ST_CREATED,ST_PREPARED] - def action_migrate(self,host): - from ..host import Host + def try_migrate(self): - host = Host.objects.filter(name = host) - - UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) - UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) + UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) + if self.state in [ST_CREATED]: return + + hPref, sPref = self.getLocationPrefs() + host_ = host.select(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + UserError.check(host_, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) + + if host_.name == self.element.host.name: return + - #Download template. Receive download_grant from template and save it to a tempfile? urllib.urlretrieve(self.element.host.grantUrl(self.action("download_grant"), "download"), self.name+"_tmp_image.tar.gz") #Create identical element on new host - new_el = host.createElement(self.TYPE, parent=None, attrs=self.attrs, ownerElement=self) + new_el = host_.createElement(self.TYPE, parent=None, attrs=self.attrs, ownerElement=self) #Kill old element on old host self.element.action("destroy") @@ -268,15 +272,19 @@ def action_migrate(self,host): self.save() for iface in self.getChildren(): - iface.action("migrate",host) + iface.try_migrate() self.element.action("prepare") self.setState(ST_PREPARED, True) - upload(host.grantUrl(new_el.action("upload_grant"),"upload"),"tmp_image.tar.gz") - new_el.action("upload_use") - + upload(host_.grantUrl(new_el.action("upload_grant"),"upload"),"tmp_image.tar.gz") + new_el.action("upload_use") + + def action_migrate(self): + UserError.check(currentUser(), code=UserError.NOT_LOGGED_IN, message="Unauthorized") + UserError.check("global_admin" in currentUser().Flags, code=UserError.DENIED, message="Unauthorized") + self.try_migrate() def upcast(self): @@ -339,17 +347,13 @@ def _remove(self): self.save() def checkMigrate(self): - return self.state in ST_PREPARED + return self.state in [ST_CREATED,ST_PREPARED] - def action_migrate(self,host): - from ..host import Host - - host = Host.objects.filter(name = host) - - UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) - UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) + def try_migrate(self): + UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) - + if self.state in [ST_CREATED]: return + parEl = self.getParent().element assert parEl attrs = self._remoteAttrs() @@ -365,34 +369,6 @@ def readyToConnect(self): def upcast(self): return self -def upload (url, file, name="upload"): - import httplib, urlparse, os - parts = urlparse.urlparse(url) - conn = httplib.HTTPConnection(parts.netloc) - req = parts.path - if parts.query: - req += "?" + parts.query - conn.putrequest("POST", req) - filename = os.path.basename(file) - filesize = os.path.getsize(file) - BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$' - CRLF = '\r\n' - prepend = "--" + BOUNDARY + CRLF + 'Content-Disposition: form-data; name="%s"; filename="%s"' % ( - name, filename) + CRLF + "Content-Type: application/data" + CRLF + CRLF - append = CRLF + "--" + BOUNDARY + "--" + CRLF + CRLF - conn.putheader("Content-Length", len(prepend) + filesize + len(append)) - conn.putheader("Content-Type", 'multipart/form-data; boundary=%s' % BOUNDARY) - conn.endheaders() - conn.send(prepend) - fd = open(file, "r") - data = fd.read(8192) - while data: - conn.send(data) - data = fd.read(8192) - fd.close() - conn.send(append) - resps = conn.getresponse() - data = resps.read() class ConnectingElement: def getLocationData(self, maxDepth=3): diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index d8936d7f3..9262e75e7 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -228,10 +228,12 @@ def action_start(self): def checkMigrate(self): - return self._childsByState()[ST_PREPARED] != [] + return self._childsByState()[ST_PREPARED] != [] or self._childsByState()[ST_CREATED] != [] def action_migrate(self,hst): + self._parallelChildActions(self._childsByState()[ST_CREATED], "migrate",hst) self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",hst) + def upcast(self): return self @@ -345,20 +347,21 @@ def action_stop(self): self.setState(ST_PREPARED, True) def checkMigrate(self): - return self.state in [ST_PREPARED] + return self.state in [ST_CREATED,ST_PREPARED] + + def try_migrate(self): + + UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) + if self.state in [ST_CREATED]: return - def action_migrate(self,host): - from ..host import Host + hPref, sPref = self.getLocationPrefs() + host_ = host.select(elementTypes=["tinc"], hostPrefs=hPref, sitePrefs=sPref) + UserError.check(host_, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - host = Host.objects.filter(name = host) + if host_.name == self.element.host.name: return - UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) - UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) - UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) - self.action("destroy") - - self.element = host.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) + self.element = host_.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) self.save() self.setState(ST_PREPARED, True) diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index fe311583b..55f229bbd 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -114,19 +114,19 @@ def action_stop(self): self.setState(ST_PREPARED, True) def checkMigrate(self): - return self.state in [ST_PREPARED] + return self.state in [ST_CREATED,ST_PREPARED] - def action_migrate(self,host): + def action_migrate(self): + + UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) + if self.state in [ST_CREATED]: return - from ..host import Host + host_ = host.select(elementTypes=[self.remoteType()]) + UserError.check(host_, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - host = Host.objects.filter(name = host) + if host_.name == self.element.host.name: return - UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) - UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) - UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) - self.element.action("destroy") self.element = host.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) self.save() diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 0c4b63100..8ed25d53d 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -286,6 +286,7 @@ class Host(attributes.Mixin, DumpSource, models.Model): dump_last_fetch = attributes.attribute("dump_last_fetch", float, 0) detachable = attributes.attribute("detachable", bool,False) detached = attributes.attribute("detached",bool, False) + fixedPref = attributes.attribute("fixed_pref",float,0) # connections: [HostConnection] # elements: [HostElement] @@ -587,6 +588,8 @@ def modify(self, attrs): self.enabled = value elif key == "description_text": self.description_text = value + elif key == "detached": + self.detached else: raise UserError(code=UserError.UNSUPPORTED_ATTRIBUTE, message="Unknown host attribute", data={"attribute": key}) @@ -710,6 +713,7 @@ def info(self): "description_text": self.description_text, "detachable": self.detachable, "detached": self.detached, + "fixed_pref": self.fixedPref, "networks": [n for n in self.hostNetworks] if self.hostNetworks else None, } @@ -746,10 +750,6 @@ def dump_set_last_fetch(self, last_fetch): def dump_get_last_fetch(self): return self.dump_last_fetch - def deactivate(self): - self.detached = True; - self.getProxy().host_deactivate(self.name) - class HostElement(attributes.Mixin, models.Model): host = models.ForeignKey(Host, null=False, related_name="elements") @@ -1031,31 +1031,8 @@ def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, netwo pref = 0.0 pref -= host.componentErrors * 25 # discourage hosts with previous errors pref -= host.getLoad() * 100 # up to -100 points for load - if host.detachable: - host_elements = HostElement.objects.filter(host = host) - n = 0 - #Count all on this host deployed elements - for el in host_elements: - if el.state in ["started"]: - n+=1 - #If we have less than 10, "mark" him as possible candidate for detaching - if n <= 10: - pref -= 50 - elif n > 10: - pref += 25 - else: - pref += 25 - - #We need to take a view on the given resources of an host - #Give the CPU's some points - pref += host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg']/1000 - - #Points for free disc space - pref += host.hostinfo['resources']['diskspace']['data']['free']/10000000 - - #Points for Memory - pref += host.hostinfo['resources']['diskspace']['memory']['total']/1000000 - + pref += host.fixedPref + if host in hostPrefs: pref += hostPrefs[host] if host.site in sitePrefs: @@ -1086,70 +1063,62 @@ def getHostList(site=None, elementTypes=None, connectionTypes=None,networkKinds= prefs = dict([(h, getHostValue(h, site, elementTypes, connectionTypes, networkKinds, hostPrefs, sitePrefs)) for h in hosts]) return hosts, prefs -def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None): - hosts_all, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) - cand = checkForHostDeactivation() - hosts = [] - for host in hosts_all: - if host not in cand: - hosts.append(host) - if hosts != []: - hosts.sort(key= lambda h: prefs[h], reverse=True) - else: - hosts = hosts_all.sort(key= lambda h: prefs[h], reverse=True) +def getBestHost(hostList): + + hosts, prefs = hostList + return hosts[0], prefs[hosts[0]] +@util.wrap_task def checkForHostDeactivation(): - hosts, prefs = getHostList() - candidates = [] - candidates_prefs = [] - + hosts = Host.objects.filter(detached=False,enabled=True) - - import statistics + sum_free_cpu_power = 0 + sum_free_disc_space = 0 + sum_free_memory = 0 - avg = [] - for h in getHostList(): - avg.append(h.getLoad()) + fixedPref = 0 + + #Get a sum of all free resources of all hosts + for host in hosts: + sum_free_cpu_power += (host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg'])*(1-host.getLoad()) + sum_free_disc_space += host.hostinfo['resources']['diskspace']['data']['free'] + sum_free_memory += host.hostinfo['resources']['diskspace']['memory']['total']-host.hostinfo['resources']['diskspace']['memory']['used'] + + #Check for hosts that can fit into the free resources of all + for host in Host.objects.filter(detachable=True,enabled=True): - avg = statistics.mean(avg) - - if avg < AVG_MINIMUM: - for host_ in hosts: - if host_.detachable: - host_elements = HostElement.objects.filter(host = host_) - n = 0 - for el in host_elements: - if el.state in ["started"]: - n+=1 - if n == 0: - candidates.append(host_) - candidates_prefs.append((host_, prefs[host_])) - candidates.sort(key=lambda h: prefs[h], reverse=True) - return candidates + #Fixed Points for being detachable + fixedPref=-25 + + host_cpu_power_used = (host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg'])*host.getLoad() + host_disc_space_used = host.hostinfo['resources']['diskspace']['data']['used'] + host_memory_used = host.hostinfo['resources']['diskspace']['memory']['used'] + + #Check for active elements and connections and reduce fixedPref for each + host_elements = HostElement.objects.filter(host = host) + host_connections = HostConnection.objects.filter(host = host) + if host_elements == [] and host_connections == []: + fixedPref -=100 + #If we can fit the used resources of a detachable host into the other hosts, just do so + if host_cpu_power_used < (sum_free_cpu_power-host_cpu_power_used): + if host_disc_space_used < (sum_free_disc_space - host_disc_space_used): + if host_memory_used < (sum_free_memory - host_memory_used): + fixedPref -= 200 + if host_elements == [] and host_connections == []: + #He has no active elements and we can handle his load + fixedPref -=900 + + + host.fixedPref = fixedPref def reallocate(): import elements - #needs to be redefined at a better place - THRESHOLD = 20 #Walk through all elements and think about reallocating them. for el in list(elements.getAll()): - if el.state in ["started","created"]: - continue - hostPref, sitePref = el.getLocationPrefs() - mainElement = el.mainElement() - if mainElement != None and el.element: - prevScor = getHostValue(host=mainElement.host,site=mainElement.host.site,elementTypes=mainElement.type,hostPrefs=hostPref,sitePrefs=sitePref) - best,bestScor = getBestHost(site=mainElement.host.site,hostPrefs=hostPref,sitePrefs=sitePref) - - #Compare best host with preference host and migrate to better one if possible - if el.element.host != best: - if bestScor - prevScor > THRESHOLD: - if el.checkMigrate(): - el.action_migrate(best) - + el.try_reallocate() def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): @@ -1159,16 +1128,17 @@ def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None if not connectionTypes: connectionTypes = [] if not elementTypes: elementTypes = [] - host, pref = getBestHost(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) hosts, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) - logging.logMessage("select", category="host", result=host.name, + hosts.sort(key=lambda h: prefs[h], reverse=True) + logging.logMessage("select", category="host", result=hosts[0].name, prefs=dict([(k.name, v) for k, v in prefs.iteritems()]), site=site.name if site else None, element_types=elementTypes, connection_types=connectionTypes, network_types=networkKinds, host_prefs=dict([(k.name, v) for k, v in hostPrefs.iteritems()]), site_prefs=dict([(k.name, v) for k, v in sitePrefs.iteritems()])) - return host + + return hosts[0] @cached(timeout=3600, autoupdate=True) @@ -1260,7 +1230,7 @@ def synchronizeComponents(): @util.wrap_task -def host_management(): +def dynamic_allocation(): import statistics @@ -1277,29 +1247,25 @@ def host_management(): def host_deactivation(): - hosts = checkForHostDeactivation() - for host in hosts: - host.reallocate() - - for el in HostElement.objects.filter(host = host): - - new_hosts,new_hosts_pref = getHostList(site = host.site) - new_hosts.remove(host) + + reallocate() + checkForHostDeactivation() - new_hosts.sort(key=lambda h: new_hosts_pref[h], reverse=True) - el.action("migrate",new_hosts[0].name) - - if not HostElement.objects.filter(host = host).exists(): - host.allow_deactivation() + for host in Host.objects.filer(detachable=True): + if host.fixedPref < -1000: + host.modify({'detached':True}) + + def host_allocation(): - hosts = [] - for host in Host.objects.filter(detached = True): - hosts.append((host,getHostValue(host))) - - if hosts.exists(): - hosts.sort(key=lambda h: h[1], reverse=True) - hosts[0][0].action('allocate') + hosts, prefs = getHostList() + + hosts.sort(key=lambda h: prefs[h], reverse=True) + + hosts_detached = filter(lambda x: x.detached==True, hosts) + + if hosts_detached != []: + hosts_detached[0].modify({'detached':False}) #else: #TODO: Do something to chose the best technology to allocate new hosts @@ -1307,4 +1273,5 @@ def host_allocation(): scheduler.scheduleRepeated(config.HOST_UPDATE_INTERVAL, synchronize) # @UndefinedVariable scheduler.scheduleRepeated(3600, synchronizeComponents) # @UndefinedVariable -scheduler.scheduleRepeated(300, host_management) # @UndefinedVariable +scheduler.scheduleRepeated(300, checkForHostDeactivation) # @UndefinedVariable +scheduler.scheduleRepeated(300, dynamic_allocation) # @UndefinedVariable diff --git a/hostmanager/tomato/api/host.py b/hostmanager/tomato/api/host.py index 333d2f587..d2af3f8cb 100644 --- a/hostmanager/tomato/api/host.py +++ b/hostmanager/tomato/api/host.py @@ -275,9 +275,6 @@ def host_networks(): res.append(data) return res -def host_deactivate(): - print("Deactivated") - from .. import dump, elements, connections, resources, config from ..lib.cmd import hostinfo, net, dhcp #@UnresolvedImport import time \ No newline at end of file diff --git a/shared/lib/util.py b/shared/lib/util.py index f842783bb..0ea35102b 100644 --- a/shared/lib/util.py +++ b/shared/lib/util.py @@ -221,3 +221,31 @@ def secondsInMonth(year, month): end = startOfMonth(year, month+1) if month < 12 else startOfMonth(year+1, 1) return end-start +def upload (url, file, name="upload"): + import httplib, urlparse, os + parts = urlparse.urlparse(url) + conn = httplib.HTTPConnection(parts.netloc) + req = parts.path + if parts.query: + req += "?" + parts.query + conn.putrequest("POST", req) + filename = os.path.basename(file) + filesize = os.path.getsize(file) + BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$' + CRLF = '\r\n' + prepend = "--" + BOUNDARY + CRLF + 'Content-Disposition: form-data; name="%s"; filename="%s"' % ( + name, filename) + CRLF + "Content-Type: application/data" + CRLF + CRLF + append = CRLF + "--" + BOUNDARY + "--" + CRLF + CRLF + conn.putheader("Content-Length", len(prepend) + filesize + len(append)) + conn.putheader("Content-Type", 'multipart/form-data; boundary=%s' % BOUNDARY) + conn.endheaders() + conn.send(prepend) + fd = open(file, "r") + data = fd.read(8192) + while data: + conn.send(data) + data = fd.read(8192) + fd.close() + conn.send(append) + resps = conn.getresponse() + data = resps.read() From d0b00abc67d2188317b8289e3f80e3c08b1563b9 Mon Sep 17 00:00:00 2001 From: swuest Date: Tue, 1 Sep 2015 13:33:01 +0200 Subject: [PATCH 127/132] Added the configuration of the upper and lower treshold for host allocation and deactivation to config.py Fixed some bugs for different elements by updating the try_migration function. Made some changes and name changes in host.py: * changed checkHostDeactivation to loadInfluencer * updated load influencer * updated getBestHost * changed getHostValue to getHostScore * updated getHostScore * changed hostReallocation to migrator * added the migrator as an periodic function beeing activated every 30 min. --- backend/tomato/config.py | 9 +- backend/tomato/elements/external_network.py | 23 ++- backend/tomato/elements/generic.py | 18 ++- backend/tomato/elements/tinc.py | 17 +- backend/tomato/elements/udp.py | 15 +- backend/tomato/host.py | 167 +++++++++++++------- 6 files changed, 169 insertions(+), 80 deletions(-) diff --git a/backend/tomato/config.py b/backend/tomato/config.py index e200bd13b..1a78f48e6 100644 --- a/backend/tomato/config.py +++ b/backend/tomato/config.py @@ -178,4 +178,11 @@ A new user, %s, has just registered at the ToMaTo testbed.\n\ You can review all pending user registrations at https://master.tomato-lab.org/account/registrations\n\n\ Best Wishes,\nThe ToMaTo Testbed" -} \ No newline at end of file +} + + + +# Load Balancing, Migration, Resource Allocator: +MIGRATION_TRESHOLD = 1.2; #New Host has to be 20% better +AVG_MINIMUM = 0.25; +AVG_MAXIMUM = 0.7; diff --git a/backend/tomato/elements/external_network.py b/backend/tomato/elements/external_network.py index 5e5f4ea1d..0514ef5a6 100644 --- a/backend/tomato/elements/external_network.py +++ b/backend/tomato/elements/external_network.py @@ -23,6 +23,7 @@ from .. import currentUser from ..auth import Flags from ..lib.error import UserError +from tomato.config import MIGRATION_TRESHOLD class External_Network(elements.generic.ConnectingElement, elements.Element): name_attr = Attr("name", desc="Name") @@ -197,15 +198,23 @@ def checkMigrate(self): #We only migrate if the external network is already started, otherwise we don't have to migrate return self.state in [ST_PREPARED] - def action_migrate(self,host): - from ..host import Host + def try_migrate(self): - host = Host.objects.filter(name = host) - - UserError.check(host, code=UserError.NO_RESOURCES, message="Host not found",data={"type": self.TYPE}) - UserError.check(self.element.host.name != host.name, code=UserError.UNSUPPORTED_ACTION, message="Migrating to the same host not allowed",data={"type": self.TYPE}) UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) + + hPref, sPref = self.getLocationPrefs() + + bestHost,bestPref = host.getBestHost(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) + + hostScore = host.getHostScore(self.element.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + + if bestPref > hostScore*MIGRATION_TRESHOLD: + return + + + kind = self.getParent().network.kind if self.parent and self.getParent().samenet else self.kind if self.parent and self.getParent().samenet: @@ -214,7 +223,7 @@ def action_migrate(self,host): self.network = r_network.getInstance(host, self.kind) attrs = {"network": self.network.network.kind} self.element.action("destroy") - self.element = host.createElement("external_network", parent=None, attrs=attrs, ownerElement=self) + self.element = bestHost.createElement("external_network", parent=None, attrs=attrs, ownerElement=self) self.setState(ST_STARTED) self.triggerConnectionStart() diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 6c18941a4..1cc7913ea 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -23,6 +23,7 @@ from ..lib.util import upload import time import urllib +from tomato.config import MIGRATION_TRESHOLD ST_CREATED = "created" ST_PREPARED = "prepared" @@ -246,23 +247,26 @@ def checkMigrate(self): def try_migrate(self): - UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) if self.state in [ST_CREATED]: return hPref, sPref = self.getLocationPrefs() - host_ = host.select(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) - UserError.check(host_, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - if host_.name == self.element.host.name: return + bestHost,bestPref = host.getBestHost(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) + + hostScore = host.getHostScore(self.element.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + + if bestPref > hostScore*MIGRATION_TRESHOLD: + return #Download template. Receive download_grant from template and save it to a tempfile? urllib.urlretrieve(self.element.host.grantUrl(self.action("download_grant"), "download"), self.name+"_tmp_image.tar.gz") #Create identical element on new host - new_el = host_.createElement(self.TYPE, parent=None, attrs=self.attrs, ownerElement=self) + new_el = bestHost.createElement(self.TYPE, parent=None, attrs=self.attrs, ownerElement=self) #Kill old element on old host self.element.action("destroy") @@ -277,7 +281,7 @@ def try_migrate(self): self.setState(ST_PREPARED, True) - upload(host_.grantUrl(new_el.action("upload_grant"),"upload"),"tmp_image.tar.gz") + upload(bestHost.grantUrl(new_el.action("upload_grant"),"upload"),"tmp_image.tar.gz") new_el.action("upload_use") def action_migrate(self): @@ -354,6 +358,8 @@ def try_migrate(self): UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) if self.state in [ST_CREATED]: return + + parEl = self.getParent().element assert parEl attrs = self._remoteAttrs() diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index 9262e75e7..edfbf94ac 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -22,6 +22,7 @@ from ..lib.attributes import Attr #@UnresolvedImport from generic import ST_CREATED, ST_PREPARED, ST_STARTED from ..lib.error import UserError, assert_ +from tomato.config import MIGRATION_TRESHOLD class Tinc_VPN(elements.generic.ConnectingElement, elements.Element): name_attr = Attr("name", desc="Name", type="str") @@ -230,7 +231,7 @@ def action_start(self): def checkMigrate(self): return self._childsByState()[ST_PREPARED] != [] or self._childsByState()[ST_CREATED] != [] - def action_migrate(self,hst): + def try_migration(self,hst): self._parallelChildActions(self._childsByState()[ST_CREATED], "migrate",hst) self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",hst) @@ -355,13 +356,19 @@ def try_migrate(self): if self.state in [ST_CREATED]: return hPref, sPref = self.getLocationPrefs() - host_ = host.select(elementTypes=["tinc"], hostPrefs=hPref, sitePrefs=sPref) - UserError.check(host_, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - if host_.name == self.element.host.name: return + + bestHost,bestPref = host.getBestHost(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) + + hostScore = host.getHostScore(self.element.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + + if bestPref > hostScore*MIGRATION_TRESHOLD: + return + self.action("destroy") - self.element = host_.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) + self.element = bestHost.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) self.save() self.setState(ST_PREPARED, True) diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index 55f229bbd..ef0c08be7 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -20,6 +20,7 @@ from ..lib.attributes import Attr #@UnresolvedImport from generic import ST_CREATED, ST_PREPARED, ST_STARTED from ..lib.error import UserError +from tomato.config import MIGRATION_TRESHOLD class UDP_Endpoint(elements.Element): @@ -117,18 +118,24 @@ def checkMigrate(self): return self.state in [ST_CREATED,ST_PREPARED] - def action_migrate(self): + def try_migrate(self): UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) if self.state in [ST_CREATED]: return host_ = host.select(elementTypes=[self.remoteType()]) - UserError.check(host_, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - if host_.name == self.element.host.name: return + bestHost,bestPref = host.getBestHost(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) + + hostScore = host.getHostScore(self.element.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + + if bestPref > hostScore*MIGRATION_TRESHOLD: + return + self.element.action("destroy") - self.element = host.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) + self.element = bestHost.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) self.save() self.setState(ST_PREPARED, True) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 8ed25d53d..f19a16b0a 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -25,6 +25,8 @@ from auth import Flags from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys +from tomato.elements.generic import ST_PREPARED +from tomato.config import AVG_MINIMUM class RemoteWrapper: def __init__(self, url, host, *args, **kwargs): @@ -1022,7 +1024,7 @@ def create(name, site, attrs=None): return host -def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): +def getHostScore(host, site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): if not sitePrefs: sitePrefs = {} if not hostPrefs: hostPrefs = {} if not networkKinds: networkKinds = [] @@ -1031,6 +1033,7 @@ def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, netwo pref = 0.0 pref -= host.componentErrors * 25 # discourage hosts with previous errors pref -= host.getLoad() * 100 # up to -100 points for load + pref -= len(HostElement.objects.filter(host = host)); pref += host.fixedPref if host in hostPrefs: @@ -1039,7 +1042,7 @@ def getHostValue(host, site=None, elementTypes=None, connectionTypes=None, netwo pref += sitePrefs[host.site] return pref -def getHostList(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None): +def getHostList(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None, detached=False): if not sitePrefs: sitePrefs = {} if not hostPrefs: hostPrefs = {} if not networkKinds: networkKinds = [] @@ -1056,69 +1059,125 @@ def getHostList(site=None, elementTypes=None, connectionTypes=None,networkKinds= continue if set(networkKinds) - set(host.getNetworkKinds()): continue - if host.detached: + if host.detached and detached: continue hosts.append(host) UserError.check(hosts, code=UserError.INVALID_CONFIGURATION, message="No hosts found for requirements") - prefs = dict([(h, getHostValue(h, site, elementTypes, connectionTypes, networkKinds, hostPrefs, sitePrefs)) for h in hosts]) + prefs = dict([(h, getHostScore(h, site, elementTypes, connectionTypes, networkKinds, hostPrefs, sitePrefs)) for h in hosts]) + return hosts, prefs -def getBestHost(hostList): - - hosts, prefs = hostList +def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds=None, hostPrefs=None, sitePrefs=None, detached=False): + if not sitePrefs: sitePrefs = {} + if not hostPrefs: hostPrefs = {} + if not networkKinds: networkKinds = [] + if not connectionTypes: connectionTypes = [] + if not elementTypes: elementTypes = [] + all_ = getAll(site=site) if site else getAll() + bestHost = None; + bestScore = None; - return hosts[0], prefs[hosts[0]] + for host in all_: + score = getHostScore(host, site, elementTypes, connectionTypes, networkKinds, hostPrefs, sitePrefs)) + if(score > bestScore): + bestHost = host; + bestScore = score; + + + return bestHost, bestScore @util.wrap_task -def checkForHostDeactivation(): +def loadInfluencer(): + import statistics as stat + + hosts = Host.objects.filter(detached=False,enabled=True) - sum_free_cpu_power = 0 - sum_free_disc_space = 0 - sum_free_memory = 0 + + + sum_cpu_power = 0 + sum_disc_space = 0 + sum_memory = 0 - fixedPref = 0 - #Get a sum of all free resources of all hosts + cloud_cpu_load =[] + cloud_memory_used=[] + cloud_disk_space_used=[] + #Get a sum of all resources of all hosts for host in hosts: - sum_free_cpu_power += (host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg'])*(1-host.getLoad()) - sum_free_disc_space += host.hostinfo['resources']['diskspace']['data']['free'] - sum_free_memory += host.hostinfo['resources']['diskspace']['memory']['total']-host.hostinfo['resources']['diskspace']['memory']['used'] - - #Check for hosts that can fit into the free resources of all + + cloud_cpu_load.append(host.getLoad()) + cloud_memory_used.append(host.hostinfo['resources']['diskspace']['memory']['used']) + cloud_disk_space_used.append(host.hostinfo['resources']['diskspace']['data']['used']/host.hostinfo['resources']['diskspace']['data']['total']) + + sum_cpu_power += (host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg']) + sum_disc_space += host.hostinfo['resources']['diskspace']['data']['total'] + sum_memory += host.hostinfo['resources']['diskspace']['memory']['total'] + + + + avgLoad = [] + avgLoad.append(stat.mean(cloud_cpu_load)) + avgLoad.append(stat.mean(cloud_memory_used/sum_memory) + avgLoad.append(stat.mean(cloud_disk_space_used/sum_disc_space)) + + + cloud_load = min(max(avgLoad),1.0) + #If the average load is not less or equal to the defined MINIMUM, stop this function + + + #Check for hosts that can fit into the resources of the cloud for host in Host.objects.filter(detachable=True,enabled=True): - #Fixed Points for being detachable - fixedPref=-25 + fixedPref = 0 + + host_cpu_power = (host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg']) + host_disc_space = host.hostinfo['resources']['diskspace']['data']['used'] + host_memory = host.hostinfo['resources']['diskspace']['memory']['used'] + host_load = host.getLoad() - host_cpu_power_used = (host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg'])*host.getLoad() - host_disc_space_used = host.hostinfo['resources']['diskspace']['data']['used'] - host_memory_used = host.hostinfo['resources']['diskspace']['memory']['used'] #Check for active elements and connections and reduce fixedPref for each host_elements = HostElement.objects.filter(host = host) host_connections = HostConnection.objects.filter(host = host) - if host_elements == [] and host_connections == []: - fixedPref -=100 - #If we can fit the used resources of a detachable host into the other hosts, just do so - if host_cpu_power_used < (sum_free_cpu_power-host_cpu_power_used): - if host_disc_space_used < (sum_free_disc_space - host_disc_space_used): - if host_memory_used < (sum_free_memory - host_memory_used): - fixedPref -= 200 - if host_elements == [] and host_connections == []: - #He has no active elements and we can handle his load - fixedPref -=900 + + if(cloud_load> AVG_MINIMUM): + host.fixedPref = 0; + else: + fixedPref -= 25; + + + avgLoad_tmp = [] + avgLoad.append(stat.mean(cloud_cpu_load.remove(host_load)))) + avgLoad.append(stat.mean(cloud_memory_used/(sum_memory-host_memory)) + avgLoad.append(stat.mean(cloud_disk_space_used/(sum_disc_space-host_disc_space)) + + tmp_cloud_load = min(max(avgLoad),1.0) + + + + #If we can fit the used resources of a detachable host into the other hosts, just do so + if tmp_cloud_load < AVG_MAXIMUM: + fixedPref -= 200 + + if host_elements == [] and host_connections == []: + #He has no active elements and we can handle his load + fixedPref -=900 - host.fixedPref = fixedPref + + host.fixedPref = fixedPref -def reallocate(): +def checkMigration(): - import elements + import elements as ele #Walk through all elements and think about reallocating them. - for el in list(elements.getAll()): - el.try_reallocate() + elementList = list(ele.getAll()); + + for el in elementList: + if(el.state = ST_PREPARED): + el.try_migrate() def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None, hostPrefs=None, sitePrefs=None): @@ -1128,17 +1187,9 @@ def select(site=None, elementTypes=None, connectionTypes=None, networkKinds=None if not connectionTypes: connectionTypes = [] if not elementTypes: elementTypes = [] - hosts, prefs = getHostList(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) - - hosts.sort(key=lambda h: prefs[h], reverse=True) - logging.logMessage("select", category="host", result=hosts[0].name, - prefs=dict([(k.name, v) for k, v in prefs.iteritems()]), - site=site.name if site else None, element_types=elementTypes, connection_types=connectionTypes, - network_types=networkKinds, - host_prefs=dict([(k.name, v) for k, v in hostPrefs.iteritems()]), - site_prefs=dict([(k.name, v) for k, v in sitePrefs.iteritems()])) + host, pref = getBestHost(site, elementTypes, connectionTypes,networkKinds, hostPrefs, sitePrefs) - return hosts[0] + return host; @cached(timeout=3600, autoupdate=True) @@ -1223,10 +1274,6 @@ def synchronizeComponents(): -#TODO: Maybe put into backend config file? -#AVG load needed for host deactivation -AVG_MINIMUM = 0.4 -AVG_MAXIMUM = 0.8 @util.wrap_task @@ -1248,12 +1295,17 @@ def dynamic_allocation(): def host_deactivation(): - reallocate() - checkForHostDeactivation() + loadInfluencer() - for host in Host.objects.filer(detachable=True): + hosts,prefs = getHostList() + + hosts = filter(lambda x: not x.detached and x.detachable, hosts) + + if not hosts == []: + host = hosts[-1] if host.fixedPref < -1000: host.modify({'detached':True}) + #host.deactivate() @@ -1267,11 +1319,12 @@ def host_allocation(): if hosts_detached != []: hosts_detached[0].modify({'detached':False}) #else: - #TODO: Do something to chose the best technology to allocate new hosts + #TODO: Do something to chose the correct cloud provider plugin to allocate new hosts scheduler.scheduleRepeated(config.HOST_UPDATE_INTERVAL, synchronize) # @UndefinedVariable scheduler.scheduleRepeated(3600, synchronizeComponents) # @UndefinedVariable +scheduler.scheduleRepeated(1800, checkMigration) # @UndefinedVariable scheduler.scheduleRepeated(300, checkForHostDeactivation) # @UndefinedVariable scheduler.scheduleRepeated(300, dynamic_allocation) # @UndefinedVariable From 2c45c3d0f20e634fd49509caaf654464b3663e50 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 14 Sep 2015 09:18:05 +0200 Subject: [PATCH 128/132] Bugfixes --- backend/tomato/elements/generic.py | 4 +-- backend/tomato/elements/tinc.py | 5 ++- backend/tomato/elements/udp.py | 5 ++- backend/tomato/host.py | 51 ++++++++++++++++++------------ 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index 1cc7913ea..df62e975f 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -248,7 +248,6 @@ def checkMigrate(self): def try_migrate(self): - UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) if self.state in [ST_CREATED]: return hPref, sPref = self.getLocationPrefs() @@ -256,7 +255,7 @@ def try_migrate(self): bestHost,bestPref = host.getBestHost(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - hostScore = host.getHostScore(self.element.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + hostScore = host.getHostScore(self.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) if bestPref > hostScore*MIGRATION_TRESHOLD: return @@ -355,7 +354,6 @@ def checkMigrate(self): def try_migrate(self): - UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) if self.state in [ST_CREATED]: return diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index edfbf94ac..d94607872 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -352,16 +352,15 @@ def checkMigrate(self): def try_migrate(self): - UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) if self.state in [ST_CREATED]: return hPref, sPref = self.getLocationPrefs() - bestHost,bestPref = host.getBestHost(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + bestHost,bestPref = host.getBestHost(elementTypes=["tinc"], hostPrefs=hPref, sitePrefs=sPref) UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - hostScore = host.getHostScore(self.element.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + hostScore = host.getHostScore(self.host,elementTypes=["tinc"], hostPrefs=hPref, sitePrefs=sPref) if bestPref > hostScore*MIGRATION_TRESHOLD: return diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index ef0c08be7..ef6323709 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -120,15 +120,14 @@ def checkMigrate(self): def try_migrate(self): - UserError.check(self.element.checkMigrate(), code=UserError.UNSUPPORTED_ACTION, message="Element can't be migrated",data={"type": self.TYPE}) if self.state in [ST_CREATED]: return host_ = host.select(elementTypes=[self.remoteType()]) - bestHost,bestPref = host.getBestHost(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + bestHost,bestPref = host.getBestHost(elementTypes=[self.remoteType()]) UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - hostScore = host.getHostScore(self.element.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + hostScore = host.getHostScore(self.host,elementTypes=[self.remoteType()]) if bestPref > hostScore*MIGRATION_TRESHOLD: return diff --git a/backend/tomato/host.py b/backend/tomato/host.py index f19a16b0a..242ee222d 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -25,8 +25,7 @@ from auth import Flags from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys -from tomato.elements.generic import ST_PREPARED -from tomato.config import AVG_MINIMUM +from tomato.config import AVG_MINIMUM, AVG_MAXIMUM class RemoteWrapper: def __init__(self, url, host, *args, **kwargs): @@ -1078,7 +1077,7 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= bestScore = None; for host in all_: - score = getHostScore(host, site, elementTypes, connectionTypes, networkKinds, hostPrefs, sitePrefs)) + score = getHostScore(host, site, elementTypes, connectionTypes, networkKinds, hostPrefs, sitePrefs) if(score > bestScore): bestHost = host; bestScore = score; @@ -1090,6 +1089,7 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= def loadInfluencer(): import statistics as stat + print("Load Influencer") hosts = Host.objects.filter(detached=False,enabled=True) @@ -1106,19 +1106,21 @@ def loadInfluencer(): #Get a sum of all resources of all hosts for host in hosts: + hostInfo = host.hostinfo + cloud_cpu_load.append(host.getLoad()) - cloud_memory_used.append(host.hostinfo['resources']['diskspace']['memory']['used']) - cloud_disk_space_used.append(host.hostinfo['resources']['diskspace']['data']['used']/host.hostinfo['resources']['diskspace']['data']['total']) + cloud_memory_used.append(hostInfo['resources']['diskspace']['memory']['used']) + cloud_disk_space_used.append(hostInfo['resources']['diskspace']['data']['used']/hostInfo['resources']['diskspace']['data']['total']) - sum_cpu_power += (host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg']) - sum_disc_space += host.hostinfo['resources']['diskspace']['data']['total'] - sum_memory += host.hostinfo['resources']['diskspace']['memory']['total'] + sum_cpu_power += (hostInfo['resources']['cpus_present']['count']*hostInfo['resources']['cpu_present']['bogomips_avg']) + sum_disc_space += hostInfo['resources']['diskspace']['data']['total'] + sum_memory += hostInfo['resources']['diskspace']['memory']['total'] avgLoad = [] avgLoad.append(stat.mean(cloud_cpu_load)) - avgLoad.append(stat.mean(cloud_memory_used/sum_memory) + avgLoad.append(stat.mean(cloud_memory_used/sum_memory)) avgLoad.append(stat.mean(cloud_disk_space_used/sum_disc_space)) @@ -1130,11 +1132,13 @@ def loadInfluencer(): for host in Host.objects.filter(detachable=True,enabled=True): - fixedPref = 0 + fixedPref = 0 + + hostInfo = host.hostinfo - host_cpu_power = (host.hostinfo['resources']['cpus_present']['count']*host.hostinfo['resources']['cpu_present']['bogomips_avg']) - host_disc_space = host.hostinfo['resources']['diskspace']['data']['used'] - host_memory = host.hostinfo['resources']['diskspace']['memory']['used'] + host_cpu_power = (hostInfo['resources']['cpus_present']['count']*hostInfo['resources']['cpu_present']['bogomips_avg']) + host_disc_space = hostInfo['resources']['diskspace']['data']['used'] + host_memory = hostInfo['resources']['diskspace']['memory']['used'] host_load = host.getLoad() @@ -1150,9 +1154,9 @@ def loadInfluencer(): avgLoad_tmp = [] - avgLoad.append(stat.mean(cloud_cpu_load.remove(host_load)))) - avgLoad.append(stat.mean(cloud_memory_used/(sum_memory-host_memory)) - avgLoad.append(stat.mean(cloud_disk_space_used/(sum_disc_space-host_disc_space)) + avgLoad.append(stat.mean(cloud_cpu_load.remove(host_load))) + avgLoad.append(stat.mean(cloud_memory_used/(sum_memory-host_memory))) + avgLoad.append(stat.mean(cloud_disk_space_used/(sum_disc_space-host_disc_space))) tmp_cloud_load = min(max(avgLoad),1.0) @@ -1172,11 +1176,14 @@ def loadInfluencer(): def checkMigration(): import elements as ele + + print("checkMigration") + from tomato.elements.generic import ST_PREPARED #Walk through all elements and think about reallocating them. elementList = list(ele.getAll()); for el in elementList: - if(el.state = ST_PREPARED): + if(el.state == ST_PREPARED): el.try_migrate() @@ -1281,15 +1288,19 @@ def dynamic_allocation(): import statistics + print("dynamic allocation") avg = [] for h in getHostList(): avg.append(h.getLoad()) avg = statistics.mean(avg) - if avg < AVG_MINIMUM: + if avg < AVG_MINIMUM: + print("Minimum") host_deactivation() elif avg >= AVG_MAXIMUM: + + print("Maximum") host_allocation() @@ -1325,6 +1336,6 @@ def host_allocation(): scheduler.scheduleRepeated(config.HOST_UPDATE_INTERVAL, synchronize) # @UndefinedVariable scheduler.scheduleRepeated(3600, synchronizeComponents) # @UndefinedVariable -scheduler.scheduleRepeated(1800, checkMigration) # @UndefinedVariable -scheduler.scheduleRepeated(300, checkForHostDeactivation) # @UndefinedVariable +scheduler.scheduleRepeated(300, checkMigration) # @UndefinedVariable +scheduler.scheduleRepeated(300, loadInfluencer) # @UndefinedVariable scheduler.scheduleRepeated(300, dynamic_allocation) # @UndefinedVariable From 065368b8b5ffffcd008641971c66ab6c72663e52 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 14 Sep 2015 09:34:56 +0200 Subject: [PATCH 129/132] Better sorting for the load influenecer. Bug fix --- backend/tomato/host.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 242ee222d..7ceb12354 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -26,6 +26,7 @@ from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys from tomato.config import AVG_MINIMUM, AVG_MAXIMUM +from tomato.elements.generic import ST_STARTED class RemoteWrapper: def __init__(self, url, host, *args, **kwargs): @@ -1088,9 +1089,7 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= @util.wrap_task def loadInfluencer(): import statistics as stat - - print("Load Influencer") - + hosts = Host.objects.filter(detached=False,enabled=True) @@ -1129,7 +1128,10 @@ def loadInfluencer(): #Check for hosts that can fit into the resources of the cloud - for host in Host.objects.filter(detachable=True,enabled=True): + detachableHosts = Host.objects.filter(detachable=True,enabled=True) + detachableHosts = sorted(detachableHosts, key = lambda host: (len(HostElement.objects.filter(host = host,state = ST_STARTED)), getHostScore(host))) + + for host in detachableHosts: fixedPref = 0 @@ -1143,7 +1145,7 @@ def loadInfluencer(): #Check for active elements and connections and reduce fixedPref for each - host_elements = HostElement.objects.filter(host = host) + host_elements = HostElement.objects.filter(host = host,state = ST_STARTED) host_connections = HostConnection.objects.filter(host = host) if(cloud_load> AVG_MINIMUM): @@ -1154,11 +1156,11 @@ def loadInfluencer(): avgLoad_tmp = [] - avgLoad.append(stat.mean(cloud_cpu_load.remove(host_load))) - avgLoad.append(stat.mean(cloud_memory_used/(sum_memory-host_memory))) - avgLoad.append(stat.mean(cloud_disk_space_used/(sum_disc_space-host_disc_space))) + avgLoad_tmp.append(stat.mean(cloud_cpu_load.remove(host_load))) + avgLoad_tmp.append(stat.mean(cloud_memory_used/(sum_memory-host_memory))) + avgLoad_tmp.append(stat.mean(cloud_disk_space_used/(sum_disc_space-host_disc_space))) - tmp_cloud_load = min(max(avgLoad),1.0) + tmp_cloud_load = min(max(avgLoad_tmp),1.0) @@ -1314,7 +1316,7 @@ def host_deactivation(): if not hosts == []: host = hosts[-1] - if host.fixedPref < -1000: + if host.fixedPref < -1000 and HostElement.objects.filter(host = host) == []: host.modify({'detached':True}) #host.deactivate() From 381ea07e6f3eed877caefd5eed29ce352de02e98 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 14 Sep 2015 09:43:20 +0200 Subject: [PATCH 130/132] Removed prints which have been added for bugfixes. --- backend/tomato/api/host.py | 3 --- backend/tomato/host.py | 8 ++------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/backend/tomato/api/host.py b/backend/tomato/api/host.py index 3491d3fe3..b7fcd6a3d 100644 --- a/backend/tomato/api/host.py +++ b/backend/tomato/api/host.py @@ -188,9 +188,6 @@ def host_remove(name): h.remove() host_list.invalidate() -@checkauth -def host_reallocate(): - host.reallocate() @checkauth def host_users(name): diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 7ceb12354..24fcb1564 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -26,7 +26,6 @@ from dumpmanager import DumpSource import time, hashlib, threading, datetime, zlib, base64, sys from tomato.config import AVG_MINIMUM, AVG_MAXIMUM -from tomato.elements.generic import ST_STARTED class RemoteWrapper: def __init__(self, url, host, *args, **kwargs): @@ -1089,7 +1088,8 @@ def getBestHost(site=None, elementTypes=None, connectionTypes=None,networkKinds= @util.wrap_task def loadInfluencer(): import statistics as stat - + from tomato.elements.generic import ST_STARTED + hosts = Host.objects.filter(detached=False,enabled=True) @@ -1179,7 +1179,6 @@ def checkMigration(): import elements as ele - print("checkMigration") from tomato.elements.generic import ST_PREPARED #Walk through all elements and think about reallocating them. elementList = list(ele.getAll()); @@ -1290,7 +1289,6 @@ def dynamic_allocation(): import statistics - print("dynamic allocation") avg = [] for h in getHostList(): avg.append(h.getLoad()) @@ -1298,11 +1296,9 @@ def dynamic_allocation(): avg = statistics.mean(avg) if avg < AVG_MINIMUM: - print("Minimum") host_deactivation() elif avg >= AVG_MAXIMUM: - print("Maximum") host_allocation() From cc50e61e8f40d4b4074c18cebb33c0dc532635f2 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 14 Sep 2015 12:12:03 +0200 Subject: [PATCH 131/132] Bugfix --- backend/tomato/elements/external_network.py | 4 ++- backend/tomato/elements/generic.py | 26 +++++++------------ backend/tomato/elements/tinc.py | 28 ++++++++++++++++----- backend/tomato/elements/udp.py | 6 ++--- backend/tomato/host.py | 2 +- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/backend/tomato/elements/external_network.py b/backend/tomato/elements/external_network.py index 0514ef5a6..640090f12 100644 --- a/backend/tomato/elements/external_network.py +++ b/backend/tomato/elements/external_network.py @@ -208,6 +208,7 @@ def try_migrate(self): bestHost,bestPref = host.getBestHost(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) + hostScore = host.getHostScore(self.element.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) if bestPref > hostScore*MIGRATION_TRESHOLD: @@ -222,7 +223,8 @@ def try_migrate(self): else: self.network = r_network.getInstance(host, self.kind) attrs = {"network": self.network.network.kind} - self.element.action("destroy") + + self.action_destroy() self.element = bestHost.createElement("external_network", parent=None, attrs=attrs, ownerElement=self) self.setState(ST_STARTED) self.triggerConnectionStart() diff --git a/backend/tomato/elements/generic.py b/backend/tomato/elements/generic.py index df62e975f..3231a2212 100644 --- a/backend/tomato/elements/generic.py +++ b/backend/tomato/elements/generic.py @@ -240,13 +240,9 @@ def after_start(self): def after_upload_use(self): self.custom_template = True self.save() - - def checkMigrate(self): - #We only migrate if the element is prepared - return self.state in [ST_CREATED,ST_PREPARED] - def try_migrate(self): + if self.state in [ST_CREATED]: return @@ -255,20 +251,21 @@ def try_migrate(self): bestHost,bestPref = host.getBestHost(site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - hostScore = host.getHostScore(self.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) + hostScore = host.getHostScore(self.element.host,site=self.site, elementTypes=[self.TYPE]+self.CAP_CHILDREN.keys(), hostPrefs=hPref, sitePrefs=sPref) if bestPref > hostScore*MIGRATION_TRESHOLD: return #Download template. Receive download_grant from template and save it to a tempfile? - urllib.urlretrieve(self.element.host.grantUrl(self.action("download_grant"), "download"), self.name+"_tmp_image.tar.gz") + urllib.urlretrieve(self.element.host.grantUrl(self.element.action("download_grant"), "download"), self.name+"_tmp_image.tar.gz") + attrs = self._remoteAttrs() #Create identical element on new host - new_el = bestHost.createElement(self.TYPE, parent=None, attrs=self.attrs, ownerElement=self) + new_el = bestHost.createElement(self.TYPE, parent=None, attrs=attrs, ownerElement=self) #Kill old element on old host - self.element.action("destroy") + self.action_destroy() #Set new element and save it self.element = new_el @@ -280,14 +277,9 @@ def try_migrate(self): self.setState(ST_PREPARED, True) - upload(bestHost.grantUrl(new_el.action("upload_grant"),"upload"),"tmp_image.tar.gz") + upload(bestHost.grantUrl(new_el.action("upload_grant"),"upload"),self.name+"_tmp_image.tar.gz") new_el.action("upload_use") - def action_migrate(self): - - UserError.check(currentUser(), code=UserError.NOT_LOGGED_IN, message="Unauthorized") - UserError.check("global_admin" in currentUser().Flags, code=UserError.DENIED, message="Unauthorized") - self.try_migrate() def upcast(self): @@ -354,14 +346,14 @@ def checkMigrate(self): def try_migrate(self): - if self.state in [ST_CREATED]: return + if self.state in [ST_CREATED,ST_STARTED]: return parEl = self.getParent().element assert parEl attrs = self._remoteAttrs() - element = parEl.createChild(self.Type, attrs=attrs, ownerElement=self) + element = parEl.createChild(self.TYPE, attrs=attrs, ownerElement=self) self.element.remove() self.element = element diff --git a/backend/tomato/elements/tinc.py b/backend/tomato/elements/tinc.py index d94607872..30ec0d12a 100644 --- a/backend/tomato/elements/tinc.py +++ b/backend/tomato/elements/tinc.py @@ -231,9 +231,25 @@ def action_start(self): def checkMigrate(self): return self._childsByState()[ST_PREPARED] != [] or self._childsByState()[ST_CREATED] != [] - def try_migration(self,hst): - self._parallelChildActions(self._childsByState()[ST_CREATED], "migrate",hst) - self._parallelChildActions(self._childsByState()[ST_PREPARED], "migrate",hst) + def try_migrate(self): + + childList = self._childsByState()[ST_PREPARED] + lock = threading.RLock() + class WorkerThread(threading.Thread): + def run(self): + while True: + with lock: + if not childList: + return + ch = childList.pop() + ch.try_migrate() + threads = [] + for _ in xrange(0, min(len(childList), 10)): + thread = WorkerThread() + threads.append(thread) + thread.start() + for thread in threads: + thread.join() def upcast(self): @@ -360,14 +376,14 @@ def try_migrate(self): bestHost,bestPref = host.getBestHost(elementTypes=["tinc"], hostPrefs=hPref, sitePrefs=sPref) UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - hostScore = host.getHostScore(self.host,elementTypes=["tinc"], hostPrefs=hPref, sitePrefs=sPref) + hostScore = host.getHostScore(self.element.host,elementTypes=["tinc"], hostPrefs=hPref, sitePrefs=sPref) if bestPref > hostScore*MIGRATION_TRESHOLD: return - self.action("destroy") - self.element = bestHost.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) + self.action_destroy() + self.element = bestHost.createElement(self.remoteType(), parent=None, attrs=attrs, ownerElement=self) self.save() self.setState(ST_PREPARED, True) diff --git a/backend/tomato/elements/udp.py b/backend/tomato/elements/udp.py index ef6323709..66011fabe 100644 --- a/backend/tomato/elements/udp.py +++ b/backend/tomato/elements/udp.py @@ -127,14 +127,14 @@ def try_migrate(self): bestHost,bestPref = host.getBestHost(elementTypes=[self.remoteType()]) UserError.check(bestHost, code=UserError.NO_RESOURCES, message="No matching host found for element", data={"type": self.TYPE}) - hostScore = host.getHostScore(self.host,elementTypes=[self.remoteType()]) + hostScore = host.getHostScore(self.element.host,elementTypes=[self.remoteType()]) if bestPref > hostScore*MIGRATION_TRESHOLD: return - self.element.action("destroy") - self.element = bestHost.createElement(self.remoteType(), parent=None, attrs=self.attrs, ownerElement=self) + self.action_destroy() + self.element = bestHost.createElement(self.remoteType(), parent=None, attrs=attrs, ownerElement=self) self.save() self.setState(ST_PREPARED, True) diff --git a/backend/tomato/host.py b/backend/tomato/host.py index 24fcb1564..1bcf79aeb 100644 --- a/backend/tomato/host.py +++ b/backend/tomato/host.py @@ -1334,6 +1334,6 @@ def host_allocation(): scheduler.scheduleRepeated(config.HOST_UPDATE_INTERVAL, synchronize) # @UndefinedVariable scheduler.scheduleRepeated(3600, synchronizeComponents) # @UndefinedVariable -scheduler.scheduleRepeated(300, checkMigration) # @UndefinedVariable +scheduler.scheduleRepeated(30, checkMigration) # @UndefinedVariable scheduler.scheduleRepeated(300, loadInfluencer) # @UndefinedVariable scheduler.scheduleRepeated(300, dynamic_allocation) # @UndefinedVariable From c315a4d6e750a689f8c6459dea80983720d5e8a5 Mon Sep 17 00:00:00 2001 From: swuest Date: Mon, 14 Sep 2015 12:15:11 +0200 Subject: [PATCH 132/132] Bugfix --- hostmanager/tomato/lib/newcmd/qemu_img.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hostmanager/tomato/lib/newcmd/qemu_img.py b/hostmanager/tomato/lib/newcmd/qemu_img.py index 5cd6c6b0e..a10707c49 100644 --- a/hostmanager/tomato/lib/newcmd/qemu_img.py +++ b/hostmanager/tomato/lib/newcmd/qemu_img.py @@ -75,7 +75,7 @@ def create(path, format="qcow2", size=None, backingImage=None): @_public def convert(src, dst, srcFormat="qcow2", dstFormat="qcow2", compress=True): src = params.convert(src, check=_checkImage) - dst = params.convert(dst, check=lambda p: not os.path.exists(p)) + dst = params.convert(dst, check=lambda p: not os.path.exists(p[1])) srcFormat = params.convert(srcFormat, convert=str) dstFormat = params.convert(dstFormat, convert=str) try: