Added ability to update PXE DHCP parameters after deploy

It's possible to change PXE settings on post deploy stage, but, in fact,
dnsmasq configuration will not be changed. This patch introduce puppet
call to get these changes applied.

Function puppetApply was refactored to return Bool value,
previously it has returned None or False.

Change-Id: I3fc7097035f492ad24483205cedc0d2c773af24b
Closes-Bug: #1500667
Depends-On: I9200c90747dba1e5c5b4e5457e423cb4c3ff3062
This commit is contained in:
mzhnichkov 2016-04-26 12:13:13 +03:00 committed by Mikhail
parent 8cd87313fe
commit 599d801eb0
8 changed files with 129 additions and 10 deletions

View File

@ -33,8 +33,8 @@ def inSameSubnet(ip1, ip2, netmask_or_cidr):
cidr1 = netaddr.IPNetwork("%s/%s" % (ip1, netmask_or_cidr))
cidr2 = netaddr.IPNetwork("%s/%s" % (ip2, netmask_or_cidr))
return cidr1 == cidr2
except netaddr.AddrFormatError:
log.exception('Invalid address specified: {0}'.format(cidr1))
except netaddr.AddrFormatError as e:
log.exception(e.message)
return False

View File

@ -68,6 +68,7 @@ def puppetApply(classes):
log.error("Exit code: %d. Error: %s Stdout: %s",
code, err, out)
return False
return True
def puppetApplyManifest(manifest):

View File

@ -19,9 +19,11 @@ LOGFILE = "/var/log/fuelmenu.log"
PUPPET_LOGFILE = "/var/log/puppet/fuelmenu-puppet.log"
PUPPET_NAILGUN = "/etc/puppet/modules/fuel/examples/nailgun.pp"
PUPPET_FUEL_MASTER = "/etc/puppet/modules/fuel/examples/host.pp"
PUPPET_DHCP_RANGES = "/etc/puppet/modules/fuel/examples/dhcp-ranges.pp"
SETTINGS_FILE = "/etc/fuel/astute.yaml"
RELEASE_FILE = "/etc/fuel_release"
HIERA_NET_SETTINGS = "/etc/hiera/networks.yaml"
DEFAULT_LOCK_FILE = "/var/run/fuelmenu.lock"
@ -31,3 +33,5 @@ POST_DEPLOYMENT_MODE = "post"
PUPPET_TYPE_LITERAL = "literal"
PUPPET_TYPE_RESOURCE = "resource"
PUPPET_TYPE_CLASS = "class"
ADMIN_NETWORK_ID = 1

View File

@ -13,18 +13,26 @@
# License for the specific language governing permissions and limitations
# under the License.
import logging
import os
from fuelclient.cli import error
from fuelclient.objects import NetworkGroup
import netaddr
import urwid
import urwid.raw_display
import urwid.web_display
import yaml
from fuelmenu.common import dialog
from fuelmenu.common.errors import BadIPException
from fuelmenu.common.modulehelper import ModuleHelper
from fuelmenu.common.modulehelper import WidgetType
from fuelmenu.common import network
from fuelmenu.common import puppet
import fuelmenu.common.urwidwrapper as widget
from fuelmenu.common import utils
import logging
import netaddr
import urwid
import urwid.raw_display
import urwid.web_display
from fuelmenu import consts
log = logging.getLogger('fuelmenu.pxe_setup')
blank = urwid.Divider()
@ -78,6 +86,10 @@ to advertise via DHCP to nodes",
self.load()
self.extdhcp = True
self.screen = None
self.apply_dialog_message = {
'title': "Apply failed in module {0}".format(self.name),
"message": "Error applying changes. Check logs for details."
}
def check(self, args):
"""Validates all fields have valid values and some sanity checks."""
@ -276,10 +288,110 @@ interface first.")
log.error("Check failed. Not applying")
log.error("%s" % (responses))
return False
self.save(responses)
if utils.is_post_deployment():
self.parent.apply_tasks.add(self.update_dhcp)
return True
def update_dhcp(self):
settings = self.parent.settings.get("ADMIN_NETWORK")
if not self._update_nailgun(settings):
return False
if os.path.exists(consts.HIERA_NET_SETTINGS):
result, msg = self._update_hiera_dnsmasq(settings)
else:
result = self._update_dnsmasq(settings)
if not result:
ModuleHelper.display_dialog(
self, error_msg=self.apply_dialog_message["message"],
title=self.apply_dialog_message["title"])
return False
cobbler_sync = ["cobbler", "sync"]
code, out, err = utils.execute(cobbler_sync)
if code != 0:
log.error(err)
ModuleHelper.display_dialog(
self, error_msg=self.apply_dialog_message["message"],
title=self.apply_dialog_message["title"])
return False
return True
def _update_nailgun(self, settings):
msg = "Apply changes to Nailgun"
log.info(msg)
self.parent.footer.set_text(msg)
self.parent.refreshScreen()
# TODO(mzhnichkov) this manifest apply twice(here and in feature
# groups). Need to combine this calls
result, msg = puppet.puppetApplyManifest(consts.PUPPET_NAILGUN)
if not result:
ModuleHelper.display_dialog(
self, error_msg=self.apply_dialog_message["message"],
title=self.apply_dialog_message["title"])
return False
data = {
"gateway": settings["dhcp_gateway"],
"ip_ranges": [
[settings["dhcp_pool_start"], settings["dhcp_pool_end"]]
]
}
try:
NetworkGroup(consts.ADMIN_NETWORK_ID).set(data)
except error.HTTPError as e:
log.error(e.message)
ModuleHelper.display_dialog(
self, error_msg=self.apply_dialog_message["message"],
title=self.apply_dialog_message["title"])
return False
return True
def _update_hiera_dnsmasq(self, settings):
"""Update Hiera and dnsmasq
PXE related configuration should be written in separate
configuration file when you create additional admin
network(this behavior was introduced in nailgun's
DnsmasqUpdateTask class)
"""
msg = "Apply changes to Hiera and Dnsmasq"
log.info(msg)
self.parent.footer.set_text(msg)
self.parent.refreshScreen()
with open(consts.HIERA_NET_SETTINGS, "r") as hiera_settings:
networks = yaml.safe_load(hiera_settings)
net = netaddr.IPNetwork(
"{0}/{1}".format(settings["ipaddress"],
settings["netmask"]))
for admin_net in networks["admin_networks"]:
if str(net.cidr) == admin_net["cidr"]:
admin_net["ip_ranges"] = [
[settings["dhcp_pool_start"],
settings["dhcp_pool_end"]]
]
admin_net["gateway"] = settings["dhcp_gateway"]
with open(consts.HIERA_NET_SETTINGS, "w") as hiera_settings:
yaml.safe_dump(networks, hiera_settings)
return puppet.puppetApplyManifest(consts.PUPPET_DHCP_RANGES)
def _update_dnsmasq(self, settings):
puppet_classes = [{
"type": "resource",
"class": "fuel::dnsmasq::dhcp_range",
"name": "default",
"params": {
"dhcp_start_address": settings["dhcp_pool_start"],
"dhcp_end_address": settings["dhcp_pool_end"],
"dhcp_netmask": settings["netmask"],
"dhcp_gateway": settings["dhcp_gateway"],
"next_server": settings["ipaddress"]
}
}]
log.debug("Start puppet with data {0}".format(puppet_classes))
return puppet.puppetApply(puppet_classes)
def cancel(self, button):
ModuleHelper.cancel(self, button)
self.setNetworkDetails()

View File

@ -306,7 +306,7 @@ class Interfaces(urwid.WidgetWrap):
try:
self.parent.refreshScreen()
result = puppet.puppetApply(puppetclasses)
if result is False:
if not result:
raise Exception("Puppet apply failed")
ModuleHelper.getNetwork(self)
gateway = self.get_default_gateway_linux()

View File

@ -58,7 +58,7 @@ class TestPuppetApply(unittest.TestCase):
]
def test_puppet_apply(self, m_execute, m_log):
self.assertEqual(puppet.puppetApply(self.classes), None)
self.assertEqual(puppet.puppetApply(self.classes), True)
m_execute.assert_called_once_with(self.command, stdin=self.input)
m_log.info.assert_called_once_with('Puppet start')
self.assertFalse(m_log.error.called)

View File

@ -23,6 +23,7 @@ requirements = [
'netifaces>=0.5',
'urwid>=1.1.1',
'requests>=2.5.2,!=2.8.0,!=2.9.0',
'python-fuelclient>=9.0.0'
]
if sys.version_info[0:2] == (2, 6):

View File

@ -26,6 +26,7 @@ Requires: python-urwid >= 1.1.0
Requires: PyYAML
Requires: screen
Requires: python-six
Requires: python-fuelclient
%if 0%{?rhel} == 6
Requires: python-ordereddict
%endif