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

Fogify integration #8

Open
wants to merge 1 commit into
base: fogify
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 50 additions & 64 deletions ether/converter/fogify.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,78 +2,64 @@
from typing import Dict, NamedTuple, List

from ether.topology import Topology
# TODO: import fogify model and classes instead
from ether.util import to_size_string
from FogifySDK import FogifySDK
from ether.core import Node

class Placement(object):
"""
A small class for placement policy definition.
The services (services names) should be described in the initial docker-compose file.
"""

class FogifyModel(NamedTuple):
nodes: List[Dict]
networks: List[Dict]
topology: List[Dict]
def __init__(self):
self.topology = dict()

def deploy_service_to_node(self, service_name: str, node: Node):
self.topology[node.name] = service_name

def serialize(fogify: FogifyModel, yaml_file):
# TODO
pass
def get_nodes(self) -> list:
return [node_name for node_name in self.topology]

def topology_to_fogify(topology: Topology, fogify: FogifySDK, placement: Placement) -> FogifySDK:

def topology_to_fogify(topology: Topology) -> FogifyModel:
nodes = list()
networks = defaultdict(dict)
fogify_topology = list()

# Node translation from ether to Fogify model
for n in topology.get_nodes():
nodes.append({
'name': n.name,
'capabilities': {
'processors': {
'cores': int(n.capacity.cpu_millis / 1000),
'clock': 0, # TODO
},
'memory': to_size_string(n.capacity.memory, 'G'),
# TODO: ether has more capabilities hidden in labels (GPU, TPU, etc.)
}
})

# TODO: need to clarify fogify internet network
# this is kinda roundabout, as we're reconstructing the original higher-level 'Cloudlet', 'LANCell', etc structure
for link in topology.get_links():
if link.tags.get('type') == 'downlink':
name = link.tags['name'][5:] # cut off 'down_' prefix of uplink
networks[name]['name'] = name
networks[name]['uplink'] = {
'bandwidth': f'{link.bandwidth}Mbps',
'latency': {
'delay': 0,
},
'drop': '0.1%', # TODO: QoS modelling is still quite rudimentary in ether
}

for edge in topology.in_edges([link]):
connection = topology.get_edge_data(edge[0], edge[1])['connection']
networks[name]['downlink']['latency']['delay'] = float(connection.get_mode_latency())
break # should only be one edge
if n.name in placement.get_nodes():
num_of_cores = int(n.capacity.cpu_millis / 1000)

elif link.tags.get('type') == 'uplink':
name = link.tags['name'][3:] # cut off 'up_' prefix of uplink
networks[name]['name'] = name
networks[name]['downlink'] = {
'bandwidth': f'{link.bandwidth}Mbps',
'latency': {
'delay': 0,
},
'drop': '0.1%', # TODO: QoS modelling is still quite rudimentary in ether
}
fogify.add_node(n.name,
cpu_cores=num_of_cores,
cpu_freq= 1000, # TODO update the frequency
memory=to_size_string(n.capacity.memory, 'G'))
# the limit of memory is 7 due to the PC's limitation power
# TODO: ether has more capabilities hidden in labels (GPU, TPU, etc.)
fogify.add_network("ether_net", bidirectional={}) # Maybe we need to describe the general network characteristics

for edge in topology.out_edges([link]):
connection = topology.get_edge_data(edge[0], edge[1])['connection']
networks[name]['downlink']['latency']['delay'] = float(connection.get_mode_latency())
break # should only be one edge

# TODO: internet

# TODO: collapse uplink/downlink to 'bidirectional' (fogify concept) if uplink == downlink with all QoS values
for n in topology.get_nodes():
for j in topology.get_nodes():
if type(n) == Node and type(j) == Node and n != j \
and n.name in placement.get_nodes() and j.name in placement.get_nodes(): # introduce link connection between compute nodes
bandwidth = min([k.bandwidth for k in topology.route(n, j).hops])
latency = round(float(topology.route(n, j).rtt/2), 2)
fogify.add_link(
"ether_net",
from_node=n.name,
to_node=j.name,
bidirectional=False,
properties={
'latency': {
'delay': f'{latency}ms',
},
'bandwidth': f'{bandwidth}Mbps'
}
)
for node_name in placement.topology:
fogify.add_deployment_node(
node_name,
placement.topology[node_name], # How can we introduce services in ether?
node_name,
networks=["ether_net"]
)

model = FogifyModel(nodes, list(networks.values()), fogify_topology)
print(model)
return model
return fogify
35 changes: 20 additions & 15 deletions examples/fogify/fogify.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import matplotlib.pyplot as plt
import yaml
import os

from ether.converter.fogify import topology_to_fogify
from FogifySDK import FogifySDK
import matplotlib.pyplot as plt
from ether.converter.fogify import topology_to_fogify, Placement
from ether.scenarios.industrialiot import IndustrialIoTScenario
from ether.topology import Topology
from ether.vis import draw_basic

if __name__ == '__main__':
t = Topology()

scen = IndustrialIoTScenario(1)
scen.materialize(t)

fogify_model = topology_to_fogify(t)
ether_topology = Topology()
dir_path = os.path.dirname(os.path.realpath(__file__))
docker_compose_file = dir_path+"/simple-docker-compose.yaml"
fogify = FogifySDK("http://contorller:5000", docker_compose_file)
scen = IndustrialIoTScenario()
scen.materialize(ether_topology)

print(yaml.dump({'x-fogify': {
'nodes': fogify_model.nodes,
'networks': fogify_model.networks,
'topology': fogify_model.topology,
}}))
# determine the placement
# for testing reasons we will deploy the same service ("test") on every node
placement = Placement()
for node in ether_topology.get_nodes():
placement.deploy_service_to_node("test", node)

draw_basic(t)
# Generate the fogify model
fogify_model = topology_to_fogify(ether_topology, fogify, placement)
fogify_model.upload_file(False) # with False as parameter, the function generates the fogified-docker-compose file
# here we can deploy the generated mode with fogify.deploy() function
draw_basic(ether_topology)
fig = plt.gcf()
fig.set_size_inches(18.5, 10.5)
plt.show() # display
5 changes: 5 additions & 0 deletions examples/fogify/simple-docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
test:
image: busybox:latest
command: top
version: '3.7'
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ scikit-learn~=0.23.2
setuptools~=50.3.0
pyvis~=0.1.8.2
PyYAML
FogifySDK