venerdì 19 dicembre 2014

Edit dei file di codice sorgente da Web con Visual Studio Online

Brian Harry, sul suo blog, ha annunciato il nuovo rilascio di Visual Studio Online; rilascio che comprende anche l'attesa funzionalità di editing del codice direttamente dal portale web.
Vediamo come funziona.
 
 
Edit
Dopo essere entrati sulla Dashboard del Team Project che vogliamo gestire, andiamo sulla sezione "Code" e selezioniamo dal menù ad albero di sinistra uno dei file di codice sorgente.
 
Sulla destra si aprirà, come al solito, la schermata in sola lettura che contiene il codice. A differenza di quanto succedeva precedentemente, però, è disponibile un nuovo bottone "Edit".
 
 
Cliccando sul bottone, succederanno tre cose:
  1. La toolbar cambierà visualizzazione
  2. Nel menu ad albero il file selezionato verrà "marcato" con un * ad indicare che è in modifica
  3. Nella schermata sarà possibile apportare modifiche al codice sorgente
 
 
Una volta completata la modifica, è possibile (consigliato, a dire il vero...) inserire un commento nella textbox che verrà associato al checkin e premere sul pulsante di salvataggio (comparso nella toolbar).
 
Cliccato su "Save", la modifiche vengono salvate sul source control, viene creato un changeset e viene visualizzato un tooltip che ci informa dell'esito positivo dell'operazione, con un link alla visualizzazione del changeset stesso.
 
 
È anche possibile annullare le modifiche utilizzando il bottone "Discard", sempre nella toolbar.
Infine, se prima di fare il checkin vogliamo verificare le modifiche apportate, è possibile fare una diff tra il file residente sul source control e la nostra versione, utilizzando il pulsante all'estrema destra della toolbar.
 
 
  
Upload, Create, Rename, Delete
Oltre a modificare direttamente i sorgenti, è possibile anche rinominare, cancellare e creare file e cartelle e fare l'upload di nuovi file.
 
 
Per creare un nuovo file o farne l'upload basta cliccare con il tasto destro su una cartella e scegliere "Add file(s)".
Si aprirà un popup in cui si può scegliere se creare un file nuovo o se scegliere dei file già esistenti da caricare.
 
 
Viceversa, per cancellare un file cliccarci sopra con il tasto destro e scegliere "Delete" (viene chiesta conferma).
 
Per rinominarlo, infine, sempre dal menù contestuale che appare con il tasto destro scegliere "Rename".
 
Tutte queste operazioni genereranno un changeset, quindi le modifiche saranno mappate e storicizzate sul source control.

mercoledì 12 novembre 2014

Aggiungere Azure Application Insights ad un Web Site

Sviluppando una Web Application, è possibile usare Visual Studio 2013.3 per aggiungere automaticamente tutte le librerie e le configurazioni di cui "Azure Application Insights" ha bisogno pre funzionare.
 
Ma invece per quanto riguarda i Web Sites? Se si crea un Web Site (oppure si vuole modificarne o gestirne uno già esistente) l'opzione per aggiungere l'Application Insights non è presente. Cosa possiamo fare, quindi? Com'è possibile raggiungere lo stesso risultato? Come possiamo integrare Azure Application Insights in un Web Site?
 
È possibile! Basta seguire questi step:
  1. Creare un nuovo servizio "Application Insights" usando il nuovo Azure portal (preview)
  2. Copiare lo snippet di codice JavaScript che viene proposto dal portale ed aggiungerlo a tutte le pagine che si vogliono monitorare (oppure alla master page, se ce n'è una)
  3. In Visual Studio 2013.3, creare una nuova web application vuota ed aggiungere ad essa Application Insights usando il menu contestuale
  4. Copiare i seguenti file dalla cartella "bin" della Web App alla cartella "bin" del Web Site:
    Microsoft.ApplicationInsights.dll
    Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry.dll
    Microsoft.ApplicationInsights.Extensibility.Web.dll
    Microsoft.Diagnostics.Tracing.EventSource.dll
    (volendo è possibile anche copiare i relativi file .xml e .pdb)
    
  5. Tornare nell'Azure portal (preview), andare nella sezione dell'Application Insights creato precedentemente, cliccare sul bottone "Properties" e copiare il valore della texbox "Instrumentation Key"
  6. Copiare il file ApplicationInsights.config dalla root della Web App alla root folder del Web Site
  7. In questo file, sostituire il valore della chiave "InstrumentationKey" con quello copiato al punto 5
  8.  Cambiare il file web.config del website aggiungendo le seguenti righe:
    <system.web>
     [...]
        <httpModules>
       [...]
          <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule, Microsoft.ApplicationInsights.Extensibility.Web" />
       [...]
        </httpModules>
     [...]
    </system.web>
    
    <system.webServer>
     [...]
        <validation validateIntegratedModeConfiguration="false" />
     [...]
     <modules runAllManagedModulesForAllRequests="true">
       [...]
          <remove name="ApplicationInsightsWebTracking" />
          <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Extensibility.Web.RequestTracking.WebRequestTrackingModule, Microsoft.ApplicationInsights.Extensibility.Web" preCondition="managedHandler" />
       [...]
        </modules> 
     [...]
    </system.webServer> 
    
 
A questo punto è possibile avviare e testare il Web Site e, dopo qualche secondo, i dati e le statistiche saranno presenti nella blade dell'Application Insights (sempre sul nuovo Azure portal)

martedì 11 novembre 2014

Gestire i Cloud Load Test con le REST API

Le REST API dei Cloud-based Load Testing (CLT) permettono di automatizzare l'esecuzione dei Load test dal Cloud, in modo da poterli integrare nei processi di Continuous Integration / Deployment e di Test Automation.

Ecco una lista (sicuramente in espansione) di quello che si può fare con queste nuove API:
  • Creare / Lanciare / Stoppare un Load Test Run
  • Recuperare i Load Test Results - un set di gruppi di  KPI - Performance, Throughput, Application
  • Recuperare i Messages del servizio durante l'esecuzione
  • Recuperare le Exceptions, se ci sono
  • Recuperare le Counter instances di un  Load Test run
  • Recuperare gli Application Counters delle App configurate nel load test
  • Recuperare una lista di tutti i Load test Runs eseguiti - con filtri per requester, date, status ecc..
Queste API lavorano in stretta vicinanza con le Azure API, visto che si leggono i test file da un Azure Blob e salvano i risultati nella stessa drop folder sempre sull'Azure Blob.

È importante notare che:
  • Per usare le REST API, è necessario abilitare le alternate credentials su Visual Studio Online e quindi utilizzarle per l'autenticazione
  • Aggiungere"vsclt" al nome dell'account VSO per essere rediretti al "Cloud-based Load Test (CLT) service" di visualstudio.com. Ade sempio, se l'account è https://abc.visualstudio.com/, quando si utilizzano le API indicare https://abc.vsclt.visualstudio.com/
 
Il pattern di base per le  API è il seguente:
VERB    https://{account}.vsclt.visualstudio.com/_apis/clt/{resource}[/{options}]
 
Dove "resource" può essere una delle seguenti e le "options" dipendono dalla resource:
 
Test
  • Per i "Test Runs": testruns
  • Per le "Test Drops" (i container dove vengono salvati i dati): testdrops
 
Dipendenti dai Test Run
  • Per le "Counter Instances": testruns/{testrunid}/counterinstances
  • Per i "Counter Samples": testruns/{testrunid}/countersamples
 
Application Performance Management:
  • Per i "APM Plugins": apm/plugins
  • Per le "APM Applications ": apm/applications
  • Per i "APM Counters ": apm/counters

Creare un Test Run
Per creare un Cloud Load Test Run, è necessario fare una chiamata POST alle API, passando nel body un set di parametri e test settings come in questo esempio.

Request Url:
POST    https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns

Request Body:
{
  "name": "MyAppToTest.loadtest",
  "description": "nightly loadtest",
  "testSettings": {
    "cleanupCommand": "",
    "hostProcessPlatform": "x86",
    "setupCommand": ""
  },
  "testDrop": {
    "id": "fe35ed32-eaab-4178-ba7e-ad2577ee187f"
  }
}


Response:
{
  "id": "a5e0d4b9-d387-4b3e-9566-163da9c39b67",
  "name": "MyAppToTest.loadtest",
  "createdDate": "2014-11-1T08:51:27.0965365Z",
  "state": "pending",
  "subState": "none",
  "testSettings": {
    "cleanupCommand": "",
    "hostProcessPlatform": "x86",
    "setupCommand": ""
  },
  "testDrop": {
    "id": "fe35ed32-eaab-4178-ba7e-ad2577ee187f",
    "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/TestDrops/fe35ed32-eaab-4178-ba7e-ad2577ee187f"
  },
  "runSpecificDetails": {
    "duration": 180,
    "virtualUserCount": 250,
    "samplingInterval": 15
  },
  "createdBy": {
    "id": "76cabfe4-0e20-4f5b-862e-9693a68232f1",
    "displayName": "iamtheuser@dbtek.it"
  },
  "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67"
}


Come si può vedere, nella response si trovano tutti i dati che possono servire relativi al test run appena creato.

Avviare un Test Run
Con questi dati possiamo per esempio avviare (o meglio accodare) il test run, chiamando le API usando un verb PATCH:

Request Url:
PATCH    https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67

Request Body:
{
  "state": "queued"
}


Response:
Status code: 202


Recuperare i Test results
Infine, quando il test è finito, possiamo recuperare i risultati con una call in GET.

Request Url:
GET    https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67/results

Response:
{
  "resultsUrl": "http://127.0.0.1:10000/devstoreaccount1/ets-containerfor-aeee0697-d734-43d7-956e-e662252c265c/2150fbd4-e71c-42fd-8b90-95222a556d87/TestResult/LoadTest.ltrar.zip?sv=2012-02-12&se=2014-06-03T05%3A05%3A39Z&sr=b&si=sas_tenant_policyaeee0697-d734-43d7-956e-e662252c265c&sig=n1Tj%2BsCtiOqQu9UtcXsl%2Bn3ixP%2FVebHCKDJvfD5Tr%2FE%3D",
  "counterGroups": {
    "count": 3,
    "value": [
      {
        "groupName": "Performance",
        "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67/CounterInstances?groupNames=Performance"
      },
      {
        "groupName": "Throughput",
        "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67/CounterInstances?groupNames=Throughput"
      },
      {
        "groupName": "Application",
        "url": "https://dbtek.vsclt.visualstudio.com/_apis/clt/testruns/a5e0d4b9-d387-4b3e-9566-163da9c39b67/CounterInstances?groupNames=Application"
      }
    ]
  }
}



Recuperare i Test errors
È anche possibile recuperare una lista di eventuali errori che si sono verificati durante l'esecuzione del test. Di nuovo, va utilizzata una chiamata in GET.

Request Url:
GET    https://dbtek.vsclt.visualstudio.com/_apis/clt/testRuns/47be20f0-ac4a-40cd-acb7-d9f8c44d0404/Errors

Response:
{
  "count": 2,
  "value": [
    {
      "type": "Exception",
      "subType": "UriFormatException",
      "occurrences": 50,
      "testCaseName": "ErrorsAndExceptionsWebTest",
      "scenarioName": "LoadTestingScenarioWarmupDuration",
      "request": "http://www.bing:123.com/----{GET}",
      "stackTrace": "   at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)\n   at System.Uri..ctor(String uriString, Boolean dontEscape)\n   at Microsoft.VisualStudio.TestTools.WebStress.WebTestTransaction..ctor(String requestUrl)\n   at Microsoft.VisualStudio.TestTools.WebStress.WebTestInstrumentedTransaction.CreateTransaction()\n   at Microsoft.VisualStudio.TestTools.WebStress.WebTestInstrumentedTransaction.Execute(WebTestCaseContext testCaseContext, AsyncCallback completionCallback, Object callerState)",
      "messageText": "Invalid URI: Invalid port specified.",
      "lastErrorDate": "2014-11-11T09:14:20.363Z"
    },
    {
      "type": "ExtractionRuleError",
      "subType": "ExtractText",
      "occurrences": 50,
      "testCaseName": "ErrorsAndExceptionsWebTest",
      "scenarioName": "LoadTestingScenarioWarmupDuration",
      "request": "http://www.bing.com/----{GET}",
      "stackTrace": "",
      "messageText": "StartsWith text was not found in the response",
      "lastErrorDate": "2014-11-11T09:14:23.663Z"
    }
  ]
}

giovedì 30 ottobre 2014

Mettere il Database sotto Source Control - eBook gratuito

Normalmente, un sistema di Source e Version control mostra enormi benefici nel coordinamento del lavoro dei team di sviluppo, garantendo un audit trail completo di tutte le modifiche ai file di codice e permettendo alla squadra di tenere traccia di qualsiasi versione specifica o build.

Anche gli sviluppatori di database possono (e dovrebbero...) trarre beneficio dal audit history e dalle funzionalità di change-tracking, c'è molto di più che salvare qualche script DB in una sottocartella dell'applicazione sul sistema di source control. A differenza di chi sviluppa applicazioni, i database developers non assemblano file e classi in un pacchetto applicativo, ma invece eseguono script che magari si alimentano a vicenda o da altri oggetti esistenti instaurando una stretta interdipendenza tra il codice ed i dati.

Per coprire quello che possiamo chiamare "Database Lifecycle Management", e considerare un ramo dell'ALM, RedGate ha sviluppato un interessante ebook gratuito, dal nome "SQL Server Source Control Basics".

Purtroppo, gli autori del libro hanno deciso di utilizzare SVN, ma i concetti chiave si possono applicare senza problami anche a Team Foundation Server o Visual Studio Online.

Tra gli argomenti trattati ci sono:
Concetti fondamentali dei sistemi di source control
Scegliere un sistema di version control per il database e definirne la struttura
Strategie di branch e merge
Automatizzare il versionamento del database ed il suo deployment
Introduzione al "Database continuous integration"

L'eBook offre una guida dettagliata sui concetti di Database source control con esempi chiari e completi.

Può essere scaricatoto, gratis, qui (disponibile solo in lingua inglese):

martedì 28 ottobre 2014

Visual Studio Online REST API versione 1.0

Oggi è stata rilasciata la prima versione ufficiale delle REST API di Visual Studio Online, la 1.0.

Annunciate in preview in maggio, ora hanno raggiunto una maturità tale da spingere il team di sviluppo a chiudere la prima release. Questo non significa che non ci saranno cambiamenti o che gli sviluppi siano terminati; significa che le funzionalità core sono ora complete e da qui in avanti verranno versionate per mantenere  la compatibilità all'indietro, in modo che tutte le applicazioni ed i servizi che le utilizzano rimangano comunque funzionanti a prescindere dagli aggiornamenti futuri.

Congiuntamente all'annuncio, il team ha modificato il "API Reference portal" e la "Getting started guide"

Importante
Se avete delle applicazioni esistenti che utilizzano la versione 1.0 preview delle API, dovreste iniziare la migrazione alla  release 1.0 prima possibile; infatti la versione 1.0 preview (e precedenti) smetteranno di funzionare in 12 settimane da oggi. Per sapere di più sul versioning e sulla migrazione è possibile consultare la "versioning and migration page".

Detto questo, ricordate che a partire da oggi, quindi, le Visual Studio Online REST API seguono questo pattern:

VERB https://{account}.VisualStudio.com/DefaultCollection/_apis[/{area}]/{resource}?api-version=1.0

lunedì 13 ottobre 2014

Integrare un’applicazione o un servizio con Visual Studio Online - Guest Post MSDN

Venerdì scorso è stato pubblicato su MSDN Italia il mio secondo Guest post, in cui parlo di com'è possibile e facile integrare le nostre applicazioni e servizi con Visual Studio Online utilizzando le nuove REST API ed i Service Hooks.

Per leggere l'articolo completo utilizzare il link sottostante:

lunedì 6 ottobre 2014

Migrare facilmente da Team Foundation Server a Visual Studio Online - Guest Post MSDN

Oggi è stato pubblicato su MSDN Italia un mio Guest post in cui spiego come effettuare la migrazione da un Team Foundation Server (quindi normale scenario di installazione on-premises) al suo corrispettivo on-cloud Visual Studio Online e quali sono le motivazioni che potrebbero spingerci a farlo.

Per leggere il post utilizzare il link sottostante:

martedì 30 settembre 2014

Creare un Work Item con le REST API - Visual Studio Online

A volte può essere utile aggiungere un nuovo Work Item ad un nostro Team Project in modo automatico, magari in risposta ad un determinato evento.

Le nuove "WIT REST API v1.0 (preview 2)" (rilasciate il 4 settembre) esposte da Visual Studio Online ci permettono di farlo.

Quando creiamo un work item, possiamo indicare i valori per qualsiasi tipo di work item fields.

Per creare un work item, è necessario effettuare una richiesta HTTP PATCH a:

https://your_account.visualstudio.com/defaultcollection/team_project_name/_apis/wit/workitems/$work_item_type_name?api-version=1.0-preview.2

Il body della richiesta deve essere valorizzato in base a questo formato:

[
    {
        "op": "add",
        "path": { string }
        "value": { string or int, depending on the field }
    },
    {
        "op": "add",
        "path": "/relations/-",
        "value":
        {
            "rel": { string },
            "url": { string },
            "attributes":
            {
                { name/value pairs }
            }
        }
    }
]

Un esempio di richiesta potrebbe essere:

https://myAccount.visualstudio.com/defaultcollection/myProject/_apis/wit/workitems/$task?api-version=1.0-preview.2

[
  {
    "op": "add",
    "path": "/fields/System.Title",
    "value": "Change blog title height"
  }
]

Questa richiesta produce una response come la seguente, in cui si possono trovare tutte le informazioni relative al work item appena creato:

{
  "id": 88,
  "rev": 1,
  "fields": {
    "System.AreaPath": "myProject",
    "System.TeamProject": "myProject",
    "System.IterationPath": "myProject",
    "System.WorkItemType": "Task",
    "System.State": "To Do",
    "System.Reason": "New task",
    "System.CreatedDate": "2014-09-30T10:25:12.943Z",
    "System.CreatedBy": "Davide Benvegnu",
    "System.ChangedDate": "2014-09-30T10:25:12.943Z",
    "System.ChangedBy": "Davide Benvegnu,
    "System.Title": "Change blog title height"
  },
  "_links": {
    "self": {
      "href": "https://myAccount.visualstudio.com/DefaultCollection/_apis/wit/workItems/88"
    },
    "workItemUpdates": {
      "href": "https://myAccount.visualstudio.com/DefaultCollection/_apis/wit/workItems/88/updates"
    },
    "workItemRevisions": {
      "href": "https://myAccount.visualstudio.com/DefaultCollection/_apis/wit/workItems/88/revisions"
    },
    "workItemHistory": {
      "href": "https://myAccount.visualstudio.com/DefaultCollection/_apis/wit/workItems/88/history"
    },
    "html": {
      "href": "https://myAccount.visualstudio.com/web/wi.aspx?pcguid=0fa87894-6f48-4458-957d-3438b6bb9343&id=88"
    },
    "workItemType": {
      "href": "https://myAccount.visualstudio.com/DefaultCollection/c4637008-2068-4b3f-828d-a214e2ba5210/_apis/wit/workItemTypes/Task"
    },
    "fields": {
      "href": "https://myAccount.visualstudio.com/DefaultCollection/_apis/wit/fields"
    }
  },
  "url": "https://myAccount.visualstudio.com/DefaultCollection/_apis/wit/workItems/88"
}

venerdì 12 settembre 2014

A proposito di Azure Websites Extensions

Ogni Azure Website fornisce un end point di management estendibile che permette di sfruttare un potente set di strumenti, deployato come site extensions. Questi strumenti spaziano dagli editor di codice sorgente come Visual Studio Online a strumenti di gestione delle risorse connesse, come un database MySQL collegato ad un sito web. 

Le Site Extensions sono, di fatto, delle web app con dei metadati che vengono usati per la registrazione dell'estensione; possono essere create per ogni development stack supportato dalla piattaforma degli Azure Websites.

Le Site Extesions esistenti sono disponibili, per ogni WebSite, all'interno dell'Azure Preview Portal:


Per aggiungere una nuova estensione sito basta andare alla sezione Configurazione nella "pagina" del web site, fare clic sul pulsante ADD e selezionare un'estensione dalla lista.  Ognuna di queste estensioni è resa disponibile dal publisher riportato sotto il nome dell'extension e con i temini legali che devono essere accettati esplicitamente prima dell'installazione.


Una volta aggiunta, il contenuto della Site Extension viene copiato dentro la cartella %HOME%\SiteExtensions parallela alla website root. Attenzione che l'aggiunta di un'estensione fa riavviare il sito.


È possibile anche creare delle nuove estensioni.
Se risultano necessari strumenti che non sono già presenti, è possibile creare nuove Site Extension da utilizzare con i WebSite seguendo le istruzioni a questo link
È inoltre possibile pubblicare nuove estensioni in modo che siano disponibili per tutta la piattaforma Azure WebSites attraverso il portale "Site Extension Gallery submission": http://www.siteextensions.net.

martedì 19 agosto 2014

Azure Web Sites Deploy: come funziona?

Gli Azure Web Sites supportano il continuous deployment da strumenti del controllo del codice sorgente e repository com BitBucket, CodePlex, Dropbox, Git, GitHub, Mercurial e TFS/VSO. È possibile infatti utilizzare questi strumenti per manutenere i contenuti ed i sorgenti del sito e poi pubblicare le modifiche in modo semplice e veloce.

Metodi di deploy supportati
Usando un repository Git locale è possibile, ad esempio, fare la "promozione" manuale degli aggiornamenti da un progetto locale ad un Azure Web Site;  deployando invece da strumenti come BitBucket, CodePlex, Dropbox, GitHub, TFS/VSO o Mercurial è possibile abilitare un processo di continuous deployment in cui sarà Azure stesso a fare il pull update più recenti del progetto.

Entrambi i metodi permettono di deployare i progetti su un Azure Web Site, ma il continuous deployment è utile quando ci sono più persone che lavorano su un progetto e ci si vuole assicurare che l'ultima versione sia sempre pubblicata indipendentemente da chi ha fatto l'aggiornamento più recente. Il continuous deployment è anche utile se viene utilizzato uno degli strumenti di cui sopra come repository centrale per l'applicazione.

Su internet ci sono un sacco di articoli che spiegano come fare il deploy di un Azure WebSite (ad esempio http://azure.microsoft.com/en-us/documentation/articles/web-sites-deploy/) o come implementare delle strategia di Continuous Deployment (es. http://azure.microsoft.com/en-us/documentation/articles/web-sites-publish-source-control/).

Ma come funziona in realtà "dietro le quinte"?

La risposta è "Kudu".

Kudu è il motore che sta dietro il deployments degli Azure Web Sites, ma può anche funzionare al di fuori di Azure.
Ha un'architettura alquanto insolita, nel senso che è un servizio single-tenant anziché multi-tenant. Questo significa che ogni sito Web Azure ha una propria istanza del servizio Kudu, completamente distinta dalle istanze Kudu utilizzate per altri siti Azure.

Il componente rimane attivo in background e "controlla" se si verificano checkin, commit, nuovi file, build e così via. Quando rileva qualcosa, KuduSync inizia e fare il "lavoro sporco".

Si tratta di uno strumento piuttosto interessante:
  • è un progetto open source disponibile su GitHub (https://github.com/projectkudu/kudu)
  • è installato automaticamente per ogni Azure Web Sites
  • può utilizzare uno script di distribuzione personalizzato

Ma la cosa più importante (imho) è questa:
Il deployment viene creato nella struttura delle cartelle del sito web e il nuova deployment viene copiato nella root del sito, lasciando intatti i vecchi deployment. 
Questo significa che è possibile fare il "rollback" a qualsiasi deploy fatto in passato!

È anche possibile accedere alla dashboard web di Kudu, utilizzando un url  del tipo "https://your_website_name.scm.azurewebsites.net/" e le deployment credentials associate (oppure le credenziali di un amminisistratore del servizio).

Dashboard di Kudu

Nella dashboard di Kudu è possibile trovare un sacco di informazioni utili sull'ambiente del tuo sito web insieme a una serie di strumenti per gestire il sito e, ultimo ma non meno importante, un set completo di API REST. C'è anche la possibilità di gestire le WebSite extension.

C'è anche un interessante video (in inglese) in cui David Ebbo e Scott Guthrie spiegano come funziona Kudu: http://channel9.msdn.com/Shows/Azure-Friday/What-is-Kudu-Azure-Web-Sites-Deployment-with-David-Ebbo

mercoledì 6 agosto 2014

Azure WebSite, Cloud Service e Virtual Machine: quale scegliere?

Capita, a volte, di dover iniziare un nuovo sviluppo o di dover pianificare una pubblicazione sul cloud, su Azure, ma di non sapere nel dettaglio che tipo di servizio è meglio utilizzare: dovrei usare un WebSite, un Cloud Service o una Virtual Machine? Che tipi di vantaggi / svantaggi ho in un caso o nell'altro?

Vediamo quelle che sono le principali differenze.

Attenzione: questo post è aggiornato con le info disponibili al 5 agosto 2014.

Innanzitutto uno schema, che usa Microsoft nella documentazione ufficiale di Azure, per comparare i 3 servizi:

Courtesy of Microsoft

In questa immagine è abbastanza chiaro il livello di semplicità vs possibilità di controllo che offrono le tre soluzioni. Volendo essere estremamente sintetici:

  • WebSite:
    • Soluzione estremamente semplice da utilizzare, che offre comunque un buon set di strumenti a supporto (monitoring, alerts, scale, ecc) ma a discapito del livello di personalizzazione e controllo sulla configurazione.
    • In applicazioni multi-tier, fornisce il supporto alla solo web tier
  • Cloud Service:
    • Meno semplice da utilizzare e deployare rispetto ai Websites, fornisce un livello di controllo molto maggiore.
    • Anche in questo caso ci sono diversi strumenti di monitoraggio e supporto già inclusi
    • È possibile utilizzare sia i WebRole (che di fatto sono delle VM dedicate con installato IIS) sia i WorkerRole (sempre delle VM dedicate, ma senza IIS. È possibile paragonare un WorkerRole ad un Windows Service)
    • In scenari multi-tier, è possibile utilizzare una combinazione di WebRole e WorkerRole per implementare sia il web tier che il middle-tier che il backend 
    • In scenari multi-tier, è possibile scalare il frontend ed il backend in modo indipendente
  • Virtual Machine:
    • Lascia la configurazione e la personalizzazione completamente in mano all'utente, quindi è più complicata da gestire ma fornisce il massimo livello di controllo possibile, come con i server on-premises.
    • Si possono utilizzare per qualsiasi tipo di applicazione ed architettura
    • È necessario occuparsi manualmente della gestione del sistema, quindi anche di aggiornamenti, policy di sicurezza ecc ecc
    • È la scelta ideale in scenari particolarmente complessi o quando si ha necessità di hostare servizi o software che non sono supportati nelle altre modalità.

Questa è la tabella ufficiale con la comparazione dei tre tipi di servizio:

FEATUREWEB SITESCLOUD SERVICES
(WEB ROLES)
VIRTUAL MACHINES
Access to services like Service Bus, Storage, SQL Database
XXX
Host web or web services tier of a multi-tier architecture
XXX
Host middle tier of a multi-tier architecture
XX
Integrated MySQL-as-a-service support
X1X
Support for ASP.NET, classic ASP, Node.js, PHP, Python
XXX
Scale out to multiple instances without redeploy
XX2
Support for SSL
3XX
Visual Studio integration
XXX
Remote Debugging
XXX
Deploy code with TFS
XXX
Deploy code with GIT, FTP
XX
Deploy code with Web Deploy
X4X
WebMatrix support
XX
Near-instant deployment
X
Instances share content and configuration
X
Scale up to larger machines without redeploy
X
Multiple deployment environments (production and staging)
XX
Network isolation with Azure Virtual Network
XX
Support for Azure Traffic Manager
XXX
Remote desktop access to servers
XX
Ability to define/execute start-up tasks
XX
Automatic OS update management
XX
Integrated Endpoint Monitoring
XXX
Seamless platform switching (32bit/64bit)
XX
1 Web or worker roles can integrate MySQL-as-a-service through ClearDB's offerings, but not as part of the Management Portal workflow.
2 Although Virtual Machines can scale out to multiple instances, the services running on these machines must be written to handle this scale-out. An additional load balancer must be configured to route requests across the machines. Finally, an Affinity Group should be created for all machines participating in the same role to protect them from simultaneous restarts from maintenance or hardware failures.
3 For Web Sites, SSL for custom domain names is only supported for standard mode. For more information on using SSL with Web Sites, see Configuring an SSL certificate for an Azure Web Site.
4 Web Deploy is supported for cloud services when deploying to single-instance roles. However, production roles require multiple instances to meet the Azure SLA. Therefore, Web Deploy is not a suitable deployment mechanism for cloud services in production.

Per vedere la comparazione completa dei tre servizi, costantemente aggiornata, è possibile consultare la guida ufficiale sulla documentazione di Azure

mercoledì 30 luglio 2014

Indirizzo IP dedicato sugli Azure Website

Quando si ha un indirizzo IP condiviso con altri siti / clienti (come accade in un ambiente multi-tenant), si possono avere alcuni problemi come, per esempio, vedersi inserito l'IP in una blacklist a causa del contenuto di altri siti.

L'unico modo affidabile per risolvere questo ed altri problemi è quello di configurare il website con un IP dedicato. Ciò significa che il sito utilizzerà un proprio IP, che quindi non sarà condiviso con altri siti. 

In Azure, è possibile facilmente ottenere un IP dedicato con l'attivazione dell'IP SSL. Questa opzione è disponibile solo per i siti del tier Standard e se il website utilizza un dominio personalizzato ci sono alcune considerazioni supplementari.

Se si utilizza un dominio personalizzato ed è stato configurato un record CNAME che punta al sito su Azure (ad esempio, mysite.azurewebsites.net), allora è piuttosto semplice - basta cambiare il record con il proprio provider DNS e quindi configurare IP-SSL.

Se, invece, è stato configurato un record A per risolvere l'hostname è necessario seguire questa procedura:

  1. Cambiare la mappatura dell'hostname (cioè www.mysite.com) da un record a un CNAME che punta al Website su Azure (cioè mysite.azurewebsites.net). Questa operazione non dovrebbe causare nessun downtime visto che entrambi i record risolveranno lo stesso indirizzo IP. Attendere un po' di tempo per essere sicuri che i DNS si siano replicati correttamente.
  2. Caricare un certificato valido per www.mysite.com sul Website utilizzando la pagina "Domains" nella tab "Configure". Normalmente il certificato va acquistato da un provider abilitato (una certification authority), ma se non si intende utilizzare effettivamente SSL, è possibile utilizzare un certificato auto-firmato che è facile da generare e, soprattutto, è gratis.
  3. Configurare un binding SSL IP Based per www.mysite.com. Questa opzione è disponibile sotto "SSL Binding" nella scheda "Configure". Per maggiori informazioni è possibile consultare la sezione "Configure SSL" nella guida per attivare l'SSL su Azure.

martedì 22 luglio 2014

Visual Studio Online ora supporta Azure Active Directory


Ieri il team vsalm di Microsoft ha iniziato il deploy dello sprint 68.

La parte più grande ed interessante dell'annuncio è la nuova fase del supporto di Azure Active Directory in VS Online. Hanno iniziato questo "viaggio" in maggio quando hanno annunciato le prime parti del supporto all'AAD a "Build". Poi hanno aggiunto alcune (poche) altre informazioni durante "TechEd" ma era una cosa passata un po' in sordina visto che, fino a questa settimana, non era possibile convertire o associare un account esistente ad AAD. Con questo deploy, invece, diventa possibile! Ufficialmente è in preview e quindi è necessario richiedere l'accesso alla funzionalità, ma sembra accettino tutte le richieste quindi non dovrebbe essere un grosso problema (anche perchè va fatto una volta sola). 

Con queste modifiche, è possibile:

  • Associare un OrgID (ovvero credenziali AAD/AD) alla sottoscrizione MSDN, se ce n'è una, ed usarla come grant per la licenza VSO
  • Creare un nuovo account collecato ad AAD
  • Collegare un account esistente ad AAD
  • Scollegare un account da AAD
  • Accedere sia con un Microsoft Account che con un OrgID (solo AAD oppure in sycn con l'Active Directory on premises) creando di fatto un SSO con le credenziali corporate, Office 365, ecc.



Per vedere tutti i dettagli riguardo il supporto AD e le altre cose incluse nell'update è possibile leggere il post originale di Brian Harry su MSDN.

lunedì 14 luglio 2014

ASP.net MVC ActionLink con un'Immagine: Parte 3 (Ajax)

Nei mie precedenti post abbiamo visto come implementare alcuni helper custom per aggiungere dei Glifi Bootstap o delle Immagini agli ActionLinks.

Ora invece vedremo come fare più o meno la stessa cosa ma aggiungendo il supporto Ajax.

Sostanzialmente quello che bisogna fare è costruire l'html tenendo conto di tutte le "cose" relative ad ajax (attributi, parametri, ecc) che il normale helper Ajax.ActionLink aggiunge.

In questo esempio ho usato la versione che utilizza i glifi, ma è ovviamente possibile usare lo stesso approccio anche nel caso si vogliano usare immagini normali.

/// <summary>
/// Create an Ajax.ActionLink with an associated glyphicon
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="linkText"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="glyphicon"></param>
/// <param name="routeValues"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static MvcHtmlString ImageActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, string glyphicon, AjaxOptions ajaxOptions, RouteValueDictionary routeValues = null, object htmlAttributes = null)
{
 //Example of result:           
 //<a id="btnShow" href="/Customers/ShowArtworks?customerId=1" data-ajax-update="#pnlArtworks" data-ajax-success="jsSuccess" 
 //data-ajax-mode="replace" data-ajax-method="POST" data-ajax-failure="jsFailure" data-ajax-confirm="confirm" data-ajax-complete="jsComplete" 
 //data-ajax-begin="jsBegin" data-ajax="true">
 //  <i class="glyphicon glyphicon-pencil"></i>
 //  <span>Edit</span>
 //</a>

 var builderI = new TagBuilder("i");
 builderI.MergeAttribute("class", "glyphicon " + glyphicon);
 string iTag = builderI.ToString(TagRenderMode.Normal);

 string spanTag = "";
 if (!string.IsNullOrEmpty(linkText))
 {
  var builderSPAN = new TagBuilder("span");
  builderSPAN.InnerHtml = " " + linkText;
  spanTag = builderSPAN.ToString(TagRenderMode.Normal);
 }

 //Create the "a" tag that wraps
 var builderA = new TagBuilder("a");

 var requestContext = HttpContext.Current.Request.RequestContext;
 var uh = new UrlHelper(requestContext);

 builderA.MergeAttribute("href", uh.Action(actionName, controllerName, routeValues));

 //Ajax section
 builderA.MergeAttribute("data-ajax", "true");
 builderA.MergeAttribute("data-ajax-update", ajaxOptions.UpdateTargetId.StartsWith("#") ? ajaxOptions.UpdateTargetId : "#" + ajaxOptions.UpdateTargetId);
   
 if (!string.IsNullOrEmpty(ajaxOptions.InsertionMode.ToString()))
  builderA.MergeAttribute("data-ajax-mode", ajaxOptions.InsertionMode.ToString());            
 
 if (!string.IsNullOrEmpty(ajaxOptions.OnBegin))
  builderA.MergeAttribute("data-ajax-begin", ajaxOptions.OnBegin);
 
 if (!string.IsNullOrEmpty(ajaxOptions.OnComplete))
  builderA.MergeAttribute("data-ajax-complete", ajaxOptions.OnComplete);
   
 if (!string.IsNullOrEmpty(ajaxOptions.OnFailure))
  builderA.MergeAttribute("data-ajax-failure", ajaxOptions.OnFailure);
   
 if (!string.IsNullOrEmpty(ajaxOptions.OnSuccess))
  builderA.MergeAttribute("data-ajax-success", ajaxOptions.OnSuccess);
   
 if (!string.IsNullOrEmpty(ajaxOptions.Confirm))
  builderA.MergeAttribute("data-ajax-confirm", ajaxOptions.Confirm);
  
 if (!string.IsNullOrEmpty(ajaxOptions.HttpMethod))
  builderA.MergeAttribute("data-ajax-method", ajaxOptions.HttpMethod);

 if (htmlAttributes != null)
 {
  IDictionary<string, object> attributes = new RouteValueDictionary(htmlAttributes);
  builderA.MergeAttributes(attributes);
 }

 builderA.InnerHtml = iTag + spanTag;

 return new MvcHtmlString(builderA.ToString(TagRenderMode.Normal));
}


Come si può vedere, il codice è simile a quello che abbiamo utilizzato nei post precedenti con l'eccezione del fatto che stiamo estendendo un "AjaxHelper" invece che un "HtmlHelper" come accadeva prima e che abbiamo aggiunto una "ajax section".

giovedì 10 luglio 2014

Modifiche alle licenze di Visual Studio Online (in meglio)

La scorsa primavera Visual Studio Online ha visto la sua "promozione" da "Preview" a "General Availability". Tale processo ha incluso modifiche al branding, gli SLA, l'annuncio dei prezzi, la fine del programma early adopter e altro ancora.

Ora, il team VSO / TFS ha deciso di apportare questi due importanti cambiamenti al licensing (indicativamente nei prossimi due mesi):


  • qualsiasi account VS Online sarà in grado di avere un numero illimitato di utenti "stakeholder" con accesso ad un sottoinsieme di funzionalità, senza alcun costo aggiuntivo. 
  • il piano Visual Studio Online Advanced comprenderà l'accesso a tutte le funzionalità del Test hub.


Il team sta lavorando sodo per implementare questi cambiamenti di licenza e l'aspettativa è che avranno circa 2 sprint da copmletare per dinire tutto. Il che posizionerebbe la data effettiva di rilascio attorno a metà agosto.

In generale, l'obiettivo del team è quello di mantenere le licenze per VS Online e Team Foundation Server più "parallele" possibili - per limitare il grado di complessità. Come risultato, stanno evolvendo l'attuale esenzione dalle CAL di TFS "Work Item Web Access" per allinearla al modello di "stakeholder" di VSO. Ciò si tradurrà in più funzionalità a disposizione degli utenti TFS senza CAL. La speranza è di ottenere questo cambiamento a partire da Team Foundation Server 2013 Update 4.

Per leggere l'annunco originale di Brian Harry, visitate:
http://blogs.msdn.com/b/bharry/archive/2014/07/09/upcoming-vs-online-licensing-changes.aspx

mercoledì 9 luglio 2014

ASP.net MVC ActionLink con un'Immagine: Parte 2 (Immagine)

Nel mio precedente post ho parlato di come creare un helper custom per renderizzare un ActionLink con un glifo.

In questo post, invece, vedremo come creare un helper simile ma che usa delle immagini "normali" al posto dei bootstrap glyphs.

/// <summary>
/// Create an ActionLink with an associated image
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="linkText"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="imagePath"></param>
/// <param name="routeValues"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static MvcHtmlString ImageImgActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string imagePath, object routeValues = null, object htmlAttributes = null)
{
 //Exemple of result:
 //<a href="@Url.Action("Edit", new { id = Model.id_rod })">
 //  <i class="glyphicon glyphicon-pencil"></i>
 //  <span>Edit</span>
 //</a>

 if (imagePath.StartsWith("~/"))
 {
  imagePath = VirtualPathUtility.ToAbsolute(imagePath);
 }

 var builderImage = new TagBuilder("image");
 builderImage.MergeAttribute("src", imagePath);
 builderImage.MergeAttribute("alt", linkText);
 builderImage.MergeAttribute("style", "border=0");
 string imageTag = builderImage.ToString(TagRenderMode.SelfClosing);

 string spanTag = "";
 if (!string.IsNullOrEmpty(linkText))
 {
  var builderSPAN = new TagBuilder("span");
  builderSPAN.InnerHtml = " " + linkText;
  spanTag = builderSPAN.ToString(TagRenderMode.Normal);
 }

 //Create the "a" tag that wraps
 var builderA = new TagBuilder("a");

 var requestContext = HttpContext.Current.Request.RequestContext;
 var uh = new UrlHelper(requestContext);

 builderA.MergeAttribute("href", uh.Action(actionName, controllerName, routeValues));

 if (htmlAttributes != null)
 {
  IDictionary<string, object> attributes = new RouteValueDictionary(htmlAttributes);
  builderA.MergeAttributes(attributes);
 }

 builderA.InnerHtml = imageTag + spanTag;

 return new MvcHtmlString(builderA.ToString(TagRenderMode.Normal));
}


È possibile passare all'helper sia url relativi che assoluti (parametro imagePath) in modo da avere la massima flessibilità.

lunedì 7 luglio 2014

ASP.net MVC ActionLink con un'Immagine: Parte 1 (Glyph)

Se state usando ASP.net MVC saprete sicuramente che c'è un helper piuttosto utile che permette di creare dei link a delle Action dei controller: si tratta del Html.ActionLink.

È possibile utilizzare questo helper solo con link testuali, ma se invece volessimo aggiungere al link anche un glifo di bootstrap, come in questo esempio?



Beh, la risposta "fast&dirty" è quella di scrivere un po' di codice html direttamente nella pagina cshtml. Qualcosa tipo:

<a href="@Url.Action("Edit", new { id = Model.id })">
  <i class="glyphicon glyphicon-pencil"></i>
  <span>Edit</span>
</a>


Questo approccio è sicuramente più veloce di qualsiasi altro, se abbiamo bisogno di avere un comportamento di questo tipo solo in un paio di posti. Ma se avessimo necessità di avere i link con le immagini un po' ovunque nella nostra applicazione? (come ad esempio nel mio caso) Dovremmo copiare quel codice in N posti diversi e cambiarlo di volta in volta a seconda delle necessità... non è il massimo.

In questo caso, la soluzione migliore è quella di scrivere un custom helper che lo faccia per noi:

/// <summary>
/// Create an ActionLink with an associated glyphicon
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="linkText"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="glyphicon"></param>
/// <param name="routeValues"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static MvcHtmlString ImageActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string glyphicon, object routeValues = null, object htmlAttributes = null)
{
 //Exemple of result:
 //<a href="@Url.Action("Edit", new { id = Model.id_rod })">
 //  <i class="glyphicon glyphicon-pencil"></i>
 //  <span>Edit</span>
 //</a>

 var builderI = new TagBuilder("i");
 builderI.MergeAttribute("class", "glyphicon " + glyphicon);
 string iTag = builderI.ToString(TagRenderMode.Normal);

 string spanTag = "";
 if (!string.IsNullOrEmpty(linkText))
 {
  var builderSPAN = new TagBuilder("span");
  builderSPAN.InnerHtml = " " + linkText;
  spanTag = builderSPAN.ToString(TagRenderMode.Normal);
 }            

 //Create the "a" tag that wraps
 var builderA = new TagBuilder("a");

 var requestContext = HttpContext.Current.Request.RequestContext;
 var uh = new UrlHelper(requestContext);
 
 builderA.MergeAttribute("href", uh.Action(actionName, controllerName, routeValues));

 if (htmlAttributes != null)
 {
  IDictionary<string, object> attributes = new RouteValueDictionary(htmlAttributes);
  builderA.MergeAttributes(attributes);
 }
  
 builderA.InnerHtml = iTag + spanTag;
 
 return new MvcHtmlString(builderA.ToString(TagRenderMode.Normal));
}

A questo punto sarà possibile invocare l'helper Html.ImageActionLink con gli stessi parametri che passeremmo al normale Html.ActionLink ma con in più la classe glyphicon della glyph image che vogliamo aggiungere al nostro link.

mercoledì 2 luglio 2014

Eliminare work item da TFS e VSO

Vi è mai capitato di creare un sacco di work item che in seguito si sono dovuti eliminare? A me si... soprattutto come utente della TFS Integration Platform. E quando le cose vanno male possono andare molto, molto male.

Anche se i work item si possono mettere nello stato "removed", rimangono ancora presenti nel sistema. L'unico modo disponibile out of the box per rimuovere gli elementi è quello recuperare l'ID per ogni elemento di lavoro che si desidera eliminare ed eseguire il seguente comando (da riga di comando) per ciascuno di essi:

witadmin destroywi /collection:CollectionURL /id:id [/noprompt]

Beh, questo approccio è ottimo se non avete un qualche migliaio di work item da eliminare.
Per questo motivo ho scritto un po' di codice che lo fa per me; in questo esempio ho creato un piccolo programma console ma è possibile utilizzare lo stesso codice in qualsiasi tipo di progetto.

using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

[...]

TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri("http://your_tfs_url:8080/tfs/CollectionName"));
WorkItemStore store = tpc.GetService();

string query = @"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = 'projectName'  AND  [System.AreaPath] UNDER 'projectName\_TOBEDELETED' ORDER BY [System.Id]";

WorkItemCollection wis = store.Query(query);
var wisIds = wis.Select( wi => wi.Id);

Console.WriteLine(string.Format("DESTROY {0} work items (they really can't be resurrected): y/n?", wis.Count));
ConsoleKeyInfo cki = Console.ReadKey();
Console.WriteLine();

if (cki.Key.ToString().ToLower() == "y")
{
 try
 {
  Console.WriteLine("Deleting....");
  var items = store.DestroyWorkItems(wisIds.ToArray());
  Console.WriteLine("DONE");
  foreach (var item in items)
  {
   Console.WriteLine(item.ToString());
  }
 }
 catch (Exception ex)
 {
  [...]
 }

}

Console.WriteLine("Finished");


La prima cosa che si può notare è che cerco elementi in una specifica area. Ho usato _TOBEDELETED in modo che sia ovvio ciò che accadrà agli elementi che finiscono lì dentro. Anche se ho lavorato con un utente che si lamentava che tutti i suoi file erano scomparsi e quando gli è stato chiesto dove li teneva ha indicato il cestino sul suo desktop!

Comunque, nel caso in cui si sia fatto un errore fatto un errore, il software consente di sapere quanti elementi si stanno per eliminare. È un semplice controllo, ma grazie a questo una volta ho evitato di eliminare più di 100.000 work item... come potete immaginare ho killato molto attentamente il programma (mai fidarsi l'opzione 'no' :) ).

lunedì 23 giugno 2014

Autoscale delle Virtual Machine con Microsoft Azure

Uno dei principali vantaggi che la piattaforma di Azure offre è la possibilità di scalare rapidamente le applicazioni in the cloud, in risposta alle fluttuazioni di carico.

Normalmente si scalano website o cloud services, ma se invece abbiamo le nostre applicazioni hostate su una Virtual Machine e le vogliamo scalare orizzontalmente? Anche questo è possibile.

Per farlo, vanno effettuati sostanzialmente 2 step: creare una Load Balanced Web Farm epoi configurare il servizio di AutoScale.

Ecco come:


Passaggi:

  1. Creare una VM Standard ed assegnarla ad un availability set
  2. Configurare la VM secondo le necessità (IIS, Application server, ftp, ecc...)
  3. Clonare la VM
    1. Sysprep 
    2. Cattura
    3. Ricreare la VM originale ed aggiungere tutti gli endpoint necessari
    4. Creare la seconda  VM senza "endpoint extra"
    5. Optional - ripetere il punto 3.4 per creare ulteriori VM
  4. Bilanciare le VM
    1. Cambiare gli endpoint sulla prima VM per creare un Load-Balanced set
    2. Aggiungere gli endpoint alla seconda (terza, ecc...) VM sul Load-Balanced set
    3. Ripetere i punti 4.1 e 4.2 per tutti gli endpoint che devono essere bilanciati
    4. Fare attenzione al Session State (se necessario)
  5. Configurare l'Autoscale

Dettagli:

3.1 - Sysprep
La prima cosa da fare quando si clona una VM Windows è il "sysprepping". Su Linux c'è un'opzione simile sull'Azure agent. Il Sysprep fa in modo che la macchina possa essere clonata in una nuova VM personalizzando le impostazioni come hostname ed indirizzo IP. 



Dopo il sysprep, la VM va spenta (se non si è selezionata l'apposita opzione che la spegne automaticamente). Può essere fatto in Remote Desktop, SSH oppure, semplicemente, dall'Azure portal.

3.2 - Cattura
A questo punto, nell'Azure portal bisogna andare sulla dashboard della VM e cliccare il bottone "Capture" per creare un immagine del disco della VM. Diamogli un nome e selezioniamo la checbox vicino a "Yes, I’ve sysprepped the machine" per poter continuare.


Dopo aver cliccato su "OK", Azure creerà l'immagine del nostro server "originale".

3.3 - Ricreare la VM originale ed aggiungere tutti gli endpoint necessari
Dopo che l'immagine è stata creata, si noterà che la VM che abbiamo appena "catturato"... non esiste più! È normale: la macchina è stata "smontata" per creare da essa un template. Ora quindi è possibile ricrearla semplicemente usando la nuova VM image appena create invece che uno dei template forniti da Microsoft.

Nella configurazione degli endpoint aggiungiamo di nuovo l'endpoint HTTP in ascolto sulla porta 80 o, comunque, tutti gli endpoint di cui abbiamo bisogno per poter utilizzare la nostra applicazione.

3.4 - Creare la seconda VM senza "endpoint extra"
Per creare la seconda VM nella webfarm basta creare una nuova macchina partendo sempre dall'immagine che è stata creata precedentemente.
Nello step 4 della creazione macchina assicuriamoci di selezionare lo stesso "Cloud Service" del primo server ed inserire la VM nello stesso availability set. 


NON aggiungere ancora alla macchinal'endpoint HTTP (o gli altri endpoint configurati al punto 3.3).

Ora abbiamo due macchine "uguali" in esecuzione, ma non sono ancora sotto bilanciamento. Noterete che entrambe le macchine sono già esposte con lo stesso nome host e che condividono lo stesso indirizzo IP pubblico virtuale. Ciò è dovuto al fatto che abbiamo precedentemente linkato le VM selezionando lo stesso Cloud Service. Se non lo fate, non sarete in grado di utilizzare il sistema di bilanciamento di carico che Azure fornisce out-of-the-box. Questo significa anche che l'endpoint per il desktop remoto pubblico dovrà essere diverso per entrambe le macchine: c'è un solo indirizzo IP esposto al mondo esterno quindi dovrete pensare  voi a differenziare l'endpoint.

4.1 - Cambiare gli endpoint sulla prima VM per creare un Load-Balanced set
L'ultima sezione per configurare la nostra webfarm è il load balancing.  Di fatto, configurarlo è molto semplice. 
Come prima cosa, andare sulla pagina "Endpoints" della prima VM, Selezionare un Endpoint che deve essere bilanciato ed andare in modifica.
Selezionare il checkbox "Create a Load-Balance set".


Nello step 2 della configurazione, dare un nome al Load-Balanced set e configurare i parametri di probe (nell'esempio, ho configurato un endpoint HTTPS, quindi voglio che sia monitorata ogni 15 secondi la risposta della porta 443. Dopo 2 tentativi falliti, il bilanciatore switcherà sull'altra macchina in via esclusiva)

4.2 - Aggiungere gli endpoint alla seconda (terza, ecc...) VM sul Load-Balanced set
Andare sulla dashboard della seconda VM, sull'Azure portal, e selezionare anche in questo caso la tab "Endpoints". Abbiamo gia aggiunto l'endpoint HTTPS alla prima macchina, quindi per la seconda basta "sottoscrivere" il load balanced set creato:



A questo punto abbiamo attivo il bilanciamento di carico con round-robin, che ogni n secondi verificherà che tutte le macchine e tutti gli endpoint configurati siano attivi e funzionanti. E visto che abbiamo linkato le VM attraverso un availability set, saranno in differenti fault domains nel datacenter riducendo il rischio di malfunzionamenti o errori dovuti a problemi hardware o manutenzione. È possibile anche spegnere tranquillamente una VM. Sostanzialmente, tutto quello che ci si può aspettare da un load balancer (ad eccezione delle sticky sessions).

4.4 - Fare attenzione al Session State (se necessario)
Ora che abbiamo le nostre VM bilanciate, dobbiamo stare attenti a come la nostra applicazione gestisce il session state.
Se, per esempio, stiamo deployando dei web server con sopra delle applicazioni Asp.Net dobbiamo configurare le machine key ed il sessione state nello stesso modo in cui lo faremmo se fossimo in un ambiente on-premise. Su Azure è possibile scegliere di usare la "solita" base dati delle sessioni (quindi Session state memorizzato su un Azure database), oppure usare l'Azure storage o ancora la "nuova" Azure cache.

Visitate questo link su msdn (http://blogs.msdn.com/b/cie/archive/2013/05/17/session-state-management-in-windows-azure-web-roles.aspx) per avere una panoramica della gestione del Session State su Azure.

5 - Configurare l'Autoscale
Ok, è giunto il momento di configurare l'autoscale!
Ora abbiamo le nostre VM attive e bilanciate. Ma abbiamo veramente sempre bisogno di averle tutte attive nello stesso momento? Probabilmente no. Magari abbiamo bisogno di averle tutte attive solo in una determinata fascia oraria oppure solo se il carico sull'applicazione supera una certa soglia...

Se vi ricordate, quando abbiamo creato le nostre VM abbiamo selezionato per tutte lo stesso Cloud Service. Ebbene, per configurare l'autoscale delle VM basta andare a configurare quello del relativo Cloud Service: andare quindi sulla dashboard del servizio e selezionare la pagina "Scale".

Da qui è possibile selezionare il tipo di scaling che vogliamo: None (scalign disattivato...), Cpu (in base a delle soglie di utilizzo del processore) o Queue. 


Nel mio caso, ho deciso di scalare usando la percentuale di utilizzo della CPU come parametro. Lo slider "Target CPU" riporta che io voglio scalare "in più" quando la media dell'utilizzo della CPU supera l'80% e scalare "in meno" quando riscende sotto il 60%. 

Nel mio esempio ho solo 2 VM, quindi posso configurare che in condizioni normali ce ne sia solo 1 attiva e che la seconda venga abilitata solo in caso di "scale up".

Dalla stessa schermata è anche possibile selezionare che il servizio scali automaticamente in base a delle fasce orarie configurabili.

mercoledì 23 aprile 2014

ALM Deep dive with TFS 2013: Evento by DotNetToscana


ALM Deep dive with TFS 2013

DotNetToscana, community ufficiale Microsoft per la Toscana di cui faccio parte, organizza il giorno 30 maggio a Firenze un evento gratuito sull'Application Lifecycle Management con Team Foundation Server 2013.

Io parteciperò come speaker sia alla KeyNote sia a due sessioni tecniche.

Questo l'Abstract dell'evento:
Applicare metodologie di Application Lifecycle Management significa gestire il ciclo di vita delle applicazioni in modo predicibile, ripetibile, agile, consistente, semplice e con qualità. Microsoft da parecchi anni fornisce delle soluzioni software per l'ALM, ma mai si era arrivati ad avere prodotti completamente integrati per tutte le fasi dell'ALM come con la versione 2013 di Team Foundation Server e Visual Studio Online.  

DotNetToscana dedica un'intera giornata all'argomento: analizzeremo le nuove funzionalità offerte e mostreremo come realizzare, on-premises e on-cloud, un sistema di gestione completo. Vedremo inoltre come utilizzare gli strumenti a disposizione per fornire soluzioni di Continuos Integration e Continuos Delivery ed infine scoprire come è semplice poter sviluppare applicazioni, anche mobile, che si interfacciano con le API del nostro TFS.

Per maggiori informazioni e per registrarti all’evento visita la pagina http://www.dotnettoscana.org/alm-deep-dive-with-tfs-2013.aspx

Oppure scarica il volantino dell'eventohttp://1drv.ms/1if7bQ8

giovedì 17 aprile 2014

Work Item Query Language nell'URL con TFS2013

Come molti di voi giù sicuramente sapranno, è possibile fare delle query sui work items in TFS tramite un url diretto sul server.

In TFS 2008/2010 la sintassi dell'Url era:

http://<ServerAddress>:8080/tfs/<TPC Name>/q.aspx?pname=<Project>&wiql=<WIQL>

In TFS 2012/2013, però, questo url non funziona. Infatti, è stato cambiato il formato dell'url stesso ed ora è il seguente:

http://<ServerAddress>:8080/tfs/<TPC Name>/<Project>/_workitems#_a=query&wiql=<WIQL>

Dove:
TPC Name è il nome della project collection su cui lavorare
Project è il nome del progetto su cui eseguire la query
WIQL è la query scritta con il "Work Item Query Language"

martedì 15 aprile 2014

Aggiornamenti Azure: Web Sites, VMs, Mobile Services, Notification Hubs, Storage, VNets, Scheduler, AutoScale ed altro

Quelli passati sono stati 10 giorni molto intensi per il team di Azure. Questo post vuole essere un veloce recap di tutti gli aggiornamenti e le migliorie che quel team ha fatto.

Web Sites: SSL included, Traffic Manager, supporto a Java, nuovo Basic Tier
Virtual Machines: Supporto per le estensioni Chef e Puppet, nuovo Basic Pricing Tier
Virtual Network: General Availability dei Gateways VPN per il DynamicRouting e Point-to-Site VPN
Mobile Services: Preview del supporto a Visual Studio con .NET, integrazione con Azure Active Directory e supporto Offline
Notification Hubs: Supporto per i dispositivi Kindle Fires ed integrazione con Visual Studio Server Explorer
Autoscale: General Availability release
Storage: General Availability release degli storage Read Access Geo Redundant
Active Directory Premium: General Availability release
Scheduler service: General Availability release
Automation: Preview release del nuovo Azure Automation service

Tutte queste features sono disponibili immediatamente (attenzione che alcune sono ancora in preview).

Vedi questo post sul blog di Scott Guthrie per avere tutti i dettagli.