aboutsummaryrefslogtreecommitdiffstats
path: root/patches
diff options
context:
space:
mode:
authorAlexandru Avadanii <Alexandru.Avadanii@enea.com>2017-03-21 20:56:37 +0000
committerGerrit Code Review <gerrit@opnfv.org>2017-03-21 20:56:37 +0000
commit0f52c5ccea01691f9138eb540d7554d15070b98d (patch)
treede7f68d1002a25e831bcb4623a18e8a7b87bbddd /patches
parente185a63ff1781afcf819967c53438907ebb0528f (diff)
parentf221993becc58bcba6516e3ca759fa427aaa15e8 (diff)
Merge "fuel-library: Revert cobbler removal" into stable/danube
Diffstat (limited to 'patches')
-rw-r--r--patches/fuel-library/0002-Revert-Fix-deletion-graph-no-cobbler-mode.patch501
-rw-r--r--patches/fuel-library/0003-Revert-Remove-cobbler-and-use-dhcpd-named-and-tftp.patch1621
-rw-r--r--patches/fuel-library/upstream-backports/0002-Increase-reboot-task-timeout.patch31
3 files changed, 2122 insertions, 31 deletions
diff --git a/patches/fuel-library/0002-Revert-Fix-deletion-graph-no-cobbler-mode.patch b/patches/fuel-library/0002-Revert-Fix-deletion-graph-no-cobbler-mode.patch
new file mode 100644
index 00000000..bf180cdb
--- /dev/null
+++ b/patches/fuel-library/0002-Revert-Fix-deletion-graph-no-cobbler-mode.patch
@@ -0,0 +1,501 @@
+From: Alexandru Avadanii <Alexandru.Avadanii@enea.com>
+Date: Tue, 21 Mar 2017 18:01:23 +0100
+Subject: [PATCH 1/2] Revert "Fix deletion graph (no cobbler mode)"
+
+This reverts commit 83ae1d3d617e5043309d72802cd186c22405738a.
+---
+ deployment/puppet/fuel/examples/hiera.pp | 1 +
+ deployment/puppet/fuel/examples/provision.pp | 97 +++++++++++-----------
+ deployment/puppet/provision/manifests/dhcpd.pp | 18 ++--
+ deployment/puppet/provision/manifests/named.pp | 22 ++---
+ deployment/puppet/provision/manifests/params.pp | 34 ++++----
+ deployment/puppet/provision/manifests/tftp.pp | 29 ++++---
+ .../puppet/provision/templates/xinetd.conf.erb | 4 +-
+ graphs/deletion/tasks.yaml | 39 ++++-----
+ graphs/provision/tasks.yaml | 2 +-
+ 9 files changed, 119 insertions(+), 127 deletions(-)
+
+diff --git a/deployment/puppet/fuel/examples/hiera.pp b/deployment/puppet/fuel/examples/hiera.pp
+index 916cd6f..58bae50 100644
+--- a/deployment/puppet/fuel/examples/hiera.pp
++++ b/deployment/puppet/fuel/examples/hiera.pp
+@@ -6,6 +6,7 @@ $data = [
+ 'nodes',
+ 'networks',
+ 'astute',
++ 'known_hosts',
+ 'provision',
+ 'common',
+ ]
+diff --git a/deployment/puppet/fuel/examples/provision.pp b/deployment/puppet/fuel/examples/provision.pp
+index f07f700..9b2aa26 100644
+--- a/deployment/puppet/fuel/examples/provision.pp
++++ b/deployment/puppet/fuel/examples/provision.pp
+@@ -2,20 +2,19 @@ notice('MODULAR: provision.pp')
+
+ Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'}
+
+-$fuel_settings = parseyaml($astute_settings_yaml)
+-
+-$mco_user = $::fuel_settings['mcollective']['user']
+-$mco_pass = $::fuel_settings['mcollective']['password']
+-$dns_address = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
+-$domain_name = $::fuel_settings['DNS_DOMAIN']
+-$dns_search = $::fuel_settings['DNS_SEARCH']
+-$forwarders = split($::fuel_settings['DNS_UPSTREAM'], ',')
+-$start_address = $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_start']
+-$end_address = $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_end']
+-$network_mask = $::fuel_settings['ADMIN_NETWORK']['netmask']
+-$network_address = ipcalc_network_by_address_netmask($start_address, $network_mask)
+-$dhcp_gateway = $::fuel_settings['ADMIN_NETWORK']['dhcp_gateway']
+-
++$fuel_settings = parseyaml($astute_settings_yaml)
++
++$mco_user = $::fuel_settings['mcollective']['user']
++$mco_pass = $::fuel_settings['mcollective']['password']
++$dns_address = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
++$domain_name = $::fuel_settings['DNS_DOMAIN']
++$dns_search = $::fuel_settings['DNS_SEARCH']
++$forwarders = split($::fuel_settings['DNS_UPSTREAM'], ',')
++$start_address = $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_start']
++$end_address = $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_end']
++$network_mask = $::fuel_settings['ADMIN_NETWORK']['netmask']
++$network_address = ipcalc_network_by_address_netmask($start_address, $network_mask)
++$dhcp_gateway = $::fuel_settings['ADMIN_NETWORK']['dhcp_gateway']
+ if $dhcp_gateway {
+ $router = $dhcp_gateway
+ }
+@@ -23,20 +22,22 @@ else {
+ $router = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
+ }
+
+-$next_server = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
+-$nailgun_api_url = "http://${::fuel_settings['ADMIN_NETWORK']['ipaddress']}:8000/api"
+-$ethdevice_timeout = hiera('ethdevice_timeout', '120')
+-$ddns_key = hiera('ddns_key', 'VyCWe0kutrawqQ2WEFKkAw=')
+-$ddns_key_algorithm = hiera('ddns_key_algorithm', 'HMAC-MD5')
+-$ddns_key_name = hiera('ddns_key_name', 'DHCP_UPDATE')
+-$bootstrap_menu_label = hiera('bootstrap_menu_label', 'bootstrap')
++$next_server = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
++
++$nailgun_api_url = "http://${::fuel_settings['ADMIN_NETWORK']['ipaddress']}:8000/api"
++$ethdevice_timeout = hiera('ethdevice_timeout', '120')
++
++$ddns_key = hiera('ddns_key', 'VyCWe0kutrawqQ2WEFKkAw=')
++$ddns_key_algorithm = hiera('ddns_key_algorithm', 'HMAC-MD5')
++$ddns_key_name = hiera('ddns_key_name', 'DHCP_UPDATE')
++
++$bootstrap_menu_label = hiera('bootstrap_menu_label', 'bootstrap')
+ $bootstrap_kernel_path = hiera('bootstrap_kernel_path', '/images/vmlinuz')
+ $bootstrap_initrd_path = hiera('bootstrap_initrd_path', '/images/initrd.img')
+
+-$bootstrap_settings = pick($::fuel_settings['BOOTSTRAP'], {})
+-$bootstrap_path = pick($bootstrap_settings['path'], '/var/www/nailgun/bootstraps/active_bootstrap')
+-$metadata_yaml = file("${bootstrap_path}/metadata.yaml", '/dev/null')
+-
++$bootstrap_settings = pick($::fuel_settings['BOOTSTRAP'], {})
++$bootstrap_path = pick($bootstrap_settings['path'], '/var/www/nailgun/bootstraps/active_bootstrap')
++$metadata_yaml = file("${bootstrap_path}/metadata.yaml", '/dev/null')
+ if empty($metadata_yaml) {
+ $bootstrap_meta = {}
+ } else {
+@@ -50,44 +51,44 @@ $known_hosts = get_merged_network_metadata_from_yamls()
+ $chain32_files = tftp_files("/var/lib/tftpboot/pxelinux.cfg", $known_hosts)
+
+ class { "::provision::dhcpd" :
+- network_address => ipcalc_network_by_address_netmask($start_address, $network_mask),
+- network_mask => $network_mask,
+- broadcast_address => $broadcast_address,
+- start_address => $start_address,
+- end_address => $end_address,
+- router => $router,
+- next_server => $next_server,
+- dns_address => $dns_address,
+- domain_name => $domain_name,
+- ddns_key => $ddns_key,
++ network_address => ipcalc_network_by_address_netmask($start_address, $network_mask),
++ network_mask => $network_mask,
++ broadcast_address => $broadcast_address,
++ start_address => $start_address,
++ end_address => $end_address,
++ router => $router,
++ next_server => $next_server,
++ dns_address => $dns_address,
++ domain_name => $domain_name,
++ ddns_key => $ddns_key,
+ ddns_key_algorithm => $ddns_key_algorithm,
+- ddns_key_name => $ddns_key_name,
+- known_hosts => $known_hosts,
++ ddns_key_name => $ddns_key_name,
++ known_hosts => $known_hosts,
+ }
+
+ class { "::provision::tftp" :
+- bootstrap_menu_label => $bootstrap_menu_label,
+- bootstrap_kernel_path => $bootstrap_kernel_path,
+- bootstrap_initrd_path => $bootstrap_initrd_path,
++ bootstrap_menu_label => $bootstrap_menu_label,
++ bootstrap_kernel_path => $bootstrap_kernel_path,
++ bootstrap_initrd_path => $bootstrap_initrd_path,
+ bootstrap_kernel_params => $bootstrap_kernel_params,
+- chain32_files => $chain32_files,
++ chain32_files => $chain32_files,
+ } ->
+
+-file { "/var/lib/tftpboot/${bootstrap_kernel_path}" :
++file { "/var/lib/tftpboot${bootstrap_kernel_path}" :
+ source => "${bootstrap_path}/vmlinuz",
+ } ->
+
+-file { "/var/lib/tftpboot/${bootstrap_initrd_path}" :
++file { "/var/lib/tftpboot${bootstrap_initrd_path}" :
+ source => "${bootstrap_path}/initrd.img"
+ }
+
+ class { "::provision::named" :
+- domain_name => $domain_name,
+- dns_address => $dns_address,
+- forwarders => $forwarders,
+- ddns_key => $ddns_key,
++ domain_name => $domain_name,
++ dns_address => $dns_address,
++ forwarders => $forwarders,
++ ddns_key => $ddns_key,
+ ddns_key_algorithm => $ddns_key_algorithm,
+- ddns_key_name => $ddns_key_name,
++ ddns_key_name => $ddns_key_name,
+ } ->
+
+ file { '/etc/resolv.conf':
+diff --git a/deployment/puppet/provision/manifests/dhcpd.pp b/deployment/puppet/provision/manifests/dhcpd.pp
+index f0e970a..6837532 100644
+--- a/deployment/puppet/provision/manifests/dhcpd.pp
++++ b/deployment/puppet/provision/manifests/dhcpd.pp
+@@ -14,10 +14,9 @@ class provision::dhcpd (
+ $known_hosts = [],
+ ) inherits provision::params {
+
+- $package_name = $::provision::params::dhcpd_package
+- $service_name = $::provision::params::dhcpd_service
+-
+- package { $package_name : }
++ package { "dhcpd" :
++ name => $::provision::params::dhcpd_package,
++ }
+
+ file { $::provision::params::dhcpd_conf :
+ ensure => present,
+@@ -25,8 +24,8 @@ class provision::dhcpd (
+ owner => 'dhcpd',
+ group => 'dhcpd',
+ mode => '0640',
+- require => Package[$package_name],
+- notify => Service[$service_name],
++ require => Package["dhcpd"],
++ notify => Service["dhcpd"],
+ }
+
+ file { $::provision::params::dhcpd_conf_d :
+@@ -34,7 +33,7 @@ class provision::dhcpd (
+ owner => 'root',
+ group => 'root',
+ mode => '0755',
+- require => Package[$package_name],
++ require => Package["dhcpd"],
+ }
+
+ # It is just a file that could be modified by other modules
+@@ -43,12 +42,13 @@ class provision::dhcpd (
+ require => File[$::provision::params::dhcpd_conf_d],
+ }
+
+- service { $service_name :
++ service { "dhcpd" :
++ name => $::provision::params::dhcpd_service,
+ ensure => running,
+ enable => true,
+ hasrestart => false,
+ hasstatus => false,
+- require => Package[$package_name],
++ require => Package["dhcpd"],
+ }
+
+ }
+diff --git a/deployment/puppet/provision/manifests/named.pp b/deployment/puppet/provision/manifests/named.pp
+index 6609fee..ee940c9 100644
+--- a/deployment/puppet/provision/manifests/named.pp
++++ b/deployment/puppet/provision/manifests/named.pp
+@@ -7,17 +7,16 @@ class provision::named (
+ $ddns_key_name = $::provision::params::ddns_key_name,
+ ) inherits provision::params {
+
+- $package_name = $::provision::params::named_package
+- $service_name = $::provision::params::named_service
+-
+- package { $package_name : }
++ package { "named" :
++ name => $::provision::params::named_package,
++ }
+
+ file { "/var/named" :
+ ensure => directory,
+ owner => 'named',
+ group => 'named',
+ mode => '0750',
+- require => Package[$package_name],
++ require => Package["named"],
+ }
+
+ file { $::provision::params::named_conf :
+@@ -26,8 +25,8 @@ class provision::named (
+ owner => 'named',
+ group => 'named',
+ mode => '0640',
+- require => Package[$package_name],
+- notify => Service[$service_name],
++ require => Package["named"],
++ notify => Service["named"],
+ }
+
+ file { "/var/named/${domain_name}" :
+@@ -36,16 +35,17 @@ class provision::named (
+ owner => 'named',
+ group => 'named',
+ mode => '0644',
+- require => Package[$package_name],
+- notify => Service[$service_name],
++ require => Package["named"],
++ notify => Service["named"],
+ }
+
+- service { $service_name :
++ service { "named" :
++ name => $::provision::params::named_service,
+ ensure => running,
+ enable => true,
+ hasrestart => false,
+ hasstatus => false,
+- require => Package[$package_name],
++ require => Package["named"],
+ }
+
+ }
+diff --git a/deployment/puppet/provision/manifests/params.pp b/deployment/puppet/provision/manifests/params.pp
+index 1508edd..2bcae12 100644
+--- a/deployment/puppet/provision/manifests/params.pp
++++ b/deployment/puppet/provision/manifests/params.pp
+@@ -14,23 +14,23 @@ class provision::params {
+ fail("Unsupported osfamily ${::osfamily}")
+ }
+ }
+- $network_address = "10.20.0.0"
+- $network_mask = "255.255.255.0"
+- $broadcast_address = "10.20.0.255"
+- $start_address = "10.20.0.3"
+- $end_address = "10.20.0.254"
+- $router = "10.20.0.1"
+- $next_server = "10.20.0.2"
+- $dns_address = "10.20.0.2"
+- $forwarders = ["8.8.8.8", "8.8.4.4"]
+- $domain_name = "domain.tld"
+- $ddns_key = "VyCWe0kutrawqQ2WEFKkAw=="
+- $ddns_key_algorithm = "HMAC-MD5"
+- $ddns_key_name = "DHCP_UPDATE"
+- $bootstrap_kernel_path = "/images/ubuntu_bootstrap/vmlinuz"
+- $bootstrap_initrd_path = "/images/ubuntu_bootstrap/initrd.img"
++ $network_address = "10.20.0.0"
++ $network_mask = "255.255.255.0"
++ $broadcast_address = "10.20.0.255"
++ $start_address = "10.20.0.3"
++ $end_address = "10.20.0.254"
++ $router = "10.20.0.1"
++ $next_server = "10.20.0.2"
++ $dns_address = "10.20.0.2"
++ $forwarders = ["8.8.8.8", "8.8.4.4"]
++ $domain_name = "domain.tld"
++ $ddns_key = "VyCWe0kutrawqQ2WEFKkAw=="
++ $ddns_key_algorithm = "HMAC-MD5"
++ $ddns_key_name = "DHCP_UPDATE"
++
++ $bootstrap_kernel_path = "/images/ubuntu_bootstrap/vmlinuz"
++ $bootstrap_initrd_path = "/images/ubuntu_bootstrap/initrd.img"
+ $bootstrap_kernel_params = "ksdevice=bootif lang= console=ttyS0,9600 console=tty0 toram locale=en_US text boot=live biosdevname=0 components ip=frommedia ethdevice-timeout=120 net.ifnames=1 panic=60"
+- $bootstrap_menu_label = "ubuntu_bootstrap"
+- $tftp_root = "/var/lib/tftpboot"
++ $bootstrap_menu_label = "ubuntu_bootstrap"
+
+ }
+diff --git a/deployment/puppet/provision/manifests/tftp.pp b/deployment/puppet/provision/manifests/tftp.pp
+index 39c7633..f05bd16 100644
+--- a/deployment/puppet/provision/manifests/tftp.pp
++++ b/deployment/puppet/provision/manifests/tftp.pp
+@@ -1,10 +1,9 @@
+ class provision::tftp (
+ $bootstrap_kernel_params = $::provision::params::bootstrap_kernel_params,
+- $bootstrap_kernel_path = $::provision::params::bootstrap_kernel_path,
+- $bootstrap_initrd_path = $::provision::params::bootstrap_initrd_path,
+- $bootstrap_menu_label = $::provision::params::bootstrap_menu_label,
+- $tftp_root = $::provision::params::tftp_root,
+- $chain32_files = [],
++ $bootstrap_kernel_path = $::provision::params::bootstrap_kernel_path,
++ $bootstrap_initrd_path = $::provision::params::bootstrap_initrd_path,
++ $bootstrap_menu_label = $::provision::params::bootstrap_menu_label,
++ $chain32_files = [],
+ ) inherits provision::params {
+
+ Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'}
+@@ -46,7 +45,7 @@ class provision::tftp (
+
+ ensure_packages($tftp_packages)
+
+- file { ["${tftp_root}/images", "${tftp_root}/pxelinux.cfg"] :
++ file { ["/var/lib/tftpboot/images", "/var/lib/tftpboot/pxelinux.cfg"] :
+ ensure => directory,
+ owner => 'root',
+ group => 'root',
+@@ -54,35 +53,35 @@ class provision::tftp (
+ require => Package[$tftp_packages],
+ }
+
+- file { "${tftp_root}/pxelinux.cfg/default" :
++ file { "/var/lib/tftpboot/pxelinux.cfg/default" :
+ ensure => present,
+ content => template("provision/tftp.default.erb"),
+ owner => 'root',
+ group => 'root',
+ mode => '0644',
+- require => File["${tftp_root}/pxelinux.cfg"],
++ require => File["/var/lib/tftpboot/pxelinux.cfg"],
+ }
+
+- file { "${tftp_root}/chain.c32":
++ file { '/var/lib/tftpboot/chain.c32':
+ source => '/usr/share/syslinux/chain.c32',
+ require => Package[$tftp_packages],
+ }
+
+- file { "${tftp_root}/pxelinux.0":
++ file { '/var/lib/tftpboot/pxelinux.0':
+ source => '/usr/share/syslinux/pxelinux.0',
+ require => Package[$tftp_packages],
+ }
+
+- file { "${tftp_root}/menu.c32":
++ file { '/var/lib/tftpboot/menu.c32':
+ source => '/usr/share/syslinux/menu.c32',
+ require => Package[$tftp_packages],
+ }
+
+ # TODO Create custom type that will remove all 01-* files that
+ # are not in the $chain32_files list
+- exec { "remove ${tftp_root}/pxelinux.cfg/01-* files" :
+- command => "find ${tftp_root}/pxelinux.cfg -type f -name '01-*' -delete",
+- require => File["${tftp_root}/pxelinux.cfg"],
++ exec { 'remove /var/lib/tftpboot/pxelinux.cfg/01-* files' :
++ command => "find /var/lib/tftpboot/pxelinux.cfg -type f -name '01-*' -delete",
++ require => File["/var/lib/tftpboot/pxelinux.cfg"],
+ } ->
+
+ file { $chain32_files :
+@@ -91,6 +90,6 @@ class provision::tftp (
+ owner => 'root',
+ group => 'root',
+ mode => '0644',
+- require => File["${tftp_root}/pxelinux.cfg"],
++ require => File["/var/lib/tftpboot/pxelinux.cfg"],
+ }
+ }
+diff --git a/deployment/puppet/provision/templates/xinetd.conf.erb b/deployment/puppet/provision/templates/xinetd.conf.erb
+index 1ff50ba..0a90f33 100644
+--- a/deployment/puppet/provision/templates/xinetd.conf.erb
++++ b/deployment/puppet/provision/templates/xinetd.conf.erb
+@@ -1,10 +1,10 @@
+ defaults
+ {
+- log_type = SYSLOG daemon info
++ log_type = SYSLOG daemon info
+ log_on_failure = HOST
+ log_on_success = PID HOST DURATION EXIT
+
+- cps = 50 10
++ cps = 50 10
+ instances = 50
+ per_source = 10
+
+diff --git a/graphs/deletion/tasks.yaml b/graphs/deletion/tasks.yaml
+index 2fd0188..a2c678c 100644
+--- a/graphs/deletion/tasks.yaml
++++ b/graphs/deletion/tasks.yaml
+@@ -7,44 +7,35 @@
+ type: stage
+ requires: [deletion_start]
+
+-- id: upload_provision_info_master
+- type: upload_file
++- id: cobbler_enable_netboot
++ type: master_shell
+ version: 2.1.0
+- role: ['master']
++ role: ['/.*/']
+ requires: [deletion_start]
+- required_for: [reconfigure_dhcpd]
++ required_for: [move_to_bootstrap]
+ parameters:
+- path: /var/lib/fuel/configs/{CLUSTER_ID}/provision.yaml
++ cmd:
++ yaql_exp: 'concat("sh /etc/puppet/modules/osnailyfacter/modular/provision/netboot enable ", $.provision.name)'
+ timeout: 180
+- data:
+- #TODO: Replace dict($.items) to $ when LP1666913 is fixed
+- yaql_exp: "($.provision.set('packages', $.provision.packages) + $.repo_setup + dict('output' => '/var/www/nailgun/targetimages') + dict($.items())).toYaml()"
+
+-- id: reconfigure_dhcpd
+- type: puppet
+- version: 2.1.0
+- role: ['master']
+- requires: [upload_provision_info_master]
+- required_for: [node_reboot]
+- parameters:
+- puppet_manifest: /etc/puppet/modules/fuel/examples/provision.pp
+- puppet_modules: /etc/puppet/modules
+- timeout: 3600
+-
+-- id: node_reboot
+- type: reboot
++- id: move_to_bootstrap
++ type: move_to_bootstrap
+ version: 2.1.0
+ role: ['/.*/']
+- requires: [reconfigure_dhcpd]
++ requires: [cobbler_enable_netboot]
+ required_for: [node_erase]
+ parameters:
+- timeout: 300
++ slave_name:
++ yaql_exp: '$.provision.name'
++ provisioning_info:
++ yaql_exp: '$.provision'
++ timeout: 180
+
+ - id: node_erase
+ type: erase_node
+ version: 2.1.0
+ role: ['/.*/']
+- requires: [node_reboot]
++ requires: [move_to_bootstrap]
+ required_for: [deletion_end]
+ parameters:
+ timeout: 180
+diff --git a/graphs/provision/tasks.yaml b/graphs/provision/tasks.yaml
+index 1494176..3a21c87 100644
+--- a/graphs/provision/tasks.yaml
++++ b/graphs/provision/tasks.yaml
+@@ -85,7 +85,7 @@
+ type: reboot
+ version: 2.1.0
+ role: ['/.*/']
+- requires: [system_provision]
++ requires: [cobbler_disable_netboot]
+ required_for: [set_status_provisioned]
+ parameters:
+ timeout: 900
diff --git a/patches/fuel-library/0003-Revert-Remove-cobbler-and-use-dhcpd-named-and-tftp.patch b/patches/fuel-library/0003-Revert-Remove-cobbler-and-use-dhcpd-named-and-tftp.patch
new file mode 100644
index 00000000..b2493e12
--- /dev/null
+++ b/patches/fuel-library/0003-Revert-Remove-cobbler-and-use-dhcpd-named-and-tftp.patch
@@ -0,0 +1,1621 @@
+From: Alexandru Avadanii <Alexandru.Avadanii@enea.com>
+Date: Tue, 21 Mar 2017 18:01:31 +0100
+Subject: [PATCH 2/2] Revert "Remove cobbler and use dhcpd named and tftp"
+
+This reverts commit 0b5ab4ff80414adad996012b9152de0719888274.
+---
+ deployment/puppet/fuel/examples/cobbler.pp | 79 ++++++++++++-
+ deployment/puppet/fuel/examples/deploy.sh | 2 +-
+ deployment/puppet/fuel/examples/dhcp-ranges.pp | 26 +++--
+ deployment/puppet/fuel/examples/hiera.pp | 9 --
+ deployment/puppet/fuel/examples/host.pp | 2 +-
+ deployment/puppet/fuel/examples/provision.pp | 99 ----------------
+ .../parser/functions/create_dnsmasq_dhcp_ranges.rb | 47 ++++++++
+ .../lib/puppet/parser/functions/get_dhcp_ranges.rb | 46 --------
+ .../get_merged_network_metadata_from_yamls.rb | 20 ----
+ deployment/puppet/fuel/manifests/cobbler.pp | 130 +++++++++++++++++++++
+ .../puppet/fuel/manifests/dnsmasq/dhcp_range.pp | 29 +++++
+ deployment/puppet/fuel/manifests/iptables.pp | 3 +-
+ .../functions/create_dnsmasq_dhcp_ranges_spec.rb | 70 +++++++++++
+ deployment/puppet/fuel/templates/dhclient.conf.erb | 2 +-
+ deployment/puppet/fuel/templates/dhcpd_ranges.erb | 21 ----
+ .../puppet/fuel/templates/dnsmasq.dhcp-range.erb | 7 ++
+ deployment/puppet/fuel/templates/provision.yaml | 8 --
+ deployment/puppet/fuel/templates/resolv.conf.erb | 4 +-
+ .../manifests/provision/build_image.pp | 22 ++--
+ .../lib/puppet/parser/functions/tftp_files.rb | 22 ----
+ deployment/puppet/provision/manifests/dhcpd.pp | 54 ---------
+ deployment/puppet/provision/manifests/iptables.pp | 28 -----
+ deployment/puppet/provision/manifests/named.pp | 51 --------
+ deployment/puppet/provision/manifests/params.pp | 36 ------
+ deployment/puppet/provision/manifests/tftp.pp | 95 ---------------
+ .../puppet/provision/templates/dhcpd.conf.erb | 69 -----------
+ .../puppet/provision/templates/named.conf.erb | 32 -----
+ .../puppet/provision/templates/tftp.chain32.erb | 8 --
+ .../puppet/provision/templates/tftp.default.erb | 19 ---
+ .../puppet/provision/templates/tftp.xinetd.erb | 13 ---
+ .../puppet/provision/templates/xinetd.conf.erb | 17 ---
+ deployment/puppet/provision/templates/zone.erb | 11 --
+ graphs/provision/tasks.yaml | 43 ++++---
+ tests/noop/spec/hosts/master/cobbler_spec.rb | 79 +++++++++++++
+ tests/noop/spec/hosts/master/dhcp-ranges_spec.rb | 17 +++
+ tests/noop/spec/hosts/master/host_spec.rb | 2 +
+ 36 files changed, 527 insertions(+), 695 deletions(-)
+ mode change 120000 => 100644 deployment/puppet/fuel/examples/cobbler.pp
+ delete mode 100644 deployment/puppet/fuel/examples/provision.pp
+ create mode 100644 deployment/puppet/fuel/lib/puppet/parser/functions/create_dnsmasq_dhcp_ranges.rb
+ delete mode 100644 deployment/puppet/fuel/lib/puppet/parser/functions/get_dhcp_ranges.rb
+ delete mode 100644 deployment/puppet/fuel/lib/puppet/parser/functions/get_merged_network_metadata_from_yamls.rb
+ create mode 100644 deployment/puppet/fuel/manifests/cobbler.pp
+ create mode 100644 deployment/puppet/fuel/manifests/dnsmasq/dhcp_range.pp
+ create mode 100644 deployment/puppet/fuel/spec/functions/create_dnsmasq_dhcp_ranges_spec.rb
+ delete mode 100644 deployment/puppet/fuel/templates/dhcpd_ranges.erb
+ create mode 100644 deployment/puppet/fuel/templates/dnsmasq.dhcp-range.erb
+ delete mode 100644 deployment/puppet/fuel/templates/provision.yaml
+ delete mode 100644 deployment/puppet/provision/lib/puppet/parser/functions/tftp_files.rb
+ delete mode 100644 deployment/puppet/provision/manifests/dhcpd.pp
+ delete mode 100644 deployment/puppet/provision/manifests/iptables.pp
+ delete mode 100644 deployment/puppet/provision/manifests/named.pp
+ delete mode 100644 deployment/puppet/provision/manifests/params.pp
+ delete mode 100644 deployment/puppet/provision/manifests/tftp.pp
+ delete mode 100644 deployment/puppet/provision/templates/dhcpd.conf.erb
+ delete mode 100644 deployment/puppet/provision/templates/named.conf.erb
+ delete mode 100644 deployment/puppet/provision/templates/tftp.chain32.erb
+ delete mode 100644 deployment/puppet/provision/templates/tftp.default.erb
+ delete mode 100644 deployment/puppet/provision/templates/tftp.xinetd.erb
+ delete mode 100644 deployment/puppet/provision/templates/xinetd.conf.erb
+ delete mode 100644 deployment/puppet/provision/templates/zone.erb
+ create mode 100644 tests/noop/spec/hosts/master/cobbler_spec.rb
+ create mode 100644 tests/noop/spec/hosts/master/dhcp-ranges_spec.rb
+
+diff --git a/deployment/puppet/fuel/examples/cobbler.pp b/deployment/puppet/fuel/examples/cobbler.pp
+deleted file mode 120000
+index c48bab0..0000000
+--- a/deployment/puppet/fuel/examples/cobbler.pp
++++ /dev/null
+@@ -1 +0,0 @@
+-provision.pp
+\ No newline at end of file
+diff --git a/deployment/puppet/fuel/examples/cobbler.pp b/deployment/puppet/fuel/examples/cobbler.pp
+new file mode 100644
+index 0000000..d409689
+--- /dev/null
++++ b/deployment/puppet/fuel/examples/cobbler.pp
+@@ -0,0 +1,78 @@
++notice('MODULAR: cobbler.pp')
++
++Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'}
++
++$fuel_settings = parseyaml($astute_settings_yaml)
++$admin_network = $::fuel_settings['ADMIN_NETWORK']
++$nailgun_api_url = "http://${::fuel_settings['ADMIN_NETWORK']['ipaddress']}:8000/api"
++$bootstrap_settings = pick($::fuel_settings['BOOTSTRAP'], {})
++$bootstrap_path = pick($bootstrap_settings['path'], '/var/www/nailgun/bootstraps/active_bootstrap')
++$bootstrap_ethdevice_timeout = pick($bootstrap_settings['ethdevice_timeout'], '120')
++$dhcp_gw = $::fuel_settings['ADMIN_NETWORK']['dhcp_gateway']
++$dns_domain = $::fuel_settings['DNS_DOMAIN']
++$dns_search = $::fuel_settings['DNS_SEARCH']
++$dns_upstream = split($::fuel_settings['DNS_UPSTREAM'], ',')
++$cobbler_host = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
++
++# TODO(mmalchuk): the right way with updated loadyaml function
++# $bootstrap_meta = loadyaml("${bootstrap_path}/metadata.yaml", {})
++# and remove if else block
++$metadata_yaml = file("${bootstrap_path}/metadata.yaml", '/dev/null')
++if empty($metadata_yaml) {
++ $bootstrap_meta = {}
++} else {
++ $bootstrap_meta = parseyaml($metadata_yaml)
++}
++
++if $dhcp_gw {
++ $dhcp_gateway = $dhcp_gw
++}
++else {
++ $dhcp_gateway = $cobbler_host
++}
++
++class { '::fuel::cobbler':
++ cobbler_user => $::fuel_settings['cobbler']['user'],
++ cobbler_password => $::fuel_settings['cobbler']['password'],
++ bootstrap_path => $bootstrap_path,
++ bootstrap_meta => $bootstrap_meta,
++ server => $::fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ name_server => $::fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ next_server => $::fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ mco_user => $::fuel_settings['mcollective']['user'],
++ mco_pass => $::fuel_settings['mcollective']['password'],
++ dns_upstream => $dns_upstream,
++ dns_domain => $dns_domain,
++ dns_search => $dns_search,
++ dhcp_ipaddress => $::fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ nailgun_api_url => $nailgun_api_url,
++ bootstrap_ethdevice_timeout => $bootstrap_ethdevice_timeout,
++} ->
++
++file { '/etc/resolv.conf':
++ content => template('fuel/resolv.conf.erb'),
++ owner => 'root',
++ group => 'root',
++ mode => '0644',
++}
++
++Fuel::Systemd {
++ start => true,
++ template_path => 'fuel/systemd/restart_template.erb',
++ config_name => 'restart.conf',
++ service_manage => false,
++}
++
++fuel::systemd { ['httpd', 'cobblerd', 'xinetd'] :}
++
++fuel::systemd { 'dnsmasq': template_path => 'fuel/systemd/dnsmasq_template.erb' }
++
++fuel::dnsmasq::dhcp_range {'default':
++ dhcp_start_address => $admin_network['dhcp_pool_start'],
++ dhcp_end_address => $admin_network['dhcp_pool_end'],
++ dhcp_netmask => $admin_network['netmask'],
++ dhcp_gateway => $admin_network['dhcp_gateway'],
++ next_server => $admin_network['ipaddress'],
++ listen_address => $admin_network['ipaddress'],
++ notify => Service['dnsmasq'],
++}
+diff --git a/deployment/puppet/fuel/examples/deploy.sh b/deployment/puppet/fuel/examples/deploy.sh
+index c1b7494..afff4af 100755
+--- a/deployment/puppet/fuel/examples/deploy.sh
++++ b/deployment/puppet/fuel/examples/deploy.sh
+@@ -17,7 +17,7 @@
+ TASKS="
+ hiera
+ host
+-provision
++cobbler
+ postgresql
+ rabbitmq
+ mcollective
+diff --git a/deployment/puppet/fuel/examples/dhcp-ranges.pp b/deployment/puppet/fuel/examples/dhcp-ranges.pp
+index 1209207..7420e1b 100644
+--- a/deployment/puppet/fuel/examples/dhcp-ranges.pp
++++ b/deployment/puppet/fuel/examples/dhcp-ranges.pp
+@@ -1,12 +1,20 @@
+ notice('MODULAR: dhcp-ranges.pp')
+
+-$admin_network = hiera('ADMIN_NETWORK')
+-$next_server = $admin_network['ipaddress']
+-$domain_name = hiera('DNS_DOMAIN')
+-$dns_address = $admin_network['ipaddress']
+-$dhcp_ranges = get_dhcp_ranges(hiera('admin_networks', [{}]))
+-
+-file { $::provision::params::dhcpd_conf_extra :
+- ensure => present,
+- content => template('fuel/dhcpd_ranges.erb'),
++$admin_networks = hiera('admin_networks', [{}])
++$admin_network = hiera('ADMIN_NETWORK')
++
++Fuel::Dnsmasq::Dhcp_range <||> {
++ next_server => $admin_network['ipaddress'],
++}
++
++# Ensure dir with purge and recurse to remove configs for
++# non-existing (removed) nodegroups and ip ranges
++file { '/etc/dnsmasq.d':
++ ensure => 'directory',
++ recurse => true,
++ purge => true,
+ }
++
++# Create admin networks dhcp-range files except for 'default' nodegroup
++# by creating Fuel::Dnsmasq::Dhcp_range puppet resources
++create_dnsmasq_dhcp_ranges($admin_networks)
+diff --git a/deployment/puppet/fuel/examples/hiera.pp b/deployment/puppet/fuel/examples/hiera.pp
+index 58bae50..ca228ae 100644
+--- a/deployment/puppet/fuel/examples/hiera.pp
++++ b/deployment/puppet/fuel/examples/hiera.pp
+@@ -6,15 +6,12 @@ $data = [
+ 'nodes',
+ 'networks',
+ 'astute',
+- 'known_hosts',
+- 'provision',
+ 'common',
+ ]
+ $astute_data_file = '/etc/fuel/astute.yaml'
+ $hiera_main_config = '/etc/hiera.yaml'
+ $hiera_puppet_config = '/etc/puppet/hiera.yaml'
+ $hiera_data_file = "${data_dir}/astute.yaml"
+-$hiera_data_provision = "${data_dir}/provision.yaml"
+
+ File {
+ owner => 'root',
+@@ -43,12 +40,6 @@ file { 'hiera_data_astute' :
+ target => $astute_data_file,
+ }
+
+-file { 'hiera_data_provision' :
+- ensure => present,
+- path => $hiera_data_provision,
+- content => template('fuel/provision.yaml'),
+-}
+-
+ file { 'hiera_puppet_config' :
+ ensure => 'symlink',
+ path => $hiera_puppet_config,
+diff --git a/deployment/puppet/fuel/examples/host.pp b/deployment/puppet/fuel/examples/host.pp
+index f94d642..f5cfac4 100644
+--- a/deployment/puppet/fuel/examples/host.pp
++++ b/deployment/puppet/fuel/examples/host.pp
+@@ -9,7 +9,7 @@ $ntp_servers = delete(delete_undef_values([$::fuel_settings['NTP1'],
+ $::fuel_settings['NTP2'], $::fuel_settings['NTP3']]), '')
+
+ # Vars for File['/etc/dhcp/dhclient.conf']
+-$dns_address = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
++$cobbler_host = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
+
+ # Vars for File['/etc/fuel-utils/config']
+ $admin_ip = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
+diff --git a/deployment/puppet/fuel/examples/provision.pp b/deployment/puppet/fuel/examples/provision.pp
+deleted file mode 100644
+index 9b2aa26..0000000
+--- a/deployment/puppet/fuel/examples/provision.pp
++++ /dev/null
+@@ -1,99 +0,0 @@
+-notice('MODULAR: provision.pp')
+-
+-Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'}
+-
+-$fuel_settings = parseyaml($astute_settings_yaml)
+-
+-$mco_user = $::fuel_settings['mcollective']['user']
+-$mco_pass = $::fuel_settings['mcollective']['password']
+-$dns_address = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
+-$domain_name = $::fuel_settings['DNS_DOMAIN']
+-$dns_search = $::fuel_settings['DNS_SEARCH']
+-$forwarders = split($::fuel_settings['DNS_UPSTREAM'], ',')
+-$start_address = $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_start']
+-$end_address = $::fuel_settings['ADMIN_NETWORK']['dhcp_pool_end']
+-$network_mask = $::fuel_settings['ADMIN_NETWORK']['netmask']
+-$network_address = ipcalc_network_by_address_netmask($start_address, $network_mask)
+-$dhcp_gateway = $::fuel_settings['ADMIN_NETWORK']['dhcp_gateway']
+-if $dhcp_gateway {
+- $router = $dhcp_gateway
+-}
+-else {
+- $router = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
+-}
+-
+-$next_server = $::fuel_settings['ADMIN_NETWORK']['ipaddress']
+-
+-$nailgun_api_url = "http://${::fuel_settings['ADMIN_NETWORK']['ipaddress']}:8000/api"
+-$ethdevice_timeout = hiera('ethdevice_timeout', '120')
+-
+-$ddns_key = hiera('ddns_key', 'VyCWe0kutrawqQ2WEFKkAw=')
+-$ddns_key_algorithm = hiera('ddns_key_algorithm', 'HMAC-MD5')
+-$ddns_key_name = hiera('ddns_key_name', 'DHCP_UPDATE')
+-
+-$bootstrap_menu_label = hiera('bootstrap_menu_label', 'bootstrap')
+-$bootstrap_kernel_path = hiera('bootstrap_kernel_path', '/images/vmlinuz')
+-$bootstrap_initrd_path = hiera('bootstrap_initrd_path', '/images/initrd.img')
+-
+-$bootstrap_settings = pick($::fuel_settings['BOOTSTRAP'], {})
+-$bootstrap_path = pick($bootstrap_settings['path'], '/var/www/nailgun/bootstraps/active_bootstrap')
+-$metadata_yaml = file("${bootstrap_path}/metadata.yaml", '/dev/null')
+-if empty($metadata_yaml) {
+- $bootstrap_meta = {}
+-} else {
+- $bootstrap_meta = parseyaml($metadata_yaml)
+-}
+-
+-$bootstrap_kernel_params = extend_kopts($bootstrap_meta['extend_kopts'], "console=ttyS0,9600 console=tty0 panic=60 ethdevice-timeout=${ethdevice_timeout} boot=live toram components fetch=http://${next_server}:8080/bootstraps/active_bootstrap/root.squashfs biosdevname=0 url=${nailgun_api_url} mco_user=${mco_user} mco_pass=${mco_pass} ip=frommedia")
+-
+-
+-$known_hosts = get_merged_network_metadata_from_yamls()
+-$chain32_files = tftp_files("/var/lib/tftpboot/pxelinux.cfg", $known_hosts)
+-
+-class { "::provision::dhcpd" :
+- network_address => ipcalc_network_by_address_netmask($start_address, $network_mask),
+- network_mask => $network_mask,
+- broadcast_address => $broadcast_address,
+- start_address => $start_address,
+- end_address => $end_address,
+- router => $router,
+- next_server => $next_server,
+- dns_address => $dns_address,
+- domain_name => $domain_name,
+- ddns_key => $ddns_key,
+- ddns_key_algorithm => $ddns_key_algorithm,
+- ddns_key_name => $ddns_key_name,
+- known_hosts => $known_hosts,
+-}
+-
+-class { "::provision::tftp" :
+- bootstrap_menu_label => $bootstrap_menu_label,
+- bootstrap_kernel_path => $bootstrap_kernel_path,
+- bootstrap_initrd_path => $bootstrap_initrd_path,
+- bootstrap_kernel_params => $bootstrap_kernel_params,
+- chain32_files => $chain32_files,
+-} ->
+-
+-file { "/var/lib/tftpboot${bootstrap_kernel_path}" :
+- source => "${bootstrap_path}/vmlinuz",
+-} ->
+-
+-file { "/var/lib/tftpboot${bootstrap_initrd_path}" :
+- source => "${bootstrap_path}/initrd.img"
+-}
+-
+-class { "::provision::named" :
+- domain_name => $domain_name,
+- dns_address => $dns_address,
+- forwarders => $forwarders,
+- ddns_key => $ddns_key,
+- ddns_key_algorithm => $ddns_key_algorithm,
+- ddns_key_name => $ddns_key_name,
+-} ->
+-
+-file { '/etc/resolv.conf':
+- content => template('fuel/resolv.conf.erb'),
+- owner => 'root',
+- group => 'root',
+- mode => '0644',
+-}
+diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/create_dnsmasq_dhcp_ranges.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/create_dnsmasq_dhcp_ranges.rb
+new file mode 100644
+index 0000000..a43ba51
+--- /dev/null
++++ b/deployment/puppet/fuel/lib/puppet/parser/functions/create_dnsmasq_dhcp_ranges.rb
+@@ -0,0 +1,47 @@
++require 'ipaddr'
++require 'zlib'
++
++module Puppet::Parser::Functions
++ newfunction(:create_dnsmasq_dhcp_ranges, :doc => <<-EOS
++Creates fuel::dnsmasq::dhcp_range puppet resources from list of admin networks.
++ EOS
++) do |args|
++ admin_nets = args[0]
++ unless admin_nets.is_a?(Array) and admin_nets[0].is_a?(Hash)
++ raise(Puppet::ParseError, 'Should pass list of hashes as a parameter')
++ end
++ admin_nets.each do |net|
++ next unless net['ip_ranges'].is_a? Array
++ net['ip_ranges'].each do |ip_range|
++ # loop through local facts to pull which interface has an IP in the
++ # dhcp range so we can properly listen on the interface for dhcp
++ # messages
++ cidr = IPAddr.new(net['cidr'])
++ listen_address = []
++ interfaces = lookupvar('interfaces')
++ if ! interfaces.nil?
++ interfaces.split(',').each do |interface|
++ local_address = lookupvar("ipaddress_#{interface}")
++ listen_address.push(local_address) if cidr.include?(local_address)
++ end
++ end
++ netmask = IPAddr.new('255.255.255.255').mask(net['cidr'].split('/')[1]).to_s
++ print_range = ip_range.join('_')
++ resource_name = sprintf("range_%08x", Zlib::crc32("#{print_range}_#{net['cidr']}").to_i)
++ range_comment = "# Environment: #{net['cluster_name']}\n# Nodegroup: #{net['node_group_name']}\n# IP range: #{ip_range}"
++ dhcp_range_resource = {
++ resource_name => {
++ 'file_header' => "# Generated automatically by puppet\n#{range_comment}",
++ 'listen_address' => listen_address.join(','),
++ 'dhcp_start_address' => ip_range[0],
++ 'dhcp_end_address' => ip_range[1],
++ 'dhcp_netmask' => netmask,
++ 'dhcp_gateway' => net['gateway'],
++ }
++ }
++ debug("Trying to create fuel::dnsmasq::dhcp_range resource: #{dhcp_range_resource.inspect}")
++ function_create_resources(['fuel::dnsmasq::dhcp_range', dhcp_range_resource])
++ end
++ end
++ end
++end
+diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/get_dhcp_ranges.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/get_dhcp_ranges.rb
+deleted file mode 100644
+index 574ae78..0000000
+--- a/deployment/puppet/fuel/lib/puppet/parser/functions/get_dhcp_ranges.rb
++++ /dev/null
+@@ -1,46 +0,0 @@
+-require 'ipaddr'
+-
+-module Puppet::Parser::Functions
+- newfunction(:get_dhcp_ranges, :doc => <<-EOS
+-Returns a list of dhcp ranges from a list of admin networks.
+- EOS
+-) do |args|
+- admin_nets = args[0]
+- unless admin_nets.is_a?(Array) and admin_nets[0].is_a?(Hash)
+- raise(Puppet::ParseError, 'Should pass list of hashes as a parameter')
+- end
+- dhcp_ranges = []
+- admin_nets.each do |net|
+- next unless net['ip_ranges'].is_a? Array
+- net['ip_ranges'].each do |ip_range|
+- # loop through local facts to pull which interface has an IP in the
+- # dhcp range so we can properly listen on the interface for dhcp
+- # messages
+- cidr = IPAddr.new(net['cidr'])
+- listen_address = []
+- interfaces = lookupvar('interfaces')
+- if ! interfaces.nil?
+- interfaces.split(',').each do |interface|
+- local_address = lookupvar("ipaddress_#{interface}")
+- listen_address.push(local_address) if cidr.include?(local_address)
+- end
+- end
+- netmask = IPAddr.new('255.255.255.255').mask(net['cidr'].split('/')[1]).to_s
+- range_comment = "# Environment: #{net['cluster_name']}\n# Nodegroup: #{net['node_group_name']}\n# IP range: #{ip_range}"
+- dhcp_range = {
+- 'comment' => range_comment,
+- 'listen_address' => listen_address.join(','),
+- 'start_address' => ip_range[0],
+- 'end_address' => ip_range[1],
+- 'netaddr' => cidr.to_s,
+- 'netmask' => netmask,
+- 'broadcast' => cidr.to_range.to_a[-1].to_s,
+- 'gateway' => net['gateway'],
+- }
+- debug("Appending dhcp range to the list of ranges: #{dhcp_range.inspect}")
+- dhcp_ranges << dhcp_range
+- end
+- end
+- dhcp_ranges
+- end
+-end
+diff --git a/deployment/puppet/fuel/lib/puppet/parser/functions/get_merged_network_metadata_from_yamls.rb b/deployment/puppet/fuel/lib/puppet/parser/functions/get_merged_network_metadata_from_yamls.rb
+deleted file mode 100644
+index 91028c6..0000000
+--- a/deployment/puppet/fuel/lib/puppet/parser/functions/get_merged_network_metadata_from_yamls.rb
++++ /dev/null
+@@ -1,20 +0,0 @@
+-module Puppet::Parser::Functions
+- newfunction(:get_merged_network_metadata_from_yamls, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+-Load a provision data from a set of YAML files for a set of cluster
+-located in /var/lib/fuel/configs/{CLUSTER_ID}/provision.yaml
+-
+- ENDHEREDOC
+- require 'yaml'
+- merged_data = {}
+- Dir["/var/lib/fuel/configs/*/provision.yaml"].each do |f|
+- begin
+- data = YAML::load_file(f) || {}
+- rescue Exception => e
+- warning("Found file #{f} but could not parse it")
+- data = {}
+- end
+- merged_data.merge!(data['network_metadata']['nodes'])
+- end
+- merged_data
+- end
+-end
+diff --git a/deployment/puppet/fuel/manifests/cobbler.pp b/deployment/puppet/fuel/manifests/cobbler.pp
+new file mode 100644
+index 0000000..ea312da
+--- /dev/null
++++ b/deployment/puppet/fuel/manifests/cobbler.pp
+@@ -0,0 +1,130 @@
++class fuel::cobbler(
++ $repo_root = $::fuel::params::repo_root,
++ $cobbler_user = $::fuel::params::cobbler_user,
++ $cobbler_password = $::fuel::params::cobbler_password,
++ $bootstrap_path,
++ $bootstrap_meta,
++ # network interface configuration timeout (in seconds)
++ $bootstrap_ethdevice_timeout = $::fuel::params::bootstrap_ethdevice_timeout,
++ $bootstrap_profile = $::fuel::params::bootstrap_profile,
++ $centos_repos = $::fuel::params::centos_repos,
++ $ks_system_timezone = $::fuel::params::ks_system_timezone,
++ $server = $::fuel::params::cobbler_host,
++ $name_server = $::fuel::params::cobbler_host,
++ $next_server = $::fuel::params::cobbler_host,
++ $dns_upstream = $::fuel::params::dns_upstream,
++ $dns_domain = $::fuel::params::dns_domain,
++ $dns_search = $::fuel::params::dns_search,
++ $mco_user = $::fuel::params::mco_user,
++ $mco_pass = $::fuel::params::mco_password,
++ $dhcp_ipaddress = $::fuel::params::dhcp_ipaddress,
++ $nailgun_api_url = "http://${::fuel::params::nailgun_host}:${::fuel::params::nailgun_port}/api",
++ # default password is 'r00tme'
++ $ks_encrypted_root_password = $::fuel::params::ks_encrypted_root_password,
++ ) inherits fuel::params {
++
++ anchor { 'nailgun-cobbler-begin': }
++ anchor { 'nailgun-cobbler-end': }
++
++ Anchor<| title == 'nailgun-cobbler-begin' |> ->
++ Class['::cobbler'] ->
++ Anchor<| title == 'nailgun-cobbler-end' |>
++
++ $real_server = $next_server
++
++ $fence_ssh_source = 'puppet:///modules/fuel/cobbler/fence_ssh.centos7.py'
++
++ class { '::cobbler':
++ server => $server,
++ domain_name => $domain_name,
++ dns_upstream => $dns_upstream,
++ dns_domain => $dns_domain,
++ dns_search => $dns_search,
++ name_server => $name_server,
++ next_server => $next_server,
++ dhcp_ipaddress => $dhcp_ipaddress,
++ cobbler_user => $cobbler_user,
++ cobbler_password => $cobbler_password,
++ pxetimeout => '50'
++ }
++
++ file { '/etc/cobbler/power/fence_ssh.template':
++ content => template('fuel/cobbler/fence_ssh.template.erb'),
++ owner => 'root',
++ group => 'root',
++ mode => '0644',
++ require => Class['::cobbler::server'],
++ }
++
++ file { '/usr/sbin/fence_ssh':
++ source => $fence_ssh_source,
++ owner => 'root',
++ group => 'root',
++ mode => '0755',
++ require => Class['::cobbler::server'],
++ }
++
++ cobbler_distro { 'ubuntu_bootstrap':
++ kernel => "${bootstrap_path}/vmlinuz",
++ initrd => "${bootstrap_path}/initrd.img",
++ arch => 'x86_64',
++ breed => 'ubuntu',
++ osversion => 'xenial',
++ ksmeta => '',
++ require => Class['::cobbler::server'],
++ }
++
++ cobbler_profile { 'ubuntu_bootstrap':
++ distro => 'ubuntu_bootstrap',
++ menu => true,
++ kickstart => '',
++ kopts => extend_kopts($bootstrap_meta['extend_kopts'], "console=ttyS0,9600 console=tty0 panic=60 ethdevice-timeout=${bootstrap_ethdevice_timeout} boot=live toram components fetch=http://${server}:8080/bootstraps/active_bootstrap/root.squashfs biosdevname=0 url=${nailgun_api_url} mco_user=${mco_user} mco_pass=${mco_pass} ip=frommedia"),
++ ksmeta => '',
++ server => $real_server,
++ require => Cobbler_distro['ubuntu_bootstrap'],
++ }
++
++ exec { 'cobbler_system_add_default':
++ command => "cobbler system add --name=default \
++ --profile=${bootstrap_profile} --netboot-enabled=True",
++ onlyif => 'test -z `cobbler system find --name=default`',
++ require => Cobbler_profile[$bootstrap_profile],
++ }
++
++ exec { 'cobbler_system_edit_default':
++ command => "cobbler system edit --name=default \
++ --profile=${bootstrap_profile} --netboot-enabled=True",
++ unless => "cobbler system report --name default 2>/dev/null | grep -q -E '^Profile\\s*:\\s*${bootstrap_profile}'",
++ require => Cobbler_profile[$bootstrap_profile],
++ }
++
++ exec { 'nailgun_cobbler_sync':
++ command => 'cobbler sync',
++ refreshonly => true,
++ }
++
++ Exec['cobbler_system_add_default'] ~> Exec['nailgun_cobbler_sync']
++ Exec['cobbler_system_edit_default'] ~> Exec['nailgun_cobbler_sync']
++ Cobbler_profile<| |> ~> Exec['nailgun_cobbler_sync']
++
++ #FIXME(mattymo): move pubkey to astute fact or download it
++ exec { 'cp /root/.ssh/id_rsa.pub /etc/cobbler/authorized_keys':
++ command => 'cp /root/.ssh/id_rsa.pub /etc/cobbler/authorized_keys',
++ creates => '/etc/cobbler/authorized_keys',
++ require => Class['::cobbler::server'],
++ }
++
++ file { '/etc/dnsmasq.conf':
++ ensure => link,
++ target => '/etc/cobbler.dnsmasq.conf',
++ }
++
++ file { ['/var/log/cobbler/anamon',
++ '/var/log/cobbler/kicklog',
++ '/var/log/cobbler/syslog',
++ '/var/log/cobbler/tasks'] :
++ ensure => directory,
++ require => Class['::cobbler::server'],
++ }
++
++}
+diff --git a/deployment/puppet/fuel/manifests/dnsmasq/dhcp_range.pp b/deployment/puppet/fuel/manifests/dnsmasq/dhcp_range.pp
+new file mode 100644
+index 0000000..a60bac5
+--- /dev/null
++++ b/deployment/puppet/fuel/manifests/dnsmasq/dhcp_range.pp
+@@ -0,0 +1,29 @@
++#
++# fuel::dnsmasq::dhcp_range creates config files in /etc/dnsmasq.d/
++#
++# [next_server] IP address that will be used as PXE tftp server
++# [dhcp_start_address] First address of dhcp range
++# [dhcp_end_address] Last address of dhcp range
++# [dhcp_netmask] Netmask of the network
++# [dhcp_gateway] Gateway address for installed nodes
++# [lease_time] DHCP lease time
++# [file_header] File header for comments
++
++define fuel::dnsmasq::dhcp_range(
++ $dhcp_start_address = '10.0.0.201',
++ $dhcp_end_address = '10.0.0.254',
++ $dhcp_netmask = '255.255.255.0',
++ $dhcp_gateway = $::ipaddress,
++ $listen_address = $::ipaddress,
++ $file_header = undef,
++ $lease_time = '120m',
++ $next_server = $::ipaddress,
++){
++ $range_name = $name
++ file { "/etc/dnsmasq.d/${name}.conf":
++ content => template('fuel/dnsmasq.dhcp-range.erb'),
++ owner => 'root',
++ group => 'root',
++ mode => '0644',
++ }
++}
+diff --git a/deployment/puppet/fuel/manifests/iptables.pp b/deployment/puppet/fuel/manifests/iptables.pp
+index b3ac965..fc0afb7 100644
+--- a/deployment/puppet/fuel/manifests/iptables.pp
++++ b/deployment/puppet/fuel/manifests/iptables.pp
+@@ -23,7 +23,8 @@ class fuel::iptables (
+ $chain = 'INPUT',
+ ) inherits fuel::params {
+
+- include ::provision::iptables
++ #Enable cobbler's iptables rules even if Cobbler not called
++ include ::cobbler::iptables
+
+ firewallchain { 'INPUT:filter:IPv4':
+ ensure => present,
+diff --git a/deployment/puppet/fuel/spec/functions/create_dnsmasq_dhcp_ranges_spec.rb b/deployment/puppet/fuel/spec/functions/create_dnsmasq_dhcp_ranges_spec.rb
+new file mode 100644
+index 0000000..7158984
+--- /dev/null
++++ b/deployment/puppet/fuel/spec/functions/create_dnsmasq_dhcp_ranges_spec.rb
+@@ -0,0 +1,70 @@
++require 'spec_helper'
++
++describe 'create_dnsmasq_dhcp_ranges' do
++
++ let(:admin_networks) do
++ [
++ {"id" => 1,
++ "node_group_name" => nil,
++ "node_group_id" => nil,
++ "cluster_name" => nil,
++ "cluster_id" => nil,
++ "cidr" => "10.145.0.0/24",
++ "gateway" => "10.145.0.2",
++ "ip_ranges" => [["10.145.0.3", "10.145.0.250"]],
++ },
++ {"id" => 2,
++ "node_group_name" => "default2",
++ "node_group_id" => 22,
++ "cluster_name" => "default2",
++ "cluster_id" => 2,
++ "cidr" => "10.144.0.0/24",
++ "gateway" => "10.144.0.5",
++ "ip_ranges" => [["10.144.0.10", "10.144.0.254"]],
++ },
++ ]
++ end
++
++ let(:facts) do
++ {
++ :interfaces => 'docker0,enp0s3,enp0s4,enp0s5,lo',
++ :ipaddress_docker0 => '172.17.0.1',
++ :ipaddress_enp0s3 => '10.145.0.2',
++ :ipaddress_enp0s4 => '10.144.0.2',
++ }
++ end
++ let(:catalog) do
++ lambda { catalogue }
++ end
++
++ it 'refuses String' do
++ is_expected.to run.with_params('foo').and_raise_error(Puppet::ParseError, /Should pass list of hashes as a parameter/)
++ end
++
++ it 'accepts empty data' do
++ is_expected.to run.with_params([{}])
++ end
++
++ it 'can create dnsmasq dhcp ranges' do
++ is_expected.to run.with_params(admin_networks)
++ parameters = {
++ :file_header=>"# Generated automatically by puppet\n# Environment: \n# Nodegroup: \n# IP range: [\"10.145.0.3\", \"10.145.0.250\"]",
++ :listen_address=>'10.145.0.2',
++ :dhcp_start_address=>"10.145.0.3",
++ :dhcp_end_address=>"10.145.0.250",
++ :dhcp_netmask=>"255.255.255.0",
++ :dhcp_gateway=>"10.145.0.2",
++ }
++ expect(catalog).to contain_fuel__dnsmasq__dhcp_range('range_6be3c888').with parameters
++ parameters = {
++ :file_header=>"# Generated automatically by puppet\n# Environment: default2\n# Nodegroup: default2\n# IP range: [\"10.144.0.10\", \"10.144.0.254\"]",
++ :listen_address=>'10.144.0.2',
++ :dhcp_start_address=>"10.144.0.10",
++ :dhcp_end_address=>"10.144.0.254",
++ :dhcp_netmask=>"255.255.255.0",
++ :dhcp_gateway=>"10.144.0.5",
++ }
++ expect(catalog).to contain_fuel__dnsmasq__dhcp_range('range_ff724fd0').with parameters
++ end
++
++end
+diff --git a/deployment/puppet/fuel/templates/dhclient.conf.erb b/deployment/puppet/fuel/templates/dhclient.conf.erb
+index 9b54550..d17616c 100644
+--- a/deployment/puppet/fuel/templates/dhclient.conf.erb
++++ b/deployment/puppet/fuel/templates/dhclient.conf.erb
+@@ -1 +1 @@
+-prepend domain-name-servers <%= @dns_address %>;
++prepend domain-name-servers <%= @cobbler_host %>;
+diff --git a/deployment/puppet/fuel/templates/dhcpd_ranges.erb b/deployment/puppet/fuel/templates/dhcpd_ranges.erb
+deleted file mode 100644
+index d455a95..0000000
+--- a/deployment/puppet/fuel/templates/dhcpd_ranges.erb
++++ /dev/null
+@@ -1,21 +0,0 @@
+-<% @dhcp_ranges.each do |range| -%>
+-
+-# <%= range['comment'] %>
+-subnet <%= range['netaddr'] %> netmask <%= range['netmask'] %> {
+- range <%= range['start_address'] %> <%= range['end_address'] %>;
+- option routers <%= range['gateway'] %>;
+- option subnet-mask <%= range['netmask'] %>;
+- option broadcast-address <%= range['broadcast'] %>;
+- option domain-name-servers <%= @dns_address %>;
+- option domain-name "<%= @domain_name %>";
+- next-server <%= @next_server %>;
+- default-lease-time 7200;
+- max-lease-time 7200;
+- ddns-hostname = concat("dhcp-",binary-to-ascii(10,8,"-", leased-address));
+- class "pxeclients" {
+- match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
+- filename "pxelinux.0";
+- }
+-}
+-
+-<% end -%>
+\ No newline at end of file
+diff --git a/deployment/puppet/fuel/templates/dnsmasq.dhcp-range.erb b/deployment/puppet/fuel/templates/dnsmasq.dhcp-range.erb
+new file mode 100644
+index 0000000..aa41d20
+--- /dev/null
++++ b/deployment/puppet/fuel/templates/dnsmasq.dhcp-range.erb
+@@ -0,0 +1,7 @@
++<% if @file_header %><%= @file_header %><% end %>
++<% if @listen_address && !@listen_address.empty? %>listen-address=<%= @listen_address %><% end %>
++dhcp-range=<%= @range_name %>,<%= @dhcp_start_address %>,<%= @dhcp_end_address %>,<%= @dhcp_netmask %>,<%= @lease_time %>
++dhcp-option=net:<%= @range_name %>,option:router,<%= @dhcp_gateway %>
++dhcp-boot=net:<%= @range_name %>,pxelinux.0,boothost,<%= @next_server %>
++dhcp-match=set:ipxe,175
++dhcp-option-force=tag:ipxe,210,http://<%= @next_server %>/cobbler/boot/
+diff --git a/deployment/puppet/fuel/templates/provision.yaml b/deployment/puppet/fuel/templates/provision.yaml
+deleted file mode 100644
+index 3d5d3c7..0000000
+--- a/deployment/puppet/fuel/templates/provision.yaml
++++ /dev/null
+@@ -1,8 +0,0 @@
+----
+-ddns_key: VyCWe0kutrawqQ2WEFKkAw==
+-ddns_key_algorithm: HMAC-MD5
+-ddns_key_name: DHCP_UPDATE
+-bootstrap_menu_label: bootstrap
+-bootstrap_kernel_path: /images/vmlinuz
+-bootstrap_initrd_path: /images/initrd.img
+-ethdevice_timeout: 120
+diff --git a/deployment/puppet/fuel/templates/resolv.conf.erb b/deployment/puppet/fuel/templates/resolv.conf.erb
+index ceb69d8..4e9541f 100644
+--- a/deployment/puppet/fuel/templates/resolv.conf.erb
++++ b/deployment/puppet/fuel/templates/resolv.conf.erb
+@@ -1,3 +1,3 @@
+ search <%= @dns_search %>
+-domain <%= @domain_name %>
+-nameserver <%= @dns_address %>
++domain <%= @dns_domain %>
++nameserver <%= @cobbler_host %>
+diff --git a/deployment/puppet/osnailyfacter/manifests/provision/build_image.pp b/deployment/puppet/osnailyfacter/manifests/provision/build_image.pp
+index 02fa0f0..3f90aec 100644
+--- a/deployment/puppet/osnailyfacter/manifests/provision/build_image.pp
++++ b/deployment/puppet/osnailyfacter/manifests/provision/build_image.pp
+@@ -1,7 +1,13 @@
+-class osnailyfacter::provision::build_image {
++class osnailyfacter::provision::build_image(
++ $data_file = '/tmp/provision.yaml',
++){
+
+- $data_file = "/var/lib/fuel/configs/${::cluster_id}/provision.yaml"
+- $data = loadyaml($data_file)
++ if $data_file == undef {
++ $data = loadyaml('/tmp/provision.yaml')
++ } else {
++ $data = loadyaml($data_file)
++ }
++ $cluster_id = $data['cluster']['id']
+
+ if $data['ironic']['enabled'] == 'true' {
+ $ironic_packages = [
+@@ -23,10 +29,10 @@ class osnailyfacter::provision::build_image {
+ ]
+
+ $package_list = join(prefix($ironic_packages, '--package '), ' ')
+- $ssh_auth_file = "/var/lib/fuel/keys/${::cluster_id}/ironic/ironic.pub"
++ $ssh_auth_file = "/var/lib/fuel/keys/${cluster_id}/ironic/ironic.pub"
+ $ssh_params = "--root-ssh-authorized-file ${ssh_auth_file}"
+
+- $out_dir = "/var/www/nailgun/bootstrap/ironic/${::cluster_id}/"
++ $out_dir = "/var/www/nailgun/bootstrap/ironic/${cluster_id}/"
+ $out_params = "--output-dir ${out_dir}"
+
+ $extra_params = "--extra-dir /usr/share/ironic-fa-bootstrap-configs/ --no-compress --no-default-extra-dirs --no-default-packages"
+@@ -35,19 +41,19 @@ class osnailyfacter::provision::build_image {
+ exec { 'generate_image_with_ironic':
+ command => "fuel-bootstrap build ${package_list} ${ssh_params} ${out_params} ${extra_params} ${log_params}",
+ path => ['/bin', '/usr/bin'],
+- unless => "test -e /var/www/nailgun/bootstrap/ironic/${::cluster_id}/vmlinuz",
++ unless => "test -e /var/www/nailgun/bootstrap/ironic/${cluster_id}/vmlinuz",
+ }
+
+ } else {
+ $build_dir = '--image_build_dir /var/lib/fuel/ibp'
+- $log_params = "--log-file /var/log/fuel-agent-env-${::cluster_id}.log"
++ $log_params = "--log-file /var/log/fuel-agent-env-${cluster_id}.log"
+ $extra_params = '--data_driver nailgun_build_image'
+
+ exec { 'generate_image_with_fuel':
+ command => "fa_build_image ${build_dir} ${log_params} ${extra_params} --input_data_file ${data_file}",
+ path => ['/bin', '/usr/bin'],
+ timeout => 1800,
+- unless => "test -e /var/www/nailgun/bootstrap/ironic/${::cluster_id}/vmlinuz",
++ unless => "test -e /var/www/nailgun/bootstrap/ironic/${cluster_id}/vmlinuz",
+ }
+ }
+ }
+diff --git a/deployment/puppet/provision/lib/puppet/parser/functions/tftp_files.rb b/deployment/puppet/provision/lib/puppet/parser/functions/tftp_files.rb
+deleted file mode 100644
+index e05a48b..0000000
+--- a/deployment/puppet/provision/lib/puppet/parser/functions/tftp_files.rb
++++ /dev/null
+@@ -1,22 +0,0 @@
+-module Puppet::Parser::Functions
+- newfunction(:tftp_files, :type => :rvalue) do |args|
+- # args[0] is a path prefix, e.g. /var/lib/tftpboot/pxelinux.cfg
+- # args[1] is a dict of hosts
+- # node-1:
+- # dhcp_binding_params:
+- # name: node-1
+- # mac:
+- # - aa:bb:cc:dd:ee:ff
+- # - 00:11:22:33:44:55
+- # ip_address: 10.20.0.10
+- # result is a list of file names
+- # - /var/lib/tftpboot/pxelinux.cfg/01-aa-bb-cc-dd-ee-ff
+- # - /var/lib/tftpboot/pxelinux.cfg/01-00-11-22-33-44-55
+- files = []
+- args[1].each {|host_name, host_data|
+- mac = host_data["dhcp_binding_params"]["mac"]
+- files << (args[0] + "/01-" + mac.gsub(":", "-"))
+- }
+- files
+- end
+-end
+diff --git a/deployment/puppet/provision/manifests/dhcpd.pp b/deployment/puppet/provision/manifests/dhcpd.pp
+deleted file mode 100644
+index 6837532..0000000
+--- a/deployment/puppet/provision/manifests/dhcpd.pp
++++ /dev/null
+@@ -1,54 +0,0 @@
+-class provision::dhcpd (
+- $network_address = $::provision::params::network_address,
+- $network_mask = $::provision::params::network_mask,
+- $broadcast_address = $::provision::params::broadcast_address,
+- $start_address = $::provision::params::start_address,
+- $end_address = $::provision::params::end_address,
+- $router = $::provision::params::router,
+- $next_server = $::provision::params::next_server,
+- $dns_address = $::provision::params::dns_address,
+- $domain_name = $::provision::params::domain_name,
+- $ddns_key = $::provision::params::ddns_key,
+- $ddns_key_algorithm = $::provision::params::ddns_key_algorithm,
+- $ddns_key_name = $::provision::params::ddns_key_name,
+- $known_hosts = [],
+-) inherits provision::params {
+-
+- package { "dhcpd" :
+- name => $::provision::params::dhcpd_package,
+- }
+-
+- file { $::provision::params::dhcpd_conf :
+- ensure => present,
+- content => template('provision/dhcpd.conf.erb'),
+- owner => 'dhcpd',
+- group => 'dhcpd',
+- mode => '0640',
+- require => Package["dhcpd"],
+- notify => Service["dhcpd"],
+- }
+-
+- file { $::provision::params::dhcpd_conf_d :
+- ensure => directory,
+- owner => 'root',
+- group => 'root',
+- mode => '0755',
+- require => Package["dhcpd"],
+- }
+-
+- # It is just a file that could be modified by other modules
+- file { $::provision::params::dhcpd_conf_extra :
+- ensure => present,
+- require => File[$::provision::params::dhcpd_conf_d],
+- }
+-
+- service { "dhcpd" :
+- name => $::provision::params::dhcpd_service,
+- ensure => running,
+- enable => true,
+- hasrestart => false,
+- hasstatus => false,
+- require => Package["dhcpd"],
+- }
+-
+-}
+diff --git a/deployment/puppet/provision/manifests/iptables.pp b/deployment/puppet/provision/manifests/iptables.pp
+deleted file mode 100644
+index f5aec5b..0000000
+--- a/deployment/puppet/provision/manifests/iptables.pp
++++ /dev/null
+@@ -1,28 +0,0 @@
+-class provision::iptables {
+-
+- firewall { '101 dns_tcp':
+- chain => INPUT,
+- dport => '53',
+- proto => 'tcp',
+- action => 'accept',
+- }
+- firewall { '102 dns_udp':
+- chain => INPUT,
+- dport => '53',
+- proto => 'udp',
+- action => 'accept',
+- }
+- firewall { '103 dhcp':
+- chain => INPUT,
+- dport => ['67','68'],
+- proto => 'udp',
+- action => 'accept',
+- }
+- firewall { '104 tftp':
+- chain => INPUT,
+- dport => '69',
+- proto => 'udp',
+- action => 'accept',
+- }
+-
+-}
+diff --git a/deployment/puppet/provision/manifests/named.pp b/deployment/puppet/provision/manifests/named.pp
+deleted file mode 100644
+index ee940c9..0000000
+--- a/deployment/puppet/provision/manifests/named.pp
++++ /dev/null
+@@ -1,51 +0,0 @@
+-class provision::named (
+- $domain_name = $::provision::params::domain_name,
+- $dns_address = $::provision::params::dns_address,
+- $forwarders = $::provision::params::forwarders,
+- $ddns_key = $::provision::params::ddns_key,
+- $ddns_key_algorithm = $::provision::params::ddns_key_algorithm,
+- $ddns_key_name = $::provision::params::ddns_key_name,
+-) inherits provision::params {
+-
+- package { "named" :
+- name => $::provision::params::named_package,
+- }
+-
+- file { "/var/named" :
+- ensure => directory,
+- owner => 'named',
+- group => 'named',
+- mode => '0750',
+- require => Package["named"],
+- }
+-
+- file { $::provision::params::named_conf :
+- ensure => present,
+- content => template('provision/named.conf.erb'),
+- owner => 'named',
+- group => 'named',
+- mode => '0640',
+- require => Package["named"],
+- notify => Service["named"],
+- }
+-
+- file { "/var/named/${domain_name}" :
+- ensure => present,
+- content => template('provision/zone.erb'),
+- owner => 'named',
+- group => 'named',
+- mode => '0644',
+- require => Package["named"],
+- notify => Service["named"],
+- }
+-
+- service { "named" :
+- name => $::provision::params::named_service,
+- ensure => running,
+- enable => true,
+- hasrestart => false,
+- hasstatus => false,
+- require => Package["named"],
+- }
+-
+-}
+diff --git a/deployment/puppet/provision/manifests/params.pp b/deployment/puppet/provision/manifests/params.pp
+deleted file mode 100644
+index 2bcae12..0000000
+--- a/deployment/puppet/provision/manifests/params.pp
++++ /dev/null
+@@ -1,36 +0,0 @@
+-class provision::params {
+- case $::osfamily {
+- 'RedHat': {
+- $dhcpd_package = "dhcp"
+- $dhcpd_service = "dhcpd"
+- $dhcpd_conf = "/etc/dhcp/dhcpd.conf"
+- $dhcpd_conf_d = "/etc/dhcp/dhcpd.d"
+- $dhcpd_conf_extra = "/etc/dhcp/dhcpd.d/extra.conf"
+- $named_package = "bind"
+- $named_service = "named"
+- $named_conf = "/etc/named.conf"
+- }
+- default: {
+- fail("Unsupported osfamily ${::osfamily}")
+- }
+- }
+- $network_address = "10.20.0.0"
+- $network_mask = "255.255.255.0"
+- $broadcast_address = "10.20.0.255"
+- $start_address = "10.20.0.3"
+- $end_address = "10.20.0.254"
+- $router = "10.20.0.1"
+- $next_server = "10.20.0.2"
+- $dns_address = "10.20.0.2"
+- $forwarders = ["8.8.8.8", "8.8.4.4"]
+- $domain_name = "domain.tld"
+- $ddns_key = "VyCWe0kutrawqQ2WEFKkAw=="
+- $ddns_key_algorithm = "HMAC-MD5"
+- $ddns_key_name = "DHCP_UPDATE"
+-
+- $bootstrap_kernel_path = "/images/ubuntu_bootstrap/vmlinuz"
+- $bootstrap_initrd_path = "/images/ubuntu_bootstrap/initrd.img"
+- $bootstrap_kernel_params = "ksdevice=bootif lang= console=ttyS0,9600 console=tty0 toram locale=en_US text boot=live biosdevname=0 components ip=frommedia ethdevice-timeout=120 net.ifnames=1 panic=60"
+- $bootstrap_menu_label = "ubuntu_bootstrap"
+-
+-}
+diff --git a/deployment/puppet/provision/manifests/tftp.pp b/deployment/puppet/provision/manifests/tftp.pp
+deleted file mode 100644
+index f05bd16..0000000
+--- a/deployment/puppet/provision/manifests/tftp.pp
++++ /dev/null
+@@ -1,95 +0,0 @@
+-class provision::tftp (
+- $bootstrap_kernel_params = $::provision::params::bootstrap_kernel_params,
+- $bootstrap_kernel_path = $::provision::params::bootstrap_kernel_path,
+- $bootstrap_initrd_path = $::provision::params::bootstrap_initrd_path,
+- $bootstrap_menu_label = $::provision::params::bootstrap_menu_label,
+- $chain32_files = [],
+-) inherits provision::params {
+-
+- Exec {path => '/usr/bin:/bin:/usr/sbin:/sbin'}
+-
+- case $::osfamily {
+- 'RedHat': {
+- $tftp_packages = ['xinetd', 'tftp-server', 'syslinux']
+-
+- service { 'xinetd':
+- ensure => running,
+- enable => true,
+- hasrestart => true,
+- require => Package[$tftp_packages],
+- }
+-
+- file { '/etc/xinetd.conf':
+- content => template('provision/xinetd.conf.erb'),
+- owner => 'root',
+- group => 'root',
+- mode => '0600',
+- require => Package[$tftp_packages],
+- notify => Service['xinetd'],
+- }
+-
+- file { '/etc/xinetd.d/tftp' :
+- content => template('provision/tftp.xinetd.erb'),
+- owner => 'root',
+- group => 'root',
+- mode => '0644',
+- require => Package[$tftp_packages],
+- notify => Service['xinetd'],
+- }
+-
+- }
+- default : {
+- fail("Unsupported osfamily ${::osfamily}")
+- }
+- }
+-
+- ensure_packages($tftp_packages)
+-
+- file { ["/var/lib/tftpboot/images", "/var/lib/tftpboot/pxelinux.cfg"] :
+- ensure => directory,
+- owner => 'root',
+- group => 'root',
+- mode => '0755',
+- require => Package[$tftp_packages],
+- }
+-
+- file { "/var/lib/tftpboot/pxelinux.cfg/default" :
+- ensure => present,
+- content => template("provision/tftp.default.erb"),
+- owner => 'root',
+- group => 'root',
+- mode => '0644',
+- require => File["/var/lib/tftpboot/pxelinux.cfg"],
+- }
+-
+- file { '/var/lib/tftpboot/chain.c32':
+- source => '/usr/share/syslinux/chain.c32',
+- require => Package[$tftp_packages],
+- }
+-
+- file { '/var/lib/tftpboot/pxelinux.0':
+- source => '/usr/share/syslinux/pxelinux.0',
+- require => Package[$tftp_packages],
+- }
+-
+- file { '/var/lib/tftpboot/menu.c32':
+- source => '/usr/share/syslinux/menu.c32',
+- require => Package[$tftp_packages],
+- }
+-
+- # TODO Create custom type that will remove all 01-* files that
+- # are not in the $chain32_files list
+- exec { 'remove /var/lib/tftpboot/pxelinux.cfg/01-* files' :
+- command => "find /var/lib/tftpboot/pxelinux.cfg -type f -name '01-*' -delete",
+- require => File["/var/lib/tftpboot/pxelinux.cfg"],
+- } ->
+-
+- file { $chain32_files :
+- ensure => present,
+- content => template("provision/tftp.chain32.erb"),
+- owner => 'root',
+- group => 'root',
+- mode => '0644',
+- require => File["/var/lib/tftpboot/pxelinux.cfg"],
+- }
+-}
+diff --git a/deployment/puppet/provision/templates/dhcpd.conf.erb b/deployment/puppet/provision/templates/dhcpd.conf.erb
+deleted file mode 100644
+index 8120dc1..0000000
+--- a/deployment/puppet/provision/templates/dhcpd.conf.erb
++++ /dev/null
+@@ -1,69 +0,0 @@
+-ddns-updates on;
+-update-static-leases on;
+-ddns-domainname "<%= @domain_name %>";
+-ddns-update-style interim;
+-ignore client-updates;
+-update-static-leases true;
+-
+-key <%= @ddns_key_name %> {
+- algorithm <%= @ddns_key_algorithm %>;
+- secret <%= @ddns_key %>;
+-}
+-
+-local-address <%= @dns_address %>;
+-zone <%= @domain_name %>. {
+- primary <%= @dns_address %>;
+- key <%= @ddns_key_name %>;
+-}
+-
+-allow booting;
+-allow bootp;
+-set vendorclass = option vendor-class-identifier;
+-option pxe-system-type code 93 = unsigned integer 16;
+-default-lease-time 3600;
+-max-lease-time 3600;
+-log-facility local7;
+-
+-subnet <%= @network_address %> netmask <%= @network_mask %> {
+- range <%= @start_address %> <%= @end_address %>;
+- option domain-name-servers <%= @dns_address %>;
+- option domain-name "<%= @domain_name %>";
+- option subnet-mask <%= @network_mask %>;
+- option routers <%= @router %>;
+- option broadcast-address <%= @broadcast_address %>;
+- next-server <%= @next_server %>;
+- ddns-hostname = pick(option fqdn.hostname,option host-name, concat("dhcp-",binary-to-ascii(10,8,"-", leased-address)));
+- class "pxeclients" {
+- match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
+- filename "pxelinux.0";
+- }
+-}
+-
+-<% if @known_hosts -%>
+-group {
+-
+- option domain-name-servers <%= @dns_address %>;
+- option domain-name "<%= @domain_name %>";
+- option subnet-mask <%= @network_mask %>;
+- option routers <%= @router %>;
+- option broadcast-address <%= @broadcast_address %>;
+- next-server <%= @next_server %>;
+- class "pxeclients" {
+- match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
+- filename "pxelinux.0";
+- }
+-
+- <% @known_hosts.each do |host_name, host_data| -%>
+- host <%= host_data['dhcp_binding_params']['name'] %> {
+- hardware ethernet <%= host_data['dhcp_binding_params']['mac'] %>;
+- fixed-address <%= host_data['dhcp_binding_params']['ip_address'] %>;
+- ddns-hostname "<%= host_data['dhcp_binding_params']['name'].split('.')[0] %>";
+- ddns-domainname "<%= @domain_name%>";
+- option host-name "<%= host_data['dhcp_binding_params']['name'].split('.')[0] %>";
+- option domain-name "<%= @domain_name %>";
+- }
+- <% end -%>
+-}
+-<% end -%>
+-
+-include "<%= scope.lookupvar('::provision::params::dhcpd_conf_extra') %>";
+diff --git a/deployment/puppet/provision/templates/named.conf.erb b/deployment/puppet/provision/templates/named.conf.erb
+deleted file mode 100644
+index f612204..0000000
+--- a/deployment/puppet/provision/templates/named.conf.erb
++++ /dev/null
+@@ -1,32 +0,0 @@
+-options {
+- listen-on port 53 { <%= @dns_address %>; };
+- directory "/var/named";
+- dump-file "/var/named/data/cache_dump.db";
+- statistics-file "/var/named/data/named_stats.txt";
+- memstatistics-file "/var/named/data/named_mem_stats.txt";
+- recursion yes;
+- forward only;
+- forwarders {
+- <% @forwarders.each do |forwarder| -%>
+- <%= forwarder %>;
+- <% end -%>
+- };
+-};
+-
+-key <%= @ddns_key_name %> {
+- algorithm <%= @ddns_key_algorithm %>;
+- secret <%= @ddns_key %>;
+-};
+-
+-logging {
+- channel default_debug {
+- file "data/named.run";
+- severity dynamic;
+- };
+-};
+-
+-zone "<%= @domain_name %>." {
+- type master;
+- file "<%= @domain_name %>";
+- allow-update { key <%= @ddns_key_name %>; };
+-};
+diff --git a/deployment/puppet/provision/templates/tftp.chain32.erb b/deployment/puppet/provision/templates/tftp.chain32.erb
+deleted file mode 100644
+index fae5e43..0000000
+--- a/deployment/puppet/provision/templates/tftp.chain32.erb
++++ /dev/null
+@@ -1,8 +0,0 @@
+-DEFAULT local
+-PROMPT 0
+-TIMEOUT 0
+-TOTALTIMEOUT 0
+-ONTIMEOUT local
+-
+-LABEL local
+- COM32 chain.c32
+diff --git a/deployment/puppet/provision/templates/tftp.default.erb b/deployment/puppet/provision/templates/tftp.default.erb
+deleted file mode 100644
+index e1cee87..0000000
+--- a/deployment/puppet/provision/templates/tftp.default.erb
++++ /dev/null
+@@ -1,19 +0,0 @@
+-DEFAULT menu
+-PROMPT 0
+-MENU TITLE Boot menu
+-TIMEOUT 50
+-TOTALTIMEOUT 0
+-ONTIMEOUT <%= @bootstrap_menu_label %>
+-
+-LABEL local
+- MENU LABEL (local)
+- MENU DEFAULT
+- LOCALBOOT -1
+-
+-LABEL <%= @bootstrap_menu_label %>
+- kernel <%= @bootstrap_kernel_path %>
+- MENU LABEL <%= @bootstrap_menu_label %>
+- append initrd=<%= @bootstrap_initrd_path %> <%= @bootstrap_kernel_params %>
+- ipappend 2
+-
+-MENU end
+diff --git a/deployment/puppet/provision/templates/tftp.xinetd.erb b/deployment/puppet/provision/templates/tftp.xinetd.erb
+deleted file mode 100644
+index bde8373..0000000
+--- a/deployment/puppet/provision/templates/tftp.xinetd.erb
++++ /dev/null
+@@ -1,13 +0,0 @@
+-service tftp
+-{
+- disable = no
+- socket_type = dgram
+- protocol = udp
+- wait = yes
+- user = root
+- server = /usr/sbin/in.tftpd
+- server_args = -B 1380 -v -s /var/lib/tftpboot
+- per_source = 11
+- cps = 100 2
+- flags = IPv4
+-}
+diff --git a/deployment/puppet/provision/templates/xinetd.conf.erb b/deployment/puppet/provision/templates/xinetd.conf.erb
+deleted file mode 100644
+index 0a90f33..0000000
+--- a/deployment/puppet/provision/templates/xinetd.conf.erb
++++ /dev/null
+@@ -1,17 +0,0 @@
+-defaults
+-{
+- log_type = SYSLOG daemon info
+- log_on_failure = HOST
+- log_on_success = PID HOST DURATION EXIT
+-
+- cps = 50 10
+- instances = 50
+- per_source = 10
+-
+- v6only = no
+-
+- groups = yes
+- umask = 002
+-}
+-
+-includedir /etc/xinetd.d
+diff --git a/deployment/puppet/provision/templates/zone.erb b/deployment/puppet/provision/templates/zone.erb
+deleted file mode 100644
+index ea1b87a..0000000
+--- a/deployment/puppet/provision/templates/zone.erb
++++ /dev/null
+@@ -1,11 +0,0 @@
+-$TTL 300
+-@ IN SOA ns.<%= @domain_name %>. nobody.<%= @domain_name %>. (
+- 2017021302 ; Serial
+- 600 ; Refresh
+- 1800 ; Retry
+- 604800 ; Expire
+- 300 ; TTL
+- )
+-
+- IN NS ns.<%= @domain_name %>.
+-ns IN A <%= @dns_address %>
+diff --git a/graphs/provision/tasks.yaml b/graphs/provision/tasks.yaml
+index 3a21c87..68716ce 100644
+--- a/graphs/provision/tasks.yaml
++++ b/graphs/provision/tasks.yaml
+@@ -14,7 +14,7 @@
+ requires: [provision_start]
+ required_for: [build_deploy_image]
+ parameters:
+- path: /var/lib/fuel/configs/{CLUSTER_ID}/provision.yaml
++ path: /tmp/provision.yaml
+ timeout: 180
+ data:
+ #TODO: Replace dict($.items) to $ when LP1666913 is fixed
+@@ -40,27 +40,31 @@
+ requires: [upload_provision_info_master, generate_ironic_bootstrap_keys]
+ required_for: [provision_end]
+ parameters:
+- command_prefix: FACTER_cluster_id={CLUSTER_ID}
+ puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/provision/build_image.pp
+ puppet_modules: /etc/puppet/modules
+ timeout: 3600
+
+-- id: provision_master
+- type: puppet
++- id: move_to_bootstrap
++ type: move_to_bootstrap
+ version: 2.1.0
+- role: ['master']
+- requires: [upload_provision_info_master]
+- required_for: [build_deploy_image]
++ role: ['/.*/']
++ requires: [provision_start, build_deploy_image]
++ required_for: [upload_provision_info]
++ cross-depends:
++ - name: build_deploy_image
++ role: master
+ parameters:
+- puppet_manifest: /etc/puppet/modules/fuel/examples/provision.pp
+- puppet_modules: /etc/puppet/modules
+- timeout: 3600
++ slave_name:
++ yaql_exp: '$.network_metadata.nodes.values().where($.uid = new($.uid)).name.first()'
++ provisioning_info:
++ yaql_exp: '$.provision'
++ timeout: 180
+
+ - id: upload_provision_info
+ type: upload_file
+ version: 2.1.0
+ role: ['/.*/']
+- requires: [provision_master]
++ requires: [move_to_bootstrap]
+ required_for: [system_provision]
+ parameters:
+ path: /tmp/provision.json
+@@ -72,8 +76,8 @@
+ type: shell
+ version: 2.1.0
+ role: ['/.*/']
+- requires: [provision_master, upload_provision_info]
+- required_for: [node_reboot]
++ requires: [move_to_bootstrap, upload_provision_info]
++ required_for: [cobbler_disable_netboot]
+ cross-depends:
+ - name: build_deploy_image
+ role: master
+@@ -81,6 +85,19 @@
+ cmd: /usr/bin/provision
+ timeout: 3600
+
++- id: cobbler_disable_netboot
++ type: master_shell
++ version: 2.1.0
++ role: ['/.*/']
++ requires: [system_provision]
++ required_for: [node_reboot]
++ parameters:
++ strategy:
++ type: one_by_one
++ cmd:
++ yaql_exp: 'concat("sh /etc/puppet/modules/osnailyfacter/modular/provision/netboot disable ", $.provision.name)'
++ timeout: 180
++
+ - id: node_reboot
+ type: reboot
+ version: 2.1.0
+diff --git a/tests/noop/spec/hosts/master/cobbler_spec.rb b/tests/noop/spec/hosts/master/cobbler_spec.rb
+new file mode 100644
+index 0000000..f7c36fb
+--- /dev/null
++++ b/tests/noop/spec/hosts/master/cobbler_spec.rb
+@@ -0,0 +1,79 @@
++require 'spec_helper'
++require 'shared-examples'
++require 'yaml'
++manifest = 'master/cobbler.pp'
++
++# HIERA: master
++# FACTS: master_centos7
++
++describe manifest do
++ shared_examples 'catalog' do
++ let(:fuel_settings) do
++ YAML.load facts[:astute_settings_yaml]
++ end
++
++ let(:bootstrap_settings) do
++ fuel_settings.fetch 'BOOTSTRAP', {}
++ end
++
++ it 'should contain class "fuel::cobbler" with correct parameters' do
++ parameters = {
++ :cobbler_user => fuel_settings['cobbler']['user'],
++ :cobbler_password => fuel_settings['cobbler']['password'],
++ :bootstrap_path => bootstrap_settings.fetch('path', '/var/www/nailgun/bootstraps/active_bootstrap'),
++ # :bootstrap_meta => nil,
++ :server => fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ :name_server => fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ :next_server => fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ :mco_user => fuel_settings['mcollective']['user'],
++ :mco_pass => fuel_settings['mcollective']['password'],
++ :dns_upstream => [fuel_settings['DNS_UPSTREAM']],
++ :dns_domain => fuel_settings['DNS_DOMAIN'],
++ :dns_search => fuel_settings['DNS_SEARCH'],
++ :dhcp_ipaddress => fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ :nailgun_api_url => "http://#{fuel_settings['ADMIN_NETWORK']['ipaddress']}:8000/api",
++ :bootstrap_ethdevice_timeout => bootstrap_settings.fetch('ethdevice_timeout', '120'),
++ }
++ is_expected.to contain_class('fuel::cobbler').with parameters
++ end
++
++ it { is_expected.to contain_file '/etc/resolv.conf' }
++
++ %w(httpd cobblerd xinetd).each do |service|
++ it "should containt '#{service}' fuel::systemd service with correct parameters" do
++ parameters = {
++ :start => true,
++ :template_path => 'fuel/systemd/restart_template.erb',
++ :config_name => 'restart.conf',
++ }
++ is_expected.to contain_fuel__systemd(service).with parameters
++ end
++ end
++
++ it "should containt dnsmasq fuel::systemd service with correct parameters" do
++ parameters = {
++ :start => true,
++ :template_path => 'fuel/systemd/dnsmasq_template.erb',
++ :config_name => 'restart.conf',
++ }
++ is_expected.to contain_fuel__systemd('dnsmasq').with parameters
++ end
++
++ it 'should declare the "fuel::dnsmasq::dhcp_range" with "default" title and correct parameters' do
++ parameters = {
++ :dhcp_start_address => fuel_settings['ADMIN_NETWORK']['dhcp_pool_start'],
++ :dhcp_end_address => fuel_settings['ADMIN_NETWORK']['dhcp_pool_end'],
++ :dhcp_netmask => fuel_settings['ADMIN_NETWORK']['netmask'],
++ :dhcp_gateway => fuel_settings['ADMIN_NETWORK']['dhcp_gateway'],
++ :next_server => fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ :listen_address => fuel_settings['ADMIN_NETWORK']['ipaddress'],
++ }
++ is_expected.to contain_fuel__dnsmasq__dhcp_range('default').with parameters
++ is_expected.to contain_fuel__dnsmasq__dhcp_range('default').that_notifies 'Service[dnsmasq]'
++ end
++
++ it { is_expected.to contain_cobbler_profile('ubuntu_bootstrap').with_kopts(/\bip=frommedia\b/) }
++
++ end
++ run_test manifest
++end
+diff --git a/tests/noop/spec/hosts/master/dhcp-ranges_spec.rb b/tests/noop/spec/hosts/master/dhcp-ranges_spec.rb
+new file mode 100644
+index 0000000..b34675b
+--- /dev/null
++++ b/tests/noop/spec/hosts/master/dhcp-ranges_spec.rb
+@@ -0,0 +1,17 @@
++require 'spec_helper'
++require 'shared-examples'
++manifest = 'master/dhcp-ranges.pp'
++
++# HIERA: master
++# FACTS: master_centos7
++
++describe manifest do
++ shared_examples 'catalog' do
++ context 'with empty admin_networks' do
++ it 'should not create any dhcp ranges' do
++ is_expected.to have_nailgun__dnsmasq__dhcp_range_resource_count 0
++ end
++ end
++ end
++ run_test manifest
++end
+diff --git a/tests/noop/spec/hosts/master/host_spec.rb b/tests/noop/spec/hosts/master/host_spec.rb
+index 9937ff3..66c3b4b 100644
+--- a/tests/noop/spec/hosts/master/host_spec.rb
++++ b/tests/noop/spec/hosts/master/host_spec.rb
+@@ -263,6 +263,8 @@ describe manifest do
+ should contain_firewall('102 dns_udp')
+ should contain_firewall('103 dhcp')
+ should contain_firewall('104 tftp')
++ should contain_firewall('105 squidproxy')
++ should contain_firewall('106 cobbler_web')
+ end
+
+ it 'should declare "openstack::clocksync" class with parameters' do
diff --git a/patches/fuel-library/upstream-backports/0002-Increase-reboot-task-timeout.patch b/patches/fuel-library/upstream-backports/0002-Increase-reboot-task-timeout.patch
deleted file mode 100644
index a675fc78..00000000
--- a/patches/fuel-library/upstream-backports/0002-Increase-reboot-task-timeout.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-: Copyright (c) 2017 Enea AB and others.
-:
-: All rights reserved. This program and the accompanying materials
-: are made available under the terms of the Apache License, Version 2.0
-: which accompanies this distribution, and is available at
-: http://www.apache.org/licenses/LICENSE-2.0
-::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-From: Stanislaw Bogatkin <sbogatkin@mirantis.com>
-Date: Mon, 13 Mar 2017 14:13:34 +0300
-Subject: [PATCH] Increase reboot task timeout
-
-To avoid broken provision on baremetal servers, increase reboot
-task timeout to 15 minutes.
-
-Change-Id: Ia7b9aa96407dae5819420146f5e1e934031b662c
-Closes-Bug: #1671793
----
- graphs/provision/tasks.yaml | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/graphs/provision/tasks.yaml b/graphs/provision/tasks.yaml
-index 46f4faa..68716ce 100644
---- a/graphs/provision/tasks.yaml
-+++ b/graphs/provision/tasks.yaml
-@@ -105,4 +105,4 @@
- requires: [cobbler_disable_netboot]
- required_for: [set_status_provisioned]
- parameters:
-- timeout: 180
-+ timeout: 900