Git Product home page Git Product logo

fog-openstack's Introduction

Fog::OpenStack

Gem Version Build Status Dependency Status Coverage Status Code Climate Join the chat at https://gitter.im/fog/fog-openstack

This is the plugin Gem to talk to OpenStack clouds via fog.

The main maintainers for the OpenStack sections are @dhague, @Ladas, @seanhandley, @mdarby and @jjasghar. Please send CC them on pull requests.

Supported OpenStack APIs

See the list of supported OpenStack projects.

Installation

Add this line to your application's Gemfile:

gem 'fog-openstack'

And then execute:

$ bundle

Or install it yourself as:

$ gem install fog-openstack

Usage

Initial Setup

Require the gem:

require "fog/openstack"

Checklist:

  • Before you can do anything with an OpenStack cloud, you need to authenticate yourself with the identity service, "Keystone".
  • All following examples assume that @connection_params is a hash of valid connection information for an OpenStack cloud.
  • The :openstack_username and :openstack_api_key keys must map to a valid user/password combination in Keystone.
  • If you don't know what domain your user belongs to, chances are it's the default domain. By default, all users are a member of the default domain unless otherwise specified.
  • Keystone endpoints are version less. Version 3 is the default as v2.0 is deprecated. Meanwhile Keystone V3 still supports v2.0 for backward compatibility. Therefore passing a tenant instead of a project (along with a domain) makes Keystone provide v2.0 token. Connection parameters:
@connection_params = {
  openstack_auth_url:     "http://devstack.test:5000",
  openstack_username:     "admin",
  openstack_api_key:      "password",
  openstack_project_name: "admin",
  openstack_domain_id:    "default"
}

If you're using Keystone V2, you don't need to supply domain details but ensure to either provide a tenant name (openstack_tenant) or a tenant id (openstack_tenant_id). Alternatively you can use :openstack_identity_api_version parameter with 'v2.0'.

@connection_params = {
  openstack_auth_url: "http://devstack.test:5000",
  openstack_username: "admin",
  openstack_api_key:  "password",
  openstack_tenant:   "admin"
}

If you're not sure whether your OpenStack cloud uses Keystone V2 or V3 then you can find out by logging into the dashboard (Horizon) and navigating to "Access & Security" under the "Project" section. Select "API Access" and find the line for the Identity Service. If the endpoint has "v3" in it, you're on Keystone V3, if it has "v2" then (surprise) you're on Keystone V2.

If you need a version of OpenStack to test against, get youself a copy of DevStack.

Networking Gotcha

Note that tenants (aka projects) in OpenStack usually require that you create a default gateway router in order to allow external access to your instances.

The exception is if you're using Nova (and not Neutron) for your instance networking. If you're using Neutron, you'll want to set up your default gateway before you try to give instances public addresses (aka floating IPs).

Compute (Nova)

Initialise a connection to the compute service:

compute = Fog::OpenStack::Compute.new(@connection_params)

Get a list of available images for use with booting new instances:

p compute.images
# =>   <Fog::OpenStack::Compute::Images
#     filters={},
#     server=nil
#     [
#                   <Fog::OpenStack::Compute::Image
#         id="57a67f8a-7bae-4578-b684-b9b4dcd48d7f",
#         ...
#       >
#     ]
#   >

List available flavors so we can decide how powerful to make this instance:

p compute.flavors
# =>   <Fog::OpenStack::Compute::Flavors
#     [
#                   <Fog::OpenStack::Compute::Flavor
#         id="1",
#         name="m1.tiny",
#         ram=512,
#         disk=1,
#         vcpus=1,
#         ...
#       >,
#                   <Fog::OpenStack::Compute::Flavor
#         id="2",
#         name="m1.small",
#         ram=2048,
#         disk=20,
#         vcpus=1,
#         ...
#       >,
#       ...

Now we know the id numbers of a valid image and a valid flavor, we can instantiate an instance:

flavor   = compute.flavors[0]
image    = compute.images[0]
instance = compute.servers.create name: 'test',
                                  image_ref: image.id,
                                  flavor_ref: flavor.id

# Optionally, wait for the instance to provision before continuing
instance.wait_for { ready? }
# => {:duration=>17.359134}

p instance
# =>   <Fog::OpenStack::Compute::Server
#     id="63633125-26b5-4fe1-a909-0f44d1ab3337",
#     instance_name=nil,
#     addresses={"public"=>[{"OS-EXT-IPS-MAC:mac_addr"=>"fa:16:3e:f4:75:ab", "version"=>4, "addr"=>"1.2.3.4", "OS-EXT-IPS:type"=>"fixed"}]},
#     flavor={"id"=>"2"},
#     host_id="f5ea01262720d02e886508bc4fa994782c516557d232c72aeb79638e",
#     image={"id"=>"57a67f8a-7bae-4578-b684-b9b4dcd48d7f"},
#     name="test",
#     personality=nil,
#     progress=0,
#     accessIPv4="",
#     accessIPv6="",
#     availability_zone="nova",
#     user_data_encoded=nil,
#     state="ACTIVE",
#     created=2016-03-07 08:07:36 UTC,
#     updated=2016-03-07 08:07:52 UTC,
#     tenant_id="06a9a90c60074cdeae5f7fdd0048d9ac"
#     ...
#   >

And destroy it when we're done:

instance.destroy
# => true

You'll probably need your instances to be accessible via SSH. Learn more about SSH keypairs.

Allow TCP traffic through port 22:

security_group = compute.security_groups.create name:  "Test SSH",
                                                description: "Allow access to port 22"
# =>   <Fog::OpenStack::Compute::SecurityGroup
#     id="e5d53d00-b3f9-471a-b90f-985694b966ed",
#     name="Test SSH",
#     description="Allow access to port 22",
#     security_group_rules=    <Fog::OpenStack::Compute::SecurityGroupRules
#       [

#       ]
#     >,
#     tenant_id="06a9a90c60074cdeae5f7fdd0048d9ac"
#   >

compute.security_group_rules.create parent_group_id: security_group.id,
                                    ip_protocol:     "tcp",
                                    from_port:       22,
                                    to_port:         22

key_pair = compute.key_pairs.create name:       "My Public Key",
                                    public_key: "/full/path/to/ssh.pub"
# =>   <Fog::OpenStack::Compute::KeyPair
#     name="My Public Key",
#     ...
#     user_id="20746f49211e4037a91269df6a3fbf7b",
#     id=nil
#   >

Now create a new server using the security group and keypair we created:

instance = compute.servers.create name:            "Test 2",
                                  image_ref:       image.id,
                                  flavor_ref:      flavor.id,
                                  key_name:        key_pair.name,
                                  security_groups: security_group
# =>   <Fog::OpenStack::Compute::Server
#     id="e18ebdfb-e5f5-4a45-929f-4cc9926dc2c7",
#     name="Test 2",
#     state="ACTIVE",
#     tenant_id="06a9a90c60074cdeae5f7fdd0048d9ac",
#     key_name="My Public Key",
#   >
# (some data omitted for brevity)

Finally, assign a floating IP address to make this instance sit under a world-visible public IP address:

pool_name = compute.addresses.get_address_pools[0]['name']
floating_ip_address = compute.addresses.create pool: pool_name
instance.associate_address floating_ip_address.ip

p floating_ip_address
# =>   <Fog::OpenStack::Compute::Address
#     id="54064324-ce7d-448d-9753-94497b29dc91",
#     ip="1.2.3.4",
#     pool="external",
#     fixed_ip="192.168.0.96",
#     instance_id="e18ebdfb-e5f5-4a45-929f-4cc9926dc2c7"
#   >

Now you can SSH into the instance:

$ ssh [email protected]
The authenticity of host '1.2.3.4 (1.2.3.4)' can't be established.
RSA key fingerprint is SHA256:cB0L/owUtcHsMhFhsuSZXxK4oRg/uqP/6IriUomQnQQ.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '1.2.3.4' (RSA) to the list of known hosts.
$ pwd
/home/cirros

Volume (Cinder)

Create and attach a volume to a running instance:

compute = Fog::OpenStack::Compute.new(@connection_params)

volume = compute.volumes.create name:        "Test",
                                description: "Testing",
                                size:        1
# =>   <Fog::OpenStack::Compute::Volume
#     id="4a212986-c6b6-4a93-8319-c6a98e347750",
#     name="Test",
#     description="Testing",
#     size=1,
#     availability_zone="Production",
#     created_at="2016-03-07T13:40:43.914063",
#     attachments=[{}]
#   >

flavor   = compute.flavors[3]
image    = compute.images[0]
instance = compute.servers.create name:       "test",
                                  image_ref:  image.id,
                                  flavor_ref: flavor.id
instance.wait_for { ready? }

volume.reload

instance.attach_volume(volume.id, "/dev/vdb")

Detach volume and create a snapshot:

instance.detach_volume(volume.id)
volume.reload

compute.snapshots.create volume_id:   volume.id,
                         name:        "test",
                         description: "test"
# =>   <Fog::OpenStack::Compute::Snapshot
#     id="7a8c9192-25ee-4364-be91-070b7a6d9855",
#     name="test",
#     description="test",
#     volume_id="4a212986-c6b6-4a93-8319-c6a98e347750",
#     status="creating",
#     size=1,
#     created_at="2016-03-07T13:47:11.543814"
#   >

Destroy a volume:

volume.destroy
# => true

Image (Glance)

Download Glance image:

image = Fog::OpenStack::Image.new(@connection_params)

image_out = File.open("/tmp/cirros-image-download", 'wb')

streamer = lambda do |chunk, _, _|
  image_out.write chunk
end

image.download_image(image.images.first.id, response_block: streamer)

Create Glance image from file or URL:

cirros_location = "http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img"
image_out = File.open("/tmp/cirros-image-#{SecureRandom.hex}", 'wb')

streamer = lambda do |chunk, _, _|
  image_out.write chunk
end

Excon.get cirros_location, response_block: streamer
image_out.close

image_handle = image.images.create name:             "cirros",
                                   disk_format:      "qcow2",
                                   container_format: "bare"

# => <Fog::OpenStack::Image::V2::Image
#      id="67c4d02c-5601-4619-bd14-d2f7f96a046c",
#      name="cirros",
#      visibility="private",
#      tags=[],
#      self="/v2/images/67c4d02c-5601-4619-bd14-d2f7f96a046c",
#      size=nil,
#      disk_format="qcow2",
#      container_format="bare",
#      id="67c4d02c-5601-4619-bd14-d2f7f96a046c",
#      checksum=nil,
#      self="/v2/images/67c4d02c-5601-4619-bd14-d2f7f96a046c",
#      file="/v2/images/67c4d02c-5601-4619-bd14-d2f7f96a046c/file",
#      min_disk=0,
#      created_at="2016-10-31T03:38:28Z",
#      updated_at="2016-10-31T03:38:28Z",
#      protected=false,
#      status="queued",
#      min_ram=0,
#      owner="6b9ec8080b8443c5afe2267a39b9bf74",
#      properties=nil,
#      metadata=nil,
#      location=nil,
#      network_allocated=nil,
#      base_image_ref=nil,
#      image_type=nil,
#      instance_uuid=nil,
#      user_id=nil
#    >


image_handle.upload_data File.binread(image_out.path)

Destroy image:

cirros = image.images.get("4beedb46-e32f-4ef3-a87b-7f1234294dc1")
cirros.destroy

Identity (Keystone)

List domains (Keystone V3 only):

identity = Fog::OpenStack::Identity.new(@connection_params)

identity.domains
# =>   <Fog::OpenStack::Identity::V3::Domains
#     [
#                   <Fog::OpenStack::Identity::V3::Domain
#         id="default",
#         description="",
#         enabled=true,
#         name="Default",
#       >
#     ]
#   >

List projects (aka tenants):

identity.projects
# =>   <Fog::OpenStack::Identity::V3::Projects
#     [
#                   <Fog::OpenStack::Identity::V3::Project
#         id="008e5537d3424295a03560abc923693c",
#         domain_id="default",
#         description="Project 1",
#         enabled=true,
#         name="project_1",
#       >,
#        ...
#        ]

# On Keystone V2
identity.tenants
# =>   <Fog::OpenStack::Identity::V2::Tenants
#     [ ... ]

List users:

identity.users
# =>   <Fog::OpenStack::Identity::V3::Users
#     [ ... ]

Create/destroy new user:

project_id = identity.projects[0].id

user = identity.users.create name: "test",
                             project_id: project_id,
                             email: "[email protected]",
                             password: "test"
# =>   <Fog::OpenStack::Identity::V3::User
#     id="474a59153ebd4e709938e5e9b614dc57",
#     default_project_id=nil,
#     description=nil,
#     domain_id="default",
#     email="[email protected]",
#     enabled=true,
#     name="test",
#     password="test"
#   >

user.destroy
# => true

Create/destroy new tenant:

project = identity.projects.create name: "test",
                                   description: "test"
# =>   <Fog::OpenStack::Identity::V3::Project
#     id="423559128a7249f2973cdb7d5d581c4d",
#     domain_id="default",
#     description="test",
#     enabled=true,
#     name="test",
#     parent_id=nil,
#     subtree=nil,
#     parents=nil
#   >

project.destroy
# => true

Grant user role on tenant and revoke it:

role = identity.roles.select{|role| role.name == "_member_"}[0]
# =>   <Fog::OpenStack::Identity::V3::Role
#     id="9fe2ff9ee4384b1894a90878d3e92bab",
#     name="_member_",
#   >

project.grant_role_to_user(role.id, user.id)

project.revoke_role_from_user(role.id, user.id)

Networking (Neutron)

Set up a project's public gateway (needed for external access):

identity  = Fog::OpenStack::Identity.new(@connection_params)

tenants = identity.projects.select do |project|
  project.name == @connection_params[:openstack_project_name]
end

tenant_id = tenants[0].id

neutron = Fog::OpenStack::Network.new(@connection_params)

network = neutron.networks.create name:      "default",
                                  tenant_id: tenant_id

subnet  = network.subnets.create  name:            "default",
                                  cidr:            "192.168.0.0/24",
                                  network_id:      network.id,
                                  ip_version:      4,
                                  dns_nameservers: ["8.8.8.8", "8.8.4.4"],
                                  tenant_id:       tenant_id

external_network = neutron.networks.select(&:router_external)[0]

router = neutron.routers.create   name:                  'default',
                                  tenant_id:             tenant_id,
                                  external_gateway_info: external_network.id

neutron.add_router_interface router.id, subnet.id

Further Reading

Development

$ git clone https://github.com/fog/fog-openstack.git # Clone repository
$ cd fog-openstack; bin/setup   # Install dependencies from project directory
$ bundle exec rake test   # Run tests
$ bundle exec rake spec   # Run tests
$ bin/console   # Run interactive prompt that allows you to experiment (optional)
$ bundle exec rake install   # Install gem to your local machine (optional)

You can also use a docker image for development and running tests. Once you have cloned the repository, it can be run with:

$ docker-compose up test
$ docker-compose up ruby # Start a container with the ruby environment

In order to release a new version, perform the following steps:

  1. Update version number in version.rb.
  2. Run bundle exec rake release, which will create a git tag for the version.
  3. Push git commits and tags.
  4. Push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/fog/fog-openstack. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

fog-openstack's People

Contributors

andypf avatar andyvesel avatar apophizzz avatar ares avatar aufi avatar auhlig avatar beyhan avatar carthaca avatar dhague avatar foreverqihe avatar geemus avatar gildub avatar ioggstream avatar kevinloiseau avatar ladas avatar mansam avatar mrhillsman avatar normandlemay avatar plribeiro3000 avatar rb1whitney avatar rwsu avatar scambra avatar seanhandley avatar shamox avatar shaneboulden avatar sseago avatar timuralp avatar tlesmann avatar voelzmo avatar zhitonglbn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fog-openstack's Issues

503 Service Unavailable

Hi there,
I am trying to get fog working with swift at an OpenStack provider. I get what seems to be a correct service object after creation (correct urls and credentials for interacting with swift). When I try to use that object, I get 503 Service Unavailable for requests. How can I debug this? I get the full excon response object after the unexpected response. Am I able to capture the request object so that I can see what is going on?
Thanks,
Robert

Original issue opened by @robear at fog/fog#3696

Authenticates using passwordCredentials always

Is there a way to use an API key?
Currently I use the connection param openstack_api_key: 'password' and it uses passwordCredentials to authenticate, however this isn't always optimal.

I've migrated from the rackspace gem to the openstack as it is easier to work with both rackspace and openstack clouds. However I could use an API key in the rackspace version

Can not reload glance image model

When create glance image model via glance v2 api, following error occurs.

E, [2016-04-11T07:51:38.359236 #5466] ERROR -- : identity is required for this operation (ArgumentError)

I think this issue related to this code.

Openstack methods assume the extension for floating IP's is loaded

server.public_ip_address and server.private_ip_address fail when executed against an Openstack implementation without the floating-ip extension loaded. I'm not sure how common this is, but Rackspace does it. While fog has a separate Rackspace provider, other small openstack implementations may follow their lead on config options.

Stacktraces:

irb(main):006:0> server.public_ip_address
Fog::Compute::OpenStack::NotFound: Fog::Compute::OpenStack::NotFound
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/excon-0.25.3/lib/excon/middlewares/expects.rb:10:in `response_call'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/excon-0.25.3/lib/excon/middlewares/response_parser.rb:8:in `response_call'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/excon-0.25.3/lib/excon/connection.rb:349:in `response'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/excon-0.25.3/lib/excon/connection.rb:247:in `request'
from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/core/connection.rb:57:in `request'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/core/deprecated/connection.rb:20:in `request'
   from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/compute.rb:339:in `request'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/requests/compute/list_all_addresses.rb:10:in `list_all_addresses'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/models/compute/server.rb:95:in `all_addresses'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/models/compute/server.rb:110:in `floating_ip_addresses'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/models/compute/server.rb:116:in `floating_ip_address'
    from (irb):6
    from /usr/local/bin/irb:12:in `<main>'

irb(main):007:0> server.private_ip_address
Fog::Compute::OpenStack::NotFound: Fog::Compute::OpenStack::NotFound
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/excon-0.25.3/lib/excon/middlewares/expects.rb:10:in `response_call'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/excon-0.25.3/lib/excon/middlewares/response_parser.rb:8:in `response_call'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/excon-0.25.3/lib/excon/connection.rb:349:in `response'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/excon-0.25.3/lib/excon/connection.rb:247:in `request'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/core/connection.rb:57:in `request'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/core/deprecated/connection.rb:20:in `request'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/compute.rb:339:in `request'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/requests/compute/list_all_addresses.rb:10:in `list_all_addresses'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/models/compute/server.rb:95:in `all_addresses'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/models/compute/server.rb:110:in `floating_ip_addresses'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/models/compute/server.rb:122:in `private_ip_addresses'
    from /usr/local/Cellar/ruby/1.9.3-p392/lib/ruby/gems/1.9.1/gems/fog-1.15.0/lib/fog/openstack/models/compute/server.rb:126:in `private_ip_address'
    from (irb):7
    from /usr/local/bin/irb:12:in `<main>'

This was discovered while testing kitchen-openstack: test-kitchen/kitchen-openstack#16

Original issue opened by @mikelococo at fog/fog#2160.

Fog and resource registry

I tried to use a nested template to deploy my autoscaling system using by a template.
In the template I use a nested template. It works fine with heat CLI command. Validation error occurs when I use Fog.

I tried to pass environment yaml file to Fog by ':environment' and then by ':files' option, but heat-api gives back a validate error:

"Failed to validate: Unknown resource Type : http://localhost:3000/hot/lb_node_yaml"

same error occurs when I tried file:/// resource type

same template works well from CLI.

Please help

Original issue opened by @vizes-nyolcas at fog/fog#3834

inconsistent model-collection methods to get by id

In Fog, the model collections classes (typically the pluralised names in lib/fog/provider/models/service) have a get(id) method to fetch a model object by its ID.
In the case where the ID cannot be found, the get(id) method typically swallows the NotFound exception and returns nil.

In the OpenStack provider case, some classes use get(id) as described above, some use get(id) but do not swallow the NotFound exception, some classes use find_by_id(id) and not not swallow the exception, and in one case both methods are supported with find_by_id being marked as deprecated.

In other words, there is a great deal of inconsistency in how to get a model object by its ID in the Fog OpenStack provider.

Original issue opened by @Hague at fog/fog#3726

Create/list/delete server groups and assign VMs into them

Hello,

Does somebody know whether OpenStack provider implments creation/deletion/listing of server groups as well as asignment of VMs into them.
Basically I am interested in creation of virtual machine in a certain server group:

nova boot  --image ubuntu --flavor m1.small --hint group=aa8a69f4-2567-47c6-a28c-2934a8c7959c vm1

Thanks

Original issue opened by @pdilung at fog/fog#3656

randomly failing tests in CI

Randomly failing tests in CI, probably dependent on some variable order of things

Fog::Compute[:openstack] | security_group (openstack) ++++++++
tests/openstack/models/compute/security_group_tests.rb
success
Fog::Compute[:openstack] | security_group (openstack)
- successfully destroyed rule
expected => true
returned => false

  tests/openstack/models/compute/security_group_tests.rb
  - succeeds
    expected => true
    returned => false

  tests/openstack/models/compute/security_group_tests.rb
  - succeeds
    expected => true
    returned => false

and

Fog::Compute[:openstack] | server requests (openstack) +++++

tests/openstack/requests/compute/server_tests.rb
success
Fog::Compute[:openstack] | server requests (openstack)

  • succeeds
    expected => true
    returned => false

Original issue opened by @Ladas at fog/fog#3603

fog 1.36.0 now fails to list tenants

Works in 1.35.0, now fails.
Stacktrace:

/Users/pivotal/.gem/ruby/2.2.3/gems/fog-1.36.0/lib/fog/openstack/requests/compute/list_tenants.rb:6:in `list_tenants': undefined method `request' for nil:NilClass (NoMethodError)
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-1.36.0/lib/fog/openstack/models/compute/tenants.rb:11:in `all'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/core/collection.rb:113:in `lazy_load'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/core/collection.rb:17:in `map'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/formatador.rb:85:in `inspect_object'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/formatador.rb:72:in `block in nested_objects_string'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/formatador-0.2.5/lib/formatador.rb:92:in `indent'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/formatador.rb:41:in `indent'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/formatador.rb:72:in `nested_objects_string'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/formatador.rb:54:in `object_string'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/formatador.rb:14:in `block in format'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/formatador-0.2.5/lib/formatador.rb:92:in `indent'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/formatador.rb:41:in `indent'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/formatador.rb:14:in `format'
    from /Users/pivotal/.gem/ruby/2.2.3/gems/fog-core-1.34.0/lib/fog/core/collection.rb:73:in `inspect'
    from /Users/pivotal/Library/Preferences/RubyMine80/scratches/scratch_3:15:in `p'
    from /Users/pivotal/Library/Preferences/RubyMine80/scratches/scratch_3:15:in `<top (required)>'

Here's the code that we use to verify the bug:

gem 'fog', '1.36.0'
require 'fog'

c = Fog::Compute.new({
  provider: 'openstack',
  openstack_auth_url: 'http://10.85.40.2:5000/v2.0/tokens',
  openstack_identity_endpoint: 'http://10.85.40.2:5000/v2.0',
  openstack_username: 'admin',
  openstack_api_key: 'admin',
  openstack_region: 'RegionOne',
  connection_options: {}
})

p c.tenants

Original issue opened by @drich10 at fog/fog#3770

How to pass information for cloud-init during server creation

Hello,

I would need some help on how to pass information that is further used by cloud-init within the guest OS. I am doing the following without any luck:

@node_creation_opts = { 
          :name         => nodename,
          :image_ref    => template.id,
          :flavor_ref   => flavor.id,
          :nics => add_network_ports,
          :personality => [
          {
            'path' => '/var/lib/cloud/seed/nocloud-net/user-data',
            'contents' => Base64.encode64("#cloud-config\npassword: supersecret\nchpasswd: { expire: False }\nssh_pwauth: True")
          },
          {
            'path' => '/var/lib/cloud/seed/nocloud-net/meta-data',
            'contents' => ' '
          }
        ]
        }

...
...
...
def create_node_instance
        instance = compute_provider.servers.create(@node_creation_opts)
        wait_for_task_completion(instance)
        instance.reload
end
...
...
...

Any help (preferably with examples ;)) would be much appreciated.

Original issue opened by @pdilung at fog/fog#3590

Fix badges :+1:

I got the PR merged in, but we need to actually set up the badges eh eh?

Speaking of, @geemus how do we get CodeClimate and Travis and all set up? Is there a shared key or something that we use?

get_user_by_name request does not work as expected

It looks like Identity.get_user_by_name returns the full list of users currently and tests fail against a real installation.

I believe @drbrain noted this first (see b430ec6a20eb1216130df5024e32d18c4a60c3d6), so the question is, should we tweak the request to return the user requested or should we remove it?

@dprince?

I'd like to open a pull request if there's consensus around this feature.

Original issue opened by @rubiojr at fog/fog#1622.

availability zone is ignored when creating volume

It seems that Fog ignores the value of the availability_zone parameter when creating OpenStack volumes. In https://github.com/fog/fog/blob/master/lib/fog/openstack/models/compute/volume.rb line 28 I would expect this argument to be passed to the create_volume call, but it's not.

If this is by design, for example because there are problems with the OpenStack API when using this feature, it should be documented; but I would currently consider this a bug.

Original issue opened by @dennis-sig at fog/fog#3011

Fog::Image::OpenStack does not correctly construct URL for versioned API

My image endpoint is configured as http://glance.local:9292/ without an API version number, so Fog::Image::OpenStack uses Fog::OpenStack.get_supported_version to figure out the versioned API base URL by querying GET / on the Glance. This is the result returned from Glance (Kilo):

{
    "versions": [
        // various entries for v2.x omitted for brevity
        {
            "id": "v1.1",
            "links": [
                {
                    "href": "http://glance.local:9292/v1/",
                    "rel": "self"
                }
            ],
            "status": "SUPPORTED"
        },
        {
            "id": "v1.0",
            "links": [
                {
                    "href": "http://glance.local:9292/v1/",
                    "rel": "self"
                }
            ],
            "status": "SUPPORTED"
        }
    ]
}

The get_supported_version method decides that it likes the v1.1 version and returns that, but then Fog::Image::OpenSTack constructs the wrong URL in lib/fog/openstack/image.rb:206

@path = "/" + Fog::OpenStack.get_supported_version(SUPPORTED_VERSIONS,
                                                   uri,
                                                   @auth_token,
                                                   @connection_options)

This breaks because the URL path is /v1/ for the v1.1 API, not /v1.1/. Glance reports the correct URL in the response shown above, and that URL should be preferred over doing our own guesswork.

Original issue opened by @majewsky at fog/fog#3578

Populating Mock Data in Orchestration Requests

I'm currently writing tests for code that uses Openstack Orchestration requests.

One of the test fails, when I looked at the Mock for list_resources

`class Mock
def list_resources(options = {}, options_deprecated = {})
puts "YYY Resources: #{self.data}"
resources = self.data[:resources].values

      Excon::Response.new(
        :body   => { 'resources' => resources },
        :status => 200
      )
    end
  end

`

The error occurs because self.data[:resources] is nil, so .values being called on a Nil class.
Is there a correct method to populate self.data? in the Mock class, prior to executing the test?
I can't see a recommended approach.

Network class reauthentication causes Fog::Network::OpenStack::NotFound exceptions

When token is expired and Fog::Network::OpenStack::Real#request tries to reauthenticate, the supported api version path is not set thus causing 404 errors.

[116] pry(main)> a.class
=> Fog::Network::OpenStack::Real
[117] pry(main)> a.list_floating_ips.body['floatingips'].size
=> 13
[118] pry(main)> a.auth_token='invalid'
=> "invalid"
[119] pry(main)> a.list_floating_ips.body['floatingips'].size
Fog::Network::OpenStack::NotFound: Expected(200) <=> Actual(404 Not Found)
excon.error.response
  :body          => "404 Not Found\n\nUnknown API version specified\n\n   "
  :headers       => {
    "Content-Length" => "49"
    "Content-Type"   => "text/plain; charset=UTF-8"
    "Date"           => "Tue, 05 Apr 2016 06:45:14 GMT"
  }
  :host          => "*redacted*"
  :local_address => "*redacted*"
  :local_port    => 44715
  :path          => "/floatingips"
  :port          => 9696
  :reason_phrase => "Not Found"
  :remote_ip     => "*redacted*"
  :status        => 404
  :status_line   => "HTTP/1.1 404 Not Found\r\n"
from /usr/local/bundle/gems/excon-0.48.0/lib/excon/middlewares/expects.rb:6:in `response_call'
[120] pry(main)> a.set_api_path
=> "/v2.0"
[121] pry(main)> a.list_floating_ips.body['floatingips'].size
=> 13

No tags for release versions > 0.1.2

Hey,
I've noticed that releases above 0.1.2 don't have tags associated in github.
Not sure why that is the case. Maybe that is on purpose so people don't use them?
If not, could you please tag those? Thanks!

Lazy Fog::Storage::OpenStack connection?

I'm hitting a performance issue with Fog::Storage::Openstask which authenticates to the remote server as soon as it's initialized. The auth_token is indeed required when interacting with the storage, yet I often just need to generate signed URL to dowload private files, but these do require the management_url which is received along with the auth_token (to extract the scheme, host and port).

I was wondering if it would be safe to provide these values or the management_url directly? That would enable us to have a lazy connection, which would only authenticate before making the first request. Or maybe there are reasons to not do that in the Swift protocol?

Original issue opened by @ysbaddaden at fog/fog#3194

Fog OpenStack keystone v3 caching is non deterministic

brought by:
fog/fog#3738

My biggest problem is, that the behavior is non deterministic now, which is not good for lib I think. So for ManageIQ CI, which is doing a lot of request per one recorded VCR, it will always pass the 30 second interval, always having variable amount of requests cached. Then of course the recorded VCR is much quicker, so that is another issue, it would require having sleep there.

So, this makes it impossible to get deterministic behavior. When Invoking the same methods, I am getting basically random API requests fired. And that always breaks our CI.

My proposed solution:
1.) Having it configurable, disabled caching by default, we would pass e.g. :cache_ttl => 30 as options for auth request, then other services could take the settings from there, e.g. for keystone project list, etc.
So it would be Fog::Compute.new({..., :cache_ttl => 30 })

2.) Revert the caching here and rather rely on application specific implementation of caching, using redis, memcache, etc. But unless we will just have http layer caching, we would need to expose the Auth object.

So e.g. something like this:
auth = Fog::Auth.new({
:provider => 'openstack', # OpenStack Fog provider
:openstack_auth_url => 'http://KEYSTONE_HOST:KEYSTONE_PORT/v2.0/tokens', # OpenStack Keystone endpoint
:openstack_username => OPEN_STACK_USER, # Your OpenStack Username
:openstack_tenant => OPEN_STACK_TENANT, # Your tenant id
:openstack_api_key => OPEN_STACK_PASSWORD, # Your OpenStack Password
:connection_options => {} # Optional
})

then:

Fog::Compute.new(auth_object => auth)
Fog::Image.new(auth_object => auth)

I think these would not need to do API request then, if we will fetch auth token and keystone catalog into the auth object. And the Auth object could support rescoping maybe? Which we use for changing a tenant scope e.g. Fog::Image.new(auth_object => auth, openstack_tenant => 'project1'), which would just fire one api request for rescoping using existing token.

Original issue opened by @Ladas at fog/fog#3812

Instance addresses are assumed to always be named 'public' or 'private'

I have a cloud where the default names of 'public' and 'private' are not used for the collection of addresses returned upon a new server's creation. Newer OpenStack deployments offer metadata along with the addresses to give a hint as to whether they are public or private, but given that with Neutron you can have arbitrary numbers of networks and IP addresses, simply assuming 'public' and 'private' here is insufficient.

Most OpenStack deployments have an extension enabled that gives you metadata called OS-EXT-IPS which gives you a hint as to whether the IP address is public or private. There is a 'type' field which can contain the following values: "fixed", "floating", where fixed is assumed private and floating is assumed public.

For more detail:
https://github.com/openstack/nova/blob/master/doc/api_samples/OS-EXT-IPS/servers-detail-resp.json

Original issue opened by @devcamcar at fog/fog#2559.

swift: add support for max_keys when retrieving dir items

Currently there is no remapping in getting directory keys. This means that people are forced to add 'limit' explicitly into the calls. This is a problem when you try to have code that's compatible with multiple cloud vendors, as this breaks some other APIs, like Google Cloud Storage.

Raised PR, but it needs a bit more work. I am opening this issue so that someone else can take this over, as I have no SWIFT currently to test against.

Original issue opened by @mtekel at fog/fog#3723

:openstack_auth_url should not require trailing /tokens

Rubiojr's gist is the first Google hit for "ruby fog openstack". Notice how the parameters for Fog::Compute.new there are mostly direct equivalents of the OS_* environment variables of the Unified CLI, except for OS_AUTH_URL_FOG. That is because the common OS_AUTH_URL is the "identity API endpoint" which, as quoted by the /tokens API output itself, is of the form scheme://host:5000/2.0. OS_AUTH_URL_FOG currently needs to be ${OS_AUTH_URL}/tokens.

I think :openstack_auth_url should be compatible with the unified CLI and not require the trailing /tokens.

A related issue is that the code distinguishing v1 authentication from v2 requires a trailing / after the 2.0.

Original issue created by @mvidner at fog/fog#1210.

Unable to perform Fog::Mock.reset

When I try to do Fog::Mock.reset, I got a:

NameError: uninitialized constant Fog::OpenStack::Compute
from XXXX/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/fog-core-1.35.0/lib/fog/core/mock.rb:98:in `const_get'

please fix this , or at least tell me where was wrong so that I can help to fix this!!! Thank you!

Volume API uses Fog::Compute::OpenStack::NotFound exception class

lib/fog/openstack/volume.rb#L177 has what is probably just a copy-paste error:

rescue Excon::Errors::HTTPStatusError => error
  raise case error
  when Excon::Errors::NotFound
    Fog::Compute::OpenStack::NotFound.slurp(error)
  else
    error
  end

That custom exception class should be Fog::Volume::OpenStack::NotFound.(with Volume instead of Compute). Since that class already exists and is used in a few other places, I don't see an easy way to fix that in a backwards-compatible way. So it should at least be noted and fixed when backwards compatibility is broken the next time.

Original issue opened by @majewsky at fog/fog#3618

Bigdecimal gem dependency missing

On my current environment Ruby 2.3.1p112 (latest Fedora 24),
bundle exec rake spec fails because crack requires bigdecimal gem. Even though bigdecimal gem is installed, bundle doesn't allow it because it's not in the gemfile.

$ bundle exec rake spec
/usr/bin/ruby -I"lib:lib:spec" -I"/home/gil/.gem/ruby/2.3.0/gems/rake-10.5.0/lib" "/home/gil/.gem/ruby/2.3.0/gems/rake-10.5.0/lib/rake/rake_test_loader.rb" "spec/**/*_spec.rb" 
[Coveralls] Set up the SimpleCov formatter.
[Coveralls] Using SimpleCov's default settings.
[Coveralls] Outside the CI environment, not sending data.
/home/gil/.gem/ruby/2.3.0/gems/crack-0.4.3/lib/crack/xml.rb:9:in `require': cannot load such file -- bigdecimal (LoadError)

New minitest suite does ignore FOG_MOCK ENV variable

While doing reviews for "shindont to minitest" PRs I found out that running both
FOG_MOCK=true SEED=5161 bundle exec rake minitest and
FOG_MOCK=false SEED=5161 bundle exec rake minitest runs the same set of tests despite conditions for Fog.mocking? and conditioned skips in tests.

In fact in both cases calling Fog.mock? or Fog.mocking? returns always true and so prevents switching between running tests against mock or against real provider.

This is caused by unconditional Fog.mock! at https://github.com/fog/fog-openstack/blob/master/test/test_helper.rb#L14

I think that we should keep option of setting up FOG_MOCK ENV variable working to ensure that we can run tests against real providers.

Travis test environment broken

Travis fails on Ruby: 2.3.0 environment.
Installation of VCR 3.0.2 fails.
Rubygem version needs to be bumped up (>=2.5.2).
Local workaround: gem update --system

Refactor code for style failures on Code Climate

Our Code Climate score isn't great. We can probably promote some Cs to Bs and Fs to Es if we fix all the style contraventions listed.

Some of those F scores are crying out for a refactoring already, particularly the code that handles Keystone authentication (just try and follow it end-to-end and you'll see how confusing it is). I'll raise a separate issue for that chunk of work at some point (though if anyone else is feeling brave, please do feel free to dive in ๐Ÿ˜‰).

Compute's mock detach_volume fails

attach_volume adds an entry to self.data[:volumes][volume_id], but detach_volume attempts to find it via self.data[:volumes][attachment_id]. Instead, it should find the volume in self.data[:volumes] that has an attachment with the given attachment_id:

volume = self.data[:volumes].find { |v| v['attachments'].any? { |a| a['id'] == attachment_id } }
if volume
  volume['attachments'].reject! { |a| a['id'] == attachment_id && a['server_id'] == server_id }
end

https://github.com/fog/fog/blob/master/lib/fog/openstack/requests/compute/detach_volume.rb#L17

Original issue opened by @xian at fog/fog#3382

Cannot Get Openstack Identity v3 Calls Working

I am trying to use identity v3, but it defaults back to v2. We pass in the /v3/auth/tokens URL and it authenticates correctly, but all calls go to the older v2 URL. During debugging, we turned on EXCON_DEBUG and noticed the code is switching to v2 based on the endpoints provided in server response. In the response there is no v3 endpoints. In the v2 code, @openstack_management_url is set to use the authentication URL as a base, which seems to drive future calls to v2 resources. Is there anything we need to do to get v3 identity to work properly?

Original issue opened by @j-bailey at fog/fog#3758

Monitoring / Monasca support

Hi,

Currently fog-openstack does not support Monitoring (Monasca).
I'd like to contribute and add proper support by introducing a new monitoring service, req. models and collections for that.

I'll follow up with a PR with an initial version of that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.