Plano de Gerenciamento de Software

editar

Visão Geral

editar

O SME-UnB é uma aplicação web desenvolvida para auxiliar o monitoramento energético de transdutores instalados em quadros da Universidade de Brasília. Suas principais funcionalidades são:

  • Geração de relatórios;
  • Gráficos de consumo, demanda e afins;
  • Monitoramento temporal de transdutores;
  • Simulação de fatura;
  • Sistema de alarme para eventos indesejados.

O SME-UnB é desenvolvido em liguagem Python usando o Web Framework Django.

Repositório Oficial: https://gitlab.com/brenddongontijo/SME-UnB Repositório do Projeto: https://gitlab.com/matheus.fga/SME-UnB

Finalidade

editar

Esse documento servirá para mostrar os objetivos que devem ser atingidos com o gerenciamento e configuração de software(GCS) e as ferramentas utilizadas.

Escopo

editar

O escopo desse projeto projeto irá contemplar a melhoria de GCS do projeto SME-UnB. Para tanto, é definido 2 objetivos:

  1. Passar o projeto para Docker
  2. Empacotamento para DEB

GCS atual

editar

O projeto em questão já possui uma política de GCS que oferece um guia de instalação com a utilização das ferramentas Vagrant e Chef

Ferramentas

editar

As ferramentas que serão utilizadas no projeto serão:

Ferramentas Descrição
Docker Uma plataforma aberta para desenvolvedores e administradores de sistemas para construir e executar aplicações distribuídas, seja em laptops, data center VMs, ou na nuvem.
Vagrant Possibilita a criação e configuração de um ambiente de produção em uma máquina virtual, no qual estará pronta para ser utilizada por um desenvolvedor.
Pip Um sistema de gerenciamento de pacotes usado para instalar e gerenciar pacotes de software escritos na linguagem de programação Python. Facilita a instalação de dependências do software e resolução de dependência entre pacotes.
Git Gerenciador de versões utilizada pela equipe de desenvolvimento.
dpkg Sistema de gerenciamento de pacotes da distribuição linux Debian.
Gitlab Source forge onde está presente o repositório do projeto, no qual contribuidores e interessados podem ver o código do software.

Cronograma

editar
Período Descrição
20/09 ~ 26/09 Planejamento do pla

no de GCS

27/09 ~ 03/10 Estudar a ferramenta Docker
04/10 ~ 10/10 chef Começa a aplicar Docker para build no projeto
11/10 ~ 17/10 Evoluir Docker e Vagrant do projeto
18/10 ~ 31/10 Aplicar Docker para desenvolvimento
01/11 ~ 14/11 Estudar empacotamento
15/11 ~ 28/11 Empacotamento parcial de DEB

Relatório de Projeto

editar

Ambiente automatizado usando o Vagrant

editar

O Vagrant é uma ferramenta de criação e configuração de infraestrutura (Ambientes de desenvolvimento) para um determinado projeto, a partir da utilização de uma Máquina Virtual (VM). Essa ferramenta auxilia na gerência dessas VMs.

Com essa ferramenta, foi feito a configuração automática do ambiente de desenvolvimento do projeto SME-UnB. Utilizando junto ao Vagrant uma receita chef que servirá como uma biblioteca para gerência de configuração e um arquivo shell script que irá instalar as dependência restantes dentro da VM.

A seguir vai ser apresentado o Vagrantfile que define as configurações da máquina virtual.

# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "precise32"
  config.vm.box_url = "http://files.vagrantup.com/precise32.box"

  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--memory", "2048"]
  end

  config.vm.network :forwarded_port, guest: 3000, host: 3000

  config.omnibus.chef_version = "12.10.24"

  config.vm.provision :chef_solo do |chef|
    chef.cookbooks_path = ["cookbooks"]

    chef.add_recipe "apt"
    chef.add_recipe "vim"
    chef.add_recipe "git"
    chef.add_recipe "build-essential"
    chef.add_recipe "python"
  end
end

Execute o script cookbooks_script.sh, o qual se encarregará com o resto da instalação:

$ ./cookbooks_script.sh

A seguir será apresentado o arquivo shell script que irá clonar os repositórios necessários para a execução do cookbook. Esse arquivo ja existia no projeto, mas apresentava erros.

#!/bin/bash
# Script to download all necessary cookbooks for Chef and run vagrant up.
mkdir cookbooks && cd cookbooks/
git clone https://github.com/chef-cookbooks/apt.git
git clone https://github.com/chef-cookbooks/build-essential.git
git clone https://github.com/chef-cookbooks/chef_handler.git
git clone https://github.com/chef-cookbooks/compat_resource.git
git clone https://github.com/chef-cookbooks/dmg.git
git clone https://github.com/chef-cookbooks/git.git
git clone https://github.com/chef-cookbooks/mingw.git
git clone https://github.com/chef-cookbooks/openssl.git
git clone https://github.com/chef-cookbooks/vim.git
git clone https://github.com/chef-cookbooks/windows.git
git clone https://github.com/chef-cookbooks/yum-epel.git
git clone https://github.com/chef-cookbooks/yum.git
git clone https://github.com/daptiv/seven_zip.git
git clone https://github.com/poise/python.git
git clone https://github.com/sethvargo/chef-sugar.git
git clone https://github.com/chef/ohai.git
cd .. && vagrant up
vagrant ssh -c "/vagrant/after_installation_script.sh"
vagrant ssh

A seguir será apresentado o arquivo shell script que instalará as dependências restantes para o bom funcionamento do projeto. Esse arquivo ja existia no projeto, mas apresentava erros.

#!/bin/bash
sudo apt-get install postgresql python-psycopg2 libpq-dev -y
ADMIN="admin"
SMEDB="smeunb"
sudo su - postgres -c "createuser vagrant --no-superuser --no-createdb --no-createrole" || true
sudo su - postgres -c "createuser $ADMIN --no-superuser --createdb --no-createrole" || true
sudo su - postgres -c "createdb $SMEDB -O $ADMIN" || true
cd /vagrant
sudo pip install -r requirements.txt
python manage.py migrate

Ambiente automatizado usando o Docker

editar

O Docker é uma ferramenta de isolamento de ambiente assim como uma VM, utilizando um container para fazer esse isolamento. A grande diferença entre uma VM e um container é que na VM roda um sistema operacional completo compartilhando os recursos de hardware, já no container há um isolamento entre recursos como processos, sistema de arquivos, interfaces de rede e recursos do kernel fazendo com que fique mais leve do que uma VM.

O Dockerfile, assim como o Vagrantfile vai definir as configurações do isolamento, mas nesse caso no container. A seguir será apresentado as configurações do Dockerfile:

FROM python:2.7
MAINTAINER matheussilva.fga@gmail.com

ENV PYTHONUNBUFFERED 1
ENV APPLICATION_ROOT /SME-UnB/

RUN mkdir -p $APPLICATION_ROOT
WORKDIR $APPLICATION_ROOT
ADD . $APPLICATION_ROOT
RUN pip install -r requirements.txt

Foi utilizado o docker-compose para ecução de múltiplos containers de aplicação. Com o docker-compose, é possível criar arquivo do tipo yaml para definir como será o ambiente de sua aplicação para usar um único comando iniciando todos os serviços definidos. A seguir será apresentado as configurações do arquivo docker-compose.yml:

version: '2'
services:
    web:
        build: .
        command: bash -c "sleep 5 && python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
        volumes:
            - .:/SME-UnB
        ports:
            - "8000:8000"
        depends_on:
            - db
    db:
        image: postgres:9.4
        environment:

            POSTGRES_USER: admin
            POSTGRES_PASSWORD: admin
            POSTGRES_DB: smeunb

É necessário configurar o arquivo settings.py no caminho SME-UnB/src/SME_UnB para o funcionamento do docker-compose:

"""
Django settings for SME_UnB project.

Generated by 'django-admin startproject' using Django 1.9.6.

For more information on this file, see
https://docs.djangoproject.com/en/1.9/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.9/ref/settings/
"""

import os
import logging

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/

SECRET_KEY = 'secret_key'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'data_reader.apps.DataReaderConfig',
    'transductor.apps.TransductorConfig',
    'bootstrap3',
    'polymorphic',
]

MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'SME_UnB.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'SME_UnB.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'smeunb',
        'USER': 'admin',
        'PASSWORD': 'admin',
        'HOST': 'db',
        'PORT': '5432',
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, Java, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'

Empacotamento Debian

editar

Nesta seção serão descritos os passos para a construção de um pacote Debian (.deb) com o intuito de realizar deploy da aplicação SME-UnB em um servidor Debian.

O primeiro passo é criar um diretório nomeado "debian" para armazenar os arquivos do pacote , e copiar a pasta do projeto para dentro deste diretório:

$ mkdir ./debian
$ mkdir -p ./debian/usr/share
$ cp -r smeunb/ ./debian/usr/share/

Após isso, deve-se criar uma subpasta DEBIAN onde serão armazenados os arquivos fundamentais para a construção e personalização do pacote:

$ mkdir ./debian/DEBIAN

Arquivos DEBIAN

editar

O diretório DEBIAN contém os seguintes arquivos:

  • control
  • conffiles
  • postinst
  • postrm
  • preinst
  • prerm

control

editar

Este arquivo é o mais importante pois é nele que estão as principais informações do pacote juntamente com algumas dependências. Este arquivo contém vários valores que as ferramentas de gerenciamento de pacotes usarão para gerenciar o pacote. Este é o conteúdo do arquivo:

Package: smeunb
Version: 0.1-1
Section: devel
Priority: optional
Architecture: all
Depends: python, python-django, python-flup, debconf, lighttpd
Maintainer: Matheus Silva <matheussilva.fga@gmail.com>
Description: web application for energy monitoring 
 To assist the energy monitoring of transducers installed in cadres
 of the University of Brasília. The idea is that each campus contained
 in the UnB can be able to use the tool and have a better knowledge of 
 how its energy consumption is over time, thus enabling possible strategies
 to help its economy.

A linha "Depends" consiste em uma lista de pacotes necessários para que o nosso pacote seja executado corretamente.

conffiles

editar

O Conffiles contêm os arquivos de configurações que geralmente ficam localizando no diretório /etc. Lá são alocados o nosso Django start script e o arquivo de configuração lighttpd.conf. o conteúdo do arquivo é:

/etc/init.d/django
/etc/lighttpd/lighttpd.conf

Deve-se criar subpastas dentro de /etc/ para armazenar os arquivos de configuração:

$ mkdir .debian/etc/init.d/
$ mkdir .debian/etc/lighttpd/

preinst

editar

O conteúdo desse script é executado antes da instalação do pacote.

#!/bin/bash
set -e
 
# stop django server
if [ -f /etc/init.d/django ]
then
  invoke-rc.d django stop
fi

postinst

editar

O conteúdo deste arquivo é executado depois que o pacote é descompactado.

#!/bin/sh
set -e
 
# Source debconf library.
. /usr/share/debconf/confmodule

ln -s /usr/share/smeunb/ /var/www/smeunb    
 
# register django
update-rc.d django defaults 90 >/dev/null

# start django
invoke-rc.d django start

db_stop

O conteúdo deste script é executado antes do pacote ser removido.

#!/bin/bash
set -e
 
# stop django server
invoke-rc.d django stop

postrm

editar

O conteúdo deste script é executado depois que pacote é removido.

#!/bin/bash
set -e
 
if [ "$1" = "purge" -a -e /usr/share/debconf/confmodule ]; then
    # Source debconf library.
    . /usr/share/debconf/confmodule
    # Remove my changes to the db.
    db_purge
fi
 
if [ "$1" = "remove" ]; then
 
# Source debconf library.
. /usr/share/debconf/confmodule
 
# remove Django start script
update-rc.d -f django remove
 
# Remove my changes to the db.
db_purge
fi

Configuração do Web Server e do Django init.d script

editar

A subpasta lighttpd possuíra o arquivo lighttpd.conf que será o responsável por gerenciar a configuração do web server. O conteúdo desse arquivo é:

server.modules = (
        "mod_access",
        "mod_alias",
        "mod_compress",
        "mod_redirect",
        "mod_fastcgi",
#       "mod_rewrite",
)

server.document-root        = "/var/www"
server.upload-dirs          = ( "/var/cache/lighttpd/uploads" )
server.errorlog             = "/var/log/lighttpd/error.log"
server.pid-file             = "/var/run/lighttpd.pid"
server.username             = "www-data"
server.groupname            = "www-data"

index-file.names            = ( "index.php", "index.html",
                                "index.htm", "default.htm",
                               " index.lighttpd.html" )

url.access-deny             = ( "~", ".inc" )

static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

## Use ipv6 if available
#include_shell "/usr/share/lighttpd/use-ipv6.pl"

dir-listing.encoding        = "utf-8"
server.dir-listing          = "enable"

compress.cache-dir          = "/var/cache/lighttpd/compress/"
compress.filetype           = ( "application/x-javascript", "text/css", "text/html", "text/plain" )

include_shell "/usr/share/lighttpd/create-mime.assign.pl"
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"

fastcgi.server = (
  "/smeunb.fcgi" => (
    "main" => (
      # Use host / port instead of socket for TCP fastcgi
      "host" => "127.0.0.1",
      "port" => 3033,
      "check-local" => "disable",
  ))
)

A subpasta init.d possuíra o script django que será o responsável por gerenciar o start e o stop da aplicação. O conteúdo desse script é:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          FastCGI servers for Django
# Required-Start:    networking
# Required-Stop:     networking
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Django FastCGI
#
 
DJANGO_SITE="smeunb"
SITE_PATH=/var/www
RUNFILES_PATH=$SITES_PATH/tmp
HOST=127.0.0.1
PORT_START=3033
RUN_AS=www-data
 
set -e
 
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="Django FastCGI"
NAME=$0
SCRIPTNAME=/etc/init.d/$NAME
 
#       Function that starts the daemon/service.
#
d_start()
{
    # Starting all Django FastCGI processes
    echo -n ", $DJANGO_SITE"
    if [ -f $RUNFILES_PATH/$DJANGO_SITE.pid ]; then
        echo -n " already running"
    else
       start-stop-daemon --start --quiet \
                       --pidfile $RUNFILES_PATH/$DJANGO_SITE.pid \
                       --chuid $RUN_AS --exec /usr/bin/env -- python \
                       $SITE_PATH/$DJANGO_SITE/manage.py runfcgi \
                       host=$HOST port=$PORT \
                       pidfile=$RUNFILES_PATH/$DJANGO_SITE.pid
    fi
}
 
#
#       Function that stops the daemon/service.
#
d_stop() {
    # Killing all Django FastCGI processes running
    echo -n ", $DJANGO_SITE"
    start-stop-daemon --stop --quiet --pidfile $RUNFILES_PATH/$SITE.pid \
                          || echo -n " not running"
    if [ -f $RUNFILES_PATH/$DJANGO_SITE.pid ]; then
        rm $RUNFILES_PATH/$DJANGO_SITE.pid
    fi
}
 
ACTION="$1"
case "$ACTION" in
    start)
        echo -n "Starting $DESC: $NAME"
        d_start
        echo "."
        ;;
 
    stop)
        echo -n "Stopping $DESC: $NAME"
        d_stop
        echo "."
        ;;
 
    restart|force-reload)
        echo -n "Restarting $DESC: $NAME"
        d_stop
        sleep 1
        d_start
        echo "."
        ;;
 
    *)
        echo "Usage: $NAME {start|stop|restart|force-reload}" >&2
        exit 3
        ;;
esac
 
exit 0


editar

changelog

editar
smeunb (0.1-1) unstable; urgency=low
  * Initial release.
    + Initial package
 
 -- Matheus Silva <matheussilva.fga@gmail.com>  Wed, 19 November 2016 00:00:00 +0000
editar
Upstream-Name: SME-UnB
source: https://gitlab.com/brenddongontijo/SME-UnB

Files: *
Copyright: 2016 Brenddon Gontijo Furtado
License: MIT

Files: *
Copyright: 2016 Mathes Silva <matheussilva.fga@gmail.com>
License: MIT

License: MIT

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


estes arquivos precisam ser alocados em um subdiretório chamado "doc". O arquivo changelog deve ser compactado de acordo com a política da comunidade Debian.

$ mkdir -p ./debian/usr/share/doc/smeunb

$ cp changelog copyright ./debian/usr/share/doc/smeunb/

$ gzip --best ./debian/usr/share/doc/smeunb/changelog

Construindo o Pacote

editar

Precisa-se mudar as permissões dos arquivos dento do diretório debian para que estes possam ser executados:

find ./debian -type d | xargs chmod 755

A flag 755 significa permissão de leitura, escrita e execução para o dono do arquivo (7), leitura e execução para usuários do mesmo grupo (5) e também para outros usuários (5).

Para construir o pacote, executa-se:

$ fakeroot dpkg-deb --build debian

$ mv debian.deb smeunb_0.1-1_all.deb

$ lintian smeunb_0.1-1_all.deb

Para instalar o pacote deve ser usado o comando

$ sudo dpkg -i smeunb_0.1-1_all.deb