rebase cleanup

This commit is contained in:
Matthew Mosesohn 2013-09-25 15:24:06 +04:00
parent fd9e9c8848
commit 6041bf10c9
17 changed files with 0 additions and 2246 deletions

View File

View File

@ -1,42 +0,0 @@
import yaml
import ConfigParser
import collections
import os
try:
from collections import OrderedDict
except:
# python 2.6 or earlier use backport
from ordereddict import OrderedDict
class NailyFacterSettings():
def __init__(self):
pass
def read(self, infile='naily.facts.default'):
config = OrderedDict()
fd=open(infile, 'r')
lines = fd.readlines()
for line in lines:
key = line.split('=')[0]
value = line.split('=')[1]
config[key]=value
fd.close()
return config
def write(self, newvalues, prefix='mnbs_', defaultsfile='naily.facts.default', outfn='naily.facts'):
#Read outfn if it exists
if os.path.isfile(outfn):
config=self.read(outfn)
elif defaultsfile is not None:
#Get default config or start new
config=self.read(defaultsfile)
else:
config=OrderedDict()
#Insert newvalues with prefix into config
for key in newvalues.keys():
config["%s%s" % (prefix,key)]="%s\n" %newvalues[key]
#Write out new file
outfile = open(outfn, 'w')
for key in config.keys():
outfile.write("%s=%s" % (key, config[key]))
outfile.close()
return True

View File

@ -1,38 +0,0 @@
import netaddr
def inSameSubnet(ip1,ip2,netmask_or_cidr):
try:
cidr1=netaddr.IPNetwork("%s/%s" % (ip1,netmask_or_cidr))
cidr2=netaddr.IPNetwork("%s/%s" % (ip2,netmask_or_cidr))
return cidr1 == cidr2
except:
return False
def getCidr(ip, netmask):
try:
ipn = netaddr.IPNetwork("%s/%s" % (ip, netmask))
return str(ipn.cidr)
except:
return False
def getCidrSize(cidr):
try:
ipn = netaddr.IPNetwork(cidr)
return ipn.size
except:
return False
def getNetwork(ip, netmask):
#Return a list excluding ip and broadcast IPs
try:
ipn = netaddr.IPNetwork("%s/%s" % (ip, netmask))
ipn_list = list(ipn)
#Drop broadcast and network ip
ipn_list = ipn_list[1:-1]
#Drop ip
ipn_list[:] = [value for value in ipn_list if str(value) != ip]
return ipn_list
except:
return False

View File

@ -1,62 +0,0 @@
import subprocess
import sys
import logging
#Python 2.6 hack to add check_output command
if "check_output" not in dir( subprocess ): # duck punch it in!
def f(*popenargs, **kwargs):
if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.')
process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise Exception(retcode, cmd)
return output
subprocess.check_output = f
def puppetApply(classname, name=None, params=None):
'''Runs puppet apply -e "classname {'name': params}" '''
log = logging
log.basicConfig(filename='./fuelmenu.log',level=logging.DEBUG)
log.info("Puppet start")
#name should be a string
#params should be a dict
# command=["puppet","apply","-d","-v","--logdest","/tmp/puppet.log", "-e",'\'',classname,"{",'"%s":' % name]
# #Build params
# for key,value in params.items():
# command.extend([key,"=>",'"%s",' % value])
# command.append('{\'')
command=["puppet","apply","-d","-v","--logdest","/tmp/puppet.log",]
input=[classname,"{",'"%s":' % name]
#Build params
for key,value in params.items():
input.extend([key,"=>",'"%s",' % value])
input.append('}')
log.debug(' '.join(command))
log.debug(' '.join(input))
output=""
try:
#output = subprocess.check_output(command)
process = subprocess.Popen(command, stdout=subprocess.PIPE,
stdin=subprocess.PIPE, stderr=subprocess.PIPE)
output, errout = process.communicate(input=' '.join(input))[0]
#output = subprocess.check_output(command)
except Exception, e:
import traceback
log.error(traceback.print_exc())
log.error(e)
log.debug(output)
log.debug(e)
if "err:" in output:
log.error(e)
return False
else:
log.debug(output)
return True

View File

@ -1,13 +0,0 @@
import re
def replaceInFile(filename, orig, new):
lines=open(filename).readlines()
for lineno,line in enumerate(lines):
lines[lineno]=re.sub(orig, new, line)
f=open(filename, 'w')
print ''.join(lines)
f.write("".join(lines))
f.flush()
f.close()

View File

@ -1,86 +0,0 @@
import urwid
import urwid.raw_display
import urwid.web_display
def TextField(keyword, label, width, default_value=None, tooltip=None, toolbar=None, disabled=False):
"""Returns an Urwid Edit object"""
if not tooltip:
edit_obj = urwid.Edit(('important', label.ljust(width)), default_value)
else:
edit_obj = TextWithTip(('important', label.ljust(width)), default_value, tooltip, toolbar)
wrapped_obj = urwid.AttrWrap(edit_obj, 'editbx', 'editfc')
if disabled:
wrapped_obj = urwid.WidgetDisable(urwid.AttrWrap(edit_obj, 'important', 'editfc'))
#Add get_edit_text and set_edit_text to wrapped_obj so we can use later
wrapped_obj.set_edit_text = edit_obj.set_edit_text
wrapped_obj.get_edit_text = edit_obj.get_edit_text
return wrapped_obj
def ChoicesGroup(self, choices, default_value=None, fn=None):
"""Returns list of RadioButtons and a horizontal Urwid GridFlow with
radio choices on one line."""
rb_group = []
for txt in choices:
#if default_value == None:
# is_default = "first True"
#else:
# is_default = True if txt == default_value else False
is_default = True if txt == default_value else False
radio_button = urwid.AttrWrap(urwid.RadioButton(rb_group, txt,
is_default, on_state_change=fn, user_data=txt),
'buttn','buttnf')
#txt, is_default, on_state_change=self.radioSelect, user_data=txt), 'buttn','buttnf')
wrapped_choices = urwid.GridFlow(rb_group, 13, 3, 0, 'left')
#Bundle rb_group so we can use it later easily
wrapped_choices.rb_group=rb_group
#setattr(wrapped_choices.rb_group,
#wrapped_choices = urwid.Padding(urwid.GridFlow(rb_group, 13, 3, 0,
# 'left'), left=4, right=3, min_width=13)
return wrapped_choices
def TextLabel(text):
"""Returns an Urwid text object"""
return urwid.Text(text)
def HorizontalGroup(objects, cell_width, align="left"):
"""Returns a padded Urwid GridFlow object that is left aligned"""
return urwid.Padding(urwid.GridFlow(objects, cell_width, 1, 0, align),
left=0,right=0,min_width=61)
def Columns(objects):
"""Returns a padded Urwid Columns object that is left aligned.
Objects is a list of widgets. Widgets may be optionally specified
as a tuple with ('weight', weight, widget) or (width, widget).
Tuples without a widget have a weight of 1."""
return urwid.Padding(urwid.Columns(objects, 1),
left=0,right=0,min_width=61)
def Button(text, fn):
"""Returns a wrapped Button with reverse focus attribute"""
button = urwid.Button(text, fn)
return urwid.AttrMap(button, None, focus_map='reversed')
class TextWithTip(urwid.Edit):
def __init__(self, label, default_value=None, tooltip=None, toolbar=None):
#def __init__(self, keyword, label, width, default_value=None, tooltip=None, toolbar=None):
#super(TextWithTip, self).__init__("")
urwid.Edit.__init__(self, caption=label, edit_text=default_value)
self.tip = tooltip
self.toolbar = toolbar
#def keypress(self, size, key):
# key = super(TextWithTip, self).keypress(size, key)
# self.toolbar.set_text(self.tip)
# return key
def render(self, size, focus=False):
if focus:
self.toolbar.set_text(self.tip)
canv = super(TextWithTip, self).render(size, focus)
return canv
#def mouse_event(self, size, event, button, x, y, focus):
# self.toolbar.set_text(self.tip)
# (maxcol,) = size
# if button==1:
# return self.move_cursor_to_coords( (maxcol,), x, y )

View File

@ -1,249 +0,0 @@
import urwid
import urwid.raw_display
import urwid.web_display
import sys
import operator
import os
import sys
# set up logging
import logging
#logging.basicConfig(filename='./fuelmenu.log')
#logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(filename='./fuelmenu.log',level=logging.DEBUG)
log = logging.getLogger('fuelmenu.loader')
class Loader:
def __init__(self, parent):
self.modlist = []
self.choices = []
self.child = None
self.children = []
self.childpage = None
self.parent = parent
def load_modules(self, module_dir):
if not module_dir in sys.path:
sys.path.append(module_dir)
modules = [os.path.splitext(f)[0] for f in os.listdir(module_dir)
if f.endswith('.py')]
for module in modules:
log.info('loading module %s' % module)
try:
imported = __import__(module)
pass
#imported = process(module)
except ImportError as e:
log.error('module could not be imported: %s' % e)
continue
clsobj = getattr(imported, module, None)
modobj = clsobj(self.parent)
# add the module to the list
if modobj.visible:
self.modlist.append(modobj)
# sort modules
self.modlist.sort(key=operator.attrgetter('priority'))
for module in self.modlist:
self.choices.append(module.name)
return (self.modlist,self.choices)
version="3.2"
#choices= u"Status,Networking,OpenStack Setup,Terminal,Save & Quit".split(',')
class FuelSetup():
def __init__(self):
self.footer = None
self.frame = None
self.screen = None
self.defaultsettingsfile = "settings.yaml"
self.settingsfile = "newsettings.yaml"
self.main()
self.choices = []
def menu(self, title, choices):
body = [urwid.Text(title), urwid.Divider()]
for c in choices:
button = urwid.Button(c)
urwid.connect_signal(button, 'click', self.menu_chosen, c)
body.append(urwid.AttrMap(button, None, focus_map='reversed'))
return urwid.ListBox(urwid.SimpleListWalker(body))
#return urwid.ListBox(urwid.SimpleFocusListWalker(body))
def menu_chosen(self, button, choice):
size = self.screen.get_cols_rows()
self.screen.draw_screen(size, self.frame.render(size))
#Highlight menu item
#menulist=self.menuitems.original_widget
#log.info("%s" % self.menuitems)
#log.info("%s" % self.menuitems.contents())
for item in self.menuitems.body.contents:
try:
log.info("inside loop %s" % item.original_widget.get_label())
#self.footer.set_text("inside loop %s" % item.original_widget.get_label())
if item.original_widget.get_label() == choice:
self.footer.set_text("Found choice %s" % choice)
item.set_attr_map({ None: 'header'})
else:
item.set_attr_map({ None: None})
except Exception, e:
self.footer.set_text("%s" % item)
log.info("%s" % item)
log.error("%s" % e)
#continue
self.setChildScreen(name=choice)
def setChildScreen(self, name=None):
if name is None:
child = self.children[0]
else:
child = self.children[int(self.choices.index(name))]
self.childpage = child.screenUI()
self.childfill = urwid.Filler(self.childpage, 'top', 40)
self.childbox = urwid.BoxAdapter(self.childfill, 40)
self.cols = urwid.Columns([
('fixed', 20, urwid.Pile([
urwid.AttrMap(self.menubox, 'bright'),
urwid.Divider(" ")])),
('weight', 3, urwid.Pile([
urwid.Divider(" "),
self.childbox,
urwid.Divider(" ")]))
], 1)
self.listwalker[:] = [self.cols]
def refreshScreen(self):
size = self.screen.get_cols_rows()
self.screen.draw_screen(size, self.frame.render(size))
def refreshChildScreen(self, name):
child = self.children[int(self.choices.index(name))]
#Refresh child listwalker
child.listwalker[:]=child.listbox_content
#reassign childpage top level objects
self.childpage = urwid.ListBox(child.listwalker)
self.childfill = urwid.Filler(self.childpage, 'middle', 22)
self.childbox = urwid.BoxAdapter(self.childfill, 22)
self.cols = urwid.Columns([
('fixed', 20, urwid.Pile([
urwid.AttrMap(self.menubox, 'bright'),
urwid.Divider(" ")])),
('weight', 3, urwid.Pile([
urwid.Divider(" "),
self.childbox,
urwid.Divider(" ")]))
], 1)
#Refresh top level listwalker
#self.listwalker[:] = [self.cols]
def main(self):
text_header = (u"Fuel %s setup "
u"UP / DOWN / PAGE UP / PAGE DOWN scroll. F8 exits."
% version)
text_footer = (u"Status messages go here.")
blank = urwid.Divider()
#Top and bottom lines of frame
self.header = urwid.AttrWrap(urwid.Text(text_header), 'header')
self.footer = urwid.AttrWrap(urwid.Text(text_footer), 'footer')
#Prepare submodules
loader = Loader(self)
self.children, self.choices = loader.load_modules(module_dir="./modules")
if len(self.children) == 0:
import sys
sys.exit(1)
self.menuitems=self.menu(u'Menu', self.choices)
menufill = urwid.Filler(self.menuitems, 'top', 40)
self.menubox = urwid.BoxAdapter(menufill, 40)
child = self.children[0]
self.childpage = child.screenUI()
self.childfill = urwid.Filler(self.childpage, 'top', 22)
self.childbox = urwid.BoxAdapter(self.childfill, 22)
self.cols = urwid.Columns([
('fixed', 20, urwid.Pile([
urwid.AttrMap(self.menubox, 'bright'),
urwid.Divider(" ")])),
('weight', 3, urwid.Pile([
urwid.Divider(" "),
self.childbox,
urwid.Divider(" ")]))
], 1)
self.listwalker = urwid.SimpleListWalker([self.cols])
#self.listwalker = urwid.TreeWalker([self.cols])
self.listbox = urwid.ListBox(self.listwalker)
#listbox = urwid.ListBox(urwid.SimpleListWalker(listbox_content))
#frame = urwid.Frame(urwid.AttrWrap(cols, 'background'), header=header, footer=footer)
#frame = urwid.Frame(urwid.AttrWrap(cols, 'body'), header=header, footer=footer)
self.frame = urwid.Frame(urwid.AttrWrap(self.listbox, 'body'), header=self.header, footer=self.footer)
palette = [
('body','black','light gray', 'standout'),
('reverse','light gray','black'),
('header','white','dark red', 'bold'),
('important','dark blue','light gray',('standout','underline')),
('editfc','white', 'dark blue', 'bold'),
('editbx','light gray', 'dark blue'),
('editcp','black','light gray', 'standout'),
('bright','dark gray','light gray', ('bold','standout')),
('buttn','black','dark cyan'),
('buttnf','white','dark blue','bold'),
('light gray','white', 'light gray','bold'),
('red','dark red','light gray','bold'),
('black','black','black','bold'),
]
# use appropriate Screen class
if urwid.web_display.is_web_request():
self.screen = urwid.web_display.Screen()
else:
self.screen = urwid.raw_display.Screen()
def unhandled(key):
log.debug(key)
if key == 'f8':
raise urwid.ExitMainLoop()
if key == 'enter' and type(self.mainloop.widget) == urwid.Overlay:
log.debug("overlay enter key")
self.mainloop.widget = self.frame
self.mainloop= urwid.MainLoop(self.frame, palette, self.screen,
unhandled_input=unhandled)
self.mainloop.run()
def exit_program(self, button):
raise urwid.ExitMainLoop()
def setup():
urwid.web_display.set_preferences("Fuel Setup")
# try to handle short web requests quickly
if urwid.web_display.handle_short_request():
return
fm = FuelSetup()
if '__main__'==__name__ or urwid.web_display.is_web_request():
if urwid.VERSION < (1,1,0):
print "This program requires urwid 1.1.0 or greater."
setup()

View File

@ -1,42 +0,0 @@
import operator
import os
import sys
from .constants import *
from .module import Module
from .moduleset import ModuleSet
import ethtool
# set up logging
import logging
logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger('fuelmenu.loader')
class Loader:
def __init__(self):
self.modlist = []
def load_modules(self, module_dir):
if not module_dir in sys.path:
sys.path.append(module_dir)
modules = [os.path.splitext(f)[0] for f in os.listdir(module_dir)
if f.endswith('.py')]
for module in modules:
log.info('loading module %s', module)
try:
imported = process(module)
except ImportError as e:
log.error('module could not be imported: %s', e)
continue
# add the module to the list
self.modlist.append(module)
# sort modules
self.modlist.sort(key=operator.attrgetter('priority'))
return self.modlist

View File

@ -1,527 +0,0 @@
#!/usr/bin/env python
import urwid
import urwid.raw_display
import urwid.web_display
import logging
import sys
import re
import copy
import socket, struct
import netaddr
import dhcp_checker.api
sys.path.append("/home/mmosesohn/git/fuel/iso/fuelmenu")
from settings import *
from common import network, puppet, replace, nailyfactersettings, dialog
from common.urwidwrapper import *
log = logging.getLogger('fuelmenu.pxe_setup')
blank = urwid.Divider()
#Need to define fields in order so it will render correctly
#fields = ["hostname", "domain", "mgmt_if","dhcp_start","dhcp_end",
# "blank","ext_if","ext_dns"]
fields = ["static_label",
"ADMIN_NETWORK/static_start", "ADMIN_NETWORK/static_end",
"blank", "dynamic_label", "ADMIN_NETWORK/first",
"ADMIN_NETWORK/last"]
facter_translate = {
"ADMIN_NETWORK/interface" : "internal_interface",
#"ADMIN_NETWORK/ipaddr" : "internal_ipaddress",
"ADMIN_NETWORK/first" : "dhcp_pool_start",
"ADMIN_NETWORK/last" : "dhcp_pool_end",
"ADMIN_NETWORK/static_start" : "static_pool_start",
"ADMIN_NETWORK/static_end" : "static_pool_end",
}
mnbs_internal_ipaddress="10.20.0.2"
mnbs_internal_netmask="255.255.255.0"
mnbs_static_pool_start="10.20.0.130"
mnbs_static_pool_end="10.20.0.250"
mnbs_dhcp_pool_start="10.20.0.10"
mnbs_dhcp_pool_end="10.20.0.120"
mnbs_internal_interface="eth1"
DEFAULTS = {
#"ADMIN_NETWORK/interface" : { "label" : "Management Interface",
# "tooltip": "This is the INTERNAL network for provisioning",
# "value" : "eth0"},
"ADMIN_NETWORK/first" : { "label" : "DHCP Pool Start",
"tooltip": "Used for defining IPs for hosts and instance public addresses",
"value" : "10.0.0.130"},
"ADMIN_NETWORK/last" : { "label" : "DHCP Pool End",
"tooltip": "Used for defining IPs for hosts and instance public addresses",
"value" : "10.0.0.254"},
"static_label" : { "label" : "Static pool for installed nodes:",
"tooltip" : "",
"value" : "label"},
"ADMIN_NETWORK/static_start" : { "label" : "Static Pool Start",
"tooltip": "Static pool for installed nodes",
"value" : "10.0.0.10"},
"ADMIN_NETWORK/static_end": { "label" : "Static Pool End",
"tooltip": "Static pool for installed nodes",
"value" : "10.0.0.120"},
"dynamic_label" : { "label" : "DHCP pool for node discovery:",
"tooltip" : "",
"value" : "label"},
#"ADMIN_NETWORK/dynamic_start" : { "label" : "Static Pool Start",
# "tooltip": "DHCP pool for node discovery",
# "value" : "10.0.0.10"},
#"ADMIN_NETWORK/dynamic_end": { "label" : "Static Pool End",
# "tooltip": "DHCP pool for node discovery",
# "value" : "10.0.0.120"},
}
class cobblerconf(urwid.WidgetWrap):
def __init__(self, parent):
self.name="PXE Setup"
self.priority=20
self.visible=True
self.netsettings = dict()
self.deployment="pre"
self.getNetwork()
self.gateway=self.get_default_gateway_linux()
self.activeiface = sorted(self.netsettings.keys())[0]
self.extdhcp=True
self.parent = parent
self.oldsettings= self.load()
#self.screen = self.screenUI()
def check(self, args):
"""Validates that all fields have valid values and some sanity checks"""
self.parent.footer.set_text("Checking data...")
self.parent.refreshScreen()
#Get field information
responses=dict()
for index, fieldname in enumerate(fields):
if fieldname == "blank" or "label" in fieldname:
pass
else:
responses[fieldname]=self.edits[index].get_edit_text()
responses["ADMIN_NETWORK/interface"]=self.activeiface
###Validate each field
errors=[]
#ensure management interface is valid
if responses["ADMIN_NETWORK/interface"] not in self.netsettings.keys():
errors.append("Management interface not valid")
else:
self.parent.footer.set_text("Scanning for DHCP servers. Please wait...")
self.parent.refreshScreen()
###Start DHCP check on this interface
#dhcp_server_data=[{'server_id': '192.168.200.2', 'iface': 'eth2', 'yiaddr': '192.168.200.15', 'mac': '52:54:00:12:35:02', 'server_ip': '192.168.200.2', 'dport': 67, 'message': 'offer', 'gateway': '0.0.0.0'}]
dhcp_server_data=dhcp_checker.api.check_dhcp_on_eth(\
self.activeiface,timeout=5)
num_dhcp=len(dhcp_server_data)
if num_dhcp == 0:
log.debug("No DHCP servers found")
else:
#We have a problem and will report it, but permit it to continue
log.error("%s foreign DHCP server(s) found: %s" % (num_dhcp, dhcp_server_data))
#Build dialog elements
dhcp_info=[]
dhcp_info.append(urwid.Padding(\
urwid.Text(("header","!!! WARNING !!!"))\
,"center"))
dhcp_info.append(TextLabel("You have selected an interface that \
contains one or more DHCP servers. This will impact provisioning. You should \
disable these DHCP servers before you continue, or else deployment will \
likely fail."))
dhcp_info.append(TextLabel(""))
for index, dhcp_server in enumerate(dhcp_server_data):
dhcp_info.append(TextLabel("DHCP Server # %s:" % (index+1)))
dhcp_info.append(TextLabel("IP address: %-10s" % dhcp_server['server_ip']))
dhcp_info.append(TextLabel("MAC address: %-10s" % dhcp_server['mac']))
dhcp_info.append(TextLabel(""))
dialog.display_dialog(self,urwid.Pile(dhcp_info),"DHCP Servers Found on %s" \
% self.activeiface)
###Ensure pool start and end are on the same subnet as mgmt_if
#Ensure mgmt_if has an IP first
if len(self.netsettings[responses["ADMIN_NETWORK/interface"]]["addr"]) == 0:
errors.append("Go to Interfaces to configure management interface first.")
else:
#Ensure ADMIN_NETWORK/interface is not running DHCP
if self.netsettings[responses["ADMIN_NETWORK/interface"]]["bootproto"] == "dhcp":
errors.append("%s is running DHCP. Change it to static first."
% self.activeiface)
#Ensure Static Pool Start and Static Pool are valid IPs
try:
if netaddr.valid_ipv4(responses["ADMIN_NETWORK/static_start"]):
static_start=netaddr.IPAddress(responses["ADMIN_NETWORK/static_start"])
else:
raise Exception("")
except Exception, e:
errors.append("Not a valid IP address for Static Pool Start: %s"
% e)
#% responses["ADMIN_NETWORK/first"])
try:
if netaddr.valid_ipv4(responses["ADMIN_NETWORK/static_end"]):
static_end=netaddr.IPAddress(responses["ADMIN_NETWORK/static_end"])
else:
raise Exception("")
except:
errors.append("Not a valid IP address for Static Pool end: %s"
% responses["ADMIN_NETWORK/static_end"])
#Ensure DHCP Pool Start and DHCP Pool are valid IPs
try:
if netaddr.valid_ipv4(responses["ADMIN_NETWORK/first"]):
dhcp_start=netaddr.IPAddress(responses["ADMIN_NETWORK/first"])
else:
raise Exception("")
except Exception, e:
errors.append("Not a valid IP address for DHCP Pool Start: %s"
% e)
#% responses["ADMIN_NETWORK/first"])
try:
if netaddr.valid_ipv4(responses["ADMIN_NETWORK/last"]):
dhcp_end=netaddr.IPAddress(responses["ADMIN_NETWORK/last"])
else:
raise Exception("")
except:
errors.append("Not a valid IP address for DHCP Pool end: %s"
% responses["ADMIN_NETWORK/last"])
#Ensure pool start and end are in the same subnet of each other
netmask=self.netsettings[responses["ADMIN_NETWORK/interface"]]["netmask"]
if network.inSameSubnet(responses["ADMIN_NETWORK/first"],responses["ADMIN_NETWORK/last"],
netmask) is False:
errors.append("DHCP Pool start and end are not in the same subnet.")
#Ensure pool start and end are in the netmask of ADMIN_NETWORK/interface
mgmt_if_ipaddr=self.netsettings[responses["ADMIN_NETWORK/interface"]]["addr"]
if network.inSameSubnet(responses["ADMIN_NETWORK/first"],mgmt_if_ipaddr,
netmask) is False:
errors.append("DHCP Pool start does not match management network.")
if network.inSameSubnet(responses["ADMIN_NETWORK/last"],mgmt_if_ipaddr,
netmask) is False:
errors.append("DHCP Pool end is not in the same subnet as management interface.")
if len(errors) > 0:
self.parent.footer.set_text("Errors: %s First error: %s" % (len(errors), errors[0]))
return False
else:
self.parent.footer.set_text("No errors found.")
return responses
def apply(self, args):
responses = self.check(args)
if responses is False:
log.error("Check failed. Not applying")
log.error("%s" % (responses))
return False
#Always save even if "post"
self.save(responses)
#Need to decide if we are pre-deployment or post-deployment
if self.deployment == "post":
self.updateCobbler(responses)
services.restart("cobbler")
def updateCobbler(self, params):
patterns={
'cblr_server' : '^server: .*',
'cblr_next_server' : '^next_server: .*',
'mgmt_if' : '^interface=.*',
'domain' : '^domain=.*',
'server' : '^server=.*',
'dhcp-range' : '^dhcp-range=',
'dhcp-option' : '^dhcp-option=',
'pxe-service' : '^pxe-service=(^,)',
'dhcp-boot' : '^dhcp-boot=([^,],{3}),'
}
def cancel(self, button):
for index, fieldname in enumerate(fields):
if fieldname == "blank" or "label" in fieldname:
pass
else:
self.edits[index].set_edit_text(DEFAULTS[fieldname]['value'])
self.setNetworkDetails()
def load(self):
#Read in yaml
defaultsettings=Settings().read(self.parent.defaultsettingsfile)
oldsettings=defaultsettings
oldsettings.update(Settings().read(self.parent.settingsfile))
log.debug("Old settings %s" % oldsettings)
for setting in DEFAULTS.keys():
if "label" in setting:
continue
elif "/" in setting:
part1, part2 = setting.split("/")
DEFAULTS[setting]["value"] = oldsettings[part1][part2]
else:
DEFAULTS[setting]["value"] = oldsettings[setting]
if oldsettings["ADMIN_NETWORK"]["interface"] in self.netsettings.keys():
self.activeiface=oldsettings["ADMIN_NETWORK"]["interface"]
return oldsettings
def save(self, responses):
## Generic settings start ##
newsettings = dict()
for setting in responses.keys():
if "/" in setting:
part1, part2 = setting.split("/")
if not newsettings.has_key(part1):
#We may not touch all settings, so copy oldsettings first
newsettings[part1]=self.oldsettings[part1]
newsettings[part1][part2] = responses[setting]
else:
newsettings[setting] = responses[setting]
## Generic settings end ##
## Need to calculate and set cidr, netmask, size
newsettings['ADMIN_NETWORK']['netmask'] = \
self.netsettings[newsettings['ADMIN_NETWORK']['interface']]["netmask"]
newsettings['ADMIN_NETWORK']['cidr'] = network.getCidr(
self.netsettings[newsettings['ADMIN_NETWORK']['interface']]["addr"],
newsettings['ADMIN_NETWORK']['netmask'])
newsettings['ADMIN_NETWORK']['size']=network.getCidrSize(
newsettings['ADMIN_NETWORK']['cidr'])
log.debug(str(newsettings))
Settings().write(newsettings,defaultsfile=self.parent.settingsfile,
outfn="newsettings.yaml")
#Write naily.facts
factsettings=dict()
#for key in newsettings.keys():
log.debug(str(facter_translate))
log.debug(str(newsettings))
for key in facter_translate.keys():
factsettings[facter_translate[key]]=responses[key]
n=nailyfactersettings.NailyFacterSettings()
log.debug("Facts to write: %s" % factsettings)
n.write(factsettings)
#Set oldsettings to reflect new settings
self.oldsettings = newsettings
#Update DEFAULTS
for index, fieldname in enumerate(fields):
if fieldname != "blank" and "label" not in fieldname:
DEFAULTS[fieldname]['value']= responses[fieldname]
self.parent.footer.set_text("Changes saved successfully.")
def getNetwork(self):
"""Uses netifaces module to get addr, broadcast, netmask about
network interfaces"""
import netifaces
for iface in netifaces.interfaces():
if 'lo' in iface or 'vir' in iface:
#if 'lo' in iface or 'vir' in iface or 'vbox' in iface:
if iface != "virbr2-nic":
continue
try:
self.netsettings.update({iface: netifaces.ifaddresses(iface)[netifaces.AF_INET][0]})
self.netsettings[iface]["onboot"]="Yes"
except:
self.netsettings.update({iface: {"addr": "", "netmask": "",
"onboot": "no"}})
self.netsettings[iface]['mac'] = netifaces.ifaddresses(iface)[netifaces.AF_LINK][0]['addr']
#Set link state
try:
with open("/sys/class/net/%s/operstate" % iface) as f:
content = f.readlines()
self.netsettings[iface]["link"]=content[0].strip()
except:
self.netsettings[iface]["link"]="unknown"
#Change unknown link state to up if interface has an IP
if self.netsettings[iface]["link"] == "unknown":
if self.netsettings[iface]["addr"] != "":
self.netsettings[iface]["link"]="up"
#We can try to get bootproto from /etc/sysconfig/network-scripts/ifcfg-DEV
try:
with open("/etc/sysconfig/network-scripts/ifcfg-%s" % iface) as fh:
for line in fh:
if re.match("^BOOTPROTO=", line):
self.netsettings[iface]['bootproto']=line.split('=').strip()
break
except:
#Let's try checking for dhclient process running for this interface
if self.getDHCP(iface):
self.netsettings[iface]['bootproto']="dhcp"
else:
self.netsettings[iface]['bootproto']="none"
def getDHCP(self, iface):
"""Returns True if the interface has a dhclient process running"""
import subprocess
noout=open('/dev/null','w')
dhclient_running = subprocess.call(["pgrep","-f","dhclient.*%s" % (iface)],
stdout=noout, stderr=noout)
if dhclient_running == 0:
return True
else:
return False
def get_default_gateway_linux(self):
"""Read the default gateway directly from /proc."""
with open("/proc/net/route") as fh:
for line in fh:
fields = line.strip().split()
if fields[1] != '00000000' or not int(fields[3], 16) & 2:
continue
return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))
def radioSelectIface(self, current, state, user_data=None):
"""Update network details and display information"""
### This makes no sense, but urwid returns the previous object.
### The previous object has True state, which is wrong..
### Somewhere in current.group a RadioButton is set to True.
### Our quest is to find it.
for rb in current.group:
if rb.get_label() == current.get_label():
continue
if rb.base_widget.state == True:
self.activeiface = rb.base_widget.get_label()
break
self.gateway=self.get_default_gateway_linux()
self.getNetwork()
self.setNetworkDetails()
return
def radioSelectExtIf(self, current, state, user_data=None):
"""Update network details and display information"""
### This makes no sense, but urwid returns the previous object.
### The previous object has True state, which is wrong..
### Somewhere in current.group a RadioButton is set to True.
### Our quest is to find it.
for rb in current.group:
if rb.get_label() == current.get_label():
continue
if rb.base_widget.state == True:
if rb.base_widget.get_label() == "Yes":
self.extdhcp=True
else:
self.extdhcp=False
break
self.setExtIfaceFields(self.extdhcp)
return
def setNetworkDetails(self):
#condensed mode:
self.net_text1.set_text("Interface: %-13s Link: %s" % (self.activeiface, self.netsettings[self.activeiface]['link'].upper()))
self.net_text2.set_text("IP: %-15s MAC: %s" % (self.netsettings[self.activeiface]['addr'],
self.netsettings[self.activeiface]['mac']))
self.net_text3.set_text("Netmask: %-15s Gateway: %s" %
(self.netsettings[self.activeiface]['netmask'],
self.gateway))
log.debug("bootproto for %s: %s" % (self.netsettings[self.activeiface],
self.netsettings[self.activeiface]['bootproto']))
if self.netsettings[self.activeiface]['link'].upper() == "UP":
if self.netsettings[self.activeiface]['bootproto'] == "dhcp":
self.net_text4.set_text("WARNING: Cannot use interface running DHCP.\n\
Reconfigure as static in Network Setup screen.")
else:
self.net_text4.set_text("")
else:
self.net_text4.set_text("WARNING: This interface is DOWN. Configure it first.")
#Calculate and set Static/DHCP pool fields
#Max IPs = net size - 2 (master node + bcast)
net_ip_list = network.getNetwork(self.netsettings[self.activeiface]['addr'],
self.netsettings[self.activeiface]['netmask'])
try:
half = int(len(net_ip_list)/2)
static_pool = list(net_ip_list[:half])
dhcp_pool = list(net_ip_list[half:])
static_start = str(static_pool[0])
static_end = str(static_pool[-1])
dynamic_start = str(dhcp_pool[0])
dynamic_end = str(dhcp_pool[-1])
if self.net_text4.get_text() == "":
self.net_text4.set_text("This network configuration can support %s \
nodes." % len(dhcp_pool))
except:
#We don't have valid values, so mark all fields empty
static_start = ""
static_end = ""
dynamic_start = ""
dynamic_end = ""
for index, key in enumerate(fields):
if key == "ADMIN_NETWORK/static_start":
self.edits[index].set_edit_text(static_start)
elif key == "ADMIN_NETWORK/static_end":
self.edits[index].set_edit_text(static_end)
elif key == "ADMIN_NETWORK/first":
self.edits[index].set_edit_text(dynamic_start)
elif key == "ADMIN_NETWORK/last":
self.edits[index].set_edit_text(dynamic_end)
#def setExtIfaceFields(self, enabled=True):
# ###TODO: Define ext iface fields as disabled and then toggle
# pass
def screenUI(self):
#Define your text labels, text fields, and buttons first
text1 = urwid.Text("Settings for PXE booting of slave nodes.")
text2 = urwid.Text("Select the interface where PXE will run:")
#Current network settings
self.net_text1 = TextLabel("")
self.net_text2 = TextLabel("")
self.net_text3 = TextLabel("")
self.net_text4 = TextLabel("")
log.debug("Default iface %s" % self.activeiface)
self.net_choices = ChoicesGroup(self, sorted(self.netsettings.keys()),
default_value=self.activeiface,
fn=self.radioSelectIface)
self.edits = []
toolbar = self.parent.footer
for key in fields:
#for key, values in DEFAULTS.items():
#Example: key = hostname, label = Hostname, value = fuel-pm
if key == "blank":
self.edits.append(blank)
elif DEFAULTS[key]["value"] == "radio":
label = TextLabel(DEFAULTS[key]["label"])
choices = ChoicesGroup(self,["Yes", "No"],
default_value="Yes", fn=self.radioSelectExtIf)
self.edits.append(Columns([label,choices]))
elif DEFAULTS[key]["value"] == "label":
self.edits.append(TextLabel(DEFAULTS[key]["label"]))
else:
caption = DEFAULTS[key]["label"]
default = DEFAULTS[key]["value"]
tooltip = DEFAULTS[key]["tooltip"]
self.edits.append(TextField(key, caption, 23, default, tooltip, toolbar))
#Button to check
button_check = Button("Check", self.check)
#Button to revert to previously saved settings
button_cancel = Button("Cancel", self.cancel)
#Button to apply (and check again)
button_apply = Button("Apply", self.apply)
#Wrap buttons into Columns so it doesn't expand and look ugly
check_col = Columns([button_check, button_cancel,
button_apply,('weight',2,blank)])
self.listbox_content = [text1, blank, text2]
self.listbox_content.extend([self.net_choices, self.net_text1,
self.net_text2, self.net_text3,
self.net_text4, blank])
self.listbox_content.extend(self.edits)
self.listbox_content.append(blank)
self.listbox_content.append(check_col)
#Add listeners
#Build all of these into a list
#self.listbox_content = [ text1, blank, blank, edit1, edit2, \
# edit3, edit4, edit5, edit6, button_check ]
self.setNetworkDetails()
#Add everything into a ListBox and return it
self.listwalker=urwid.SimpleListWalker(self.listbox_content)
screen = urwid.ListBox(self.listwalker)
return screen

View File

@ -1,382 +0,0 @@
#!/usr/bin/env python
import urwid
import urwid.raw_display
import urwid.web_display
import logging
import sys
import re
import copy
import socket, struct
import netaddr
sys.path.append("/home/mmosesohn/git/fuel/iso/fuelmenu")
from settings import *
from common import network, puppet, replace, nailyfactersettings, dialog
from common.urwidwrapper import *
log = logging.getLogger('fuelmenu.mirrors')
blank = urwid.Divider()
#Need to define fields in order so it will render correctly
#fields = ["hostname", "domain", "mgmt_if","dhcp_start","dhcp_end",
# "blank","ext_if","ext_dns"]
fields = ["HOSTNAME", "DNS_DOMAIN", "DNS_SEARCH","DNS_UPSTREAM","blank", "TEST_DNS"]
DEFAULTS = {
"HOSTNAME" : { "label" : "Hostname",
"tooltip": "Hostname to use for Fuel master node",
"value" : "fuel"},
"DNS_UPSTREAM" : { "label" : "External DNS",
"tooltip": "DNS server(s) (comma separated) to handle DNS\
requests (example 8.8.8.8)",
"value" : "8.8.8.8"},
"DNS_DOMAIN" : { "label" : "Domain",
"tooltip": "Domain suffix to user for all nodes in your cluster",
"value" : "example.com"},
"DNS_SEARCH" : { "label" : "Search Domain",
"tooltip": "Domains to search when looking up DNS\
(space separated)",
"value" : "example.com"},
"TEST_DNS" : { "label" : "Hostname to test DNS:",
"value" : "www.google.com",
"tooltip": "DNS record to resolve to see if DNS is \
accessible",}
}
class dnsandhostname(urwid.WidgetWrap):
def __init__(self, parent):
self.name="DNS & Hostname"
self.priority=15
self.visible=True
self.netsettings = dict()
self.deployment="pre"
self.getNetwork()
self.gateway=self.get_default_gateway_linux()
self.extdhcp=True
self.parent = parent
self.oldsettings= self.load()
#self.screen = self.screenUI()
def check(self, args):
"""Validates that all fields have valid values and some sanity checks"""
self.parent.footer.set_text("Checking data...")
self.parent.refreshScreen()
#Get field information
responses=dict()
for index, fieldname in enumerate(fields):
if fieldname == "blank":
pass
else:
responses[fieldname]=self.edits[index].get_edit_text()
###Validate each field
errors=[]
#hostname must be under 60 chars
if len(responses["HOSTNAME"]) >= 60:
errors.append("Hostname must be under 60 chars.")
#hostname must not be empty
if len(responses["HOSTNAME"]) == 0:
errors.append("Hostname must not be empty.")
#hostname needs to have valid chars
if not re.match('[a-z0-9-]',responses["HOSTNAME"]):
errors.append("Hostname must contain only alphanumeric and hyphen.")
#domain must be under 180 chars
if len(responses["DNS_DOMAIN"]) >= 180:
errors.append("Domain must be under 180 chars.")
#domain must not be empty
if len(responses["DNS_DOMAIN"]) == 0:
errors.append("Domain must not be empty.")
#domain needs to have valid chars
if not re.match('[a-z0-9-.]',responses["DNS_DOMAIN"]):
errors.append("Domain must contain only alphanumeric, period and hyphen.")
#ensure external DNS is valid
if len(responses["DNS_UPSTREAM"]) == 0:
#We will allow empty if user doesn't need external networking
#and present a strongly worded warning
msg="If you continue without DNS, you may not be able to access \
external data necessary for installation needed for some OpenStack \
Releases."
diag=dialog.display_dialog(self,TextLabel(msg), "Empty DNS Warning")
else:
#external DNS must contain only numbers, periods, and commas
#TODO: More serious ip address checking
if not re.match('[0-9.,]',responses["DNS_UPSTREAM"]):
errors.append("External DNS must contain only IP addresses and commas.")
#ensure test DNS name isn't empty
if len(responses["TEST_DNS"]) == 0:
errors.append("Test DNS must not be empty.")
#Validate first IP address
try:
if netaddr.valid_ipv4(responses["DNS_UPSTREAM"].split(",")[0]):
DNS_UPSTREAM=responses["DNS_UPSTREAM"].split(",")[0]
else:
errors.append("Not a valid IP address for External DNS: %s"
% responses["DNS_UPSTREAM"])
#Try to resolve with first address
#Note: Python's internal resolver caches negative answers.
#Therefore, we should call dig externally to be sure.
import subprocess
noout=open('/dev/null','w')
dns_works = subprocess.call(["dig","+short","+time=3",
"+retries=1",responses["TEST_DNS"],
"@%s" % DNS_UPSTREAM],stdout=noout, stderr=noout)
if dns_works != 0:
errors.append("Domain Name server %s unable to resolve host."
% DNS_UPSTREAM)
#from twisted.names import client
#for nameserver in responses["ext_dns"].split(","):
# resolver = client.createResolver(servers=[(nameserver,53))
# if resolver.getHostByName('wikipedia.org')
except Exception, e:
errors.append(e)
errors.append("Not a valid IP address for External DNS: %s"
% responses["DNS_UPSTREAM"])
if len(errors) > 0:
self.parent.footer.set_text("Errors: %s First error: %s" % (len(errors), errors[0]))
return False
else:
self.parent.footer.set_text("No errors found.")
return responses
def apply(self, args):
responses = self.check(args)
if responses is False:
log.error("Check failed. Not applying")
log.error("%s" % (responses))
return False
self.save(responses)
#Apply hostname
expr='HOSTNAME=.*'
replace.replaceInFile("/etc/sysconfig/network",expr,"HOSTNAME=%s"
% (responses["HOSTNAME"]))
#Write dnsmasq upstream server
with open('/etc/dnsmasq.upstream','a') as f:
nameservers=responses['DNS_UPSTREAM'].replace(',',' ')
f.write("nameserver %s\n" % nameservers)
f.close()
###Future feature to apply post-deployment
#Need to decide if we are pre-deployment or post-deployment
#if self.deployment == "post":
# self.updateCobbler(responses)
# services.restart("cobbler")
# def updateCobbler(self, params):
# patterns={
# 'cblr_server' : '^server: .*',
# 'cblr_next_server' : '^next_server: .*',
# 'mgmt_if' : '^interface=.*',
# 'domain' : '^domain=.*',
# 'server' : '^server=.*',
# 'dhcp-range' : '^dhcp-range=',
# 'dhcp-option' : '^dhcp-option=',
# 'pxe-service' : '^pxe-service=(^,)',
# 'dhcp-boot' : '^dhcp-boot=([^,],{3}),'
# }
def cancel(self, button):
for index, fieldname in enumerate(fields):
if fieldname == "blank":
pass
else:
self.edits[index].set_edit_text(DEFAULTS[fieldname]['value'])
def load(self):
#Read in yaml
defaultsettings=Settings().read(self.parent.defaultsettingsfile)
oldsettings=defaultsettings
oldsettings.update(Settings().read(self.parent.settingsfile))
oldsettings=Settings().read(self.parent.settingsfile)
for setting in DEFAULTS.keys():
try:
if "/" in setting:
part1, part2 = setting.split("/")
DEFAULTS[setting]["value"] = oldsettings[part1][part2]
else:
DEFAULTS[setting]["value"] = oldsettings[setting]
except:
log.warning("No setting named %s found." % setting)
continue
#Read hostname if it's already set
try:
import os
oldsettings["HOSTNAME"]=os.uname()[1]
except:
log.warning("Unable to look up system hostname")
return oldsettings
def save(self, responses):
## Generic settings start ##
newsettings = dict()
for setting in responses.keys():
if "/" in setting:
part1, part2 = setting.split("/")
if not newsettings.has_key(part1):
#We may not touch all settings, so copy oldsettings first
newsettings[part1]=self.oldsettings[part1]
newsettings[part1][part2] = responses[setting]
else:
newsettings[setting] = responses[setting]
## Generic settings end ##
#log.debug(str(newsettings))
Settings().write(newsettings,defaultsfile=self.parent.settingsfile,
outfn="newsettings.yaml")
#Write naily.facts
factsettings=dict()
#log.debug(newsettings)
for key in newsettings.keys():
if key != "blank":
factsettings[key]=newsettings[key]
n=nailyfactersettings.NailyFacterSettings()
n.write(factsettings)
#Set oldsettings to reflect new settings
self.oldsettings = newsettings
#Update DEFAULTS
for index, fieldname in enumerate(fields):
if fieldname != "blank":
DEFAULTS[fieldname]['value']= newsettings[fieldname]
def getNetwork(self):
"""Uses netifaces module to get addr, broadcast, netmask about
network interfaces"""
import netifaces
for iface in netifaces.interfaces():
if 'lo' in iface or 'vir' in iface:
#if 'lo' in iface or 'vir' in iface or 'vbox' in iface:
if iface != "virbr2-nic":
continue
try:
self.netsettings.update({iface: netifaces.ifaddresses(iface)[netifaces.AF_INET][0]})
self.netsettings[iface]["onboot"]="Yes"
except:
self.netsettings.update({iface: {"addr": "", "netmask": "",
"onboot": "no"}})
self.netsettings[iface]['mac'] = netifaces.ifaddresses(iface)[netifaces.AF_LINK][0]['addr']
#Set link state
try:
with open("/sys/class/net/%s/operstate" % iface) as f:
content = f.readlines()
self.netsettings[iface]["link"]=content[0].strip()
except:
self.netsettings[iface]["link"]="unknown"
#Change unknown link state to up if interface has an IP
if self.netsettings[iface]["link"] == "unknown":
if self.netsettings[iface]["addr"] != "":
self.netsettings[iface]["link"]="up"
#We can try to get bootproto from /etc/sysconfig/network-scripts/ifcfg-DEV
try:
with open("/etc/sysconfig/network-scripts/ifcfg-%s" % iface) as fh:
for line in fh:
if re.match("^BOOTPROTO=", line):
self.netsettings[iface]['bootproto']=line.split('=').strip()
break
except:
#Let's try checking for dhclient process running for this interface
if self.getDHCP(iface):
self.netsettings[iface]['bootproto']="dhcp"
else:
self.netsettings[iface]['bootproto']="none"
def getDHCP(self, iface):
"""Returns True if the interface has a dhclient process running"""
import subprocess
noout=open('/dev/null','w')
dhclient_running = subprocess.call(["pgrep","-f","dhclient.*%s" % (iface)],
stdout=noout, stderr=noout)
def get_default_gateway_linux(self):
"""Read the default gateway directly from /proc."""
with open("/proc/net/route") as fh:
for line in fh:
fields = line.strip().split()
if fields[1] != '00000000' or not int(fields[3], 16) & 2:
continue
return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))
def radioSelectIface(self, current, state, user_data=None):
"""Update network details and display information"""
### This makes no sense, but urwid returns the previous object.
### The previous object has True state, which is wrong..
### Somewhere in current.group a RadioButton is set to True.
### Our quest is to find it.
for rb in current.group:
if rb.get_label() == current.get_label():
continue
if rb.base_widget.state == True:
self.activeiface = rb.base_widget.get_label()
break
self.gateway=self.get_default_gateway_linux()
self.getNetwork()
self.setNetworkDetails()
return
def screenUI(self):
#Define your text labels, text fields, and buttons first
text1 = urwid.Text("DNS and hostname setup")
text2 = urwid.Text("Note: Leave External DNS blank if you do not have"\
" Internet access.")
self.edits = []
toolbar = self.parent.footer
for key in fields:
#for key, values in DEFAULTS.items():
#Example: key = hostname, label = Hostname, value = fuel-pm
if key == "blank":
self.edits.append(blank)
elif DEFAULTS[key]["value"] == "radio":
label = TextLabel(DEFAULTS[key]["label"])
choices = ChoicesGroup(self,["Yes", "No"],
default_value="Yes", fn=self.radioSelectExtIf)
self.edits.append(Columns([label,choices]))
else:
caption = DEFAULTS[key]["label"]
default = DEFAULTS[key]["value"]
tooltip = DEFAULTS[key]["tooltip"]
self.edits.append(TextField(key, caption, 23, default, tooltip, toolbar))
#Button to check
button_check = Button("Check", self.check)
#Button to revert to previously saved settings
button_cancel = Button("Cancel", self.cancel)
#Button to apply (and check again)
button_apply = Button("Apply", self.apply)
#Wrap buttons into Columns so it doesn't expand and look ugly
check_col = Columns([button_check, button_cancel,
button_apply,('weight',2,blank)])
self.listbox_content = [text1,blank,text2, blank]
self.listbox_content.extend(self.edits)
self.listbox_content.append(blank)
self.listbox_content.append(check_col)
#Add listeners
#Build all of these into a list
#self.listbox_content = [ text1, blank, blank, edit1, edit2, \
# edit3, edit4, edit5, edit6, button_check ]
#Add everything into a ListBox and return it
self.listwalker=urwid.SimpleListWalker(self.listbox_content)
screen = urwid.ListBox(self.listwalker)
return screen

View File

@ -1,417 +0,0 @@
#!/usr/bin/env python
import urwid
import urwid.raw_display
import urwid.web_display
import logging
import sys
import copy
import socket, struct
import re
import netaddr
sys.path.append("/home/mmosesohn/git/fuel/iso/fuelmenu")
from settings import *
from common import network, puppet, replace, dialog
from common.urwidwrapper import *
blank = urwid.Divider()
#Need to define fields in order so it will render correctly
fields = ["blank", "ifname", "onboot", "bootproto", "ipaddr", "netmask", "gateway"]
DEFAULTS = {
"ifname" : { "label" : "Interface name:",
"tooltip": "Interface system identifier",
"value" : "locked"},
"onboot" : { "label" : "Enabled on boot:",
"tooltip": "",
"value" : "radio"},
"bootproto" : { "label" : "Configuration via DHCP:",
"tooltip": "",
"value" : "radio",
"choices": ["DHCP", "Static"]},
"ipaddr" : { "label" : "IP address:",
"tooltip": "Manual IP address (example 192.168.1.2)",
"value" : ""},
"netmask" : { "label" : "Netmask:",
"tooltip": "Manual netmask (example 255.255.255.0)",
"value" : "255.255.255.0"},
"gateway" : { "label" : "Default Gateway:",
"tooltip": "Manual gateway to access Internet (example 192.168.1.1)",
"value" : ""},
}
YAMLTREE = "cobbler_common"
class interfaces(urwid.WidgetWrap):
def __init__(self, parent):
self.name="Network Setup"
self.priority=5
self.visible=True
self.netsettings = dict()
logging.basicConfig(filename='./fuelmenu.log',level=logging.DEBUG)
self.log = logging
self.log.basicConfig(filename='./fuelmenu.log',level=logging.DEBUG)
self.log.info("init Interfaces")
self.getNetwork()
self.gateway=self.get_default_gateway_linux()
self.activeiface = sorted(self.netsettings.keys())[0]
self.extdhcp=True
self.parent = parent
self.screen = None
def check(self, args):
"""Validates that all fields have valid values and some sanity checks"""
#self.popup(msg="Test",buttons=None)
#self.popup(msg="Test",buttons=None)
#diag=dialog.display_dialog(self,TextLabel("Test"), "Test")
#Test pop up
#dd = popupdialog.PopUpDialog(self.screen)
#dd = dialogdisplay.PopUp(self.screen,"Test")
#dd.open_pop_up()
#dd = dialogdisplay.PopUpDialog("Test")
#Get field information
responses=dict()
self.parent.footer.set_text("Checking data...")
for index, fieldname in enumerate(fields):
if fieldname == "blank" or fieldname == "ifname":
pass
elif fieldname == "bootproto":
rb_group = self.edits[index].rb_group
if rb_group[0].state:
responses["bootproto"]="dhcp"
else:
responses["bootproto"]="none"
elif fieldname == "onboot":
rb_group = self.edits[index].rb_group
if rb_group[0].state:
responses["onboot"]="yes"
else:
responses["onboot"]="no"
else:
responses[fieldname]=self.edits[index].get_edit_text()
###Validate each field
errors=[]
#Perform checks only if enabled
if responses["onboot"] == "no":
return responses
#No checks yet for DHCP, just return
if responses["bootproto"] == "dhcp":
return responses
#Check ipaddr, netmask, gateway only if static
if responses["bootproto"] == "none":
try:
if netaddr.valid_ipv4(responses["ipaddr"]):
ipaddr=netaddr.IPAddress(responses["ipaddr"])
else:
raise Exception("")
except:
errors.append("Not a valid IP address: %s" % responses["ipaddr"])
try:
if netaddr.valid_ipv4(responses["netmask"]):
netmask=netaddr.IPAddress(responses["netmask"])
if netmask.is_netmask is False:
raise Exception("")
else:
raise Exception("")
except:
errors.append("Not a valid netmask: %s" % responses["netmask"])
try:
if len(responses["gateway"]) > 0:
gateway=netaddr.IPAddress(responses["netmask"])
#Check if gateway is valid
if gateway.valid_ipv4 is False:
raise Exception("Gateway IP address is not valid")
#Check if gateway is in same subnet
if network.inSameSubnet(responses["ipaddr"],responses["gateway"],
responses["netmask"]) is False:
raise Exception("Gateway IP address is not in the same subnet as\
IP address")
except Exception, e:
errors.append(e)
if len(errors) > 0:
self.parent.footer.set_text("Errors: %s First error: %s" % (len(errors), errors[0]))
return False
else:
self.parent.footer.set_text("No errors found.")
return responses
def apply(self, args):
responses = self.check(args)
if responses is False:
self.log.error("Check failed. Not applying")
self.parent.footer.set_text("Check failed. Not applying.")
self.log.error("%s" % (responses))
return False
self.parent.footer.set_text("Applying changes...")
puppetclass="l23network::l3::ifconfig"
if responses["onboot"].lower() == "no":
params={"ipaddr": "none"}
elif responses["bootproto"] == "dhcp":
params={"ipaddr": "dhcp"}
else:
params={"ipaddr": responses["ipaddr"],
"netmask": responses["netmask"]}
if len(responses["gateway"]) > 1:
params["gateway"]=responses["gateway"]
self.log.info("Puppet data: %s %s %s" % (puppetclass, self.activeiface, params))
try:
self.parent.refreshScreen()
puppet.puppetApply(puppetclass,self.activeiface, params)
except Exception, e:
self.log.error(e)
self.parent.footer.set_text("Error applying changes. Check logs for details.")
self.getNetwork()
self.setNetworkDetails()
return False
self.parent.footer.set_text("Changes successfully applied.")
self.getNetwork()
self.setNetworkDetails()
return True
#leftover from network. we let puppet save everything
def save(self, args):
newsettings = dict()
newsettings['common'] = { YAMLTREE : { "domain" : DEFAULTS['domain']['value']}}
for key, widget in self.edits.items():
text = widget.original_widget.get_edit_text()
newsettings['common'][YAMLTREE][key] = text
log.warning(str(newsettings))
Settings().write(newsettings, tree=YAMLTREE)
logging.warning('And this, too')
def getNetwork(self):
"""Uses netifaces module to get addr, broadcast, netmask about
network interfaces"""
import netifaces
for iface in netifaces.interfaces():
if 'lo' in iface or 'vir' in iface:
#if 'lo' in iface or 'vir' in iface or 'vbox' in iface:
if iface != "virbr2-nic":
continue
try:
self.netsettings.update({iface: netifaces.ifaddresses(iface)[netifaces.AF_INET][0]})
self.netsettings[iface]["onboot"]="Yes"
except:
#Interface is down, so mark it onboot=no
self.netsettings.update({iface: {"addr": "", "netmask": "",
"onboot": "no"}})
self.netsettings[iface]['mac'] = netifaces.ifaddresses(iface)[netifaces.AF_LINK][0]['addr']
#Set link state
try:
with open("/sys/class/net/%s/operstate" % iface) as f:
content = f.readlines()
self.netsettings[iface]["link"]=content[0].strip()
except:
self.netsettings[iface]["link"]="unknown"
#Change unknown link state to up if interface has an IP
if self.netsettings[iface]["link"] == "unknown":
if self.netsettings[iface]["addr"] != "":
self.netsettings[iface]["link"]="up"
#We can try to get bootproto from /etc/sysconfig/network-scripts/ifcfg-DEV
#default to static
self.netsettings[iface]['bootproto']="none"
try:
with open("/etc/sysconfig/network-scripts/ifcfg-%s" % iface) as fh:
for line in fh:
if re.match("^BOOTPROTO=", line):
self.netsettings[iface]['bootproto']=line.split('=').strip()
break
except:
#Let's try checking for dhclient process running for this interface
if self.getDHCP(iface):
self.netsettings[iface]['bootproto']="dhcp"
else:
self.netsettings[iface]['bootproto']="none"
def getDHCP(self, iface):
"""Returns True if the interface has a dhclient process running"""
import subprocess
noout=open('/dev/null','w')
dhclient_running = subprocess.call(["pgrep","-f","dhclient.*%s" % (iface)],
stdout=noout, stderr=noout)
#self.log.info("Interface %s: %s" % (iface, dhclient_running))
if dhclient_running != 0:
return False
else:
return True
def get_default_gateway_linux(self):
"""Read the default gateway directly from /proc."""
with open("/proc/net/route") as fh:
for line in fh:
fields = line.strip().split()
if fields[1] != '00000000' or not int(fields[3], 16) & 2:
continue
return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))
def radioSelectIface(self, current, state, user_data=None):
"""Update network details and display information"""
### This makes no sense, but urwid returns the previous object.
### The previous object has True state, which is wrong..
### Somewhere in current.group a RadioButton is set to True.
### Our quest is to find it.
for rb in current.group:
if rb.get_label() == current.get_label():
continue
if rb.base_widget.state == True:
self.activeiface = rb.base_widget.get_label()
break
self.gateway=self.get_default_gateway_linux()
self.getNetwork()
self.setNetworkDetails()
return
def radioSelectExtIf(self, current, state, user_data=None):
"""Update network details and display information"""
### This makes no sense, but urwid returns the previous object.
### The previous object has True state, which is wrong..
### Somewhere in current.group a RadioButton is set to True.
### Our quest is to find it.
for rb in current.group:
if rb.get_label() == current.get_label():
continue
if rb.base_widget.state == True:
if rb.base_widget.get_label() == "Yes":
self.extdhcp=True
else:
self.extdhcp=False
break
self.setExtIfaceFields(self.extdhcp)
return
def setNetworkDetails(self):
#condensed mode:
self.net_text1.set_text("Interface: %-13s Link: %s" % (self.activeiface, self.netsettings[self.activeiface]['link'].upper()))
self.net_text2.set_text("IP: %-15s MAC: %s" % (self.netsettings[self.activeiface]['addr'],
self.netsettings[self.activeiface]['mac']))
self.net_text3.set_text("Netmask: %-15s Gateway: %s" %
(self.netsettings[self.activeiface]['netmask'],
self.gateway))
# #Old spread out method
# self.net_text1.set_text("Current network settings for %s" % self.activeiface)
# self.net_text2.set_text("MAC address: %s" % self.netsettings[self.activeiface]['mac'])
# self.net_text3.set_text("IP address: %s" % self.netsettings[self.activeiface]['addr'])
# self.net_text4.set_text("Netmask: %s" % self.netsettings[self.activeiface]['netmask'])
# self.net_text5.set_text("Default gateway: %s" % (self.gateway))
#
#Set text fields to current netsettings
for index, fieldname in enumerate(fields):
if fieldname == "ifname":
self.edits[index].base_widget.set_edit_text(self.activeiface)
elif fieldname == "bootproto":
rb_group = self.edits[index].rb_group
for rb in rb_group:
if self.netsettings[self.activeiface]["bootproto"].lower() == "dhcp":
rb_group[0].set_state(True)
rb_group[1].set_state(False)
else:
rb_group[0].set_state(False)
rb_group[1].set_state(True)
elif fieldname == "onboot":
rb_group = self.edits[index].rb_group
for rb in rb_group:
if self.netsettings[self.activeiface]["onboot"].lower() == "yes":
rb_group[0].set_state(True)
rb_group[1].set_state(False)
else:
rb_group[0].set_state(False)
rb_group[1].set_state(True)
elif fieldname == "ipaddr":
self.edits[index].set_edit_text(self.netsettings[self.activeiface]['addr'])
elif fieldname == "netmask":
self.edits[index].set_edit_text(self.netsettings[self.activeiface]['netmask'])
elif fieldname == "gateway":
#This is gateway for iface only if self.gateway is in same subnet
if network.inSameSubnet(self.netsettings[self.activeiface]['addr'],
self.gateway,
self.netsettings[self.activeiface]['netmask']):
self.edits[index].set_edit_text(self.gateway)
else:
self.edits[index].set_edit_text("")
def setExtIfaceFields(self, enabled=True):
###TODO: Define ext iface fields as disabled and then toggle
pass
def screenUI(self):
#Define your text labels, text fields, and buttons first
text1 = TextLabel("Network interface setup")
#Current network settings
self.net_text1 = TextLabel("")
self.net_text2 = TextLabel("")
self.net_text3 = TextLabel("")
self.net_choices = ChoicesGroup(self, sorted(self.netsettings.keys()),
default_value=self.activeiface, fn=self.radioSelectIface)
self.edits = []
toolbar = self.parent.footer
for key in fields:
#Example: key = hostname, label = Hostname, value = fuel
if key == "blank":
self.edits.append(blank)
elif DEFAULTS[key]["value"] == "radio":
label = TextLabel(DEFAULTS[key]["label"])
if DEFAULTS[key].has_key("choices"):
choices_list = DEFAULTS[key]["choices"]
else:
choices_list = ["Yes", "No"]
choices = ChoicesGroup(self,choices_list,
default_value="Yes", fn=self.radioSelectExtIf)
columns=Columns([('weight',2,label),('weight',3,choices)])
#Attach choices rb_group so we can use it later
columns.rb_group = choices.rb_group
self.edits.append(columns)
else:
caption = DEFAULTS[key]["label"]
default = DEFAULTS[key]["value"]
tooltip = DEFAULTS[key]["tooltip"]
disabled = True if key == "ifname" else False
self.edits.append(TextField(key, caption, 23, default, tooltip,
toolbar, disabled=disabled))
#Button to check
button_check = Button("Check", self.check)
#Button to apply (and check again)
button_apply = Button("Apply", self.apply)
#Wrap buttons into Columns so it doesn't expand and look ugly
check_col = Columns([button_check, button_apply,('weight',3,blank)])
self.listbox_content = [text1, blank]
self.listbox_content.extend([self.net_choices, self.net_text1,
self.net_text2, self.net_text3,
blank])
self.listbox_content.extend(self.edits)
self.listbox_content.append(blank)
self.listbox_content.append(check_col)
#Add listeners
#Build all of these into a list
#self.listbox_content = [ text1, blank, blank, edit1, edit2, \
# edit3, edit4, edit5, edit6, button_check ]
#Add everything into a ListBox and return it
self.listwalker=urwid.SimpleListWalker(self.listbox_content)
screen = urwid.ListBox(self.listwalker)
self.setNetworkDetails()
self.screen = screen
return screen

View File

@ -1,123 +0,0 @@
#!/usr/bin/env python
import urwid
import urwid.raw_display
import urwid.web_display
import logging
import sys
import copy
sys.path.append("/home/mmosesohn/git/fuel/iso/fuelmenu")
from settings import *
from common.urwidwrapper import *
log = logging.getLogger('fuelmenu.mirrors')
log.info("test")
blank = urwid.Divider()
DEFAULTS = {
"custom_mirror" : "http://mirror.your-company-name.com/",
"parent_proxy" : "",
"port" : "3128"
}
class mirrors(urwid.WidgetWrap):
def __init__(self, parent):
self.name="Repo Mirrors"
self.priority=25
self.visible=False
self.parent = parent
self.listbox_content = []
self.settings = copy.deepcopy(DEFAULTS)
self.screen = self.screenUI()
def apply(self, args):
if not self.check(args):
log.error("Check failed. Not applying")
return False
conf = Settings()
conf.write(module="mirrors",values=self.settings)
def check(self, args):
log = logging.getLogger('fuelmenu.mirrors')
customurl = self.edit1.get_edit_text()
self.parent.footer.set_text("Checking %s" % customurl)
log.info("Checking %s" % customurl)
if self.repochoice == "Defult":
self.parent.footer.set_text("")
pass
else:
#Ensure host can connect
import subprocess
reachable = subprocess.call(["curl","-o","/dev/null","--silent","--head","--write-out","'%{http_code}\n'",customurl])
error_msg = None
if reachable == 0:
pass
elif reachable == 1 or reachable == 3:
error_msg = u"Unrecognized protocol. Did you spell it right?"
elif reachable == 6:
error_msg = u"Couldn't resolve host."
elif reachable == 7:
error_msg = u"Couldn't connect to host."
elif reachable == 6:
error_msg = u"Couldn't resolve host."
if error_msg:
self.parent.footer.set_text("Could not reach custom mirror. Error: %s" % (error_msg))
return False
self.parent.footer.set_text("Reached custom mirror!")
#Ensure valid page with 2XX or 3XX return code
status_code = subprocess.check_output(["curl","-o","/dev/null","--silent","--head","--write-out","'\%{http_code}'",customurl])
import re
regexp = re.compile(r'[23]\d\d')
if regexp.search(status_code) is not None:
error_msg = "URL not reachable on server. Error %s" % status_code
log.error("Could not reach custom url %s. Error code: %s" % (customurl, reachable))
self.parent.footer.set_text("Could not reach custom url %s. Error code: %s" % (customurl, reachable))
return False
self.parent.footer.set_text("Repo mirror OK!")
return True
def radioSelect(self, current, state, user_data=None):
for rb in current.group:
if rb.get_label() == current.get_label():
continue
if rb.base_widget.state == True:
self.repochoice = rb.base_widget.get_label()
break
#def keypress(self, size, key):
# self.parent.footer.set_text("keypress")
#def displayTooltip(self, obj):
# focus = obj.get_focus()[0].content
# self.parent.footer.set_text(focus.get_label())
def screenUI(self):
#Define your text labels, text fields, and buttons first
text1 = TextLabel(u"Choose repo mirrors to use.\n"
u"Note: Refer to Fuel documentation on how to set up a custom mirror.")
choice_list = [u"Default", u"Custom"]
self.choices = ChoicesGroup(self, choice_list)
self.repochoice = "Default"
#self.edit1 = TextField("custom_mirror", "Custom URL:", 15, DEFAULTS["custom_mirror"], "URL goes here", self.parent.footer)
self.edit1 = TextField("custom_mirror", "Custom URL:", 15, DEFAULTS["custom_mirror"], "URL goes here", self.parent.footer)
self.edit2 = TextField("parent_proxy", "Squid parent proxy:", 20, DEFAULTS["parent_proxy"], "Squid proxy URL (include http://)", self.parent.footer)
self.edit3 = TextField("port", "Port:", 5, DEFAULTS["parent_proxy"], "Squid Proxy port (usually 3128)", self.parent.footer)
self.proxyedits = Columns([('weight', 3, self.edit2), self.edit3])
#Button to check
button_check = Button("Check", self.check)
#Button to apply (and check again)
button_apply = Button("Apply", self.apply)
#Wrap into Columns so it doesn't expand and look ugly
check_col = Columns([button_check, button_apply,('weight',7,blank)])
#Build all of these into a list
self.listbox_content = [ text1, blank, blank, self.choices, blank, self.edit1, blank, self.proxyedits, blank, blank, check_col ]
#Add everything into a ListBox and return it
walker = urwid.SimpleListWalker(self.listbox_content)
#urwid.connect_signal(walker, 'modified', self.displayTooltip)
self.myscreen = urwid.ListBox(walker)
return self.myscreen

View File

@ -1,39 +0,0 @@
#!/usr/bin/env python
import urwid
import urwid.raw_display
import urwid.web_display
from common.urwidwrapper import *
import subprocess
blank = urwid.Divider()
class shell():
def __init__(self, parent):
self.name="Shell Login"
self.priority=99
self.visible=True
self.parent=parent
#self.screen = self.screenUI()
def check(self):
#TODO: Ensure all params are filled out and sensible
return True
def start_shell(self, args):
self.parent.mainloop.screen.stop()
message="Type exit to return to the main UI."
subprocess.call("clear ; echo '%s';echo; bash" % message, shell=True)
self.parent.mainloop.screen.start()
def screenUI(self):
#Define your text labels, text fields, and buttons first
text1 = urwid.Text("Press the button below to enter a shell login.")
login_button = Button("Shell Login",self.start_shell)
#Build all of these into a list
listbox_content = [ text1, blank, login_button ]
#Add everything into a ListBox and return it
screen = urwid.ListBox(urwid.SimpleListWalker(listbox_content))
return screen

View File

@ -1,102 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import urwid
import urwid.raw_display
import urwid.web_display
from common.urwidwrapper import *
blank = urwid.Divider()
class welcome():
def __init__(self, parent):
self.name="Welcome"
self.priority=1
self.visible=False
self.screen = self.screenUI()
def check(self):
#TODO: Ensure all params are filled out and sensible
return True
def screenUI(self):
#Define your text labels, text fields, and buttons first
text1 = urwid.Text("Welcome to Fuel! Use the menu on the left")
fuellogo_huge=[
[('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY')],
[('light gray','YYYY'),('red','YYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYY'),('red','YYYY'),('light gray','YYYYYYYYYYYY'),('red','YYYY'),('light gray','YYYYYYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYY'),('red','YYYY'),('light gray','YYYYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYY'),('light gray','YYYY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYYYY'),('light gray','YY')],
[('light gray','YY'),('red','YYYYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYYYYYYYYYY'),('light gray','YYYYYYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYYYY'),('light gray','YY')],
[('light gray','YYYY'),('red','YYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'),('red','YYYYYYYYYYYY'),('light gray','YYYYYYYYYYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYY'),('light gray','YYYYYYYY'),('red','YYYYYYYYYYYYYYYYYYYYYY'),('light gray','YYYY')],
[('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY')],
[('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY')],
[('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY')],
[('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY')],
[('light gray','YYYYYY'),('black','YYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYY'),('black','YYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'),('black','YYYYYY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYYYY')],
[('light gray','YYYY'),('black','YY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYYYY'),('black','YY'),('light gray','YYYYYYYYYYYYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYYYY')],
[('light gray','YY'),('black','YYYYYY'),('light gray','YYYY'),('black','YYYY'),('light gray','YYYY'),('black','YYYY'),('light gray','YYYYYYYYYY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YY'),('black','YYYYYY'),('light gray','YYYYYY'),('black','YYYY'),('light gray','YYYY'),('black','YYYYYY'),('light gray','YYYY'),('black','YY'),('light gray','YYYYYY'),('black','YYYYYY'),('light gray','YY'),('black','YYYYYY'),('light gray','YYYYYY'),('black','YYYY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY')],
[('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YYYYYYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY')],
[('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YYYYYYYY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYYYY'),('black','YYYYYY'),('light gray','YY'),('black','YY'),('light gray','YYYYYY'),('black','YYYY'),('light gray','YYYYYY')],
[('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYYYYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY')],
[('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYYYYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYYYY'),('black','YY'),('light gray','YY'),('black','YY'),('light gray','YYYY')],
[('light gray','YYYY'),('black','YY'),('light gray','YYYYYY'),('black','YYYY'),('light gray','YYYY'),('black','YY'),('light gray','YYYYYYYYYYYYYY'),('black','YYYYYY'),('light gray','YYYY'),('black','YYYYYY'),('light gray','YYYYYY'),('black','YYYYYY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY'),('black','YYYYYY'),('light gray','YYYYYY'),('black','YY'),('light gray','YYYY'),('black','YYYYYY'),('light gray','YYYY'),('black','YYYY'),('light gray','YY'),('black','YY'),('light gray','YYYY'),('black','YY'),('light gray','YY')],
[('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY')],
[('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'),('black','YY'),('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY')],
[('light gray','YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY')],
]
fuellogo_small=[
[('red',u'±ÛÛÛÛÛÛÛÛÛÛ± ±ÛÛ± ±ÛÛ± ±ÛÛÛÛÛÛÛÛÛ± ±ÛÛ± TM')],
[('red',u'Û²²²²²²²²²²Û Û²²² Û²²² Û²²²²²²²²²² Û²²²')],
[('red',u'Û²²²²²²²²²²° Û²²² Û²²² Û²²²²²²²²²± Û²²²')],
#[('red',u'Û²²² Û²²² Û²²² Û²²² Û²²²')],
#[('red',u'Û²²² Û²²² Û²²² Û²²² Û²²²')],
[('red',u'Û²²² Û²²² Û²²² Û²²² Û²²²')],
[('red',u'Û²²² Û²²² Û²²² Û²²² Û²²²')],
[('red',u'Û²²²ÛÛÛÛÛ Û²²² Û²²² Û²²²ÛÛÛÛÛ Û²²²')],
[('red',u'Û²²²²²²²² Û²²² Û²²² Û²²²²²²²² Û²²²')],
#[('red',u'Û²²² Û²²² Û²²² Û²²² Û²²²')],
#[('red',u'Û²²² Û²²² Û²²² Û²²² Û²²²')],
[('red',u'Û²²² Û²²² Û²²² Û²²² Û²²²')],
[('red',u'Û²²² Û²²²Û Û²²²² Û²²² Û²²²')],
[('red',u'Û²²² ±²²²²ÛÛÛ²²²²° Û²²²ÛÛÛÛÛÛ° Û²²²ÛÛÛÛÛÛÛ°')],
[('red',u'Û²²² ²²²²²²²²²²² Û²²²²²²²²²Û Û²²²²²²²²²²Û')],
[('red',u'±²²° °²²²²²²²° ±²²²²²²²²²° ±²²²²²²²²²²°')],
#[''],
#[''],
[('light gray',u' ÛÛ ÛÛÛ ÛÛÛ Û R')],
[('light gray',u' Û Û Û Û Û Û ')],
[('light gray',u'ÛÛÛ ÛÛ ÛÛÛ Û Û ÛÛÛ ÛÛÛÛ ÛÛÛÛ Û ÛÛÛ ÛÛ ÛÛ Û Û')],
[('light gray',u' Û Û Û Û Û Û Û Û Û Û Û Û ÛÛ Û Û Û Û Û')],
[('light gray',u' Û Û Û Û Û Û Û Û ÛÛÛÛ Û Û Û Û ÛÛÛ Û ÛÛ')],
[('light gray',u' Û Û Û Û Û Û Û Û Û Û Û Û Û Û Û Û Û Û')],
[('light gray',u' Û ÛÛ Û ÛÛÛ ÛÛÛ ÛÛÛÛ Û Û ÛÛÛ ÛÛ ÛÛÛ ÛÛ Û Û')],
[('light gray',u' Û')],
[('light gray',u' Û')],
]
logotexts=[]
for line in fuellogo_small:
logotexts.append(TextLabel(line))
#Build all of these into a list
listbox_content = [ text1 ] + logotexts
#Add everything into a ListBox and return it
screen = urwid.ListBox(urwid.SimpleListWalker(listbox_content))
return screen

View File

@ -1,7 +0,0 @@
mnbs_internal_ipaddress=10.20.0.2
mnbs_internal_netmask=255.255.255.0
mnbs_static_pool_start=10.20.0.130
mnbs_static_pool_end=10.20.0.250
mnbs_dhcp_pool_start=10.20.0.10
mnbs_dhcp_pool_end=10.20.0.120
mnbs_internal_interface=eth1

View File

@ -1,102 +0,0 @@
import yaml
import collections
try:
from collections import OrderedDict
except:
# python 2.6 or earlier use backport
from ordereddict import OrderedDict
def construct_ordered_mapping(self, node, deep=False):
if not isinstance(node, yaml.MappingNode):
raise ConstructorError(None, None,
"expected a mapping node, but found %s" % node.id,
node.start_mark)
mapping = OrderedDict()
for key_node, value_node in node.value:
key = self.construct_object(key_node, deep=deep)
if not isinstance(key, collections.Hashable):
raise ConstructorError("while constructing a mapping", node.start_mark,
"found unhashable key", key_node.start_mark)
value = self.construct_object(value_node, deep=deep)
mapping[key] = value
return mapping
yaml.constructor.BaseConstructor.construct_mapping = construct_ordered_mapping
def construct_yaml_map_with_ordered_dict(self, node):
data = OrderedDict()
yield data
value = self.construct_mapping(node)
data.update(value)
yaml.constructor.Constructor.add_constructor(
'tag:yaml.org,2002:map',
construct_yaml_map_with_ordered_dict)
def represent_ordered_mapping(self, tag, mapping, flow_style=None):
value = []
node = yaml.MappingNode(tag, value, flow_style=flow_style)
if self.alias_key is not None:
self.represented_objects[self.alias_key] = node
best_style = True
if hasattr(mapping, 'items'):
mapping = list(mapping.items())
for item_key, item_value in mapping:
node_key = self.represent_data(item_key)
node_value = self.represent_data(item_value)
if not (isinstance(node_key, yaml.ScalarNode) and not node_key.style):
best_style = False
if not (isinstance(node_value, yaml.ScalarNode) and not node_value.style):
best_style = False
value.append((node_key, node_value))
if flow_style is None:
if self.default_flow_style is not None:
node.flow_style = self.default_flow_style
else:
node.flow_style = best_style
return node
yaml.representer.BaseRepresenter.represent_mapping = represent_ordered_mapping
yaml.representer.Representer.add_representer(OrderedDict,
yaml.representer.SafeRepresenter.represent_dict)
class Settings():
def __init__(self):
pass
def read(self, yamlfile):
try:
infile = file(yamlfile, 'r')
settings = yaml.load(infile)
return settings
except:
import logging
logging.error("Unable to read YAML: %s" % yamlfile)
return OrderedDict()
def write(self, newvalues, tree=None, defaultsfile='settings.yaml', outfn='mysettings.yaml'):
settings = self.read(defaultsfile)
settings.update(self.read(outfn))
settings.update(newvalues)
outfile = file(outfn, 'w')
yaml.dump(settings, outfile, default_flow_style=False)
return True
if __name__ == '__main__':
import textwrap
sample = """
one:
two: fish
red: fish
blue: fish
two:
a: yes
b: no
c: null
"""
infile = file('settings.yaml', 'r')
data = yaml.load(infile)
#data = yaml.load(infile, OrderedDictYAMLLoader)
#data = yaml.load(textwrap.dedent(sample), OrderedDictYAMLLoader)
outfile = file("testout", 'w')
yaml.dump(data, outfile, default_flow_style=False)
#assert type(data) is OrderedDict
print data.items()

View File

@ -1,15 +0,0 @@
HOSTNAME: "fuel"
DNS_DOMAIN: "example.com"
DNS_SEARCH: "example.com"
DNS_UPSTREAM: "8.8.8.8"
ADMIN_NETWORK:
interface: "eth0"
cidr: "10.20.0.0/24"
netmask: "255.255.255.0"
size: "256"
static_start: "10.20.0.10"
static_end: "10.20.0.120"
first: "10.20.0.130"
last: "10.20.0.254"