Difference between revisions of "Version 9"
m |
Latest revision as of 09:07, 6 August 2014
[edit] 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.
[edit] 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;