FacebookTwitterFlickrYoutuberss

Version 2

From Zentyal Linux Small Business Server
Jump to: navigation, search

Index || < Prev | Next >


Contents

Version 0.2: adding a table

Next iteration. So far our module only manages the listening port. This is way too trivial. In this iteration we will manage apache modules, but in a simple way for sake of clarity. We will let the user enable disable some of the modules shipped along with apache.

In Ubuntu and Debian, there are a couple of apache directories which are of interest for this task: /etc/apache2/mods-available and /etc/apache2/mods-enabled. The system administrator can enable a module by symliking a couple of files. There's a tool called a2enmod that makes this task automatic.

Let's pick a few modules to be managed by Zentyal:

    • ssl
    • info
    • status
    • version


In this first version, our UI will look like a table that the user can add rows to. Every row will represent one of the above modules, and will have a field to indicate if the module is enabled or disabled. We will only take care of the modules listed in this table, i.e., if the module has not been added as a row in the table we will not touch its configuration and we will leave it as it is.

Data model

The data model to manage modules is pretty simple, we will need a field to store the module name and another field to enable and disable the module.

We need to create a new model called Modules which is composed of a Select type called module and a Boolean type called enabled. The type of model is a table instead of a form as we did in version 0.1.

You have to edit the schemas/apache2.yaml file like this (adding the Modules model):

class: 'EBox::Apache2'

models:
    - Settings
    - Modules

And the model file src/EBox/Apache2/Model/Modules.pm:

package EBox::Apache2::Model::Modules;

use base 'EBox::Model::DataTable';

use strict;
use warnings;

use EBox::Gettext;

use EBox::Types::Boolean;
use EBox::Types::Select;


#   Callback function to fill out the values that can
#   be picked from the <EBox::Types::Select> field module
#
# Returns:
#
#   Array ref of hash refs containing:
#
#
sub populate_module
{

    my @opts = ();
    push (@opts, { value => 'ssl', printableValue => 'SSL' });
    push (@opts, { value => 'info', printableValue => 'Info' });
    push (@opts, { value => 'status', printableValue => 'Status' });
    push (@opts, { value => 'version', printableValue => 'Version' });
    return \@opts;

}


# Method: _table
#
# Overrides:
#
#       <EBox::Model::DataTable::_table>
#
sub _table
{
    my ($self) = @_;

    my @fields = (
        new EBox::Types::Select(
            'fieldName' => 'module',
            'printableName' => __('module'),
            'populate' => \&populate_module,
            'unique' => 1,
            'editable' => 1,
        ),
        new EBox::Types::Boolean(
            'fieldName' => 'enabled',
            'printableName' => __('enabled'),
            'optional'      => 0,
            'editable'      => 1,
            'defaultValue'  => 0
        ),
    );

    my $dataTable =
    {
        'tableName' => 'Modules',
        'printableTableName' => __('Modules'),
        'modelDomain' => 'Apache2',
        'defaultActions' => ['add', 'del', 'editField', 'changeView' ],
        'tableDescription' => \@fields,
        'printableRowName'=> __('Apache module'),
        'sortedBy' => 'module',
        'help' => __('This is the help of the model'),
    };

    return $dataTable; 

}

1;


Build and install the package.

For now there's no menu entry to check the view associated to this module, but we can easily guess the URL as we know the model name. Fire up to browser, log in Zentyal and go to https://your_ip/Apache2/View/Modules. You will see something like this:

Image(modules-1.png)

If you click on the Add new link you will see:

Image(modules-2.png)

To modify the options to show in our new model, you can edit the populate_module function that populates the drop-down box, i.e: our Select type.

Open src/EBox/Apache2/Model/Modules.pm and go to the function called populate_module:

#   Callback function to fill out the values that can
#   be picked from the <EBox::Types::Select> field module
#
# Returns:
#
#   Array ref of hash refs containing:
#
#
sub populate_module
{

    my @opts = ();
    push (@opts, { value => 'ssl', printableValue => 'SSL' });
    push (@opts, { value => 'info', printableValue => 'Info' });
    push (@opts, { value => 'status', printableValue => 'Status' });
    push (@opts, { value => 'version', printableValue => 'Version' });
    return \@opts;

}

populate_module is a callback that will be called by our field module which is a Select type to populate the available options within the drop-down box. Check out the code which instances this type and how we pass a pointer to this method using the attribute populate:

...
    my @fields = (
        new EBox::Types::Select(
            'fieldName' => 'module',
            'printableName' => __('module'),
            'populate' => \&populate_module,
            'unique' => 1,
            'editable' => 1,
        ),

...

Once you add some fields, you will see something like this:

Image(modules-3.png)

This is the code that controls how the table looks like:

...

    my $dataTable =
    {
        'tableName' => 'Modules',
        'printableTableName' => __('Modules'),
        'modelDomain' => 'Apache2',
        'defaultActions' => ['add', 'del', 'editField', 'changeView' ],
        'tableDescription' => \@fields,
        'printableRowName'=> __('Apache module'),
        'sortedBy' => 'module',
        'help' => __('This is the help of the model'),
    };

...


The printableRowName field controls which is the name that will be used to show information to the user when an action takes place on a row, and sortedBy tells the framework to order the table using a given field, in this case module.

Fetching the stored values

This time, the Zentyal' shell is not the best option to check the stored values, given that it only accepts one line commands and in this case, we need to iterate over all select options. Here we have a script we would use to check the content values:

use EBox;
use EBox::Global;

# This is the very first thing we always have to do from external scripts
EBox::init();

# Instance module
my $module = EBox::Global->modInstance('apache2');

# Instance model
my $modules = $module->model('Modules');

# Iterates over the rows and print info
for my $id (@{$modules->ids()}) {
        my $row = $modules->row($id);
        my $name = $row->valueByName('module');
        my $enabled = $row->valueByName('enabled');
        print "Module: $name enabled $enabled\n";
}

We will skip the first part and we will go directly into the loop. As you can see, we iterate over every row that is stored in our model. We use the method ids() (remember our model inherits from EBox::Model::DataTable) to fetch the row identifiers. And for every identifier we retrieve its row by calling row(). Then we fetch the value for the two fields that make it up: module, and enabled. The method valueByName, as we have already seen, takes care of looking up the field and returning its value.

Writing the apache configuration

We will take advantage of a2enmod and a2dismod script to enable and disable apache modules. These scripts take care of symlinking the relevant files to carry out the actions. Their use is straightforward:

a2enmod module_name

In our main class (src/EBox/Apache2.pm) we will implement a private method called _configureModules which will iterate over the configured modules and will run a2enmod if the module is enabled, or a2dismod if it's disabled. The method will look like this:

# Method: _configureModules                                                     
#                                                                               
#       This method is used to enable or disable apache modules based           
#       on the user configuration.                                              
#                                                                               
sub _configureModules                                                           
{                                                                               
    my ($self) = @_;                                                            
                                                                                
    my $model = $self->model('Modules');                                        
                                                                                
    for my $id (@{$model->ids()}) {                                             
        my $row = $model->row($id);                                             
        my $module = $row->valueByName('module');                               
        my $enabled = $row->valueByName('enabled');                             
        if ($enabled) {                                                         
            EBox::Sudo::root("a2enmod $module");                                
        } else {                                                                
            EBox::Sudo::root("a2dismod $module");                               
        }                                                                       
    }                                                                           
} 

The last thing to do is call this method from the _setConf method. Remember that that this is the method which is called by _regenConfig when the user saves changes. It should look something like this:

# Method: _setConf
#
#       Overrides <EBox::Module::Service::_setConf>
#
sub _setConf
{
        my ($self) = @_;

...

        $self->_configureModules();
}


Index || < Prev | Next >

Template:TracNotice

Personal tools
Namespaces

Variants
Actions

Zentyal Wiki

Zentyal Doc
Navigation
Toolbox