Skip to content

Commit

Permalink
add multiple nodes to network in one deployment (#1558)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-motawea committed Oct 29, 2020
1 parent a545a16 commit 2a0b03a
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 18 deletions.
32 changes: 14 additions & 18 deletions jumpscale/packages/tfgrid_solutions/chats/kubernetes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import uuid
from textwrap import dedent

from jumpscale.loader import j
from jumpscale.sals.chatflows.chatflows import GedisChatBot, chatflow_step
from jumpscale.sals.reservation_chatflow import DeploymentFailed, deployer, deployment_context, solutions

Expand Down Expand Up @@ -82,25 +82,21 @@ def public_key_get(self):
@deployment_context()
def ip_selection(self):
self.md_show_update("Deploying Network on Nodes....")
# deploy network on nodes
for i in range(len(self.selected_nodes)):
node = self.selected_nodes[i]
pool_id = self.selected_pool_ids[i]
result = deployer.add_network_node(
self.network_view.name,
node,
pool_id,
self.network_view,
bot=self,
owner=self.solution_metadata.get("owner"),
)
if not result:
continue
result = deployer.add_multiple_network_nodes(
self.network_view.name,
[node.node_id for node in self.selected_nodes],
self.selected_pool_ids,
self.network_view,
self,
owner=self.solution_metadata.get("owner"),
)
if result:
for wid in result["ids"]:
success = deployer.wait_workload(wid, self, breaking_node_id=node.node_id)
success = deployer.wait_workload(wid, self)
if not success:
raise DeploymentFailed(f"Failed to add node {node.node_id} to network {wid}", wid=wid)
self.network_view = self.network_view.copy()
workload = j.sals.zos.get().workloads.get(wid)
raise DeploymentFailed(f"Failed to add node {workload.info.node_id} to network {wid}", wid=wid)
self.network_view = self.network_view.copy()

# get ip addresses
self.ip_addresses = []
Expand Down
71 changes: 71 additions & 0 deletions jumpscale/sals/reservation_chatflow/deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,46 @@ def add_node(self, node, pool_id):
j.sals.zos.get().network.add_node(network, node.node_id, str(subnet), pool_id)
return network

def add_multiple_nodes(self, node_ids, pool_ids):
used_ip_ranges = set()
existing_nodes = []
for workload in self.network_workloads:
used_ip_ranges.add(workload.iprange)
for peer in workload.peers:
used_ip_ranges.add(peer.iprange)
if workload.info.node_id in node_ids:
existing_nodes.append(workload.info.node_id)

if len(existing_nodes) == len(node_ids):
return

node_to_range = {}
node_to_pool = {}
for idx, node_id in enumerate(node_ids):
if node_id in existing_nodes:
continue
node_to_pool[node_id] = pool_ids[idx]
network_range = netaddr.IPNetwork(self.iprange)
for _, subnet in enumerate(network_range.subnet(24)):
subnet = str(subnet)
if subnet not in used_ip_ranges:
node_to_range[node_id] = subnet
used_ip_ranges.add(subnet)
break
else:
raise StopChatFlow("Failed to find free network")

zos = j.sals.zos.get()
network = zos.network.create(self.iprange, self.name)
node_workloads = {}
for net_workload in self.network_workloads:
node_workloads[net_workload.info.node_id] = net_workload
network.network_resources = list(node_workloads.values()) # add only latest network resource for each node

for node_id, node_range in node_to_range.items():
zos.network.add_node(network, node_id, node_range, node_to_pool[node_id])
return network

def add_access(self, node_id=None, use_ipv4=True, pool_id=None):
if node_id and not pool_id:
raise StopChatFlow("You must specify the pool id if you specify the node id")
Expand Down Expand Up @@ -811,6 +851,37 @@ def add_network_node(self, name, node, pool_id, network_view=None, bot=None, **m
parent_id = ids[-1]
return {"ids": ids, "rid": ids[0]}

def add_multiple_network_nodes(self, name, node_ids, pool_ids, network_view=None, bot=None, **metadata):
if not network_view:
network_view = NetworkView(name)
network = network_view.add_multiple_nodes(node_ids, pool_ids)
if not network:
return

parent_id = network_view.network_workloads[-1].id
ids = []
node_workloads = {}
# deploy only latest resource generated by zos sal for each node
for workload in network.network_resources:
node_workloads[workload.info.node_id] = workload
dry_run_name = uuid.uuid4().hex
with NetworkView.dry_run_context(dry_run_name):
network_view.dry_run(
dry_run_name,
list(node_workloads.keys()),
[w.info.pool_id for w in node_workloads.values()],
bot,
breaking_node_ids=node_ids,
)
for workload in node_workloads.values():
workload.info.reference = ""
workload.info.description = j.data.serializers.json.dumps({"parent_id": parent_id})
metadata["parent_network"] = parent_id
workload.info.metadata = self.encrypt_metadata(metadata)
ids.append(j.sals.zos.get().workloads.deploy(workload))
parent_id = ids[-1]
return {"ids": ids, "rid": ids[0]}

def select_network(self, bot, network_views=None):
network_views = network_views or self.list_networks()
if not network_views:
Expand Down

0 comments on commit 2a0b03a

Please sign in to comment.