dotCloud and go
Una Breve Introduzione a DotCloud




                1
L’immancabile esempio



          2
3
4
5
6
7
8
9
dove lo metto?



      10
COME lo metto?



      11
QUANTO TEMPO
  CI METTO?


     12
dotCloud



   13
14
IaaS - PaaS - SaaS



        15
IaaS - PaaS - SaaS
        15
16
17
18
19
dotcloud



   20
easy_install



     21
Easy Install è un modulo
python (easy_install)
incluso in setuptools che
vi consente di scaricare ed
installare automaticamente
pacchetti Python.

             22
Easy Install è un modulo
python (easy_install)
incluso in setuptools che
vi consente di scaricare ed
installare automaticamente
pacchetti Python.

             23
Sì, Python



    24
(è il motivo per cui
queste slide sono nere)


           25
26
     (-:
Python 2.7



    27
28
     )-:
$ dotcloud create whatever
Created application "whatever"




              29
30
$ cat dotcloud.yml
www:
   type: perl
   approot: www
backend:
   type: perl-worker
   approot: backend
nosqldb:
   type: redis
sqldb:
   type: mysql



          31
$ cat dotcloud.yml
 www:
    type: perl
    approot: www
 backend:
    type: perl-worker
    approot: backend
 nosqldb:
    type: redis
 sqldb:
    type: mysql



32
$ cat dotcloud.yml
     www:
        type: perl
        approot: www
     backend:
        type: perl-worker
        approot: backend
     nosqldb:
        type: redis
     sqldb:
        type: mysql



33
type: perl




    34
$ cat app.psgi
#!/usr/bin/env perl
use Dancer;
use whatever;
dance();




 35
$ cat Makefile.PL
...
  PREREQ_PM => {
     'Test::More' => 0,
     'YAML'        => 0,
     'Dancer'      => 1.3070,
     'Plack::Request' => 0,
     'Template' => 0,
     'JSON' => 0,
     'Redis' => 0,
     ...
  },
...
    36
type: perl-worker




        37
$ cat supervisord.conf
[program:exporter]
command = perl /home/dotcloud/current/bin/exporter

[program:saver]
command = perl /home/dotcloud/current/bin/saver

                         38
$ cat supervisord.conf
[program:exporter]
command = perl /home/dotcloud/current/bin/exporter

[program:saver]
command = perl /home/dotcloud/current/bin/saver


                         39
$ cat supervisord.conf
[program:exporter]
command = perl /home/dotcloud/current/bin/exporter

[program:saver]
command = perl /home/dotcloud/current/bin/saver


                         40
$ cat dotcloud.yml
     www:
        type: perl
        approot: www
     backend:
        type: perl-worker
        approot: backend
     nosqldb:
        type: redis
     sqldb:
        type: mysql



41
Connettersi




     42
43
$ cat /home/dotcloud/environment.yml
DOTCLOUD_ENVIRONMENT: default
DOTCLOUD_NOSQLDB_REDIS_HOST: whatever-polettix.dotcloud.com
DOTCLOUD_NOSQLDB_REDIS_LOGIN: redis
DOTCLOUD_NOSQLDB_REDIS_PASSWORD: ...
DOTCLOUD_NOSQLDB_REDIS_PORT: '13749'
DOTCLOUD_NOSQLDB_REDIS_URL: ...
DOTCLOUD_PROJECT: whatever
DOTCLOUD_SERVICE_ID: 0
DOTCLOUD_SERVICE_NAME: www
DOTCLOUD_SQLDB_MYSQL_HOST: whatever-polettix.dotcloud.com
DOTCLOUD_SQLDB_MYSQL_LOGIN: root
DOTCLOUD_SQLDB_MYSQL_PASSWORD: ...
DOTCLOUD_SQLDB_MYSQL_PORT: '13747'
DOTCLOUD_SQLDB_MYSQL_URL: ...




                             44
use JSON qw< from_json >;
use File::Slurp qw< read_file >;

sub get_dotcloud_config {
   my $filename = shift || '/home/dotcloud/environment.json';
   my $config_text = read_file($filename);
   my $config = from_json($config_text);
   return $config;
} ## end sub get_dotcloud_config




                             45
sub get_redis {
   my $config = get_dotcloud_config();
   my ($password, $hostname, $port) = map {
      $config->{'DOTCLOUD_NOSQLDB_REDIS_' . $_}
   } qw< PASSWORD HOST PORT >;

    require Redis;
    my $redis = Redis->new(server => "$hostname:$port");
    $redis->auth($password);
    return $redis;
}




                              46
ROTFL
sub get_redis {
   my $config = get_dotcloud_config();
   my ($password, $hostname, $port) = map {
      $config->{'DOTCLOUD_NOSQLDB_REDIS_' . $_}
   } qw< PASSWORD HOST PORT >;

    require Redis;
    my $redis = Redis->new(server => "$hostname:$port");
    $redis->auth($password);
    return $redis;
}




                              47
(mi basta poco)



       48
sub get_dbh {
   my $config = get_dotcloud_config();
   my ($username, $password, $hostname, $port) = map {
      $config->{'DOTCLOUD_SQLDB_MYSQL_' . $_}
   } qw< LOGIN PASSWORD HOST PORT >;

    require DBI;
    my $dbh = DBI->connect(
       "dbi:mysql:host=$hostname;port=$port"
          . ";database=whatever",
       $username, $password,
       { RaiseError => 1},
    );
    return $dbh;
}




                              49
50
51
use lib '/home/dotcloud/code/lib';
                52
DotCloud::Environment



          53
54
ora... in produzione



         55
$ dotcloud push whatever
# Found dotcloud.yml: Using /home/poletti/sviluppo/
perl/whatever as a base directory
# upload /home/poletti/sviluppo/perl/whatever ssh://
dotcloud@uploader.dotcloud.com:443/whatever/
branch:master
# git
...
2011-08-27 09:00:16 [api] Deploy whatever scheduled
for revision=latest
2011-08-27 09:00:16 [api] Waiting for the build. (It
may take a few minutes)
2011-08-27 09:00:17 [api] All the services are ready.
Beginning the build.
...




                          56
uso git



   57
potete usare mercurial



          58
oppure niente



      59
io uso git



    60
fatto



  61
$ dotcloud list whatever
whatever:
  - www     (type: perl; instances: 1)
  - nosqldb (type: redis; instances: 1)
  - sqldb   (type: mysql; instances: 1)
  - backend (type: perl-worker; instances: 1)

$ dotcloud url whatever
www: http://www.whatever.dotcloud.com/




                      62
63
$ dotcloud info whatever.backend
build_revision: git-b2f52d5
cluster: wolverine
config: {}
created_at: 1313990084.301964
image_version: b81a3f3949a8 (latest)
ports:
-   name: ssh
    url: ssh://dotcloud@whatever-polettix.dotcloud.com:13750
state: running
type: perl-worker




                             64
telecomando:
dotcloud run


      65
type: mysql
$ dotcloud info whatever.sqldb
cluster: wolverine
config:
    mysql_password: <the-password>
created_at: 1313990083.324873
...

$ dotcloud run whatever.sqldb -- 
    mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ;
or g.
...
mysql> CREATE TABLE weight (...
                         66
troubleshooting?



       67
dotcloud logs
    (Luke!)


      68
$ dotcloud logs whatever.backend
#       tail -F /var/log/supervisor/*.log
==> /var/log/supervisor/exporter-stderr---supervisor-2y6P9O.log <==
[2011/08/27    01:35:25   INFO   ]   serving pending requests if needed...
[2011/08/27    01:35:25   INFO   ]   waiting for more export requests...
[2011/08/27    01:39:20   INFO   ]   serving pending requests if needed...
[2011/08/27    01:39:20   INFO   ]   waiting for more export requests...
[2011/08/27    01:39:42   INFO   ]   got element to export: {"email":"flavio@polettix.it","username":"silvia"}
[2011/08/27    01:42:18   INFO   ]   serving pending requests if needed...
[2011/08/27    01:42:18   INFO   ]   waiting for more export requests...
[2011/08/27    01:42:30   INFO   ]   got element to export: {"email":"flavio@polettix.it","username":"silvia"}
[2011/08/27    09:00:24   INFO   ]   serving pending requests if needed...
[2011/08/27    09:00:24   INFO   ]   waiting for more export requests...


==> /var/log/supervisor/exporter-stdout---supervisor-foI5vi.log <==
==> /var/log/supervisor/saver-stderr---supervisor-pt1_hK.log <==
[2011/08/27    01:35:25   INFO   ]   waiting for more data...
[2011/08/27    01:36:04   INFO   ]   got element to save: {"epoch":1313913600,"weight":83200,"username":"flavio"}
[2011/08/27    01:37:25   INFO   ]   got element to save: {"epoch":1313827200,"weight":62000,"username":"silvia"}
[2011/08/27    01:39:20   INFO   ]   performing initial transfer if needed...
[2011/08/27    01:39:20   INFO   ]   waiting for more data...
[2011/08/27    01:42:18   INFO   ]   performing initial transfer if needed...
[2011/08/27    01:42:18   INFO   ]   waiting for more data...
[2011/08/27    01:44:04   INFO   ]   got element to save: {"epoch":1313913600,"weight":78000,"username":"whatever"}
[2011/08/27    09:00:24   INFO   ]   performing initial transfer if needed...
[2011/08/27    09:00:24   INFO   ]   waiting for more data...


==> /var/log/supervisor/saver-stdout---supervisor-iQDgpA.log <==

==> /var/log/supervisor/supervisord.log <==
2011-08-27    01:42:18,703   INFO     spawned:   'saver' with pid 19587
2011-08-27    01:42:18,713   INFO     spawned:   'exporter' with pid 19588
2011-08-27    01:42:19,914   INFO     success:   saver entered RUNNING state, process has stayed up   for > than 1 seconds (startsecs)
2011-08-27    01:42:19,943   INFO     success:   exporter entered RUNNING state, process has stayed   up for > than 1 seconds (startsecs)
2011-08-27    09:00:22,067   INFO     stopped:   saver (terminated by SIGTERM)
2011-08-27    09:00:22,070   INFO     stopped:   exporter (terminated by SIGTERM)
2011-08-27    09:00:24,079   INFO     spawned:   'saver' with pid 19729
2011-08-27    09:00:24,086   INFO     spawned:   'exporter' with pid 19730
2011-08-27    09:00:25,426   INFO     success:   saver entered RUNNING state, process has stayed up   for > than 1 seconds (startsecs)
2011-08-27    09:00:25,426   INFO     success:   exporter entered RUNNING state, process has stayed   up for > than 1 seconds (startsecs)
                                                                             69
PIÙ troubleshooting?



         70
dotcloud run
   (like hell)


      71
$ dotcloud run whatever.www -- ps afx
# ps afx
  PID TTY     STAT   TIME COMMAND
 3558 ?       S      0:00 sshd: dotcloud@pts/0
 3559 pts/0   Rs+    0:00 _ ps afx
  144 ?       Ss     0:44 /usr/bin/python /usr/
 3495 ?       S      0:00 _ /usr/local/bin/uwsg
 3496 ?       S      0:00      _ /usr/local/bin/




                       72
ANCORA PIÙ
troubleshooting?


       73
dotcloud ssh



     74
dotcloud ssh
 (no root, sorry!)


        75
$ dotcloud ssh whatever.backend
# $SHELL
dotcloud@whatever-default-backend-0:~$

$ dotcloud ssh whatever.nosqldb
# $SHELL
redis@whatever-default-nosqldb-0:~$ redis-cli
redis> auth ...
OK
redis> smembers users
1) "silvia"
2) "flavio"
3) "whatever"

                      76
77
$ git commit
     78
OPPURE



  79
$ dotcloud push --all whatever




               80
$ dotcloud push whatever -b branch




                 81
82
83
È tutto molto triste



         84
85
Account Multipli:
https://github.com/polettix/dotmulti



                 86
87

dotCloud and go

  • 1.
    dotCloud and go UnaBreve Introduzione a DotCloud 1
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
    QUANTO TEMPO CI METTO? 12
  • 13.
  • 14.
  • 15.
    IaaS - PaaS- SaaS 15
  • 16.
    IaaS - PaaS- SaaS 15
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
    Easy Install èun modulo python (easy_install) incluso in setuptools che vi consente di scaricare ed installare automaticamente pacchetti Python. 22
  • 24.
    Easy Install èun modulo python (easy_install) incluso in setuptools che vi consente di scaricare ed installare automaticamente pacchetti Python. 23
  • 25.
  • 26.
    (è il motivoper cui queste slide sono nere) 25
  • 27.
    26 (-:
  • 28.
  • 29.
    28 )-:
  • 30.
    $ dotcloud createwhatever Created application "whatever" 29
  • 31.
  • 32.
    $ cat dotcloud.yml www: type: perl approot: www backend: type: perl-worker approot: backend nosqldb: type: redis sqldb: type: mysql 31
  • 33.
    $ cat dotcloud.yml www: type: perl approot: www backend: type: perl-worker approot: backend nosqldb: type: redis sqldb: type: mysql 32
  • 34.
    $ cat dotcloud.yml www: type: perl approot: www backend: type: perl-worker approot: backend nosqldb: type: redis sqldb: type: mysql 33
  • 35.
  • 36.
    $ cat app.psgi #!/usr/bin/envperl use Dancer; use whatever; dance(); 35
  • 37.
    $ cat Makefile.PL ... PREREQ_PM => { 'Test::More' => 0, 'YAML' => 0, 'Dancer' => 1.3070, 'Plack::Request' => 0, 'Template' => 0, 'JSON' => 0, 'Redis' => 0, ... }, ... 36
  • 38.
  • 39.
    $ cat supervisord.conf [program:exporter] command= perl /home/dotcloud/current/bin/exporter [program:saver] command = perl /home/dotcloud/current/bin/saver 38
  • 40.
    $ cat supervisord.conf [program:exporter] command= perl /home/dotcloud/current/bin/exporter [program:saver] command = perl /home/dotcloud/current/bin/saver 39
  • 41.
    $ cat supervisord.conf [program:exporter] command= perl /home/dotcloud/current/bin/exporter [program:saver] command = perl /home/dotcloud/current/bin/saver 40
  • 42.
    $ cat dotcloud.yml www: type: perl approot: www backend: type: perl-worker approot: backend nosqldb: type: redis sqldb: type: mysql 41
  • 43.
  • 44.
  • 45.
    $ cat /home/dotcloud/environment.yml DOTCLOUD_ENVIRONMENT:default DOTCLOUD_NOSQLDB_REDIS_HOST: whatever-polettix.dotcloud.com DOTCLOUD_NOSQLDB_REDIS_LOGIN: redis DOTCLOUD_NOSQLDB_REDIS_PASSWORD: ... DOTCLOUD_NOSQLDB_REDIS_PORT: '13749' DOTCLOUD_NOSQLDB_REDIS_URL: ... DOTCLOUD_PROJECT: whatever DOTCLOUD_SERVICE_ID: 0 DOTCLOUD_SERVICE_NAME: www DOTCLOUD_SQLDB_MYSQL_HOST: whatever-polettix.dotcloud.com DOTCLOUD_SQLDB_MYSQL_LOGIN: root DOTCLOUD_SQLDB_MYSQL_PASSWORD: ... DOTCLOUD_SQLDB_MYSQL_PORT: '13747' DOTCLOUD_SQLDB_MYSQL_URL: ... 44
  • 46.
    use JSON qw<from_json >; use File::Slurp qw< read_file >; sub get_dotcloud_config { my $filename = shift || '/home/dotcloud/environment.json'; my $config_text = read_file($filename); my $config = from_json($config_text); return $config; } ## end sub get_dotcloud_config 45
  • 47.
    sub get_redis { my $config = get_dotcloud_config(); my ($password, $hostname, $port) = map { $config->{'DOTCLOUD_NOSQLDB_REDIS_' . $_} } qw< PASSWORD HOST PORT >; require Redis; my $redis = Redis->new(server => "$hostname:$port"); $redis->auth($password); return $redis; } 46
  • 48.
    ROTFL sub get_redis { my $config = get_dotcloud_config(); my ($password, $hostname, $port) = map { $config->{'DOTCLOUD_NOSQLDB_REDIS_' . $_} } qw< PASSWORD HOST PORT >; require Redis; my $redis = Redis->new(server => "$hostname:$port"); $redis->auth($password); return $redis; } 47
  • 49.
  • 50.
    sub get_dbh { my $config = get_dotcloud_config(); my ($username, $password, $hostname, $port) = map { $config->{'DOTCLOUD_SQLDB_MYSQL_' . $_} } qw< LOGIN PASSWORD HOST PORT >; require DBI; my $dbh = DBI->connect( "dbi:mysql:host=$hostname;port=$port" . ";database=whatever", $username, $password, { RaiseError => 1}, ); return $dbh; } 49
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
    $ dotcloud pushwhatever # Found dotcloud.yml: Using /home/poletti/sviluppo/ perl/whatever as a base directory # upload /home/poletti/sviluppo/perl/whatever ssh:// dotcloud@uploader.dotcloud.com:443/whatever/ branch:master # git ... 2011-08-27 09:00:16 [api] Deploy whatever scheduled for revision=latest 2011-08-27 09:00:16 [api] Waiting for the build. (It may take a few minutes) 2011-08-27 09:00:17 [api] All the services are ready. Beginning the build. ... 56
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
    $ dotcloud listwhatever whatever: - www (type: perl; instances: 1) - nosqldb (type: redis; instances: 1) - sqldb (type: mysql; instances: 1) - backend (type: perl-worker; instances: 1) $ dotcloud url whatever www: http://www.whatever.dotcloud.com/ 62
  • 64.
  • 65.
    $ dotcloud infowhatever.backend build_revision: git-b2f52d5 cluster: wolverine config: {} created_at: 1313990084.301964 image_version: b81a3f3949a8 (latest) ports: - name: ssh url: ssh://dotcloud@whatever-polettix.dotcloud.com:13750 state: running type: perl-worker 64
  • 66.
  • 67.
    type: mysql $ dotcloudinfo whatever.sqldb cluster: wolverine config: mysql_password: <the-password> created_at: 1313990083.324873 ... $ dotcloud run whatever.sqldb -- mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or g. ... mysql> CREATE TABLE weight (... 66
  • 68.
  • 69.
    dotcloud logs (Luke!) 68
  • 70.
    $ dotcloud logswhatever.backend # tail -F /var/log/supervisor/*.log ==> /var/log/supervisor/exporter-stderr---supervisor-2y6P9O.log <== [2011/08/27 01:35:25 INFO ] serving pending requests if needed... [2011/08/27 01:35:25 INFO ] waiting for more export requests... [2011/08/27 01:39:20 INFO ] serving pending requests if needed... [2011/08/27 01:39:20 INFO ] waiting for more export requests... [2011/08/27 01:39:42 INFO ] got element to export: {"email":"flavio@polettix.it","username":"silvia"} [2011/08/27 01:42:18 INFO ] serving pending requests if needed... [2011/08/27 01:42:18 INFO ] waiting for more export requests... [2011/08/27 01:42:30 INFO ] got element to export: {"email":"flavio@polettix.it","username":"silvia"} [2011/08/27 09:00:24 INFO ] serving pending requests if needed... [2011/08/27 09:00:24 INFO ] waiting for more export requests... ==> /var/log/supervisor/exporter-stdout---supervisor-foI5vi.log <== ==> /var/log/supervisor/saver-stderr---supervisor-pt1_hK.log <== [2011/08/27 01:35:25 INFO ] waiting for more data... [2011/08/27 01:36:04 INFO ] got element to save: {"epoch":1313913600,"weight":83200,"username":"flavio"} [2011/08/27 01:37:25 INFO ] got element to save: {"epoch":1313827200,"weight":62000,"username":"silvia"} [2011/08/27 01:39:20 INFO ] performing initial transfer if needed... [2011/08/27 01:39:20 INFO ] waiting for more data... [2011/08/27 01:42:18 INFO ] performing initial transfer if needed... [2011/08/27 01:42:18 INFO ] waiting for more data... [2011/08/27 01:44:04 INFO ] got element to save: {"epoch":1313913600,"weight":78000,"username":"whatever"} [2011/08/27 09:00:24 INFO ] performing initial transfer if needed... [2011/08/27 09:00:24 INFO ] waiting for more data... ==> /var/log/supervisor/saver-stdout---supervisor-iQDgpA.log <== ==> /var/log/supervisor/supervisord.log <== 2011-08-27 01:42:18,703 INFO spawned: 'saver' with pid 19587 2011-08-27 01:42:18,713 INFO spawned: 'exporter' with pid 19588 2011-08-27 01:42:19,914 INFO success: saver entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2011-08-27 01:42:19,943 INFO success: exporter entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2011-08-27 09:00:22,067 INFO stopped: saver (terminated by SIGTERM) 2011-08-27 09:00:22,070 INFO stopped: exporter (terminated by SIGTERM) 2011-08-27 09:00:24,079 INFO spawned: 'saver' with pid 19729 2011-08-27 09:00:24,086 INFO spawned: 'exporter' with pid 19730 2011-08-27 09:00:25,426 INFO success: saver entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2011-08-27 09:00:25,426 INFO success: exporter entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 69
  • 71.
  • 72.
    dotcloud run (like hell) 71
  • 73.
    $ dotcloud runwhatever.www -- ps afx # ps afx PID TTY STAT TIME COMMAND 3558 ? S 0:00 sshd: dotcloud@pts/0 3559 pts/0 Rs+ 0:00 _ ps afx 144 ? Ss 0:44 /usr/bin/python /usr/ 3495 ? S 0:00 _ /usr/local/bin/uwsg 3496 ? S 0:00 _ /usr/local/bin/ 72
  • 74.
  • 75.
  • 76.
    dotcloud ssh (noroot, sorry!) 75
  • 77.
    $ dotcloud sshwhatever.backend # $SHELL dotcloud@whatever-default-backend-0:~$ $ dotcloud ssh whatever.nosqldb # $SHELL redis@whatever-default-nosqldb-0:~$ redis-cli redis> auth ... OK redis> smembers users 1) "silvia" 2) "flavio" 3) "whatever" 76
  • 78.
  • 79.
  • 80.
  • 81.
    $ dotcloud push--all whatever 80
  • 82.
    $ dotcloud pushwhatever -b branch 81
  • 83.
  • 84.
  • 85.
    È tutto moltotriste 84
  • 86.
  • 87.
  • 88.

Editor's Notes

  • #2 \n
  • #3 &amp;#xC8; utile riferire il contenuto della presentazione ad un esempio di massima... ed in questo caso mi riguarda da vicino!\n
  • #4 Sicuramente non ve ne sarete accorti, ma sono un tantino sovrappeso. L&amp;#x2019;idea &amp;#xE8; quella di un sistema per la registrazione giornaliera del mio peso... quantomeno per vergognarmi a dovere!\n
  • #5 Il sistema &amp;#xE8; costituito da quattro blocchi funzionali separati: un front-end per l&amp;#x2019;interazione con gli utenti, un database &amp;#x201C;no SQL&amp;#x201D; per memorizzare i dati dell&amp;#x2019;ultimo mese, un back-end per le operazioni dietro le quinte ed un database SQL per registrare i dati da qui all&amp;#x2019;eternit&amp;#xE0;. Certo, un&amp;#x2019;architettura un po&amp;#x2019; roboante per registrare una sola misurazione al giorno, ma diciamo che vista la stazza il sistema si potrebbe appesantire rapidamente.\n
  • #6 L&amp;#x2019;interazione dell&amp;#x2019;utente &amp;#xE8; con il Front-End attraverso l&amp;#x2019;utilizzo di un comune browser; il Front-End interagisce a sua volta con il database &amp;#x201C;no SQL&amp;#x201D; (redis in particolare) per sia per visualizzare i dati relativi all&amp;#x2019;ultimo mese che per registrarne di nuovi. In particolare, si pu&amp;#xF2;: visualizzare i dati mensili di ciascun utente, inserire una nuova misura oppure richiedere l&amp;#x2019;export dei dati storici relativi ad un utente (questo export verr&amp;#xE0; spedito via email a cura del Back-End).\n
  • #7 Redis implementa un meccanismo Sottoscrizione/Pubblicazione molto comodo per gestire delle code; il Back-End &amp;#xE8; impostato per ascoltare le notifiche tanto in relazione all&amp;#x2019;inserimento/aggiornamento dei dati di peso di un giorno (per salvarli nel database completo) quanto per ricevere le richieste di export dei dati. In entrambi i casi viene utilizzata una lista per trasferire i dati secondo una gestione a coda, ed il meccanismo di notifica per evitare che il Back-End faccia richieste continue per vedere se ci sono nuovi dati.\n
  • #8 Come conseguenza dell&amp;#x2019;inserimento/aggiornamento di uno o pi&amp;#xF9; dati di peso, il Back-End consuma la coda relativa ai &amp;#x201C;new-weights&amp;#x201D; provvedendo all&amp;#x2019;inserimento nel database MySQL. Una volta terminato si rimette in ascolto aspettando la notifica successiva.\n
  • #9 Analogamente, il Back-End consuma anche la coda di richieste di export dei dati, provvedendo a raccogliere i dati dal database per l&amp;#x2019;utente richiesto, formattarli come file CSV e spedirli via email all&amp;#x2019;indirizzo passato dal Front-End nella richiesta di export.\n
  • #10 I quattro elementi base dell&amp;#x2019;architettura sono stati implementati con tecnologie differenti: Perl/Dancer per il Front-End e Perl &amp;#x201C;semplice&amp;#x201D; per il Back-End, oltre ovviamente ai due database basati su Redis e MySQL.\n
  • #11 Il problema ora &amp;#xE8; che questo marchingegno dovrebbe essere messo da qualche parte a cui posso accedere facilmente ovunque mi trovi...\n
  • #12 ... il che poi non &amp;#xE8; l&amp;#x2019;unico problema, perch&amp;#xE9; dovr&amp;#xF2; anche capire come far&amp;#xF2; a mettere tutti questi elementi differenti...\n
  • #13 ... per non parlare del fatto che tutto questo processo mi richieder&amp;#xE0; plausibilmente una bella fetta di tempo.\n
  • #14 E qui, finalmente, dopo solo 13 slide... arriviamo a dotCloud.\n
  • #15 La homepage &amp;#xE8; piuttosto invitante: sono disponibili tante combinazioni in &amp;#x201C;stack&amp;#x201D; applicativi differenti in una piattaforma di controllo e gestione unica, il che sembra l&amp;#x2019;ideale per ospitare la nostra applicazione che &amp;#xE8; basata su quattro elementi differenti fra loro. Fortunatamente - altrimenti questa presentazione avrebbe avuto seri problemi - questi quattro elementi che abbiamo scelto sono tutti supportati.\n
  • #16 Di cloud c&amp;#x2019;&amp;#xE8; molto da parlare, soprattutto perch&amp;#xE9; dopo il calcio sembra un argomento in cui ognuno ha una sua idea. All&amp;#x2019;interno della tassonomia pi&amp;#xF9; classica - l&amp;#x2019;Infrastruttura come Servizio, la Piattaforma come Servizio, il Software come Servizio - dotCloud si colloca decisamente come un un fornitore di Piattaforma, ossia strizza l&amp;#x2019;occhio allo sviluppatore dandogli un ambiente che NON deve gestire a pi&amp;#xF9; basso livello (come sarebbe successo con IaaS, ad esempio Amazon EC2 o Rackspace Servers) ma che gli consente di implementare la propria applicazione, non di utilizzarne una gi&amp;#xE0; costruita (come avviene tipicamente con SaaS).\n
  • #17 Di cloud c&amp;#x2019;&amp;#xE8; molto da parlare, soprattutto perch&amp;#xE9; dopo il calcio sembra un argomento in cui ognuno ha una sua idea. All&amp;#x2019;interno della tassonomia pi&amp;#xF9; classica - l&amp;#x2019;Infrastruttura come Servizio, la Piattaforma come Servizio, il Software come Servizio - dotCloud si colloca decisamente come un un fornitore di Piattaforma, ossia strizza l&amp;#x2019;occhio allo sviluppatore dandogli un ambiente che NON deve gestire a pi&amp;#xF9; basso livello (come sarebbe successo con IaaS, ad esempio Amazon EC2 o Rackspace Servers) ma che gli consente di implementare la propria applicazione, non di utilizzarne una gi&amp;#xE0; costruita (come avviene tipicamente con SaaS).\n
  • #18 Non rimane che iscriversi, tanto &amp;#xE8; gratuito...\n
  • #19 ... anche se dovrete riempire un po&amp;#x2019; di scartoffie digitali.\n
  • #20 Se avete un account, potete entrare e trovare la roboante &amp;#x201C;dashboard&amp;#x201D; di ingresso...\n
  • #21 ... ossia una pagina piuttosto anonima che vi invita ad installare il programma di controllo a linea di comando. Questa pagina dovr&amp;#xE0; cambiare, spero non sia avvenuto prima di questo talk!\n
  • #22 Lo strumento principale di interazione con dotCloud &amp;#xE8; - secondo il principio della minima sorpresa - un programma che si chiama dotcloud.\n
  • #23 Installarlo dovrebbe essere piuttosto semplice, visto che il modo consigliato per farlo &amp;#xE8; utilizzare un altro programma chiamato &amp;#x201C;easy_install&amp;#x201D;. Diciamo che quanto a marketing siamo sulla strada giusta... ma il marketing non basta.\n
  • #24 \n
  • #25 \n
  • #26 \n
  • #27 \n
  • #28 \n
  • #29 Non ostante easy_install sia supportato anche da versioni precedenti di Python, per utilizzare dotcloud (il programma) &amp;#xE8; necessario avere Python 2.7 almeno, ma non Python 3.\n
  • #30 Questo pu&amp;#xF2; essere un problema per parecchi, perch&amp;#xE9; se siete dei nostalgici come me starete utilizzando una distribuzione che probabilmente ancora non include questa versione di Python. A me &amp;#xE8; toccato installarlo a mano. Dunque easy_install &amp;#xE8; un ottimo gestore... il problema &amp;#xE8; tutto quello su cui poggia! Sarebbe stato bello avere pythonbrew... o quantomeno sapere se c&amp;#x2019;erano alternative.\n
  • #31 Siamo pronti per creare la nostra prima applicazione. Il principio della minima sorpresa continua a spadroneggiare, perch&amp;#xE9; basta lanciare il sottocomando &amp;#x201C;create&amp;#x201D; dando il nome della nostra applicazione.\n
  • #32 L&amp;#x2019;applicazione, in particolare, &amp;#xE8; stata organizzata in una struttura come quella in figura: il Front-End ha una sua directory &amp;#x201C;www&amp;#x201D;, il Back-End una sua &amp;#x201C;backend&amp;#x201D;. Oltre a queste due cartelle si nota la presenza di un file di configurazione YAML il cui nome lascia sospettare la sua destinazione.\n
  • #33 Il file &amp;#xE8; in effetti quanto verr&amp;#xE0; utilizzato per costruire il nostro stack applicativo.\n
  • #34 In particolare possiamo riconoscere, a livello pi&amp;#xF9; elevato, i differenti servizi necessari per realizzare la nostra applicazione. Per ciascun servizio viene specificato il &amp;#x201C;type&amp;#x201D;, ossia &amp;#x201C;perl&amp;#x201D; per applicazioni di Front-End web, &amp;#x201C;perl-worker&amp;#x201D; per applicazioni di Back-End in Perl, redis e mysql per i due tipi di database.\n
  • #35 Nel file specifichiamo anche che le directory di base per Front-End e Back-End sono separate, in modo che possiamo avere una struttura pulita. DotCloud sapr&amp;#xE0; quindi che nelle macchine dove verr&amp;#xE0; realizzato il Front-End la directory di riferimento sar&amp;#xE0; &amp;#x201C;www&amp;#x201D;, mentre in quelle del Back-End sar&amp;#xE0; &amp;#x201C;backend&amp;#x201D;.\n
  • #36 Il tipo di servizio &amp;#x201C;perl&amp;#x201D; &amp;#xE8; orientato alla realizzazione di Front-End di tipo web basati, per l&amp;#x2019;appunto, su Perl. Il modello di riferimento in questo caso &amp;#xE8; quello dell&amp;#x2019;interfaccia PSGI, che costituisce un porting piuttosto felice nel mondo Perl di idee nate in ambito Ruby/Python. Non ostante la directory abbia vari elementi, quelli realmente interessanti per dotCloud sono due: app.psgi e Makefile.PL.\n
  • #37 app.psgi, in particolare, &amp;#xE8; l&amp;#x2019;applicazione web vera e propria. Deve SEMPRE esistere in un servizio dotCloud di tipo &amp;#x201C;perl&amp;#x201D;. Nel caso specifico si &amp;#xE8; utilizzato il framework Dancer, molto comodo e costruito in modo da rispettare l&amp;#x2019;interfaccia PSGI. Come si potr&amp;#xE0; intuire, la vera &amp;#x201C;ciccia&amp;#x201D; dell&amp;#x2019;applicazione si trova all&amp;#x2019;interno del modulo &amp;#x201C;whatever&amp;#x201D;, che - l&amp;#x2019;avrete gi&amp;#xE0; indovinato - &amp;#xE8; nella directory lib. In realt&amp;#xE0; qui per&amp;#xF2; pu&amp;#xF2; esserci qualunque cosa che possa essere considerata aderente alle specifice PSGI.\n
  • #38 L&amp;#x2019;altro file molto importante - per quanto tecnicamente non obbligatorio - &amp;#xE8; Makefile.PL. Va generato in maniera analoga a quanto si farebbe per una distribuzione su CPAN; come in quel caso, quindi, &amp;#xE8; utile perch&amp;#xE9; contiene una sezione PREREQ_PM dove possiamo andare ad inserire tutti i prerequisiti della nostra applicazione web.\n
  • #39 La tipologia di servizio &amp;#x201C;perl-worker&amp;#x201D; &amp;#xE8; anch&amp;#x2019;essa basata su Perl, ma &amp;#xE8; orientata all&amp;#x2019;esecuzione di programmi di lunga durata (demoni). Anche in questo caso il file Makefile.PL pu&amp;#xF2;/deve essere utilizzato per specificare i requisiti in termini di moduli da installare, altrimenti il perl che avremo a disposizione non ci permetter&amp;#xE0; di lavorare.\n
  • #40 Il file pi&amp;#xF9; peculiare in questo caso &amp;#xE8; per&amp;#xF2; supervisord.conf, che non &amp;#xE8; altro che il file di configurazione del progamma supervisord. Tramite questo file possiamo specificare quanti programmi devono essere eseguiti contemporanemente e monitorati per controllare che vengano tenuti in esecuzione. Ovviamente potrete soddisfare ogni vostra curiosit&amp;#xE0; su http://supervisord.org/; nel caso in questione, basta notare che per ciascun demone c&amp;#x2019;&amp;#xE8; un titolo con il nome da dare ed una riga &amp;#x201C;command&amp;#x201D; dove specifichiamo cosa va eseguito.\n
  • #41 Avrete sicuramente fatto caso che nella specifica dei comandi compaiono dei percorsi piuttosto curiosi. Ebbene s&amp;#xEC;, poich&amp;#xE9; questi programmi verranno eseguiti su delle macchine... queste macchine hanno un filesystem ed i vostri programmi del Back-End li troverete proprio l&amp;#xEC;!\n
  • #42 In particolare, quando la vostra applicazione viene distribuita, all&amp;#x2019;interno della macchina del Back-End (nel Front-End &amp;#xE8; analogo) viene creata una directory con la directory base che ha un nome non anticipabile. Il sistema di dotCloud, per&amp;#xF2;, vi garantisce che verr&amp;#xE0; anche creato un link simbolico che da /home/dotcloud/current punta verso la directory principale del servizio.\n
  • #43 In poche parole, /home/dotcloud/current non fa altro che puntare a quella sottodirectory che abbiamo specificato come &amp;#x201C;approot&amp;#x201D; nel file di configurazione dotcloud.yml.\n
  • #44 Abbiamo capito cosa succede a Front-End e Back-End... ma per i database che succede? In realt&amp;#xE0; vengono create delle macchine virtuali &amp;#x201C;speciali&amp;#x201D; anche in quel caso - la specialit&amp;#xE0; risiede nel fatto che le macchine di tipo &amp;#x201C;redis&amp;#x201D; contengono il server ed il client Redis e quelle di tipo MySQL... lo avrete gi&amp;#xE0; indovinato.\nIl problema per&amp;#xF2; &amp;#xE8;: come ci si connette a questi due database? Dove stanno, soprattutto?\n
  • #45 Per rispondere a queste domande dobbiamo tornare alla struttura delle directory che ci troviamo nelle macchine del Front-End e del Back-End. Abbiamo gi&amp;#xE0; detto che /home/dotcloud/current punta alla directory specificata come approot per ciascuna applicazione, ma nella directory /home/dotcloud ci sono altri due file interessanti: environment.yml (in formato YAML) ed environment.json (in formato JSON).\n
  • #46 Molto prosaicamente, questi due file contengono entrambi le informazioni necessarie per raggiungere i servizi dati del nostro stack, includendo cio&amp;#xE8; gli indirizzi di dove si trovano, su quale porta sono in ascolto e quali sono le credenziali di accesso.\n
  • #47 A questo punto, a seconda che ci piaccia di pi&amp;#xF9; JSON o YAML, &amp;#xE8; facile scrivere una routine che va a leggere il file di configurazione giusto per caricare le differenti variabili che ci servono per la connessione.\n
  • #48 Per Redis avremo bisogno della password e dei dettagli sulla connessione, ossia il nome della macchina su cui &amp;#xE8; ospitato il nostro servizio e la porta. Nel restituire un oggetto Redis facciamo anche un favore all&amp;#x2019;utente e &amp;#x201C;sblocchiamo&amp;#x201D; la connessione inviando la password.\n
  • #49 Incidentalmente, &amp;#x201C;get_redis&amp;#x201D; fa ridere. Beh, almeno MI fa ridere.\n
  • #50 \n
  • #51 Per la connessione MySQL il discorso &amp;#xE8; analogo: basta andare a prendere le variabili giuste dalla configurazione caricata e creare l&amp;#x2019;oggetto utilizzando il modulo DBI. Il resto &amp;#xE8; roba standard.\n
  • #52 Questo codice &amp;#xE8; in realt&amp;#xE0; utile tanto al Front-End quanto al Back-End... dove collocarlo? Occorre duplicare?\n
  • #53 L&amp;#x2019;aspetto interessante &amp;#xE8; che sia l&amp;#x2019;istanza di Front-End che quella di Back-End contengono in realt&amp;#xE0; tutto il codice, ossia anche quello dell&amp;#x2019;altra istanza. Analogamente a quanto succede con /home/dotcloud/current (che punta alla appdir impostata nel file dotcloud.yml), l&amp;#x2019;infrastruttura di dotCloud crea anche un link simbolico che da /home/dotcloud/code punta alla directory principale della distribuzione.\n
  • #54 Con questi presupposti, dunque, la soluzione pi&amp;#xF9; semplice &amp;#xE8; quella di aggiungere un&amp;#x2019;area comune a cui i vari servizi possono attingere.\n
  • #55 Nel caso specifico, per&amp;#xF2;, c&amp;#x2019;&amp;#xE8; un modulo su CPAN che serve proprio a questo scopo...\n
  • #56 ... ma non ne parleremo oltre, visto che si tratta di autopromozione!\n
  • #57 \n
  • #58 Per andare in produzione &amp;#xE8; sufficiente &amp;#x201C;spingere&amp;#x201D; la nostra applicazione su dotcloud. La prima volta verranno normalmente inizializzati gli ambienti caricando i vari moduli impostati nei prerequisiti, quindi ci metter&amp;#xE0; un po&amp;#x2019; di tempo; successivamente dovrebbe essere pi&amp;#xF9; rapido, a meno di non aggiungere svariati altri prerequisiti.\n
  • #59 Nel caso dell&amp;#x2019;esempio io utilizzo git, per cui dotcloud &amp;#x201C;sa cosa fare&amp;#x201D; e prende i file da git. Questo &amp;#xE8; un punto su cui occorre fare attenzione, perch&amp;#xE9; per default va a prendere il ramo &amp;#x201C;master&amp;#x201D; e non &amp;#xE8; detto che sia quello su cui state lavorando o che sia quello che volete effettivamente attivare su dotCloud.\n
  • #60 Se utilizzate mercurial il comportamento &amp;#xE8; analogo.\n
  • #61 In alternativa potete non utilizzare nessuno dei due, nel qual caso il meccanismo di invio scelto da dotcloud sar&amp;#xE0; rsync.\n
  • #62 \n
  • #63 Nel tempo di questa breve digressione il caricamento dell&amp;#x2019;applicazione dovrebbe essere terminato.\n
  • #64 Il programma dotcloud mette a disposizione vari comandi; in questa fase, &amp;#xE8; utile vedere cosa sia stato effettivamente creato per la nostra applicazione - ossia il nostro &amp;#x201C;stack&amp;#x201D; - e dove sia possibile raggiungerla con il browser.\nIl comando list, nell&amp;#x2019;esempio, riporta una cosa interessante: per ciascun servizio &amp;#xE8; stata attiva un&amp;#x2019;istanza. Queste istanze altro non sono che macchine virtuali attivate nella nuvola di Amazon EC2.\n
  • #65 Certo, la grafica lascia a desiderare... ma ad occhio e croce il Front-End funziona visto che riporta anche un elenco degli utenti presenti ed un paio di registrazioni.\n
  • #66 Il comando &amp;#x201C;info&amp;#x201D; &amp;#xE8; molto utile per avere informazioni generali sui vari servizi. Avrete notato che il nome dei servizi &amp;#xE8; composto dal nome dell&amp;#x2019;applicazione, un punto e poi il nome del servizio vero e proprio all&amp;#x2019;interno dell&amp;#x2019;applicazione. In questo modo potete avere dei servizi &amp;#x201C;backend&amp;#x201D; in tutte le applicazioni, senza che questi si disturbino fra loro.\n
  • #67 \n
  • #68 Il comando run torna immediatamente utile perch&amp;#xE9; c&amp;#x2019;&amp;#xE8; un&amp;#x2019;ultima cosa che &amp;#xE8; stata lasciata in sospeso nelle basi dati. Con Redis non c&amp;#x2019;&amp;#xE8; bisogno di inizializzazione perch&amp;#xE9; sostanzialmente &amp;#x201C;autovivifica&amp;#x201D;, ma con MySQL occorre definire una tabella, altrimenti &amp;#xE8; difficile scriverci qualcosa.\nUtilizzando il comando info possiamo vedere la password - analogamente potremmo entrare nel Front-End o nel Back-End e leggerla dentro il file environment.*, ma a che pro se esiste un comando apposito?\nCon il comando run possiamo invece lanciare qualsiasi comando remoto; in questo caso, dunque, lanciamo il client di mysql per poter definire la tabella dove il Back-End salva i dati. Certo, certo: alla creazione della tabella potrebbe provvedere il Back-End stesso, ma poi come mostravo il comando run?\n
  • #69 Ovviamente nessuno di noi pensa che andr&amp;#xE0; liscia al primo tentativo. Nemmeno nei 100 successivi, per la verit&amp;#xE0;.\n
  • #70 Il primo santo a cui votarsi &amp;#xE8; il comando logs, che ci consente di vedere i log specifici di ciascun servizio.\n
  • #71 Nel Back-End, ad esempio, d&amp;#xE0; una visione contemporanea di tutti i file nella directory /var/log/supervisor/, ossia dei log dei nostri programmi pi&amp;#xF9; il log del supervisord stesso. Potete decidere di salvare i log da qualche altra parte, ma &amp;#xE8; particolarmente comodo utilizzare STDERR e lasciare che vengano messi in un posto dove possono essere raccolti facilmente con il comando logs.\n
  • #72 Che fare se i log non bastano? A parte la consueta chiodata, ovviamente?\n
  • #73 Beh, il comando run pu&amp;#xF2; tornare utile anche in questa occasione.\n
  • #74 In particolare, tramite run possiamo eseguire comandi nell&amp;#x2019;istanza remota, quindi &amp;#xE8; un po&amp;#x2019; come avere una shell a disposizione. Magari un po&amp;#x2019; lenta, visto che si dove riconnettere ad ogni comando.\n
  • #75 Che fare quindi se vogliamo andare oltre?!?\n
  • #76 Beh, non rimane che entrare da terminale sull&amp;#x2019;istanza che ospita il servizio che fa le bizze.\n
  • #77 No, l&amp;#x2019;accesso come root non &amp;#xE8; contemplato.\n
  • #78 A seconda dell&amp;#x2019;istanza troveremo ovviamente un ambiente differente con programmi differenti a disposizione. Ad esempio, redis-cli &amp;#xE8; disponibile nell&amp;#x2019;istanza di tipo &amp;#x201C;redis&amp;#x201D; ma non nell&amp;#x2019;istanza del backend - anche se avrebbe fatto comodo.\n
  • #79 Trovo che Pitfall! fosse un gioco stupendo, ma occorre stare attenti a non cadere!\n
  • #80 Una delle noie maggiori che ho trovato &amp;#xE8; il fatto che occorre sempre fare &amp;#x201C;git commit&amp;#x201D; prima di effettuare il push, altrimenti dotcloud non prende le modifiche nella directory di lavoro. Stiamo ovviamente parlando del caso in cui venga utilizzato git.\n
  • #81 \n
  • #82 Un&amp;#x2019;alternativa molto rapida e molto comoda quando si stanno facendo prove &amp;#xE8; utilizzare &amp;#x201C;--all&amp;#x201D;. In questo modo viene ignorato il meccanismo di base della distribuzione e viene sempre utilizzato rsync.\n
  • #83 L&amp;#x2019;altro aspetto a cui prestare attenzione &amp;#xE8; che il push normalmente prende il ramo &amp;#x201C;master&amp;#x201D;, per cui se si lavora ad un altro ramo occorre ricordarsi di includere il nome del ramo giusto. Questa la trovo una mancanza, poich&amp;#xE9; &amp;#xE8; semplice sapere quale sia il ramo attivo di una directory di lavoro; probabilmente per&amp;#xF2; per chi ci lavora &amp;#x201C;sul serio&amp;#x201D; &amp;#xE8; un meccanismo di protezione, per cui non borbotter&amp;#xF2; oltre.\n
  • #84 Dopo averci dato tanta libert&amp;#xE0;... purtroppo dotCloud ha posto anche delle restrizioni.\n
  • #85 Da poco tempo &amp;#xE8; infatti uscito il prezziario. &amp;#xC8; proprio vero che una volta si stava meglio: se si entrava nella beta, infatti, si poteva giocare molto. Ora sembra che il piano gratuito consenta di avere al massimo due servizi... che fine far&amp;#xE0; il mio carrozzone che ne ha quattro?\n
  • #86 \n
  • #87 Certo, si pu&amp;#xF2; sempre barare...\n
  • #88 ... ad esempio creando account multipli ed utilizzando un servizio di directory centralizzato dove vengono salvate le configurazioni di tutte le applicazioni (i file &amp;#x201C;environment.*&amp;#x201D; per intenderci). Un esempio di una directory di questo tipo &amp;#xE8; nel link nella slide e - senza nemmeno dirlo - l&amp;#x2019;applicazione &amp;#xE8; fatta per girare su dotcloud utilizzando due servizi.\n
  • #89 \n