diff --git a/default.nix b/default.nix index affa43f..fb4a671 100644 --- a/default.nix +++ b/default.nix @@ -2,82 +2,59 @@ pkgs ? (import { }), }: let - moduleEX2300 = import ./moduleMaker.nix [ - "ge-0/0/0" - "ge-0/0/1" - "ge-0/0/2" - "ge-0/0/3" - "ge-0/0/4" - "ge-0/0/5" - "ge-0/0/6" - "ge-0/0/7" - "ge-0/0/8" - "ge-0/0/9" - "ge-0/0/10" - "ge-0/0/11" - "ge-0/0/12" - "ge-0/0/13" - "ge-0/0/14" - "ge-0/0/15" - "ge-0/0/16" - "ge-0/0/17" - "ge-0/0/18" - "ge-0/0/19" - "ge-0/0/20" - "ge-0/0/21" - "ge-0/0/22" - "ge-0/0/23" - "ge-0/0/24" - "ge-0/0/25" - "ge-0/0/26" - "ge-0/0/27" - "ge-0/0/28" - "ge-0/0/29" - "ge-0/0/30" - "ge-0/0/31" - "ge-0/0/32" - "ge-0/0/33" - "ge-0/0/34" - "ge-0/0/35" - "ge-0/0/36" - "ge-0/0/37" - "ge-0/0/38" - "ge-0/0/39" - "ge-0/0/40" - "ge-0/0/41" - "ge-0/0/42" - "ge-0/0/43" - "ge-0/0/44" - "ge-0/0/45" - "ge-0/0/46" - "ge-0/0/47" - - "ge-0/1/0" - "ge-0/1/1" - "ge-0/1/2" - "ge-0/1/3" - - "xe-0/1/0" - "xe-0/1/1" - "xe-0/1/2" - "xe-0/1/3" - - "me0" - ]; + lib = pkgs.lib; + hive_mod = { lib, config, name, ... }: with lib; { + options.deployment = { + targetHost = mkOption { type = types.str; }; + rpc = mkOption { + type = types.package; + readOnly = true; + }; + cmd = mkOption { + type = types.package; + readOnly = true; + }; + }; + config.deployment = rec { + rpc = + pkgs.writeText "config-${name}_rpc.xml" '' + + + + ${config.netconf.xmls.configuration} + + + + + + + + + + ''; + cmd = pkgs.writeShellApplication { + name = "deploy-${name}.sh"; + runtimeInputs = with pkgs; [ openssh ]; + text = ''ssh "${config.deployment.targetHost}" -p 830 -s netconf < ${rpc}''; + }; + }; + }; evaluator = name: module_inst: let cfg = pkgs.lib.evalModules { specialArgs = { - inherit pkgs name; + inherit name; }; modules = [ - moduleEX2300 + ./junos + ./ex2300.nix + hive_mod module_inst ]; }; in - "ln -s ${cfg.config.deployement.cmd} $out/${name}"; + "ln -s ${lib.getExe cfg.config.deployment.cmd} $out/${name}"; hive = import ./netconf-hive.nix; cmds = builtins.attrValues (builtins.mapAttrs evaluator hive); in diff --git a/ex2300.nix b/ex2300.nix new file mode 100644 index 0000000..4165b46 --- /dev/null +++ b/ex2300.nix @@ -0,0 +1,62 @@ +{ + netconf.mandatoryInterfaces = [ + "ge-0/0/0" + "ge-0/0/1" + "ge-0/0/2" + "ge-0/0/3" + "ge-0/0/4" + "ge-0/0/5" + "ge-0/0/6" + "ge-0/0/7" + "ge-0/0/8" + "ge-0/0/9" + "ge-0/0/10" + "ge-0/0/11" + "ge-0/0/12" + "ge-0/0/13" + "ge-0/0/14" + "ge-0/0/15" + "ge-0/0/16" + "ge-0/0/17" + "ge-0/0/18" + "ge-0/0/19" + "ge-0/0/20" + "ge-0/0/21" + "ge-0/0/22" + "ge-0/0/23" + "ge-0/0/24" + "ge-0/0/25" + "ge-0/0/26" + "ge-0/0/27" + "ge-0/0/28" + "ge-0/0/29" + "ge-0/0/30" + "ge-0/0/31" + "ge-0/0/32" + "ge-0/0/33" + "ge-0/0/34" + "ge-0/0/35" + "ge-0/0/36" + "ge-0/0/37" + "ge-0/0/38" + "ge-0/0/39" + "ge-0/0/40" + "ge-0/0/41" + "ge-0/0/42" + "ge-0/0/43" + "ge-0/0/44" + "ge-0/0/45" + "ge-0/0/46" + "ge-0/0/47" + + "ge-0/1/0" + "ge-0/1/1" + "ge-0/1/2" + "ge-0/1/3" + + "xe-0/1/0" + "xe-0/1/1" + "xe-0/1/2" + "xe-0/1/3" + ]; +} diff --git a/junos/default.nix b/junos/default.nix new file mode 100644 index 0000000..a8e2e45 --- /dev/null +++ b/junos/default.nix @@ -0,0 +1,36 @@ +{ + name, + lib, + config, + ... +}: +with lib; +{ + imports = [ + ./protocols.nix + ./interfaces.nix + ./vlans.nix + ]; + options = { + netconf.xmls.configuration = mkOption { + type = types.str; + readOnly = true; + }; + netconf.mandatoryInterfaces = mkOption { type = types.listOf types.str; }; + }; + config.interfaces = + let + mkIntf = name: { + inherit name; + value.enable = mkDefault false; + }; + in + listToAttrs (map mkIntf config.netconf.mandatoryInterfaces); + config.netconf.xmls.configuration = '' + + ${config.netconf.xmls.interfaces} + ${config.netconf.xmls.protocols} + ${config.netconf.xmls.vlans} + + ''; +} diff --git a/moduleMaker.nix b/moduleMaker.nix deleted file mode 100644 index dfbe1c5..0000000 --- a/moduleMaker.nix +++ /dev/null @@ -1,241 +0,0 @@ -interfaces: -{ - name, - lib, - pkgs, - config, - ... -}: -let - cfg = config; -in -with lib; -{ - options = { - deployement = { - targetHost = mkOption { type = types.str; }; - cmd = mkOption { - type = types.package; - readOnly = true; - }; - }; - vlans = - let - range_type.options = { - begin = mkOption { type = types.ints.unsigned; }; - end = mkOption { type = types.ints.unsigned; }; - }; - vlan_type.options = { - ids = mkOption { - type = types.either types.ints.unsigned ( - types.listOf (types.either types.ints.unsigned (types.submodule range_type)) - ); - default = [ ]; - }; - management = mkOption { - # FIXME : support ipv4, either static or dhcp (with the coffee) - type = types.nullOr types.str; - default = null; - description = '' - IP address with wich to permit management on this vlan. - Only one vlan can set an IP (this module limitation, not switch). - ''; - }; - }; - in - mkOption { type = types.attrsOf (types.submodule vlan_type); }; - interfaces = - let - template = name: { - enable = mkEnableOption "the interface ${name}"; - interface-mode = mkOption { - type = types.nullOr ( - types.enum [ - "trunk" - "access" - ] - ); - default = null; - }; - vlans = mkOption { - type = - let - vlan_type = types.either (types.strMatching "[^\n\r]+") (types.ints.unsigned); - in - types.listOf vlan_type; - default = [ ]; - }; - # TODO: use this option - dhcp_trusted = mkOption { - type = types.bool; - default = false; - }; - management = mkOption { - # FIXME : support ipv6, either static or dhcp (with the coffee) - type = types.nullOr types.str; - default = null; - }; - }; - in - builtins.listToAttrs ( - map (name: { - inherit name; - value = template name; - }) interfaces - ); - }; - - config.deployement.cmd = - let - intf_xmlGen = - name: - let - disable_flag = if !cfg.interfaces.${name}.enable then "" else ""; - # FIXME : need to enforce address in reality - mgmt_fam = - if !builtins.isNull cfg.interfaces.${name}.management then - '' - -
- ${cfg.interfaces.${name}.management} -
-
'' - else - ""; - members = map (vlan: "${builtins.toString vlan}") cfg.interfaces.${name}.vlans; - eth_switch = - if builtins.isNull cfg.interfaces.${name}.interface-mode then - "" - else - '' - - ${cfg.interfaces.${name}.interface-mode} - ${builtins.concatStringsSep "" members} - default - ''; - in - '' - - ${name} - ${disable_flag} - - 0 - - ${mgmt_fam} - ${eth_switch} - - - - ''; - interface_xmls = map intf_xmlGen interfaces; - rstp_gen = - name: - if cfg.interfaces.${name}.enable && !builtins.isNull cfg.interfaces.${name}.interface-mode then - "${name}" - else - ""; - rstps = map rstp_gen interfaces; - vlan_trust_table = - let - vlan_map = - inter: vlan: - if builtins.isString vlan && cfg.interfaces.${inter}.enable then - if cfg.interfaces.${inter}.dhcp_trusted then - { ${vlan}.trust = inter; } - else - { ${vlan}.notrust = inter; } - else - { }; - int_map = inter: map (vlan_map inter) cfg.interfaces.${inter}.vlans; - in - builtins.zipAttrsWith (vlan: values: builtins.zipAttrsWith (_: ints: ints) values) ( - builtins.concatMap int_map interfaces - ); - vlans = - let - id_map = - id: - let - list = - if builtins.isInt id then - builtins.toString id - else - "${builtins.toString id.begin}-${builtins.toString id.end}"; - in - ''${list}''; - vlan_map = - vlan: - let - ids = - if !builtins.isList cfg.vlans.${vlan}.ids then - [ "${builtins.toString cfg.vlans.${vlan}.ids}" ] - else - map id_map cfg.vlans.${vlan}.ids; - mgmt_flag = - if !builtins.isNull cfg.vlans.${vlan}.management then "irb.0" else ""; - in - '' - - ${vlan} - ${mgmt_flag} - ${builtins.concatStringsSep "\n" ids} - ''; - in - map vlan_map (builtins.attrNames cfg.vlans); - irb_intf = - let - addresses = map (vlan: vlan.management) (builtins.attrValues cfg.vlans); - addr = builtins.foldl' (acc: addr: if !builtins.isNull addr then addr else acc) null addresses; - in - if !builtins.isNull addr then - '' - - irb - - 0 - - -
${addr}
-
-
-
-
- '' - else - ""; - config = '' - - ${builtins.concatStringsSep "\n" interface_xmls} - ${irb_intf} - - - - ${builtins.concatStringsSep "\n" rstps} - - - - ${builtins.concatStringsSep "\n" vlans} - - ''; - rpc_requests = pkgs.writeText "config-${name}_rpc.xml" '' - - - - - ${config} - - - - - - - - - - - ''; - in - pkgs.writeShellScript "deploy-${name}.sh" '' - ${pkgs.openssh}/bin/ssh ${cfg.deployement.targetHost} -p 830 -s netconf < ${rpc_requests} - ''; -} diff --git a/netconf-hive.nix b/netconf-hive.nix index 4a531ea..0dbfe68 100644 --- a/netconf-hive.nix +++ b/netconf-hive.nix @@ -1,40 +1,60 @@ let - vlansPlan = mgmt: { - "uplink-cri".ids = 223; + vlansPlan = { + "uplink-cri".id = 223; "admin-core" = { - ids = 3000; - management = mgmt; + id = 3000; + l3-interface = "irb.0"; }; - "admin-ap".ids = 3001; - "users".ids = [ + "admin-ap".id = 3001; + "users".id-list = [ { begin = 3045; end = 4094; } ]; - "ap-staging".ids = 2000; + "ap-staging".id = 2000; }; AP = { enable = true; - interface-mode = "trunk"; - vlans = [ - "users" - "admin-ap" - ]; + unit."0".family.ethernet-switching = { + enable = true; + interface-mode = "trunk"; + vlans = [ + "users" + "admin-ap" + ]; + }; }; AP-staging = { enable = true; - interface-mode = "access"; - vlans = [ "ap-staging" ]; + unit."0".family.ethernet-switching = { + enable = true; + interface-mode = "access"; + vlans = [ "ap-staging" ]; + }; }; in { netcore01 = { - deployement.targetHost = "jourdan01.dgn"; + deployment.targetHost = "jourdan01.dgn"; + vlans = vlansPlan; + protocols.rstp = [ + "ge-0/0/12" + "ge-0/0/13" + "ge-0/0/14" + "ge-0/0/15" + "ge-0/0/16" + "ge-0/0/17" + "ge-0/0/42" + "ge-0/0/43" + "ge-0/0/47" - vlans = vlansPlan "fd26:baf9:d250:8000::1001/64"; + "xe-0/1/0" + "xe-0/1/1" + "ge-0/1/3" + ]; interfaces = { "ge-0/0/12" = AP; "ge-0/0/13" = AP; @@ -45,60 +65,85 @@ in "ge-0/0/42" = { enable = true; - interface-mode = "access"; - vlans = [ "admin-core" ]; + unit."0".family.ethernet-switching = { + enable = true; + interface-mode = "access"; + vlans = [ "admin-core" ]; + }; }; "ge-0/0/43" = AP-staging; "ge-0/0/47" = { # ilo enable = true; - interface-mode = "access"; - vlans = [ "admin-core" ]; + unit."0".family.ethernet-switching = { + enable = true; + interface-mode = "access"; + vlans = [ "admin-core" ]; + }; }; "xe-0/1/0" = { enable = true; - interface-mode = "trunk"; - vlans = [ "all" ]; - dhcp_trusted = true; + unit."0".family.ethernet-switching = { + enable = true; + interface-mode = "trunk"; + vlans = [ "all" ]; + }; }; "xe-0/1/1" = { enable = true; - interface-mode = "trunk"; - vlans = [ - "users" - "admin-ap" - "admin-core" - ]; + unit."0".family.ethernet-switching = { + enable = true; + interface-mode = "trunk"; + vlans = [ + "users" + "admin-ap" + "admin-core" + ]; + }; }; "ge-0/1/3" = { enable = true; - interface-mode = "trunk"; - vlans = [ "uplink-cri" ]; + unit."0".family.ethernet-switching = { + enable = true; + interface-mode = "trunk"; + vlans = [ "uplink-cri" ]; + }; }; "me0" = { enable = true; - management = "192.168.42.6/24"; + unit."0".family.inet = { + enable = true; + address = [ "192.168.42.6/24" ]; + }; + }; + + "irb" = { + enable = true; + unit."0".family.inet6 = { + enable = true; + address = [ "fd26:baf9:d250:8000::1001/64" ]; + }; }; }; }; - netaccess01 = { - deployement.targetHost = "root@192.168.42.6"; + # netaccess01 = { + # deployement.targetHost = "root@192.168.42.6"; - vlans = vlansPlan "fd26:baf9:d250:8000::2001/64"; - interfaces = { - "xe-0/1/0" = { - enable = true; - interface-mode = "trunk"; - vlans = [ "all" ]; - dhcp_trusted = true; - }; + # vlans = vlansPlan "fd26:baf9:d250:8000::2001/64"; + # interfaces = { + # "xe-0/1/0" = { + # enable = true; + # interface-mode = "trunk"; + # vlans = [ "all" ]; + # dhcp_trusted = true; + # }; - "me0" = { - enable = true; - management = "192.168.42.6/24"; - }; - }; - }; + # "me0" = { + # enable = true; + # management = "192.168.42.6/24"; + # }; + # }; + # }; }