Register for the iXsystems Community to get an ad-free experience and exclusive discounts in our eBay Store.

Modifying/Adding to GUI

Not open for further replies.


I'm modifying a running system since most people don't know how to build or want to build from source. I figured my method was easier for the average user.

Yeah, I'm sure it will happen 'officially' at some point. It seems like now they're planning to skip version 8.1 and go directly to 8.2, probably to sync up the version numbers with FreeBSD a little faster.
Ding-ding-ding! Correct :).


For hackers who want to hack, here's an incomplete guide on how to do things based on my understanding of the world as well as the things I would like to see done in the future in order for FreeNAS to become a complete well-designed, featureful, scalable project.

1. Django provides you with a python-based, server side means of dynamically producing HTML.
2. Dojo is the JavaScript framework that works hand-in-hand to give Django an Ajax-y feel.

Put them together and you get dojango.

Now, Django 'simplifies' the creation of webpages and database schema by allowing the user to define an MVC (model-view-controller)-type configuration for webpages (it's a software design pattern that aims to simplify and improve UI design), via models (, a view (, and a controller (HTML/JavaScript goo).

Now, enter in southdb. south DB is a mechanism with which one can migrate the database schema from one version to another (either insert, replace, or drop/delete database tables and/or fields). This is what takes place in the second reboot after an upgrade.

Once upon a time, not too long ago, the initial database used to be hardcoded and that database was used for initial installs and configuration reset, but nowadays it's produced on the fly during the build and also when running "config reset". So that file that from modified ( shouldn't in reality be modified -- otherwise the database schema won't persist properly for upgrades (IIRC.. william can correct me if I'm totally wet here) :).

This in a nutshell from a 20k foot view sort of describes how the GUI stuff works.

Now, for the question everyone's wondering: WTF does notifier do, how does the middleware work, and how do I make my shiny buttons do things? There are a couple considerations to make:

1. Configuration generation and service loading at boot.
2. Configuration generation and service [re]loading at runtime.

There are two big pieces to this puzzle:

1. The [ix] rc-scripts.
2. notifier.

The ix rc-scripts are the scripts which (generally) poke at the database and do the grunt work of spitting out configuration in a manner that's suitable for either a running service or the base system, s.t. the system does what the user requested. Optionally there are some ix scripts that invoke other rc-scripts (example: ix-activedirectory, etc), but this kind of design is discouraged because it obfuscates the actual problem that the "hack" is attempting to resolve.

Now, for notifier..

- [paraphrased] "notifier was never intended to be what it is today"
- [paraphrased] "notifier needs a rewrite" :).

What notifier does today:

1. Manages services (see the start, stop, restart, reload, etc routines).
2. Storage querying and management.
3. It houses the upgrade and servicepack shim logic.
4. It goes and pokes around the base system in other ways that would make the dojango code more of a mess, e.g. determining whether or not kernel modules were loaded, what version of ZFS is running in the background, etc.
5. A lot more fun stuff I'm not mentioning here.

Word to the wise:

- Don't stick too many things in notifier or you'll more than likely end up shuffling stuff around unnecessarily; stick them in a separate file and import them at the top of notifier, similar to this:

"""gui.service.mysql blurb"""
def _start_mysql(obj):
    obj.__system("/usr/sbin/service mysqld quietstart")
    # ...

def _restart_mysql(obj):
    obj.__system("/usr/sbin/service mysqld restart")

"""gui.middleware.notifier blurb"""
class Notifier:
    from service.mysql import _start_mysql, _restart_mysql, _reload_mysql

And stick to the design pattern in the start-stop-restart logic. This pollute's notifiers namespace, but it's less invasive, and until notifier does just IPC, this is the only way to go to keep your local changes sane.

- Create an ix (or whatever) script that runs before your service(s); key points are to look at the rc-script headers (BEFORE:, REQUIRE:, etc), as well as refer to man 5 rc and the FreeBSD article on the topic of rc-scripts: (there might be more if you Google for them).

- Don't hardwire stuff into the GUI. This is what plugins were for and it will need to be ripped out eventually, and given the amount of churn in the GUI, I recommend not planning on putting stuff there indefinitely for the sake of your own sanity.
- Hang ten for 8.2.1+, etc before designing plugins unless you want to be doing bleeding edge development that is most likely going to change a lot. There won't really be a concrete API in 8.2.0 as far as I can see and if there is going to be one it's going to have some serious rough edges.. but you can design stuff that will be installable and persist across upgrades if you decide to be bold and develop plugins -- heck, we need testers I guess. It's up to you.
Not open for further replies.