// Rodolfo Fadino

/* LIFE RUNS ON CODE */

Archive for the ‘Server’ Category

A Amazon Web Service  oferece diversos produtos e soluções em cloud computing, atualmente ela forneçe uma das mais completas gama de produtos e soluções do mercado de cloud. Uma dessas soluções é o Amazon Simple Storage Service (Amazon S3), que consiste em uma plataforma de armazenamento, onde é possível criar diversos containers e gerenciar arquivos, permissões, etc.

Durante esta semana estava estudando alguns serviços para um backup off-site, entre todos eles eu optei por utilizar o S3, a partir desta escolha comecei a estudar com quais ferramentas eu poderia automatizar a tranferência entre meus servidores e o armazenamento na S3. No mercado exitem diversas ferramentas para isso, entre elas optei por utilizar o SDK da Amazon e PowerShell, no qual eu consegui escrever a rotina que eu precisava e configurar esse script como uma tarefa agendada do windows server.

Começando

Para começar vamos precisar fazer donwload do SDK da Amazon para .NET, eu poderia ter feito um programa com C# utilizando o SDK da Amazon, mas como a idéia é utilizar e aprender a usar PowerShell, utilizei ele para escrever um script que copia todos os arquivos de um diretorio para a S3.

Inicialmente eu utilizei um método de upload ( .Upload ) do SDK que funcionava bem para arquivos pequenos, entretanto, como a idéia era fazer backup de grandes arquivos (+de 1G) eu precisei utilizar uma feature da API da Amazon chamada Multipart Upload (Using the AWS SDK for .NET for Multipart Upload) nela, eu particiono o arquivo, faço upload de todas as partes, e, no final do upload eu utilizo um comando que une todas as partes, criando a versão final do arquivo.

Para iniciar o script vou incluir a dll do SDK da Amazon:

Add-Type -Path "C:\Program Files (x86)\AWS SDK for .NET\bin\AWSSDK.dll"

Como segundo passo do meu script adicionarei as variáveis de acesso da API (com um usuário que eu criei e gerei a chave de acesso) e também criarei a variável com o Bucket que eu criei na S3

$secretKeyID="colocar secret key"
$secretAccessKeyID="colocar access key"
$bucket="NomeDoBucket"

O proximo passo do script é definir qual diretório eu farei o backup (“C:\teste”) e qual será o nome do diretório final no Bucket da S3 (“Backup_yyyy_mm_dd”):

$backup_directory="C:\teste"
$new_folder_format = Get-Date -uformat "Backup_%Y_%m_%d/"

Agora eu criarei um laço entre todos os arquivos do diretório, dentro desse laço nos faremos todo o trabalho de upload dos arquivos:

foreach($file in Get-ChildItem -Path $backup_directory){

#script de upload

}
Write-Host "Backup Finalizado"

Dentro desse laço, para cada arquivo eu farei o seguinte:

Escrever o nome do arquivo e instanciar o Cliente de acesso para a AWS

Write-Host $file.fullname
$client=[Amazon.AWSClientFactory]::CreateAmazonS3Client($secretKeyID,$secretAccessKeyID)

Em um segundo passo eu defino os nomes do arquivo final e o nome do arquivo fisico para fazer o upload.

$finalName=$new_folder_format+$file.name
$fileFullPath=$file.fullname

Também instancio um List de UploadPartResponse e uma instancia do InitiateMultipartUploadRequest para iniciarmos o upload.

$uploadResponses = New-Object "System.Collections.Generic.List[Amazon.S3.Model.UploadPartResponse]"

$initRequest=New-Object "Amazon.S3.Model.InitiateMultipartUploadRequest"
[void] $initRequest.WithBucketName($bucket)
[void] $initRequest.WithKey($finalName)

Com isso já podemos iniciar o MultipartUpload com o $client passando o $initRequest, tambem instancio algumas variaveis de controle, que utilizaremos para fazer upload de 5Mb por parte do arquivo.

$initResponse =$client.InitiateMultipartUpload($initRequest)

$fileInfo = New-Object -TypeName System.IO.FileInfo $arquivoFisico
$lengh= $fileInfo.Length
$partSize= 5242880

$filePosition =New-Object "Long"
$filePosition = 0

Com essas variaveis eu faço um loop entre as partes do arquivo para fazer upload de cada 5Mb

for ( $partNumber = 1; $filePosition -le $lengh;  $partNumber++)
{
	$uploadRequest = New-Object "Amazon.S3.Model.UploadPartRequest"
	[void] $uploadRequest.WithBucketName($bucket)
	[void] $uploadRequest.WithKey($finalName)
	[void] $uploadRequest.WithUploadId($initResponse.UploadId)
	[void] $uploadRequest.WithPartNumber($partNumber)
	[void] $uploadRequest.WithPartSize($partSize)
	[void] $uploadRequest.WithFilePosition($filePosition)
	[void] $uploadRequest.WithFilePath($fileFullPath)

	$uploadResponses.Add($client.UploadPart($uploadRequest))
	$filePosition += $partSize
	Write-Host $partNumber
}

Finalmente podemos juntar todas as partes do upload, para isso utilizamos o seguinte comando:

$compRequest = New-Object "Amazon.S3.Model.CompleteMultipartUploadRequest"
[void] $compRequest.WithBucketName($bucket)
[void] $compRequest.WithKey($finalName)
[void] $compRequest.WithUploadId($initResponse.UploadId)
[void] $compRequest.WithPartETags($uploadResponses)

$completeUploadResponse =$client.CompleteMultipartUpload($compRequest)

Por ultimo precisamos fechar o laço que fizemos entre cada arquivo do diretorio e escrevo uma mensagem de finalizado, com isso o script ficou da seguinte maneira:

Add-Type -Path "C:\Program Files (x86)\AWS SDK for .NET\bin\AWSSDK.dll"

$secretKeyID="secret key"
$secretAccessKeyID="access key"
$bucket="BucketName"

$backup_directory="C:\teste"
$new_folder_format = Get-Date -uformat "Backup_%Y_%m_%d/"

foreach($file in Get-ChildItem -Path $backup_directory){
	Write-Host $file.fullname
	$client=[Amazon.AWSClientFactory]::CreateAmazonS3Client($secretKeyID,$secretAccessKeyID)

	$finalName=$new_folder_format+$file.name
	$fileFullPath=$file.fullname

	$uploadResponses = New-Object "System.Collections.Generic.List[Amazon.S3.Model.UploadPartResponse]"

	$initRequest=New-Object "Amazon.S3.Model.InitiateMultipartUploadRequest"
	[void] $initRequest.WithBucketName($bucket)
	[void] $initRequest.WithKey($finalName)

	$initResponse =$client.InitiateMultipartUpload($initRequest)

	$fileInfo = New-Object -TypeName System.IO.FileInfo $fileFullPath
	$lengh= $fileInfo.Length
	$partSize= 5242880

	$filePosition =New-Object "Long"
	$filePosition = 0

	for ( $partNumber = 1; $filePosition -le $lengh;  $partNumber++)
	{
		$uploadRequest = New-Object "Amazon.S3.Model.UploadPartRequest"
		[void] $uploadRequest.WithBucketName($bucket)
		[void] $uploadRequest.WithKey($finalName)
		[void] $uploadRequest.WithUploadId($initResponse.UploadId)
		[void] $uploadRequest.WithPartNumber($partNumber)
		[void] $uploadRequest.WithPartSize($partSize)
		[void] $uploadRequest.WithFilePosition($filePosition)
		[void] $uploadRequest.WithFilePath($fileFullPath)

		$uploadResponses.Add($client.UploadPart($uploadRequest))
		$filePosition += $partSize
		Write-Host $partNumber
	}

	$compRequest = New-Object "Amazon.S3.Model.CompleteMultipartUploadRequest"
	[void] $compRequest.WithBucketName($bucket)
	[void] $compRequest.WithKey($finalName)
	[void] $compRequest.WithUploadId($initResponse.UploadId)
	[void] $compRequest.WithPartETags($uploadResponses)

	$completeUploadResponse =$client.CompleteMultipartUpload($compRequest)
}
Write-Host "Backup Finalizado"

O  script também pode ser encontrado no meu GitHub: https://gist.github.com/2691325

Para executar o script eu criei uma tarefa agendada, para isso eu coloquei o seguinte comando:

Caso o script apresente erro de segurança ao executar, é necessário habilitar a execução de scripts na maquina, abra um prompt do PowerShell e utilize o seguinte comando:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

Espero que este post seja útil,

estou a disposição para dúvidas, críticas e sugestões.

abs

Rodolfo

C# , dev , Server

A plataforma de virtualização oferecida pela Microsoft com o Hyper-V oferece diversos recursos, entre eles posso citar o dynamic memory, live migration, snapshots, etc. Ele pode ser utilizado como uma role do Windows Server 2008, ou então em um SO especifico chamado Microsoft Windows Hyper-V Server que é um sistema operacional  independente, que contém apenas o Windows Hypervisor, o modelo de driver do Windows Server e os componentes de virtualização, entre suas principais vantagens está o pouco consumo de recursos.

Uma possibilidade bastantemente útil para alguns cenários de virtualização é a de conectar um disco físico diretamente a uma máquina virtual, sem criar um VHD ou precisar transformar qualquer coisa no disco. Alem disso, caso seja utiliza um driver SCSI essa conexao poderá ser feita com a maquina virtual ligada (no caso do disco já estar conectado a máquina host).

Neste exemplo eu vou conectar um HD Sata que está conectado na máquina host que está com o Hyper-V Server (sistema operacional), como este SO não tem algumas interfaces para gerenciamento eu vou gerenciar ele através do Remote Server Administration Tools for Windows 7.

Começando:

Primeiro vou abrir o console de Gerenciamento do Computador e conectar na máquina Host (Hyper-V Server)

 

 

Para isso eu precisarei escolher o IP ou algum nome consiga chegar ao servidor que queremos gerenciar.

 

 

O próximo passo é identificar o disco que utilizaremos para conectar na máquina virtual, para poder atacha-lo na VM precisaremos deixar ele Offline.

Com o disco offline podemos abrir o gerenciado do Hyper-V e podemos abrir as configurações da máquina virtual que queremos adicionar o disco físico.

Nesta caso vamos adicionar uma unidade SCSI (caso a Vm estivesse desligada eu poderia adicionar um driver IDE, ou de outro tipo)

Após adicionar o controlador SCSI precisaremos selecionar que ele será um disco físico e escolher o disco que deixamos offline.

Após salvar e fechar esas configurações podemos conectar na VM e ir no gerenciamento de disco, nele poderemos visualizar o nosso disco, incialmente ele estará offline, basta clicarmos com o botão direito e selecionarmos a opção online:

 

Após isto o disco já estará acessivel no Windows Explorer da nossa máquina virtual.

 

Espero que este post seja útil :)

estou a disposição para dúvidas, dicas, críticas ou sugestões

abs

Rodolfo

 

Server

Uma das principais dificuldades na comunicação entre a maquina host e as maquinas virtuais acontece quando a maquina host está sem nenhuma interface de rede conectada, ou seja, não possui ip, não conseguindo se comunicar a nivel de rede com as maquinas virtuais.
Para resolver este problema é possivel instalar o Loopback Adapter, que funcionará como uma interface de rede (conectada) na maquina host

Espero que este video seja útil

Rodolfo

Server