This was used before to ensure the domain name was ASCII. However, str
does not convert to ASCII in Python 3.
Note that in config module, which sets the system domain name, the
domain is already restricted to alphanumerics, hyphen, and period.
Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
Domain name is not case sensitive, but Let's Encrypt certificate paths
use lower-case domain name.
Add an extra 1 second delay to tests that configure DynamicDNS domain.
Test: DynamicDNS functional tests are passing.
Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
After a domain name change, Let's Encrypt will restart the webserver
and could cause a connection failure.
Test: DynamicDNS functional tests are passing.
Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
Domain name is not case sensitive, but Let's Encrypt certificate paths
use lower-case domain name.
Closes: #1964.
Tests: Config functional tests passed.
Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
Closes: #2074
sunil's changes:
- Ensure that secret is not asked for a second time after creating admin user
and logging in (this happens due to discarding of old session and creating new
one).
- Ensure that this logic is not applied to user using FreedomBox images who are
not required to input the first wizard secret.
- Change the name of the session variable for readability.
Tests performed:
- Without the patch, start first boot wizard on the first browser on a
FreedomBox image (or run the file `base64 < /dev/urandom | head -c 16 | sed -e
's+$+\n+' > /var/lib/plinth/firstboot-wizard-secret`). Finish the welcome step
with first wizard secret. Then open a second browser or from another computer
visit the web interface. The first wizard secret is not asked and user can
create an admin account.
- Repeat with fresh image again with the patch. To mimic fresh image, one may
run `sudo rm -f /var/lib/plinth/plinth.sqlite3` and `echo "password" | | sudo
/freedombox/actions/users remove-user tester`. This time when a different
browser other than the one that provided the first wizard secret try to access
the account creation page, a redirection will occur to welcome page. Providing
the first wizard secret takes the user to account creation page.
- Accessing network first wizard page or internal pages on second browser also
takes one back to the welcome page.
- Accessing help pages from second browser requires login.
- Accessing account login page from second browser is allowed. After creating
the account from first browser, second browser can login and continue the
wizard.
- Clearing cookies in the middle of the wizard takes the user back to welcome
page.
- Clear cookies in the middles of the wizard. Visit the wizard, go to first boot
welcome page. Provide secret and the wizard will continue where it was left
off.
- Clear cookies in the middles of the wizard. Visit the wizard, go to first boot
welcome page. Access login page, login as admin. Then first wizard secret is
not asked. First wizard can be continued.
- On a fresh image, simply complete the first wizard. No change to earlier flow
is noticed. First wizard secret is only asked once at the beginning.
- On a fresh image, remove the file /var/lib/plinth/firstboot-wizard-secret.
First wizard can be completed without the secret.
[sunil: improvements to original patch by Kirill Schmidt]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Tested-by: Sunil Mohan Adapa <sunil@medhas.org>
When LDAP is set up but the first admin is not yet set up, some of the
users module tests fail because known admin users is deleted before other
users. A known admin user must exists to delete existing users.
Fix this by deleting a known admin user only after deleting other users
when cleaning up tests.
Tests performed on Debian stable and testing:
- All the users module unit tests pass:
- when LDAP is not set up yet
- after LDAP is set up but empty
- after first admin user has set up using the web UI
Signed-off-by: Veiko Aasa <veiko17@disroot.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
Update security_report.html text to clarify what vulnerability total
numbers mean, and give more info to learn what the vulnerabilties are.
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
[jvalleroy: Make URL a link]
Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Closes: Debian #805108.
Primary motivation is to provide swap for FreedomBox machines. On all FreedomBox
images, currently there is no swap configured. Swap on disk may not be good for
SBCs most of which use SD card for storage. We wish for processes to not get
killed when hard memory limit is reached.
Zram seems like a good solution to the problem suitable not only for SBCs but
also for desktops and bigger machines. Fedora is currently using Zram as its
default swap solution configured by the installer. Zram creates a block device
with a configured size. Writing blocks into the device compresses them and
stores them in RAM. This block device can be configured as swap among other
things. See:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/blockdev/zram.rst
Set the size of the swap to be 50% of RAM. Expected compression is about 1:2.
That means, in an average case, 25% of RAM is consumed to provide the swap
device. This results in the system being able to consume about 125% of RAM
capacity to run processes. This value is inspired by Fedora.
https://fedoraproject.org/wiki/Changes/SwapOnZRAM .
Zram based swap takes priority over disk based swap (due the priority being set
to 100). This reduces IO and improves latency on machines that already have a
swap device.
On containers, zramswap.service fails to start as it will not be possible to
insert the 'zram' kernel module from within the container. This should not cause
any further problems.
Since 'config' app is an essential app, zram-tools now becomes a hard dependency
of freedombox package.
For FreedomBox images, zram-tools will be pre-installed and pre-configured. So,
it will work on first boot. For users installing FreedomBox via apt or those
upgrading from an older version, zram-tools will be newly installed but
configuration will not be picked up until the next reboot. Restarting
zramswap.service is not done because it may not be a safe/successful operation.
systemd-zram-generator is a project that essentially does what zram-tools. It
appears to be a better implementation and we may migrate to it when it becomes
available in Debian. Migration expected to be straight forward.
Tests performed:
- Running `sudo -u plinth ./run --list-dependencies` shows zram-tools as a
dependency.
- On a container, `systemctl status zramswap.service` shows as failed.
- On a virtual machine, confirm that configuration is installed properly. Run
`./setup.py install; systemctl daemon-reload; systemctl show zramswap.service |
grep Environment`.
- On a virtual machine, ensure that you have more than 512MiB or RAM. Then
restart zramswap.service. This should create a swap space of 50% of RAM
capacity. Confirm with `free` and `zramswap status`.
- Restarting the VM retains the swap that has been setup.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
Helps: #664.
Currently, logs are written to disk twice, once by journald and once by rsyslog.
rsyslog may log to multiple locations depending on the type of the log. To
reduce disk I/O, disable rsyslog and rely solely on systemd journal.
Place the code in config module as there is no better place for it currently
without creating a new module. Can be sorted later.
The following files under /var/log/ are no longer populated on FreedomBox. They
will be rotated away over a few days. Use journalctl instead to view the
messages:
- syslog
- messages*
- auth.log*
- debug*
- daemon.log
- kern.log
- lpr.log
- mail.log
- mail.info
- mail.warn
- mail.err
- user.log
Tests performed:
- On a machine with rsyslog running, run ./setup.py install and start FreedomBox
service. This triggers the config app's setup. rsyslog is disabled and masked.
systemd-journald is restarted.
- Even when rsyslog is unmaked and enabled manually, systemd journald does not
forward message to syslog anymore.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
Tests:
- Disable fail2ban. When version number of the app is incremented, setup is run,
fail2ban is reloaded but fail2ban is not enabled after setup.
- Disable fail2ban. When app is uninstalled and FreedomBox is run, setup is
performed and fail2ban is enabled.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
Since security app manages fail2ban, it makes sense to set the default
configuration in this app.
Tests performed:
- `./setup.py install` installs the file in the correct place.
- Only 10 incorrect SSH login attempts as noticed in the fail2ban log will
result in ban.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
- This allows disabling syslog daemons.
- Fall back to using file based monitoring for Apache.
Tests performed:
- Before and after the patch, connecting via SSH and typing in incorrect
password leads to a entry in fail2ban.log. 10 incorrect attempts result in a 10
minute ban.
- Before and after the patch, typing in incorrect password for radicale leads to
a entry in fail2ban.log. 10 incorrect attempts result in a 10 minute ban.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
Add the debian-deluged user to the freedombox-share group *before* running
app setup. The app setup process restarts the deluged daemon
after which the process has correct group ownerships.
Tests done in Debian stable and testing dev containers:
- After installing the deluge app, checked from /proc/--process-id--/status that
the deluged daemon process has the freedombox-share group.
Signed-off-by: Veiko Aasa <veiko17@disroot.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Add nslcd.service as a dependency to the services that depend on users
and groups defined in LDAP. deluged, mldonkey-server, syncthing@syncthing
and transmission-daemon services depend on freedombox-share LDAP group.
Closes#2061
Tests done with apps deluge, mldonkey, syncthing and transmission,
in both debian stable and testing dev containers, after applying changes:
- After installing an app and after reboot, the daemon user is a member
of the freedombox-share group.
- Checked with the `systemctl show` command that nslcd.service is added to
After=... dependencies.
- All the functional tests pass (in Debian stable, closed manually
the syncthing usage reporting form - #2059).
Signed-off-by: Veiko Aasa <veiko17@disroot.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Sunil:
- Minor update to the TURN server message.
- Drop updating the FAQ link since there may not be much time for translators to
translate the changed message due to our current release schedule. The old link
still works.
Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net>
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
- Matrix Synapse will automatically pick up the locally installed coturn server
during its installation. This handles only the case where coturn is installed
and configured with a valid TLS domain name before matrix-synapse is installed.
- Allow overriding STUN/TURN config. Matrix Synapse uses the local coturn
server's configuration by default. However, an administrator can override the
STUN/TURN configuration from FreedomBox web interface. Allow administrator's
overrides to co-exist with FreedomBox's managed STUN/TURN configuration.
Administrator's configuration, if it exists, always overrides FreedomBox's
managed configuration. Any updates to FreedomBox's managed configuration will
have no impact on the administrator's configuration since the latter takes
precedence.
Sunil:
- Collapse multiple turn actions into a single one for simplicity. Sending empty
configuration means removal of the configuration.
- Ensure that when removing configuration file is idempotent.
- Manage TURN configuration even when app setup is not yet completed. This fixes
issue with TURN configuration not getting setup on app installation and setup.
- Fix issue with TURN configuration getting updated on form submission even when
the field is not changed. This is due to mismatch between the browser submitted
\r\n with the internal \n.
- Simplify JavaScript for the form and attach handlers only after DOM is ready.
- Drop the no-JS message since the loss of functionality is trivial and to
reduce translation burden.
- Fix issue with URIs and secret parameters not getting updated unless the
managed checkbox changes.
- Drop specialized success messages for TURN configuration update to reduce
translation burden.
Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net>
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Sunil:
- Join the string in the template instead of the view.
Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net>
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Sunil:
- Add TurnConfiguration to reference documentation. Add more details in
docstrings.
- Rename the component to TurnConsumer since 'Component' in the name is
redundant and unconventional. Also, hopefully, the component will retain the
API over multiple TURN servers.
- Log when notifying other components about configuration change.
- Use TurnConfiguration class more widely.
- Refactor for simplicity.
- Additional tests.
- Move URI generation code into TurnConfiguration.
Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net>
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Closes: #2050.
Current implementation of Zoph does not work with version 0.9.9 in Buster. As an
easy hack to make the app only available in Bullseye, php7.4 dependency has been
added. After making the last release for Buster, this can be removed to allow
compatibility with newer versions of PHP that become available.
An incomplete list of problems with current implementation with Buster:
- zoph --get-config is unavailable. Can be circumvented by querying the DB
directly.
- zoph --dump-config is unavailable. Can be circumvented by querying the DB
directly.
- interface.user.remote and authentication based on REMOTE_USER are unavailable.
The Apache configuration shipped by Debian package does not include FreedomBox
related LDAP configuration.
- interface.user.cli defaults to "0" instead of "1". This cases running zoph
from command line. This can be circumvented by setting this configuration value
to "1" via DB interaction.
Tests:
- On stable container, zoph is not available for installation.
- On testing container, zoph can be installed, setup and used.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
Remove the percentage check, which was incorrectly checking used
percent, not free percent.
Closes: #2046.
Tests:
- Fill up disk space so that 4.5G is free. Dist upgrade does not start
due to not enough free space.
- Fill up disk space so that 5.5G is free. Dist upgrade can be
started.
Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
- Identify Freedbombox admin who installed the app to be zoph admin.
- Implement backup and restore.
- Photos directory should remain at /var/lib/zoph, for proper operation of
backups.
- There remains an issue that the App is enabled before it is configured but
will not work correctly until configuration.
- OpenStreetMap mapping is enabled. These should be configurable before
installation.
- Add initial forms.py and views.py to Zoph app, however these are currently
unused as urls.py does not invoke the view. When the view is not invoked the
Zoph App installs, with single signon, currently as the first LDAP user, rather
than the plinth user.
- The first user's preferences are not set, and need to be manually set to avoid
other errors.
* Sunil's changes
- Squash commits and re-split them.
- Drop documentation as it will be auto populated from wiki later.
- Remove outdated validation code from manifest.
- Drop some dead code.
- Don't send MySQL password over command line for improved security. Instead
rely on Unix authentication of root user similar to backup/restore process.
- Use JSON for exchanging configuration dump to avoid encoding errors.
- Add username validation to avoid a potential SQL injection.
- Update description for neural tone and brevity. Add information about how user
accounts work in FreedomBox
- Fix functional tests.
- Drop all code related to changing photos path until it is ready.
- Update URL from /zoph to /zoph/ to avoid another redirect.
- Fix disabling the app.
- Use icon that Zoph uses for favicon as logo. Update copyright file.
- Fix spelling unzip.
- Minor refactors. Run yapf and isort.
- Use subprocess.run() instead of os.popen() everywhere for better security with
argument parsing.
- Enable OpenStreetMap by default. User have a choice to disable it before using
the app. Add label to explain privacy concerns.
- Fix dropping database by using --force argument.
- Cleanup enabling the app to not enable the app when updating configuration.
- Use AppView's default template instead of overriding.
- Update functional tests to just check if the app is enabled/disabled as
expected. Checking that Zoph site is available will require reliable handling of
admin user.
Signed-off-by: John Lines <john@paladyn.org>
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Add running spinner before every app installation step text, this
makes the fact that installation is in progress visually more noticeable.
Tested when installing the mediawiki app, the running spinner is shown
on every installation step.
Signed-off-by: Veiko Aasa <veiko17@disroot.org>
[sunil: Horizontally align the text and spinner by the spinner inline]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Matrix Synapse 1.26 needs a new dependency python3-psycopg2. apt
preferences have to be updated to be able to install this package from
buster-backports.
Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net>
In testing and unstable, jQuery 3.5.1 is available. For security reasons, it
removes expanding of HTML code that JSXC relies on. Restore that functionality
as shown in jQuery Upgrade Guide.
Tests performed:
- Log in JSXC. Add a contact. In the contact list, the name of the contact is
shown properly.
- Clicking on the contact open a proper chat window.
- Using to two user accounts add each other to contact lists and start
conversation, the conversation show work properly.
- Authenticating each other and performing a secure conversation should work
properly.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
During 'setup' and 'update' post installation calls, the mediawiki
app page doesn't show any status information. Use the call name 'post'
instead so that the 'Performing post-install operation' message is displayed on the app page.
Fixes#2024
Tested that all the mediawiki app tests pass on first app installation.
Signed-off-by: Veiko Aasa <veiko17@disroot.org>
Reviewed-by: Fioddor Superconcentrado <fioddor@gmail.com>
Notification for dist upgrade started, or not started due to lack of
free space.
Currently, these notifications only appear once.
Tests:
- Checked each notification appears.
- Notification does not appear again after being dismissed.
Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
Separate checking for dist upgrade from other setup. We don't want to
start a dist upgrade during the module's setup.
Tests: Checked logs for the following:
- Up to date.
- Updates not enabled.
- Dist upgrade started.
Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
Fixes: #2026.
Upgrade from 1.2.1+dfsg-1+b1 to 1.3.x.
Tests:
- Install version 1.2.1+dfsg-1+b1. Change the default media directory. Run
unattended upgrades it will fail to upgrade. With the new patch, run apt update.
This will force upgrade. After upgrade the earlier set media directory is
retained.
- Functional tests run.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
Tests performed:
- Functional tests work as expected.
- Updating the media directory works newly updated media directory is show.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
Closes: #2023.
When importing the test module, datetime.now() is executed and value is kept. If
a test suite runs for a long time, the time deltas are being calculated much
later when the test case runs. This creates an difference in expected different
between the two values.
Fix this by completely removing all uses of time relative to current date time.
Only use absolute date time values. This should not reduce the effectiveness of
the test cases.
Tests performed:
- Rerun unit tests for backups module.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
After enabling the calibre app, the app uses IP 127.0.0.1 to advertise
ODPS feeds via BonJour/mDNS. It breaks accessing freedombox.local as it now
points to 127.0.0.1.
This MR disables the BonJour in Calibre.
Fixes#2027.
Tests performed on both Debian stable and testing containers:
- Check the accessability of freedombox.local:
1) Before applying patch:
- Start the container, check on the host that freedombox.local points to
correct IP address of the container:
```
host$ avahi-resolve -4 --name freedombox.local
freedombox.local 10.42.1.166
```
- Enable the calibre app. Check on the host that freedombox.local
points to wrong ip address 127.0.0.1:
```
host$ avahi-resolve -4 --name freedombox.local
freedombox.local 127.0.0.1
```
2) Stop the calibre app, apply patch (update the calibre systemd service file,
reload systemd), restart the Service Discovery app, check on the host that
freedombox.local points to correct address.
3) Start the calibre app, check on the host that freedombox.local points to
correct address.
- All the calibre functional tests pass.
Signed-off-by: Veiko Aasa <veiko17@disroot.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Tests performed:
- Upgrade from old 2.x versions to 3.x has not been tested.
- Fresh installation of radicale 3 works (via FreedomBox). Web interface works.
Able to create a calendar.
- Upgrading from radicale 2 to radicale 3 works (via unattended-upgrades). There
were no configuration file prompts in FreedomBox (where only
/etc/radicale/config is modified).
- After upgrade, all functional test cases for radicale in FreedomBox
passed (including backup and restore of data).
- After upgrade, I have tested that permissions system as configured in
FreedomBox owner_only = allow file permissions, owner_write and authorized are
same as defined in radicale.
- These permissions have worked as expected as tested with Thunderbird.
- Radicale says that file based permissions format has changed, however,
FreedomBox relies on only the right files provided by default.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Tested-by: Sunil Mohan Adapa <sunil@medhas.org>
Ability to use lru_cache(user_function) was only introduced in Python 3.8.
Buster has Python 3.7. This causes startup failure in Buster. Fix this by using
the older API for lru_cache instead of the new one.
Tests:
- On stable and testing, starting the Plinth daemon and visiting the performance
page should work.
- Adding a print statement in the _get_url() method shows that it is only called
once, ever.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
Helps: #1962
Shown an alarming warning in connection_show page (only) for the primary
connection. Captions 'Deactivate' and 'Delete' buttons, now explicitly
mention the primary connection and they are placed within the warning
box.
Signed-off-by: Fioddor Superconcentrado <fioddor@gmail.com>
[sunil: Primary connection is not the same as connection user is using]
[sunil: Reduce the importance of primary connection as it is just default route]
[sunil: Update primary connection message]
[sunil: Fix the use of exclamation icon for screen readers as per bootstrap]
[sunil: Don't place buttons inside the warning, as it is non-intuitive UI]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Closes: #1974
BTW: Javascript IPV4/6 hide/show arrangements triggered on page load.
Otherwise page loads form fields inconsistently.
Signed-off-by: Fioddor Superconcentrado <fioddor@gmail.com>
[sunil: Fix the use of RadioSelect widget]
[sunil: Alter the wording of what each type means]
[sunil: Drop the help text for radio group as it is mostly repetitive]
[sunil: js: Make the entire jQuery code run on document ready]
[sunil: js: Revert unneeded double call to change methods, change() is enough]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Pull the delete button in the connection show page to the right to prevent
hitting it by accident.
Signed-off-by: Fioddor Superconcentrado <fioddor@gmail.com>
[sunil: Use a new consistent style compatible with bootstrap4]
[sunil: Styled the delete button with danger color]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Closes: #2022.
- Differently URL based on version of Cockpit used.
- Lazily evaluate when necessary.
- Cache the result.
[sunil: Use subprocess.run() instead of getoutput() for security]
[sunil: Use long form arguments in command invocation for readability]
[sunil: Perform isort]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>