FacebookTwitterFlickrYoutuberss

Version 6

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

Index || < Prev | Next >


Contents

Version 0.6: adding a submodel

In this version we will add support for Server Aliases. These aliases allow the user to configure the same virtual host with more than one name.This way we can have the same virtual host for foo.com and www.foo.com.

To support this feature we will introduce the concept of submodel. A submodel is just a normal model whose data is related to a parent model. For example, we will be creating a new model called serverAliases, this model will behave as a submodel. For every virtual host, that is, for every row in the VirtualHosts model we will associate another model of serverAliases. Or to put it another way, every row of VirtualHosts has many serverAliases. In practice this means a few things, amongst them: configuration data is stored in a tree or directory structure, so submodel data will live under its parent model directory.

    • VirtualHost: foo.com
      • serverAliases: www.foo.com
      • serverAliases: www1.foo.com
    • VirtualHost: bar.com
      • serverAliases: www.bar.com
      • serverAliases: www1.bar.com


Data model

Our new model is going to be pretty simple: ServerAliases will just be a list of domains. Create the new model in src/EBox/Apache2/Model/ServerAliases with the following code:

package EBox::Apache2::Model::ServerAliases;

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

use strict;
use warnings;

use EBox::Gettext;

use EBox::Types::DomainName;

sub _table
{

    my ($self) = @_;  

    my @fields = (
        new EBox::Types::DomainName(
            'fieldName' => 'name',
            'printableName' => __('Aliases'),
            'size' => '8',
            'unique' => 1,
            'editable' => 1
        ),
    );

    my $dataTable =
    {
        'tableName' => 'ServerAliases',
        'printableTableName' => __('Server Aliases'),
        'modelDomain' => 'Apache2',
        'defaultActions' => ['add', 'del', 'editField', 'changeView' ],
        'tableDescription' => \@fields,
        'help' => '', # FIXME
        'sortedBy' => 'name',
        'enableProperty' => 1,
    };

    return $dataTable;
}

1;

The next step is making the VirtualHosts model use our recently created ServerAliases. To do so we will have to modify src/EBox/Apache2/Model/VirtualHosts.pm. First of all, we will have to use a new type EBox::Types::HasMany which is used to store submodels:

use EBox::Types::HasMany;

Now we will have to modify the model to actually use this new type and the ServerAliases model:

new EBox::Types::HasMany(
     'fieldName' => 'aliases',
     'printableName' => __('Aliases'),
     'foreignModel' => 'ServerAliases',
     'view' => '/Apache2/View/ServerAliases',
),

Pay attention to the attribute foreignModel that is used to set our EBox::Types::HasMany type to use our model, and view to set the URL to access the model view.

The whole file should be:

package EBox::Apache2::Model::VirtualHosts;

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

use strict;
use warnings;

use EBox::Gettext;

use EBox::Types::DomainName;
use EBox::Types::HasMany;

sub _table
{

    my ($self) = @_;  

    my @fields = (
        new EBox::Types::DomainName(
            'fieldName' => 'name',
            'printableName' => __('Virtual Host'),
            'size' => '8',
            'unique' => 1,
            'editable' => 1
        ),
        new EBox::Types::HasMany(
           'fieldName' => 'aliases',
           'printableName' => __('Aliases'),
           'foreignModel' => 'ServerAliases',
           'view' => '/Apache2/View/ServerAliases',
        ),
    );

    my $dataTable =
    {
        'tableName' => 'VirtualHosts',
        'printableTableName' => __('VirtualHosts'),
        'modelDomain' => 'Apache2',
        'defaultActions' => ['add', 'del', 'editField', 'changeView' ],
        'tableDescription' => \@fields,
        'help' => '', # FIXME
        'sortedBy' => 'name',
        'enableProperty' => 1,
    };

    return $dataTable;
}

1;

Build and install the package. Click on Apache2->Virtual Hosts and you will see a new field called Aliases where you can click on.

Image(virtual-host-3.png)

Fetching the stored values

Let's make a simple script to retrieve the stored values. Note that there is something important to learn here: the way we deal with submodels when it comes to fetching data.

Here is the script:

use EBox;
use EBox::Global;

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

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

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

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

Note that within the first loop we iterate over the virtual hosts, and the inner loop is used to iterate over each alias of the virtual host. To be able to fetch the aliases rows we call the method subModel('aliases') from the a virtual host row, subModel receives the name of a EBox::Types::HasMany field which exists in a given model and does the magic to return a submodel which can be used just like you were using a normal model; that's why we call ids().

Setting the Apache configuration

We will have to slightly modify the template used to generate the virtual host configuration to write the server aliases. Our template stubs/virtual-host.conf.mas should look like this now:

<%args>
$name
@alias
</%args>
<VirtualHost *:80>
        ServerAdmin webmaster@localhost

        ServerName <% $name %>

%       for my $aliasName (@alias) {
        ServerAlias <% $aliasName %>
%       }

        DocumentRoot /var/www/<% $name %>
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/<% $name %>>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

        ErrorLog /var/log/apache2/error.log

        # Possible valu
        # alert, emerg.
        LogLevel warn

        CustomLog /var/log/apache2/access.log combined
</VirtualHost>

Note the changes: we have added a new parameter @alias, an array used to receive all the aliases for this virtual host, and a loop to iterate over them and write ServerAlias name.

If we add a new parameter to the template, we need to modify src/EBox/Apache2.pm to set and pass the @alias parameter properly. We modify the _setVirtualHosts method to do this, using the subModel method to iterate over the aliases and set each position in the array:

# Method: _setVirtualHosts
#
#       This method is used to set the virtual hosts
#
sub _setVirtualHosts
{
    my ($self) = @_;

    my $model = $self->model('VirtualHosts');

    # Iterate over the virtual host table
    for my $id (@{$model->ids()}) {
        my $row = $model->row($id);
        my $name = $row->valueByName('name');
        my $enabled = $row->valueByName('enabled');
        my @alias;
        for my $aliasId (@{$row->subModel('aliases')->ids()}) {
            my $aliasRow = $row->subModel('aliases')->row($aliasId);
            my $aliasName = $aliasRow->valueByName('name');
            push (@alias, $aliasName);
        }
        my @params = (name => $name, alias => \@alias);
        my $outputFile = "/etc/apache2/sites-available/ebox-$name";
        # Write virtual host configuration file
        $self->writeConfFile(
            $outputFile, 'apache2/virtual-host.conf.mas', \@params);

        # Create the document root directory if it does not exist
        my $docRoot = "/var/www/$name";
        unless ( -d $docRoot ) {
            EBox::Sudo::root("mkdir $docRoot");
        }
        # Enable or disable the virtual host depending on the user
        # configuration
        if ($enabled) {
            EBox::Sudo::root("a2ensite ebox-$name");
        } else {
            EBox::Sudo::root("a2dissite ebox-$name");
        }
    }
}


Index || < Prev | Next >

Template:TracNotice

Personal tools
Namespaces

Variants
Actions

Zentyal Wiki

Zentyal Doc
Navigation
Toolbox