Category Archives: Software Livre

(Português) Primeiros passos com Docker

Sorry, this entry is only available in Brazilian Portuguese. For the sake of viewer convenience, the content is shown below in the alternative language. You may click the link to switch the active language.

Docker é um sistema de virtualização, porém, não tradicional. Enquanto em um ambiente de virtualização tradicional nós temos um S.O. completo e isolado (Virtualbox, Xen etc), dentro do Docker nós temos recursos isolados que utilizam bibliotecas de kernel em comum (entre host e container), isso é possível pois o Docker utiliza como backend o nosso conhecido LXC. (conhecido de quem????)

O Docker possibilita o empacotamento de uma aplicação ou ambiente inteiro dentro de um container, e a partir desse momento o ambiente inteiro torna-se portável para qualquer outro Host que contenha o Docker instalado.

Isso reduz drasticamente o tempo de deploy de alguma infraestrutura ou até mesmo aplicação, pois não há necessidade de ajustes de ambiente para o correto funcionamento do serviço, o ambiente é sempre o mesmo, configure-o uma vez e replique-o quantas vezes quiser.

Para desenvolvedores, a criação de uma imagem para a aplicação, garante que o resultado obtido no ambiente de desenvolvimento será o mesmo nos ambientes de homologação e de produção.

O Docker agiliza o processo de levantar ambientes de testes. Basta um comando e uma aplicação estará pronta para rodar em instantes, sem a necessidade de executar o velho passo a passo de instalação que consome algumas horas de trabalho.

Instalar Docker no Mint

Siga a instalação disponível neste link

https://www.simon-hardy.com/blog/post/install-docker-on-linux-mint-18

Por padrão, apenas o usuário root pode executar comandos da docker. Para permitir que seu usuário de trabalho possa executar comandos na Docker, siga os seguintes passos:

sudo usermod -aG docker seu_usuario

sudo setfacl -m user:seu_usuario:rw /var/run/docker.sock

Primeiros passos

Para entender como operar o Docker, vamos começar por algo simples. Vamos rodar uma aplicação como  o OTRS (sistema de help desk)

O comando básico é o seguinte:

docker run --name meu_otrs -d ligero/otrs_easy

Sobre o comando acima:

run: é comando utilizado para criar um container

–name, é importante para facilitar o trabalho de gestão dos containers. Se você não passa um nome, o Docker cria um por conta própria e pode ser difícil de lembrar do que se trata, depois de ter uma dezenas de containers criados

-d (detached), significa que o container vai rodar como um “serviço”, ou seja, você não terá acesso ao shell do mesmo durante o momento da criação, apenas depois se desejar

ligero/otrs_easy, nome da imagem que será executada como base do container.

O Docker verifica inicialmente se imagem existe na máquina local, caso contrário tenta encontrá-la no site hub.docker.com

Voltando aos nossos primeiros passos, você pode verificar como está o andamento da inicialização de sua docker, através do comando logs:

docker logs meu_otrs

O sistema irá exibir todo o log de inicialização do container. No exemplo do OTRS, quando você ver a linha abaixo, saberá que a aplicação já está pronta para ser acessada:

2018-02-16 17:51:07,501 INFO success: apache2 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

Cada imagem terá sua própria maneira de informar que está pronta para utilização

Neste exemplo estamos criando um container OTRS que responde na porta 80 do container. Cada Container recebe um IP dinâmico. Precisamos saber qual é o ip que foi concedido para o container, de tal forma que possamos acessá-lo através do navegador. Para isso podemos acessar o Shell do container, através do comando abaixo:

docker exec -ti meu_otrs /bin/bash

Explicando:

-ti de forma resumida, é necessário colocar esta opção para fazer com que o terminal de sua máquina se conecte no terminal do container

/bin/bash o shell que deseja executar

Dentro do shell do container, execute:

ip a

Para fechar o bash do container, pressione Crtl+P+Q

Você também pode executar um comando no container diretamente, sem abrir um terminal do mesmo. Veja como obter o ip diretamente:

docker exec meu_otrs ip a

Com o IP obtido, acesse então o navegador

http://ip_do_container/otrs/index.pl

Formas mais avançadas de se criar um container

Executando uma versão específica da imagem:

Por padrão, quando escolhemos uma imagem, tal como ligero/otrs_easy, o docker vai tentar obter a última versão da mesma, ou seja, neste caso, ligero/otrs_easy:latest.

Você pode sempre escolher qual versão deseja rodar de uma determinada imagem, por exemplo:

docker run --name meu_otrs -d ligero/otrs_easy:5.0.26

Você irá encontrar as versões disponíveis para execução de cada aplicação em sua documentação ou na aba “tags” de seu repositório no hub.docker.com.

Mapeando portas do container para sua máquina

Que tal executar esta aplicação acima e fazer com que ela responda em http://localhost/otrs/index.pl ao invés do http://ip_do_container/otrs/index.pl?

Isto é possível através do parâmetro -p:

docker run --name meu_otrs -p 80:80 -d ligero/otrs_easy:5.0.26

Do lado esquerdo, temos a porta do container (80), do lado direito, a porta na qual queremos fazer o mapeamento em nossa máquina.

Note que se houver algum outro serviço rodando na porta 80 de sua máquina, não será possível mapear a porta deste container. Neste caso você pode escolher outra porta local, por exemplo, 8080:

docker run --name meu_otrs -p 80:8080 -d ligero/otrs_easy:5.0.26

Variáveis de inicialização

Muitas imagens, permitem uma customização de paramêtros durante sua inicialização através das variáveis de ambiente.

O OTRS por exemplo, permite que seja definido o idioma padrão da aplicação, durante sua execução. Para isso, usamos a opção -e junto com o parâmetro que é indicado na documentação da imagem:

docker run --name meu_otrs -e OTRS_DEFAULT_LANGUAGE=pt_BR -p 80:80 -d ligero/otrs_easy:5.0.26

O conjunto de variáveis de inicialização que permitem parametrização dos containers está disponível na documentação de cada imagem.

Usando volumes persistentes

Um ponto importante sobre os containers Docker, é que seus dados, a princípio, são voláteis, ou seja, quando você remover um container com o comando “rm”, todos os arquivos deste container serão apagados.

No entanto, há uma forma de criar volumes ou pastas persistentes, ou seja, pastas que são armazenadas no seu computador e não são apagadas quando o container é apagado:

docker run -ti --name meu_otrs -v otrs_mysql:/var/lib/mysql -v otrs_app:/opt/otrs -p 80:80 -e OTRS_DEFAULT_LANGUAGE=pt_BR ligero/otrs_easy:5.0.26

Observe no comando acima, que criamos um volume de nome otrs_mysql, que será mapeado na pasta /var/lib/mysql da container e armazenará os arquivos do mysql, e um outro volume otrs_app que armazenará os dados da aplicação.

O Docker armazena estes volumes na pasta /var/lib/docker/volumes da máquina hospedeira.

Você também pode fazer o mapeamento de uma pasta já existente na máquina hospedeira para dentro do container. Neste caso, basta passar o caminho completo da mesma:

docker run -ti --name meu_otrs -v /opt/clientex/mysql:/var/lib/mysql -v /opt/clientex/otrs:/opt/otrs -p 80:80 -e OTRS_DEFAULT_LANGUAGE=pt_BR ligero/otrs_easy:5.0.26

Gerenciando os containers

Verificando os containers em execução

Para verificar quais containers estão em execução no momento, utilize o comando ps:

docker ps

Você terá acesso a uma tabela com as seguintes informações de cada container:

  • CONTAINER ID: Id gerado de forma automática. Quando você for realizar alguma operação no container como parar, apagar ou reiniciar, você poderá utilizar seu ID ou seu nome.
  • IMAGE: Imagem que deu origem ao container. No nosso exemplo, seria ligero/otrs_easy:5.0.26
  • COMMAND: o comando de inicialização do container. Um comando padrão é especificado pelo criador da imagem, mas também há a possibilidade de se rodar um container com um comando de inicialização persolinalizado.
  • CREATED: Tempo desde sua criação.
  • STATUS: Quando tempo desde a última vez que foi inicializado.
  • PORTS: Porta expostas do container.
  • NAMES: Nome do container.

Você pode ver também uma listagem de todos os containers, incluindo os que estão em pausa ou paralizados com o seguinte comando:

docker ps a

Parando e retomando a execução de um container

Sim! Você pode parar um container para retomar sua execução posteriormente. O ato de parar um container não implica na exclusão de seus arquivos

Para para um container, execute o comando:

docker stop nome_do_container

Para inicializá-lo:

docker start nome_do_container

Importante: Ao inicializar um container novamente, ele poderá pegar um IP diferente do que o que havia na execução anterior.

Removendo definitivamente um Container

Para remover um container, utilize o seguinte comando:

docker rm nome_do_container

O container precisa estar parado para que ação seja executada. Se quiser excluir um container em execução, utilize a opção -f:

docker rm -f nome_do_container

Criando uma imagem personalizada, a partir de um container em execução

Não é muito usual nem muito recomendado, mas você pode criar uma imagem local de seu container, com os arquivos que você modificou durante a execução do mesmo. Isto pode ser útil para estudos e replicações rápidas. Para isso, utilize o comando abaixo:

docker commit meu_container nomedaminhaimagem:1.2.3

Note que o “nomedaminhaimagem”, pode ser criado neste caso de forma livre, pois você está apenas criando uma imagem local. Você pode também especificar a versão desta imagem, como fizemos no comando acima.

Para criar um novo container a partir desta imagem modificada, basta utilizar o comando run apontando para ela:

docker run --name meu_container nomedaminhaimagem:1.2.3

Novamente, este recurso não é muito utilizado, visto que uma das coisas mais belas da utilização da Docker, são as receitas de criação das imagens (Dockerfile). Através da Dockerfile, qualquer pessoa sabe exatamente como aquela imagem foi gerada. Através do recurso de commit no entanto, não será possível saber quais modificações deram origem a uma determinada imagem.

Gerenciando Imagens

Verificando as imagens locais

Para verificar todas as imagens que estão em seu computador e o respectivo tamanho de cada uma delas, execute o comando abaixo:

docker images

Removendo uma imagem

Para remover uma imagem, execute:

docker rmi nome_da_imagem:versao

Se existirem containers criados com esta versão da imagem a ser apagado, você deverá utilizar a opção -f para forçar a exclusão:

docker rmi -f nome_da_imagem:versao

Este post foi publicado por mim também no Blog da Complemento:

Primeiros passos com Docker

(Português) O impacto que gerei, com o opensource

Sorry, this entry is only available in Brazilian Portuguese. For the sake of viewer convenience, the content is shown below in the alternative language. You may click the link to switch the active language.

Olá! Passando aqui no meu blog, para compartilhar um post que fiz no Facebok, após uma visita ao Senado Federal em Julho de 2018:

Nos últimos dois dias realizei um trabalho para área de TI do Senado Federal. Não tinha noção, mas no universo da TI que navego, sou conhecido como “Richieri” (E eu sempre achei que Richieri ou “Richieri do Acordeon” nunca seria um bom nome artístico, quem diria hahha).

Tenho um blog antigo onde compartilhei muito conhecimento e virei referência para um monte de gente e esse é o endereço (richieri.com) e por isso me conhecem assim.

Teve gente que abriu empresa seguindo meus passos e pedindo meus conselhos, teve gente que resolveu seus problemas corporativos lendo meus materiais, gente que ganhou muito dinheiro (ou ao menos economizou muito dinheiro) usando meus tutoriais, sem me dar nada em troca é claro, e isto é o opensource e está tudo certo . E lá no Senado, muitas pessoas queridas vieram me agradecer nos últimos dias pela dedicação que tive e tenho em compartilhar conhecimento, de forma aberta.

Teve até um rapaz veio me agradecer e disse que me usou de referência no TCC dele e isso é muito gratificante para mim  sou referência Acadêmica, logo eu, o cara da Aprendizagem Informal, quem diria hahahah. Confesso que isso não dá muito dinheiro, às vezes até não dá dinheiro, mas quando você senta com uma Gestora de TI do Senado, que diz que o Senado adotou uma tecnologia opensource graças a um Webinar que você realizou há alguns anos atrás e aos materiais que publicou, bem, isso é bem gratificante!

Que bom que contribuí de forma espontânea e altruísta com muitas pessoas. Que bom que ajudei muitas empresas e ONGs. E que bom que ajudei muitos e muitos órgãos públicos municipais, estaduais e federais como prefeituras, tribunais, secretarias, ministérios, Câmara dos Deputados, Senado e órgãos militares a melhorarem seus processos de forma a atender melhor as pessoas e economizarem muiiiiito nosso dinheiro (algumas dezenas de milhões de reais), compartilhando conhecimento de forma voluntária. Bom este deve ter sido parte do meu “Seva” até agora 

Gratidão!

Ronaldo Richieri

Complemento

http://www.complemento.net.br

(Português) Workshop de OTRS no FISL 2013

Sorry, this entry is only available in Brazilian Portuguese. For the sake of viewer convenience, the content is shown below in the alternative language. You may click the link to switch the active language.

Nesta quarta feira, 3 de Julho de 2013, apresentei o OTRS para pessoas do Governo, iniciativa privada, desenvolvedores e estudantes da PUC de Porto Alegre, juntamente com os camaradas Thiago Pacheco, Fabricio Pacheco e Leonardo Thietbohl Rodrigues, com quem formei a Complemento.

Para nós foi um grande prazer realizar esta apresentação e descobrir que nosso trabalho de anos de divulgação das soluções de software livre tem repercutido. Várias pessoas me agradeceram pessoalmente (inclusive um rapaz do Ministério das Comunicações), pelos módulos e artigos que sempre fiz questão de produzir e publicar na comunidade.

Recebemos também um convite da direção da Associação do Software Livre para participar de um jantar realizado para os palestrantes e ver um dos pais do software livre, Jon Maddog Hall, vestido de monge, com brincos e pirceings.

Mais uma pra recordar.

libXtst.so.6: cannot open shared object file: No such file or director

This error occurred trying to open some Java applications.

My Operation System is Linux Mint Nadia 64 bits (same base of Ubuntu 64 bits).

libXtst was already installed, but the error still happen. I could solve it installing the 32 bits version of the lib:

sudo apt-get install libxtst6:i386

Hope it helps you to!

One way of creating approval workflows with OTRS

Approval workflows can be created in different ways on OTRS.

There is a simple way to do that using ITSMIncidentProblemManagement.

With ITSMIncidentProblemManagement package, you get a Decision link on ticket menu. Obviously some configurations have to be done in order to this link be shown only for some users like a department manager (we will call this role decision makers now on). This also can be made in different ways.

I’d like to show a way to create those workflows. I made it this days and see to be efficient.

The concept

We have a group called Service Desk which watchs a queue called “ServiceDesk”. This team receives and process all tickets on the system and try to solve them. They also send some tickets to approval when it’s needed.

So we have to create a queue for each decision group. We may have decision makers on IT and decision makers on HR department for example.

We have those queues on the system:

  • ServiceDesk
  • Ask Approval
    • IT Decision Makers
    • HR Decision Makers
  • Infraestructure specialist
  • Applications specialist

When the ServiceDesk identifies a request which needs approval, they send it to the respective decision maker group.

The Decision Maker approves or not the ticket and he or she move it again to the service desk queue.

How to show Decision link only for decision makers?

Decision Makers will be registered on 2 groups: decisionit and decisionhr

Go to the SysConfig and access Ticket -> Frontend::Agent::Ticket::MenuModule

Find Ticket::Frontend::MenuModule###420-Decision and add a key called “Group” with this content: “rw:decisionit;rw:decisionhr”.

And it’s done!

Making it better

To make the decision maker’s life easier, I created a module (and a package) that moves the ticket to a “next defined queue”, in the same screen where the approval is done. In our example, the ticket will be moved back to the ServiceDesk queue.

You can download this package here.

After it’s installation, you may configure it on Sysconfig -> Ticket -> Frontend::Agent::Ticket::ViewDecisionMove

Other ways

I think OTRS is a very flexible (and not high documented) tool. So, if you know another way to make decisions workflows, please share with us 🙂

Single sign on between Joomla and OTRS Customer Interface

I have just developed my first version of a module called Kernel::System::CustomerAuth::JoomlaSSO

It allows Joomla logged users to access directly OTRS Customer interface (with automatic login) with no need to type user and pw again. OTRS Customer Backend should be the same as joomla for it to work.

Some customizetion are need on Joomla and OTRS side, so it’s not a module yet.

If you are interested on it, contact me please.

(Português) OTRS – Listas de Controle de Acessos (Access Control Lists ou ACL’s)

Sorry, this entry is only available in Brazilian Portuguese. For the sake of viewer convenience, the content is shown below in the alternative language. You may click the link to switch the active language.

As ACL’s servem para incrementar o sistema de permissões do OTRS. Com elas é possível restringir escolhas de atributos do ticket ou ações possíveis de serem tomadas de acordo com as propriedades atuais do mesmo (fila atual, estado etc).

Atualmente criamos as ACLs com implementação de códigos no arquivo Kernel/Config.pm (recomendado) e não há interface gráfica para isso. Com sua utilização, é possível inclusive implementar pequenos workflows no sistema.

Vejamos um exemplo de ACL que restringe um chamado de prioridade alta (5) para que seja permitido move-lo apenas para uma fila chamada Alerta:

# ticket acl
$Self->{TicketAcl}->{'ACL-Nome-2'} = {
  # match properties
  Properties => {
    # current ticket match properties
    Ticket => {
    Queue => ['Raw'],
    Priority => ['5 very high'],
    }
  },
  # return possible options (white list)
  Possible => {
    # possible ticket options (white list)
    Ticket => {
      Queue => ['Alerta'],
    },
  },
};

Neste exemplo, é bom que se deixe claro que a única ação que restringimos foi a alteração de fila. As outras ações continuam possíveis de acordo com as parametrizações e permissões do usuário. Por exemplo, ainda é possível adicionar notas ao chamado, responde-lo, mudar seu status para qualquer um disponível no sistema.

É possível notar que existem dois blocos de código neste exemplo acima. O  primeiro com comentário “# match properties” é a definição das propriedades atuais do ticket, como se fosse um filtro onde definimos em que ocasiões essa ACL será aplicada.

No segundo bloco definimos as restrições ou permissões que os tickets que “cairem” nesta ACL sofrerão.

Action

Vamos aprimorar este exemplo fazendo com que um ticket de prioridade 5 não possa ser fechado na fila Raw através da tela “Fechar” (módulo AgenteTicketClose). Ficaria assim:

# ticket acl
	$Self->{TicketAcl}->{'ACL-Alerta5'} = {
	  # match properties
	  Properties => {
	    # current ticket match properties
	    Ticket => {
	    Queue => ['Raw'],
	    Priority => ['5 very high'],
	    }
	  },
	  # return possible options (white list)
	  Possible => {
	    # possible ticket options (white list)
	    Ticket => {
	      Queue => ['Alerta'],
	    },
	    Action => {
              AgentTicketClose => 0,
            },
	  },
	};

Além de restringir a escolha dos atributos dos tickets, podemos definir quais ações (ou telas) poderão ser exibidas ou não ao agente/cliente. Neste exemplo acima, além de permitir apenas que o agente mova este chamado para fila Alerta, também desabilitamos a tela e o botão “Fechar” (módulo AgenteTicketClose). Assim não encorajaremos o atendente a fechar os tickets de prioridade 5 na fila Raw.

PossibleNot

No entanto, o atendente da ainda pode encerrar o chamado se este estiver na fila Raw, pois não desabilitamos a escolha os estados “Fechado” com e sem exito, ou seja, ele não verá a tela fechar, mas pode fechar o chamado caso clique em “Chamada telefônica realizada” e escolha um dos estados fechado.

Vamos simular então uma ACL onde o atendente nunca poderá fechar um chamado se o mesmo estiver na fila Raw com prioridade 5. Ficaria assim:

# ticket acl
$Self->{TicketAcl}->{'ACL-Alerta5'} = {
  # match properties
  Properties => {
    # current ticket match properties
    Ticket => {
    Queue => ['Raw'],
    Priority => ['5 very high'],
    }
  },
  # return possible options (white list)
  Possible => {
    # possible ticket options (white list)
    Ticket => {
      Queue => ['Alerta'],
    },
    Action => {
      AgentTicketClose => 0,
    },
  },
  PossibleNot => {
    # possible not ticket options
    Ticket => {
        State => ['closed successful','closed unsuccessful'],
    },	  
  },
};

Notem que adicionamos um terceiro bloco de código, o “PossibleNot”. Ali definimos o que não será possível fazer. Para tentar esclarecer mais:

  • Properties: “Quais chamados ou situações”. No nosso caso, todos os chamados que estiverem na fila Raw com prioridade 5 (Muito Alta)
  • Possible: “É possível apenas isto”! No nosso caso, em relação a mover chamados, restringimos para que seja apenas possível mover para a fila Alerta
  • PossibleNot: “Não é possível apenas isto, o resto pode”! No nosso caso, o atendente poderá escolher todos os estados disponíveis de ticket, menos “Fechado com sucesso” e “Fechado sem sucesso”.
Expressões Regulares

Também é possível utilizar expressões regulares. No exemplo abaixo (retirado da documentação oficial), exibimos apenas serviços que comecem com a palavra “Hardware”, para um ticket estiver na fila HW ou uma de suas subfilas:

$Self->{TicketAcl}->{'Only-Hardware-Services-for-HW-Queues'} = {
       # match properties
        # note we don't have "Ticket => {" because there's no ticket yet
        Properties => {
        Queue => {
            Name => ['[RegExp]HW'],
            }
        },
        # return possible options
        Possible => {
            # possible ticket options
            Ticket => {
                Service => ['[RegExp]^(Hardware)'],
            },
        },
    };

Vale a pena lembrar que os serviços começados com a palavra “Hardware” continuaram sendo exibidos em outras filas. Foi utilizando esse tipo de ACL que construí um módulo que permite escolher os serviços que queremos exibir em cada uma das filas do sistema.

 

Parâmetros possíveis

Aqui temos uma lista de todos os parâmetros possíveis para as ACLs:

# ticket acl
    $Self->{TicketAcl}->{'ACL-Name-Test'} = {
        # match properties
        Properties => {
            # current action match properties
            Frontend => {
                Action => ['AgentTicketPhone', 'AgentTicketEmail'],
            },
            # current user match properties
            User => {
                Group_rw => [
                    'hotline',
                ],
            },
            # current user match properties
            Ticket => {
                Queue => ['Raw'],
                State => ['new', 'open'],
                Priority => ['some priority'],
                Lock => ['lock'],
                CustomerID => ['some id'],
                CustomerUserID => ['some id'],
                TicketFreeKey1 => ['some key'],
                TicketFreeKey2 => ['some key'],
                # ...
                TicketFreeKey8 => ['some key'],
                TicketFreeText1 => ['some value'],
                TicketFreeText2 => ['some value'],
                # ...
                TicketFreeText8 => ['some value'],
            }
        },
        # return possible options (white list)
        Possible => {
            # possible ticket options (white list)
            Ticket => {
                Queue => ['Hotline', 'Koordination'],
                State => => ['some state'],
                Priority => ['5 very high'],
                TicketFreeKey1 => ['some key'],
                TicketFreeKey2 => ['some key'],
                # ...
                TicketFreeKey8 => ['some key'],
                TicketFreeText1 => ['some value'],
                TicketFreeText2 => ['some value'],
                # ...
                TicketFreeText8 => ['some value'],
            },
            # possible action options (white list)
            Action => {
                AgentTicketLock => 1,
                AgentTicketZoom => 1,
                AgentTicketClose => 1,
                AgentTicketPending => 0,
                AgentTicketNote => 1,
                AgentTicketHistory => 0,
                AgentTicketPriority => 1,
                AgentTicketFreeText => 0,
                AgentTicketHistory => 1,
                AgentTicketCompose => 1,
                AgentTicketBounce => 1,
                AgentTicketTicketPrint => 0,
                AgentTicketForward => 1,
                AgentTicketTicketLink => 1,
                AgentTicketPrint => 1,
                AgentTicketPhone => 1,
                AgentTicketCustomer => 1,
                AgentTicketOwner => 0,
            },
        },
        # remove options (black list)
        PossibleNot => {
            # possible ticket options (black list)
            Ticket => {
                Queue => ['Hotline', 'Koordination'],
                State => ['closed', 'removed'],
            },
        },
    };

 

Consulte também: