terça-feira, 31 de maio de 2016

FreeNAS + VirtualBox

Introdução


Coisas que geralmente me incomodam tendem a sumir quando minha paciência com elas se esgotam. E uma das coisas que sempre me incomodou é o fato de precisar reinstalar meu notebook de trabalho, ou porque comprei um novo, ou porque resolvi trocar o HD por um maior/melhor ou porque alguma merda mesmo aconteceu e o mesmo precisou ser reinstalado.

Alguém pode dizer, basta criar uma partição de dados e colocar tudo lá. OK, é uma alternativa, mas e se quiser trocar o SO, quiser restaurar seu notebook para o padrão de fábrica, o particionamento que você achou que era o ideal não é mais, ou seja, uma das partições já está cheia e você vê a outra nadando em espaço livre até que você decide mexer nas partições e correr o risco de perder tudo.

Esse blog post visa documentar uma outra estratégia, não sei se é melhor, mais simples ou mais segura, mas é a abordagem que estarei seguindo a partir de agora para testar, e só o futuro me dirá se foi uma aposta acertada ou não.

Estratégia


Estarei usando duas tecnologias para essa nova abordagem: VirtualBox e FreeNAS.

A ideia básica é criar um servidor "NAS local" rodando em uma máquina virtual. O servidor NAS será criado utilizando o FreeNAS.

Uma vez que eu tenha um servidor NAS disponível, meu notebook estará montando os pontos de montagem disponível no NAS via NFS ou CIFS. Como isso, todos meus arquivos, programas, workspaces de trabalho, etc estarão armazenados nesse servidor NAS.

domingo, 8 de maio de 2016

Clonando um banco de dados HP Vertica

Introdução



Já precisei algumas vezes clonar uma base de dados Vertica para um outro servidor, para ter uma base idêntica de testes ou por alguma razão ter que refazer o servidor.

Mas sempre foi muito trabalhoso esse processo. Por vezes, é necessário a mesma configuração do servidor anterior, como estrutura de diretórios e/ou mesmo endereço IP. Algumas vezes atender esses requisitos é fácil, mas outras vezes não.

Existe na documentação oficial do Vertica formas de clonar uma base de dados, algumas vezes funcionou pra mim, outras vezes não devido alguma particularidade do meu ambiente.

Basicamente, o que eu gostaria de fazer era copiar os diretórios de dados/catálogo e configuração da máquina antiga para a máquina nova e pronto, subir o Vertica e ir pra casa feliz da vida. A ideia desse post é justamente mostrar como fazer isso, usando uma técnica que não está muito documentada, que é usar o 'Catalog Editor' para alterar configurações que estão armazenadas dentro dos catálogos e não em arquivos externos.

Alterar o catálogo é algo extremamento arriscado, então essa operação é por sua própria conta e risco. A boa notícia é que se estamos alterando em uma nova máquina e alguma besteira for feita isso não irá afetar as outras máquinas em produção, desde que você altere uma cópia do catálogo e não a única cópia que você tenha.

terça-feira, 5 de abril de 2016

Menu de Navegação usando Dashboard Component

Introdução


Dashboard Component é um novo componente existente no CDE quando o mesmo está configurado como RequireJS.

Ele permite carregar um certo dashboard em um dado placeholder (DIV) do layout CDE, como podíamos fazer antigamente com o velho iframe.

O mesmo permite ainda fazer a ligação de parâmetros para a passagem de valores do dashboard pai para o dashboard filho.

Esse post irá mostrar como criar um menu de navegação usando o Dashboard Component disponível no CDE.

Esta abordagem permitirá, entre outros, a criação de um portal ou painel de administração onde os links de um menu, que apontam para diferentes dashboards, sejam carregados em uma área específica do dashboard principal.

Além de termos um dashboard principal que é carregado apenas uma única vez, essa abordagem nos permite também termos filtros, seletores, entre outros componentes CDE compartilhados entre todos dashboards filhos.

Temos ainda a capacidade de passarmos valores do dashboard pai para o dashboard filho e vice-versa.

sábado, 2 de abril de 2016

Template addIn - tableComponent

Introdução


O template addIn faz parte do conjunto de addIn’s existentes para serem utilizados no tableComponent. Este é um addIn relativamente simples mas que trás uma grande flexibilidade para customizar as colunas de uma tabela, podendo alterar seu conteúdo baseado em um template html e um modelo de dados, ou até mesmo criar botões/checkbox’s/etc com eventos associados.

Referência


Template addIn Source Code

Valores default


Em geral todo addIn possui valores default que podem serem alterados para mudar seu comportamento, ou seja, customizar o comportamento do addIn de acordo com a necessidade de cada projeto. 

Uma forma de saber quais são os valores default que podem serem alterados, é abrir do código fonte do addIn e olhar para a seguinte parte do código:
defaults: { templateType: 'mustache', template: '<div>{{items}}</div>', rootElement: 'items', formatters: [], events: [], modelHandler: function(st, opt) { var model = {}; model[opt.rootElement] = $.parseJSON(st.value); return model; }, postProcess: function(info) {} }

Para o nosso caso, os parâmetros acima são exatamente aqueles que podemos alterar e utilizar.

Vamos passar por cada um deles para entender qual o seu papel dentro de todo o processo.

Entendendo e alterando os valores default



templateType

Permite informar qual o tipo de template html que será utilizado. As opções possíveis de template são ‘mustache’ e ‘underscore’. 

template

É o template html de acordo com o templateType escolhido. Qualquer código html aqui descrito será inserido dentro da célula que está sendo processada e os tokens (ou expressões) definidos no template serão substituídos pelos dados existentes no modelo.

rootElement 

Este é o nome que será utilizado como a raiz do seu modelo de dados.

formatters

Um formatter permite formatar o valor de uma expressão para ser exibida. Essa ‘formatação’ pode ser na forma de exibição, como transformar todas as letras para maiúscula, como passar um valor adicional para ser multiplicado com o valor da expressão.

Formatters podem ser concatenados usando um ‘|’. O atributo formatters espera um array composto de array’s de dois elementos, como:

formatters: [ [ ‘formatter_name’, function(str, id) {} ], [ ‘uppercase’, function(str, id) {} ], [ ‘calcPercent’, function(str, id) {} ] ]


  • formatter_name: um nome que representa o que a função faz. 
  • function(str, id): função que irá realizar o trabalho duro. O primeiro parâmetro da função é o valor da expressão ao qual você pediu para aplicar o formatter. O segundo parâmetro é um valor adicional que você possa e vir a precisar dentro da sua função. O retorno da sua função deverá ser o novo valor que deseja exibir. 
Para usar o formatter no seu template, basta aplicá-lo na expressão que deseja. Considere o seguinte template :

<div> <div> <span> Name: {{name | formatter : "uppercase"}} </span> </div> <div> <span> Percent: {{value | formatter : “calcPercent” : 100}} % </span> </div> </div>

Então, o formatter de nome ‘uppercase’ deve receber no parâmetro ‘str’ o valor de ‘name’ e retornar este em letra maiúscula. 

E o formatter de nome ‘calcPercent’ deve receber no parâmetro ‘str’ o valor de ‘value’ e no parâmetro ‘id’ o número 100, e retornar uma conta que provavelmente será ‘str’ * ‘id’. 

events

É um array composto de array's de dois elementos, onde você pode configurar diferentes tipos de eventos e indicar qual elemento do template esses eventos devem ser registrados. Veja:

events: [ [ ‘event,selector’, function(e) {} ] ]


  • event,selector: é o nome do evento e um seletor, separado por uma vírgula, com o seletor indicando onde deve ser feito o bind dentro do template para o respectivo evento. O ‘seletor’ é opcional e se não for informado, o bind será aplicado no <td> da célula. 


  • function(e): é a respectiva função do evento. Como parâmetro é passado dados do evento e dentro do ‘e.data’ você tem informações adicionais relacionadas ao seus dados. 
Como exemplo, imagine o seguinte template:

<div> <div> <span> Name: {{name | formatter : "uppercase"}} </span> </div> <div> <span> Percent: {{value | formatter : “calcPercent” : 100}} % </span> </div> <button id=‘btnDelete’>Delete!</button> </div>

E a seguinte configuração do evento:

events: [ [ 'click,#btnDelete’, function(e) { $(this).closest('tr').remove(); } ]   ]

O exemplo acima irá registrar um evento de click no botão e que permitirá remover a respectiva linha.

modelHandler

modelHandler é uma função onde você deverá criar o modelo de dados apropriado para o template html que foi definido. 

Essa função recebe dois parâmetros: 

  • st: informações sobre os seus dados. 
  • opt: as opções passadas para o addIn, que basicamente são os valores default com suas alterações. Isso é importante pois você pode definir uma nova função dentro do default e utilizá-la dentro do modelHandler. 

Considerando nosso template acima, vamos considerar que a coluna onde estou aplicando o template tenha dados no seguinte formato : ‘Paulo/0.75’ 

A função abaixo cria um modelo de dados para o template definido com base no formato da string acima.

modelHandler: function(st, opt) { var model = {}; var _values = st.value.split('/'); var ret = {}; ret.name = _values[0]; ret.value = _values[1]; return model[opt.rootElement] = ret; }

A função acima irá retornar o seguinte objeto:

{ items:{ name: ‘Paulo’, value: 0.75 } }

Repare que o ‘root’ do objeto deve ser o nome definido no ‘rootElement’; 

postProcess 

Caso tenha a necessidade de fazer algum processamento após a execução do addIn, use o postProcess para definir sua função. 

A função possui apenas um parâmetro, que recebe um objeto contendo os mesmo valores recebidos pelo addIn no início da sua execução.

info = {target: tgt, status: st, options: opt}

Utilizando o addIn


Como qualquer addIn para o tableComponent, basta definir o nome ‘template’ na propriedade ‘Column Type’ para a coluna onde o mesmo será aplicado.

Configure no preExecution do tableComponent o addIn para alterar qualquer um dos valores default, como mostrado no exemplo abaixo:

function f(){ this.setAddInOptions("colType","template",function(state){ return { events: [ [ 'click,#btnDelete’, function(e) { $(this).closest('tr').remove(); } ] ], formatters: [ [ ‘uppercase’, function(str, id) {} ], [ ‘calcPercent’, function(str, id) {} ] ], template: '<div><div><span>Name: {{name | formatter : "uppercase"}}</span></div><div><span>Percent: {{value | formatter : “calcPercent” : 100}} %</span></div><button id=“btnDelete”>Delete!</button></div>', modelHandler: function(st, opt) { var model = {}; var _values = st.value.split('/'); var ret = {}; ret.value = _values[0]; ret.expected = _values[1]; return model[opt.rootElement] = ret; }, postProcess: function(info) {} }; }); }

Exemplo


Veja o vídeo abaixo: