FacebookTwitterFlickrYoutuberss

Version 9

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

Index || < Prev | Next >


Version 0.9: Making changes take immediate effect

In this version you will learn how to create a model that does not store anything on disk, and commits its configuration changes immediately. Although this is not the preferred way to do this, it can be useful for some scenarios.

If you remember, most of the modules in Zentyal let the user make configuration changes, and these changes do not take effect on the real configuration until the user clicks on the Save changes button.

Data model

Let's create our new model called AllModules. This model is going to be used to configure apache modules as well. However, we will be doing things in a different way.

First of all, we are going to build our rows in run-time. This approach can be very useful if you have a read-only table with thousands of rows as its very memory-efficient.

We need to create our row identifier vector in run-time. To simplify things, we will be using the name of the apache modules as row identifiers. We will override EBox::Model::DataTable::ids() to return our row identifier vector based on the available modules

The code to carry out that task will look like::

# Method: ids
#
#   Override <EBox::Model::DataTable::ids> to return
#   row identifiers based on the apache modules that
#   are available in /etc/apache2/mods-available
sub ids
{
    my ($self) = @_;

    opendir (my $dh, '/etc/apache2/mods-available');
    my @mods;
    while (defined (my $file = readdir($dh))) {
        next unless ($file =~ /(.*)\.conf$/);
        push (@mods, $1);
    }

    @mods = sort @mods;
    $self->{modules} = \@mods;

    return $self->{modules};
}

The next step is overriding EBox::Model::DataTable::row to build and return a row.:

# Method: row
#
#   Override <EBox::Model::DataTable::row> to return
#   a row
sub row
{
    my ($self, $id) = @_;

    # Check if the module is enabled by checking if the file
    # "/etc/apache2/mods-enabled/$id.load" exits.
    my $enabled = ( -f "/etc/apache2/mods-enabled/$id.load" );
    my $row = $self->_setValueRow( module => $id, enabled => $enabled );
    $row->setId($id);
    return $row;
}

row() receives the row identifier as parameter. As this identifier is the name of the apache module, we check if the module is enabled or notwith::

my $enabled = ( -f "/etc/apache2/mods-enabled/$id.load" );

We build a row using the convenient method EBox::Model::DataTable::_setValueRow with its values. And after setting its row identifier, we return the row.

Now, we need to apply the change, we do it overriding EBox::Model::DataTable::setTypedRow so we can execute the actions as soon as the user do them on the web UI.

sub setTypedRow
{
    my ($self, $id, $paramsRef, %optParams) = @_;

    my $module = $paramsRef->{module}->value();
    if ($paramsRef->{enabled}->value()) {
        EBox::Sudo::root("a2enmod $module");
    } else {
        EBox::Sudo::root("a2dismod $module");
    }
}

Finally, given that the ids are generated from the filesystem content, without using Redis, we also need to override EBox::Model::DataTable::_checkRowExist, that way the validator will find the rows being changed:

sub _checkRowExist
{
    my ($self, $id, $text) = @_;

    my @modules = @{$self->{modules}};

    unless (@modules and grep { $_ eq $id } @modules) {
        throw EBox::Exceptions::DataNotFound(
                data => $text,
                value => $id);
    }
}

Let's recap how the whole code::

package EBox::Apache2::Model::AllModules;

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

use strict;
use warnings;

use EBox::Gettext;

use EBox::Types::Boolean;
use EBox::Types::Text;

# Method: ids
#
#   Override <EBox::Model::DataTable::ids> to return
#   row identifiers based on the apache modules that
#   are available in /etc/apache2/mods-available
sub ids
{
    my ($self) = @_;

    opendir (my $dh, '/etc/apache2/mods-available');
    my @mods;
    while (defined (my $file = readdir($dh))) {
        next unless ($file =~ /(.*)\.conf$/);
        push (@mods, $1);
    }

    @mods = sort @mods;
    $self->{modules} = \@mods;

    return $self->{modules};
}

# Method: row
#
#   Override <EBox::Model::DataTable::row> to return
#   a row
sub row
{
    my ($self, $id) = @_;

    # Check if the module is enabled by checking if the file
    # "/etc/apache2/mods-enabled/$id.load" exits.
    my $enabled = ( -f "/etc/apache2/mods-enabled/$id.load" );
    my $row = $self->_setValueRow( module => $id, enabled => $enabled );
    $row->setId($id);
    return $row;
}


# Method: setTypedRow
#
#   Override <EBox::Model::DataTable::setTypedRow> to apply directly module activations
#
sub setTypedRow
{
    my ($self, $id, $paramsRef, %optParams) = @_;

    my $module = $paramsRef->{module}->value();
    if ($paramsRef->{enabled}->value()) {
        EBox::Sudo::root("a2enmod $module");
    } else {
        EBox::Sudo::root("a2dismod $module");
    }
}

# Method: _checkRowExist
#
#   Override <EBox::Model::DataTable::checkRowExist> to accept the module list from apache.
#
sub _checkRowExist
{
    my ($self, $id, $text) = @_;

    my @modules = @{$self->{modules}};

    unless (@modules and grep { $_ eq $id } @modules) {
        throw EBox::Exceptions::DataNotFound(
                data => $text,
                value => $id);
    }
}

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

    my @fields = (
        new EBox::Types::Text(
           'fieldName' => 'module',
            'printableName' => __('Module'),
            'size' => 8,
        ),
        new EBox::Types::Boolean(
            'fieldName' => 'enabled',
            'printableName' => __('Enabled'),
            'editable' => 1,
        ),
    );

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

    return $dataTable;
}

1;


Index || < Prev | Next >

Template:TracNotice

Personal tools
Namespaces

Variants
Actions

Zentyal Wiki

Zentyal Doc
Navigation
Toolbox