Class: ForemanOpenstackV3::Openstack

Inherits:
ComputeResource
  • Object
show all
Defined in:
app/models/foreman_openstack_v3/openstack.rb

Constant Summary collapse

SEARCHABLE_ACTIONS =
[:server_group_anti_affinity, :server_group_affinity, :raw]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#scheduler_hint_valueObject

Returns the value of attribute scheduler_hint_value.



3
4
5
# File 'app/models/foreman_openstack_v3/openstack.rb', line 3

def scheduler_hint_value
  @scheduler_hint_value
end

#tenantObject

Returns the value of attribute tenant.



3
4
5
# File 'app/models/foreman_openstack_v3/openstack.rb', line 3

def tenant
  @tenant
end

Class Method Details

.available?Boolean

Returns:

  • (Boolean)


20
21
22
# File 'app/models/foreman_openstack_v3/openstack.rb', line 20

def self.available?
  Fog::Compute.providers.include?(:openstack)
end

.model_nameObject



24
25
26
# File 'app/models/foreman_openstack_v3/openstack.rb', line 24

def self.model_name
  ComputeResource.model_name
end

.provider_friendly_nameObject



178
179
180
# File 'app/models/foreman_openstack_v3/openstack.rb', line 178

def self.provider_friendly_name
  "OpenStack"
end

Instance Method Details

#address_poolsObject



72
73
74
# File 'app/models/foreman_openstack_v3/openstack.rb', line 72

def address_pools
  client.addresses.get_address_pools.map { |p| p["name"] }
end

#allow_external_networkObject



44
45
46
# File 'app/models/foreman_openstack_v3/openstack.rb', line 44

def allow_external_network
  Foreman::Cast.to_bool(attrs[:allow_external_network])
end

#allow_external_network=(enabled) ⇒ Object



48
49
50
# File 'app/models/foreman_openstack_v3/openstack.rb', line 48

def allow_external_network=(enabled)
  attrs[:allow_external_network] = Foreman::Cast.to_bool(enabled)
end

#associated_host(vm) ⇒ Object



170
171
172
# File 'app/models/foreman_openstack_v3/openstack.rb', line 170

def associated_host(vm)
  associate_by("ip", [vm.floating_ip_address, vm.private_ip_address].compact)
end

#available_imagesObject



68
69
70
# File 'app/models/foreman_openstack_v3/openstack.rb', line 68

def available_images
  client.images.select { |image| image.status.downcase == 'active' }
end

#boot_from_volume(args = {}) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'app/models/foreman_openstack_v3/openstack.rb', line 85

def boot_from_volume(args = {})
  vm_name = args[:name]
  args[:size_gb] = image_size(args[:image_ref]) if args[:size_gb].blank?
  volume_name = "#{vm_name}-vol0"
  boot_vol = volume_client.volumes.create(
    :name => volume_name, # Name attribute in OpenStack volumes API v2
    :display_name => volume_name, # Name attribute in API v1
    :volumeType => "Volume",
    :size => args[:size_gb],
    :imageRef => args[:image_ref])
  @boot_vol_id = boot_vol.id.tr('"', '')
  boot_vol.wait_for { status == 'available' }
  args[:block_device_mapping_v2] = [ {
    :source_type => "volume",
    :destination_type => "volume",
    :delete_on_termination => "1",
    :uuid => @boot_vol_id,
    :boot_index => "0"
  } ]
end

#capabilitiesObject



32
33
34
# File 'app/models/foreman_openstack_v3/openstack.rb', line 32

def capabilities
  [:image]
end

#console(uuid) ⇒ Object



165
166
167
168
# File 'app/models/foreman_openstack_v3/openstack.rb', line 165

def console(uuid)
  vm = find_vm_by_uuid(uuid)
  vm.console.body.merge({'timestamp' => Time.now.utc})
end

#create_vm(args = {}) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'app/models/foreman_openstack_v3/openstack.rb', line 130

def create_vm(args = {})

  boot_from_volume(args) if Foreman::Cast.to_bool(args[:boot_from_volume])
  network = args.delete(:network)
  # fix internal network format for fog.
  args[:nics].delete_if(&:blank?)
  args[:nics].map! {|nic| { 'net_id' => nic } }
  format_scheduler_hint_filter(args) if args[:scheduler_hint_filter].present?
  vm = super(args)
  if network.present?
    address = allocate_address(network)
    assign_floating_ip(address, vm)
  end
  vm
rescue => e
  message = JSON.parse(e.response.body)['badRequest']['message'] rescue (e.to_s)
  logger.warn "failed to create vm: #{message}"
  destroy_vm vm.id if vm
  volume_client.volumes.delete(@boot_vol_id) if args[:boot_from_volume]
  raise message
end

#destroy_vm(uuid) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
# File 'app/models/foreman_openstack_v3/openstack.rb', line 152

def destroy_vm(uuid)
  vm           = find_vm_by_uuid(uuid)
  floating_ips = vm.all_addresses
  floating_ips.each do |address|
    client.disassociate_address(uuid, address['ip']) rescue true
    client.release_address(address['id']) rescue true
  end
  super(uuid)
rescue ActiveRecord::RecordNotFound
  # if the VM does not exists, we don't really care.
  true
end

#flavor_name(flavor_ref) ⇒ Object



174
175
176
# File 'app/models/foreman_openstack_v3/openstack.rb', line 174

def flavor_name(flavor_ref)
  client.flavors.get(flavor_ref).try(:name)
end

#format_scheduler_hint_filter(args = {}) ⇒ Object

Raises:

  • (::Foreman::Exception)


116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'app/models/foreman_openstack_v3/openstack.rb', line 116

def format_scheduler_hint_filter(args = {})
  raise ::Foreman::Exception.new(N_('Hint data is missing')) if args[:scheduler_hint_data].nil?
  name = args.delete(:scheduler_hint_filter).underscore.to_sym
  data = args.delete(:scheduler_hint_data)
  filter = {}
  case name
    when :server_group_anti_affinity, :server_group_affinity
      filter[:group] = data[:scheduler_hint_value]
    when :raw
      filter = JSON.parse(data[:scheduler_hint_value])
  end
  args[:os_scheduler_hints] = filter
end

#get_server_groups(policy) ⇒ Object



110
111
112
113
114
# File 'app/models/foreman_openstack_v3/openstack.rb', line 110

def get_server_groups(policy)
  server_groups = client.server_groups.select{ |sg| sg.policies.include?(policy) }
  errors.add(:scheduler_hint_value, _("No matching server groups found")) if server_groups.empty?
  server_groups
end

#image_param_nameObject



28
29
30
# File 'app/models/foreman_openstack_v3/openstack.rb', line 28

def image_param_name
  :image_ref
end

#image_size(image_id) ⇒ Object



81
82
83
# File 'app/models/foreman_openstack_v3/openstack.rb', line 81

def image_size(image_id)
  client.get_image_details(image_id).body['image']['minDisk']
end

#internal_networksObject



76
77
78
79
# File 'app/models/foreman_openstack_v3/openstack.rb', line 76

def internal_networks
  return {} if network_client.nil?
  allow_external_network ? network_client.networks.all : network_client.networks.all.select { |net| !net.router_external }
end

#possible_scheduler_hintsObject



106
107
108
# File 'app/models/foreman_openstack_v3/openstack.rb', line 106

def possible_scheduler_hints
  SEARCHABLE_ACTIONS.collect{|x| x.to_s.camelize }
end

#provided_attributesObject



16
17
18
# File 'app/models/foreman_openstack_v3/openstack.rb', line 16

def provided_attributes
  super.merge({ :ip => :floating_ip_address })
end

#tenantsObject



52
53
54
55
56
57
58
59
# File 'app/models/foreman_openstack_v3/openstack.rb', line 52

def tenants
  if url =~ /\/v3\/auth\/tokens/
    user_id       = identity_client.current_user_id
    identity_client.list_user_projects(user_id).body["projects"].map { |p| Fog::Identity::OpenStack::V3::Project.new(p) }
  else
    client.tenants
  end
end

#test_connection(options = {}) ⇒ Object



61
62
63
64
65
66
# File 'app/models/foreman_openstack_v3/openstack.rb', line 61

def test_connection(options = {})
  super
  errors[:user].empty? && errors[:password] && tenants
rescue => e
  errors[:base] << e.message
end

#user_data_supported?Boolean

Returns:

  • (Boolean)


182
183
184
# File 'app/models/foreman_openstack_v3/openstack.rb', line 182

def user_data_supported?
  true
end

#zonesObject



186
187
188
# File 'app/models/foreman_openstack_v3/openstack.rb', line 186

def zones
  @zones ||= (client.list_zones.body["availabilityZoneInfo"].try(:map){|i| i["zoneName"]} || [])
end