I will definitely be sending a follow-up patch to address your concerns as well as support block and networking devices.
On Sunday, March 3, 2019 at 4:34:29 AM UTC-5, Nadav Har'El wrote: > > > On Fri, Feb 22, 2019 at 4:15 PM Waldemar Kozaczuk <[email protected] > <javascript:>> wrote: > >> This patch adds simple Python script that allows >> booting OSv loader.elf on firecracker. >> >> It also automates process of downloading and installing >> firecracker. Evenntually it might be incorporated >> into scripts/run.py >> > > I committed your patch, but have a few comments below for your > consideration for future incremental patches. > Thanks! > > >> Signed-off-by: Waldemar Kozaczuk <[email protected] <javascript:>> >> --- >> scripts/firecracker.py | 126 +++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 126 insertions(+) >> create mode 100755 scripts/firecracker.py >> >> diff --git a/scripts/firecracker.py b/scripts/firecracker.py >> new file mode 100755 >> index 00000000..bed4cf58 >> --- /dev/null >> +++ b/scripts/firecracker.py >> @@ -0,0 +1,126 @@ >> +#!/usr/bin/env python >> +# >> +# pip install requests-unixsocket >> > > > I had an annoying Python problem that's not related to your code, of > course, but maybe other people will encounter too. > Trying to run firecracker.py I got Python errors complaining that urllib3 > is trying to use ".util.queue" and it's missing. > Or something like that. Took my a while to figure out that my urllib3, > which in the past I got from some manual > "pip install", was somehow broken. I had to manually remove it, and > install from Fedora's package: > > # rm -r /usr/lib/python2.7/site-packages/urllib3 > # dnf install python2-urllib > > I don't know why this happens, but if someone else has the same problem on > Fedora 29, you can save a few minutes of frustration by doing the above. > > >> +import sys >> +import os >> +import stat >> +import json >> +import subprocess >> +import time >> +from os.path import expanduser >> +from datetime import datetime >> +import requests_unixsocket >> + >> + >> +class ApiClient(object): >> + def __init__(self, domain_socket_path): >> + self.socket_path = domain_socket_path >> + self.session = requests_unixsocket.Session() >> + >> + def api_socket_url(self, path): >> + return "http+unix://%s%s" % (self.socket_path, path) >> + >> + def make_put_call(self, path, request_body): >> + url = self.api_socket_url(path) >> + res = self.session.put(url, data=json.dumps(request_body)) >> + print("%s: %s" % (path, res.status_code)) >> + if res.status_code != 204: >> + print(res.text) >> + return res.status_code >> + >> + def create_instance(self, kernel_image_path, cmdline): >> + self.make_put_call('/boot-source', { >> + 'kernel_image_path': kernel_image_path, >> + 'boot_args': cmdline >> + }) >> + >> + def start_instance(self): >> + self.make_put_call('/actions', { >> + 'action_type': 'InstanceStart' >> + }) >> + >> + def configure_logging(self): >> + self.make_put_call('/logger', { >> + "log_fifo": "log.fifo", >> + "metrics_fifo": "metrics.fifo", >> + "level": "Info", >> + "show_level": True, >> + "show_log_origin": True >> + }) >> + >> + >> +def print_time(msg): >> + now = datetime.now() >> + print("%s: %s" % (now.strftime('%H:%M:%S.%f'), msg)) >> + >> + >> +# Check if firecracker is installed >> +home_dir = expanduser("~") >> +firecracker_path = os.path.join(home_dir, '.firecracker/firecracker') >> > > Personally I would prefer that instead of this appearing in my home > directory, we would just put firecracker in the current directory, i.e., > the OSv build directory. > It's just 6MB, and if you "strip" it (we should. I don't know why it isn't > stripped by default!), it's just 2MB. Nobody will complain that each OSv > build directory will have a copy of that 2MB. > > So you can honor FIRECRACKER_PATH below to allow a user to set a fixed > location, but I'd personally prefer the default to be "." (or > "./firecracker" or whatever it needs to be). > > > +if os.environ.get('FIRECRACKER_PATH'): >> + firecracker_path = os.environ.get('FIRECRACKER_PATH') >> + >> +# And offer to install if not found >> +if not os.path.exists(firecracker_path): >> + download_url = ' >> https://github.com/firecracker-microvm/firecracker/releases/download/v0.14.0/firecracker-v0.14.0 >> ' >> + answer = raw_input("Firecracker executable has not been found under >> %s. " >> + "Would you like to download it from %s and place >> it under %s? [y|Y]" % >> > > "y/Y"? That's like an offer I cannot refuse :-) > Looking at the code below, I guess you meant "y/N"? > > >> + (firecracker_path, download_url, >> firecracker_path)) >> + if answer.capitalize() != 'Y': >> > + print("Firecracker not available. Exiting ...") >> + sys.exit(-1) >> + >> + directory = os.path.dirname(firecracker_path) >> + if not os.path.exists(directory): >> + os.mkdir(directory) >> + subprocess.call(['wget', download_url, '-O', firecracker_path]) >> + os.chmod(firecracker_path, stat.S_IRUSR | stat.S_IXUSR) >> + >> +# Firecracker is installed so lets start >> +print_time("Start") >> +socket_path = '/tmp/firecracker.socket' >> + >> +# Delete socker file if exists >> > > socket > > +if os.path.exists(socket_path): >> + os.unlink(socket_path) >> + >> +# Start firecracker process to communicate over specified UNIX socker >> file >> > > socket > > +firecracker = subprocess.Popen([firecracker_path, '--api-sock', >> socket_path], >> + stdin=subprocess.PIPE, >> stdout=sys.stdout, >> + stderr=subprocess.STDOUT) >> + >> +# Prepare arguments we are going to pass when creating VM instance >> +dirname = os.path.dirname(os.path.abspath(__file__)) >> +kernel_path = os.path.join(dirname, >> '../build/release/loader-stripped.elf') >> + >> +if len(sys.argv) > 1: >> + cmdline = sys.argv[1] >> +else: >> + with open(os.path.join(dirname, '../build/release/cmdline'), 'r') as >> f: >> + cmdline = f.read() >> + >> +# Create API client and make API calls >> +client = ApiClient(socket_path.replace("/", "%2F")) >> + >> +try: >> + # Very often on the very first run firecracker process >> + # is not ready yet to accept calls over socket file >> + # so we poll existence of this file as an good >> + # enough indicator of firecracker readyness >> + while not os.path.exists(socket_path): >> + time.sleep(0.01) >> + print_time("Firecracker ready") >> + >> + client.create_instance(kernel_path, cmdline) >> + print_time("Created OSv VM") >> + >> + client.start_instance() >> + print_time("Booted OSv VM") >> +except Exception as e: >> + print("Failed to run OSv on firecracker due to: ({0}): {1} >> !!!".format(e.errno, e.strerror)) >> + firecracker.kill() >> + exit(-1) >> + >> +print_time("Waiting for firecracker process to terminate") >> +firecracker.wait() >> +print_time("End") >> > > In my case, where I didn't apply some of your patches yet so OSv doesn't > really work with firecracker, I didn't get an exception above, but got: > > 11:30:12.743018: Created OSv VM > 2019-03-03T11:30:12.748831329 [anonymous-instance:ERROR:vmm/src/ > sigsys_handler.rs:70] Shutting down VM after intercepting a bad syscall > (131). > 2019-03-03T11:30:12.748820490 [anonymous-instance:ERROR:vmm/src/ > lib.rs:1206] Failed to log metrics while stopping: Logger was not > initialized. > 2019-03-03T11:30:12.748871644 [anonymous-instance:ERROR:vmm/src/ > sigsys_handler.rs:76] Failed to log metrics while stopping: Logger was > not initialized. > /actions: 204 > 11:30:12.749496: Booted OSv VM > 11:30:12.749533: Waiting for firecracker process to terminate > 11:30:12.757930: End > > I can understand it's some sort of error, but it's not very clear what it > means. > Anyway, not critical - it's more important that it works *with* your > patches to make it work :-) > > -- >> 2.19.1 >> >> -- >> You received this message because you are subscribed to the Google Groups >> "OSv Development" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
