Hi,

I have just committed a patch that addresses your comments. It also 
enhances it enough to allow running OSv with block and networking devices 
or firecracker. So once we have other 3 outstanding patches reviewed and 
merged we should have full firecracker support and be able to test it using 
this latest version the scripts/firecracker.py.

On Sunday, March 3, 2019 at 10:26:02 AM UTC-5, Waldek Kozaczuk wrote:
>
> 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]> 
>> 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]>
>>> ---
>>>  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].
>>> 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.

Reply via email to