Merge "Added ability to update PXE DHCP parameters after deploy"

This commit is contained in:
Jenkins 2016-06-03 07:06:20 +00:00 committed by Gerrit Code Review
commit c13fde0abd
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)) cidr1 = netaddr.IPNetwork("%s/%s" % (ip1, netmask_or_cidr))
cidr2 = netaddr.IPNetwork("%s/%s" % (ip2, netmask_or_cidr)) cidr2 = netaddr.IPNetwork("%s/%s" % (ip2, netmask_or_cidr))
return cidr1 == cidr2 return cidr1 == cidr2
except netaddr.AddrFormatError: except netaddr.AddrFormatError as e:
log.exception('Invalid address specified: {0}'.format(cidr1)) log.exception(e.message)
return False return False

View File

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

View File

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

View File

@ -13,18 +13,26 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # 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 import dialog
from fuelmenu.common.errors import BadIPException from fuelmenu.common.errors import BadIPException
from fuelmenu.common.modulehelper import ModuleHelper from fuelmenu.common.modulehelper import ModuleHelper
from fuelmenu.common.modulehelper import WidgetType from fuelmenu.common.modulehelper import WidgetType
from fuelmenu.common import network from fuelmenu.common import network
from fuelmenu.common import puppet
import fuelmenu.common.urwidwrapper as widget import fuelmenu.common.urwidwrapper as widget
from fuelmenu.common import utils from fuelmenu.common import utils
import logging from fuelmenu import consts
import netaddr
import urwid
import urwid.raw_display
import urwid.web_display
log = logging.getLogger('fuelmenu.pxe_setup') log = logging.getLogger('fuelmenu.pxe_setup')
blank = urwid.Divider() blank = urwid.Divider()
@ -78,6 +86,10 @@ to advertise via DHCP to nodes",
self.load() self.load()
self.extdhcp = True self.extdhcp = True
self.screen = None 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): def check(self, args):
"""Validates all fields have valid values and some sanity checks.""" """Validates all fields have valid values and some sanity checks."""
@ -276,10 +288,110 @@ interface first.")
log.error("Check failed. Not applying") log.error("Check failed. Not applying")
log.error("%s" % (responses)) log.error("%s" % (responses))
return False return False
self.save(responses) self.save(responses)
if utils.is_post_deployment():
self.parent.apply_tasks.add(self.update_dhcp)
return True 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): def cancel(self, button):
ModuleHelper.cancel(self, button) ModuleHelper.cancel(self, button)
self.setNetworkDetails() self.setNetworkDetails()

View File

@ -306,7 +306,7 @@ class Interfaces(urwid.WidgetWrap):
try: try:
self.parent.refreshScreen() self.parent.refreshScreen()
result = puppet.puppetApply(puppetclasses) result = puppet.puppetApply(puppetclasses)
if result is False: if not result:
raise Exception("Puppet apply failed") raise Exception("Puppet apply failed")
ModuleHelper.getNetwork(self) ModuleHelper.getNetwork(self)
gateway = self.get_default_gateway_linux() 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): 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_execute.assert_called_once_with(self.command, stdin=self.input)
m_log.info.assert_called_once_with('Puppet start') m_log.info.assert_called_once_with('Puppet start')
self.assertFalse(m_log.error.called) self.assertFalse(m_log.error.called)

View File

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

View File

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