Introduction
Misty is a HTTP client for OpenStack APIs, aiming to be slick and dynamic.
Misty handles OpenStack APIs requests as Transparently as possible by:
- Directly submitting request to Openstack Service endpoints
- Or by using APIs Schema defined functions which are dynamically extracted from OpenStackAPI reference.
Main features
- Standardized OpenStack APIs: Based upon API-ref offering flexibility to easily integrate new OpenStack services. Any request can be overridden or completed
- Microversions & Legacy Versions
- Transparent request data handling and response data format of choice: JSON or Hash
- Custom HTTP Methods for special needs
- And also: Lazy service loading, Low gem dependency (use only Net/HTTP and JSON), Persistent HTTP connections (default since HTTP 1.1 anyway)
Current Microversion support
- Cinder v3.44
- Ironic v1.32
- Magnum v1.4
- Manilla v2.40
- Nova v2.60
How To
Fetch and install
gem install misty
Get started
Create a Misty::Cloud
object with mandatory :auth
parameter such as:
require 'misty'
cloud = Misty::Cloud.new(
:auth => {
:url => 'http://localhost:5000',
:user => 'admin',
:password => 'secret',
:domain => 'default',
:project => 'admin',
:project_domain_id => 'default'
})
Then requets can be made against OpenStack services:
servers = cloud.compute.list_servers.body
networks = cloud.networking.list_networks
first_network_id = networks.body['networks'][0]['id']
first_network = cloud.networking.show_network_details(first_network_id)
network = Misty.to_json(:network => {:name => 'misty-example'})
cloud.network.create_network(network)
v1 = cloud..show_v1_api
Configuration
To provide the maximum flexibility, there are 4 levels of configuration which are always propagated from top to bottom.
- The Cloud global defaults
- The Cloud global parameters
- The service level parameters
- The request level ephemeral parameters
No global parameters provided, the defaults are applied.
cloud = Misty::Cloud.new(:auth => { ... })
Some provided global parameters, which override respective global and apply at service level.
cloud = Misty::Cloud.new(:auth => { ... }, :log_file => './misty.log', :headers => {"x-tra:" => "value"})
Provided service level parameters are applied for all service requests.
Some such as the headers are cumulative.
Others such as the microversion feature, don't have global definition.
cloud = Misty::Cloud.new(:auth => { ... }, compute {:version => 2.60})
# All following requests are going to be with version 2.60, unless overridden at request level
cloud.compute.list_servers
And finally, at requests level, provided parameters are ephemeral
cloud = Misty::Cloud.new(:auth => { ... })
cloud.compute(:version => 'latest', :content_type => :json, :headers => {"key" => "value"}).list_servers
# Back to defaults (since there are no global or service level parameters provided)
cloud.compute.list_servers
Authentication
Openstack Identity service Keystone version 3 is the default, version 2.0, although deprecated, is available.
Parameters
The following parameters can be used: To authenticate with credentials details:
:context
- Allow to provide already authenticated context(catalog, token, expiry time). Used for v2.0 only. Exclusive with other parameters.:domain_id
- Domain id, default: "default":domain
- Domain name, default: "Default":password
- User password. Exclusive with :token.:project_id
- Project id:project
- Project name:project_domain_id
- Project domain id:project_domain
- Project domain name:ssl_verify_mode
- Boolean flag for SSL client verification. SSL is defined when URI scheme => "https://".:tenant_id
- Tenant id, used for v2.0 only.:tenant
- Tenant name, used for v2.0 only.:token
- Allow to provide unscoped token.:user_id
- User id:user
- User name:user_domain_id
- User domain id:user_domain
- User domain name
Keystone v3
Version 3 relies on the concept of domain name or id to authenticates
Misty::AuthV3
is used by default unless authentication credentials contains a tenant name or id in wich case it
will use on Misty::AuthV2
.
The credentials are a combination of "id" and "name" used to uniquely identify projects, users and their domains. When using only the name, a domain must be specified to guarantee a unique record from the Identity service.
Examples
auth = {
:url => 'http://localhost:5000',
:user => 'admin',
:user_domain => 'default',
:password => 'secret',
:project => 'admin',
:project_domain => 'default'
}
}
cloud = Misty::Cloud.new(:auth => auth_v3)
# The API requests are of course specific to this version:
cloud.identity.list_projects
Using IDs:
auth = {
:url => 'http://localhost:5000',
:user_id => '48985e6b8da145699d411f12a3459fca',
:password => 'secret',
:project_id => '8e1e232f6cbb4116bbef715d8a0afe6e',
}
}
Or alternatively using a context
context = { :context => { :token => token_id, :catalog => service_catalog, :expires => expire_date } }
cloud = Misty::Cloud.new(:auth => context)
Keystone v2.0
By providing tenant details Misty will detect it's using v2.0 for authentication:
auth = {
:url => 'http://localhost:5000',
:user => 'admin',
:password => 'secret',
:tenant => 'admin',
}
cloud = Misty::Cloud.new(:auth => auth_v2)
# The API requests are of course specific to this version:
cloud.identity.list_tenants
Note
It's possible to authenticate against Keystone V3 and use the identity service v2.0, for instance: In which case API set for v2.0 applies: tenants are available but not the projects.
cloud = Misty::Cloud.new(:auth => auth_v3)
cloud.identity(:api_version => 'v2.0')
Global configuration options
The configuration parameters used to initialize Misty::Cloud
are global. They are optionals and Misty::Config
defaults are applied if needed.
:auth
- Authentication credentials hash containing 'auth_url' and user context. SeeMisty::Auth
.:content_type
- HTTP responses body format. :json or :hash structures. Default isMisty::Config::CONTENT_TYPE
.:headers
- Hash of extra HTTP headers to be applied to all services:interface
- Endpoint interface, allowed values are: "public", "internal", "admin".:log_file
- Log destination, Value is either file path (./misty.log) or IO object (SDOUT). Default is '/dev/null':log_level
- Value is Fixnum - Default is 1 (Logger::INFO) - See Logger from Ruby standard Library:region_id
- Alternative Region identifier. Default isMisty::Config::REGION_ID
Default isMisty::Config::INTERFACE
:ssl_verify_mode
- Boolean flag for SSL client verification. SSL is defined when URI scheme => "https://". Default isMisty::Config::SSL_VERIFY_MODE
SeeMisty::Config
for more details
Headers
Headers are cumulative, applied from Cloud top level, then at Service level and finally at request level.
HTTP headers can effectively be optionally added to any request. An Header object must be created and passed as the last parameter of a request.
For example for an already initialized cloud:
header = Misty::HTTP::Header.new(
'x-container-meta-web-listings' => false,
'x-container-meta-quota-count' => "",
'x-container-meta-quota-bytes' => nil,
'x-versions-location' => "",
'x-container-meta-web-index' => ""
)
openstack.object_storage.(container_name, header)
Service and Request levels configuration parameters
The same parameters used at the global configuration variables can be applied at Service level or at a Request level.
The global values passed from Misty::Cloud
level are then overridden at the Service level.
The following parameters can be also used:
:api_version
- String for specifying Openstack API service version to use. Default is latest supported version. Applies only at service level as it's needed for service creation.:base_path
- Allows to force the base path for every URL requests Default nil.:base_url
- Allows to force the base URL for every requests. Default nil.:version
- Version to be used when microversion is supported by the service. Default:nil
Allowed values:'latest'
, or a version number such as '2.10'
Examples
Initialize cloud
cloud = Misty::Cloud.new(:auth => { ... }, region_id => 'regionOne', :log_level => 0)
Then use different options, for example, the identify service, therefore overriding respective global defaults or specified values
cloud.identity => {:region_id => 'regionTwo', :interface => 'admin'}
Provide service specific option
cloud.compute => {:version => '2.27'})
Services
The latest list of supported service can be obtain from Misty.services
:
require 'misty'
puts Misty.services
=>
application_catalog: murano, versions: ["v1"]
alarming: aodh, versions: ["v2"]
backup: freezer, versions: ["v1"]
baremetal: ironic, versions: ["v1"], microversion: v1
block_storage: cinder, versions: ["v3", "v2", "v1"], microversion: v3
clustering: senlin, versions: ["v1"]
compute: nova, versions: ["v2.1"], microversion: v2.1
container_infrastructure_management: magnum, versions: ["v1"], microversion: v1
data_processing: sahara, versions: ["v1.1"]
data_protection_orchestration: karbor, versions: ["v1"]
database: trove, versions: ["v1.0"]
dns: designate, versions: ["v2"]
identity: keystone, versions: ["v3", "v2.0"]
image: glance, versions: ["v2", "v1"]
load_balancer: octavia, versions: ["v2.0"]
messaging: zaqar, versions: ["v2"]
metering: ceilometer, versions: ["v2"]
networking: neutron, versions: ["v2.0"]
nfv_orchestration: tacker, versions: ["v1.0"]
object_storage: swift, versions: ["v1"]
orchestration: heat, versions: ["v1"]
search: searchlight, versions: ["v1"]
shared_file_systems: manila, versions: ["v2"], microversion: v2
Service Prefix
A shorter name can be used to call a service only if it's unique among all services.
For instance net
or network
can be used instead of networking
because it's not ambiguous.
Meanwhile data
doesn't work because it's ambiguous between data_processing
and data_protection_orchestration
Aliases
domain_name_server
is an alias fordns
volume
is an alias forblock_storage
Requests
The exhaustive list of requests, extracted from the current service API's and cumulated with Misty service defined requests if any, is available as follow:
Example (Output truncated)
cloud.compute.requests
=> [:add_a_single_tag,
:add_associate_fixed_ip_addfixedip_action_deprecated,
:add_associate_floating_ip_addfloatingip_action_deprecated,
:add_flavor_access_to_tenant_addtenantaccess_action,
:add_host,
:add_network,
:add_security_group_to_a_server_addsecuritygroup_action,
:associate_host_deprecated,
:attach_a_volume_to_an_instance,
:bulk_delete_floating_ips,
:capacities,
:change_administrative_password_changepassword_action,
:check_tag_existence,
:clear_admin_password,
:confirm_resized_server_confirmresize_action,
:create_agent_build,
:create_aggregate,
:create_allocate_floating_ip_address,
:create_assisted_volume_snapshots,
:create_cell,
:create_cloudpipe,
:create_console,
Direct HTTP requests to REST resources
To send requests directly use the 'get', 'delete', 'post' and 'put' methods directly:
openstack.network.post('/v2.0/qos/policies/48985e6b8da145699d411f12a3459fca/dscp_marking_rules', data)
Orchestration
Example
heat_template = {
"files": {},
"disable_rollback": true,
"parameters": {
"flavor": "m1.tiny"
},
"stack_name": "test_stack",
"template": {
"heat_template_version": "2013-05-23",
"description": "Template to test heat",
"parameters": {
"flavor": {
"default": "m1.small",
"type": "string"
}
},
"resources": {
"hello_world": {
"type": "OS::Nova::Server",
"properties": {
"flavor": { "get_param": "flavor" },
"image": "50fd6f2b-d9f0-41b6-b0a9-4482bfe61914",
"user_data": "/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
}
}
}
},
"timeout_mins": 60
}
require 'misty'
require 'pp'
cloud = Misty::Cloud.new(:auth => { ... })
data_heat_template = Misty.to_json(heat_template)
response = cloud.orchestration.create_stack(data_heat_template)
id = response.body['stack']['id']
stack = cloud.orchestration.show_stack_details('test_stack', id)
pp stack.body
Some usage examples
cloud = Misty::Cloud.new(:auth => { ... })
pp cloud.compute.versions
=> [{"status"=>"SUPPORTED",
"updated"=>"2011-01-21T11:33:21Z",
"links"=>[{"href"=>"http://192.0.2.1:8774/v2/", "rel"=>"self"}],
"min_version"=>"",
"version"=>"",
"id"=>"v2.0"},
{"status"=>"CURRENT",
"updated"=>"2013-07-23T11:33:21Z",
"links"=>[{"href"=>"http://192.0.2.1:8774/v2.1/", "rel"=>"self"}],
"min_version"=>"2.1",
"version"=>"2.53",
"id"=>"v2.1"}]
cloud.compute(:version => '2.25')
data_keypair = Misty.to_json('keypair': {'name': 'admin-keypair'})
admin_keypair = cloud.compute.create_or_import_keypair(data_keypair)
user_id = admin_keypair.body['keypair']['user_id']
keypairs = cloud.compute.list_keypairs
pp keypairs.body
Nova version 2.10+, a keypair name can be filtered by user_id
user_id=1e50c2f0995446fd9b135a1a549cabdb
cloud.compute(:version => '2.10').show_keypair_details("admin-keypair?user_id=#{user_id}")
With Nova version 2.2+, the type field is also returned when showing keypair details
cloud.compute(:version => '2.2')
pp admin_keypair.body
=> {'keypair'=>
{'public_key'=>
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjenEe7B87OQHYjZAdJWmaY13mF0N3VooviHypEXaSDfEmFj4GinXorKD0kdXAL30orT0wgAVtpAvRhH2iFTPF2VKCdq4VMzLuai60e3oB3vsTWdZQIJtvaW0mpTNVUQKczbFhRFUi4CNsAijjmGJJgxhihd6rAfynFtalLO0yNn3dKtEMbsvs7KeMxT9SXbfLmEXD4reAK/WXQBVjrEjJIgpC3+SXOO6vsavaOTFu7/Nbha/p4g4yJ3rHUU+7lj79a7iy0sNeExBSZ2aKTq7FQ5XDmtZjjpUeas16kMMX5HdxISYkbq3QnG9iTrIy+GEAYKkZPzhuAa76Qpze35aV Generated-by-Nova\n',
'user_id'=>'1e50c2f0995446fd9b135a1a549cabdb',
'name'=>'admin-keypair',
'deleted'=>false,
'created_at'=>'2016-11-23T01:23:53.000000',
'updated_at'=>nil,
'fingerprint'=>'4e:db:2d:bd:93:70:01:b8:61:17:96:23:e0:78:e2:69',
'deleted_at'=>nil,
'type'=>'ssh',
'id'=>8}}
OpenstackAPI notes
Neutron
Driver Vendor Passthru (drivers) has 2 methods call with same name. One for Node Vendor Passthru and one for Drivers Passthru. They are respectively associated with the methods #call_a_vendor_method and #call_a_driver_method.
Ruby versions tested
- Ruby MRI 2.5.0
- Ruby MRI 2.4.2
- Ruby MRI 2.3.4
Contributing
Contributors are welcome and must adhere to the Contributor covenant code of conduct.
Please submit issues/bugs and patches on the Misty repository.
Copyright
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ - See LICENSE for details.