Mudanças entre as edições de "Projeto: Administração Centralizada de Sistemas Operacionais"
(→NFS) |
|||
(297 revisões intermediárias por 3 usuários não estão sendo mostradas) | |||
Linha 1: | Linha 1: | ||
==Projeto== | ==Projeto== | ||
− | O projeto "'''Administração Centralizada de Sistemas Operacionais'''" | + | O projeto "'''Administração Centralizada de Sistemas Operacionais'''" foi realizado no Instituto Federal de Educação, Ciência e Tecnologia de Santa Catarina Campus São José, no período de 02/08/2010 à 22/12/2010 pelo aluno Gustavo Paulo Medeiros Da Silva (4ª fase, CST Sistemas de Telecomunicações) e orientado pelo professor [[Ederson Torresini]]. |
==Objetivos== | ==Objetivos== | ||
Linha 7: | Linha 7: | ||
==Diário de Bordo== | ==Diário de Bordo== | ||
===06/08/2010 (semana 1)=== | ===06/08/2010 (semana 1)=== | ||
− | Nesta primeira semana foi feita uma pesquisa para conhecer e comparar programas que copiam imagens de um SO para outros computadores, através da rede. | + | Nesta primeira semana foi feita uma pesquisa para conhecer e comparar programas que copiam imagens de um SO para outros computadores, através da rede. A seguir tem uma tabela comparando os programas pesquisados. |
Linha 15: | Linha 15: | ||
| colspan="6" align="center" | Armazenamento de partição || colspan="2" | Operações pós-instalação | | colspan="6" align="center" | Armazenamento de partição || colspan="2" | Operações pós-instalação | ||
|- | |- | ||
− | | Projeto || [http://pt.wikipedia.org/wiki/Sistema_operativo S.O.] baseado em...|| Livre? || [http://pt.wikipedia.org/wiki/Multicast Multicast] || [http://pt.wikipedia.org/wiki/Anexo:Lista_de_protocolos_de_redes Protocolos] || [http://pt.wikipedia.org/wiki/Sistema_de_ficheiros Sistema de arquivo] || Trocar o nome da máquina || | + | | Projeto || [http://pt.wikipedia.org/wiki/Sistema_operativo S.O.] baseado em...|| Livre? || [http://pt.wikipedia.org/wiki/Multicast Multicast] || [http://pt.wikipedia.org/wiki/Anexo:Lista_de_protocolos_de_redes Protocolos] || [http://pt.wikipedia.org/wiki/Sistema_de_ficheiros Sistema de arquivo] || Trocar o nome da máquina || redimensionamento de partição |
|- | |- | ||
− | | [http://www.fogproject.org/wiki/index.php?title=Main_Page FOG Project] || UNIX, DOS || Sim || Sim || TFTP, UDP, TCP, NFS || NTFS, XFS, JFS, HPFS, FAT16/32, Reiser3, EXT2, EXT3 || Sim || Sim | + | | [http://www.fogproject.org/wiki/index.php?title=Main_Page FOG Project] || UNIX, DOS || Sim || Sim || TFTP, UDP, TCP, NFS || NTFS, XFS, JFS, HPFS, FAT16/32, Reiser3, EXT2, EXT3 || Sim**** || Sim*** |
|- | |- | ||
| [http://en.wikipedia.org/wiki/Clonezilla Clonezilla] || UNIX || Sim || Sim || TFTP, UDP, TCP || NTFS, FAT16/32, EXT2, EXT3, Reiserfs || Não* || Sim** | | [http://en.wikipedia.org/wiki/Clonezilla Clonezilla] || UNIX || Sim || Sim || TFTP, UDP, TCP || NTFS, FAT16/32, EXT2, EXT3, Reiserfs || Não* || Sim** | ||
Linha 33: | Linha 33: | ||
(*) É necessário trocar o nome dos computadores para não haver confusão na rede. Trocar o nome, | (*) É necessário trocar o nome dos computadores para não haver confusão na rede. Trocar o nome, | ||
máquina por máquina.<br/> | máquina por máquina.<br/> | ||
− | (**) Não é possível utilizar a rede, tem que realizar o boot no cd de instalação do produto. | + | (**) Não é possível utilizar a rede, tem que realizar o boot no cd de instalação do produto.<br/> |
+ | (***) O redimensionamento é feito apenas com imagens do sistema Windows. Para esse caso redimensionar é colocar uma imagem de um disco rígido de 200 GB em um disco rígido de 10GB, enquanto os dados são menores do que 10GB.<br/> | ||
+ | (****) A troca é possível apenas para o Windows. | ||
===11/08/2010 (semana 2)=== | ===11/08/2010 (semana 2)=== | ||
Linha 83: | Linha 85: | ||
Ao longo das últimas semanas tivemos dificuldades com a montagem do cenário de testes, detalhes despercebidos estavam atrapalhando a execução do projeto que aos poucos foram encontrados e eliminados. | Ao longo das últimas semanas tivemos dificuldades com a montagem do cenário de testes, detalhes despercebidos estavam atrapalhando a execução do projeto que aos poucos foram encontrados e eliminados. | ||
====Problemas==== | ====Problemas==== | ||
− | 1°- Para o servidor de imagens funcionar é preciso que a instalação do Ubuntu esteja em inglês. | + | *1° - Para o servidor de imagens funcionar é preciso que a instalação do Ubuntu esteja em inglês.<br/> |
− | 2°- Para as vlans se "enxergarem" é preciso que as máquinas virtuais estejam na mesma rede. No VirtualBox por padrão, na configurações de rede no campo '''conectado a''' está selecionado a opção '''NAT''', opção que separa a máquina virtual da rede do hospedeiro, para as vlans funcionarem é preciso selecionar a opção '''Interface do Hospedeiro''' ou '''Placa em modo Bridge'''. | + | *2° - Para as vlans se "enxergarem" é preciso que as máquinas virtuais estejam na mesma rede. No VirtualBox por padrão, na configurações de rede no campo '''conectado a''' está selecionado a opção '''NAT''', opção que separa a máquina virtual da rede do hospedeiro, para as vlans funcionarem é preciso selecionar a opção '''Interface do Hospedeiro''' ou '''Placa em modo Bridge'''.<br/> |
− | 3°- Para o VirtualBox dá o boot pela rede, ele irá procurar o servidor na rede real, desprezando a vlan. Para dá o boot na vlan, é preciso configurar uma interface vitual no computador hospedeiro e na configurações de rede do VirtualBox no campo '''NOME''' selecione a interface virtual criada, (ex.: eth0.1).<br/><br/> | + | *3° - Para o VirtualBox dá o boot pela rede, ele irá procurar o servidor na rede real, desprezando a vlan. Para dá o boot na vlan, é preciso configurar uma interface vitual no computador hospedeiro e na configurações de rede do VirtualBox no campo '''NOME''' selecione a interface virtual criada, (ex.: eth0.1).<br/><br/> |
====Organização do cenário de testes==== | ====Organização do cenário de testes==== | ||
Linha 140: | Linha 142: | ||
===30/09/2010 (semana 9)=== | ===30/09/2010 (semana 9)=== | ||
− | Ao longo das últimas semanas | + | '''Testes de cópia'''.<br/> |
+ | Ao longo das últimas semanas alguns testes foram feitos com o servidor.<br/> | ||
*'''Teste n° 1''' - o cliente irá fornecer uma cópia de si mesma para o servidor.<br/> | *'''Teste n° 1''' - o cliente irá fornecer uma cópia de si mesma para o servidor.<br/> | ||
− | Depois da várias tentativas sem sucesso, notamos que no momento em que o servidor estava tentando copiar o sistema do cliente, aparecia na tela em um curto momento um erro com o NFS (na verdade quem notou esse erro foi o prof. Ederson, eu nem enxerguei isso).<br/> | + | Depois da várias tentativas sem sucesso, notamos que no momento em que o servidor estava tentando copiar o sistema do cliente, aparecia na tela em um curto momento um erro com o "NFS" (na verdade quem notou esse erro foi o prof. Ederson, eu nem enxerguei isso).<br/> |
Um erro com NFS, pra começar, o que é NFS?<br/> | Um erro com NFS, pra começar, o que é NFS?<br/> | ||
É um aplicativo que torna uma pasta de um coputador visível por todos os computadores da mesma rede. Para mais informações siga o link http://pt.wikipedia.org/wiki/Network_File_System <br/> | É um aplicativo que torna uma pasta de um coputador visível por todos os computadores da mesma rede. Para mais informações siga o link http://pt.wikipedia.org/wiki/Network_File_System <br/> | ||
− | + | O motivo do erro com o "NFS" ainda é desconhecido, mas para funcionar, instalei um servidor "NFS" em outro computador e alguns testes foram feitos. Os testes foram simples, Montar uma pasta no computador onde estar instalado o FOG (esse computador será o cliente NFS) e no computador servidor NFS, na pasta onde será compartilhada deixar um arquivo qualquer, após os testes o servidor não apresentava mais problemas. | |
+ | *'''Teste n° 2''' - um outro cliente irá puxar a imagem do servidor FOG. | ||
+ | O teste dois apenas está funcionando com outra máquina com as mesmas características (HD com mesmo tamanho), máquinas com características diferentes ainda apresentam erros. | ||
+ | |||
+ | ===01/10/2010 (semana 9)=== | ||
+ | Os testes feitos ontem foram repetidos, mas desta vez, com sistema operacional '''Windows XP'''.<br/> | ||
+ | O teste um não apresentou nem um tipo de problema, nem mesmo com o NFS. O teste dois continua com o mesmo problema, | ||
+ | está funcionando com outra máquina com as mesmas características, máquinas com características diferentes ainda apresentam erros. | ||
+ | |||
+ | ===13/10/2010 (semana 11)=== | ||
+ | '''Cópia de imagens para as máquinas'''.<br/> | ||
+ | *'''Imagens''' - ubuntu, windows (as duas imagens são clones de máquinas com um HD de 3 GB, o ubuntu é do tipo ''Multiple Partition - All Disks'' e o windows é do tipo ''Single Partition NTFS'').<br/> | ||
+ | *'''Hosts''' - windows, ubuntu, windows_pequeno, ubuntu_pequeno, SEM_SO.<br/> | ||
+ | windows e ubuntu possuem um HD de 8 GB.<br/> | ||
+ | windows_pequeno e ubuntu_pequeno possuem HD de 3 GB.<br/> | ||
+ | SEM_SO, HD de 3 GB e sem sistema operacional.<br/> | ||
+ | |||
+ | <center> | ||
+ | {| border=1 | ||
+ | |- | ||
+ | |'''imagem''' || '''máquinas''' || '''aceita''' | ||
+ | |- | ||
+ | |windows || windows_pequeno || S | ||
+ | |- | ||
+ | |windows || windows || N * | ||
+ | |- | ||
+ | |windows || ubuntu_pequeno || S | ||
+ | |- | ||
+ | |windows || SEM_SO || S | ||
+ | |- | ||
+ | |ubuntu || windows_pequeno || S | ||
+ | |- | ||
+ | |ubuntu || ubuntu || N ** | ||
+ | |- | ||
+ | |ubuntu || ubuntu_pequeno || S | ||
+ | |- | ||
+ | |ubuntu || SEM_SO || N | ||
+ | |- | ||
+ | |} | ||
+ | </center> | ||
+ | |||
+ | (*) copia, mas após a cópia aparece "Erro de disco".<br/> | ||
+ | (**) antes de começar o processo de cópia abre um terminal de comandos grub.<br/> | ||
+ | |||
+ | ===14/10/2010 (semana 11)=== | ||
+ | O teste agora é com uma imagem do ubuntu do tipo ''Multiple Partition - Single Disk'' com 3 GB, os resultados não mudaram muito de acordo com a tabela anterior mas desta vez a máquina de 8 GB de HD aceitou a imagem ubuntu. | ||
+ | |||
+ | ===22/10/2010 (semana 12)=== | ||
+ | Após um computador com um HD de 8 GB ter um sistema de 3 GB precisamos aumentar a partição.<br/> | ||
+ | Como fazer isso de maneira rápida e se está com a partição montada?<br/> | ||
+ | * 1- Podemos dá um boot em um cd de instalação e aumentar a partição. Esse método é demorado.<br/> | ||
+ | * 2- entrar no ubuntu, utilizar o comandos parted ou fdisk para criar uma nova partição para preencher o restante do disco, esses comandos não funcionam com o disco montado. A intenção é aumentar partição para preencher o restante do disco e não criar uma nova. Esse método é inadequado.<br/> | ||
+ | * 3- Junto com o servidor FOG ter também um servidor [http://pt.wikipedia.org/wiki/LTSP LTSP] para processar os comandos fdisk ou parted sem estar com o HD montado. Método adequado. | ||
+ | |||
+ | ===26/10/2010 (semana 13)=== | ||
+ | |||
+ | O servidor LTSP não obteve sucessos e como este projeto tem prazo de conclusão não vou me aprofundar nos seus mecanismos. | ||
+ | |||
+ | ===29/10/2010 (semana 13)=== | ||
+ | |||
+ | '''Testes com multicast'''.<br/> | ||
+ | Os testes com multicast foram um pouco limitados pelo motivo do cenário de teste ser apenas com dois computadores reais, mas nada que atrapalhe esse método com três máquinas virtuais rodando com 200 MB de RAM. Demerou um pouco mas os testes ocorreram bem.<br/> | ||
+ | O servidor FOG irá disponibilizar uma única imagem, é o mesmo processo do unicast, mas agora possui vários clientes que devem estar alinhados para receber a imagem. | ||
+ | Para fazer o alinhamento é preciso modificar o campo "UDPSENDER_MAXWAIT" do arquivo /opt/fog/service/etc/config.php, esse campo indica o quanto tempo (em segundos) em que todos os computadores que irão puxar a imagem devem estar preparados, no meu caso, como testei com três máquinas virtuais configurei para esperar dez segundos, caso um computador se atrase a cópia não é feita e todos os outros computadores ficam travados. | ||
+ | |||
+ | ===03/11/2010 (semana 14)=== | ||
+ | '''Nome de interface de rede diferente'''.<br/> | ||
+ | Ao digitar o comando ''ifconfig'' no terminal de um computador que recebeu uma imagem, a interface de rede estará com um nome diferente de "eth0", como "eth1" ou "eth2".<br/> | ||
+ | <syntaxhighlight lang=bash> | ||
+ | eth1 Link encap:Ethernet Endereço de HW 00:08:54:45:30:2d | ||
+ | inet end.: 172.18.22.149 Bcast:172.18.255.255 Masc:255.255.0.0 | ||
+ | endereço inet6: fe80::208:54ff:fe45:302d/64 Escopo:Link | ||
+ | UP BROADCAST RUNNING MULTICAST MTU:1500 Métrica:1 | ||
+ | pacotes RX:4785911 erros:0 descartados:0 excesso:0 quadro:0 | ||
+ | Pacotes TX:3214739 erros:0 descartados:0 excesso:0 portadora:0 | ||
+ | colisões:0 txqueuelen:1000 | ||
+ | RX bytes:1415960411 (1.4 GB) TX bytes:2246766805 (2.2 GB) | ||
+ | IRQ:20 Endereço de E/S:0x2000 | ||
+ | |||
+ | lo Link encap:Loopback Local | ||
+ | inet end.: 127.0.0.1 Masc:255.0.0.0 | ||
+ | endereço inet6: ::1/128 Escopo:Máquina | ||
+ | UP LOOPBACK RUNNING MTU:16436 Métrica:1 | ||
+ | pacotes RX:4 erros:0 descartados:0 excesso:0 quadro:0 | ||
+ | Pacotes TX:4 erros:0 descartados:0 excesso:0 portadora:0 | ||
+ | colisões:0 txqueuelen:0 | ||
+ | RX bytes:240 (240.0 B) TX bytes:240 (240.0 B) | ||
+ | </syntaxhighlight> | ||
+ | Para resolver esse problema, antes de clonar um computador, devemos excluir o arquivo "/etc/udev/rules.d/70-persistent-net.rules", esse arquivo é responsável por ligar um endereço MAC a um nome.<br/> | ||
+ | Quando o computador é reiniciado o arquivo excluído é restaurado.<br/> | ||
+ | Caso o arquivo do computador clonado não é excluído, o arquivo do computador que recebe a imagem ficará assim. | ||
+ | <syntaxhighlight lang=bash> | ||
+ | # This file maintains persistent names for network interfaces. | ||
+ | # See udev(7) for syntax. | ||
+ | # | ||
+ | # Entries are automatically added by the 75-persistent-net-generator.rules | ||
+ | # file; however you are also free to add your own entries. | ||
+ | |||
+ | ENDEREÇO MAC DO COMPUTADOR CLONADO. | ||
+ | # PCI device 0x10ec:0x8168 (r8169) | ||
+ | SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:1a:4d:a5:17:28", ATTR{type}=="1", | ||
+ | KERNEL=="eth*", NAME="eth0" | ||
+ | |||
+ | |||
+ | ENDEREÇO MAC DO COMPUTADOR CLIENTE. | ||
+ | # PCI device 0x10ec:0x8169 (r8169) | ||
+ | SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:08:54:45:30:2d", ATTR{type}=="1", | ||
+ | KERNEL=="eth*", NAME="eth1" | ||
+ | |||
+ | |||
+ | !!!Note que o MAC "00:08:54:45:30:2d" está com a interface "eth1"!!! | ||
+ | </syntaxhighlight> | ||
+ | Caso contrário.<br/> | ||
+ | <syntaxhighlight lang=bash> | ||
+ | # This file maintains persistent names for network interfaces. | ||
+ | # See udev(7) for syntax. | ||
+ | # | ||
+ | # Entries are automatically added by the 75-persistent-net-generator.rules | ||
+ | # file; however you are also free to add your own entries. | ||
+ | |||
+ | ENDEREÇO MAC DO COMPUTADOR CLIENTE. | ||
+ | # PCI device 0x10ec:0x8169 (r8169) | ||
+ | SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:08:54:45:30:2d", ATTR{type}=="1", | ||
+ | KERNEL=="eth*", NAME="eth0" | ||
+ | |||
+ | |||
+ | !!!Note que o MAC "00:08:54:45:30:2d" está com a interface "eth0"!!! | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===10/11/2010 (semana 15)=== | ||
+ | '''Nomes dos computadores iguais'''.<br/> | ||
+ | Um problema de uma distribuição de imagens é que todos os computadores que receberem essa imagem terão o mesmo nome. O servidor FOG apresenta uma solução mas apenas para sistemas Windows [http://www.fogproject.org/wiki/index.php?title=FOGUserGuide#The_FOG_Client_Service]. Para o Ubuntu é preciso mudar manualmente em cada máquina ou fazer um programa para fazer isso automaticamente.<br/> | ||
+ | '''Estratégia do programa'''.<br/> | ||
+ | O programa irá consultar o endereço MAC do computador no arquivo "/etc/udev/rules.d/70-persistent-net.rules", comparar com um arquivo texto onde está registrado o seu MAC e o seu nome e depois o programa irá modificar o arquivo "/etc/hostname". | ||
+ | <syntaxhighlight lang=c> | ||
+ | //feito por Gustavo Paulo Medeiros Da Silva | ||
+ | |||
+ | #include<stdio.h> | ||
+ | #include<string.h> | ||
+ | #include<stdlib.h> | ||
+ | |||
+ | main(){ | ||
+ | int i, x=1, n=0, m=16; | ||
+ | char *y; | ||
+ | char mac1[19], mac2[273], mac3[18]="ATTR{address}==", nome[18], nome1[50]; | ||
+ | |||
+ | //abre o arquivo o arquivo 70-persistent-net.rules | ||
+ | FILE *pt; | ||
+ | pt=fopen("/etc/udev/rules.d/70-persistent-net.rules","r"); | ||
+ | |||
+ | //faz a leitura e contatena cada string até a string que contém o primeiro endereço MAC em "mac2" | ||
+ | for(i=0;i<44;i++){ | ||
+ | fscanf(pt,"%s",mac1);//lê estring do arquivo | ||
+ | strcat(mac2,mac1); | ||
+ | } | ||
+ | fclose(pt); | ||
+ | |||
+ | //procura em "mac2" a string "ATTR{address}==" e copia o endereço MAC para "y" | ||
+ | y=strstr (mac2, mac3); | ||
+ | |||
+ | //filtra o endereço MAC para a string "mac3" | ||
+ | while(n<=16){ | ||
+ | mac3[n]=y[m]; | ||
+ | n++, m++; | ||
+ | } | ||
+ | FILE *p; | ||
+ | p=fopen("nome.txt","r");//abre o arquivo nome.txt | ||
+ | |||
+ | //se o arquivo não for encontrado o programa é finalizado | ||
+ | //o arquivo nome tem que ficar no diretório onde o programa está sendo executado | ||
+ | if (!p){ | ||
+ | printf ("O arquivo nome.txt não foi encontrado!\n"); | ||
+ | exit (1); | ||
+ | } | ||
+ | |||
+ | //procura o nome ligado ao MAC | ||
+ | while(x!=0){ | ||
+ | fscanf(p,"%s",nome1); | ||
+ | x= strcmp ( mac3, nome1 ); | ||
+ | //se o MAC está registrado no arquivo nome.txt, o nome é passado para string "nome" | ||
+ | if(x==0){ | ||
+ | fscanf(p,"%s",nome); | ||
+ | printf("%s %s\n",mac3,nome); | ||
+ | } | ||
+ | |||
+ | //se o endereço MAC não for encontrado o programa é finalizado | ||
+ | i=feof(p); | ||
+ | if(i==1){ | ||
+ | printf("Este computador não está registrado no arquivo nome.txt!\n"); | ||
+ | exit (1); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | fclose(p); | ||
+ | |||
+ | x=strlen(nome); | ||
+ | //grava o nome no arquivo /etc/hostname | ||
+ | FILE *f; | ||
+ | f=fopen("/etc/hostname","w"); | ||
+ | |||
+ | //Para executar esse programa é preciso ser administrador | ||
+ | if (!f){ | ||
+ | printf ("Para alterar o nome desse computador é preciso ser administrador!\n"); | ||
+ | exit (1); | ||
+ | } | ||
+ | |||
+ | fwrite(nome,x,1,f); | ||
+ | fclose(f); | ||
+ | |||
+ | //reiniciar o computador para alterar o nome | ||
+ | printf("É necessário reiniciar, continuar? Ctrl+C para cancelar...\n"); | ||
+ | getchar(); | ||
+ | system("sudo reboot"); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | O arquivo "nome.txt" que o programa irá consultar deve estar no mesmo diretório do programa. | ||
+ | <code> | ||
+ | # endereço_mac nome_do_computador | ||
+ | |||
+ | 00:08:54:45:30:2d nome_1 | ||
+ | 00:1d:7d:fb:2a:a0 nome_2 | ||
+ | 00:1a:4d:a5:17:28 nome_3 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | ===8/12/2010 (semana 20)=== | ||
+ | '''Controle de computadores em uma rede'''.<br/> | ||
+ | Nas ultimas cinco semanas, estava tentando fazer um programa que de alguma forma controlaria computadores em uma rede local. Esse método existe, através do [http://pt.wikipedia.org/wiki/SSH ssh], mas não em multicast.<br/> | ||
+ | É um pouco complicado, mas se quebrar-mos a cabeça podemos sim ter um controle em multicast.<br/> | ||
+ | Como eu não sou um expert em liguagem C, os programas são umas gambiarras, mas o importante é que funciona.<br/> | ||
+ | O problema é que não podemos ter uma interação com os computadores, por exemplo, o comando top, vi e outros, os comandos têm que ser simples.<br/> | ||
+ | Primeiro o programa irá enviar em broadcast uma string indicando que o servidor quer se comunicar com os clientes.<br/> | ||
+ | Os clientes então enviam as suas informações como nome e as interfaces que possui.<br/> | ||
+ | Agora podemos enviar os comandos, esses comandos passam por uma espécie de criptografia para tornar o processo um pouco mais seguro.<br/> | ||
+ | Os programas foram montados em socket UDP para facilitar o processo de broadcast.<br/> | ||
+ | O programa servidor que irá enviar os comandos.<br/> | ||
+ | <syntaxhighlight lang=c> | ||
+ | //Programa servidor | ||
+ | |||
+ | #include <sys/types.h> | ||
+ | #include <sys/socket.h> | ||
+ | #include <netinet/in.h> | ||
+ | #include <arpa/inet.h> | ||
+ | #include <time.h> | ||
+ | #include <string.h> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <unistd.h> | ||
+ | #include <sys/wait.h> | ||
+ | #include <signal.h> | ||
+ | |||
+ | #define HELLO_PORT 12345 | ||
+ | #define HELLO_GROUP "225.0.0.0" | ||
+ | #define MSGBUFSIZE 1500 | ||
+ | |||
+ | |||
+ | int i, x=1,n=0, cont=0, comp; | ||
+ | char bin[]=" < /bin/sh"; | ||
+ | char b, string[1000], info[1500], tab[]=" ", vir[]=";", saida[]="exit"; | ||
+ | const char* interface ="p"; | ||
+ | |||
+ | |||
+ | //parte servidor | ||
+ | void servidor(){ | ||
+ | printf("\e[;m"); | ||
+ | struct sockaddr_in addr; | ||
+ | int fd, cnt, nbytes, addrlen; | ||
+ | struct ip_mreq mreq; | ||
+ | char comando[1500]; | ||
+ | char msgbuf[MSGBUFSIZE]; | ||
+ | |||
+ | if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) { | ||
+ | perror("socket"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | // set up destination address | ||
+ | memset(&addr,0,sizeof(addr)); | ||
+ | addr.sin_family=AF_INET; | ||
+ | addr.sin_addr.s_addr=inet_addr(HELLO_GROUP); | ||
+ | addr.sin_port=htons(HELLO_PORT); | ||
+ | |||
+ | //laço onde é digitados os comandos | ||
+ | while (1) { | ||
+ | printf(">> "); | ||
+ | gets(&comando[0]); | ||
+ | i=strlen(comando); | ||
+ | comp=strcmp(saida,comando); | ||
+ | |||
+ | //criptografa os comandos | ||
+ | for(x=0;x<i;x++){ | ||
+ | comando[x]=comando[x]+5237; | ||
+ | } | ||
+ | //envia os comandos | ||
+ | if (sendto(fd,comando,sizeof(comando),0,(struct sockaddr *) &addr,sizeof(addr)) < 0) { | ||
+ | perror("sendto"); | ||
+ | exit(1); | ||
+ | } | ||
+ | if(comp==0){ | ||
+ | exit(0); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | main(int argc, char *argv[]){ | ||
+ | struct sockaddr_in addr; | ||
+ | int fd, cnt, nbytes, addrlen; | ||
+ | struct ip_mreq mreq; | ||
+ | char comando[1500]; | ||
+ | char msgbuf[MSGBUFSIZE]; | ||
+ | |||
+ | //avisa para os computadores que o servidor está ativo enviando a string "pronto_para_conexao" | ||
+ | if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) { | ||
+ | perror("socket"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | /* set up destination address */ | ||
+ | memset(&addr,0,sizeof(addr)); | ||
+ | addr.sin_family=AF_INET; | ||
+ | addr.sin_addr.s_addr=inet_addr(HELLO_GROUP); | ||
+ | addr.sin_port=htons(HELLO_PORT); | ||
+ | char pronto[]="pronto_para_conexao"; | ||
+ | //envio da string | ||
+ | if (sendto(fd,pronto,sizeof(pronto),0,(struct sockaddr *) &addr,sizeof(addr)) < 0) { | ||
+ | perror("sendto"); | ||
+ | exit(1); | ||
+ | } | ||
+ | close(fd); | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | //parte em que o servidor passa a ter o papel de cliente para receber as informações das interfaces | ||
+ | u_int yes=1; | ||
+ | |||
+ | // create what looks like an ordinary UDP socket | ||
+ | if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) { | ||
+ | perror("socket"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | |||
+ | // allow multiple sockets to use the same PORT number | ||
+ | if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) { | ||
+ | perror("Reusing ADDR failed"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | // set up destin(ioctl(sock, SIOCGIFADDR, &ifr[iface])ation address | ||
+ | memset(&addr,0,sizeof(addr)); | ||
+ | addr.sin_family=AF_INET; | ||
+ | addr.sin_addr.s_addr=htonl(INADDR_ANY); // N.B.: differs from sender | ||
+ | addr.sin_port=htons(HELLO_PORT); | ||
+ | |||
+ | |||
+ | |||
+ | // bind to receive address | ||
+ | if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) { | ||
+ | perror("bind"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | // use setsockopt() to request that the kernel join a multicast group | ||
+ | mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP); | ||
+ | mreq.imr_interface.s_addr=htonl(INADDR_ANY); | ||
+ | while (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) { | ||
+ | |||
+ | } | ||
+ | |||
+ | if (sendto(fd,comando,sizeof(comando),0,(struct sockaddr *) &addr,sizeof(addr)) < 0) { | ||
+ | perror("sendto"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | //tempo para se conectar com o servidor 1 segundo, após esse tempo o servidor estará pronto para enviar os comandos | ||
+ | //as informações das interfaces dos clientes são recebidas | ||
+ | alarm(1); | ||
+ | while(1){ | ||
+ | signal(SIGALRM, servidor); | ||
+ | addrlen=sizeof(addr); | ||
+ | //recebe as informações | ||
+ | if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0) { | ||
+ | perror("recvfrom"); | ||
+ | exit(1); | ||
+ | } | ||
+ | //descriptografar as informações das interfaces | ||
+ | i=strlen(msgbuf); | ||
+ | for(x=i-1;x>=0;x--){ | ||
+ | msgbuf[x]=msgbuf[x]-5237; | ||
+ | } | ||
+ | |||
+ | printf("\e[31m"); | ||
+ | |||
+ | if(cont!=0){ | ||
+ | printf("+----------------------------------------------------------------+\n"); | ||
+ | printf("%s\n",msgbuf); | ||
+ | printf("+----------------------------------------------------------------+\n"); | ||
+ | } | ||
+ | cont++; | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | O programa cliente foi planejado para está sempre ativo enquanto o computador estiver ligado.<br/> | ||
+ | Um bom conselho é deixar o programa cliente no arquivo de iniciação do sistema, caso precisamos de executar um comando sendo administrador não precisar dar o comando sudo.<br/> | ||
+ | Para fazer isso.<br/> | ||
+ | Compile o programa o salve no diretório /etc/init.d. | ||
+ | No terminal dentro do caminho /etc/init.d, digite o comando:<br/> | ||
+ | <syntaxhighlight lang=bash> | ||
+ | sudo chmod 755 programa_cliente | ||
+ | </syntaxhighlight> | ||
+ | Isso dará as permissões necessárias para o arquivo ser executado.<br/> | ||
+ | Após ter feito isso, utilize o seguinte comando:<br/> | ||
+ | <syntaxhighlight lang=bash> | ||
+ | sudo update-rc.d programa_cliente defaults | ||
+ | </syntaxhighlight> | ||
+ | Isso atualizará os diretórios rc.d, adicionando o programa na inicialização do sistema.<br/> | ||
+ | O servidor é ativado apenas quando quisermos utiliza-lo.<br/> | ||
+ | <syntaxhighlight lang=c> | ||
+ | //Programa cliente | ||
+ | |||
+ | #include <sys/types.h> | ||
+ | #include <sys/socket.h> | ||
+ | #include <netinet/in.h> | ||
+ | #include <arpa/inet.h> | ||
+ | #include <time.h> | ||
+ | #include <string.h> | ||
+ | #include <stdio.h> | ||
+ | #include <unistd.h> | ||
+ | #include <sys/ioctl.h> | ||
+ | #include <net/if.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | #define HELLO_PORT 12345 | ||
+ | #define HELLO_GROUP "225.0.0.0" | ||
+ | #define MSGBUFSIZE 1500 | ||
+ | |||
+ | int i,x=1,a,n=0, cont=0, comp, conexao=0; | ||
+ | char bin[]=" < /bin/sh", saida[]="exit"; | ||
+ | char string[1000], info[1500], tab[]=" ", vir[]=";"; | ||
+ | const char* interface ="p"; | ||
+ | char pronto[]="pronto_para_conexao"; | ||
+ | |||
+ | main(int argc, char *argv[]){ | ||
+ | struct sockaddr_in addr; | ||
+ | int fd, cnt, nbytes, addrlen; | ||
+ | struct ip_mreq mreq; | ||
+ | char comando[1500]; | ||
+ | char msgbuf[MSGBUFSIZE]; | ||
+ | //primeiro o cliente irá 'escutar' a rede, para verificar se o servidor está ativo | ||
+ | goto cliente; | ||
+ | |||
+ | //parte onde o cliente irá mandar as informações da's' interface's' de rede | ||
+ | enviando_interfaces:{ | ||
+ | /* create what looks like an ordinary UDP socket */ | ||
+ | if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) { | ||
+ | perror("socket"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | /* set up destination address */ | ||
+ | memset(&addr,0,sizeof(addr)); | ||
+ | addr.sin_family=AF_INET; | ||
+ | addr.sin_addr.s_addr=inet_addr(HELLO_GROUP); | ||
+ | addr.sin_port=htons(HELLO_PORT); | ||
+ | |||
+ | |||
+ | //nome do computador, ler o arquivo "/etc/hostname" | ||
+ | FILE *pt; | ||
+ | pt=fopen("/etc/hostname","r"); | ||
+ | while(!feof(pt)){ | ||
+ | fgets(string,1500,pt); | ||
+ | } | ||
+ | fclose(pt); | ||
+ | strcpy(info,string); | ||
+ | |||
+ | |||
+ | //lista as interfaces de rede e seus ip's | ||
+ | struct ifconf ifc; | ||
+ | char buff[BUFSIZ]; | ||
+ | int sock, iface, num; | ||
+ | struct ifreq *ifr=NULL; | ||
+ | |||
+ | sock = socket(AF_INET, SOCK_DGRAM,IPPROTO_IP); | ||
+ | ifc.ifc_len = sizeof(buff); | ||
+ | ifc.ifc_buf = buff; | ||
+ | |||
+ | ioctl(sock, SIOCGIFCONF, &ifc); | ||
+ | ifr = ifc.ifc_req; | ||
+ | |||
+ | num = ifc.ifc_len / sizeof(struct ifreq); | ||
+ | |||
+ | for (iface=0 ; iface<num ; iface++){ | ||
+ | if ((ioctl(sock, SIOCGIFADDR, &ifr[iface]) == 0)&&(n!=0)){ | ||
+ | strcat(info,ifr[iface].ifr_name); | ||
+ | strcat(info,tab); | ||
+ | if(strcmp(ifr[iface].ifr_name, interface) < 0){ | ||
+ | strcat(info,inet_ntoa((*(struct sockaddr_in *)&ifr[iface].ifr_addr).sin_addr)); | ||
+ | strcat(info,vir); | ||
+ | strcat(info,tab); | ||
+ | } | ||
+ | } | ||
+ | n++; | ||
+ | } | ||
+ | |||
+ | //codificação das informações da's' interface's' | ||
+ | i=strlen(info); | ||
+ | for(x=0;x<i;x++){ | ||
+ | info[x]=info[x]+5237; | ||
+ | } | ||
+ | |||
+ | /* now just sendto() our destination! */ | ||
+ | |||
+ | if(sendto(fd,info,sizeof(info),0,(struct sockaddr *) &addr,sizeof(addr)) > 0){ | ||
+ | } | ||
+ | //volta a parte do cliente onde os comandos enviados pelo servidor serão execultados | ||
+ | goto cliente; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | //parte cliente | ||
+ | cliente:{ | ||
+ | u_int yes=1; | ||
+ | |||
+ | // create what looks like an ordinary UDP socket | ||
+ | if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) { | ||
+ | perror("socket"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | |||
+ | // allow multiple sockets to use the same PORT number | ||
+ | if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) { | ||
+ | perror("Reusing ADDR failed"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | // set up destin(ioctl(sock, SIOCGIFADDR, &ifr[iface])ation address | ||
+ | memset(&addr,0,sizeof(addr)); | ||
+ | addr.sin_family=AF_INET; | ||
+ | addr.sin_addr.s_addr=htonl(INADDR_ANY); // N.B.: differs from sender | ||
+ | addr.sin_port=htons(HELLO_PORT); | ||
+ | |||
+ | // bind to receive address */ | ||
+ | if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) { | ||
+ | perror("bind"); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | // use setsockopt() to request that the kernel join a multicast group | ||
+ | mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP); | ||
+ | mreq.imr_interface.s_addr=htonl(INADDR_ANY); | ||
+ | while (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) { | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | // now just enter a read-print loop | ||
+ | while (1) { | ||
+ | //ouvindo a porta 12345 | ||
+ | addrlen=sizeof(addr); | ||
+ | if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0) { | ||
+ | perror("recvfrom"); | ||
+ | exit(1); | ||
+ | } | ||
+ | comp=strcmp(msgbuf,pronto); | ||
+ | |||
+ | //se o servidor se conecta, comparar string enviada por ele | ||
+ | //a string é "pronto_para_conexao" significa que o cliente deve se preparar para enviar as informações da interface | ||
+ | //é uma espécie de convocação, onde o servidor chama os clientes que irão participar do 'controle remoto' | ||
+ | |||
+ | if((conexao==0)||(comp==0)){ | ||
+ | puts(msgbuf); | ||
+ | conexao++, n=0; | ||
+ | goto enviando_interfaces; | ||
+ | } | ||
+ | |||
+ | //após o anuncio do servidor querendo se conectar, a comunicação entre o cliente e o servidor é cripografado | ||
+ | if(conexao>0){ | ||
+ | //decodificação da mensagem | ||
+ | i=strlen(msgbuf); | ||
+ | for(x=i-1;x>=0;x--){ | ||
+ | msgbuf[x]=msgbuf[x]-5237; | ||
+ | } | ||
+ | comp=strcmp(msgbuf,saida); | ||
+ | if(comp==0){ | ||
+ | conexao=0, n=0; | ||
+ | } | ||
+ | strcat(msgbuf,bin); | ||
+ | system(msgbuf); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===9/12/2010 (semana 20)=== | ||
+ | '''Wake on lan'''.<br/> | ||
+ | Além do controle de uma rede de computadores seria muito interessante se pudéssemos ligar esses computadores remotamente. Isso é possível desde que a placa de rede suporta [http://pt.wikipedia.org/wiki/Wake-on-LAN Wake on lan].<br/> | ||
+ | Esse método consiste em mandar uma espécie de 'pacote mágico' para a placa de rede do computador que queremos ligar. O computador fica desligado mas a placa de rede fica ligada. A placa envia um sinal para a placa mãe que então liga o sistema.<br/> | ||
+ | Para baixar o programa que envia o 'pacote mágico' http://packages.debian.org/lenny/etherwake.<br/> | ||
+ | Para instalar. | ||
+ | <syntaxhighlight lang=bash> | ||
+ | sudo dpkg -i etherwake_1.09-2_i386.deb | ||
+ | #ou o nome do pacote que você baixou | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==Considerações finais== | ||
+ | |||
+ | ===10/12/2010 (semana 20)=== | ||
+ | Ao longo desse semestre testamos alguns mecanismos de controle centralizado de uma rede. Não foi uma caminhada fácil, mas, nada que não seja impossível.<br/> | ||
+ | ====O FOG Project==== | ||
+ | Uma situação que muitas pessoas tentam evitar é ter que instalar um sistema operacional em uma rede de computadores, dependendo do tamanho dessa rede, isso levaria horas ou atés dias. A solução é usar um mecanismo que facilitaria a instalação em larga escala.<br/> | ||
+ | Um desses Mecanismos que estudamos foi o FOG Project. Ele envia pela rede um clone de um computador onde os computadores dessa rede irão copiar para os seus HDs. Diferente de outros programas que fazem isso o FOG não exige que os clientes tenham um disquete ou um pen-driver, apenas exige que os as placas de rede dos clientes suportam PXE. | ||
+ | A interação Com o programa é bastante simples, é através de uma interface WEB onde o programa pode ser acessado em qualquer computador da rede.<br/> | ||
+ | |||
+ | ====O cenário de testes==== | ||
+ | Para funcionar o FOG precisa de um servidor PXE que por sua vez precisa de um DHCP, para trabalhar foi preciso montar uma espécie de laboratório para separar a rede de testes da rede da instituição. Usamos o conceito de VLAN para emular a rede e o Virtual Box para emular os computadores.<br/> | ||
+ | Essa preparação do laboratório de testes, por mais que pareça inocente, deu uma pequena dor de cabeça por causa de alguns minúsculos detalhes que estavam impedindo que a rede não funcionasse, mas nada que um bom estudo não resolvesse o problema. | ||
+ | |||
+ | ====Os testes==== | ||
+ | Alguns testes foram tranquilos, outros nem tanto, mas nada que não funcionasse. | ||
==Tutoriais== | ==Tutoriais== | ||
− | ===Virtualbox=== | + | ===[http://pt.wikipedia.org/wiki/VirtualBox Virtualbox]=== |
Siga o tutorial na página | Siga o tutorial na página | ||
http://www.guiadohardware.net/comunidade/tutorial-instalando/988514/<br/> | http://www.guiadohardware.net/comunidade/tutorial-instalando/988514/<br/> | ||
+ | Para o Ubuntu 10.04 http://ubuntued.info/como-instalar-o-virtualbox-no-ubuntu<br/> | ||
Depois da instalação do virtualbox e do sistema operacional, vá em '''configurações''', '''rede''', no campo '''Conectado a''' selecione a opção '''Interface do Hospedeiro''' ou '''Placa em modo Bridge'''. | Depois da instalação do virtualbox e do sistema operacional, vá em '''configurações''', '''rede''', no campo '''Conectado a''' selecione a opção '''Interface do Hospedeiro''' ou '''Placa em modo Bridge'''. | ||
− | ===VLAN=== | + | ===[http://pt.wikipedia.org/wiki/Virtual_LAN VLAN]=== |
Para fazer uma VLAN, no terminal de comandos digite: | Para fazer uma VLAN, no terminal de comandos digite: | ||
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
Linha 159: | Linha 790: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Para configurar a VLAN.<br/> | Para configurar a VLAN.<br/> | ||
− | <syntaxhighlight lang=bash> | + | <syntaxhighlight lang=bash> |
− | + | sudo gedit /etc/network/interfaces | |
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Adicione as configurações da VLAN, por exemplo:<br/> | Adicione as configurações da VLAN, por exemplo:<br/> | ||
Linha 170: | Linha 800: | ||
network 10.0.3.0 | network 10.0.3.0 | ||
vlan_raw_device eth0 | vlan_raw_device eth0 | ||
− | + | Esses comandos irão ativar as configurações da interface eth0.1: | |
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
vconfig add eth0 1 | vconfig add eth0 1 | ||
Linha 176: | Linha 806: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ===NFS=== | + | ===[http://pt.wikipedia.org/wiki/Network_File_System NFS]=== |
− | Para | + | Para instalar o servidor NFS, vá até o terminal e digite o comando a seguir. Apenas a instalação do NFS no cliente é o suficiente para o FOG operar, mas se você é curioso e quer fazer um servidor NFS próprio aqui tem um simples tutorial. |
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
sudo apt-get install nfs-kernel-server | sudo apt-get install nfs-kernel-server | ||
+ | </syntaxhighlight> | ||
+ | Agora para compartilhar a pasta ou Hd na rede basta editarmos o arquivo /etc/exports. Para o exemplo, utilizarei a pasta /home no computador 10.0.0.1. | ||
+ | <code> | ||
+ | /home *(rw,sync,no_root_squash) | ||
+ | </syntaxhighlight> | ||
+ | Agora vamos iniciar o servidor de NFS . | ||
+ | <syntaxhighlight lang=bash> | ||
+ | sudo /etc/init.d/nfs-kernel-server start | ||
+ | </syntaxhighlight> | ||
+ | Agora é preciso montar a pasta compartilhada no outro computador que está na rede, mas primeiro vamos instalar o cliente nfs e depois criar uma pasta para a montagem. | ||
+ | <syntaxhighlight lang=bash> | ||
+ | sudo apt-get install nfs-common | ||
+ | mkdir /home/pasta | ||
+ | </syntaxhighlight> | ||
+ | Depois. | ||
+ | <syntaxhighlight lang=bash> | ||
+ | sudo mount -t nfs 10.0.0.1:/home /home/pasta | ||
+ | </syntaxhighlight> | ||
+ | Esse comando irá montar a pasta /home do servidor na pasta /home/pasta do cliente. | ||
+ | |||
+ | ==Tutorial de instalação FOG Project== | ||
+ | * Baixar o servidor em http://sourceforge.net/projects/freeghost/files/FOG/ | ||
+ | * O Ubuntu onde o servidor FOG será instalado deve ser em inglês. | ||
+ | * Criar o diretório onde será instalado o servidor | ||
+ | <syntaxhighlight lang=bash> | ||
+ | sudo mkdir -p /opt/fog-setup | ||
+ | </syntaxhighlight> | ||
+ | * Descompactar o pacote em /opt/fog-setup | ||
+ | <syntaxhighlight lang=bash> | ||
+ | sudo tar -xvzf fog* | ||
+ | </syntaxhighlight> | ||
+ | * Executar o programa de instalação | ||
+ | <syntaxhighlight lang=bash> | ||
+ | cd fog* | ||
+ | cd bin | ||
+ | sudo ./installfog.sh | ||
+ | </syntaxhighlight> | ||
+ | *Você será solicitado para a distro Linux que você está instalando, digite 2 e aperte enter.<br/><br/> | ||
+ | *Você será solicitado para o modo de instalação, N (Normal Server) ou S (Storage Server). Se você não tiver certeza de qual opção de escolher, use N para a instalação normal.<br/><br/> | ||
+ | *O instalador irá pedir o endereço IP do servidor, em seguida, pressione enter.<br/><br/> | ||
+ | *O instalador irá perguntar se você gostaria de introduzir um endereço de roteador para DHCP, se você gostaria de digite y e pressione enter, digite o endereço e pressione enter.<br/><br/> | ||
+ | *O instalador irá perguntar se você gostaria de inserir um endereço DNS e DHCP a imagem de inicialização, se você gostaria de digite y e pressione enter, digite o endereço e pressione enter.<br/><br/> | ||
+ | *Você teria então perguntado se gostaria de mudar a interface padrão do eth0, se você gostaria de digite y, pressione enter e adicione a interface (se você estiver inseguro, selecione n).<br/><br/> | ||
+ | *Você será solicitado a escolher se deseja instalar os pacotes necessários para a tradução, se você quiser, digite y '.<br/><br/> | ||
+ | *Durante a instalação, você pode ser solicitado a definir uma senha de root do MySQL, deixe em branco.<br/><br/> | ||
+ | *Depois de concluída a instalação abrir o Firefox novamente e digite a URL: http://localhost/fog/management . Você será solicitado para instalar o esquema do banco. Clique na guia Install/Update Now.<br/><br/> | ||
+ | *Quando o esquema é atualizado, tentar ir para a URL: http://localhost/fog/management novamente. Desta vez você deve ser solicitado o login<br/> | ||
+ | <bash> | ||
+ | username: fog | ||
+ | password: password | ||
+ | </bash> | ||
+ | *'''Testando a sua instalação''' | ||
+ | Agora que está tudo instalado, você precisará de um cliente para testar a sua instalação. No cliente, alterar a ordem de boot para inicializar a partir da rede ou PXE como o primeiro dispositivo de boot. Também pode ser necessário para habilitar a inicialização de rede em algumas BIOS, em seguida, inicializar o computador e você deverá ver o menu de inicialização do nevoeiro que lhe dará algumas opções, selecione o teste de memória.<br/> | ||
+ | *'''Preparação final do servidor'''<br/> | ||
+ | Após o Ubuntu está instalado, precisamos modificar o servidor para permitir Snapin de tamanhos maiores.<br/> | ||
+ | <syntaxhighlight lang=bash> | ||
+ | sudo gedit /etc/php5/apache2/php.ini | ||
+ | #no arquivo mudar os campos | ||
+ | memory_limit = 1900M | ||
+ | post_max_size=1900M | ||
+ | upload_max_filesize=1900M | ||
+ | |||
+ | sudo /etc/init.d/apache2 restart | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==Preparando uma imagem== | ||
+ | Para preparar uma imagem para a distribuição na rede, no servidor FOG, ir na aba '''images''', no lado esquerdo clicar em '''New Image''', preencher os campos de acordo com a imagem que você deseja.<br/> | ||
+ | Agora você precisa de um computador com o sistema operacional que vai ser clonado, mas antes devemos registrá-lo no servidor.<br/> | ||
+ | Para registrar.<br> | ||
+ | *modo 1- ir na aba '''hosts''', clicar em '''Add New Host''', preencher os campos de acordo com o computador.<br/> | ||
+ | *modo 2- No computador que irá ser clonado, iniciá-lo e configurá-lo para dar o boot pela rede ou habilitar o PXE, depois irá aparecer uma interface de cliente do FOG, ir até '''Perform Full Host Registration and Inventory''', depois de esperar um tempo você preenche os campos de acordo com o computador.<br/> | ||
+ | Agora o computador está registrado no servidor, se no processo de registro não ligamos o computador a imagem não podemos iniciar à clonagem.<br/> | ||
+ | Para ligar o computador à imagem, ir na aba '''hosts''', clicar em '''List All Hosts''', no lado direito do computador registrado clicar em '''Edit''', no campo '''host Image''' selecionar a imagem, no campo '''host OS''' selecione o sistema operacional que a imagem irá conter, clicar em '''update'''.<br/> | ||
+ | Agora vamos iniciar a tarefa, no menu esquerdo clicar em '''Basic Tasks''', clicar em '''Upload''' e '''Upload Image'''.<br/> | ||
+ | Antes da clonagem é aconselhável que exclua o arquivo '''/etc/udev/rules.d/70-persistent-net.rules''' | ||
+ | No computador que será clonado, iniciar para dar o boot na rede, após um tempo o processo de clonagem irá começar.<br/> | ||
+ | Agora temos uma imagem pronta.<br/> | ||
+ | |||
+ | ==Enviando uma imagem para um único computador (unicast)== | ||
+ | Agora precisamos de um outro computador para receber a imagem. Registre esse computador, o processo é igual o processo de registro do computador que foi clonado.<br/> | ||
+ | O que vai mudar é no nenu '''Basic Tasks''', clicar em '''Deploy''' e '''Imagem All Computers'''.<br/> | ||
+ | No computador que irá receber a imagem, iniciar para dar o boot na rede, após um tempo o processo de cópia irá começar.<br/> | ||
+ | |||
+ | ==Enviando uma imagem para vários computadores (multicast)== | ||
+ | Vamos supor que temos vários computadores regitrados, na aba '''hosts''', clicar em '''List All Hosts''', no lado esquerdo de cada computador regitrado tem um campo onde podemos selecionar o computador, selecione um grupo de dois ou mais computadores, no menu inferior escolhe um nome para o grupo e clique em '''Process Group Changes'''.<br/> | ||
+ | Na aba '''tasks''' no menu esquerdo clicar em '''List All Groups''', no lado do grupo clicar na imagem de uma antena "'''Deploy(multicast)'''" e depois clicar em '''Image All Computers using multicast'''<br/> | ||
+ | O servidor FOG irá disponibilizar uma única imagem, é o mesmo processo do unicast, mas agora possui vários clientes que devem estar alinhados para receber a imagem. O alinhamento indica em quanto tempo todos os computadores do grupo estarão prontos para puxar a imagem. Caso um computador não estiver alinhado, os outros computadores não irão puxar a imagem e ficarão travados. Para fazer o alinhamento é preciso modificar o campo "UDPSENDER_MAXWAIT" do arquivo /opt/fog/service/etc/config.php, esse campo indica o quanto tempo (em segundos) em que todos os computadores que irão puxar a imagem devem estar preparados.<br/> | ||
+ | Em uma rede de maior porte, o servidor FOG distribui uma imagem para dez computadores enquanto o restante ficam esperando em uma fila a sua vez.<br/> | ||
+ | Agora é só iniciar os computadores para darem o boot na rede.<br/> | ||
+ | |||
+ | =Segunda Fase do Projeto= | ||
+ | ==16/05/11 (Semana 1)== | ||
+ | Estas primeira e segunda semana foi feito um estudo do problema e alguns testes com máquinas virtuais para a compreensão do presente projeto, sendo que na semana posterior houve a problemática(nota de rodapé), observada pelo orientador do projeto, que o que estava sendo proposto para desenvolvimento já havia sido desenvolvido (ref. Sagui). | ||
+ | |||
+ | ==23/05/11 (Semana 2)== | ||
+ | Após uma reunião referente à problemática das semanas inicias ficou então decidido que será desenvolvido um aplicativo para dispositivos móveis com sistema operacional Android para controle remoto de sistemas operacionais de forma centralizada. | ||
+ | Para início foi instalado o SDK (kit de desenvolvimento) Android que contém também um [http://developer.android.com/sdk/index.html emulador] do Sistema Operacional (SO) Android e o plugin “nbandroid 1.7” na IDE Netbeans 7.0 que faz a ligação com o SDK. | ||
+ | Vou mostrar os passos para a instalação do SDK Android e o plugin nbandroid, mas antes é necessário a instalação do JDK (kit de desenvolvimento Java) e o Netbeans 7.0 que podem ser observados nos respectivos links: | ||
+ | http://www.oracle.com/technetwork/java/javase/downloads/index.html | ||
+ | http://netbeans.org/index.html | ||
+ | |||
+ | Instalação do SDK: | ||
+ | |||
+ | # Siga o endereço: http://developer.android.com/index.html. | ||
+ | #Clique em: SDK. | ||
+ | #* android-sdk_r11-windows.zip – se você estiver no Windows | ||
+ | #* android-sdk_r11-linux_x86.tgz – se você estiver no Linux | ||
+ | # Vá ao local onde você salvou esse arquivo. | ||
+ | #Descompacte na pasta onde está instalado o Netbeans | ||
+ | # Entre na pasta “..\android-sdk-windows\tools” e execute “android.bat” | ||
+ | # Se estiver no linux através da prompt de comando entre na pasta "../android-sdk-linux_x86" e execute "./android" | ||
+ | # Clique em: | ||
+ | ## Available packages | ||
+ | ## Expanda o “checkbox” “Android Repository” | ||
+ | Obs.: para o estudo de desenvolvimento do presente projeto foi utilizado a API 2.1 então selecione nos “checkboxes”: | ||
+ | > Android SDK Platform-tools, revision 4 | ||
+ | > Documentation for Android SDK, API 12, revision 1 | ||
+ | > SDK Platform Android 2.1-update, API 7, revision 2 | ||
+ | > Selecione todos os que têm a descrição “Sample for SDK ...” | ||
+ | > Android Compatibility package, revision 2 | ||
+ | > Install Selected | ||
+ | > Install | ||
+ | > Se aparecer alguma mensagem click em “Ok” e depois feche essa caixa de diálogo. Obs.: não feche a caixa “Android SDK and AVD Manager” | ||
+ | Agora vamos criar uma Máquina Virtual que irá emular um celular com SO Android: | ||
+ | > Clique em: | ||
+ | > Virtual devices | ||
+ | > New | ||
+ | > No campo Name digite um nome qualquer | ||
+ | > No combo box Target selecione “Android 2.1-update1 – API Level 7” | ||
+ | > Selecione o radio button “Size” e digite dentro do campo 512 | ||
+ | > Selecione o radio button “Built-in e escolha no respectivo combo box WQVGA432 | ||
+ | > Create AVD | ||
+ | |||
+ | Instalação do plugin para o Netbeans: | ||
+ | |||
+ | Siga o endereço: http://kenai.com/projects/nbandroid/ | ||
+ | > Em Project Links, clique em: | ||
+ | > Installation | ||
+ | > copie o endereço http://kenai.com/projects/nbandroid/downloads/download/updatecenter/updates.xml | ||
+ | Obs.: Eu peço para entrar nesse local porque esse endereço pode mudar, então por via das dúvidas entre no local especificado e copie o que estiver lá. | ||
+ | > Execute o Netbeans 7.0 | ||
+ | > Ferramentas | ||
+ | > Plug-ins | ||
+ | > Configurações | ||
+ | > Adicionar | ||
+ | > No campo URL cole o endereço copiado anteriormente | ||
+ | > No campo Nome digite um nome qualquer – sugestão: Android | ||
+ | > Ok | ||
+ | > Plug-ins disponíveis | ||
+ | > Recarregar catálogo | ||
+ | > Selecione os checkboxes: Android e Android Test Runner for NetBeans 7.0+ | ||
+ | > Instalar | ||
+ | > Confirme todas as caixas que aparecerem. | ||
+ | > Agora clique em: | ||
+ | > Ferramentas | ||
+ | > Opções | ||
+ | > Miscelânia | ||
+ | > Android | ||
+ | > Em SDK Location cole o endereço do local que você descompactou o SDK Android, algo do tipo “..\android-sdk-windows” | ||
+ | |||
+ | Instalação do plugin para o Eclipse: | ||
+ | |||
+ | Siga o endereço: http://developer.android.com/index.html | ||
+ | > Clique em: | ||
+ | > SDK | ||
+ | > Procure por ADT Plugin | ||
+ | > procure por algo do tipo https://dl-ssl.google.com/android/eclipse/ | ||
+ | > copie o endereço | ||
+ | Obs.: Eu peço para entrar nesse local porque esse endereço pode mudar, então por via das dúvidas entre no local especificado e copie o que estiver lá. | ||
+ | > Execute Eclipse | ||
+ | > Help | ||
+ | > Install new software... | ||
+ | > Add... | ||
+ | > No campo URL cole o endereço copiado anteriormente | ||
+ | > No campo Nome digite um nome qualquer – sugestão: Android | ||
+ | > Ok | ||
+ | > Select all | ||
+ | > Next | ||
+ | > Confirme todas as caixas com ok ou next que aparecerem, caso apareça alguma mensagem, deprese-á | ||
+ | > Agora clique em: | ||
+ | > Window | ||
+ | > Preferences | ||
+ | > Expanda Android | ||
+ | > Browser... Procure o local onde foi descompactado o Android SDK | ||
+ | > Ok | ||
+ | |||
+ | > Pronto agora é só começar a brincadeira | ||
+ | |||
+ | ==30/05/11 (Semana 3)== | ||
+ | Fiz aquisição do livro sobre Android<ref>LECHETA, R. R. [http://www.livroandroid.com.br/ Google Android – Aprenda a criar aplicações para dispositivos móveis com o Android SDK]. 2a ed. 2010. ISBN 978-85-7522-244-7.</ref>. Aqui pude iniciar os estudos da tecnologia e testei alguns códigos do livro no [http://developer.android.com/sdk/index.html emulador]. | ||
+ | |||
+ | Até estudar as estruturas de códigos do Android que for relevante para o projeto a ser desenvolvido, colocarei aqui os conhecimentos adquiridos no livro. | ||
+ | |||
+ | Agora vou mostrar como criar um projeto e testar no [http://developer.android.com/sdk/index.html emulador]: | ||
+ | # Localize a barra de menu situada no canto superior da janela do Eclipse | ||
+ | # Clique em: File -> New -> Android Project | ||
+ | # Na Caixa de texto <tt>Project name</tt> digite o nome do projeto que será identificado pelo eclipse. | ||
+ | # No Botão Radio deixe selecionado <tt>Create new project in workspace</tt>. | ||
+ | Na Lista <tt>Build Target</tt> selecione a versão do SO Android que será desenvolvido o projeto, no nosso caso é recomendado a utilização da 2.1 API Level 7, pois atualmente a maioria dos SOs Android “rodando” nos celulares brasileiros são 2.1 e alguns 2.2. É importante entender que se você desenvolver um aplicativo para SO Android com API Level superior ao 8, esse aplicativo não funcionará em SOs com Level inferior, porém a recíproca é verdadeira. | ||
+ | # Na Caixa de Texto <tt>Application name</tt> digite o nome do aplicativo que aparecerá na área de trabalho do SO Android. | ||
+ | # Em <tt>Package name</tt> digite o nome do pacote que identificará o aplicativo, esse pacote precisa ter no mínimo dois nomes separados por ponto, por exemplo: <tt>com.nomeDoPacote</tt>. | ||
+ | # Em “Create Activity” digite o nome da janela principal do aplicativo. Por questões de boa prática de programação recomendo que ela tenha o mesmo no digitado em “Application name” | ||
+ | # Em “Min SDK Version” digite o valor da API Level, no nosso caso 7 | ||
+ | # Clique em: finish | ||
+ | Obs.: Não vou mostrar com detalhes de como usar o Eclipse, pois esse não é o objetivo aqui, mas vou colocar, por exemplo: clique no botão run. Aqui subintende-se que se tenha conhecimentos nessa IDE e que esse comando solicitado seja óbvio. | ||
+ | # Localize o bloco Package Explorer | ||
+ | # Clique em: | ||
+ | ## expanda o projeto, caso ele esteja recolhido | ||
+ | ## expanda src | ||
+ | ## expanda o pacote | ||
+ | ## duplo clique no nome do projeto | ||
+ | ## botão run do eclipse | ||
+ | O [http://developer.android.com/sdk/index.html emulador] demorará alguns minutos para inicializar, pois ele simulará o hardware do celular e mais o carregamento do SO Android. Após isso será possível ver na tela a palavra <tt>Hello World, nomeDoProjeto</tt>. | ||
+ | |||
+ | Legal né? Mas como que isso aconteceu sendo que no código Principal, onde tem o nome do aplicativo não existe nenhum comando para imprimir na tela essa String? Na verdade essa string está em um arquivo XML localizado na pasta <tt>res/values</tt> do projeto e nele pode-se criar variáveis estáticas para serem chamadas na classe principal. O arquivo que define quem vai ser a classe principal é o <tt>AndroidManifest.xml</tt> localizado na raiz do projeto. Agora olhando para a classe principal perceba que a classe que foi criada para esse teste é filha da classe [http://developer.android.com/reference/android/app/Activity.html Activity], que é responsável por fazer o controle dos estados e os eventos da tela. Nela, obrigatoriamente, o método <tt>onCreate</tt> precisa ser implementado e ele é chamado pelo SO quando a tela for criada. Mas perceba um detalhe, apesar dessa classe fazer o controle de tela, ela não projeta formas na tela, para isso é necessário chamar o método <tt>setContentView</tt> e passar como argumento o arquivo <tt>main.xml</tt>. O arquivo <tt>main.xml</tt> é utilizado para criar, desenhar os componentes de tela. Mas veja que o <tt>main.xml</tt>, poderia ser <tt>abobrinha.xml</tt>, só que nele tem que estar contido todas essas informações de criação de tela e depois ser passado com argumento no método <tt>setContentView</tt> falado anteriormente. Veja que no nosso caso, foi criado uma tag <nowiki><string></nowiki> com referência <tt>hello</tt> e ela é chamada no m <tt>main.xml</tt> através da tag <nowiki><TextView></nowiki> com atributo <tt>@string/hello</tt>. Recomendo dar uma lida sobre [http://developer.android.com/reference/android/widget/TextView.html TextView]. | ||
+ | |||
+ | ==06/06/11 (Semana 4)== | ||
+ | |||
+ | Essa semana dei continuação aos estudos da classe Activity além da classe Intent. | ||
+ | Desenvolvi também um código exemplo para mostrar o principal uso dessas classes que é pedir ao SO Android a intenção de executar um programa, sendo ela a classe Intent que é responsável por fazer essa interação e a classe Activity que como foi falado anteriormente é responsável por fazer o controle dos estados e os eventos da tela. | ||
+ | Nesse exemplo o programa a seguir é uma tela com dois campos para digitar valores inteiros, ele então soma e envia esse resultado para uma outra. O exemplo é bem simples, pois aqui eu não previ nenhuma condição para caso seja inserido um caractere, então por favor insira somente valores inteiros! :) | ||
+ | Apesar da simplicidade nessa etapa dos estudos, dificuldades na compreensão dessas classes foram encontradas e muitos "bugs" no desenvolvimento do programa apareceram, por isso de uma semana inteira para fazê-lo. | ||
+ | |||
+ | Esse código deve ser colocado na pasta layout do projeto. Ele é responsável por desenhar os elementos na tela. Dê o nome de meu_layout.xml. | ||
+ | <syntaxhighlight lang=xml> | ||
+ | <?xml version="1.0" encoding="utf-8"?> | ||
+ | |||
+ | <!-- | ||
+ | /** | ||
+ | * | ||
+ | * Exemplo Activity e Intent | ||
+ | * | ||
+ | * | ||
+ | * | ||
+ | * @author Sant'Clear Ali Costa | ||
+ | * Graduando de Sistemas de Telecomunicações | ||
+ | * IFSC - Campus São José (antiga Escola Técnica Federal - CEFET) | ||
+ | * | ||
+ | * | ||
+ | */ | ||
+ | --> | ||
+ | |||
+ | <!-- wrap_content -> ocupa apenas o tamho necessário | ||
+ | fill_parent -> ocupa todo o espaço definido pelo layout pai--> | ||
+ | |||
+ | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
+ | android:orientation="vertical" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="fill_parent" | ||
+ | > | ||
+ | <!-- ************************************ --> | ||
+ | <!-- Exibe um label --> | ||
+ | <TextView | ||
+ | android:id="@+id/lbNumero1" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text="Número 1" | ||
+ | /> | ||
+ | <!-- Entrada de dados --> | ||
+ | <EditText | ||
+ | android:id="@+id/tfNumero1" | ||
+ | android:numeric="integer" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | /> | ||
+ | <!-- ************************************ --> | ||
+ | |||
+ | <!-- ************************************ --> | ||
+ | <TextView | ||
+ | android:id="@+id/lbNumero2" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text="Número 2" | ||
+ | /> | ||
+ | <EditText | ||
+ | android:id="@+id/tfNumero2" | ||
+ | android:numeric="integer" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | /> | ||
+ | <!-- ************************************ --> | ||
+ | <!-- Botão --> | ||
+ | <Button | ||
+ | android:id="@+id/btCalcular" | ||
+ | android:layout_width="wrap_content" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text=" Calcular " | ||
+ | /> | ||
+ | </LinearLayout> | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | Esse código deve ser colocado na pasta src do projeto dentro do pacote principal. Essa é a tela principal que calculará e pedirá ao SO Android a intenção de execução do processo da outra tela que será mostrada a seguir. Dê o nome de Calcula.java. | ||
+ | [[imagem:Calcula.jpg|thumb|Calcula.java]] | ||
+ | <syntaxhighlight lang=java> | ||
+ | package bolsa.Telas; | ||
+ | |||
+ | import android.app.Activity; | ||
+ | import android.content.Intent; | ||
+ | import android.os.Bundle; | ||
+ | import android.view.View; | ||
+ | import android.view.View.OnClickListener; | ||
+ | import android.widget.Button; | ||
+ | import android.widget.EditText; | ||
+ | |||
+ | /** | ||
+ | * | ||
+ | * Exemplo Activity e Intent | ||
+ | * | ||
+ | * | ||
+ | * | ||
+ | * @author Sant'Clear Ali Costa | ||
+ | * Graduando de Sistemas de Telecomunicações | ||
+ | * IFSC - Campus São José (antiga Escola Técnica Federal - CEFET) | ||
+ | * | ||
+ | * | ||
+ | */ | ||
+ | |||
+ | public class Calcula extends Activity implements OnClickListener { | ||
+ | public void onCreate(Bundle icicle) { | ||
+ | super.onCreate(icicle); | ||
+ | |||
+ | setContentView(R.layout.meu_layout); | ||
+ | |||
+ | Button btCalcular = (Button) findViewById(R.id.btCalcular); | ||
+ | btCalcular.setOnClickListener(this); | ||
+ | |||
+ | } | ||
+ | |||
+ | public void onClick(View v) { | ||
+ | Intent itRes = new Intent(this, Resultado.class); | ||
+ | |||
+ | EditText tfNumero1 = (EditText) findViewById(R.id.tfNumero1); | ||
+ | EditText tfNumero2 = (EditText) findViewById(R.id.tfNumero2); | ||
+ | |||
+ | int numero1 = Integer.valueOf(tfNumero1.getText().toString()); | ||
+ | int numero2 = Integer.valueOf(tfNumero2.getText().toString()); | ||
+ | |||
+ | int resultado = numero1 + numero2; | ||
+ | |||
+ | itRes.putExtra("res", String.valueOf(resultado)); | ||
+ | startActivity(itRes); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Esse código deve ser colocado na pasta src do projeto dentro do pacote principal. Essa é a tela que receberá a informação de resultado do cálculo feito na tela anterior. Dê o nome de Resultado.java. | ||
+ | [[imagem:Resultado.jpg|thumb|Resultado.java]] | ||
+ | <syntaxhighlight lang=java> | ||
+ | package bolsa.Telas; | ||
+ | |||
+ | import android.app.Activity; | ||
+ | import android.content.Intent; | ||
+ | import android.os.Bundle; | ||
+ | import android.widget.TextView; | ||
+ | |||
+ | /** | ||
+ | * | ||
+ | * Exemplo de Activity e Intent | ||
+ | * | ||
+ | * | ||
+ | * | ||
+ | * @author Sant'Clear Ali Costa | ||
+ | * Graduando de Sistemas de Telecomunicações | ||
+ | * IFSC - Campus São José (antiga Escola Técnica Federal - CEFET) | ||
+ | * | ||
+ | * | ||
+ | */ | ||
+ | |||
+ | public class Resultado extends Activity { | ||
+ | public void onCreate(Bundle icicle) { | ||
+ | super.onCreate(icicle); | ||
+ | |||
+ | Intent itRes = getIntent(); | ||
+ | |||
+ | String res = itRes.getStringExtra("res"); | ||
+ | |||
+ | TextView view = new TextView(this); | ||
+ | view.setText("Resultado = " + res); | ||
+ | setContentView(view); | ||
+ | |||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Esse é o fluxo de interação de uma Activity com "Intenção(Intent)" de executar a próxima tela: | ||
+ | |||
+ | <center><graphviz> | ||
+ | digraph Código | ||
+ | { | ||
+ | "meu_layout.xml" [shape=Mrecord] | ||
+ | "Calcula.java" [shape=Mrecord] | ||
+ | "Resultado.java" [shape=Mrecord] | ||
+ | |||
+ | "meu_layout.xml" -> "Calcula.java" [label="função setContentView"] | ||
+ | "Calcula.java" -> "Resultado.java" [label="objeto de intenção itRes"] | ||
+ | } | ||
+ | </graphviz></center> | ||
+ | |||
+ | ==27/06/2011 (semana 7)== | ||
+ | |||
+ | A Intent é uma das classes mais importantes contidas no Android SDK, pois tudo que é executado no SO Android tem por trás uma Intent (Intenção de executar algum programa), sendo ela a responsável por enviar mensagens ao SO Android de solicitação de que algo seja executado. Por esse motivo vou colocar aqui mais um exemplo, pois o entendimento dessa classe é essencial para o desenvolvimento de aplicativos para o SO Android. | ||
+ | No exemplo a seguir vou mostrar um programa que envia uma mensagem de uma Activity para outra e essa última, ao final de sua execução, retorna um resultado para a Activity que a chamou. | ||
+ | Como no programa mostrado anteriormente eu não detalhei melhor o passo a passo, com fotos, de como criar o projeto, vou colocar no tópico dessa semana. | ||
+ | # Vamos começar executando o Eclipse: | ||
+ | # Antes certifique-se que a localização do SDK, mostrado nas linhas finais da semana 2, está configurada, clicando no menu: | ||
+ | ## Window | ||
+ | ## Preferences | ||
+ | ## Expanda Android | ||
+ | ## Como mostrado na figura (Lembre que o local que você descompactou é algo diferente disso) | ||
+ | ##* | ||
+ | ##* [[imagem:android_RetornoActivity_5.jpg]] | ||
+ | ## Clique em finish | ||
+ | # Agora criaremos o projeto clicando no botão como mostrado nas figuras | ||
+ | #* [[imagem:android_RetornoActivity_6.jpg]] | ||
+ | #* | ||
+ | #* [[imagem:android_RetornoActivity_7.jpg]] | ||
+ | #* | ||
+ | # Expanda a pasta do projeto “meuActivityIntent” | ||
+ | # Crie um arquivo .xml da tela principal como mostrado na figura | ||
+ | #* | ||
+ | #* [[imagem:android_RetornoActivity_8.jpg]] | ||
+ | #* | ||
+ | #* Cole esse código: <syntaxhighlight lang=xml><?xml version="1.0" encoding="utf-8"?> | ||
+ | |||
+ | <!-- wrap_content -> ocupa apenas o tamho necessário | ||
+ | fill_parent -> ocupa todo o espaço definido pelo layout pai--> | ||
+ | |||
+ | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
+ | android:orientation="vertical" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="fill_parent" | ||
+ | > | ||
+ | <TextView | ||
+ | android:id="@+id/lbListaFuncionarios" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text="LISTA DE FUNCIONÁRIOS" | ||
+ | /> | ||
+ | <TextView | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text=" " | ||
+ | /> | ||
+ | <TextView | ||
+ | android:id="@+id/lbFuncionario" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text="" | ||
+ | /> | ||
+ | <Button | ||
+ | android:id="@+id/btCadastrar" | ||
+ | android:layout_width="wrap_content" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text="Cadastrar" | ||
+ | /> | ||
+ | </LinearLayout></syntaxhighlight> | ||
+ | # Salve esse arquivo com CTRL + S do teclado | ||
+ | # Repita o mesmo procedimento criando um outro arquivo .xml, porém com o nome cadastro_layout.xml | ||
+ | #* E cole esse código: <syntaxhighlight lang=xml><?xml version="1.0" encoding="utf-8"?> | ||
+ | |||
+ | <!-- wrap_content -> ocupa apenas o tamho necessário | ||
+ | fill_parent -> ocupa todo o espaço definido pelo layout pai--> | ||
+ | |||
+ | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
+ | android:orientation="vertical" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="fill_parent" | ||
+ | > | ||
+ | <TextView | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text="CADASTRO DE FUNCIONÁRIOS" | ||
+ | /> | ||
+ | <TextView | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text=" " | ||
+ | /> | ||
+ | <TextView | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text="Nome:" | ||
+ | /> | ||
+ | <EditText | ||
+ | android:id="@+id/tfNome" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | /> | ||
+ | <TextView | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text="Setor:" | ||
+ | /> | ||
+ | <EditText | ||
+ | android:id="@+id/tfSetor" | ||
+ | android:layout_width="fill_parent" | ||
+ | android:layout_height="wrap_content" | ||
+ | /> | ||
+ | <Button | ||
+ | android:id="@+id/btEnviar" | ||
+ | android:layout_width="wrap_content" | ||
+ | android:layout_height="wrap_content" | ||
+ | android:text=" Enviar " | ||
+ | /> | ||
+ | </LinearLayout></syntaxhighlight> | ||
+ | # Agora crie uma classe como mostrado nas figuras | ||
+ | #* | ||
+ | #* [[imagem:android_RetornoActivity_10.jpg]] | ||
+ | #* | ||
+ | #* [[imagem:android_RetornoActivity_11.jpg]] | ||
+ | #* Cole esse código: | ||
+ | [[imagem:android_RetornoActivity_2.jpg|thumb|Cadastro.java]] | ||
+ | #* <syntaxhighlight lang=java>package bolsa.meuActivityIntent; | ||
+ | import android.app.Activity; | ||
+ | import android.content.Intent; | ||
+ | import android.os.Bundle; | ||
+ | import android.view.View; | ||
+ | import android.widget.Button; | ||
+ | import android.widget.EditText; | ||
+ | |||
+ | /** | ||
+ | * | ||
+ | * Exemplo de Activity e Intent com Retorno de Resultado | ||
+ | * | ||
+ | * @author Sant'Clear Ali Costa Graduando de Sistemas de Telecomunicações IFSC - | ||
+ | * Campus São José (antiga Escola Técnica Federal - CEFET) | ||
+ | * | ||
+ | */ | ||
+ | |||
+ | public class Cadastro extends Activity{ | ||
+ | |||
+ | @Override | ||
+ | protected void onCreate(Bundle savedInstanceState) { | ||
+ | |||
+ | super.onCreate(savedInstanceState); | ||
+ | |||
+ | setContentView(R.layout.cadastro_layout); | ||
+ | |||
+ | Button btEnviar = (Button) findViewById(R.id.btEnviar); | ||
+ | |||
+ | btEnviar.setOnClickListener(new View.OnClickListener() { | ||
+ | |||
+ | public void onClick(View v) { | ||
+ | |||
+ | Intent it = new Intent(); | ||
+ | |||
+ | EditText tfNome = (EditText) findViewById(R.id.tfNome); | ||
+ | EditText tfSetor = (EditText) findViewById(R.id.tfSetor); | ||
+ | |||
+ | String formulario = "Nome: "+ tfNome.getText().toString() +"\n"+"Setor: "+ tfSetor.getText().toString() +"\n\n"; | ||
+ | |||
+ | it.putExtra("formCadastro", formulario); | ||
+ | |||
+ | // Seta o status do resultado e a Intent | ||
+ | setResult(1, it); | ||
+ | |||
+ | // Fim desta activity | ||
+ | finish(); | ||
+ | } | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | # Salve esse arquivo com CTRL + S do teclado | ||
+ | # Apague todas a linhas de código do arquivo Lista.java e cole o código a seguir | ||
+ | [[imagem:android_RetornoActivity_1.jpg|thumb|Lista.java - Sem funcionários cadastrados]] | ||
+ | [[imagem:android_RetornoActivity_3.jpg|thumb|Lista.java - Depois de cadastrar funcionário]] | ||
+ | #* <syntaxhighlight lang=java>package bolsa.meuActivityIntent; | ||
+ | import android.app.Activity; | ||
+ | import android.content.Intent; | ||
+ | import android.os.Bundle; | ||
+ | import android.view.View; | ||
+ | import android.view.View.OnClickListener; | ||
+ | import android.widget.Button; | ||
+ | import android.widget.TextView; | ||
+ | |||
+ | /** | ||
+ | * | ||
+ | * Exemplo de Activity e Intent com Retorno de Resultado | ||
+ | * | ||
+ | * @author Sant'Clear Ali Costa Graduando de Sistemas de Telecomunicações IFSC - | ||
+ | * Campus São José (antiga Escola Técnica Federal - CEFET) | ||
+ | * | ||
+ | */ | ||
+ | |||
+ | public class Lista extends Activity implements OnClickListener { | ||
+ | |||
+ | // Para identificar a chamada no método onActivityResult | ||
+ | private static final int ACTIVITY_CADASTRO = 1; | ||
+ | private String formulario = ""; | ||
+ | |||
+ | @Override | ||
+ | protected void onCreate(Bundle icicle) { | ||
+ | |||
+ | super.onCreate(icicle); | ||
+ | |||
+ | // Utilize o modelo de layout lista_layout | ||
+ | setContentView(R.layout.lista_layout); | ||
+ | TextView semFuncionario = (TextView) findViewById(R.id.lbFuncionario); | ||
+ | |||
+ | if (formulario == "") | ||
+ | |||
+ | semFuncionario.setText("NÃO EXISTE FUNCIONÁRIO CADASTRO NO MOMENTO\n"); | ||
+ | |||
+ | // Instanciado o botão btCadastrar contido no lista_layout | ||
+ | Button btCadastrar = (Button) findViewById(R.id.btCadastrar); | ||
+ | |||
+ | // Aguarda o botão ser clicado | ||
+ | btCadastrar.setOnClickListener(this); | ||
+ | |||
+ | } | ||
+ | |||
+ | // Quando o botão for pressionando entre neste método | ||
+ | public void onClick(View v) { | ||
+ | |||
+ | // Cria uma Intenção de iniciar uma Atividade de Cadastro | ||
+ | Intent it = new Intent(this, Cadastro.class); | ||
+ | |||
+ | /* | ||
+ | * | ||
+ | * Manifesta essa Intenção ao SO Android | ||
+ | * Se nesse momento houver memória disponível, | ||
+ | * se não houver Atividades prioritárias sendo executadas, | ||
+ | * etc, então a Atividade Cadastro é iniciada | ||
+ | * | ||
+ | */ | ||
+ | startActivityForResult(it, ACTIVITY_CADASTRO); | ||
+ | |||
+ | } | ||
+ | |||
+ | @Override | ||
+ | protected void onActivityResult(int codigo, int resultado, Intent it) { | ||
+ | |||
+ | // Instanciado o label lbFuncionario contido no lista_layout | ||
+ | TextView lbFuncionario = (TextView) findViewById(R.id.lbFuncionario); | ||
+ | |||
+ | if (codigo == ACTIVITY_CADASTRO) { | ||
+ | |||
+ | // Se a Atividade Cadastro não retornar nenhum valor | ||
+ | if (it != null) { | ||
+ | |||
+ | /* | ||
+ | * | ||
+ | * Armazena no formulario o formCadastro passado na finalização | ||
+ | * da Atividade Cadastro | ||
+ | * | ||
+ | */ | ||
+ | formulario += it.getStringExtra("formCadastro"); | ||
+ | |||
+ | /* | ||
+ | * | ||
+ | * Verifica o status do resultado da Atividade Cadastro | ||
+ | * Por exemplo, se houver varios botoes, cada botão terá que ter um | ||
+ | * código de resultado diferente para poder identificá-lo | ||
+ | * Como na Atividade cadastro não existe outros eventos além do onClick, | ||
+ | * estão nem precisaria desses ifs. Apenas deixei aqui, como | ||
+ | * exemplo, caso se queira criar outros eventos no Cadastro para | ||
+ | * ter outros resultados de identificação | ||
+ | * | ||
+ | */ | ||
+ | if (resultado == 1) { | ||
+ | |||
+ | lbFuncionario.setText(formulario); | ||
+ | |||
+ | } else if (resultado == 2) { | ||
+ | |||
+ | // Algum código aqui | ||
+ | |||
+ | } else { | ||
+ | |||
+ | // Algum código aqui | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | /* | ||
+ | * Quando se quer coletar o valor de retorno de uma Atividade ela | ||
+ | * deve ter um código de identificação. No nosse exemplo temos apenas | ||
+ | * uma atividade: Cadastro, então não precisaria aqui também estes | ||
+ | * ifs, porém coloquei aqui, como exemplo, caso se queira criar | ||
+ | * outras Atividades | ||
+ | */ | ||
+ | } else if (codigo == 2) { | ||
+ | |||
+ | // Algum código aqui | ||
+ | |||
+ | } else { | ||
+ | |||
+ | // Algum código aqui | ||
+ | |||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | # Salve esse arquivo com CTRL + S do teclado | ||
+ | # Uma coisa importante que esqueci de mencionar no código da outra semana é que não pode nunca esquecer de incluir no arquivo AndroidManifest.xml toda classe que é criada, pois como falado na semana 3 ele é o arquivo que define quem vai ser a classe principal, além de conter todas as classes que serão carregadas quando o programa for executado. Se esse arquivo não estiver configurado, e você quiser chamar uma Activity que não está configurada nesse arquivo, o SO Android irá diparar uma exceção. | ||
+ | # Para configurar faça como mostrado nas figuras | ||
+ | #* | ||
+ | #* [[imagem:android_RetornoActivity_12.jpg]] | ||
+ | #* | ||
+ | #* [[imagem:android_RetornoActivity_13.jpg]] | ||
+ | #* | ||
+ | #* [[imagem:android_RetornoActivity_14.jpg]] Obs: Clique em ADD | ||
+ | #* | ||
+ | #* Selecione as Activity's do projeto | ||
+ | #* | ||
+ | #** [[imagem:android_RetornoActivity_15.jpg]] | ||
+ | |||
+ | == 09/08/2011 (semana 14) == | ||
+ | |||
+ | Desde a volta das férias de julho comecei a fase de projetar o software. Essa semana, mais especificamente, descrevi, baseado em orientações, o caso de uso do software da fase inicial do projeto:<br> | ||
+ | Usuário digita endereço remoto de um PC para estabelecer uma conexão fim-a-fim com ele. Após a conexão é possível digitar comandos de arquivos executáveis definidos na variável de ambiente (PATH), para administração remota de sistema operacional. O software aprende, com auxílio de um arquivo de histórico, os comando mais usados com suas respectivas flags de opção, oferecendo em uma lista os 10 mais usados para facilitar a digitação.<br> | ||
+ | Pesquisei, também, uma classe Java que auxiliasse a comunicação com o SO GNU/Linux, para que através de um programa Java se possa executar, por exemplo, algum comando do Bash, e esse foi o código que desenvolvi: | ||
+ | <syntaxhighlight lang=java> | ||
+ | import java.io.*; | ||
+ | import java.util.Scanner; | ||
+ | /** | ||
+ | * | ||
+ | * Exemplo de execução de comando Bash | ||
+ | * | ||
+ | * @author Sant'Clear Ali Costa Graduando de Sistemas de Telecomunicações IFSC - | ||
+ | * Campus São José (antiga Escola Técnica Federal - CEFET) | ||
+ | * | ||
+ | */ | ||
+ | class Execbash { | ||
+ | public static void main(String[] args) { | ||
+ | // String que contém o comando GNU/Linux | ||
+ | // String cmd = "ls -l /home/santclear/\"Eclipse Indigo\" | grep '^-..x' | awk '{print $8;}'"; | ||
+ | String cmd = "echo $PATH"; | ||
+ | // Primeiro parâmetro passado ao construtor para criar o processo bash | ||
+ | // Segundo parâmetro passado ao construtor é a flag de opção -c para que os comandos seja lidos como string | ||
+ | // Terceiro parâmetro passado ao construtor é um comando válido do processo bash | ||
+ | ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd); | ||
+ | /* Qualquer saída de erro gerada por subprocessos posteriormente iniciados pelo método start() deste objeto | ||
+ | * será fundida com a saída padrão, de modo que ambos podem ser lidos usando o método Process.getInputStream(). | ||
+ | * Isto torna mais fácil para correlacionar mensagens de erro com a saída correspondente*/ | ||
+ | pb.redirectErrorStream(true); | ||
+ | try { | ||
+ | // O método start() inicia um novo processo com os parâmentros passados para o construtor do objeto pb | ||
+ | Process p = pb.start(); | ||
+ | /* O método getInputStream() Retorna o fluxo de entrada ligada à saída normal do subprocesso. | ||
+ | * O fluxo obtém dados canalizado a partir da saída padrão do processo representado por este objeto de processo*/ | ||
+ | InputStream input = p.getInputStream(); | ||
+ | Scanner sc = new Scanner(input); | ||
+ | while(sc.hasNext()){ | ||
+ | System.out.println(sc.next()); | ||
+ | } | ||
+ | input.close(); | ||
+ | } catch (Exception e) { | ||
+ | System.out.println("Exception--->" + e.getMessage()); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | =Referências Bibliográficas= | ||
+ | <references/> |
Edição atual tal como às 09h14min de 9 de agosto de 2011
Projeto
O projeto "Administração Centralizada de Sistemas Operacionais" foi realizado no Instituto Federal de Educação, Ciência e Tecnologia de Santa Catarina Campus São José, no período de 02/08/2010 à 22/12/2010 pelo aluno Gustavo Paulo Medeiros Da Silva (4ª fase, CST Sistemas de Telecomunicações) e orientado pelo professor Ederson Torresini.
Objetivos
Centralizar a administração dos sistemas operacionais de uma rede.
Diário de Bordo
06/08/2010 (semana 1)
Nesta primeira semana foi feita uma pesquisa para conhecer e comparar programas que copiam imagens de um SO para outros computadores, através da rede. A seguir tem uma tabela comparando os programas pesquisados.
Armazenamento de partição | Operações pós-instalação | ||||||
Projeto | S.O. baseado em... | Livre? | Multicast | Protocolos | Sistema de arquivo | Trocar o nome da máquina | redimensionamento de partição |
FOG Project | UNIX, DOS | Sim | Sim | TFTP, UDP, TCP, NFS | NTFS, XFS, JFS, HPFS, FAT16/32, Reiser3, EXT2, EXT3 | Sim**** | Sim*** |
Clonezilla | UNIX | Sim | Sim | TFTP, UDP, TCP | NTFS, FAT16/32, EXT2, EXT3, Reiserfs | Não* | Sim** |
Symantec Ghost | DOS, UNIX | Não | Sim | TCP | NTFS, FAT16/32, EXT2, EXT3 | Não* | Sim** |
G4U | UNIX | Sim | Não | FTP, TCP | Todos (copia bit-a-bit) | Não* | Não |
UDP Cast | UNIX | Sim | Sim | TFTP, UDP | Todos (copia bit-a-bit) | Não* | Não |
Partimage | UNIX | Sim | Não | NFS, UDP, TCP | FAT16/32, Reiser3, EXT2, EXT3 | Não* | Não |
(*) É necessário trocar o nome dos computadores para não haver confusão na rede. Trocar o nome,
máquina por máquina.
(**) Não é possível utilizar a rede, tem que realizar o boot no cd de instalação do produto.
(***) O redimensionamento é feito apenas com imagens do sistema Windows. Para esse caso redimensionar é colocar uma imagem de um disco rígido de 200 GB em um disco rígido de 10GB, enquanto os dados são menores do que 10GB.
(****) A troca é possível apenas para o Windows.
11/08/2010 (semana 2)
Problema
Para redes pequenas, formatar computador por computador é um problema, porém, quando estamos falando de uma rede com maior porte (15 computadores no mínimo), o problema aumenta, porque o tempo gasto para formatar todas as máquinas será muito grande.
Proposta de Solução
Centralizar a administração de sistemas operacionais utilizando um servidor de distribuição de imagens.
Objetivo Geral
O objetivo geral do projeto é diminuir o tempo gasto pela formatação dos computadores.
Objetivos específicos
1- Copiar imagens para computadores com características físicas diferentes (HD, memória, etc).
13/08/2010 (semana 2)
Para a escolha do servidor de imagens foi feito uma lista de requisitos onde o servidor terá que atender.
Requisitos | Que seja... |
Custo | Gratuito |
SO | Unix |
Protocolo | Protocolo de transferência simples (TFTP) |
Sistemas de arquivos | O maior número possível |
Operações pós instalação | Modificar o nome do computador e expandir a partição (ou partições) |
De acordo com a pesquisa realizada, o programa que atende os requisitos mínimos para a execução do projeto foi o FOG Project.
27/08/2010 (semana 4)
Para realizar testes com o servidor escolhido vamos preparar um cenário onde apenas o servidor e um cliente estarão ativos. Por precaução, o servidor e o cliente serão instalados em máquinas virtuais rodando o UBUNTU 10.4 (OBS: O SERVIDOR SÓ FUNCIONA COM A INSTALAÇÃO DO UBUNTU EM INGLÊS). Além das máquinas, será feita uma rede virtual (Vlan) para separá-los da rede da instituição com o intuito de evitar futuro transtornos.
14/09/2010 (semana 7)
Ao longo das últimas semanas tivemos dificuldades com a montagem do cenário de testes, detalhes despercebidos estavam atrapalhando a execução do projeto que aos poucos foram encontrados e eliminados.
Problemas
- 1° - Para o servidor de imagens funcionar é preciso que a instalação do Ubuntu esteja em inglês.
- 2° - Para as vlans se "enxergarem" é preciso que as máquinas virtuais estejam na mesma rede. No VirtualBox por padrão, na configurações de rede no campo conectado a está selecionado a opção NAT, opção que separa a máquina virtual da rede do hospedeiro, para as vlans funcionarem é preciso selecionar a opção Interface do Hospedeiro ou Placa em modo Bridge.
- 3° - Para o VirtualBox dá o boot pela rede, ele irá procurar o servidor na rede real, desprezando a vlan. Para dá o boot na vlan, é preciso configurar uma interface vitual no computador hospedeiro e na configurações de rede do VirtualBox no campo NOME selecione a interface virtual criada, (ex.: eth0.1).
Organização do cenário de testes
- A máquina virtual onde o servidor está instalado tem acesso a rede real e a vlan.
- A máquina virtual que será o cliente tem acesso apenas a vlan.
<graphviz> digraph Redes { "VirtualBox (1)" [shape=Mrecord] "VirtualBox (2)" [shape=Mrecord] "eth0.1 (1)" [color=blue] "eth0.1 (2)" [color=blue] "eth0 (1)" [color=red] "eth0 (2)" [color=red]
"FOG Project" -> "VirtualBox (1)" "VirtualBox (1)" -> "Computador 1" "VirtualBox (1)" -> "eth0.1 (1)" [color=blue] "VirtualBox (1)" -> "eth0 (1)" [color=red] "Computador 1" -> "eth0 (1)" [color=red]
"VirtualBox (2)" -> "Computador 2" "VirtualBox (2)" -> "eth0.1 (2)" [color=blue] "Computador 2" -> "eth0.1 (2)" [color=blue] "Computador 2" -> "eth0 (2)" [color=red]
"rede real" [color=red] "eth0 (1)" -> "rede real" [color=red] "eth0 (2)" -> "rede real" [color=red]
"vlan" [color=blue] "eth0.1 (1)" -> "vlan" [color=blue] "eth0.1 (2)" -> "vlan" [color=blue] subgraph clusterKernel { label="rede física" "rede real" "vlan"
} } </graphviz>
Legenda:
- ----->: vlan.
- ----->: rede real.
- ----->: Máquina onde está instalado.
- (1): parte do servidor.
- (2): parte do cliente.
- eth0: interface de rede (rede real).
- eth0.1: interface de rede (vlan).
30/09/2010 (semana 9)
Testes de cópia.
Ao longo das últimas semanas alguns testes foram feitos com o servidor.
- Teste n° 1 - o cliente irá fornecer uma cópia de si mesma para o servidor.
Depois da várias tentativas sem sucesso, notamos que no momento em que o servidor estava tentando copiar o sistema do cliente, aparecia na tela em um curto momento um erro com o "NFS" (na verdade quem notou esse erro foi o prof. Ederson, eu nem enxerguei isso).
Um erro com NFS, pra começar, o que é NFS?
É um aplicativo que torna uma pasta de um coputador visível por todos os computadores da mesma rede. Para mais informações siga o link http://pt.wikipedia.org/wiki/Network_File_System
O motivo do erro com o "NFS" ainda é desconhecido, mas para funcionar, instalei um servidor "NFS" em outro computador e alguns testes foram feitos. Os testes foram simples, Montar uma pasta no computador onde estar instalado o FOG (esse computador será o cliente NFS) e no computador servidor NFS, na pasta onde será compartilhada deixar um arquivo qualquer, após os testes o servidor não apresentava mais problemas.
- Teste n° 2 - um outro cliente irá puxar a imagem do servidor FOG.
O teste dois apenas está funcionando com outra máquina com as mesmas características (HD com mesmo tamanho), máquinas com características diferentes ainda apresentam erros.
01/10/2010 (semana 9)
Os testes feitos ontem foram repetidos, mas desta vez, com sistema operacional Windows XP.
O teste um não apresentou nem um tipo de problema, nem mesmo com o NFS. O teste dois continua com o mesmo problema,
está funcionando com outra máquina com as mesmas características, máquinas com características diferentes ainda apresentam erros.
13/10/2010 (semana 11)
Cópia de imagens para as máquinas.
- Imagens - ubuntu, windows (as duas imagens são clones de máquinas com um HD de 3 GB, o ubuntu é do tipo Multiple Partition - All Disks e o windows é do tipo Single Partition NTFS).
- Hosts - windows, ubuntu, windows_pequeno, ubuntu_pequeno, SEM_SO.
windows e ubuntu possuem um HD de 8 GB.
windows_pequeno e ubuntu_pequeno possuem HD de 3 GB.
SEM_SO, HD de 3 GB e sem sistema operacional.
imagem | máquinas | aceita |
windows | windows_pequeno | S |
windows | windows | N * |
windows | ubuntu_pequeno | S |
windows | SEM_SO | S |
ubuntu | windows_pequeno | S |
ubuntu | ubuntu | N ** |
ubuntu | ubuntu_pequeno | S |
ubuntu | SEM_SO | N |
(*) copia, mas após a cópia aparece "Erro de disco".
(**) antes de começar o processo de cópia abre um terminal de comandos grub.
14/10/2010 (semana 11)
O teste agora é com uma imagem do ubuntu do tipo Multiple Partition - Single Disk com 3 GB, os resultados não mudaram muito de acordo com a tabela anterior mas desta vez a máquina de 8 GB de HD aceitou a imagem ubuntu.
22/10/2010 (semana 12)
Após um computador com um HD de 8 GB ter um sistema de 3 GB precisamos aumentar a partição.
Como fazer isso de maneira rápida e se está com a partição montada?
- 1- Podemos dá um boot em um cd de instalação e aumentar a partição. Esse método é demorado.
- 2- entrar no ubuntu, utilizar o comandos parted ou fdisk para criar uma nova partição para preencher o restante do disco, esses comandos não funcionam com o disco montado. A intenção é aumentar partição para preencher o restante do disco e não criar uma nova. Esse método é inadequado.
- 3- Junto com o servidor FOG ter também um servidor LTSP para processar os comandos fdisk ou parted sem estar com o HD montado. Método adequado.
26/10/2010 (semana 13)
O servidor LTSP não obteve sucessos e como este projeto tem prazo de conclusão não vou me aprofundar nos seus mecanismos.
29/10/2010 (semana 13)
Testes com multicast.
Os testes com multicast foram um pouco limitados pelo motivo do cenário de teste ser apenas com dois computadores reais, mas nada que atrapalhe esse método com três máquinas virtuais rodando com 200 MB de RAM. Demerou um pouco mas os testes ocorreram bem.
O servidor FOG irá disponibilizar uma única imagem, é o mesmo processo do unicast, mas agora possui vários clientes que devem estar alinhados para receber a imagem.
Para fazer o alinhamento é preciso modificar o campo "UDPSENDER_MAXWAIT" do arquivo /opt/fog/service/etc/config.php, esse campo indica o quanto tempo (em segundos) em que todos os computadores que irão puxar a imagem devem estar preparados, no meu caso, como testei com três máquinas virtuais configurei para esperar dez segundos, caso um computador se atrase a cópia não é feita e todos os outros computadores ficam travados.
03/11/2010 (semana 14)
Nome de interface de rede diferente.
Ao digitar o comando ifconfig no terminal de um computador que recebeu uma imagem, a interface de rede estará com um nome diferente de "eth0", como "eth1" ou "eth2".
eth1 Link encap:Ethernet Endereço de HW 00:08:54:45:30:2d
inet end.: 172.18.22.149 Bcast:172.18.255.255 Masc:255.255.0.0
endereço inet6: fe80::208:54ff:fe45:302d/64 Escopo:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Métrica:1
pacotes RX:4785911 erros:0 descartados:0 excesso:0 quadro:0
Pacotes TX:3214739 erros:0 descartados:0 excesso:0 portadora:0
colisões:0 txqueuelen:1000
RX bytes:1415960411 (1.4 GB) TX bytes:2246766805 (2.2 GB)
IRQ:20 Endereço de E/S:0x2000
lo Link encap:Loopback Local
inet end.: 127.0.0.1 Masc:255.0.0.0
endereço inet6: ::1/128 Escopo:Máquina
UP LOOPBACK RUNNING MTU:16436 Métrica:1
pacotes RX:4 erros:0 descartados:0 excesso:0 quadro:0
Pacotes TX:4 erros:0 descartados:0 excesso:0 portadora:0
colisões:0 txqueuelen:0
RX bytes:240 (240.0 B) TX bytes:240 (240.0 B)
Para resolver esse problema, antes de clonar um computador, devemos excluir o arquivo "/etc/udev/rules.d/70-persistent-net.rules", esse arquivo é responsável por ligar um endereço MAC a um nome.
Quando o computador é reiniciado o arquivo excluído é restaurado.
Caso o arquivo do computador clonado não é excluído, o arquivo do computador que recebe a imagem ficará assim.
# This file maintains persistent names for network interfaces.
# See udev(7) for syntax.
#
# Entries are automatically added by the 75-persistent-net-generator.rules
# file; however you are also free to add your own entries.
ENDEREÇO MAC DO COMPUTADOR CLONADO.
# PCI device 0x10ec:0x8168 (r8169)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:1a:4d:a5:17:28", ATTR{type}=="1",
KERNEL=="eth*", NAME="eth0"
ENDEREÇO MAC DO COMPUTADOR CLIENTE.
# PCI device 0x10ec:0x8169 (r8169)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:08:54:45:30:2d", ATTR{type}=="1",
KERNEL=="eth*", NAME="eth1"
!!!Note que o MAC "00:08:54:45:30:2d" está com a interface "eth1"!!!
Caso contrário.
# This file maintains persistent names for network interfaces.
# See udev(7) for syntax.
#
# Entries are automatically added by the 75-persistent-net-generator.rules
# file; however you are also free to add your own entries.
ENDEREÇO MAC DO COMPUTADOR CLIENTE.
# PCI device 0x10ec:0x8169 (r8169)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:08:54:45:30:2d", ATTR{type}=="1",
KERNEL=="eth*", NAME="eth0"
!!!Note que o MAC "00:08:54:45:30:2d" está com a interface "eth0"!!!
10/11/2010 (semana 15)
Nomes dos computadores iguais.
Um problema de uma distribuição de imagens é que todos os computadores que receberem essa imagem terão o mesmo nome. O servidor FOG apresenta uma solução mas apenas para sistemas Windows [1]. Para o Ubuntu é preciso mudar manualmente em cada máquina ou fazer um programa para fazer isso automaticamente.
Estratégia do programa.
O programa irá consultar o endereço MAC do computador no arquivo "/etc/udev/rules.d/70-persistent-net.rules", comparar com um arquivo texto onde está registrado o seu MAC e o seu nome e depois o programa irá modificar o arquivo "/etc/hostname".
//feito por Gustavo Paulo Medeiros Da Silva
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
main(){
int i, x=1, n=0, m=16;
char *y;
char mac1[19], mac2[273], mac3[18]="ATTR{address}==", nome[18], nome1[50];
//abre o arquivo o arquivo 70-persistent-net.rules
FILE *pt;
pt=fopen("/etc/udev/rules.d/70-persistent-net.rules","r");
//faz a leitura e contatena cada string até a string que contém o primeiro endereço MAC em "mac2"
for(i=0;i<44;i++){
fscanf(pt,"%s",mac1);//lê estring do arquivo
strcat(mac2,mac1);
}
fclose(pt);
//procura em "mac2" a string "ATTR{address}==" e copia o endereço MAC para "y"
y=strstr (mac2, mac3);
//filtra o endereço MAC para a string "mac3"
while(n<=16){
mac3[n]=y[m];
n++, m++;
}
FILE *p;
p=fopen("nome.txt","r");//abre o arquivo nome.txt
//se o arquivo não for encontrado o programa é finalizado
//o arquivo nome tem que ficar no diretório onde o programa está sendo executado
if (!p){
printf ("O arquivo nome.txt não foi encontrado!\n");
exit (1);
}
//procura o nome ligado ao MAC
while(x!=0){
fscanf(p,"%s",nome1);
x= strcmp ( mac3, nome1 );
//se o MAC está registrado no arquivo nome.txt, o nome é passado para string "nome"
if(x==0){
fscanf(p,"%s",nome);
printf("%s %s\n",mac3,nome);
}
//se o endereço MAC não for encontrado o programa é finalizado
i=feof(p);
if(i==1){
printf("Este computador não está registrado no arquivo nome.txt!\n");
exit (1);
}
}
fclose(p);
x=strlen(nome);
//grava o nome no arquivo /etc/hostname
FILE *f;
f=fopen("/etc/hostname","w");
//Para executar esse programa é preciso ser administrador
if (!f){
printf ("Para alterar o nome desse computador é preciso ser administrador!\n");
exit (1);
}
fwrite(nome,x,1,f);
fclose(f);
//reiniciar o computador para alterar o nome
printf("É necessário reiniciar, continuar? Ctrl+C para cancelar...\n");
getchar();
system("sudo reboot");
}
O arquivo "nome.txt" que o programa irá consultar deve estar no mesmo diretório do programa.
- endereço_mac nome_do_computador
00:08:54:45:30:2d nome_1
00:1d:7d:fb:2a:a0 nome_2
00:1a:4d:a5:17:28 nome_3
</syntaxhighlight>
8/12/2010 (semana 20)
Controle de computadores em uma rede.
Nas ultimas cinco semanas, estava tentando fazer um programa que de alguma forma controlaria computadores em uma rede local. Esse método existe, através do ssh, mas não em multicast.
É um pouco complicado, mas se quebrar-mos a cabeça podemos sim ter um controle em multicast.
Como eu não sou um expert em liguagem C, os programas são umas gambiarras, mas o importante é que funciona.
O problema é que não podemos ter uma interação com os computadores, por exemplo, o comando top, vi e outros, os comandos têm que ser simples.
Primeiro o programa irá enviar em broadcast uma string indicando que o servidor quer se comunicar com os clientes.
Os clientes então enviam as suas informações como nome e as interfaces que possui.
Agora podemos enviar os comandos, esses comandos passam por uma espécie de criptografia para tornar o processo um pouco mais seguro.
Os programas foram montados em socket UDP para facilitar o processo de broadcast.
O programa servidor que irá enviar os comandos.
//Programa servidor
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#define HELLO_PORT 12345
#define HELLO_GROUP "225.0.0.0"
#define MSGBUFSIZE 1500
int i, x=1,n=0, cont=0, comp;
char bin[]=" < /bin/sh";
char b, string[1000], info[1500], tab[]=" ", vir[]=";", saida[]="exit";
const char* interface ="p";
//parte servidor
void servidor(){
printf("\e[;m");
struct sockaddr_in addr;
int fd, cnt, nbytes, addrlen;
struct ip_mreq mreq;
char comando[1500];
char msgbuf[MSGBUFSIZE];
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(1);
}
// set up destination address
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
addr.sin_port=htons(HELLO_PORT);
//laço onde é digitados os comandos
while (1) {
printf(">> ");
gets(&comando[0]);
i=strlen(comando);
comp=strcmp(saida,comando);
//criptografa os comandos
for(x=0;x<i;x++){
comando[x]=comando[x]+5237;
}
//envia os comandos
if (sendto(fd,comando,sizeof(comando),0,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("sendto");
exit(1);
}
if(comp==0){
exit(0);
}
}
}
main(int argc, char *argv[]){
struct sockaddr_in addr;
int fd, cnt, nbytes, addrlen;
struct ip_mreq mreq;
char comando[1500];
char msgbuf[MSGBUFSIZE];
//avisa para os computadores que o servidor está ativo enviando a string "pronto_para_conexao"
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(1);
}
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
addr.sin_port=htons(HELLO_PORT);
char pronto[]="pronto_para_conexao";
//envio da string
if (sendto(fd,pronto,sizeof(pronto),0,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("sendto");
exit(1);
}
close(fd);
//parte em que o servidor passa a ter o papel de cliente para receber as informações das interfaces
u_int yes=1;
// create what looks like an ordinary UDP socket
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(1);
}
// allow multiple sockets to use the same PORT number
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
perror("Reusing ADDR failed");
exit(1);
}
// set up destin(ioctl(sock, SIOCGIFADDR, &ifr[iface])ation address
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY); // N.B.: differs from sender
addr.sin_port=htons(HELLO_PORT);
// bind to receive address
if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("bind");
exit(1);
}
// use setsockopt() to request that the kernel join a multicast group
mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
while (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
}
if (sendto(fd,comando,sizeof(comando),0,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("sendto");
exit(1);
}
//tempo para se conectar com o servidor 1 segundo, após esse tempo o servidor estará pronto para enviar os comandos
//as informações das interfaces dos clientes são recebidas
alarm(1);
while(1){
signal(SIGALRM, servidor);
addrlen=sizeof(addr);
//recebe as informações
if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0) {
perror("recvfrom");
exit(1);
}
//descriptografar as informações das interfaces
i=strlen(msgbuf);
for(x=i-1;x>=0;x--){
msgbuf[x]=msgbuf[x]-5237;
}
printf("\e[31m");
if(cont!=0){
printf("+----------------------------------------------------------------+\n");
printf("%s\n",msgbuf);
printf("+----------------------------------------------------------------+\n");
}
cont++;
}
}
O programa cliente foi planejado para está sempre ativo enquanto o computador estiver ligado.
Um bom conselho é deixar o programa cliente no arquivo de iniciação do sistema, caso precisamos de executar um comando sendo administrador não precisar dar o comando sudo.
Para fazer isso.
Compile o programa o salve no diretório /etc/init.d.
No terminal dentro do caminho /etc/init.d, digite o comando:
sudo chmod 755 programa_cliente
Isso dará as permissões necessárias para o arquivo ser executado.
Após ter feito isso, utilize o seguinte comando:
sudo update-rc.d programa_cliente defaults
Isso atualizará os diretórios rc.d, adicionando o programa na inicialização do sistema.
O servidor é ativado apenas quando quisermos utiliza-lo.
//Programa cliente
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <stdlib.h>
#define HELLO_PORT 12345
#define HELLO_GROUP "225.0.0.0"
#define MSGBUFSIZE 1500
int i,x=1,a,n=0, cont=0, comp, conexao=0;
char bin[]=" < /bin/sh", saida[]="exit";
char string[1000], info[1500], tab[]=" ", vir[]=";";
const char* interface ="p";
char pronto[]="pronto_para_conexao";
main(int argc, char *argv[]){
struct sockaddr_in addr;
int fd, cnt, nbytes, addrlen;
struct ip_mreq mreq;
char comando[1500];
char msgbuf[MSGBUFSIZE];
//primeiro o cliente irá 'escutar' a rede, para verificar se o servidor está ativo
goto cliente;
//parte onde o cliente irá mandar as informações da's' interface's' de rede
enviando_interfaces:{
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(1);
}
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
addr.sin_port=htons(HELLO_PORT);
//nome do computador, ler o arquivo "/etc/hostname"
FILE *pt;
pt=fopen("/etc/hostname","r");
while(!feof(pt)){
fgets(string,1500,pt);
}
fclose(pt);
strcpy(info,string);
//lista as interfaces de rede e seus ip's
struct ifconf ifc;
char buff[BUFSIZ];
int sock, iface, num;
struct ifreq *ifr=NULL;
sock = socket(AF_INET, SOCK_DGRAM,IPPROTO_IP);
ifc.ifc_len = sizeof(buff);
ifc.ifc_buf = buff;
ioctl(sock, SIOCGIFCONF, &ifc);
ifr = ifc.ifc_req;
num = ifc.ifc_len / sizeof(struct ifreq);
for (iface=0 ; iface<num ; iface++){
if ((ioctl(sock, SIOCGIFADDR, &ifr[iface]) == 0)&&(n!=0)){
strcat(info,ifr[iface].ifr_name);
strcat(info,tab);
if(strcmp(ifr[iface].ifr_name, interface) < 0){
strcat(info,inet_ntoa((*(struct sockaddr_in *)&ifr[iface].ifr_addr).sin_addr));
strcat(info,vir);
strcat(info,tab);
}
}
n++;
}
//codificação das informações da's' interface's'
i=strlen(info);
for(x=0;x<i;x++){
info[x]=info[x]+5237;
}
/* now just sendto() our destination! */
if(sendto(fd,info,sizeof(info),0,(struct sockaddr *) &addr,sizeof(addr)) > 0){
}
//volta a parte do cliente onde os comandos enviados pelo servidor serão execultados
goto cliente;
}
//parte cliente
cliente:{
u_int yes=1;
// create what looks like an ordinary UDP socket
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(1);
}
// allow multiple sockets to use the same PORT number
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
perror("Reusing ADDR failed");
exit(1);
}
// set up destin(ioctl(sock, SIOCGIFADDR, &ifr[iface])ation address
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY); // N.B.: differs from sender
addr.sin_port=htons(HELLO_PORT);
// bind to receive address */
if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("bind");
exit(1);
}
// use setsockopt() to request that the kernel join a multicast group
mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
while (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
}
// now just enter a read-print loop
while (1) {
//ouvindo a porta 12345
addrlen=sizeof(addr);
if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0) {
perror("recvfrom");
exit(1);
}
comp=strcmp(msgbuf,pronto);
//se o servidor se conecta, comparar string enviada por ele
//a string é "pronto_para_conexao" significa que o cliente deve se preparar para enviar as informações da interface
//é uma espécie de convocação, onde o servidor chama os clientes que irão participar do 'controle remoto'
if((conexao==0)||(comp==0)){
puts(msgbuf);
conexao++, n=0;
goto enviando_interfaces;
}
//após o anuncio do servidor querendo se conectar, a comunicação entre o cliente e o servidor é cripografado
if(conexao>0){
//decodificação da mensagem
i=strlen(msgbuf);
for(x=i-1;x>=0;x--){
msgbuf[x]=msgbuf[x]-5237;
}
comp=strcmp(msgbuf,saida);
if(comp==0){
conexao=0, n=0;
}
strcat(msgbuf,bin);
system(msgbuf);
}
}
}
}
9/12/2010 (semana 20)
Wake on lan.
Além do controle de uma rede de computadores seria muito interessante se pudéssemos ligar esses computadores remotamente. Isso é possível desde que a placa de rede suporta Wake on lan.
Esse método consiste em mandar uma espécie de 'pacote mágico' para a placa de rede do computador que queremos ligar. O computador fica desligado mas a placa de rede fica ligada. A placa envia um sinal para a placa mãe que então liga o sistema.
Para baixar o programa que envia o 'pacote mágico' http://packages.debian.org/lenny/etherwake.
Para instalar.
sudo dpkg -i etherwake_1.09-2_i386.deb
#ou o nome do pacote que você baixou
Considerações finais
10/12/2010 (semana 20)
Ao longo desse semestre testamos alguns mecanismos de controle centralizado de uma rede. Não foi uma caminhada fácil, mas, nada que não seja impossível.
O FOG Project
Uma situação que muitas pessoas tentam evitar é ter que instalar um sistema operacional em uma rede de computadores, dependendo do tamanho dessa rede, isso levaria horas ou atés dias. A solução é usar um mecanismo que facilitaria a instalação em larga escala.
Um desses Mecanismos que estudamos foi o FOG Project. Ele envia pela rede um clone de um computador onde os computadores dessa rede irão copiar para os seus HDs. Diferente de outros programas que fazem isso o FOG não exige que os clientes tenham um disquete ou um pen-driver, apenas exige que os as placas de rede dos clientes suportam PXE.
A interação Com o programa é bastante simples, é através de uma interface WEB onde o programa pode ser acessado em qualquer computador da rede.
O cenário de testes
Para funcionar o FOG precisa de um servidor PXE que por sua vez precisa de um DHCP, para trabalhar foi preciso montar uma espécie de laboratório para separar a rede de testes da rede da instituição. Usamos o conceito de VLAN para emular a rede e o Virtual Box para emular os computadores.
Essa preparação do laboratório de testes, por mais que pareça inocente, deu uma pequena dor de cabeça por causa de alguns minúsculos detalhes que estavam impedindo que a rede não funcionasse, mas nada que um bom estudo não resolvesse o problema.
Os testes
Alguns testes foram tranquilos, outros nem tanto, mas nada que não funcionasse.
Tutoriais
Virtualbox
Siga o tutorial na página
http://www.guiadohardware.net/comunidade/tutorial-instalando/988514/
Para o Ubuntu 10.04 http://ubuntued.info/como-instalar-o-virtualbox-no-ubuntu
Depois da instalação do virtualbox e do sistema operacional, vá em configurações, rede, no campo Conectado a selecione a opção Interface do Hospedeiro ou Placa em modo Bridge.
VLAN
Para fazer uma VLAN, no terminal de comandos digite:
sudo apt-get install vlan
Para configurar a VLAN.
sudo gedit /etc/network/interfaces
Adicione as configurações da VLAN, por exemplo:
auto eth0.1
iface eth0.1 inet static
address 10.0.3.2
netmask 255.255.255.0
network 10.0.3.0
vlan_raw_device eth0
Esses comandos irão ativar as configurações da interface eth0.1:
vconfig add eth0 1
/etc/init.d/networking restart
NFS
Para instalar o servidor NFS, vá até o terminal e digite o comando a seguir. Apenas a instalação do NFS no cliente é o suficiente para o FOG operar, mas se você é curioso e quer fazer um servidor NFS próprio aqui tem um simples tutorial.
sudo apt-get install nfs-kernel-server
Agora para compartilhar a pasta ou Hd na rede basta editarmos o arquivo /etc/exports. Para o exemplo, utilizarei a pasta /home no computador 10.0.0.1.
/home *(rw,sync,no_root_squash)
</syntaxhighlight>
Agora vamos iniciar o servidor de NFS .
sudo /etc/init.d/nfs-kernel-server start
Agora é preciso montar a pasta compartilhada no outro computador que está na rede, mas primeiro vamos instalar o cliente nfs e depois criar uma pasta para a montagem.
sudo apt-get install nfs-common
mkdir /home/pasta
Depois.
sudo mount -t nfs 10.0.0.1:/home /home/pasta
Esse comando irá montar a pasta /home do servidor na pasta /home/pasta do cliente.
Tutorial de instalação FOG Project
- Baixar o servidor em http://sourceforge.net/projects/freeghost/files/FOG/
- O Ubuntu onde o servidor FOG será instalado deve ser em inglês.
- Criar o diretório onde será instalado o servidor
sudo mkdir -p /opt/fog-setup
- Descompactar o pacote em /opt/fog-setup
sudo tar -xvzf fog*
- Executar o programa de instalação
cd fog*
cd bin
sudo ./installfog.sh
- Você será solicitado para a distro Linux que você está instalando, digite 2 e aperte enter.
- Você será solicitado para o modo de instalação, N (Normal Server) ou S (Storage Server). Se você não tiver certeza de qual opção de escolher, use N para a instalação normal.
- O instalador irá pedir o endereço IP do servidor, em seguida, pressione enter.
- O instalador irá perguntar se você gostaria de introduzir um endereço de roteador para DHCP, se você gostaria de digite y e pressione enter, digite o endereço e pressione enter.
- O instalador irá perguntar se você gostaria de inserir um endereço DNS e DHCP a imagem de inicialização, se você gostaria de digite y e pressione enter, digite o endereço e pressione enter.
- Você teria então perguntado se gostaria de mudar a interface padrão do eth0, se você gostaria de digite y, pressione enter e adicione a interface (se você estiver inseguro, selecione n).
- Você será solicitado a escolher se deseja instalar os pacotes necessários para a tradução, se você quiser, digite y '.
- Durante a instalação, você pode ser solicitado a definir uma senha de root do MySQL, deixe em branco.
- Depois de concluída a instalação abrir o Firefox novamente e digite a URL: http://localhost/fog/management . Você será solicitado para instalar o esquema do banco. Clique na guia Install/Update Now.
- Quando o esquema é atualizado, tentar ir para a URL: http://localhost/fog/management novamente. Desta vez você deve ser solicitado o login
<bash>
username: fog
password: password
</bash>
- Testando a sua instalação
Agora que está tudo instalado, você precisará de um cliente para testar a sua instalação. No cliente, alterar a ordem de boot para inicializar a partir da rede ou PXE como o primeiro dispositivo de boot. Também pode ser necessário para habilitar a inicialização de rede em algumas BIOS, em seguida, inicializar o computador e você deverá ver o menu de inicialização do nevoeiro que lhe dará algumas opções, selecione o teste de memória.
- Preparação final do servidor
Após o Ubuntu está instalado, precisamos modificar o servidor para permitir Snapin de tamanhos maiores.
sudo gedit /etc/php5/apache2/php.ini
#no arquivo mudar os campos
memory_limit = 1900M
post_max_size=1900M
upload_max_filesize=1900M
sudo /etc/init.d/apache2 restart
Preparando uma imagem
Para preparar uma imagem para a distribuição na rede, no servidor FOG, ir na aba images, no lado esquerdo clicar em New Image, preencher os campos de acordo com a imagem que você deseja.
Agora você precisa de um computador com o sistema operacional que vai ser clonado, mas antes devemos registrá-lo no servidor.
Para registrar.
- modo 1- ir na aba hosts, clicar em Add New Host, preencher os campos de acordo com o computador.
- modo 2- No computador que irá ser clonado, iniciá-lo e configurá-lo para dar o boot pela rede ou habilitar o PXE, depois irá aparecer uma interface de cliente do FOG, ir até Perform Full Host Registration and Inventory, depois de esperar um tempo você preenche os campos de acordo com o computador.
Agora o computador está registrado no servidor, se no processo de registro não ligamos o computador a imagem não podemos iniciar à clonagem.
Para ligar o computador à imagem, ir na aba hosts, clicar em List All Hosts, no lado direito do computador registrado clicar em Edit, no campo host Image selecionar a imagem, no campo host OS selecione o sistema operacional que a imagem irá conter, clicar em update.
Agora vamos iniciar a tarefa, no menu esquerdo clicar em Basic Tasks, clicar em Upload e Upload Image.
Antes da clonagem é aconselhável que exclua o arquivo /etc/udev/rules.d/70-persistent-net.rules
No computador que será clonado, iniciar para dar o boot na rede, após um tempo o processo de clonagem irá começar.
Agora temos uma imagem pronta.
Enviando uma imagem para um único computador (unicast)
Agora precisamos de um outro computador para receber a imagem. Registre esse computador, o processo é igual o processo de registro do computador que foi clonado.
O que vai mudar é no nenu Basic Tasks, clicar em Deploy e Imagem All Computers.
No computador que irá receber a imagem, iniciar para dar o boot na rede, após um tempo o processo de cópia irá começar.
Enviando uma imagem para vários computadores (multicast)
Vamos supor que temos vários computadores regitrados, na aba hosts, clicar em List All Hosts, no lado esquerdo de cada computador regitrado tem um campo onde podemos selecionar o computador, selecione um grupo de dois ou mais computadores, no menu inferior escolhe um nome para o grupo e clique em Process Group Changes.
Na aba tasks no menu esquerdo clicar em List All Groups, no lado do grupo clicar na imagem de uma antena "Deploy(multicast)" e depois clicar em Image All Computers using multicast
O servidor FOG irá disponibilizar uma única imagem, é o mesmo processo do unicast, mas agora possui vários clientes que devem estar alinhados para receber a imagem. O alinhamento indica em quanto tempo todos os computadores do grupo estarão prontos para puxar a imagem. Caso um computador não estiver alinhado, os outros computadores não irão puxar a imagem e ficarão travados. Para fazer o alinhamento é preciso modificar o campo "UDPSENDER_MAXWAIT" do arquivo /opt/fog/service/etc/config.php, esse campo indica o quanto tempo (em segundos) em que todos os computadores que irão puxar a imagem devem estar preparados.
Em uma rede de maior porte, o servidor FOG distribui uma imagem para dez computadores enquanto o restante ficam esperando em uma fila a sua vez.
Agora é só iniciar os computadores para darem o boot na rede.
Segunda Fase do Projeto
16/05/11 (Semana 1)
Estas primeira e segunda semana foi feito um estudo do problema e alguns testes com máquinas virtuais para a compreensão do presente projeto, sendo que na semana posterior houve a problemática(nota de rodapé), observada pelo orientador do projeto, que o que estava sendo proposto para desenvolvimento já havia sido desenvolvido (ref. Sagui).
23/05/11 (Semana 2)
Após uma reunião referente à problemática das semanas inicias ficou então decidido que será desenvolvido um aplicativo para dispositivos móveis com sistema operacional Android para controle remoto de sistemas operacionais de forma centralizada.
Para início foi instalado o SDK (kit de desenvolvimento) Android que contém também um emulador do Sistema Operacional (SO) Android e o plugin “nbandroid 1.7” na IDE Netbeans 7.0 que faz a ligação com o SDK.
Vou mostrar os passos para a instalação do SDK Android e o plugin nbandroid, mas antes é necessário a instalação do JDK (kit de desenvolvimento Java) e o Netbeans 7.0 que podem ser observados nos respectivos links:
http://www.oracle.com/technetwork/java/javase/downloads/index.html
http://netbeans.org/index.html
Instalação do SDK:
- Siga o endereço: http://developer.android.com/index.html.
- Clique em: SDK.
- android-sdk_r11-windows.zip – se você estiver no Windows
- android-sdk_r11-linux_x86.tgz – se você estiver no Linux
- Vá ao local onde você salvou esse arquivo.
- Descompacte na pasta onde está instalado o Netbeans
- Entre na pasta “..\android-sdk-windows\tools” e execute “android.bat”
- Se estiver no linux através da prompt de comando entre na pasta "../android-sdk-linux_x86" e execute "./android"
- Clique em:
- Available packages
- Expanda o “checkbox” “Android Repository”
Obs.: para o estudo de desenvolvimento do presente projeto foi utilizado a API 2.1 então selecione nos “checkboxes”:
> Android SDK Platform-tools, revision 4
> Documentation for Android SDK, API 12, revision 1
> SDK Platform Android 2.1-update, API 7, revision 2
> Selecione todos os que têm a descrição “Sample for SDK ...”
> Android Compatibility package, revision 2
> Install Selected
> Install
> Se aparecer alguma mensagem click em “Ok” e depois feche essa caixa de diálogo. Obs.: não feche a caixa “Android SDK and AVD Manager”
Agora vamos criar uma Máquina Virtual que irá emular um celular com SO Android:
> Clique em:
> Virtual devices
> New
> No campo Name digite um nome qualquer
> No combo box Target selecione “Android 2.1-update1 – API Level 7”
> Selecione o radio button “Size” e digite dentro do campo 512
> Selecione o radio button “Built-in e escolha no respectivo combo box WQVGA432
> Create AVD
Instalação do plugin para o Netbeans:
Siga o endereço: http://kenai.com/projects/nbandroid/
> Em Project Links, clique em:
> Installation
> copie o endereço http://kenai.com/projects/nbandroid/downloads/download/updatecenter/updates.xml
Obs.: Eu peço para entrar nesse local porque esse endereço pode mudar, então por via das dúvidas entre no local especificado e copie o que estiver lá.
> Execute o Netbeans 7.0
> Ferramentas
> Plug-ins
> Configurações
> Adicionar
> No campo URL cole o endereço copiado anteriormente
> No campo Nome digite um nome qualquer – sugestão: Android
> Ok
> Plug-ins disponíveis
> Recarregar catálogo
> Selecione os checkboxes: Android e Android Test Runner for NetBeans 7.0+
> Instalar
> Confirme todas as caixas que aparecerem.
> Agora clique em:
> Ferramentas
> Opções
> Miscelânia
> Android
> Em SDK Location cole o endereço do local que você descompactou o SDK Android, algo do tipo “..\android-sdk-windows”
Instalação do plugin para o Eclipse:
Siga o endereço: http://developer.android.com/index.html
> Clique em:
> SDK
> Procure por ADT Plugin
> procure por algo do tipo https://dl-ssl.google.com/android/eclipse/
> copie o endereço
Obs.: Eu peço para entrar nesse local porque esse endereço pode mudar, então por via das dúvidas entre no local especificado e copie o que estiver lá.
> Execute Eclipse
> Help
> Install new software...
> Add...
> No campo URL cole o endereço copiado anteriormente
> No campo Nome digite um nome qualquer – sugestão: Android
> Ok
> Select all
> Next
> Confirme todas as caixas com ok ou next que aparecerem, caso apareça alguma mensagem, deprese-á
> Agora clique em:
> Window
> Preferences
> Expanda Android
> Browser... Procure o local onde foi descompactado o Android SDK
> Ok
> Pronto agora é só começar a brincadeira
30/05/11 (Semana 3)
Fiz aquisição do livro sobre Android[1]. Aqui pude iniciar os estudos da tecnologia e testei alguns códigos do livro no emulador.
Até estudar as estruturas de códigos do Android que for relevante para o projeto a ser desenvolvido, colocarei aqui os conhecimentos adquiridos no livro.
Agora vou mostrar como criar um projeto e testar no emulador:
- Localize a barra de menu situada no canto superior da janela do Eclipse
- Clique em: File -> New -> Android Project
- Na Caixa de texto Project name digite o nome do projeto que será identificado pelo eclipse.
- No Botão Radio deixe selecionado Create new project in workspace.
Na Lista Build Target selecione a versão do SO Android que será desenvolvido o projeto, no nosso caso é recomendado a utilização da 2.1 API Level 7, pois atualmente a maioria dos SOs Android “rodando” nos celulares brasileiros são 2.1 e alguns 2.2. É importante entender que se você desenvolver um aplicativo para SO Android com API Level superior ao 8, esse aplicativo não funcionará em SOs com Level inferior, porém a recíproca é verdadeira.
- Na Caixa de Texto Application name digite o nome do aplicativo que aparecerá na área de trabalho do SO Android.
- Em Package name digite o nome do pacote que identificará o aplicativo, esse pacote precisa ter no mínimo dois nomes separados por ponto, por exemplo: com.nomeDoPacote.
- Em “Create Activity” digite o nome da janela principal do aplicativo. Por questões de boa prática de programação recomendo que ela tenha o mesmo no digitado em “Application name”
- Em “Min SDK Version” digite o valor da API Level, no nosso caso 7
- Clique em: finish
Obs.: Não vou mostrar com detalhes de como usar o Eclipse, pois esse não é o objetivo aqui, mas vou colocar, por exemplo: clique no botão run. Aqui subintende-se que se tenha conhecimentos nessa IDE e que esse comando solicitado seja óbvio.
- Localize o bloco Package Explorer
- Clique em:
- expanda o projeto, caso ele esteja recolhido
- expanda src
- expanda o pacote
- duplo clique no nome do projeto
- botão run do eclipse
O emulador demorará alguns minutos para inicializar, pois ele simulará o hardware do celular e mais o carregamento do SO Android. Após isso será possível ver na tela a palavra Hello World, nomeDoProjeto.
Legal né? Mas como que isso aconteceu sendo que no código Principal, onde tem o nome do aplicativo não existe nenhum comando para imprimir na tela essa String? Na verdade essa string está em um arquivo XML localizado na pasta res/values do projeto e nele pode-se criar variáveis estáticas para serem chamadas na classe principal. O arquivo que define quem vai ser a classe principal é o AndroidManifest.xml localizado na raiz do projeto. Agora olhando para a classe principal perceba que a classe que foi criada para esse teste é filha da classe Activity, que é responsável por fazer o controle dos estados e os eventos da tela. Nela, obrigatoriamente, o método onCreate precisa ser implementado e ele é chamado pelo SO quando a tela for criada. Mas perceba um detalhe, apesar dessa classe fazer o controle de tela, ela não projeta formas na tela, para isso é necessário chamar o método setContentView e passar como argumento o arquivo main.xml. O arquivo main.xml é utilizado para criar, desenhar os componentes de tela. Mas veja que o main.xml, poderia ser abobrinha.xml, só que nele tem que estar contido todas essas informações de criação de tela e depois ser passado com argumento no método setContentView falado anteriormente. Veja que no nosso caso, foi criado uma tag <string> com referência hello e ela é chamada no m main.xml através da tag <TextView> com atributo @string/hello. Recomendo dar uma lida sobre TextView.
06/06/11 (Semana 4)
Essa semana dei continuação aos estudos da classe Activity além da classe Intent.
Desenvolvi também um código exemplo para mostrar o principal uso dessas classes que é pedir ao SO Android a intenção de executar um programa, sendo ela a classe Intent que é responsável por fazer essa interação e a classe Activity que como foi falado anteriormente é responsável por fazer o controle dos estados e os eventos da tela.
Nesse exemplo o programa a seguir é uma tela com dois campos para digitar valores inteiros, ele então soma e envia esse resultado para uma outra. O exemplo é bem simples, pois aqui eu não previ nenhuma condição para caso seja inserido um caractere, então por favor insira somente valores inteiros! :)
Apesar da simplicidade nessa etapa dos estudos, dificuldades na compreensão dessas classes foram encontradas e muitos "bugs" no desenvolvimento do programa apareceram, por isso de uma semana inteira para fazê-lo.
Esse código deve ser colocado na pasta layout do projeto. Ele é responsável por desenhar os elementos na tela. Dê o nome de meu_layout.xml.
<?xml version="1.0" encoding="utf-8"?>
<!--
/**
*
* Exemplo Activity e Intent
*
*
*
* @author Sant'Clear Ali Costa
* Graduando de Sistemas de Telecomunicações
* IFSC - Campus São José (antiga Escola Técnica Federal - CEFET)
*
*
*/
-->
<!-- wrap_content -> ocupa apenas o tamho necessário
fill_parent -> ocupa todo o espaço definido pelo layout pai-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- ************************************ -->
<!-- Exibe um label -->
<TextView
android:id="@+id/lbNumero1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Número 1"
/>
<!-- Entrada de dados -->
<EditText
android:id="@+id/tfNumero1"
android:numeric="integer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<!-- ************************************ -->
<!-- ************************************ -->
<TextView
android:id="@+id/lbNumero2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Número 2"
/>
<EditText
android:id="@+id/tfNumero2"
android:numeric="integer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<!-- ************************************ -->
<!-- Botão -->
<Button
android:id="@+id/btCalcular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" Calcular "
/>
</LinearLayout>
Esse código deve ser colocado na pasta src do projeto dentro do pacote principal. Essa é a tela principal que calculará e pedirá ao SO Android a intenção de execução do processo da outra tela que será mostrada a seguir. Dê o nome de Calcula.java.
package bolsa.Telas;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
/**
*
* Exemplo Activity e Intent
*
*
*
* @author Sant'Clear Ali Costa
* Graduando de Sistemas de Telecomunicações
* IFSC - Campus São José (antiga Escola Técnica Federal - CEFET)
*
*
*/
public class Calcula extends Activity implements OnClickListener {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.meu_layout);
Button btCalcular = (Button) findViewById(R.id.btCalcular);
btCalcular.setOnClickListener(this);
}
public void onClick(View v) {
Intent itRes = new Intent(this, Resultado.class);
EditText tfNumero1 = (EditText) findViewById(R.id.tfNumero1);
EditText tfNumero2 = (EditText) findViewById(R.id.tfNumero2);
int numero1 = Integer.valueOf(tfNumero1.getText().toString());
int numero2 = Integer.valueOf(tfNumero2.getText().toString());
int resultado = numero1 + numero2;
itRes.putExtra("res", String.valueOf(resultado));
startActivity(itRes);
}
}
Esse código deve ser colocado na pasta src do projeto dentro do pacote principal. Essa é a tela que receberá a informação de resultado do cálculo feito na tela anterior. Dê o nome de Resultado.java.
package bolsa.Telas;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
/**
*
* Exemplo de Activity e Intent
*
*
*
* @author Sant'Clear Ali Costa
* Graduando de Sistemas de Telecomunicações
* IFSC - Campus São José (antiga Escola Técnica Federal - CEFET)
*
*
*/
public class Resultado extends Activity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Intent itRes = getIntent();
String res = itRes.getStringExtra("res");
TextView view = new TextView(this);
view.setText("Resultado = " + res);
setContentView(view);
}
}
Esse é o fluxo de interação de uma Activity com "Intenção(Intent)" de executar a próxima tela:
<graphviz>
digraph Código
{
"meu_layout.xml" [shape=Mrecord]
"Calcula.java" [shape=Mrecord]
"Resultado.java" [shape=Mrecord]
"meu_layout.xml" -> "Calcula.java" [label="função setContentView"]
"Calcula.java" -> "Resultado.java" [label="objeto de intenção itRes"]
}
</graphviz>
27/06/2011 (semana 7)
A Intent é uma das classes mais importantes contidas no Android SDK, pois tudo que é executado no SO Android tem por trás uma Intent (Intenção de executar algum programa), sendo ela a responsável por enviar mensagens ao SO Android de solicitação de que algo seja executado. Por esse motivo vou colocar aqui mais um exemplo, pois o entendimento dessa classe é essencial para o desenvolvimento de aplicativos para o SO Android.
No exemplo a seguir vou mostrar um programa que envia uma mensagem de uma Activity para outra e essa última, ao final de sua execução, retorna um resultado para a Activity que a chamou.
Como no programa mostrado anteriormente eu não detalhei melhor o passo a passo, com fotos, de como criar o projeto, vou colocar no tópico dessa semana.
- Vamos começar executando o Eclipse:
- Antes certifique-se que a localização do SDK, mostrado nas linhas finais da semana 2, está configurada, clicando no menu:
- Agora criaremos o projeto clicando no botão como mostrado nas figuras
- Expanda a pasta do projeto “meuActivityIntent”
- Crie um arquivo .xml da tela principal como mostrado na figura
- Cole esse código:
<?xml version="1.0" encoding="utf-8"?>
<!-- wrap_content -> ocupa apenas o tamho necessário
fill_parent -> ocupa todo o espaço definido pelo layout pai-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/lbListaFuncionarios"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="LISTA DE FUNCIONÁRIOS"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=" "
/>
<TextView
android:id="@+id/lbFuncionario"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
/>
<Button
android:id="@+id/btCadastrar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cadastrar"
/>
</LinearLayout>
- Salve esse arquivo com CTRL + S do teclado
- Repita o mesmo procedimento criando um outro arquivo .xml, porém com o nome cadastro_layout.xml
- E cole esse código:
<?xml version="1.0" encoding="utf-8"?>
<!-- wrap_content -> ocupa apenas o tamho necessário
fill_parent -> ocupa todo o espaço definido pelo layout pai-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="CADASTRO DE FUNCIONÁRIOS"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=" "
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Nome:"
/>
<EditText
android:id="@+id/tfNome"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Setor:"
/>
<EditText
android:id="@+id/tfSetor"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/btEnviar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" Enviar "
/>
</LinearLayout>
- Agora crie uma classe como mostrado nas figuras
package bolsa.meuActivityIntent;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
/**
*
* Exemplo de Activity e Intent com Retorno de Resultado
*
* @author Sant'Clear Ali Costa Graduando de Sistemas de Telecomunicações IFSC -
* Campus São José (antiga Escola Técnica Federal - CEFET)
*
*/
public class Cadastro extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cadastro_layout);
Button btEnviar = (Button) findViewById(R.id.btEnviar);
btEnviar.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent it = new Intent();
EditText tfNome = (EditText) findViewById(R.id.tfNome);
EditText tfSetor = (EditText) findViewById(R.id.tfSetor);
String formulario = "Nome: "+ tfNome.getText().toString() +"\n"+"Setor: "+ tfSetor.getText().toString() +"\n\n";
it.putExtra("formCadastro", formulario);
// Seta o status do resultado e a Intent
setResult(1, it);
// Fim desta activity
finish();
}
});
}
}
- Salve esse arquivo com CTRL + S do teclado
- Apague todas a linhas de código do arquivo Lista.java e cole o código a seguir
package bolsa.meuActivityIntent;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
/**
*
* Exemplo de Activity e Intent com Retorno de Resultado
*
* @author Sant'Clear Ali Costa Graduando de Sistemas de Telecomunicações IFSC -
* Campus São José (antiga Escola Técnica Federal - CEFET)
*
*/
public class Lista extends Activity implements OnClickListener {
// Para identificar a chamada no método onActivityResult
private static final int ACTIVITY_CADASTRO = 1;
private String formulario = "";
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Utilize o modelo de layout lista_layout
setContentView(R.layout.lista_layout);
TextView semFuncionario = (TextView) findViewById(R.id.lbFuncionario);
if (formulario == "")
semFuncionario.setText("NÃO EXISTE FUNCIONÁRIO CADASTRO NO MOMENTO\n");
// Instanciado o botão btCadastrar contido no lista_layout
Button btCadastrar = (Button) findViewById(R.id.btCadastrar);
// Aguarda o botão ser clicado
btCadastrar.setOnClickListener(this);
}
// Quando o botão for pressionando entre neste método
public void onClick(View v) {
// Cria uma Intenção de iniciar uma Atividade de Cadastro
Intent it = new Intent(this, Cadastro.class);
/*
*
* Manifesta essa Intenção ao SO Android
* Se nesse momento houver memória disponível,
* se não houver Atividades prioritárias sendo executadas,
* etc, então a Atividade Cadastro é iniciada
*
*/
startActivityForResult(it, ACTIVITY_CADASTRO);
}
@Override
protected void onActivityResult(int codigo, int resultado, Intent it) {
// Instanciado o label lbFuncionario contido no lista_layout
TextView lbFuncionario = (TextView) findViewById(R.id.lbFuncionario);
if (codigo == ACTIVITY_CADASTRO) {
// Se a Atividade Cadastro não retornar nenhum valor
if (it != null) {
/*
*
* Armazena no formulario o formCadastro passado na finalização
* da Atividade Cadastro
*
*/
formulario += it.getStringExtra("formCadastro");
/*
*
* Verifica o status do resultado da Atividade Cadastro
* Por exemplo, se houver varios botoes, cada botão terá que ter um
* código de resultado diferente para poder identificá-lo
* Como na Atividade cadastro não existe outros eventos além do onClick,
* estão nem precisaria desses ifs. Apenas deixei aqui, como
* exemplo, caso se queira criar outros eventos no Cadastro para
* ter outros resultados de identificação
*
*/
if (resultado == 1) {
lbFuncionario.setText(formulario);
} else if (resultado == 2) {
// Algum código aqui
} else {
// Algum código aqui
}
}
/*
* Quando se quer coletar o valor de retorno de uma Atividade ela
* deve ter um código de identificação. No nosse exemplo temos apenas
* uma atividade: Cadastro, então não precisaria aqui também estes
* ifs, porém coloquei aqui, como exemplo, caso se queira criar
* outras Atividades
*/
} else if (codigo == 2) {
// Algum código aqui
} else {
// Algum código aqui
}
}
}
- Salve esse arquivo com CTRL + S do teclado
- Uma coisa importante que esqueci de mencionar no código da outra semana é que não pode nunca esquecer de incluir no arquivo AndroidManifest.xml toda classe que é criada, pois como falado na semana 3 ele é o arquivo que define quem vai ser a classe principal, além de conter todas as classes que serão carregadas quando o programa for executado. Se esse arquivo não estiver configurado, e você quiser chamar uma Activity que não está configurada nesse arquivo, o SO Android irá diparar uma exceção.
- Para configurar faça como mostrado nas figuras
09/08/2011 (semana 14)
Desde a volta das férias de julho comecei a fase de projetar o software. Essa semana, mais especificamente, descrevi, baseado em orientações, o caso de uso do software da fase inicial do projeto:
Usuário digita endereço remoto de um PC para estabelecer uma conexão fim-a-fim com ele. Após a conexão é possível digitar comandos de arquivos executáveis definidos na variável de ambiente (PATH), para administração remota de sistema operacional. O software aprende, com auxílio de um arquivo de histórico, os comando mais usados com suas respectivas flags de opção, oferecendo em uma lista os 10 mais usados para facilitar a digitação.
Pesquisei, também, uma classe Java que auxiliasse a comunicação com o SO GNU/Linux, para que através de um programa Java se possa executar, por exemplo, algum comando do Bash, e esse foi o código que desenvolvi:
import java.io.*;
import java.util.Scanner;
/**
*
* Exemplo de execução de comando Bash
*
* @author Sant'Clear Ali Costa Graduando de Sistemas de Telecomunicações IFSC -
* Campus São José (antiga Escola Técnica Federal - CEFET)
*
*/
class Execbash {
public static void main(String[] args) {
// String que contém o comando GNU/Linux
// String cmd = "ls -l /home/santclear/\"Eclipse Indigo\" | grep '^-..x' | awk '{print $8;}'";
String cmd = "echo $PATH";
// Primeiro parâmetro passado ao construtor para criar o processo bash
// Segundo parâmetro passado ao construtor é a flag de opção -c para que os comandos seja lidos como string
// Terceiro parâmetro passado ao construtor é um comando válido do processo bash
ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd);
/* Qualquer saída de erro gerada por subprocessos posteriormente iniciados pelo método start() deste objeto
* será fundida com a saída padrão, de modo que ambos podem ser lidos usando o método Process.getInputStream().
* Isto torna mais fácil para correlacionar mensagens de erro com a saída correspondente*/
pb.redirectErrorStream(true);
try {
// O método start() inicia um novo processo com os parâmentros passados para o construtor do objeto pb
Process p = pb.start();
/* O método getInputStream() Retorna o fluxo de entrada ligada à saída normal do subprocesso.
* O fluxo obtém dados canalizado a partir da saída padrão do processo representado por este objeto de processo*/
InputStream input = p.getInputStream();
Scanner sc = new Scanner(input);
while(sc.hasNext()){
System.out.println(sc.next());
}
input.close();
} catch (Exception e) {
System.out.println("Exception--->" + e.getMessage());
}
}
}
Referências Bibliográficas
- ↑ LECHETA, R. R. Google Android – Aprenda a criar aplicações para dispositivos móveis com o Android SDK. 2a ed. 2010. ISBN 978-85-7522-244-7.