-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
generates mac addresses for virtual machines
- Loading branch information
Showing
2 changed files
with
67 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'digest' | ||
|
||
# generates a deterministic pseudorandom mac address, using hostname as seed | ||
# | ||
# prefix validated to follow the following parameters: | ||
# - must contain exactly 6 hex digits | ||
# - second digit must be one of [2,6,a,e] (per RFC7042 §2.1, see "Local bit") | ||
# - case is ignored | ||
# - may contain unlimited number of non-alphanumerics as delimeters | ||
# | ||
# generated address contains | ||
# - 3 byte fixed OUI (prefix) | ||
# - 21 "random" bits (seeded from hostname) | ||
# - 3 bit sequential number (index) | ||
Puppet::Functions.create_function(:generate_mac) do | ||
dispatch :generate_mac do | ||
param "String", :prefix | ||
param "String", :hostname | ||
param "Integer", :index | ||
end | ||
|
||
def generate_mac(prefix, hostname, index) | ||
unless(index.between?(0,7)) | ||
raise(ArgumentError, "#{index} must be between 0 and 7, I can only generate 8 mac addresses per host!") | ||
end | ||
|
||
oui = prefix.downcase.gsub(/[^0-9a-z]/,'') | ||
unless(oui =~ /^[a-f0-9][26ae][a-f0-9]{4}$/) | ||
raise(ArgumentError, "invalid mac prefix!") | ||
end | ||
|
||
integer_id = (Digest::SHA256.hexdigest(hostname)[0,6].to_i(16) & 0xFF_FF_F8) + index | ||
hex_id = sprintf('%06x',integer_id) | ||
"#{oui}#{hex_id}".each_char.each_slice(2).map{|x| x.join}.join(':') | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# frozen_string_literal: true | ||
|
||
# Copyright (c) 2020 The Regents of the University of Michigan. | ||
# All Rights Reserved. Licensed according to the terms of the Revised | ||
# BSD License. See LICENSE.txt for details. | ||
require "spec_helper" | ||
|
||
describe "generate_mac" do | ||
it "generates simple addresses" do | ||
is_expected.to run.with_params('02:00:00', 'example.com', 0).and_return('02:00:00:a3:79:a0') | ||
is_expected.to run.with_params('12-0f-00', 'example.com', 2).and_return('12:0f:00:a3:79:a2') | ||
end | ||
it "fails on invalid chars" do | ||
is_expected.to run.with_params('g2:00:00', 'example.com', 0).and_raise_error(ArgumentError) | ||
end | ||
it "correctly masks final 3 bits" do | ||
is_expected.to run.with_params('06 12 34', 'my.host.name', 0).and_return('06:12:34:3b:d9:98') | ||
is_expected.to run.with_params('5a.67.89', 'my.host.name', 3).and_return('5a:67:89:3b:d9:9b') | ||
is_expected.to run.with_params('AE:BC:DE', 'my.host.name', 7).and_return('ae:bc:de:3b:d9:9f') | ||
end | ||
it "fails on non-private oui" do | ||
is_expected.to run.with_params('03:00:00', 'example.com', 0).and_raise_error(ArgumentError) | ||
end | ||
it "fails on out of range index" do | ||
is_expected.to run.with_params('02:00:00', 'example.com', 11).and_raise_error(ArgumentError) | ||
is_expected.to run.with_params('02:00:00', 'example.com', -1).and_raise_error(ArgumentError) | ||
end | ||
end | ||
|