Top Banner
Introduction to Fog and Openstack Hunter Nield - 1/3/2013 Twitter: @hunternield
33

Intro to fog and openstack jp

Aug 20, 2015

Download

Technology

Satoshi Konno
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Intro to fog and openstack jp

Introduction to Fog and Openstack

Hunter Nield - 1/3/2013Twitter: @hunternield

Page 2: Intro to fog and openstack jp

Fogとは• 複数のクラウド・サービスを接続する共通インターフェイス

• オープンソース Ruby ライブラリ (MIT License)

• OpenStack への接続が容易

• http://fog.io

• https://github.com/fog/fog

Page 3: Intro to fog and openstack jp

Fogの歴史

• 2010年 Wesley Beary (geemus on Github) により開始

•初期バージョンは Amazon、Rackspace、Slicehostのみ

Page 4: Intro to fog and openstack jp

Fog と OpenStack の歴史

• Diablo バージョンにて開発開始

• Morphlabs が Essex からサポートを始め、Folsom、その後のバージョンと継続する予定。

Page 5: Intro to fog and openstack jp

BasicsFog provides high level interfaces to cloud services

Page 6: Intro to fog and openstack jp

ServicesFog Services map closely to the Openstack Services

Page 7: Intro to fog and openstack jp

ComputeConnects to the Openstack Nova API for managing

Instances (Servers), Security Groups, Floating IPs, etc

http://rubydoc.info/gems/fog/1.9.0/Fog/Compute/OpenStack

Page 8: Intro to fog and openstack jp

IdentityConnects to the Openstack Keystone API for managing Users, Tenants and Authentication

http://rubydoc.info/gems/fog/1.9.0/Fog/Identity/OpenStack

Page 9: Intro to fog and openstack jp

VolumesConnects to the Openstack Nova/Cinder API for managing Block Storage

http://rubydoc.info/gems/fog/1.9.0/Fog/Volume/OpenStack

Page 10: Intro to fog and openstack jp

ImagesConnects to the Openstack Glance API for managing VM Images and Snapshots

http://rubydoc.info/gems/fog/1.9.0/Fog/Images/OpenStack

Page 11: Intro to fog and openstack jp

StorageConnects to the Openstack Swift API for managing Object Storage

http://rubydoc.info/gems/fog/1.9.0/Fog/Storage/OpenStack

Page 12: Intro to fog and openstack jp

NetworkConnects to the Openstack Quantum API for managing Networks

http://rubydoc.info/gems/fog/1.9.0/Fog/Network/OpenStack

Page 13: Intro to fog and openstack jp

InternalsFog follows a simple structure to handle the

management of cloud services

Page 14: Intro to fog and openstack jp

RequestsQuery the cloud service APIs

Page 15: Intro to fog and openstack jp

Mock

• Test data to return example API responses

• Requires no network connection

Page 16: Intro to fog and openstack jp

Mock (Example) class Mock

def list_flavors response = Excon::Response.new response.status = 200 response.body = { 'flavors' => [ { 'name' => '256 server', 'id' => '1', 'links' => ['https://itdoesntmatterwhatshere.heh'] }, { 'name' => '512 server', 'id' => '2', 'links' => ['https://itdoesntmatterwhatshere.heh'] }, { 'name' => '1GB server', 'id' => '3', 'links' => ['https://itdoesntmatterwhatshere.heh'] }, { 'name' => '2GB server', 'id' => '4', 'links' => ['https://itdoesntmatterwhatshere.heh'] }, { 'name' => '4GB server', 'id' => '5', 'links' => ['https://itdoesntmatterwhatshere.heh'] }, { 'name' => '8GB server', 'id' => '6', 'links' => ['https://itdoesntmatterwhatshere.heh'] }, { 'name' => '15.5GB server', 'id' => '7', 'links' => ['https://itdoesntmatterwhatshere.heh'] } ] } response end

end

Page 17: Intro to fog and openstack jp

Real

• Returns actual data from the API

Page 18: Intro to fog and openstack jp

Real (Example)

class Real

def list_flavors request( :expects => [200, 203], :method => 'GET', :path => 'flavors.json' ) end

end

Page 19: Intro to fog and openstack jp

Models

• Ruby Object representation of a Cloud Service Entity (Instance, Image, etc)

• Uses one or many ‘Request’ methods to retrieve data about an Entity

• Includes convenience methods for easy access

Page 20: Intro to fog and openstack jp

Models (Example) class Server < Fog::Compute::Server

identity :id attribute :instance_name, :aliases => 'OS-EXT-SRV-ATTR:instance_name'

attribute :addresses attribute :flavor attribute :host_id, :aliases => 'hostId' attribute :image attribute :metadata attribute :links attribute :name attribute :progress attribute :accessIPv4 attribute :accessIPv6 attribute :state, :aliases => 'status' attribute :created, :type => :time attribute :updated, :type => :time

def ready? self.state == 'ACTIVE' end

def reboot(type = 'SOFT') requires :id service.reboot_server(id, type) true end end

Page 21: Intro to fog and openstack jp

Collections

• Ruby Object representation of many groups of Cloud Service Entities (Instances, Images, etc)

• Handles querying and iteration of multiple models of a single type

Page 22: Intro to fog and openstack jp

Collections (Example) class Servers < Fog::Collection

model Fog::Compute::OpenStack::Server

def all(filters = filters) self.filters = filters data = service.list_servers_detail(filters).body['servers'] load(data) end

def get(server_id) if server = service.get_server_details(server_id).body['server'] new(server) end rescue Fog::Compute::OpenStack::NotFound nil end

end

Page 23: Intro to fog and openstack jp

Servers

Server Server Server Server

Collection

Models

Page 24: Intro to fog and openstack jp

Other methodsSpecifically for Openstack

Page 25: Intro to fog and openstack jp

• service.unscoped_token

• The reusable token which can be used to retrieve scoped tokens “auth_token” on each tenant.

• service.auth_token

• The current authentication token sent to OpenStack on each request as a header (“X-Auth-Token”).

• service.current_user

• The Hash representation of the JSON returned information about the current user returned by OpenStack upon authentication.

• service.current_tenant

• The Hash representation of the JSON returned information about the current tenant returned by OpenStack upon authentication.

• service.credentials

• A convenience method to extract needed credentials to easily instantiate a new usable service object. The new service object uses the “auth_token” returned by the OpenStack API and not the provided username and password originally used for authentication.

Page 26: Intro to fog and openstack jp

Example

Page 27: Intro to fog and openstack jp

Requirements

• Ruby (1.8.7, 1.9.2 or 1.9.3)

• Fog (Installed via: gem install fog)

Page 28: Intro to fog and openstack jp

Connection# Connect to Openstack Nova

>> compute = Fog::Compute.new({:provider => 'openstack', :openstack_tenant => 'demo', :openstack_api_key => 'yourpassword', :openstack_username => 'admin', :openstack_auth_url => 'http://localhost:35357/v2.0/tokens'})

#<Fog::Compute::OpenStack::Real:25457260 @openstack_region=nil @openstack_auth_token=nil @openstack_username="admin" @openstack_service_type=["nova", "compute"] @auth_token_expiration="2013-02-21T10:30:10Z" ... snip ... @tenant_id="ee1b6e1715644f2ca020c4190769d496" @openstack_identity_public_endpoint="http://localhost:5000/v2.0" @openstack_management_url="http://localhost:8774/v2/ee1b6e1715644f2ca020c4190769d496" @port=8774 @scheme="http" @openstack_service_name=nil>

# Query the user>> compute.current_user{"username"=>"admin", "roles_links"=>[], "id"=>"5b772e8e179249aeb7152742a4b4f6e9", "roles"=>[{"name"=>"admin"}, {"name"=>"project_manager"}, {"name"=>"Member"}], "name"=>"admin"}

# Get information about the tenant>> compute.current_tenant{"enabled"=>true, "description"=>"Demo Account", "name"=>"demo", "id"=>"ee1b6e1715644f2ca020c4190769d496"}

# Check the current state of the running instances>> compute.list_servers#<Excon::Response:0x000000030b1a28 @headers={"X-Compute-Request-Id"=>"req-eb228f6f-bec7-4fe3-8d41-69ad69dbee43", "Content-Type"=>"application/json", "Content-Length"=>"15", "Date"=>"Wed, 20 Feb 2013 10:30:13 GMT"}, @status=200, @remote_ip="127.0.0.1", @body={"servers"=>[]}>

Page 29: Intro to fog and openstack jp

Servers# Get a flavor (VM Size) to use for starting a instance

>> flavor = compute.list_flavors.body['flavors'].first{"id"=>"2", "links"=>[{"href"=>"http://localhost:8774/v2/ee1b6e1715644f2ca020c4190769d496/flavors/2", "rel"=>"self"}, {"href"=>"http://localhost:8774/ee1b6e1715644f2ca020c4190769d496/flavors/2", "rel"=>"bookmark"}], "name"=>"m1.small"}

# Get an image to use for starting a instance>> image = compute.list_images.body['images'].first{"id"=>"10a11aa4-3d9c-49e5-988c-3fde3cf37842", "links"=>[{"href"=>"http://localhost:8774/v2/ee1b6e1715644f2ca020c4190769d496/images/10a11aa4-3d9c-49e5-988c-3fde3cf37842", "rel"=>"self"}, {"href"=>"http://localhost:8774/ee1b6e1715644f2ca020c4190769d496/images/10a11aa4-3d9c-49e5-988c-3fde3cf37842", "rel"=>"bookmark"}, {"href"=>"http://10.50.2.1:9292/ee1b6e1715644f2ca020c4190769d496/images/10a11aa4-3d9c-49e5-988c-3fde3cf37842", "type"=>"application/vnd.openstack.image", "rel"=>"alternate"}], "name"=>"'64Bit_Ubuntu_12.04'"}

# Boot a new server>> compute.create_server('MyFirstServer', image['id'], flavor['id'])#<Excon::Response:0x000000031d3af0 @headers={"X-Compute-Request-Id"=>"req-a0379de9-a129-496b-b627-11853e0eefca", "Location"=>"http://localhost:8774/v2/ee1b6e1715644f2ca020c4190769d496/servers/1334c522-ab51-403f-b694-0efd92ef0b10", "Content-Type"=>"application/json", "Content-Length"=>"462", "Date"=>"Wed, 20 Feb 2013 10:36:37 GMT"}, @status=202, @remote_ip="127.0.0.1", @body={"server"=>{"security_groups"=>[{"name"=>"default"}], "OS-DCF:diskConfig"=>"MANUAL", "id"=>"1334c522-ab51-403f-b694-0efd92ef0b10", "links"=>[{"href"=>"http://localhost:8774/v2/ee1b6e1715644f2ca020c4190769d496/servers/1334c522-ab51-403f-b694-0efd92ef0b10", "rel"=>"self"}, {"href"=>"http://localhost:8774/ee1b6e1715644f2ca020c4190769d496/servers/1334c522-ab51-403f-b694-0efd92ef0b10", "rel"=>"bookmark"}], "adminPass"=>"maUXeZE76o64"}}>

# Check the current state of running instances>> servers = compute.list_servers.body['servers']#<Excon::Response:0x000000031e16c8 @headers={"X-Compute-Request-Id"=>"req-cae13781-1377-4fc5-a8d2-77394468344d", "Content-Type"=>"application/json", "Content-Length"=>"388", "Date"=>"Wed, 20 Feb 2013 10:37:01 GMT"}, @status=200, @remote_ip="127.0.0.1", @body={"servers"=>[{"id"=>"1334c522-ab51-403f-b694-0efd92ef0b10", "links"=>[{"href"=>"http://localhost:8774/v2/ee1b6e1715644f2ca020c4190769d496/servers/1334c522-ab51-403f-b694-0efd92ef0b10", "rel"=>"self"}, {"href"=>"http://localhost:8774/ee1b6e1715644f2ca020c4190769d496/servers/1334c522-ab51-403f-b694-0efd92ef0b10", "rel"=>"bookmark"}], "name"=>"MyFirstServer"}]}>

Page 30: Intro to fog and openstack jp

Model Queries# Example of a Collection query for the same data

>> compute.servers<Fog::Compute::OpenStack::Servers filters={} [ <Fog::Compute::OpenStack::Server id="1334c522-ab51-403f-b694-0efd92ef0b10", instance_name=nil, addresses={"novanetwork"=>[{"version"=>4, "addr"=>"10.2.0.6"}]}, flavor={"id"=>"2", "links"=>[{"href"=>"http://localhost:8774/ee1b6e1715644f2ca020c4190769d496/flavors/2", "rel"=>"bookmark"}]}, host_id="c1e95b9f69157e41baebad3092bd069baaf840215ecbee7edddd9bb2", image={"id"=>"10a11aa4-3d9c-49e5-988c-3fde3cf37842", "links"=>[{"href"=>"http://localhost:8774/../images/...", "rel"=>"bookmark"}]}, metadata= <Fog::Compute::OpenStack::Metadata [] >, links=[{"href"=>"http://localhost:8774/v2/.../servers/...", "rel"=>"self"}, {"href"=>"http://localhost:8774/.../servers/...", "rel"=>"bookmark"}], name="MyFirstServer", personality=nil, progress=0, accessIPv4="", accessIPv6="", availability_zone=nil, user_data_encoded=nil, state="ACTIVE", created=2013-02-20 10:36:37 UTC, updated=2013-02-20 10:37:24 UTC, tenant_id="ee1b6e1715644f2ca020c4190769d496", user_id="5b772e8e179249aeb7152742a4b4f6e9", key_name=nil, fault=nil, os_dcf_disk_config="MANUAL", os_ext_srv_attr_host="cn26.la-1-2.morphlabs.net", os_ext_srv_attr_hypervisor_hostname="cn26.la-1-2.morphlabs.net", os_ext_srv_attr_instance_name="instance-00000038", os_ext_sts_power_state=1, os_ext_sts_task_state=nil, os_ext_sts_vm_state="active" > ] >

Page 31: Intro to fog and openstack jp

Volumes# Create a 1GB persistent volume

>> compute.create_volume("MyFirstVolume", "Test Volume", 1000)# <Excon::Response:0x00000003257940 @headers={"X-Compute-Request-Id"=>"req-e98c1f91-d2b9-49cc-bf14-353fd8fa46be", "Location"=>"http://localhost:8774/v2/ee1b6e1715644f2ca020c4190769d496/os-volumes?ignore_awful_caching1361357305/664000aa-e275-4e86-a477-7be86927979b", "Content-Type"=>"application/json", "Content-Length"=>"311", "Date"=>"Wed, 20 Feb 2013 10:48:27 GMT"}, @status=200, @remote_ip="127.0.0.1", @body={"volume"=>{"status"=>"creating", "displayDescription"=>"Test Volume", "availabilityZone"=>"nova", "displayName"=>"MyFirstVolume", "attachments"=>[{}], "volumeType"=>nil, "snapshotId"=>nil, "metadata"=>{}, "id"=>"664000aa-e275-4e86-a477-7be86927979b", "createdAt"=>"2013-02-20T10:48:26.709904", "size"=>1000}}>

# Query information about the current volumes for this tenant>> compute.list_volumes.body['volumes'].first{"status"=>"available", "displayDescription"=>"Test Volume", "availabilityZone"=>"nova", "displayName"=>"MyFirstVolume", "attachments"=>[{}], "volumeType"=>nil, "snapshotId"=>nil, "metadata"=>{}, "id"=>"664000aa-e275-4e86-a477-7be86927979b", "createdAt"=>"2013-02-20T10:48:26.000000", "size"=>1000}

# Attach the Volume to the running server>> compute.attach_volume(compute.list_volumes.body['volumes'].first['id'], compute.servers.first.id, "vdc")#<Excon::Response:0x000000032b0680 @headers={"X-Compute-Request-Id"=>"req-b6a2bad1-b69d-4abc-a3e6-88d1fc044827", "Content-Type"=>"application/json", "Content-Length"=>"194", "Date"=>"Wed, 20 Feb 2013 10:54:12 GMT"}, @status=200, @remote_ip="127.0.0.1", @body={"volumeAttachment"=>{"device"=>"/dev/vdc", "serverId"=>"1334c522-ab51-403f-b694-0efd92ef0b10", "id"=>"664000aa-e275-4e86-a477-7be86927979b", "volumeId"=>"664000aa-e275-4e86-a477-7be86927979b"}}>

# Check volumes by querying the Volumes collection>> compute.volumes.first <Fog::Compute::OpenStack::Volume id="664000aa-e275-4e86-a477-7be86927979b", name="MyFirstVolume", description="Test Volume", status="in-use", size=1000, type=nil, snapshot_id=nil, availability_zone="nova", created_at="2013-02-20T10:48:26.000000", attachments=[{"device"=>"/dev/vdc", "serverId"=>"1334c522-ab51-403f-b694-0efd92ef0b10", "id"=>"664000aa-e275-4e86-a477-7be86927979b", "volumeId"=>"664000aa-e275-4e86-a477-7be86927979b"}] >

Page 32: Intro to fog and openstack jp

Cleanup

# Remove the Volume from the instance>> compute.detach_volume(compute.servers.first.id, compute.list_volumes.body['volumes'].first['id'])#<Excon::Response:0x0000000338e278 @headers={"Content-Type"=>"text/html; charset=UTF-8", "Content-Length"=>"0", "Date"=>"Wed, 20 Feb 2013 10:58:10 GMT"}, @status=202, @remote_ip="127.0.0.1", @body="">

# Delete the Volume from the system>> compute.delete_volume(compute.list_volumes.body['volumes'].first['id'])#<Excon::Response:0x0000000339f6b8 @headers={"Content-Type"=>"text/html; charset=UTF-8", "Content-Length"=>"0", "Date"=>"Wed, 20 Feb 2013 10:59:22 GMT"}, @status=202, @remote_ip="127.0.0.1", @body="">

# Check volumes again>> compute.list_volumes.body['volumes']# []

# Cleanup the system by deleting the instancecompute.delete_server(servers.first['id'])#<Excon::Response:0x000000033b9dd8 @headers={"Content-Length"=>"0", "X-Compute-Request-Id"=>"req-ef6c799f-7832-4edf-9929-387d5957320a", "Content-Type"=>"application/json", "Date"=>"Wed, 20 Feb 2013 11:00:17 GMT"}, @status=204, @remote_ip="127.0.0.1", @body="">

Page 33: Intro to fog and openstack jp

Thank you!