Controller side unique node name allocation. Ref #541.

This commit is contained in:
grossmj committed 2016-06-11 17:31:30 -06:00
1 parent 6cd136b423
commit 2bde02d459
11 files changed
+128 -47

No files matched your search

+80 -2
View File
@@ -54,6 +54,7 @@ class Project:
self.path = path
self._computes = set()
self._allocated_node_names = set()
self._nodes = {}
self._links = {}
@@ -105,15 +106,89 @@ class Project:
def add_compute(self, compute):
self._computes.add(compute)
def allocate_node_name(self, base_name):
"""
Allocates a new unique name for a node in this project.
:param base_name: base name for the node which will be completed with a unique number.
:returns: allocated name or None if one could not be found
"""
if '{0}' in base_name or '{id}' in base_name:
# base name is a template, replace {0} or {id} by an unique identifier
for number in range(1, 1000000):
name = base_name.format(number, id=number)
if name not in self._allocated_node_names:
self._allocated_node_names.add(name)
return name
else:
if base_name not in self._allocated_node_names:
return base_name
# base name is not unique, let's find a unique name by appending a number
for number in range(1, 1000000):
name = base_name + str(number)
if name not in self._allocated_node_names:
self._allocated_node_names.add(name)
return name
return None
def remove_allocated_node_name(self, name):
"""
Removes an allocated node name
:param name: allocated node name
"""
if name in self._allocated_node_names:
self._allocated_node_names.remove(name)
def update_allocated_node_name(self, name):
"""
Updates a node name
:param name: new node name
"""
self.remove_allocated_node_name(name)
self._allocated_node_names.add(name)
def has_allocated_node_name(self, name):
"""
Returns either a node name is already allocated or not.
:param name: node name
:returns: boolean
"""
if name in self._allocated_node_names:
return True
return False
def update_node_name(self, node, new_name):
if new_name and node.name != new_name:
if self.has_allocated_node_name(new_name):
raise aiohttp.web.HTTPConflict(text="{} node name is already allocated in this project".format(new_name))
self.update_allocated_node_name(new_name)
return True
return False
@asyncio.coroutine
def add_node(self, compute, node_id, **kwargs):
def add_node(self, compute, name, node_id, **kwargs):
"""
Create a node or return an existing node
:param kwargs: See the documentation of node
"""
if node_id not in self._nodes:
node = Node(self, compute, node_id=node_id, **kwargs)
name = self.allocate_node_name(name)
if not name:
raise aiohttp.web.HTTPConflict(text="A node name could not be allocated (node limit reached?)")
node = Node(self, compute, name, node_id=node_id, **kwargs)
if compute not in self._project_created_on_compute:
# For a local server we send the project path
if compute.id == "local":
@@ -137,7 +212,9 @@ class Project:
@asyncio.coroutine
def delete_node(self, node_id):
node = self.get_node(node_id)
self.remove_allocated_node_name(node.name)
del self._nodes[node.id]
yield from node.destroy()
self.controller.notification.emit("node.deleted", node.__json__())
@@ -194,6 +271,7 @@ class Project:
def close(self):
for compute in self._project_created_on_compute:
yield from compute.post("/projects/{}/close".format(self._id))
self._allocated_node_names.clear()
@asyncio.coroutine
def commit(self):