foreman_gridscale 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +619 -0
- data/README.md +89 -0
- data/Rakefile +47 -0
- data/app/helpers/gridscale_images_helper.rb +128 -0
- data/app/models/concerns/fog_extensions/gridscale/server.rb +63 -0
- data/app/models/foreman_gridscale/concerns/host_managed_extensions.rb +16 -0
- data/app/models/foreman_gridscale/gridscale.rb +196 -0
- data/app/views/compute_resources/form/_gridscale.html.erb +4 -0
- data/app/views/compute_resources/show/_gridscale.html.erb +0 -0
- data/app/views/compute_resources_vms/form/gridscale/_base.html.erb +9 -0
- data/app/views/compute_resources_vms/form/gridscale/_network.html.erb +10 -0
- data/app/views/compute_resources_vms/index/_gridscale.html.erb +21 -0
- data/app/views/compute_resources_vms/show/_gridscale.html.erb +19 -0
- data/app/views/hosts/_nics.html.erb +0 -0
- data/config/routes.rb +3 -0
- data/lib/foreman_gridscale.rb +3 -0
- data/lib/foreman_gridscale/engine.rb +41 -0
- data/lib/foreman_gridscale/tasks/test.rake +45 -0
- data/lib/foreman_gridscale/version.rb +3 -0
- data/locale/Makefile +60 -0
- data/locale/en/foreman_gridscale.po +19 -0
- data/locale/foreman_gridscale.pot +19 -0
- data/locale/gemspec.rb +2 -0
- data/test/factories/foreman_gridscale_factories.rb +5 -0
- data/test/test_plugin_helper.rb +6 -0
- data/test/unit/foreman_gridscale_test.rb +11 -0
- metadata +117 -0
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# ForemanGridscale
|
2
|
+
|
3
|
+
*Plugin to enable management of gridscale instances from within foreman*
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
Foreman gridscale has the following requirements:
|
7
|
+
|
8
|
+
* Foreman 1.15+
|
9
|
+
* A working internet connection
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
1. Extract the supplied archive on the server which has Foreman installed on it. Make sure to do this in a directory which can be accessed by the user running Foreman.
|
14
|
+
|
15
|
+
2. In the foreman/bundler.d directory (usually found in /usr/share/), create or edit the file Gemfile.local.rb and add the following lines to it:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'fog-gridscale', :path => 'path to fog-gridscale directory'
|
19
|
+
gem 'foreman_gridscale', :path => 'path to foreman-gridscale directory'
|
20
|
+
```
|
21
|
+
|
22
|
+
3. Next run the following command:
|
23
|
+
|
24
|
+
```
|
25
|
+
$ cd /usr/share/foreman && sudo -u foreman /usr/bin/foreman-ruby /usr/bin/bundle install
|
26
|
+
```
|
27
|
+
|
28
|
+
4. Then restart Foreman with:
|
29
|
+
```
|
30
|
+
$ touch /usr/share/foreman/tmp/restart.txt
|
31
|
+
```
|
32
|
+
|
33
|
+
See [how to install Foreman plugins](http://projects.theforeman.org/projects/foreman/wiki/How_to_Install_a_Plugin) to learn more about plugins.
|
34
|
+
|
35
|
+
|
36
|
+
## How to Use
|
37
|
+
### Configuration
|
38
|
+
|
39
|
+
Go to **Infrastructure > Compute Resources** and click on "New Compute Resource".
|
40
|
+
|
41
|
+
Choose **gridscale** as the provider, and fill in all the fields. You need your API token and user uuid with read and write access, which can be created in the [gridscale API section](https://my.gridscale.io/APIs/).
|
42
|
+
|
43
|
+
That's it. You're now ready to create and manage servers in your new gridscale compute resource.
|
44
|
+
|
45
|
+
You should see something like this on the [Compute Resource](https://theforeman.org/manuals/1.19/index.html#5.2ComputeResources) page:
|
46
|
+
|
47
|
+
### Host Creation
|
48
|
+
1. Go to host > create host and choose gridscale as a deployment target. The virtual machine tab with all of the parameter fields to create a server will appear
|
49
|
+
2. If you already set up your compute profile, you can choose it and it will automatically set up the virtual machine parameters. you can also overwrite them
|
50
|
+
3. On the virtual machine tab, fill in the fields with the desired number cores, memory, and capacity of the storage. You can also attach a gridscale or private template to your storage
|
51
|
+
4. Fill the operating system tab
|
52
|
+
5. In the interface tab, click the edit button in actions column, and pick the gridscale network interface you wish to connect your machine to. You can also add multiple network interfaces by clicking the add interface button below the interface table. click OK once you have finished
|
53
|
+
6. Click submit button to finish the Host creation
|
54
|
+
|
55
|
+
### Compute Profile
|
56
|
+
1. Click infrastructure > compute profile
|
57
|
+
2. Click create compute profile button on the top right side of the screen
|
58
|
+
3. Fill in the name field, and click the submit button
|
59
|
+
4. Click on the compute resource link that you want to associate with your compute profile
|
60
|
+
5. Fill out the compute profile attributes and click the submit button
|
61
|
+
6. You are now ready to use your compute profile
|
62
|
+
|
63
|
+
### Host Management
|
64
|
+
Click Host > All Host. You will be able to see all of the hosts that were created through foreman in the tables. The Power column shows the power status of the server. The host’s details can be seen by clicking the link in its name.
|
65
|
+
|
66
|
+
**Powering off/on**
|
67
|
+
1. Choose the host by checking the box in the first column of the table (you can select all of the hosts by checking the box in the header)
|
68
|
+
2. Click the action button, and choose change power state
|
69
|
+
3. Select the desired power state from the dropdown power list
|
70
|
+
4. Click submit
|
71
|
+
|
72
|
+
**Delete Host**
|
73
|
+
1. Choose the host by checking the box in the first column of the table (you can select all of the hosts by checking the box on the header)
|
74
|
+
2. Click the action button, and choose delete host (you can also delete them individually by clicking the dropdown list in the actions column)
|
75
|
+
3. Click submit and confirm the action
|
76
|
+
|
77
|
+
|
78
|
+
###Host management through the compute resource page
|
79
|
+
Go to Infrastructure > Compute resource and select the compute resource for gridscale. go to the virtual machine tab. The virtual machine tab displays all of the servers in the gridscale panel.
|
80
|
+
|
81
|
+
##Known Issues
|
82
|
+
* When creating a host, multiple network interfaces can be set to bootable. The gridscale platform does not support this, which is why only one of the interfaces will actually be set to bootable if this is the case
|
83
|
+
* When creating a compute profile, the chosen network interface configuration is not saved
|
84
|
+
* The Virtual Machines overview of a compute resource can take a long time to load
|
85
|
+
* The data shown in the VM tab of a host is not complete. More input about which information is useful is needed
|
86
|
+
* Opening the console of a host in Foreman has not been implemented, but a link to gridscale is supplied
|
87
|
+
* Acpi power off fails to shut down a system which did not boot
|
88
|
+
* MAC, IP4 and IP6 information is in the VM tab, not Interface
|
89
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ForemanGridscale'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
|
24
|
+
|
25
|
+
Bundler::GemHelper.install_tasks
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
|
29
|
+
Rake::TestTask.new(:test) do |t|
|
30
|
+
t.libs << 'lib'
|
31
|
+
t.libs << 'test'
|
32
|
+
t.pattern = 'test/**/*_test.rb'
|
33
|
+
t.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
task default: :test
|
37
|
+
|
38
|
+
begin
|
39
|
+
require 'rubocop/rake_task'
|
40
|
+
RuboCop::RakeTask.new
|
41
|
+
rescue => _
|
42
|
+
puts 'Rubocop not loaded.'
|
43
|
+
end
|
44
|
+
|
45
|
+
task :default do
|
46
|
+
Rake::Task['rubocop'].execute
|
47
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module GridscaleImagesHelper
|
2
|
+
def gridscale_server_field(f)
|
3
|
+
images = @compute_resource.available_servers
|
4
|
+
images.each { |image| image.name = image.id if image.name.nil? }
|
5
|
+
select_f f, :uuid, images.to_a.sort_by(&:full_name),
|
6
|
+
:id, :full_name, {}, :label => _('Image')
|
7
|
+
end
|
8
|
+
|
9
|
+
def select_ipv4(f, compute_resource)
|
10
|
+
addresses = Array.new
|
11
|
+
compute_resource.ips.each do |ip|
|
12
|
+
if ip.relations['servers'].empty? and ip.relations['loadbalancers'].empty? and ip.family ==4
|
13
|
+
addresses << ip
|
14
|
+
end
|
15
|
+
end
|
16
|
+
if addresses.empty?
|
17
|
+
"No IPs available"
|
18
|
+
else
|
19
|
+
select_f(f,
|
20
|
+
:ipv4_uuid,
|
21
|
+
addresses,
|
22
|
+
:object_uuid,
|
23
|
+
:ip,
|
24
|
+
{ :include_blank => true },
|
25
|
+
{ :label => 'IP Address 4'})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def select_ipv6(f, compute_resource)
|
30
|
+
addresses = Array.new
|
31
|
+
compute_resource.ips.each do |ip|
|
32
|
+
if ip.relations['servers'].empty? and ip.relations['loadbalancers'].empty? and ip.family ==6
|
33
|
+
addresses << ip
|
34
|
+
end
|
35
|
+
end
|
36
|
+
if addresses.empty?
|
37
|
+
"No IPs available"
|
38
|
+
else
|
39
|
+
select_f(f,
|
40
|
+
:ipv6_uuid,
|
41
|
+
addresses,
|
42
|
+
:object_uuid,
|
43
|
+
:ip,
|
44
|
+
{ :include_blank => true },
|
45
|
+
{ :label => 'IP Address 6'})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def select_network(f, compute_resource)
|
50
|
+
networks_list = Array.new
|
51
|
+
compute_resource.networks.each do |network|
|
52
|
+
networks_list << network
|
53
|
+
end
|
54
|
+
|
55
|
+
select_f(f,
|
56
|
+
:network_uuid,
|
57
|
+
networks_list,
|
58
|
+
:object_uuid,
|
59
|
+
:name,
|
60
|
+
{ :include_blank => true },
|
61
|
+
{ :label => 'Network'})
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
def select_storage(f, compute_resource)
|
68
|
+
|
69
|
+
storages_list = Array.new
|
70
|
+
|
71
|
+
compute_resource.storages.each do |storage|
|
72
|
+
if storage.relations['servers'].empty?
|
73
|
+
storages_list << storage
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
if storages_list.empty?
|
78
|
+
"No storage available"
|
79
|
+
else
|
80
|
+
select_f(f,
|
81
|
+
:storage_uuid,
|
82
|
+
storages_list,
|
83
|
+
:object_uuid,
|
84
|
+
:name,
|
85
|
+
{ :include_blank => true },
|
86
|
+
{ :label => 'available storage'})
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def select_template(f, compute_resource)
|
91
|
+
template_list = Array.new
|
92
|
+
compute_resource.templates.each do |template|
|
93
|
+
template_list << template
|
94
|
+
end
|
95
|
+
|
96
|
+
select_f(f,
|
97
|
+
:template_uuid,
|
98
|
+
template_list,
|
99
|
+
:object_uuid,
|
100
|
+
:name,
|
101
|
+
{ :include_blank => true },
|
102
|
+
{ :label => 'Template'})
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
def select_sshkey(f, compute_resource)
|
107
|
+
template_list = Array.new
|
108
|
+
compute_resource.sshkeys.each do |template|
|
109
|
+
template_list << template
|
110
|
+
end
|
111
|
+
|
112
|
+
select_f(f,
|
113
|
+
:sshkey_uuid,
|
114
|
+
template_list,
|
115
|
+
:object_uuid,
|
116
|
+
:name,
|
117
|
+
{ :include_blank => true },
|
118
|
+
{ :label => 'SSH Key'})
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
def gridscale_image_field(f)
|
123
|
+
images = @compute_resource.available_templates
|
124
|
+
images.each { |image| image.name = image.object_uuid if image.name.nil? }
|
125
|
+
select_f f, :object_uuid, images.to_a,
|
126
|
+
:object_uuid, :name, {}, :label => _('Image')
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module FogExtensions
|
2
|
+
module Gridscale
|
3
|
+
module Server
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
attr_accessor :object_uuid, :mac, :server_uuid, :interfaces_attributes, :ipv4_address, :ipv6_address
|
7
|
+
|
8
|
+
def state
|
9
|
+
requires :status
|
10
|
+
@state ||= status
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
name
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset
|
18
|
+
reboot
|
19
|
+
end
|
20
|
+
|
21
|
+
def vm_description
|
22
|
+
format(_('%{cpus} CPUs and %{ram} memory'), :cpus => cores, :ram => memory)
|
23
|
+
end
|
24
|
+
|
25
|
+
def ip_addresses
|
26
|
+
[ipv4_address, ipv6_address].flatten.select(&:present?)
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def ip4_add_in
|
31
|
+
x = nil
|
32
|
+
if interfaces_attributes != nil
|
33
|
+
interfaces_attributes.each do |key, value|
|
34
|
+
|
35
|
+
if value["ipv4_uuid"] !=nil && value["ipv4_uuid"] != ""
|
36
|
+
x = service.ips.get(value["ipv4_uuid"])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
x.ip
|
41
|
+
end
|
42
|
+
|
43
|
+
def ip6_add_in
|
44
|
+
x = nil
|
45
|
+
if interfaces_attributes != nil
|
46
|
+
interfaces_attributes.each do |key, value|
|
47
|
+
|
48
|
+
if value["ipv6_uuid"] !=nil && value["ipv6_uuid"] != ""
|
49
|
+
x = service.ips.get(value["ipv6_uuid"])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
x.ip
|
54
|
+
end
|
55
|
+
|
56
|
+
def mac_addr
|
57
|
+
:mac
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ForemanGridscale
|
2
|
+
module Concerns
|
3
|
+
module HostManagedExtensions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
# Rails 4 does not provide dynamic finders for delegated methods and
|
8
|
+
# the SSH orchestrate compute method uses them.
|
9
|
+
def self.find_by_ip(ip)
|
10
|
+
nic = Nic::Base.find_by_ip(ip)
|
11
|
+
nic.host if nic.present?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
module ForemanGridscale
|
2
|
+
class Gridscale < ComputeResource
|
3
|
+
alias_attribute :api_token, :password
|
4
|
+
alias_attribute :user_uuid, :user
|
5
|
+
alias_attribute :object_uuid, :uuid
|
6
|
+
|
7
|
+
has_one :key_pair, :foreign_key => :compute_resource_id, :dependent => :destroy
|
8
|
+
delegate :to => :client
|
9
|
+
|
10
|
+
validates :api_token, :user_uuid, :presence => true
|
11
|
+
before_create :test_connection
|
12
|
+
|
13
|
+
|
14
|
+
def api_token
|
15
|
+
attrs[:api_token]
|
16
|
+
end
|
17
|
+
|
18
|
+
def user_uuid
|
19
|
+
attrs[:user_uuid]
|
20
|
+
end
|
21
|
+
|
22
|
+
def api_token=(api_token)
|
23
|
+
attrs[:api_token] = api_token
|
24
|
+
end
|
25
|
+
|
26
|
+
def user_uuid=(user_uuid)
|
27
|
+
attrs[:user_uuid] = user_uuid
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_label
|
31
|
+
"#{name} (#{provider_friendly_name})"
|
32
|
+
end
|
33
|
+
|
34
|
+
def provided_attributes
|
35
|
+
super.merge({})
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_ip(ipaddr_uuid)
|
39
|
+
client.ips.get(ipaddr_uuid).ip
|
40
|
+
end
|
41
|
+
|
42
|
+
def capabilities
|
43
|
+
[:build, :images]
|
44
|
+
end
|
45
|
+
|
46
|
+
def associated_host(vm)
|
47
|
+
associate_by('ip', [vm.ipv4_address])
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_vm(args = {})
|
51
|
+
args['cores'] = args['cores'].to_i
|
52
|
+
args['memory'] = args['memory'].to_i
|
53
|
+
args['storage'] = args['storage'].to_i
|
54
|
+
|
55
|
+
super(args)
|
56
|
+
rescue Fog::Errors::Error => e
|
57
|
+
logger.error "Unhandled gridscale error: #{e.status}:#{e.message}\n " + e.backtrace.join("\n ")
|
58
|
+
raise e
|
59
|
+
end
|
60
|
+
|
61
|
+
def new_interface(attr = {})
|
62
|
+
client.interfaces.new attr
|
63
|
+
end
|
64
|
+
|
65
|
+
def power_check(uuid)
|
66
|
+
client.server_power_get(uuid).body['power']
|
67
|
+
end
|
68
|
+
|
69
|
+
def power_off(uuid)
|
70
|
+
client.server_power_off(uuid) if power_check(uuid)
|
71
|
+
end
|
72
|
+
|
73
|
+
def destroy_vm(uuid)
|
74
|
+
attached_storage = []
|
75
|
+
|
76
|
+
client.servers.get(uuid).relations['storages'].each do |storage|
|
77
|
+
attached_storage << storage['object_uuid']
|
78
|
+
end
|
79
|
+
|
80
|
+
if power_check(uuid)
|
81
|
+
client.server_power_off(uuid)
|
82
|
+
end
|
83
|
+
sleep(1) until client.servers.get(uuid).status != "in-provisioning"
|
84
|
+
find_vm_by_uuid(uuid).destroy
|
85
|
+
|
86
|
+
attached_storage.each do |storage_uuid|
|
87
|
+
client.storages.destroy(storage_uuid)
|
88
|
+
end
|
89
|
+
rescue ActiveRecord::RecordNotFound
|
90
|
+
# if the VM does not exists, we don't really care.
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
94
|
+
def save_vm(uuid, attr)
|
95
|
+
vm = find_vm_by_uuid(uuid)
|
96
|
+
vm.attributes.merge!(attr.symbolize_keys).deep_symbolize_keys
|
97
|
+
update_interfaces(vm, attr[:interfaces_attributes])
|
98
|
+
vm.save
|
99
|
+
end
|
100
|
+
|
101
|
+
def ips
|
102
|
+
client.ips
|
103
|
+
end
|
104
|
+
|
105
|
+
def interfaces
|
106
|
+
client.interfaces rescue []
|
107
|
+
end
|
108
|
+
|
109
|
+
def networks
|
110
|
+
client.networks rescue []
|
111
|
+
end
|
112
|
+
|
113
|
+
def network
|
114
|
+
client.networks.get(network_uuid)
|
115
|
+
end
|
116
|
+
|
117
|
+
def storages
|
118
|
+
client.storages
|
119
|
+
end
|
120
|
+
|
121
|
+
def templates
|
122
|
+
client.templates
|
123
|
+
end
|
124
|
+
|
125
|
+
def sshkeys
|
126
|
+
client.sshkeys
|
127
|
+
end
|
128
|
+
|
129
|
+
def available_templates
|
130
|
+
images = []
|
131
|
+
collection = client.templates
|
132
|
+
begin
|
133
|
+
images += collection.to_a
|
134
|
+
end until !collection.next_page
|
135
|
+
images
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.model_name
|
139
|
+
ComputeResource.model_name
|
140
|
+
end
|
141
|
+
|
142
|
+
def find_vm_by_uuid(uuid)
|
143
|
+
client.servers.get(uuid)
|
144
|
+
rescue Fog::Compute::Gridscale::Error
|
145
|
+
raise(ActiveRecord::RecordNotFound)
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_connection(options = {})
|
149
|
+
super
|
150
|
+
errors[:token].empty? && errors[:uuid].empty? && networks.count
|
151
|
+
rescue Excon::Errors::Unauthorized => e
|
152
|
+
errors[:base] << e.response.body
|
153
|
+
rescue Fog::Errors::Error => e
|
154
|
+
errors[:base] << e.message
|
155
|
+
end
|
156
|
+
|
157
|
+
def default_region_name
|
158
|
+
@default_region_name ||= 'de/fra'
|
159
|
+
rescue Excon::Errors::Unauthorized => e
|
160
|
+
errors[:base] << e.response.body
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.provider_friendly_name
|
164
|
+
'gridscale'
|
165
|
+
end
|
166
|
+
|
167
|
+
def user_data_supported?
|
168
|
+
true
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
def client
|
174
|
+
@client ||= Fog::Compute.new(
|
175
|
+
:provider => 'gridscale',
|
176
|
+
:api_token => api_token,
|
177
|
+
:user_uuid => user_uuid
|
178
|
+
)
|
179
|
+
end
|
180
|
+
|
181
|
+
def vm_instance_defaults
|
182
|
+
super.merge(
|
183
|
+
:location_uuid => '45ed677b-3702-4b36-be2a-a2eab9827950'
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
def default_iface_name(interfaces)
|
188
|
+
nic_name_num = 1
|
189
|
+
name_blacklist = interfaces.map{ |i| i[:name]}.reject{|n| n.blank?}
|
190
|
+
nic_name_num += 1 while name_blacklist.include?("nic#{nic_name_num}")
|
191
|
+
"nic#{nic_name_num}"
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|