Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic resource allocation #975

Open
wants to merge 135 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
fecd304
Added new load balancing functionality to the host.py. Also added a m…
May 7, 2015
d157149
created a function to migrate an element from one host to another. Ad…
May 11, 2015
5cb20fe
Removed unnecessary import
May 11, 2015
1280744
bugfix
May 11, 2015
83387f0
bugfix
May 11, 2015
5bcead1
bugfix
May 11, 2015
c8521a5
bugfix
May 11, 2015
7d094cf
bugfix
May 11, 2015
86a577c
bugfix
May 11, 2015
ab95a63
bugfix
May 11, 2015
ea407d5
bugfix
May 11, 2015
5522995
bugfix
May 11, 2015
7cb90b9
bugfix
May 11, 2015
a8350dc
bugfix
May 11, 2015
c879bea
bugfix
May 11, 2015
eda9630
bugfix
May 11, 2015
2491f5b
bugfix
May 11, 2015
3a0fa1b
bugfix
May 12, 2015
fe3f37c
bugfix
May 12, 2015
4e02edc
bugfix
May 12, 2015
4f531df
bugfix
May 12, 2015
b3a471c
bugfix
May 12, 2015
b5899be
bugfix
May 12, 2015
f75875e
Added the migrate and checkMigrate function to every elementtyp.
May 12, 2015
d79b597
bugfix
May 12, 2015
f8f97a8
bugfix
May 12, 2015
7ad1730
bugfix
May 12, 2015
11395b6
bugfix
May 12, 2015
9c67dc2
bugfix
May 12, 2015
b953a0e
bugfix
May 12, 2015
5a6a5c9
bugfix
May 12, 2015
a0134e9
bugfix
May 12, 2015
f01b141
bugfix
May 12, 2015
53fbbcc
bugfix
May 12, 2015
9788101
bugfix
May 12, 2015
7e5491f
bugfix
May 12, 2015
baa3c3a
bugfix
May 12, 2015
c59ec40
Created a new allocation function as preparation for a new dynamic re…
May 12, 2015
55efd91
bugfix
May 12, 2015
79322af
bugfix
May 12, 2015
708af44
bugfix
May 12, 2015
94d3b4c
bugfix
May 12, 2015
cb09a64
bugfix
May 12, 2015
334e748
bugfix
May 12, 2015
486aa73
bugfix
May 12, 2015
8a00001
added reallokation api call for tests
May 12, 2015
ae150ed
bugfix
May 12, 2015
62d2eb2
bugfix
May 12, 2015
83537e2
bugfix
May 12, 2015
bb60e5a
bugfix
May 12, 2015
22b671c
bugfix
May 12, 2015
bf897c2
bugfix
May 12, 2015
e4fc7b3
bugfix
May 12, 2015
6736465
bugfix
May 12, 2015
98d66b0
bugfix
May 12, 2015
cb319a3
Bugfix
May 18, 2015
de90005
Bugfix
May 18, 2015
8a12e30
Bugfix
May 18, 2015
8bab4dd
Bugfix
May 18, 2015
ca8eb81
Bugfix
May 18, 2015
f85b7c5
Bugfix
May 18, 2015
3c46741
Bugfix
May 18, 2015
1d2e08e
Bugfix
May 18, 2015
ade9eb4
Bugfix
May 18, 2015
51e3a6a
Bugfix
May 18, 2015
e3d436a
Bugfix
May 18, 2015
7e5e389
Bugfix
May 18, 2015
1826573
Bugfix
May 18, 2015
1cb6749
Bugfix
May 18, 2015
34b7e23
Bugfix
May 18, 2015
e281527
Bugfix
May 18, 2015
a1f2b0e
Bugfix
May 18, 2015
27fd1fa
Bugfix
May 18, 2015
f8da4d8
Bugfix
May 18, 2015
dfb4670
Bugfix
May 18, 2015
6d9949a
Bugfix
May 18, 2015
ea92a51
Bugfix
May 18, 2015
63833e0
Bugfix
May 18, 2015
0073005
Bugfix
May 18, 2015
e7d0e05
Bugfix
May 18, 2015
064429b
Bugfix
May 18, 2015
1ec346a
bugfix
May 18, 2015
eecb929
bugfix
May 18, 2015
58348cb
bugfix
May 18, 2015
ae17b0c
bugfix
May 18, 2015
bbd14fe
bugfix
May 18, 2015
c1e30ec
bugfix
May 18, 2015
7d6c789
bugfix
May 18, 2015
124cce4
bugfix
May 18, 2015
dcf8ac2
bugfix
May 18, 2015
9217957
bugfix
May 18, 2015
4b2aaf6
bugfix
May 18, 2015
f1f1efc
bugfix
May 18, 2015
34d178b
Bugfix
May 19, 2015
44fb5be
bugfix
May 19, 2015
d3453fd
bugfix
May 19, 2015
6c9d017
bugfix
May 19, 2015
e409bad
bugfix
May 20, 2015
3b5eabe
bugfix
May 20, 2015
a15d2b6
bugfix
May 20, 2015
469e9f1
bugfix
May 20, 2015
7def20d
bugfix
May 20, 2015
040b680
bugfix
May 20, 2015
447947b
bugfix
May 20, 2015
a20a258
bugfix
May 20, 2015
0960c60
bugfix
May 20, 2015
c890b69
bugfix
May 20, 2015
af55b3b
bugfix
May 20, 2015
8d6ba7b
bugfix
May 20, 2015
0e9d4de
bugfix
May 20, 2015
70dc6f2
Added detachable flag for hosts
May 20, 2015
10787a2
Added detachable flag into hostmanager config
May 20, 2015
2cfc731
Modified the host value function and added weight for started element…
May 21, 2015
b9b05ab
Balancing
May 21, 2015
aaa0831
Balancing
May 21, 2015
21eaf05
Added a deactivated flag for each host. Also implemented an scheduled…
May 26, 2015
2a0ab8f
bugfix
May 26, 2015
1dc720b
bugfix
May 26, 2015
90a284b
bugfix
May 26, 2015
9696943
bugfix
May 26, 2015
130abe5
Merge branch 'master' of github.com:glab/ToMaTo into dynamic_ressourc…
May 26, 2015
f054cb4
bugfixes
Jun 1, 2015
0668934
Merge branch 'master' of github.com:glab/ToMaTo into dynamic_ressourc…
Jun 1, 2015
fd4741b
Stylefixes
Jun 2, 2015
3f8b79c
Added ErrorChecks and fixed some little Issues
Jun 2, 2015
e7fcaec
Bugfix
Jun 2, 2015
ec33b8f
Changed migration of connection elements and added some score for hos…
Jun 3, 2015
0ba9536
Fixed different issues:
Jun 3, 2015
93e9a64
Merge branch 'master' of github.com:glab/ToMaTo into dynamic_resource…
Jul 15, 2015
d0b00ab
Added the configuration of the upper and lower treshold for host allo…
Sep 1, 2015
2c45c3d
Bugfixes
Sep 14, 2015
065368b
Better sorting for the load influenecer. Bug fix
Sep 14, 2015
381ea07
Removed prints which have been added for bugfixes.
Sep 14, 2015
cc50e61
Bugfix
Sep 14, 2015
c315a4d
Bugfix
Sep 14, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions backend/tomato/api/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ def element_usage(id): #@ReservedAssignment
"""
el = _getElement(id)
return el.totalUsage.info()


from .. import elements, currentUser
from topology import _getTopology
Expand Down
11 changes: 11 additions & 0 deletions backend/tomato/api/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,16 @@ def host_modify(name, attrs):
host_list.invalidate()
return h.info()

@checkauth
def host_deactivate(name):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be realized using host_modify

"""
undocumented
"""
h = _getHost(name)
h.deactivate()
return h.info()


@checkauth
def host_remove(name):
"""
Expand All @@ -178,6 +188,7 @@ def host_remove(name):
h.remove()
host_list.invalidate()


@checkauth
def host_users(name):
"""
Expand Down
9 changes: 8 additions & 1 deletion backend/tomato/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}



# Load Balancing, Migration, Resource Allocator:
MIGRATION_TRESHOLD = 1.2; #New Host has to be 20% better
AVG_MINIMUM = 0.25;
AVG_MAXIMUM = 0.7;
2 changes: 2 additions & 0 deletions backend/tomato/elements/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,8 @@ def fetchInfo(self):
mel = self.mainElement()
if mel:
mel.updateInfo()



def updateUsage(self):
self.totalUsage.updateFrom([el.usageStatistics for el in self.getHostElements()]
Expand Down
40 changes: 39 additions & 1 deletion backend/tomato/elements/external_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
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.config import MIGRATION_TRESHOLD

class External_Network(elements.generic.ConnectingElement, elements.Element):
name_attr = Attr("name", desc="Name")
Expand All @@ -36,6 +37,7 @@ class External_Network(elements.generic.ConnectingElement, elements.Element):
CUSTOM_ACTIONS = {
"start": [ST_CREATED],
"stop": [ST_STARTED],
"migrate": [ST_PREPARED],
elements.REMOVE_ACTION: [ST_CREATED],
}
CUSTOM_ATTRS = {
Expand Down Expand Up @@ -192,6 +194,42 @@ 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
return self.state in [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})


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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below is all duplicated code, please create a method for this like _allocate(self, host)


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.action_destroy()
self.element = bestHost.createElement("external_network", parent=None, attrs=attrs, ownerElement=self)
self.setState(ST_STARTED)
self.triggerConnectionStart()


def readyToConnect(self):
return bool(self.element)

Expand Down
68 changes: 65 additions & 3 deletions backend/tomato/elements/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>

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
from ..lib.util import upload
import time
import urllib
from tomato.config import MIGRATION_TRESHOLD

ST_CREATED = "created"
ST_PREPARED = "prepared"
Expand All @@ -47,6 +49,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 = {
Expand Down Expand Up @@ -237,6 +240,47 @@ def after_start(self):
def after_upload_use(self):
self.custom_template = True
self.save()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if self.state == ST_CREATED: return

def try_migrate(self):


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)
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.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=attrs, ownerElement=self)

#Kill old element on old host
self.action_destroy()

#Set new element and save it
self.element = new_el
self.save()

for iface in self.getChildren():
iface.try_migrate()
self.element.action("prepare")

self.setState(ST_PREPARED, True)

upload(bestHost.grantUrl(new_el.action("upload_grant"),"upload"),self.name+"_tmp_image.tar.gz")
new_el.action("upload_use")



def upcast(self):
return self
Expand Down Expand Up @@ -297,13 +341,31 @@ def _remove(self):
self.element = None
self.save()

def checkMigrate(self):
return self.state in [ST_CREATED,ST_PREPARED]

def try_migrate(self):

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)

self.element.remove()
self.element = element
self.save()

def readyToConnect(self):
return self.state == ST_STARTED

def upcast(self):
return self


class ConnectingElement:
def getLocationData(self, maxDepth=3):
"""
Expand Down
2 changes: 2 additions & 0 deletions backend/tomato/elements/repy.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ def action_destroy(self):
self.element = None
self.setState(generic.ST_CREATED, True)




class Repy_Interface(generic.VMInterface):
TYPE = "repy_interface"
Expand Down
52 changes: 52 additions & 0 deletions backend/tomato/elements/tinc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -34,6 +35,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 = {
Expand Down Expand Up @@ -225,6 +227,31 @@ def action_start(self):
self._parallelChildActions(self._childsByState()[ST_PREPARED], "start")
self.setState(ST_STARTED)


def checkMigrate(self):
return self._childsByState()[ST_PREPARED] != [] or self._childsByState()[ST_CREATED] != []

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):
return self

Expand All @@ -249,6 +276,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 = {
Expand Down Expand Up @@ -335,6 +363,30 @@ def action_stop(self):
self.element.action("stop")
self.setState(ST_PREPARED, True)

def checkMigrate(self):
return self.state in [ST_CREATED,ST_PREPARED]

def try_migrate(self):

if self.state in [ST_CREATED]: return

hPref, sPref = self.getLocationPrefs()


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,elementTypes=["tinc"], hostPrefs=hPref, sitePrefs=sPref)

if bestPref > hostScore*MIGRATION_TRESHOLD:
return


self.action_destroy()
self.element = bestHost.createElement(self.remoteType(), parent=None, attrs=attrs, ownerElement=self)
self.save()
self.setState(ST_PREPARED, True)

def upcast(self):
return self

Expand Down
27 changes: 27 additions & 0 deletions backend/tomato/elements/udp.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
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):
element = models.ForeignKey(host.HostElement, null=True, on_delete=models.SET_NULL)
Expand All @@ -32,6 +34,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 = {
Expand Down Expand Up @@ -111,6 +114,30 @@ def action_stop(self):
self.element.action("stop")
self.setState(ST_PREPARED, True)

def checkMigrate(self):
return self.state in [ST_CREATED,ST_PREPARED]


def try_migrate(self):

if self.state in [ST_CREATED]: return

host_ = host.select(elementTypes=[self.remoteType()])

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,elementTypes=[self.remoteType()])

if bestPref > hostScore*MIGRATION_TRESHOLD:
return


self.action_destroy()
self.element = bestHost.createElement(self.remoteType(), parent=None, attrs=attrs, ownerElement=self)
self.save()
self.setState(ST_PREPARED, True)

def upcast(self):
return self

Expand Down