Support human readable synonym param ks_disks for ks_spaces, add validations for this and small refactoring.

This commit is contained in:
Vladmir Sharhsov(warpc) 2013-08-07 12:20:30 +04:00
parent 82b9a90d51
commit d67bbd5c3e
5 changed files with 198 additions and 48 deletions

View File

@ -64,7 +64,7 @@ end
reporter = ConsoleReporter.new
Astute.logger = Logger.new(STDOUT) if opts[:verbose]
environment = Astute::Cli::Enviroment.load_file(opts[:filename])
environment = Astute::Cli::Enviroment.new(opts[:filename])
deploy_engine = nil

View File

@ -27,16 +27,57 @@ nodes:
auth_key: ! '""'
mco_connector: rabbitmq
mco_host: 10.20.0.2
ks_spaces: ! '"[{\"type\": \"disk\", \"id\": \"disk/by-path/pci-0000:00:0d.0-scsi-0:0:0:0\",
\"volumes\": [{\"mount\": \"/boot\", \"type\": \"partition\", \"size\": 209715200},
{\"type\": \"mbr\"}, {\"size\": 16959668224, \"type\": \"pv\", \"vg\": \"os\"}],
\"size\": 17179869184}, {\"type\": \"disk\", \"id\": \"disk/by-path/pci-0000:00:0d.0-scsi-1:0:0:0\",
\"volumes\": [{\"size\": 536860426240, \"type\": \"pv\", \"vg\": \"os\"}], \"size\":
536870912000}, {\"type\": \"disk\", \"id\": \"disk/by-path/pci-0000:00:0d.0-scsi-2:0:0:0\",
\"volumes\": [{\"size\": 2411714314240, \"type\": \"pv\", \"vg\": \"os\"}],
\"size\": 2411724800000}, {\"type\": \"vg\", \"id\": \"os\", \"volumes\": [{\"mount\":
\"/\", \"type\": \"lv\", \"name\": \"root\", \"size\": 2963243016192}, {\"mount\":
\"swap\", \"type\": \"lv\", \"name\": \"swap\", \"size\": 2090065920}]}]"'
# ks_spaces: '"[{\"type\": \"disk\", \"id\": \"disk/by-path/pci-0000:00:0d.0-scsi-0:0:0:0\",
# \"volumes\": [{\"mount\": \"/boot\", \"type\": \"partition\", \"size\": 209715200},
# {\"type\": \"mbr\"}, {\"size\": 16959668224, \"type\": \"pv\", \"vg\": \"os\"}],
# \"size\": 17179869184}, {\"type\": \"disk\", \"id\": \"disk/by-path/pci-0000:00:0d.0-scsi-1:0:0:0\",
# \"volumes\": [{\"size\": 536860426240, \"type\": \"pv\", \"vg\": \"os\"}], \"size\":
# 536870912000}, {\"type\": \"disk\", \"id\": \"disk/by-path/pci-0000:00:0d.0-scsi-2:0:0:0\",
# \"volumes\": [{\"size\": 2411714314240, \"type\": \"pv\", \"vg\": \"os\"}],
# \"size\": 2411724800000}, {\"type\": \"vg\", \"id\": \"os\", \"volumes\": [{\"mount\":
# \"/\", \"type\": \"lv\", \"name\": \"root\", \"size\": 2963243016192}, {\"mount\":
# \"swap\", \"type\": \"lv\", \"name\": \"swap\", \"size\": 2090065920}]}]"'
ks_disks:
# All size should be set in megabytes
- type: "disk"
id: "disk/by-path/pci-0000:00:0d.0-scsi-0:0:0:0"
size: 16384
volumes:
- type: "partition"
mount: "/boot"
size: 200
- type: "mbr"
- type: "pv"
size: 16174
vg: os
- type: "disk"
id: "disk/by-path/pci-0000:00:0d.0-scsi-1:0:0:0"
size: 2300000
volumes:
- type: "pv"
size: 511990
vg: os
- type: "disk"
id: "disk/by-path/pci-0000:00:0d.0-scsi-2:0:0:0"
size: 2300000
volumes:
- type: "pv"
size: 2299990
vg: os
- type: "vg"
id: "os"
size: 2300000
volumes:
- type: "lv"
mount: "/"
name: root
size: 2825968
vg: os
- type: "lv"
mount: "/swap"
name: swap
size: 1993
vg: os
power_type: ssh
power_user: root
@ -59,11 +100,11 @@ nodes:
onboot: 'no'
peerdns: 'no'
- name: eth0
ip_address: 10.20.0.6 # ip, power_address
ip_address: 10.20.0.63 # ip, power_address
netmask: 255.255.255.0
dns_name: controller-22.domain.tld # fqdn
static: '0'
mac_address: 08:00:27:DE:91:C5 # mac
mac_address: 08:00:27:F0:B1:7E # mac
onboot: 'yes'
peerdns: 'no'
use_for_provision: true

View File

@ -13,31 +13,57 @@
# under the License.
require 'yaml'
require 'json'
require 'astute/ext/hash'
require 'astute/cli/enviroment'
require 'astute/cli/yaml_validator'
MB_TO_B = 1024 ** 2
module Astute
class Cli::Enviroment
def self.load_file(file)
@config = YAML.load_file(file)
validate_env
convert_to_full_conf
end
def self.validate_env
validator = Cli::YamlValidator.new()
errors = validator.validate(@config)
module Cli
class Enviroment
errors.each do |e|
puts "[#{e.path}] #{e.message}"
def initialize(file)
@config = YAML.load_file(file)
validate_env
convert_to_full_conf
end
def [](key)
@config[key]
end
end
def self.convert_to_full_conf
# Provision
@config['nodes'].each_with_index do |node, index|
provision_eth = node['interfaces'].find {|eth| eth['use_for_provision'] }
def validate_env
validator = YamlValidator.new
errors = validator.validate(@config)
errors.each do |e|
puts "[#{e.path}] #{e.message}"
end
end
def convert_to_full_conf
# Provision section
@config['nodes'].each_with_index do |node, index|
node.reverse_merge!(
'id' => index,
'uid' => index
)
define_provision_network(node)
define_interfaces_and_interfaces_extra(node)
define_ks_spaces(node)
end
# Deploy section
end
private
# Add duplicates params to node: ip, power_address, mac, fqdn
def define_provision_network(node)
provision_eth = node['interfaces'].find {|eth| eth['use_for_provision'] } rescue nil
if provision_eth
node.reverse_merge!(
'ip' => provision_eth['ip_address'],
@ -45,18 +71,32 @@ module Astute
'mac' => provision_eth['mac_address'],
'fqdn' => provision_eth['dns_name']
)
provision_eth.delete('use_for_provision')
end
missing_keys = node.find_missing_keys(['ip', 'power_address', 'mac', 'fqdn'])
if provision_eth.nil? && !missing_keys.empty?
absent_keys = node.absent_keys(['ip', 'power_address', 'mac', 'fqdn'])
if provision_eth.nil? && !absent_keys.empty?
raise "Please set 'use_for_provision' parameter for #{node['name']}
or set manually #{missing_keys.each {|k| p k}}"
end
node.reverse_merge!(
'id' => index,
'uid' => index
)
# Extend blocks interfaces and interfaces_extra to old formats
end
# Extend blocks interfaces and interfaces_extra to old formats:
# interfaces:
# eth0:
# ip_address: 10.20.0.188
# netmask: 255.255.255.0
# dns_name: *fqdn
# static: '0'
# mac_address: 08:00:27:C2:06:DE
# interfaces_extra:
# eth0:
# onboot: 'yes'
# peerdns: 'no'
def define_interfaces_and_interfaces_extra(node)
return if [node['interfaces'], node['extra_interfaces']].all? {|i| i.is_a?(Hash)}
formated_interfaces = {}
interfaces_extra_interfaces = {}
node['interfaces'].each do |eth|
@ -67,9 +107,46 @@ module Astute
}
end
node['interfaces'] = formated_interfaces
node['extra_interfaces'] = interfaces_extra_interfaces
node['extra_interfaces'] = interfaces_extra_interfaces
end
@config
end
end
# Generate 'ks_spaces' param from 'ks_disks' param in section 'ks_meta'
# Example input for 'ks_disks' param:
# [{
# "type"=>"disk",
# "id"=>"disk/by-path/pci-0000:00:0d.0-scsi-0:0:0:0",
# "size"=>16384,
# "volumes"=>[
# {
# "type"=>"partition",
# "mount"=>"/boot",
# "size"=>200
# },
# {
# "type"=>"pv",
# "size"=>16174,
# "vg"=>"os"
# }
# ]
# }]
# Example result for 'ks_spaces' param: [{\\\"type\":\"disk\",\"id\":\"disk/by-path/pci-0000:00:0d.0-scsi-0:0:0:0\",\"size\":16384,\"volumes\":[{\"type\":\"partition\",\"mount\":\"/boot\",\"size\":200},{\"type\":\"pv\",\"size\":16174,\"vg\":\"os\"}]}]
def define_ks_spaces(node)
return unless node['ks_meta'].absent? 'ks_spaces'
if node['ks_meta'].absent? 'ks_disks'
raise "Please set 'ks_disks' or 'ks_spaces' parameter in section ks_meta for #{node['name']}"
end
# Convert size from megabytes to bytes
node['ks_meta']['ks_disks']. each do |disk|
disk['size'] *= MB_TO_B if disk['size']
disk['volumes'].each do |volume|
volume['size'] *= MB_TO_B if volume['size']
end
end
node['ks_meta']['ks_spaces'] = node['ks_meta']['ks_disks'].to_json.gsub("\"", "\\\"")
node['ks_meta'].delete('ks_disks')
end
end # class end
end # module Cli
end

View File

@ -110,7 +110,39 @@ mapping:
required: true
"ks_spaces":
type: text
required: true
"ks_disks":
type: seq
sequence:
- type: map
mapping:
"type":
type: str
required: true
enum: [disk, vg]
"id":
type: text
required: true
unique: yes
"size":
type: int
required: true
"volumes":
type: seq
sequence:
- type: map
mapping:
"type":
type: text
required: true
enum: [lv, pv, partition, mbr]
"mount":
type: text
"size":
type: int
"vg":
type: text
"name":
type: text
"interfaces":
type: seq
sequence:

View File

@ -24,12 +24,12 @@ class Hash
replace(reverse_merge(another_hash))
end
def find_missing_keys(array)
array.select { |key| is_missing_key?(key) }
def absent_keys(array)
array.select { |key| absent?(key) }
end
def is_missing_key?(key)
self[key].nil?
def absent?(key)
self[key].nil? || self[key].empty?
end
end