Skip to content
Open
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
3a8dd2a
add fission class
mdamek Jun 6, 2020
78605d1
add run fission script
mdamek Jun 6, 2020
c8c1012
add init and lint
mdamek Jun 6, 2020
5443c4a
wip
mdamek Jun 6, 2020
25f3f0e
add create function
mdamek Jun 6, 2020
fd24ea3
Add making request
mdamek Jun 6, 2020
d4f2687
linting
mdamek Jun 6, 2020
a1edfae
[fission_start_work] Fission k8s deployment written using python scripts
xylini Jun 18, 2020
337314c
edit gitignore
mdamek Jun 20, 2020
42de6c7
manage fission start config
Jun 21, 2020
3f51a5b
add minio
mdamek Jun 20, 2020
6148f76
add packing
mdamek Jun 21, 2020
eb93174
deploy fission function
mdamek Jun 21, 2020
e6e6286
new benchmark
mdamek Jun 21, 2020
d6e9894
cleanup and fix cache error
mdamek Jun 26, 2020
3caaa12
remove unnecessary benchmark
mdamek Jun 26, 2020
341dae3
fix package code directory
mdamek Jun 26, 2020
f434a2b
add handler
mdamek Jun 29, 2020
954c5a4
delpoy function
mdamek Jun 30, 2020
68afc9d
add request invoke
mdamek Jun 30, 2020
460ca18
add requirements handling
mdamek Jun 30, 2020
77004ff
extend handler
mdamek Jul 1, 2020
0ddaded
fix bugs with shutdown
mdamek Jul 1, 2020
d0775cd
[feature_fission] cold start and some comments added
xylini Jul 1, 2020
7d451e9
add logging
mdamek Jul 1, 2020
335984b
Merge branch 'feature_fission' of https://github.com/mcopik/serverles…
mdamek Jul 1, 2020
a6415e1
cold_start fix
mdamek Jul 1, 2020
e88c255
linting
mdamek Jul 1, 2020
4276602
add minio usage
mdamek Jul 2, 2020
25de6ea
lint wrappers
mdamek Jul 2, 2020
d6894c6
lint fission
mdamek Jul 3, 2020
15922f7
s3 comment fix
mdamek Jul 3, 2020
5e816bf
ignore missing types
mdamek Jul 3, 2020
f013a68
[feature_fission] nodejs handler added
xylini Jul 3, 2020
5ad80aa
[feature_fission] space after coma
xylini Jul 3, 2020
36c03a6
add readme
mdamek Jul 3, 2020
9e1cd1c
fix pr 7 comments
mdamek Jul 7, 2020
f31b192
linting
mdamek Jul 7, 2020
9933975
[feature_fission] fission installation through install.py
xylini Jul 14, 2020
16ecf04
Merge branch 'feature_fission' of https://github.com/mcopik/serverles…
xylini Jul 14, 2020
4a4403b
[feature_fission] minio storage added to fission nodejs
xylini Jul 14, 2020
6846a47
Merge branch 'master' into feature_fission
mcopik Sep 23, 2022
4a83600
Merge branch 'master' into feature_fission
mcopik Sep 22, 2023
b3818fd
Merge remote-tracking branch 'origin/master' into feature_fission
mcopik Jun 14, 2024
d732d64
[fission] Linting
mcopik Jun 14, 2024
c0ffa55
WORKING
prajinkhadka Jul 18, 2024
501f2c6
WIP -> Main Functionality is working. Need to optimize the code and r…
prajinkhadka Aug 6, 2024
9106337
WIP -> Main Functionality is working. Need to optimize the code and r…
prajinkhadka Aug 6, 2024
25d98dd
WIP -> Pass Minio storage config as env variables.
prajinkhadka Aug 6, 2024
fcf22cc
WIP -> Do not change funcion.py anywhere
prajinkhadka Aug 6, 2024
af2ca47
Fission Completed Testing on Python3.8
prajinkhadka Aug 9, 2024
46a6f07
Fission Implementation complted.
prajinkhadka Aug 12, 2024
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,6 @@ dmypy.json
sebs-*
# cache
cache

# ide
.vscode
31 changes: 31 additions & 0 deletions benchmarks/wrappers/fission/nodejs/handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const path = require('path'), fs = require('fs');
Copy link
Collaborator

Choose a reason for hiding this comment

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

For all wrappers, we need to compare them against newest implementation in OpenWhisk/Knative - there have been changes. In particular, storage triggers received few bugfixes.


exports.handler = async function(context) {
var body = JSON.stringify(context.request.body);
var unbody = JSON.parse(body);
var func = require('./function/function');
var begin = Date.now()/1000;
var start = process.hrtime();
var ret = await func.handler(unbody);
var elapsed = process.hrtime(start);
var end = Date.now()/1000;
var micro = elapsed[1] / 1e3 + elapsed[0] * 1e6;
var is_cold = false;
var fname = path.join('/tmp','cold_run');
if(!fs.existsSync(fname)) {
is_cold = true;
fs.closeSync(fs.openSync(fname, 'w'));
}

return {
status: 200,
body: JSON.stringify({
begin,
end,
compute_time: micro,
results_time: 0,
result: ret,
is_cold
})
};
};
Comment on lines +3 to +31
Copy link

Choose a reason for hiding this comment

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

Consider adding error handling.

The function currently lacks error handling. Consider wrapping the logic in a try-catch block to handle potential errors gracefully.

exports.handler = async function(context) {
+  try {
    var body = JSON.stringify(context.request.body);
    var unbody = JSON.parse(body);
    var func = require('./function/function');
    var begin = Date.now()/1000;
    var start = process.hrtime();
    var ret = await func.handler(unbody);
    var elapsed = process.hrtime(start);
    var end = Date.now()/1000;
    var micro = elapsed[1] / 1e3 + elapsed[0] * 1e6;
    var is_cold = false;
    var fname = path.join('/tmp','cold_run');
    if(!fs.existsSync(fname)) {
        is_cold = true;
        fs.closeSync(fs.openSync(fname, 'w'));
    }

    return {
        status: 200,
        body: JSON.stringify({
            begin,
            end,
            compute_time: micro,
            results_time: 0,
            result: ret,
            is_cold
        })
    };
+  } catch (error) {
+    return {
+      status: 500,
+      body: JSON.stringify({ error: error.message })
+    };
+  }
};
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
exports.handler = async function(context) {
var body = JSON.stringify(context.request.body);
var unbody = JSON.parse(body);
var func = require('./function/function');
var begin = Date.now()/1000;
var start = process.hrtime();
var ret = await func.handler(unbody);
var elapsed = process.hrtime(start);
var end = Date.now()/1000;
var micro = elapsed[1] / 1e3 + elapsed[0] * 1e6;
var is_cold = false;
var fname = path.join('/tmp','cold_run');
if(!fs.existsSync(fname)) {
is_cold = true;
fs.closeSync(fs.openSync(fname, 'w'));
}
return {
status: 200,
body: JSON.stringify({
begin,
end,
compute_time: micro,
results_time: 0,
result: ret,
is_cold
})
};
};
exports.handler = async function(context) {
try {
var body = JSON.stringify(context.request.body);
var unbody = JSON.parse(body);
var func = require('./function/function');
var begin = Date.now()/1000;
var start = process.hrtime();
var ret = await func.handler(unbody);
var elapsed = process.hrtime(start);
var end = Date.now()/1000;
var micro = elapsed[1] / 1e3 + elapsed[0] * 1e6;
var is_cold = false;
var fname = path.join('/tmp','cold_run');
if(!fs.existsSync(fname)) {
is_cold = true;
fs.closeSync(fs.openSync(fname, 'w'));
}
return {
status: 200,
body: JSON.stringify({
begin,
end,
compute_time: micro,
results_time: 0,
result: ret,
is_cold
})
};
} catch (error) {
return {
status: 500,
body: JSON.stringify({ error: error.message })
};
}
};

42 changes: 42 additions & 0 deletions benchmarks/wrappers/fission/python/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from flask import request, jsonify, current_app

import json
import datetime
import os


def handler():
body = request.get_data().decode("utf-8")
current_app.logger.info("Body: " + body)
event = json.loads(body)
current_app.logger.info("Event: " + str(event))
begin = datetime.datetime.now()
from function import function

ret = function.handler(event)
end = datetime.datetime.now()
current_app.logger.info("Function result: " + str(ret))
log_data = {"result": ret["result"]}
if "measurement" in ret:
log_data["measurement"] = ret["measurement"]

results_time = (end - begin) / datetime.timedelta(microseconds=1)

# cold test
is_cold = False
fname = "cold_run"
if not os.path.exists(fname):
is_cold = True
open(fname, "a").close()

return jsonify(
json.dumps(
{
"begin": begin.strftime("%s.%f"),
"end": end.strftime("%s.%f"),
"results_time": results_time,
"is_cold": is_cold,
"result": log_data,
}
)
)
60 changes: 60 additions & 0 deletions benchmarks/wrappers/fission/python/storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import os
import uuid
import json
Copy link

Choose a reason for hiding this comment

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

Remove unused import.

The import statement for json is unused and should be removed to clean up the code.

- import json
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import json
Tools
Ruff

3-3: json imported but unused

Remove unused import: json

(F401)

import minio
from flask import current_app


class storage:
instance = None
client = None

def __init__(self):
file = open(os.path.join(os.path.dirname(__file__), "minioConfig.json"), "r")
minioConfig = json.load(file)
try:
self.client = minio.Minio(
minioConfig["url"],
access_key=minioConfig["access_key"],
secret_key=minioConfig["secret_key"],
secure=False,
)
except Exception as e:
current_app.logger.info(e)

@staticmethod
def unique_name(name):
name, extension = name.split(".")
return "{name}.{random}.{extension}".format(
name=name, extension=extension, random=str(uuid.uuid4()).split("-")[0]
)

def upload(self, bucket, file, filepath):
key_name = storage.unique_name(file)
self.client.fput_object(bucket, key_name, filepath)
return key_name

def download(self, bucket, file, filepath):
self.client.fget_object(bucket, file, filepath)

def download_directory(self, bucket, prefix, path):
objects = self.client.list_objects_v2(bucket, prefix, recursive=True)
for obj in objects:
file_name = obj.object_name
self.download(bucket, file_name, os.path.join(path, file_name))

def upload_stream(self, bucket, file, bytes_data):
key_name = storage.unique_name(file)
self.client.put_object(
bucket, key_name, bytes_data, bytes_data.getbuffer().nbytes
)
return key_name

def download_stream(self, bucket, file):
data = self.client.get_object(bucket, file)
return data.read()

def get_instance():
if storage.instance is None:
storage.instance = storage()
return storage.instance
16 changes: 16 additions & 0 deletions config/fission.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"experiments": {
"update_code": false,
"update_storage": false,
"download_results": false,
"deployment": "fission",
"runtime": {
"language": "python",
"version": "3.6"
}
},
"deployment": {
"name": "fission",
"shouldShutdown": false
}
}
30 changes: 30 additions & 0 deletions config/systems.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,35 @@
"username": "docker_user"
}
}
},
"fission": {
"languages": {
"python": {
"base_images": {
"env":"fission/python-env:latest",
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should verify here that we are using the correct language versions. If the user selects Python 3.10, we should use Docker image with Python 3.10 etc.

Copy link
Collaborator

Choose a reason for hiding this comment

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

yes, that is done.,

"builder":"fission/python-builder:latest"
},
"versions": ["3.6"],
"images": [],
"username": "docker_user",
"deployment": {
"files": ["handler.py", "storage.py"],
"packages": {"minio" : "^5.0.10"}
}
},
"nodejs": {
"base_images": {
"env":"fission/node-env:latest",
"builder":"fission/node-builder:latest"
},
"versions": ["10.x", "12.x"],
"images": [],
"username": "docker_user",
"deployment": {
"files": ["handler.js"],
"packages": {"minio" : "^7.0.16"}
}
}
}
}
}
40 changes: 28 additions & 12 deletions install.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
import os
import subprocess

from tools.fission_preparation import check_if_minikube_installed, check_if_k8s_installed, check_if_helm_installed, \
check_if_fission_cli_installed, install_fission_cli

parser = argparse.ArgumentParser(description="Install SeBS and dependencies.")
parser.add_argument("--with-pypapi", action="store_true")
parser.add_argument("--with-fission", action="store_true")
args = parser.parse_args()


def execute(cmd):
ret = subprocess.run(
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True
Expand All @@ -18,19 +23,20 @@ def execute(cmd):
)
return ret.stdout.decode("utf-8")

env_dir="sebs-virtualenv"

print("Creating Python virtualenv at {}".format(env_dir))
execute("python3 -mvenv {}".format(env_dir))
# env_dir="sebs-virtualenv"
#
# print("Creating Python virtualenv at {}".format(env_dir))
# execute("python3 -mvenv {}".format(env_dir))
#
# print("Install Python dependencies with pip")
# execute(". {}/bin/activate && pip3 install -r requirements.txt".format(env_dir))
#
# print("Configure mypy extensions")
# execute(". {}/bin/activate && mypy_boto3".format(env_dir))
#
# print("Initialize git submodules")
# execute("git submodule update --init --recursive")

print("Install Python dependencies with pip")
execute(". {}/bin/activate && pip3 install -r requirements.txt".format(env_dir))

print("Configure mypy extensions")
execute(". {}/bin/activate && mypy_boto3".format(env_dir))

print("Initialize git submodules")
execute("git submodule update --init --recursive")

if args.with_pypapi:
print("Build and install pypapi")
Expand All @@ -41,3 +47,13 @@ def execute(cmd):
execute("python3 setup.py build")
execute("python3 pypapi/papi_build.py")
os.chdir(cur_dir)

if args.with_fission:
check_if_minikube_installed()
check_if_k8s_installed()
check_if_helm_installed()
try:
check_if_fission_cli_installed(throws_error=True)
except subprocess.CalledProcessError:
install_fission_cli()
check_if_fission_cli_installed()
3 changes: 3 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

[mypy-docker]
ignore_missing_imports = True

[mypy-minio]
ignore_missing_imports = True
2 changes: 1 addition & 1 deletion sebs/aws/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def add_output_bucket(
self, name: str, suffix: str = "output", cache: bool = True
) -> Tuple[str, int]:

idx = self.request_input_buckets
idx = self.request_input_buckets # are you sure?
name = "{}-{}-{}".format(name, idx + 1, suffix)
if cache:
self.request_input_buckets += 1
Expand Down
7 changes: 7 additions & 0 deletions sebs/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ def supported_language_versions(
return self._system_config[deployment_name]["languages"][language_name][
"base_images"
].keys()

def benchmark_base_images(
self, deployment_name: str, language_name: str
) -> Dict[str, str]:
return self._system_config[deployment_name]["languages"][language_name][
"base_images"
]
3 changes: 3 additions & 0 deletions sebs/fission/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .fission import Fission # noqa
from .config import FissionConfig # noqa
from .minio import Minio # noqa
50 changes: 50 additions & 0 deletions sebs/fission/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from sebs.faas.config import Config, Credentials, Resources
from sebs.cache import Cache


class FissionCredentials(Credentials):
def __init__(self):
pass

@staticmethod
def initialize(config: dict, cache: Cache) -> Credentials:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Check here how Fission deployment works for containers - maybe we need to pass Docker credentials?

Copy link
Collaborator

Choose a reason for hiding this comment

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

right now, I am more focused on code package rahtner than contaienr deployment.

return FissionCredentials()

def serialize(self) -> dict:
pass


class FissionResources(Resources):
def __init__(self):
pass

def serialize(self) -> dict:
return {}

@staticmethod
def initialize(config: dict, cache: Cache) -> Resources:
pass


class FissionConfig(Config):
name: str
cache: Cache
shouldShutdown: bool
Comment on lines +259 to +262
Copy link

Choose a reason for hiding this comment

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

Remove the shouldShutdown property if not used.

The shouldShutdown property is defined but not used anywhere in the class. Remove it if it is not needed.

class FissionConfig(Config):
    name: str
    cache: Cache
-   shouldShutdown: bool
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class FissionConfig(Config):
name: str
cache: Cache
shouldShutdown: bool
class FissionConfig(Config):
name: str
cache: Cache


def __init__(self, config: dict, cache: Cache):
self.name = config["name"]
self.shouldShutdown = config["shouldShutdown"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can completely remove the support for "shutdown" option.

self.cache = cache

@staticmethod
def initialize(config: dict, cache: Cache) -> Config:
return FissionConfig(config, cache)

def credentials(self) -> Credentials:
pass

def resources(self) -> Resources:
pass

def serialize(self) -> dict:
pass
Loading