SlideShare a Scribd company logo
OR:


fog
       HOW I
      LEARNED
      TO STOP
      WORRYING
       AND
      LOVE THE

      CLOUD
geemus (Wesley Beary)
web: github.com/geemus
twitter: @geemus
employer and sponsor
web: engineyard.com
twitter: @engineyard
API driven on demand services

CLOUD   core: compute, dns, storage
        also: kvs, load balance, ...
What?
What?
on demand -   only pay for what you actually use
What?
on demand -       only pay for what you actually use

flexible -   add and remove resources in minutes (instead of weeks)
What?
on demand -       only pay for what you actually use

flexible -   add and remove resources in minutes (instead of weeks)

repeatable -      code, test, repeat
What?
on demand -         only pay for what you actually use

flexible -     add and remove resources in minutes (instead of weeks)

repeatable -        code, test, repeat

resilient -   build better systems with transient resources
Why Worry?
Why Worry?
option overload -   which provider/service should I use
Why Worry?
option overload -        which provider/service should I use

expertise -   each service has yet another knowledge silo
Why Worry?
option overload -             which provider/service should I use

expertise -       each service has yet another knowledge silo

tools -   vastly different API, quality, maintenance, etc
Why Worry?
option overload -             which provider/service should I use

expertise -       each service has yet another knowledge silo

tools -   vastly different API, quality, maintenance, etc

standards -        slow progress and differing interpretations
Ruby cloud services
web: github.com/geemus/fog
twitter: @fog
Why?
Why?
portable -   AWS, Bluebox, Brightbox, Google, Rackspace, Slicehost, Terremark, ...
Why?
portable -   AWS, Bluebox, Brightbox, Google, Rackspace, Slicehost, Terremark, ...

powerful -   compute, dns, storage, collections, models, mocks, requests, ...
Why?
portable -   AWS, Bluebox, Brightbox, Google, Rackspace, Slicehost, Terremark, ...

powerful -   compute, dns, storage, collections, models, mocks, requests, ...

established -    250k downloads, 1564 followers, 266 forks, 127 contributors, me, ...
Why?
portable -   AWS, Bluebox, Brightbox, Google, Rackspace, Slicehost, Terremark, ...

powerful -   compute, dns, storage, collections, models, mocks, requests, ...

established -    250k downloads, 1564 followers, 266 forks, 127 contributors, me, ...

Fog.mock! -     faster, cheaper, simulated cloud behavior
Who?
Who?
libraries -   carrierwave, chef, gemcutter, puppet, ...

products -    AppFog, Engine Yard, Heroku, ...
Interactive Bit!
Interactive Bit!
      cloud
Interactive Bit!
      cloud
       fog
What?
What?
That’s great and all but   I don’t have a use case...
What?
That’s great and all but   I don’t have a use case...
uptime -       because who wants a busted web site?
Setup
  geymus ~ ⌘ gem install fog
              or
geymus ~ ⌘ sudo gem install fog
Get Connected



7 # setup a connection to the service
8 compute = Fog::Compute.new(credentials)
Get Connected
1   credentials = {
2     :provider           => 'Rackspace',
3     :rackspace_api_key  => RACKSPACE_API_KEY,
4     :rackspace_username => RACKSPACE_USERNAME
5   }
6
7 # setup a connection to the service
8 compute = Fog::Compute.new(credentials)
Boot that Server
 1   server_data = compute.create_server(
 2     1,
 3     49
 4   ).body['server']
 5
Boot that Server
 1   server_data = compute.create_server(
 2     1,
 3     49
 4   ).body['server']
 5
 6    until compute.get_server_details(
 7      server_data['id']
 8    ).body['server']['status'] == 'ACTIVE'
 9    end
10
Boot that Server
 1   server_data = compute.create_server(
 2     1,
 3     49
 4   ).body['server']
 5

 6      until compute.get_server_details(
 7        server_data['id']
 8      ).body['server']['status'] == 'ACTIVE'
 9      end
10
11         commands = [
12           %{'mkdir .ssh'},
13           %{'echo #{File.read('~/.ssh/id_rsa.pub')} >> ~/.ssh/authorized_keys'},
14           %{passwd -l root},
15         ]
16
17         Net::SSH.start(
18           server_data['addresses'].first,
19           'root',
20           :password => server_data['password']
21         ) do |ssh|
22           commands.each do |command|
23             ssh.open_channel do |ssh_channel|
24               ssh_channel.request_pty
25               ssh_channel.exec(%{bash -lc '#{command}'})
26               ssh.loop
27             end
28           end
29         end
Worry!
Worry!
arguments -   what goes where, what does it mean?
Worry!
arguments -     what goes where, what does it mean?

portability -   most of this will only work on Rackspace
Worry!
arguments -      what goes where, what does it mean?

portability -   most of this will only work on Rackspace

disservice -    back to square one, but with tools in hand
Bootstrap



7 # boot server and setup ssh keys
8 server = compute.servers.bootstrap(server_attributes)
Bootstrap
1   server_attributes = {
2     :image_id         => '49',
3     :private_key_path => PRIVATE_KEY_PATH,
4     :public_key_path  => PUBLIC_KEY_PATH
5   }
6
7 # boot server and setup ssh keys
8 server = compute.servers.bootstrap(server_attributes)
Servers?
Servers?
1 compute.servers # list servers, same as #all
Servers?
1 compute.servers # list servers, same as #all
2
3 compute.servers.get(1234567890) # server by id
Servers?
1 compute.servers # list servers, same as #all
2
3 compute.servers.get(1234567890) # server by id
4
5 compute.servers.reload # update to latest
Servers?
1   compute.servers # list servers, same as #all
2
3   compute.servers.get(1234567890) # server by id
4
5   compute.servers.reload # update to latest
6
7   compute.servers.new(attributes) # local model
Servers?
1   compute.servers # list servers, same as #all
2
3   compute.servers.get(1234567890) # server by id
4
5   compute.servers.reload # update to latest
6
7   compute.servers.new(attributes) # local model
8
9   compute.servers.create(attributes) # remote model
ping
ping
1 # ping target 10 times
2 ssh_results = server.ssh("ping -c 10 #{target}")
ping
1 # ping target 10 times
2 ssh_results = server.ssh("ping -c 10 #{target}")
3 stdout = ssh_results.first.stdout
ping
1   # ping target 10 times
2   ssh_results = server.ssh("ping -c 10 #{target}")
3   stdout = ssh_results.first.stdout
4
5   # parse result, last line is summary
6   # round-trip min/avg/max/stddev = A.A/B.B/C.C/D.D ms
ping
1   # ping target 10 times
2   ssh_results = server.ssh("ping -c 10 #{target}")
3   stdout = ssh_results.first.stdout
4
5   # parse result, last line is summary
6   # round-trip min/avg/max/stddev = A.A/B.B/C.C/D.D ms
7   stats = stdout.split("/n").last.split(' ')[-2]
8   min, avg, max, stddev = stats.split('/')
ping
1   # ping target 10 times
2   ssh_results = server.ssh("ping -c 10 #{target}")
3   stdout = ssh_results.first.stdout
4
5   # parse result, last line is summary
6   # round-trip min/avg/max/stddev = A.A/B.B/C.C/D.D ms
7   stats = stdout.split("/n").last.split(' ')[-2]
8   min, avg, max, stddev = stats.split('/')

          NOTE: most complex code was string parsing!?!
cleanup
cleanup
 1 # shutdown the server
 2 server.destroy
cleanup
 1 # shutdown the server
 2 server.destroy
 3
 4 # return the data as a hash
 5 {
 6   :min    => min,
 7   :avg    => avg,
 8   :max    => max,
 9   :stddev => stddev
10 }
Next!
Next!
 1   -server_data = compute.create_server(
 2   +compute.import_key_pair(
 3   +  'id_rsa.pub',
 4   +  File.read('~/.ssh/id_rsa.pub')
 5   +)
 6   +
 7   +compute.authorize_security_group_ingress(
 8   +  'CidrIp'      => '0.0.0.0/0',
 9   +  'FromPort'    => 22,
10   +  'IpProtocol'  => 'tcp',
11   +  'GroupName'   => 'default',
12   +  'ToPort'      => 22
13   +)
14   +
15   +server_data = compute.run_instances(
16   +  'ami-1a837773',
17      1,
18   -  49
19   -).body['server']
20   +  1,
21   +  'InstanceType'  => 'm1.small',
22   +  'KeyName'       => 'id_rsa.pub',
23   +  'SecurityGroup' => 'default'
24   +).body['instancesSet'].first
25    
26   -until compute.get_server_details(
27   -  server_data['id']
28   -).body['server']['status'] == 'ACTIVE'
29   +until compute.describe_instances(
30   +  'instance-id' => server_data['instanceId']
31   +).body['reservationSet'].first['instancesSet'].first['instanceState']['name'] == 'running'
32    end
33    
34   +sleep(300)
35   +
36    Net::SSH.start(
37   -  server_data['addresses'].first,
38   -  'root',
39   -  :password => server_data['password']
40   +  server_data['ipAddress'],
41   +  'ubuntu',
42   +  :key_data => [File.read('~/.ssh/id_rsa')]
43    ) do |ssh|
44      commands = [
45        %{'mkdir .ssh'},
Next!
 1   -server_data = compute.create_server(
 2   +compute.import_key_pair(
 3   +  'id_rsa.pub',
 4   +  File.read('~/.ssh/id_rsa.pub')
 5   +)
 6   +
 7   +compute.authorize_security_group_ingress(
 8   +  'CidrIp'      => '0.0.0.0/0',
 9   +  'FromPort'    => 22,
10   +  'IpProtocol'  => 'tcp',
11   +  'GroupName'   => 'default',
12   +  'ToPort'      => 22
13   +)
14   +
15   +server_data = compute.run_instances(
16   +  'ami-1a837773',
17      1,
18   -  49
19   -).body['server']
20   +  1,
21   +  'InstanceType'  => 'm1.small',
22   +  'KeyName'       => 'id_rsa.pub',
23   +  'SecurityGroup' => 'default'
24   +).body['instancesSet'].first
25    
26   -until compute.get_server_details(
27   -  server_data['id']
28   -).body['server']['status'] == 'ACTIVE'
29   +until compute.describe_instances(
30   +  'instance-id' => server_data['instanceId']
31   +).body['reservationSet'].first['instancesSet'].first['instanceState']['name'] == 'running'
32    end
33    
34   +sleep(300)
35   +
36    Net::SSH.start(
37   -  server_data['addresses'].first,
38   -  'root',
39   -  :password => server_data['password']
40   +  server_data['ipAddress'],
41   +  'ubuntu',
42   +  :key_data => [File.read('~/.ssh/id_rsa')]
43    ) do |ssh|
44      commands = [
45        %{'mkdir .ssh'},
geopinging v1
 1 # specify a different provider
 2 credentials = {
 3   :provider           => 'AWS',
 4   :aws_access_key_id  => AWS_ACCESS_KEY_ID,
 5   :aws_secret_access_key => AWS_SECRET_ACCESS_KEY
 6 }
 7
 8 server_attributes = {
 9   :image_id         => 'ami-1a837773',
10   :private_key_path => PRIVATE_KEY_PATH,
11   :public_key_path  => PUBLIC_KEY_PATH,
12   :username         => 'ubuntu'
13 }
geopinging v2
1   # specify a different aws region
2   # ['ap-southeast-1', 'eu-west-1', 'us-west-1]
3   credentials.merge!({
4     :region => 'eu-west-1'
5   })
geopinging v...
portable -   AWS, Bluebox, Brightbox, Rackspace, Slicehost, Terremark, ...
geopinging v...
portable -   AWS, Bluebox, Brightbox, Rackspace, Slicehost, Terremark, ...

                 lather, rinse, repeat
How?
That is awesome, but   how did you...
exploring
geymus ~ ⌘ fog

  To run as 'default', add the following to ~/.fog

:default:
  :aws_access_key_id:     INTENTIONALLY_LEFT_BLANK
  :aws_secret_access_key: INTENTIONALLY_LEFT_BLANK
  :public_key_path:       INTENTIONALLY_LEFT_BLANK
  :private_key_path:      INTENTIONALLY_LEFT_BLANK
  :rackspace_api_key:     INTENTIONALLY_LEFT_BLANK
  :rackspace_username:    INTENTIONALLY_LEFT_BLANK
  ...
sign posts
sign posts
geymus ~ ⌘ fog
sign posts
geymus ~ ⌘ fog
 Welcome to fog interactive!
 :default credentials provide AWS and Rackspace
sign posts
geymus ~ ⌘ fog
 Welcome to fog interactive!
 :default credentials provide AWS and Rackspace
>> providers
sign posts
geymus ~ ⌘ fog
 Welcome to fog interactive!
 :default credentials provide AWS and Rackspace
>> providers
[AWS, Rackspace]
sign posts
geymus ~ ⌘ fog
 Welcome to fog interactive!
 :default credentials provide AWS and Rackspace
>> providers
[AWS, Rackspace]
>> Rackspace.collections
sign posts
geymus ~ ⌘ fog
  Welcome to fog interactive!
  :default credentials provide AWS and Rackspace
>> providers
[AWS, Rackspace]
>> Rackspace.collections
[:directories, :files, :flavors, :images, :servers]
sign posts
geymus ~ ⌘ fog
  Welcome to fog interactive!
  :default credentials provide AWS and Rackspace
>> providers
[AWS, Rackspace]
>> Rackspace.collections
[:directories, :files, :flavors, :images, :servers]
>> Compute[:rackspace]
sign posts
geymus ~ ⌘ fog
  Welcome to fog interactive!
  :default credentials provide AWS and Rackspace
>> providers
[AWS, Rackspace]
>> Rackspace.collections
[:directories, :files, :flavors, :images, :servers]
>> Compute[:rackspace]
#<Fog::Compute::Rackspace ...>
sign posts
geymus ~ ⌘ fog
  Welcome to fog interactive!
  :default credentials provide AWS and Rackspace
>> providers
[AWS, Rackspace]
>> Rackspace.collections
[:directories, :files, :flavors, :images, :servers]
>> Compute[:rackspace]
#<Fog::Compute::Rackspace ...>
>> Compute[:rackspace].requests
sign posts
geymus ~ ⌘ fog
  Welcome to fog interactive!
  :default credentials provide AWS and Rackspace
>> providers
[AWS, Rackspace]
>> Rackspace.collections
[:directories, :files, :flavors, :images, :servers]
>> Compute[:rackspace]
#<Fog::Compute::Rackspace ...>
>> Compute[:rackspace].requests
[:confirm_resized_server, ..., :update_server]
what are those?
what are those?
provider   => [AWS, Rackspace, Zerigo, ...]
what are those?
provider   => [AWS, Rackspace, Zerigo, ...]

 service   => [Compute, DNS, Storage, ...]
what are those?
 provider    => [AWS, Rackspace, Zerigo, ...]

  service    => [Compute, DNS, Storage, ...]

collection   => [flavors, images, servers, ...]
what are those?
 provider    => [AWS, Rackspace, Zerigo, ...]

  service    => [Compute, DNS, Storage, ...]

collection   => [flavors, images, servers, ...]

   model     => [flavor, image, server, ...]
what are those?
 provider    => [AWS, Rackspace, Zerigo, ...]

  service    => [Compute, DNS, Storage, ...]

collection   => [flavors, images, servers, ...]

   model     => [flavor, image, server, ...]

  request    => [describe_instances, run_instances, ...]
requests?
requests?
>> Compute[:rackspace].list_servers
requests?
>> Compute[:rackspace].list_servers
#<Excon::Response:0x________
requests?
>> Compute[:rackspace].list_servers
#<Excon::Response:0x________
@body = {
  "servers" => []
},
requests?
>> Compute[:rackspace].list_servers
#<Excon::Response:0x________
@body = {
  "servers" => []
},
@headers = {
  "X-PURGE-KEY"=>"/______/servers",
  ...,
  "Connection"=>"keep-alive"
},
requests?
>> Compute[:rackspace].list_servers
#<Excon::Response:0x________
@body = {
  "servers" => []
},
@headers = {
  "X-PURGE-KEY"=>"/______/servers",
  ...,
  "Connection"=>"keep-alive"
},
@status=200>
sanity check
sanity check
>> Compute[:rackspace].servers.select {|s| s.ready?}
sanity check
>> Compute[:rackspace].servers.select {|s| s.ready?}
 <Fog::Compute::Rackspace::Servers
  filters={}
  []
 >
sanity check
>> Compute[:rackspace].servers.select {|s| s.ready?}
 <Fog::Compute::Rackspace::Servers
  filters={}
  []
 >
>> Compute[:aws].servers.select {|s| s.ready?}
sanity check
>> Compute[:rackspace].servers.select {|s| s.ready?}
 <Fog::Compute::Rackspace::Servers
  filters={}
  []
 >
>> Compute[:aws].servers.select {|s| s.ready?}
 <Fog::Compute::AWS::Servers
  []
 >
sanity check
>> Compute[:rackspace].servers.select {|s| s.ready?}
 <Fog::Compute::Rackspace::Servers
  filters={}
  []
 >
>> Compute[:aws].servers.select {|s| s.ready?}
 <Fog::Compute::AWS::Servers
  []
 >
>> exit
finding images
finding images
>> Compute[:rackspace].images.table([:id, :name])
finding images
>> Compute[:rackspace].images.table([:id, :name])
 +---------
+------------------------------------------+
 | id  | name                        |
 +---------
+------------------------------------------+
 | 49   | Ubuntu 10.04 LTS (lucid)           |
 +---------
+------------------------------------------+
 ...
finding images
>> Compute[:rackspace].images.table([:id, :name])
 +---------
+------------------------------------------+
 | id  | name                        |
 +---------
+------------------------------------------+
 | 49   | Ubuntu 10.04 LTS (lucid)           |
 +---------
+------------------------------------------+
 ...
>> Compute[:aws].images # I use alestic.com listing
finding images
>> Compute[:rackspace].images.table([:id, :name])
  +---------
+------------------------------------------+
  | id  | name                       |
  +---------
+------------------------------------------+
  | 49   | Ubuntu 10.04 LTS (lucid)          |
  +---------
+------------------------------------------+
  ...
>> Compute[:aws].images # I use alestic.com listing
...
exploring...
exploring...
  It takes   forever!
exploring...
    It takes   forever!
  It’s so   expensive!
exploring...
        It takes   forever!
      It’s so   expensive!
A warm welcome for   Fog.mock!
Mocks!
geymus ~ ⌘ FOG_MOCK=true fog
             or
       require ‘fog’
       Fog.mock!
simulation
simulation
Most functions   just work!
simulation
         Most functions   just work!
Unimplemented mocks?   Errors   keep you on track.
simulation
                   Most functions   just work!
      Unimplemented mocks?       Errors      keep you on track.

Tests run against both, so it is either   consistent    or a   bug.
Elsewhere/Previously
Elsewhere/Previously
    storage -   aggregating cloud data
Elsewhere/Previously
     storage -       aggregating cloud data

   dns -   make your cloud (premium) accessible
Elsewhere/Previously
     storage -       aggregating cloud data

   dns -   make your cloud (premium) accessible

      congrats -        deploy, retire, etc
Love!
Love!
knowledge -   suffering encoded in ruby
Love!
knowledge -   expertise encoded in ruby
Love!
knowledge -   expertise encoded in ruby

empowering -    show the cloud who is boss
Love!
knowledge -        expertise encoded in ruby

empowering -          show the cloud who is boss

exciting -   this is some cutting edge stuff!
OpenStack
OpenStack
relevance? -   we share, so nothing to worry about, right?
OpenStack
relevance? -   we share, so nothing to worry about, right?

overruled! -   I am terrified
Consumers?
Consumers?
absenteeism -   unpaid, high barrier, nebulous payoff
Consumers?
absenteeism -   unpaid, high barrier, nebulous payoff

  sandbox -   greatly reduces barrier to participation
Identity
Identity
roll your own! -   initially auth was left to providers
Identity
roll your own! -    initially auth was left to providers

 keystone -   thankfully it seems we have standardized
“Compatibility”
“Compatibility”
AWS EC2 -   moving target, not a standard, kill it please
“Compatibility”
AWS EC2 -   moving target, not a standard, kill it please

    Rackspace Servers -              better, sort of
“Compatibility”
AWS EC2 -         moving target, not a standard, kill it please

     Rackspace Servers -                     better, sort of

 diff? -   slightly different is harder than vastly different
Coherence
Coherence
Code Talks -   defining API is great, but code beats specs
Coherence
Code Talks -   defining API is great, but code beats specs

 Style Guide -    specs miss stuff, so focus on general rules
Coherence
Code Talks -        defining API is great, but code beats specs

 Style Guide -         specs miss stuff, so focus on general rules

 diff? -   slightly different is harder than vastly different
Documentation
Documentation
Timely -   I need more and better docs, yesterday
Documentation
Timely -   I need more and better docs, yesterday

Maintained -     I need to docs to reflect current reality
Documentation
   Timely -   I need more and better docs, yesterday

  Maintained -       I need to docs to reflect current reality

Versioned -   I need docs that reflect particular past realities
Standard?
Standard?
headers -   apache vs nginx vs etc
Standard?
     headers -   apache vs nginx vs etc

performance -   wide range of meaning for eventually
Extensions
Extensions
differentiation -   desirable to producers, not consumers
Extensions
differentiation -   desirable to producers, not consumers

 open source -   there is already a clear path to extending
Versioning
Versioning
legacy -   for other providers, clients need only support latest
Versioning
legacy -     for other providers, clients need only support latest

future -   clients need to support infinitely many versions/extensions
Homework
Homework
clients -   engage with consumers for feedback
Homework
clients -   engage with consumers for feedback

dogfood -       use it yourselves to find the gaps
Thanks!




@geemus - questions, comments, suggestions
Thanks! Questions?
                 (see also: README)

  tutorial - http://github.com/geemus/learn_fog
examples - http://gist.github.com/729992
   slides - http://slidesha.re/hR8sP9
    repo - http://github.com/geemus/fog
    bugs - http://github.com/geemus/fog/issues
@geemus - questions, comments, suggestions

More Related Content

What's hot

Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suite
Bram Vogelaar
 
Autoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomadAutoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomad
Bram Vogelaar
 
Ansible : what's ansible & use case by REX
Ansible :  what's ansible & use case by REXAnsible :  what's ansible & use case by REX
Ansible : what's ansible & use case by REX
Saewoong Lee
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stack
Bram Vogelaar
 
Hopping in clouds: a tale of migration from one cloud provider to another
Hopping in clouds: a tale of migration from one cloud provider to anotherHopping in clouds: a tale of migration from one cloud provider to another
Hopping in clouds: a tale of migration from one cloud provider to another
Michele Orselli
 
Testing your infrastructure with litmus
Testing your infrastructure with litmusTesting your infrastructure with litmus
Testing your infrastructure with litmus
Bram Vogelaar
 
Ansible fest Presentation slides
Ansible fest Presentation slidesAnsible fest Presentation slides
Ansible fest Presentation slides
Aaron Carey
 
Roll Your Own API Management Platform with nginx and Lua
Roll Your Own API Management Platform with nginx and LuaRoll Your Own API Management Platform with nginx and Lua
Roll Your Own API Management Platform with nginx and Lua
Jon Moore
 
Lua tech talk
Lua tech talkLua tech talk
Lua tech talk
Locaweb
 
Refactoring terraform
Refactoring terraformRefactoring terraform
Refactoring terraform
Nell Shamrell-Harrington
 
Hadoop on ec2
Hadoop on ec2Hadoop on ec2
Hadoop on ec2
Mark Kerzner
 
Vagrant, Ansible, and OpenStack on your laptop
Vagrant, Ansible, and OpenStack on your laptopVagrant, Ansible, and OpenStack on your laptop
Vagrant, Ansible, and OpenStack on your laptop
Lorin Hochstein
 
Using ngx_lua in UPYUN
Using ngx_lua in UPYUNUsing ngx_lua in UPYUN
Using ngx_lua in UPYUN
Cong Zhang
 
Scaling Mapufacture on Amazon Web Services
Scaling Mapufacture on Amazon Web ServicesScaling Mapufacture on Amazon Web Services
Scaling Mapufacture on Amazon Web Services
Andrew Turner
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
tomcopeland
 
Ansible loves Python, Python Philadelphia meetup
Ansible loves Python, Python Philadelphia meetupAnsible loves Python, Python Philadelphia meetup
Ansible loves Python, Python Philadelphia meetup
Greg DeKoenigsberg
 
Mail server configuration
Mail server configurationMail server configuration
Mail server configuration
chacheng oo
 
Ansible leveraging 2.0
Ansible leveraging 2.0Ansible leveraging 2.0
Ansible leveraging 2.0
bcoca
 
Hacking ansible
Hacking ansibleHacking ansible
Hacking ansible
bcoca
 
Asynchronous Threads in Lasso 8.5
Asynchronous Threads in Lasso 8.5Asynchronous Threads in Lasso 8.5
Asynchronous Threads in Lasso 8.5
bilcorry
 

What's hot (20)

Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suite
 
Autoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomadAutoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomad
 
Ansible : what's ansible & use case by REX
Ansible :  what's ansible & use case by REXAnsible :  what's ansible & use case by REX
Ansible : what's ansible & use case by REX
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stack
 
Hopping in clouds: a tale of migration from one cloud provider to another
Hopping in clouds: a tale of migration from one cloud provider to anotherHopping in clouds: a tale of migration from one cloud provider to another
Hopping in clouds: a tale of migration from one cloud provider to another
 
Testing your infrastructure with litmus
Testing your infrastructure with litmusTesting your infrastructure with litmus
Testing your infrastructure with litmus
 
Ansible fest Presentation slides
Ansible fest Presentation slidesAnsible fest Presentation slides
Ansible fest Presentation slides
 
Roll Your Own API Management Platform with nginx and Lua
Roll Your Own API Management Platform with nginx and LuaRoll Your Own API Management Platform with nginx and Lua
Roll Your Own API Management Platform with nginx and Lua
 
Lua tech talk
Lua tech talkLua tech talk
Lua tech talk
 
Refactoring terraform
Refactoring terraformRefactoring terraform
Refactoring terraform
 
Hadoop on ec2
Hadoop on ec2Hadoop on ec2
Hadoop on ec2
 
Vagrant, Ansible, and OpenStack on your laptop
Vagrant, Ansible, and OpenStack on your laptopVagrant, Ansible, and OpenStack on your laptop
Vagrant, Ansible, and OpenStack on your laptop
 
Using ngx_lua in UPYUN
Using ngx_lua in UPYUNUsing ngx_lua in UPYUN
Using ngx_lua in UPYUN
 
Scaling Mapufacture on Amazon Web Services
Scaling Mapufacture on Amazon Web ServicesScaling Mapufacture on Amazon Web Services
Scaling Mapufacture on Amazon Web Services
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
Ansible loves Python, Python Philadelphia meetup
Ansible loves Python, Python Philadelphia meetupAnsible loves Python, Python Philadelphia meetup
Ansible loves Python, Python Philadelphia meetup
 
Mail server configuration
Mail server configurationMail server configuration
Mail server configuration
 
Ansible leveraging 2.0
Ansible leveraging 2.0Ansible leveraging 2.0
Ansible leveraging 2.0
 
Hacking ansible
Hacking ansibleHacking ansible
Hacking ansible
 
Asynchronous Threads in Lasso 8.5
Asynchronous Threads in Lasso 8.5Asynchronous Threads in Lasso 8.5
Asynchronous Threads in Lasso 8.5
 

Viewers also liked

Универсальный иммортализм
Универсальный иммортализмУниверсальный иммортализм
Универсальный иммортализм
Danila Medvedev
 
Sunil_Kumar
Sunil_KumarSunil_Kumar
Sunil_Kumar
Sunil Kumar
 
An Executive View on Cloud Service Brokers - Cloud Solutions in a CSB Model C...
An Executive View on Cloud Service Brokers - Cloud Solutions in a CSB Model C...An Executive View on Cloud Service Brokers - Cloud Solutions in a CSB Model C...
An Executive View on Cloud Service Brokers - Cloud Solutions in a CSB Model C...
Chad Lawler
 
Strategic Project Presentation
Strategic Project PresentationStrategic Project Presentation
Strategic Project Presentation
StrategicProject
 
Pnsd modulo 2 1 Colombo
Pnsd modulo 2 1 ColomboPnsd modulo 2 1 Colombo
Pnsd modulo 2 1 Colombo
Laura Anna Maria Colombo
 
Jelastic - DevOps for Java with Docker Containers - Madrid 2015
Jelastic - DevOps for Java with Docker Containers - Madrid 2015Jelastic - DevOps for Java with Docker Containers - Madrid 2015
Jelastic - DevOps for Java with Docker Containers - Madrid 2015
Jelastic Multi-Cloud PaaS
 
Corso di Formazione: Peer to Peer Education
Corso di Formazione: Peer to Peer EducationCorso di Formazione: Peer to Peer Education
Corso di Formazione: Peer to Peer Education
Design Didattico
 
Состояние мирового трансгуманизма
Состояние мирового трансгуманизмаСостояние мирового трансгуманизма
Состояние мирового трансгуманизма
Danila Medvedev
 
Strategic Technical Presenation
Strategic Technical PresenationStrategic Technical Presenation
Strategic Technical Presenation
StrategicProject
 
La rete per la didattica delle competenze
La rete  per la didattica delle competenzeLa rete  per la didattica delle competenze
La rete per la didattica delle competenzePierfranco Ravotto
 
Competenze a scuola
Competenze a scuola Competenze a scuola
Competenze a scuola
Cristiana Pivetta
 
The Rise of Cloud Service Brokerage featuring Gartner and BCBS
The Rise of Cloud Service Brokerage featuring Gartner and BCBSThe Rise of Cloud Service Brokerage featuring Gartner and BCBS
The Rise of Cloud Service Brokerage featuring Gartner and BCBS
Intel - API Security & Tokenization
 
A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...
A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...
A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...
SlideShare
 

Viewers also liked (13)

Универсальный иммортализм
Универсальный иммортализмУниверсальный иммортализм
Универсальный иммортализм
 
Sunil_Kumar
Sunil_KumarSunil_Kumar
Sunil_Kumar
 
An Executive View on Cloud Service Brokers - Cloud Solutions in a CSB Model C...
An Executive View on Cloud Service Brokers - Cloud Solutions in a CSB Model C...An Executive View on Cloud Service Brokers - Cloud Solutions in a CSB Model C...
An Executive View on Cloud Service Brokers - Cloud Solutions in a CSB Model C...
 
Strategic Project Presentation
Strategic Project PresentationStrategic Project Presentation
Strategic Project Presentation
 
Pnsd modulo 2 1 Colombo
Pnsd modulo 2 1 ColomboPnsd modulo 2 1 Colombo
Pnsd modulo 2 1 Colombo
 
Jelastic - DevOps for Java with Docker Containers - Madrid 2015
Jelastic - DevOps for Java with Docker Containers - Madrid 2015Jelastic - DevOps for Java with Docker Containers - Madrid 2015
Jelastic - DevOps for Java with Docker Containers - Madrid 2015
 
Corso di Formazione: Peer to Peer Education
Corso di Formazione: Peer to Peer EducationCorso di Formazione: Peer to Peer Education
Corso di Formazione: Peer to Peer Education
 
Состояние мирового трансгуманизма
Состояние мирового трансгуманизмаСостояние мирового трансгуманизма
Состояние мирового трансгуманизма
 
Strategic Technical Presenation
Strategic Technical PresenationStrategic Technical Presenation
Strategic Technical Presenation
 
La rete per la didattica delle competenze
La rete  per la didattica delle competenzeLa rete  per la didattica delle competenze
La rete per la didattica delle competenze
 
Competenze a scuola
Competenze a scuola Competenze a scuola
Competenze a scuola
 
The Rise of Cloud Service Brokerage featuring Gartner and BCBS
The Rise of Cloud Service Brokerage featuring Gartner and BCBSThe Rise of Cloud Service Brokerage featuring Gartner and BCBS
The Rise of Cloud Service Brokerage featuring Gartner and BCBS
 
A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...
A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...
A Guide to SlideShare Analytics - Excerpts from Hubspot's Step by Step Guide ...
 

Similar to fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)

Cloud Meetup - Automation in the Cloud
Cloud Meetup - Automation in the CloudCloud Meetup - Automation in the Cloud
Cloud Meetup - Automation in the Cloud
petriojala123
 
Cutting through the fog of cloud
Cutting through the fog of cloudCutting through the fog of cloud
Cutting through the fog of cloud
Kyle Rames
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
Tom Croucher
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NET
Gianluca Carucci
 
Apache MXNet Distributed Training Explained In Depth by Viacheslav Kovalevsky...
Apache MXNet Distributed Training Explained In Depth by Viacheslav Kovalevsky...Apache MXNet Distributed Training Explained In Depth by Viacheslav Kovalevsky...
Apache MXNet Distributed Training Explained In Depth by Viacheslav Kovalevsky...
Big Data Spain
 
Stack kicker devopsdays-london-2013
Stack kicker devopsdays-london-2013Stack kicker devopsdays-london-2013
Stack kicker devopsdays-london-2013
Simon McCartney
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in Ruby
LaunchAny
 
infra-as-code
infra-as-codeinfra-as-code
infra-as-code
Itamar Hassin
 
NGINX Can Do That? Test Drive Your Config File!
NGINX Can Do That? Test Drive Your Config File!NGINX Can Do That? Test Drive Your Config File!
NGINX Can Do That? Test Drive Your Config File!
Jeff Anderson
 
Cooking with Chef
Cooking with ChefCooking with Chef
Cooking with Chef
Ken Robertson
 
Reusable, composable, battle-tested Terraform modules
Reusable, composable, battle-tested Terraform modulesReusable, composable, battle-tested Terraform modules
Reusable, composable, battle-tested Terraform modules
Yevgeniy Brikman
 
Otimizando seu projeto Rails
Otimizando seu projeto RailsOtimizando seu projeto Rails
Otimizando seu projeto Rails
Tiago Albineli Motta
 
Presentation iv implementasi 802x eap tls peap mscha pv2
Presentation iv implementasi  802x eap tls peap mscha pv2Presentation iv implementasi  802x eap tls peap mscha pv2
Presentation iv implementasi 802x eap tls peap mscha pv2
Hell19
 
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
Matt Raible
 
Monkey man
Monkey manMonkey man
Monkey man
ShapeBlue
 
Streamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache AmbariStreamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache Ambari
Alejandro Fernandez
 
Automating the Network
Automating the NetworkAutomating the Network
Automating the Network
Puppet
 
Writing Redis in Python with asyncio
Writing Redis in Python with asyncioWriting Redis in Python with asyncio
Writing Redis in Python with asyncio
James Saryerwinnie
 
Non-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.jsNon-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.js
Marcus Frödin
 
Celery with python
Celery with pythonCelery with python
Celery with python
Alexandre González Rodríguez
 

Similar to fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition) (20)

Cloud Meetup - Automation in the Cloud
Cloud Meetup - Automation in the CloudCloud Meetup - Automation in the Cloud
Cloud Meetup - Automation in the Cloud
 
Cutting through the fog of cloud
Cutting through the fog of cloudCutting through the fog of cloud
Cutting through the fog of cloud
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NET
 
Apache MXNet Distributed Training Explained In Depth by Viacheslav Kovalevsky...
Apache MXNet Distributed Training Explained In Depth by Viacheslav Kovalevsky...Apache MXNet Distributed Training Explained In Depth by Viacheslav Kovalevsky...
Apache MXNet Distributed Training Explained In Depth by Viacheslav Kovalevsky...
 
Stack kicker devopsdays-london-2013
Stack kicker devopsdays-london-2013Stack kicker devopsdays-london-2013
Stack kicker devopsdays-london-2013
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in Ruby
 
infra-as-code
infra-as-codeinfra-as-code
infra-as-code
 
NGINX Can Do That? Test Drive Your Config File!
NGINX Can Do That? Test Drive Your Config File!NGINX Can Do That? Test Drive Your Config File!
NGINX Can Do That? Test Drive Your Config File!
 
Cooking with Chef
Cooking with ChefCooking with Chef
Cooking with Chef
 
Reusable, composable, battle-tested Terraform modules
Reusable, composable, battle-tested Terraform modulesReusable, composable, battle-tested Terraform modules
Reusable, composable, battle-tested Terraform modules
 
Otimizando seu projeto Rails
Otimizando seu projeto RailsOtimizando seu projeto Rails
Otimizando seu projeto Rails
 
Presentation iv implementasi 802x eap tls peap mscha pv2
Presentation iv implementasi  802x eap tls peap mscha pv2Presentation iv implementasi  802x eap tls peap mscha pv2
Presentation iv implementasi 802x eap tls peap mscha pv2
 
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
 
Monkey man
Monkey manMonkey man
Monkey man
 
Streamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache AmbariStreamline Hadoop DevOps with Apache Ambari
Streamline Hadoop DevOps with Apache Ambari
 
Automating the Network
Automating the NetworkAutomating the Network
Automating the Network
 
Writing Redis in Python with asyncio
Writing Redis in Python with asyncioWriting Redis in Python with asyncio
Writing Redis in Python with asyncio
 
Non-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.jsNon-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.js
 
Celery with python
Celery with pythonCelery with python
Celery with python
 

Recently uploaded

OpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - AuthorizationOpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - Authorization
David Brossard
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
kumardaparthi1024
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
Zilliz
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
DianaGray10
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
Zilliz
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
Brandon Minnick, MBA
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
Jason Packer
 
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
saastr
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
IndexBug
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
SitimaJohn
 
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying AheadDigital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Wask
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
Tomaz Bratanic
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Jeffrey Haguewood
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Speck&Tech
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
Pixlogix Infotech
 
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Tosin Akinosho
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 

Recently uploaded (20)

OpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - AuthorizationOpenID AuthZEN Interop Read Out - Authorization
OpenID AuthZEN Interop Read Out - Authorization
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
 
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
 
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying AheadDigital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying Ahead
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
 
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 

fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)

  • 1. OR: fog HOW I LEARNED TO STOP WORRYING AND LOVE THE CLOUD
  • 2. geemus (Wesley Beary) web: github.com/geemus twitter: @geemus
  • 3. employer and sponsor web: engineyard.com twitter: @engineyard
  • 4. API driven on demand services CLOUD core: compute, dns, storage also: kvs, load balance, ...
  • 6. What? on demand - only pay for what you actually use
  • 7. What? on demand - only pay for what you actually use flexible - add and remove resources in minutes (instead of weeks)
  • 8. What? on demand - only pay for what you actually use flexible - add and remove resources in minutes (instead of weeks) repeatable - code, test, repeat
  • 9. What? on demand - only pay for what you actually use flexible - add and remove resources in minutes (instead of weeks) repeatable - code, test, repeat resilient - build better systems with transient resources
  • 11. Why Worry? option overload - which provider/service should I use
  • 12. Why Worry? option overload - which provider/service should I use expertise - each service has yet another knowledge silo
  • 13. Why Worry? option overload - which provider/service should I use expertise - each service has yet another knowledge silo tools - vastly different API, quality, maintenance, etc
  • 14. Why Worry? option overload - which provider/service should I use expertise - each service has yet another knowledge silo tools - vastly different API, quality, maintenance, etc standards - slow progress and differing interpretations
  • 15. Ruby cloud services web: github.com/geemus/fog twitter: @fog
  • 16. Why?
  • 17. Why? portable - AWS, Bluebox, Brightbox, Google, Rackspace, Slicehost, Terremark, ...
  • 18. Why? portable - AWS, Bluebox, Brightbox, Google, Rackspace, Slicehost, Terremark, ... powerful - compute, dns, storage, collections, models, mocks, requests, ...
  • 19. Why? portable - AWS, Bluebox, Brightbox, Google, Rackspace, Slicehost, Terremark, ... powerful - compute, dns, storage, collections, models, mocks, requests, ... established - 250k downloads, 1564 followers, 266 forks, 127 contributors, me, ...
  • 20. Why? portable - AWS, Bluebox, Brightbox, Google, Rackspace, Slicehost, Terremark, ... powerful - compute, dns, storage, collections, models, mocks, requests, ... established - 250k downloads, 1564 followers, 266 forks, 127 contributors, me, ... Fog.mock! - faster, cheaper, simulated cloud behavior
  • 21. Who?
  • 22. Who? libraries - carrierwave, chef, gemcutter, puppet, ... products - AppFog, Engine Yard, Heroku, ...
  • 25. Interactive Bit! cloud fog
  • 26. What?
  • 27. What? That’s great and all but I don’t have a use case...
  • 28. What? That’s great and all but I don’t have a use case... uptime - because who wants a busted web site?
  • 29. Setup geymus ~ ⌘ gem install fog or geymus ~ ⌘ sudo gem install fog
  • 30. Get Connected 7 # setup a connection to the service 8 compute = Fog::Compute.new(credentials)
  • 31. Get Connected 1 credentials = { 2   :provider           => 'Rackspace', 3   :rackspace_api_key  => RACKSPACE_API_KEY, 4   :rackspace_username => RACKSPACE_USERNAME 5 } 6 7 # setup a connection to the service 8 compute = Fog::Compute.new(credentials)
  • 32. Boot that Server  1 server_data = compute.create_server(  2   1,  3   49  4 ).body['server']  5
  • 33. Boot that Server  1 server_data = compute.create_server(  2   1,  3   49  4 ).body['server']  5  6 until compute.get_server_details(  7   server_data['id']  8 ).body['server']['status'] == 'ACTIVE'  9 end 10
  • 34. Boot that Server  1 server_data = compute.create_server(  2   1,  3   49  4 ).body['server']  5  6 until compute.get_server_details(  7   server_data['id']  8 ).body['server']['status'] == 'ACTIVE'  9 end 10 11 commands = [ 12   %{'mkdir .ssh'}, 13   %{'echo #{File.read('~/.ssh/id_rsa.pub')} >> ~/.ssh/authorized_keys'}, 14   %{passwd -l root}, 15 ] 16 17 Net::SSH.start( 18   server_data['addresses'].first, 19   'root', 20   :password => server_data['password'] 21 ) do |ssh| 22   commands.each do |command| 23     ssh.open_channel do |ssh_channel| 24       ssh_channel.request_pty 25       ssh_channel.exec(%{bash -lc '#{command}'}) 26       ssh.loop 27     end 28   end 29 end
  • 36. Worry! arguments - what goes where, what does it mean?
  • 37. Worry! arguments - what goes where, what does it mean? portability - most of this will only work on Rackspace
  • 38. Worry! arguments - what goes where, what does it mean? portability - most of this will only work on Rackspace disservice - back to square one, but with tools in hand
  • 39. Bootstrap 7 # boot server and setup ssh keys 8 server = compute.servers.bootstrap(server_attributes)
  • 40. Bootstrap 1 server_attributes = { 2   :image_id         => '49', 3   :private_key_path => PRIVATE_KEY_PATH, 4   :public_key_path  => PUBLIC_KEY_PATH 5 } 6 7 # boot server and setup ssh keys 8 server = compute.servers.bootstrap(server_attributes)
  • 42. Servers? 1 compute.servers # list servers, same as #all
  • 43. Servers? 1 compute.servers # list servers, same as #all 2 3 compute.servers.get(1234567890) # server by id
  • 44. Servers? 1 compute.servers # list servers, same as #all 2 3 compute.servers.get(1234567890) # server by id 4 5 compute.servers.reload # update to latest
  • 45. Servers? 1 compute.servers # list servers, same as #all 2 3 compute.servers.get(1234567890) # server by id 4 5 compute.servers.reload # update to latest 6 7 compute.servers.new(attributes) # local model
  • 46. Servers? 1 compute.servers # list servers, same as #all 2 3 compute.servers.get(1234567890) # server by id 4 5 compute.servers.reload # update to latest 6 7 compute.servers.new(attributes) # local model 8 9 compute.servers.create(attributes) # remote model
  • 47. ping
  • 48. ping 1 # ping target 10 times 2 ssh_results = server.ssh("ping -c 10 #{target}")
  • 49. ping 1 # ping target 10 times 2 ssh_results = server.ssh("ping -c 10 #{target}") 3 stdout = ssh_results.first.stdout
  • 50. ping 1 # ping target 10 times 2 ssh_results = server.ssh("ping -c 10 #{target}") 3 stdout = ssh_results.first.stdout 4 5 # parse result, last line is summary 6 # round-trip min/avg/max/stddev = A.A/B.B/C.C/D.D ms
  • 51. ping 1 # ping target 10 times 2 ssh_results = server.ssh("ping -c 10 #{target}") 3 stdout = ssh_results.first.stdout 4 5 # parse result, last line is summary 6 # round-trip min/avg/max/stddev = A.A/B.B/C.C/D.D ms 7 stats = stdout.split("/n").last.split(' ')[-2] 8 min, avg, max, stddev = stats.split('/')
  • 52. ping 1 # ping target 10 times 2 ssh_results = server.ssh("ping -c 10 #{target}") 3 stdout = ssh_results.first.stdout 4 5 # parse result, last line is summary 6 # round-trip min/avg/max/stddev = A.A/B.B/C.C/D.D ms 7 stats = stdout.split("/n").last.split(' ')[-2] 8 min, avg, max, stddev = stats.split('/') NOTE: most complex code was string parsing!?!
  • 54. cleanup  1 # shutdown the server  2 server.destroy
  • 55. cleanup  1 # shutdown the server  2 server.destroy  3  4 # return the data as a hash  5 {  6   :min    => min,  7   :avg    => avg,  8   :max    => max,  9   :stddev => stddev 10 }
  • 56. Next!
  • 57. Next!  1 -server_data = compute.create_server(  2 +compute.import_key_pair(  3 +  'id_rsa.pub',  4 +  File.read('~/.ssh/id_rsa.pub')  5 +)  6 +  7 +compute.authorize_security_group_ingress(  8 +  'CidrIp'      => '0.0.0.0/0',  9 +  'FromPort'    => 22, 10 +  'IpProtocol'  => 'tcp', 11 +  'GroupName'   => 'default', 12 +  'ToPort'      => 22 13 +) 14 + 15 +server_data = compute.run_instances( 16 +  'ami-1a837773', 17    1, 18 -  49 19 -).body['server'] 20 +  1, 21 +  'InstanceType'  => 'm1.small', 22 +  'KeyName'       => 'id_rsa.pub', 23 +  'SecurityGroup' => 'default' 24 +).body['instancesSet'].first 25   26 -until compute.get_server_details( 27 -  server_data['id'] 28 -).body['server']['status'] == 'ACTIVE' 29 +until compute.describe_instances( 30 +  'instance-id' => server_data['instanceId'] 31 +).body['reservationSet'].first['instancesSet'].first['instanceState']['name'] == 'running' 32  end 33   34 +sleep(300) 35 + 36  Net::SSH.start( 37 -  server_data['addresses'].first, 38 -  'root', 39 -  :password => server_data['password'] 40 +  server_data['ipAddress'], 41 +  'ubuntu', 42 +  :key_data => [File.read('~/.ssh/id_rsa')] 43  ) do |ssh| 44    commands = [ 45      %{'mkdir .ssh'},
  • 58. Next!  1 -server_data = compute.create_server(  2 +compute.import_key_pair(  3 +  'id_rsa.pub',  4 +  File.read('~/.ssh/id_rsa.pub')  5 +)  6 +  7 +compute.authorize_security_group_ingress(  8 +  'CidrIp'      => '0.0.0.0/0',  9 +  'FromPort'    => 22, 10 +  'IpProtocol'  => 'tcp', 11 +  'GroupName'   => 'default', 12 +  'ToPort'      => 22 13 +) 14 + 15 +server_data = compute.run_instances( 16 +  'ami-1a837773', 17    1, 18 -  49 19 -).body['server'] 20 +  1, 21 +  'InstanceType'  => 'm1.small', 22 +  'KeyName'       => 'id_rsa.pub', 23 +  'SecurityGroup' => 'default' 24 +).body['instancesSet'].first 25   26 -until compute.get_server_details( 27 -  server_data['id'] 28 -).body['server']['status'] == 'ACTIVE' 29 +until compute.describe_instances( 30 +  'instance-id' => server_data['instanceId'] 31 +).body['reservationSet'].first['instancesSet'].first['instanceState']['name'] == 'running' 32  end 33   34 +sleep(300) 35 + 36  Net::SSH.start( 37 -  server_data['addresses'].first, 38 -  'root', 39 -  :password => server_data['password'] 40 +  server_data['ipAddress'], 41 +  'ubuntu', 42 +  :key_data => [File.read('~/.ssh/id_rsa')] 43  ) do |ssh| 44    commands = [ 45      %{'mkdir .ssh'},
  • 59. geopinging v1  1 # specify a different provider  2 credentials = {  3   :provider  => 'AWS',  4   :aws_access_key_id  => AWS_ACCESS_KEY_ID,  5   :aws_secret_access_key => AWS_SECRET_ACCESS_KEY  6 }  7  8 server_attributes = {  9   :image_id         => 'ami-1a837773', 10   :private_key_path => PRIVATE_KEY_PATH, 11   :public_key_path  => PUBLIC_KEY_PATH, 12   :username         => 'ubuntu' 13 }
  • 60. geopinging v2 1 # specify a different aws region 2 # ['ap-southeast-1', 'eu-west-1', 'us-west-1] 3 credentials.merge!({ 4   :region => 'eu-west-1' 5 })
  • 61. geopinging v... portable - AWS, Bluebox, Brightbox, Rackspace, Slicehost, Terremark, ...
  • 62. geopinging v... portable - AWS, Bluebox, Brightbox, Rackspace, Slicehost, Terremark, ... lather, rinse, repeat
  • 63. How? That is awesome, but how did you...
  • 64. exploring geymus ~ ⌘ fog   To run as 'default', add the following to ~/.fog :default:   :aws_access_key_id:     INTENTIONALLY_LEFT_BLANK   :aws_secret_access_key: INTENTIONALLY_LEFT_BLANK   :public_key_path:       INTENTIONALLY_LEFT_BLANK   :private_key_path:      INTENTIONALLY_LEFT_BLANK   :rackspace_api_key:     INTENTIONALLY_LEFT_BLANK   :rackspace_username:    INTENTIONALLY_LEFT_BLANK ...
  • 67. sign posts geymus ~ ⌘ fog Welcome to fog interactive! :default credentials provide AWS and Rackspace
  • 68. sign posts geymus ~ ⌘ fog Welcome to fog interactive! :default credentials provide AWS and Rackspace >> providers
  • 69. sign posts geymus ~ ⌘ fog Welcome to fog interactive! :default credentials provide AWS and Rackspace >> providers [AWS, Rackspace]
  • 70. sign posts geymus ~ ⌘ fog Welcome to fog interactive! :default credentials provide AWS and Rackspace >> providers [AWS, Rackspace] >> Rackspace.collections
  • 71. sign posts geymus ~ ⌘ fog Welcome to fog interactive! :default credentials provide AWS and Rackspace >> providers [AWS, Rackspace] >> Rackspace.collections [:directories, :files, :flavors, :images, :servers]
  • 72. sign posts geymus ~ ⌘ fog Welcome to fog interactive! :default credentials provide AWS and Rackspace >> providers [AWS, Rackspace] >> Rackspace.collections [:directories, :files, :flavors, :images, :servers] >> Compute[:rackspace]
  • 73. sign posts geymus ~ ⌘ fog Welcome to fog interactive! :default credentials provide AWS and Rackspace >> providers [AWS, Rackspace] >> Rackspace.collections [:directories, :files, :flavors, :images, :servers] >> Compute[:rackspace] #<Fog::Compute::Rackspace ...>
  • 74. sign posts geymus ~ ⌘ fog Welcome to fog interactive! :default credentials provide AWS and Rackspace >> providers [AWS, Rackspace] >> Rackspace.collections [:directories, :files, :flavors, :images, :servers] >> Compute[:rackspace] #<Fog::Compute::Rackspace ...> >> Compute[:rackspace].requests
  • 75. sign posts geymus ~ ⌘ fog Welcome to fog interactive! :default credentials provide AWS and Rackspace >> providers [AWS, Rackspace] >> Rackspace.collections [:directories, :files, :flavors, :images, :servers] >> Compute[:rackspace] #<Fog::Compute::Rackspace ...> >> Compute[:rackspace].requests [:confirm_resized_server, ..., :update_server]
  • 77. what are those? provider => [AWS, Rackspace, Zerigo, ...]
  • 78. what are those? provider => [AWS, Rackspace, Zerigo, ...] service => [Compute, DNS, Storage, ...]
  • 79. what are those? provider => [AWS, Rackspace, Zerigo, ...] service => [Compute, DNS, Storage, ...] collection => [flavors, images, servers, ...]
  • 80. what are those? provider => [AWS, Rackspace, Zerigo, ...] service => [Compute, DNS, Storage, ...] collection => [flavors, images, servers, ...] model => [flavor, image, server, ...]
  • 81. what are those? provider => [AWS, Rackspace, Zerigo, ...] service => [Compute, DNS, Storage, ...] collection => [flavors, images, servers, ...] model => [flavor, image, server, ...] request => [describe_instances, run_instances, ...]
  • 86. requests? >> Compute[:rackspace].list_servers #<Excon::Response:0x________ @body = { "servers" => [] }, @headers = { "X-PURGE-KEY"=>"/______/servers", ..., "Connection"=>"keep-alive" },
  • 87. requests? >> Compute[:rackspace].list_servers #<Excon::Response:0x________ @body = { "servers" => [] }, @headers = { "X-PURGE-KEY"=>"/______/servers", ..., "Connection"=>"keep-alive" }, @status=200>
  • 90. sanity check >> Compute[:rackspace].servers.select {|s| s.ready?} <Fog::Compute::Rackspace::Servers filters={} [] >
  • 91. sanity check >> Compute[:rackspace].servers.select {|s| s.ready?} <Fog::Compute::Rackspace::Servers filters={} [] > >> Compute[:aws].servers.select {|s| s.ready?}
  • 92. sanity check >> Compute[:rackspace].servers.select {|s| s.ready?} <Fog::Compute::Rackspace::Servers filters={} [] > >> Compute[:aws].servers.select {|s| s.ready?} <Fog::Compute::AWS::Servers [] >
  • 93. sanity check >> Compute[:rackspace].servers.select {|s| s.ready?} <Fog::Compute::Rackspace::Servers filters={} [] > >> Compute[:aws].servers.select {|s| s.ready?} <Fog::Compute::AWS::Servers [] > >> exit
  • 96. finding images >> Compute[:rackspace].images.table([:id, :name]) +--------- +------------------------------------------+ | id | name | +--------- +------------------------------------------+ | 49 | Ubuntu 10.04 LTS (lucid) | +--------- +------------------------------------------+ ...
  • 97. finding images >> Compute[:rackspace].images.table([:id, :name]) +--------- +------------------------------------------+ | id | name | +--------- +------------------------------------------+ | 49 | Ubuntu 10.04 LTS (lucid) | +--------- +------------------------------------------+ ... >> Compute[:aws].images # I use alestic.com listing
  • 98. finding images >> Compute[:rackspace].images.table([:id, :name]) +--------- +------------------------------------------+ | id | name | +--------- +------------------------------------------+ | 49 | Ubuntu 10.04 LTS (lucid) | +--------- +------------------------------------------+ ... >> Compute[:aws].images # I use alestic.com listing ...
  • 100. exploring... It takes forever!
  • 101. exploring... It takes forever! It’s so expensive!
  • 102. exploring... It takes forever! It’s so expensive! A warm welcome for Fog.mock!
  • 103. Mocks! geymus ~ ⌘ FOG_MOCK=true fog or require ‘fog’ Fog.mock!
  • 106. simulation Most functions just work! Unimplemented mocks? Errors keep you on track.
  • 107. simulation Most functions just work! Unimplemented mocks? Errors keep you on track. Tests run against both, so it is either consistent or a bug.
  • 109. Elsewhere/Previously storage - aggregating cloud data
  • 110. Elsewhere/Previously storage - aggregating cloud data dns - make your cloud (premium) accessible
  • 111. Elsewhere/Previously storage - aggregating cloud data dns - make your cloud (premium) accessible congrats - deploy, retire, etc
  • 112. Love!
  • 113. Love! knowledge - suffering encoded in ruby
  • 114. Love! knowledge - expertise encoded in ruby
  • 115. Love! knowledge - expertise encoded in ruby empowering - show the cloud who is boss
  • 116. Love! knowledge - expertise encoded in ruby empowering - show the cloud who is boss exciting - this is some cutting edge stuff!
  • 118. OpenStack relevance? - we share, so nothing to worry about, right?
  • 119. OpenStack relevance? - we share, so nothing to worry about, right? overruled! - I am terrified
  • 121. Consumers? absenteeism - unpaid, high barrier, nebulous payoff
  • 122. Consumers? absenteeism - unpaid, high barrier, nebulous payoff sandbox - greatly reduces barrier to participation
  • 124. Identity roll your own! - initially auth was left to providers
  • 125. Identity roll your own! - initially auth was left to providers keystone - thankfully it seems we have standardized
  • 127. “Compatibility” AWS EC2 - moving target, not a standard, kill it please
  • 128. “Compatibility” AWS EC2 - moving target, not a standard, kill it please Rackspace Servers - better, sort of
  • 129. “Compatibility” AWS EC2 - moving target, not a standard, kill it please Rackspace Servers - better, sort of diff? - slightly different is harder than vastly different
  • 131. Coherence Code Talks - defining API is great, but code beats specs
  • 132. Coherence Code Talks - defining API is great, but code beats specs Style Guide - specs miss stuff, so focus on general rules
  • 133. Coherence Code Talks - defining API is great, but code beats specs Style Guide - specs miss stuff, so focus on general rules diff? - slightly different is harder than vastly different
  • 135. Documentation Timely - I need more and better docs, yesterday
  • 136. Documentation Timely - I need more and better docs, yesterday Maintained - I need to docs to reflect current reality
  • 137. Documentation Timely - I need more and better docs, yesterday Maintained - I need to docs to reflect current reality Versioned - I need docs that reflect particular past realities
  • 139. Standard? headers - apache vs nginx vs etc
  • 140. Standard? headers - apache vs nginx vs etc performance - wide range of meaning for eventually
  • 142. Extensions differentiation - desirable to producers, not consumers
  • 143. Extensions differentiation - desirable to producers, not consumers open source - there is already a clear path to extending
  • 145. Versioning legacy - for other providers, clients need only support latest
  • 146. Versioning legacy - for other providers, clients need only support latest future - clients need to support infinitely many versions/extensions
  • 148. Homework clients - engage with consumers for feedback
  • 149. Homework clients - engage with consumers for feedback dogfood - use it yourselves to find the gaps
  • 150. Thanks! @geemus - questions, comments, suggestions
  • 151. Thanks! Questions? (see also: README) tutorial - http://github.com/geemus/learn_fog examples - http://gist.github.com/729992 slides - http://slidesha.re/hR8sP9 repo - http://github.com/geemus/fog bugs - http://github.com/geemus/fog/issues @geemus - questions, comments, suggestions

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n
  131. \n
  132. \n
  133. \n
  134. \n
  135. \n
  136. \n
  137. \n
  138. \n
  139. \n
  140. \n
  141. \n
  142. \n
  143. \n
  144. \n
  145. \n
  146. \n
  147. \n
  148. \n
  149. \n
  150. \n
  151. \n
  152. \n
  153. \n
  154. \n
  155. \n
  156. \n
  157. \n
  158. \n
  159. \n
  160. \n
  161. \n
  162. \n
  163. \n
  164. \n
  165. \n
  166. \n