ManageIQ/manageiq-providers-openstack

View on GitHub
app/models/manageiq/providers/openstack/network_manager/floating_ip.rb

Summary

Maintainability
B
5 hrs
Test Coverage
C
72%
class ManageIQ::Providers::Openstack::NetworkManager::FloatingIp < ::FloatingIp
  include ManageIQ::Providers::Openstack::HelperMethods
  include ProviderObjectMixin
  include AsyncDeleteMixin

  supports :create

  supports :delete do
    if ext_management_system.nil?
      _("The Floating Ip is not connected to an active %{table}") % {
        :table => ui_lookup(:table => "ext_management_systems")
      }
    end
  end

  supports :update do
    if ext_management_system.nil?
      _("The Floating Ip is not connected to an active %{table}") % {
        :table => ui_lookup(:table => "ext_management_systems")
      }
    end
  end

  def self.params_for_create(ems)
    {
      :fields => [
        {
          :component       => 'select',
          :id              => 'cloud_network_id',
          :name            => 'cloud_network_id',
          :label           => _('External Network'),
          :placeholder     => "<#{_('Choose')}>",
          :validateOnMount => true,
          :validate        => [{
            :type    => 'required',
            :message => _('Required'),
          }],
          :options         => ems.public_networks.map do |ct|
            {
              :label => ct.name,
              :value => ct.id.to_s,
            }
          end,
          :includeEmpty    => true,
          :clearOnUnmount  => true,
        },
        {
          :component       => 'select',
          :id              => 'cloud_tenant_id',
          :name            => 'cloud_tenant_id',
          :key             => "id-#{ems.id}",
          :label           => _('Cloud Tenant Placement'),
          :placeholder     => "<#{_('Choose')}>",
          :validateOnMount => true,
          :validate        => [{
            :type    => 'required',
            :message => _('Required'),
          }],
          :options         => ems.cloud_tenants.map do |ct|
            {
              :label => ct.name,
              :value => ct.id.to_s,
            }
          end,
          :includeEmpty    => true,
          :clearOnUnmount  => true,
        },
        {
          :component => 'sub-form',
          :title     => _('Association Information'),
          :id        => 'assocation-information',
          :name      => 'assocation-information',
          :fields    => [
            {
              :component       => 'text-field',
              :id              => 'address',
              :name            => 'address',
              :validateOnMount => true,
              :label           => _('Floating IP Address (optional)'),
            },
            {
              :component       => 'text-field',
              :id              => 'fixed_ip_address',
              :name            => 'fixed_ip_address',
              :validateOnMount => true,
              :label           => _('Fixed IP Address'),
            },
            {
              :component       => 'text-field',
              :id              => 'network_port_ems_ref',
              :name            => 'network_port_ems_ref',
              :validateOnMount => true,
              :label           => _('Associated Port ID (blank to disassociate)'),
            }
          ]
        },
      ]
    }
  end

  def params_for_update
    {
      :component => 'sub-form',
      :id        => 'placement',
      :name      => 'placement',
      :fields    => [
        {
          :component       => 'select',
          :id              => 'cloud_network_id',
          :name            => 'cloud_network_id',
          :label           => _('External Network'),
          :placeholder     => "<#{_('Choose')}>",
          :validateOnMount => true,
          :validate        => [{
            :type    => 'required',
            :message => _('Required'),
          }],
          :isDisabled      => !!id,
          :options         => ext_management_system.public_networks.map do |ct|
            {
              :label => ct.name,
              :value => ct.id.to_s,
            }
          end,
          :includeEmpty    => true,
          :clearOnUnmount  => true,
        },
        {
          :component       => 'select',
          :id              => 'cloud_tenant_id',
          :name            => 'cloud_tenant_id',
          :key             => "id-#{ems_id}",
          :label           => _('Cloud Tenant Placement'),
          :placeholder     => "<#{_('Choose')}>",
          :validateOnMount => true,
          :validate        => [{
            :type    => 'required',
            :message => _('Required'),
          }],
          :isDisabled      => !!id,
          :options         => ext_management_system.cloud_tenants.map do |ct|
            {
              :label => ct.name,
              :value => ct.id.to_s,
            }
          end,
          :includeEmpty    => true,
          :clearOnUnmount  => true,
        },
        {
          :component => 'sub-form',
          :title     => _('Association Information'),
          :id        => 'assocation-information',
          :name      => 'assocation-information',
          :fields    => [
            {
              :component       => 'text-field',
              :id              => 'address',
              :name            => 'address',
              :validateOnMount => true,
              :label           => _('Floating IP Address (optional)'),
            },
            {
              :component       => 'text-field',
              :id              => 'fixed_ip_address',
              :name            => 'fixed_ip_address',
              :validateOnMount => true,
              :label           => _('Fixed IP Address'),
            },
            {
              :component       => 'text-field',
              :id              => 'network_port_ems_ref',
              :name            => 'network_port_ems_ref',
              :validateOnMount => true,
              :label           => _('Associated Port ID (blank to disassociate)'),
            }
          ]
        },
      ]
    }
  end

  def self.raw_create_floating_ip(ext_management_system, options)
    cloud_tenant = options.delete(:cloud_tenant)
    floating_ip = nil
    floating_network_id = CloudNetwork.find(options[:cloud_network_id]).ems_ref

    raw_options = remapping(options)
    ext_management_system.with_provider_connection(connection_options(cloud_tenant)) do |service|
      floating_ip = service.create_floating_ip(floating_network_id, raw_options)
    end
    {:ems_ref => floating_ip['id'], :name => options[:floating_ip_address]}
  rescue => e
    _log.error "floating_ip=[#{options[:floating_ip_address]}], error: #{e}"
    raise MiqException::MiqFloatingIpCreateError, parse_error_message_from_neutron_response(e), e.backtrace
  end

  def self.remapping(options)
    new_options = options.dup
    new_options[:floating_ip_address] = options[:address] if options[:address]
    new_options[:tenant_id] = CloudTenant.find(options[:cloud_tenant_id]).ems_ref if options[:cloud_tenant_id]
    new_options[:port_id] = options[:network_port_ems_ref] if options[:network_port_ems_ref]

    # if we got an empty string or nil for floating_ip_address (probably from the UI form)
    # then remove the parameter from the options because otherwise Neutron will balk about the IP
    # being invalid.
    new_options.delete(:floating_ip_address) if new_options[:floating_ip_address].blank?

    new_options.delete(:address)
    new_options.delete(:cloud_network_id)
    new_options.delete(:network_port_ems_ref)
    new_options.delete(:cloud_tenant_id)
    new_options
  end

  def raw_delete_floating_ip
    ext_management_system.with_provider_connection(connection_options(cloud_tenant)) do |service|
      service.delete_floating_ip(ems_ref)
    end
  rescue => e
    _log.error "floating_ip=[#{name}], error: #{e}"
    raise MiqException::MiqFloatingIpDeleteError, parse_error_message_from_neutron_response(e), e.backtrace
  end

  def delete_floating_ip_queue(userid)
    task_opts = {
      :action => "deleting Floating IP for user #{userid}",
      :userid => userid
    }
    queue_opts = {
      :class_name  => self.class.name,
      :method_name => 'raw_delete_floating_ip',
      :instance_id => id,
      :priority    => MiqQueue::HIGH_PRIORITY,
      :role        => 'ems_operations',
      :zone        => ext_management_system.my_zone,
      :args        => []
    }
    MiqTask.generic_action_with_callback(task_opts, queue_opts)
  end

  def raw_update_floating_ip(options)
    ext_management_system.with_provider_connection(connection_options(cloud_tenant)) do |service|
      if options[:network_port_ems_ref].empty?
        service.disassociate_floating_ip(ems_ref)
      else
        service.associate_floating_ip(ems_ref, options[:network_port_ems_ref])
      end
    end
  rescue => e
    _log.error "floating_ip=[#{name}], error: #{e}"
    raise MiqException::MiqFloatingIpUpdateError, parse_error_message_from_neutron_response(e), e.backtrace
  end

  def update_floating_ip_queue(userid, options = {})
    task_opts = {
      :action => "updating Floating IP for user #{userid}",
      :userid => userid
    }
    queue_opts = {
      :class_name  => self.class.name,
      :method_name => 'raw_update_floating_ip',
      :instance_id => id,
      :priority    => MiqQueue::HIGH_PRIORITY,
      :role        => 'ems_operations',
      :zone        => ext_management_system.my_zone,
      :args        => [options]
    }
    MiqTask.generic_action_with_callback(task_opts, queue_opts)
  end

  def self.connection_options(cloud_tenant = nil)
    connection_options = {:service => "Network"}
    connection_options[:tenant_name] = cloud_tenant.name if cloud_tenant
    connection_options
  end

  def self.display_name(number = 1)
    n_('Floating IP (OpenStack)', 'Floating IPs (OpenStack)', number)
  end

  private

  def connection_options(cloud_tenant = nil)
    self.class.connection_options(cloud_tenant)
  end
end