lib/providers/lxd.rb in gogetit-0.2.1 vs lib/providers/lxd.rb in gogetit-0.3.0
- old
+ new
@@ -1,7 +1,8 @@
require 'hyperkit'
require 'gogetit/util'
+require 'yaml'
module Gogetit
class GogetLXD
include Gogetit::Util
@@ -39,36 +40,225 @@
until get_state(name) == state
sleep 3
end
end
- def create(name, args = {})
+ def generate_args(options)
+ args = {}
+ args[:devices] = {}
+
+ ifaces = check_ip_available(options['ipaddresses'], maas, logger)
+ abort("There is no dns server specified for the gateway network.") \
+ unless ifaces[0]['dns_servers'][0]
+ abort("There is no gateway specified for the gateway network.") \
+ unless ifaces[0]['gateway_ip']
+ args[:ifaces] = ifaces
+ args[:config] = {
+ 'user.network-config': {
+ 'version' => 1,
+ 'config' => [
+ {
+ 'type' => 'nameserver',
+ 'address' => ifaces[0]['dns_servers'][0]
+ }
+ ]
+ }
+ }
+
+ ifaces.each_with_index do |iface,index|
+ if index == 0
+ iface_conf = {
+ 'type' => 'physical',
+ 'name' => "eth#{index}",
+ 'subnets' => [
+ {
+ 'type' => 'static',
+ 'ipv4' => true,
+ 'address' => iface['ip'] + '/' + iface['cidr'].split('/')[1],
+ 'gateway' => iface['gateway_ip'],
+ 'mtu' => iface['vlan']['mtu'],
+ 'control' => 'auto'
+ }
+ ]
+ }
+ elsif index > 0
+ if ifaces[0]['vlan']['name'] != 'untagged'
+ iface_conf = {
+ 'type' => 'physical',
+ 'name' => "eth#{index}",
+ 'subnets' => [
+ {
+ 'type' => 'static',
+ 'ipv4' => true,
+ 'address' => iface['ip'] + '/' + iface['cidr'].split('/')[1],
+ 'mtu' => iface['vlan']['mtu'],
+ 'control' => 'auto'
+ }
+ ]
+ }
+ elsif ifaces[0]['vlan']['name'] == 'untagged'
+ iface_conf = {
+ 'type' => 'vlan',
+ 'name' => "eth0.#{iface['vlan']['vid'].to_s}",
+ 'vlan_id' => iface['vlan']['vid'].to_s,
+ 'vlan_link' => 'eth0',
+ 'subnets' => [
+ {
+ 'type' => 'static',
+ 'ipv4' => true,
+ 'address' => iface['ip'] + '/' + iface['cidr'].split('/')[1],
+ 'mtu' => iface['vlan']['mtu'],
+ 'control' => 'auto'
+ }
+ ]
+ }
+ end
+ end
+
+ args[:config][:'user.network-config']['config'].push(iface_conf)
+ end
+
+ args[:config][:"user.network-config"] = \
+ YAML.dump(args[:config][:"user.network-config"])[4..-1]
+
+ # To configure devices
+ ifaces.each_with_index do |iface,index|
+ if index == 0
+ if iface['vlan']['name'] == 'untagged' # or vid == 0
+ args[:devices][:"eth#{index}"] = {
+ mtu: iface['vlan']['mtu'].to_s, #This must be string
+ name: "eth#{index}",
+ nictype: 'bridged',
+ parent: config[:default][:native_bridge],
+ type: 'nic'
+ }
+ elsif iface['vlan']['name'] != 'untagged' # or vid != 0
+ args[:devices][:"eth#{index}"] = {
+ mtu: iface['vlan']['mtu'].to_s, #This must be string
+ name: "eth#{index}",
+ nictype: 'bridged',
+ parent: config[:default][:native_bridge] + "-" + iface['vlan']['vid'].to_s,
+ type: 'nic'
+ }
+ end
+ # When ifaces[0]['vlan']['name'] == 'untagged' and index > 0,
+ # it does not need to generate more devices
+ # since it will configure the IPs with tagged VLANs.
+ elsif ifaces[0]['vlan']['name'] != 'untagged'
+ args[:devices][:"eth#{index}"] = {
+ mtu: iface['vlan']['mtu'].to_s, #This must be string
+ name: "eth#{index}",
+ nictype: 'bridged',
+ parent: config[:default][:native_bridge] + "-" + iface['vlan']['vid'].to_s,
+ type: 'nic'
+ }
+ end
+ end
+
+ return args
+ end
+
+ def create(name, options = {})
logger.info("Calling <#{__method__.to_s}>")
- if container_exists?(name) or maas.domain_name_exists?(name)
- puts "Container #{name} already exists!"
- return false
+ abort("Container or Hostname #{name} already exists!") \
+ if container_exists?(name) or maas.domain_name_exists?(name)
+
+ args = {}
+ if options['ipaddresses']
+ args = generate_args(options)
+ elsif options[:vlans]
+ #check_vlan_available(options[:vlans])
+ else
+ args[:profiles] ||= config[:lxd][:profiles]
end
args[:alias] ||= config[:lxd][:default_alias]
- args[:profiles] ||= config[:lxd][:profiles]
args[:sync] ||= true
+
conn.create_container(name, args)
+ container = conn.container(name)
+
+ if options['vlans'] or options['ipaddresses']
+ container.devices = args[:devices].merge!(container.devices.to_hash)
+ conn.update_container(name, container)
+ # Fetch container object again
+ container = conn.container(name)
+
+ # Generate params to reserve IPs
+ args[:ifaces].each_with_index do |iface,index|
+ if index == 0
+ params = {
+ 'subnet' => iface['cidr'],
+ 'ip' => iface['ip'],
+ 'hostname' => name,
+ 'mac' => container[:expanded_config][:"volatile.eth#{index}.hwaddr"]
+ }
+ elsif index > 0
+ # if dot, '.', is used as a conjunction instead of '-', it fails ocuring '404 not found'.
+ # if under score, '_', is used as a conjunction instead of '-', it breaks MAAS DNS somehow..
+ if args[:ifaces][0]['vlan']['name'] == 'untagged'
+ params = {
+ 'subnet' => iface['cidr'],
+ 'ip' => iface['ip'],
+ 'hostname' => 'eth0' + '-' + iface['vlan']['vid'].to_s + '-' + name,
+ 'mac' => container[:expanded_config][:"volatile.eth0.hwaddr"]
+ }
+ elsif args[:ifaces][0]['vlan']['name'] != 'untagged'
+ params = {
+ 'subnet' => iface['cidr'],
+ 'ip' => iface['ip'],
+ 'hostname' => "eth#{index}" + '-' + name,
+ 'mac' => container[:expanded_config][:"volatile.eth#{index}.hwaddr"]
+ }
+ end
+ end
+ maas.ipaddresses('reserve', params)
+ end
+ end
+
conn.start_container(name, :sync=>"true")
fqdn = name + '.' + maas.get_domain
wait_until_available(fqdn, logger)
logger.info("#{name} has been created.")
true
end
def destroy(name, args = {})
logger.info("Calling <#{__method__.to_s}>")
+
+ container = conn.container(name)
args[:sync] ||= true
+
if get_state(name) == 'Running'
conn.stop_container(name, args)
end
+
wait_until_state(name, 'Stopped')
conn.delete_container(name, args)
+
+ if container[:config][:"user.network-config"]
+ net_conf = YAML.load(
+ container[:config][:"user.network-config"]
+ )['config']
+ # To remove DNS configuration
+ net_conf.shift
+
+ net_conf.each do |nic|
+ if nic['subnets'][0]['type'] == 'static'
+ # It assumes we only assign a single subnet on a VLAN.
+ # Subnets in a VLAN, VLANs in a Fabric
+ ip = nic['subnets'][0]['address'].split('/')[0]
+
+ if maas.ipaddresses_reserved?(ip)
+ maas.ipaddresses('release', { 'ip' => ip })
+ end
+ end
+ end
+ end
+
+ # When multiple static IPs were reserved, it will not delete anything
+ # since they are deleted when releasing the IPs above.
maas.delete_dns_record(name)
logger.info("#{name} has been destroyed.")
true
end
end