Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Sequel.migration do
up do
alter_table(:ip_addresses) do
add_column :nic_group, Integer, null: true
end

from(:ip_addresses).each do |row|
integer_representation = row[:address_str].to_i

cidr_notation = Bosh::Director::IpAddrOrCidr.new(integer_representation).to_s

from(:ip_addresses).where(id: row[:id]).update(address_str: cidr_notation)
end
end
down do
alter_table(:ip_addresses) do
drop_column :nic_group
end
from(:ip_addresses).each do |row|
cidr_notation = row[:address_str]

ip_addr = Bosh::Director::IpAddrOrCidr.new(cidr_notation)
integer_representation = ip_addr.to_i
from(:ip_addresses).where(id: row[:id]).update(address_str: integer_representation)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ def create_instance_plan(stemcell)
end

compilation_network = @deployment_plan.network(@deployment_plan.compilation.network_name)
reservation = DesiredNetworkReservation.new_dynamic(instance.model, compilation_network)
reservation = DesiredNetworkReservation.new_dynamic(instance.model, compilation_network, nil)
@logger.debug("Creating new dynamic reservation #{reservation.inspect} for instance '#{instance}' and compile instance group '#{compile_instance_group}'")
desired_instance = DeploymentPlan::DesiredInstance.new(compile_instance_group)
instance_plan = DeploymentPlan::InstancePlan.new(
existing_instance: instance.model,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def self.parse(network_spec, availability_zones, logger)
validate_network_has_no_key('az', name, network_spec)
validate_network_has_no_key('azs', name, network_spec)
validate_network_has_no_key('managed', name, network_spec)
validate_network_has_no_key('prefix', name, network_spec)

if network_spec.has_key?('subnets')
validate_network_has_no_key_while_subnets_present('dns', name, network_spec)
Expand All @@ -21,16 +22,21 @@ def self.parse(network_spec, availability_zones, logger)
subnets = network_spec['subnets'].map do |subnet_properties|
name_servers = name_server_parser.parse(subnet_properties['name'], subnet_properties)
cloud_properties = safe_property(subnet_properties, 'cloud_properties', class: Hash, default: {})
prefix = safe_property(subnet_properties, 'prefix', class: Integer, default: Network::IPV4_DEFAULT_PREFIX_SIZE)
raise NetworkInvalidProperty, "Prefix property is not supported for dynamic networks." unless prefix == Network::IPV4_DEFAULT_PREFIX_SIZE
subnet_availability_zones = parse_availability_zones(subnet_properties, availability_zones, name)
DynamicNetworkSubnet.new(name_servers, cloud_properties, subnet_availability_zones)
DynamicNetworkSubnet.new(name_servers, cloud_properties, subnet_availability_zones, prefix)
end
else
cloud_properties = safe_property(network_spec, 'cloud_properties', class: Hash, default: {})
# We need to set the IPv4 default value (dynamic networks only support IPv4)
prefix = Network::IPV4_DEFAULT_PREFIX_SIZE

name_servers = name_server_parser.parse(network_spec['name'], network_spec)
subnets = [DynamicNetworkSubnet.new(name_servers, cloud_properties, nil)]
subnets = [DynamicNetworkSubnet.new(name_servers, cloud_properties, nil, prefix)]
end

new(name, subnets, logger)
new(name, subnets, prefix, logger)
end

def self.validate_network_has_no_key_while_subnets_present(key, name, network_spec)
Expand Down Expand Up @@ -77,9 +83,10 @@ def self.check_validity_of_availability_zone(availability_zone, availability_zon
end
end

def initialize(name, subnets, logger)
def initialize(name, subnets, prefix, logger)
super(name, logger)
@subnets = subnets
@prefix = prefix
end

attr_reader :subnets
Expand All @@ -94,7 +101,7 @@ def initialize(name, subnets, logger)
def network_settings(reservation, default_properties = Network::REQUIRED_DEFAULTS, availability_zone = nil)
unless reservation.dynamic?
raise NetworkReservationWrongType,
"IP '#{format_ip(reservation.ip)}' on network '#{reservation.network.name}' does not belong to dynamic pool"
"IP '#{reservation.ip}' on network '#{reservation.network.name}' does not belong to dynamic pool"
end

if availability_zone.nil?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
module Bosh::Director
module DeploymentPlan
class DynamicNetworkSubnet
def initialize(dns, cloud_properties, availability_zone_names)
def initialize(dns, cloud_properties, availability_zone_names, prefix)
@dns = dns
@cloud_properties = cloud_properties
@availability_zone_names = availability_zone_names.nil? ? nil : availability_zone_names
@prefix = prefix.to_s
end

attr_reader :dns, :cloud_properties, :availability_zone_names
attr_reader :dns, :cloud_properties, :availability_zone_names, :prefix
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ def parse_networks(instance_group_spec, instance_group_name, manifest_networks)
network_specs.map do |network_spec|
network_name = safe_property(network_spec, 'name', class: String)
default_for = safe_property(network_spec, 'default', class: Array, default: [])
nic_group = safe_property(network_spec, 'nic_group', class: String, default: nil)
static_ips = parse_static_ips(network_spec['static_ips'], instance_group_name)

deployment_network = look_up_deployment_network(manifest_networks, instance_group_name, network_name)
deployment_network.validate_reference_from_job!(network_spec, instance_group_name)

JobNetwork.new(network_name, static_ips, default_for, deployment_network)
JobNetwork.new(network_name, static_ips, default_for, deployment_network, nic_group)
end
end

Expand All @@ -56,9 +57,9 @@ def parse_static_ips(static_ips_raw, instance_group_name)
if static_ips_raw
static_ips = []
each_ip(static_ips_raw) do |ip|
if static_ips.include?(ip)
if ip_in_array?(ip, static_ips)
raise JobInvalidStaticIPs,
"Instance group '#{instance_group_name}' specifies static IP '#{format_ip(ip)}' more than once"
"Instance group '#{instance_group_name}' specifies static IP '#{ip}' more than once"
end

static_ips.push(ip)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ module DeploymentPlan
class InstanceGroupSpecParser
include ValidationHelper
include Bosh::Common::Template::PropertyHelper
include IpUtil

MANUAL_LINK_KEYS = %w[instances properties address].freeze

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Bosh::Director
module DeploymentPlan
class InstanceNetworkReservations
include Enumerable
include IpUtil
extend IpUtil

def self.create_from_db(instance_model, deployment, logger)
reservations = new(logger)
Expand All @@ -17,14 +17,15 @@ def self.create_from_db(instance_model, deployment, logger)
deployment,
ip_address.network_name,
ip_address.address,
'not-dynamic')
'not-dynamic',
ip_address.nic_group)
end

unless instance_model.spec.nil?
# Dynamic network reservations are not saved in DB, recreating from instance spec
instance_model.spec.fetch('networks', []).each do |network_name, network_config|
next unless network_config['type'] == 'dynamic'
reservations.add_existing(instance_model, deployment, network_name, network_config['ip'], network_config['type'])
reservations.add_existing(instance_model, deployment, network_name, to_ipaddr(network_config['ip']), network_config['type'], network_config['nic_group'])
end
end

Expand Down Expand Up @@ -54,9 +55,9 @@ def delete(reservation)
@reservations.delete(reservation)
end

def add_existing(instance_model, deployment, network_name, ip, existing_network_type)
def add_existing(instance_model, deployment, network_name, ip, existing_network_type, nic_group)
network = find_network(deployment, ip, network_name, instance_model)
reservation = ExistingNetworkReservation.new(instance_model, network, ip, existing_network_type)
reservation = ExistingNetworkReservation.new(instance_model, network, ip, existing_network_type, nic_group)
deployment.ip_provider.reserve_existing_ips(reservation)
@reservations << reservation
end
Expand All @@ -75,17 +76,17 @@ def find_network(deployment, cidr_ip, network_name, instance_model)
ip_in_subnet = network.subnets.find { |snet| snet.is_reservable?(cidr_ip) }
next unless ip_in_subnet

@logger.debug("Registering existing reservation with IP '#{format_ip(cidr_ip)}' for instance '#{instance_model}'"\
@logger.debug("Registering existing reservation with IP '#{cidr_ip}' for instance '#{instance_model}'"\
"on network '#{network.name}'")
return network
end
elsif network_match_on_name # dynamic and static vip
@logger.debug("Registering existing reservation with IP '#{format_ip(cidr_ip)}' for instance '#{instance_model}'"\
@logger.debug("Registering existing reservation with IP '#{cidr_ip}' for instance '#{instance_model}'"\
"on network '#{network_name}'")
return network_match_on_name
end

@logger.debug("Failed to find network #{network_name} or a network with valid subnets for #{format_ip(cidr_ip)},"\
@logger.debug("Failed to find network #{network_name} or a network with valid subnets for #{cidr_ip},"\
'reservation will be marked as obsolete')
Network.new(network_name, nil)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def configuration_changed?
end

def remove_obsolete_network_plans_for_ips(ips)
network_plans.delete_if { |plan| ips.include?(plan.reservation.ip.to_s) }
network_plans.delete_if { |plan| ips.include?(plan.reservation.ip.base_addr) }
end

def release_obsolete_network_plans(ip_provider)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,16 @@ def reserve_manual(reservation)
@logger.debug("Reserving #{reservation.desc} for manual network '#{reservation.network.name}'")

if (subnet = reservation.network.find_subnet_containing(reservation.ip))
if subnet.restricted_ips.include?(reservation.ip)
message = "Failed to reserve IP '#{format_ip(reservation.ip)}' for network '#{subnet.network_name}': IP belongs to reserved range"
if ip_in_array?(reservation.ip, subnet.restricted_ips)
message = "Failed to reserve IP '#{reservation.ip}' for network '#{subnet.network_name}': IP belongs to reserved range"
@logger.error(message)
raise Bosh::Director::NetworkReservationIpReserved, message
end

reserve_manual_with_subnet(reservation, subnet)
else
raise NetworkReservationIpOutsideSubnet,
"Provided static IP '#{format_ip(reservation.ip)}' does not belong to any subnet in network '#{reservation.network.name}'"
"Provided static IP '#{reservation.ip}' does not belong to any subnet in network '#{reservation.network.name}'"
end
end
end
Expand All @@ -99,12 +99,13 @@ def reserve_manual_with_subnet(reservation, subnet)
@ip_repo.add(reservation)

subnet_az_names = subnet.availability_zone_names.to_a.join(', ')
if subnet.static_ips.include?(reservation.ip)

if ip_in_array?(reservation.ip, subnet.static_ips)
reservation.resolve_type(:static)
@logger.debug("Found subnet with azs '#{subnet_az_names}' for #{format_ip(reservation.ip)}. Reserved as static network reservation.")
@logger.debug("Found subnet with azs '#{subnet_az_names}' for #{reservation.ip}. Reserved as static network reservation.")
else
reservation.resolve_type(:dynamic)
@logger.debug("Found subnet with azs '#{subnet_az_names}' for #{format_ip(reservation.ip)}. Reserved as dynamic network reservation.")
@logger.debug("Found subnet with azs '#{subnet_az_names}' for #{reservation.ip}. Reserved as dynamic network reservation.")
end
end

Expand Down
Loading
Loading