|  | #!/usr/bin/python -u | 
|  |  | 
|  | import gobject | 
|  | import dbus | 
|  | import dbus.service | 
|  | import dbus.mainloop.glib | 
|  | import os | 
|  | import os.path as path | 
|  | import sys | 
|  | from obmc.dbuslib.bindings import DbusProperties, get_dbus | 
|  | from IPy import IP | 
|  |  | 
|  | settings_file_path = os.path.join( | 
|  | sys.prefix, | 
|  | 'share', | 
|  | 'phosphor-settings') | 
|  | sys.path.insert(1, settings_file_path) | 
|  | import settings_file as s | 
|  | import re | 
|  |  | 
|  | DBUS_NAME = 'org.openbmc.settings.Host' | 
|  | OBJ_NAME = '/org/openbmc/settings/host0' | 
|  | CONTROL_INTF = 'org.openbmc.Settings' | 
|  |  | 
|  |  | 
|  | class HostSettingsObject(DbusProperties): | 
|  | def __init__(self, bus, name, settings, path): | 
|  | super(HostSettingsObject, self).__init__(conn=bus, object_path=name, | 
|  | validator=self.input_validator) | 
|  | self.bus = bus | 
|  | self.path = path | 
|  | # Needed to ignore the validation on default networkconfig values as | 
|  | # opposed to user giving the same. | 
|  | self.adminmode = True | 
|  |  | 
|  | if not os.path.exists(path): | 
|  | os.mkdir(path) | 
|  |  | 
|  | # Listen to changes in the property values and sync them to the BMC | 
|  | bus.add_signal_receiver( | 
|  | self.settings_signal_handler, | 
|  | dbus_interface="org.freedesktop.DBus.Properties", | 
|  | signal_name="PropertiesChanged", | 
|  | path="/org/openbmc/settings/host0") | 
|  |  | 
|  | # Create the dbus properties | 
|  | for i in settings[DBUS_NAME].iterkeys(): | 
|  | shk = settings[DBUS_NAME][i] | 
|  | self.set_settings_property(shk['name'], | 
|  | shk['type'], | 
|  | shk['default']) | 
|  | # Done with consuming factory settings. | 
|  | self.adminmode = False | 
|  |  | 
|  | def get_bmc_value(self, name): | 
|  | try: | 
|  | with open(path.join(self.path, name), 'r') as f: | 
|  | return f.read() | 
|  | except (IOError): | 
|  | pass | 
|  | return None | 
|  |  | 
|  | # Create dbus properties based on bmc value. | 
|  | # This will be either a value previously set, | 
|  | # or the default file value if the BMC value | 
|  | # does not exist. | 
|  | def set_settings_property(self, name, type, value): | 
|  | bmcv = self.get_bmc_value(name) | 
|  | if bmcv: | 
|  | value = bmcv | 
|  | if type == "i": | 
|  | self.Set(DBUS_NAME, name, int(value)) | 
|  | elif type == "s": | 
|  | self.Set(DBUS_NAME, name, str(value)) | 
|  | elif type == "b": | 
|  | self.Set(DBUS_NAME, name, bool(value)) | 
|  |  | 
|  | # Save the settings to the BMC. This will write the settings value in | 
|  | # individual files named by the property name to the BMC. | 
|  | def set_system_settings(self, name, value): | 
|  | bmcv = self.get_bmc_value(name) | 
|  | if bmcv != value: | 
|  | filepath = path.join(self.path, name) | 
|  | with open(filepath, 'w') as f: | 
|  | f.write(str(value)) | 
|  |  | 
|  | # Signal handler for when one ore more settings properties were updated. | 
|  | # This will sync the changes to the BMC. | 
|  | def settings_signal_handler( | 
|  | self, interface_name, changed_properties, invalidated_properties): | 
|  | for name, value in changed_properties.items(): | 
|  | self.set_system_settings(name, value) | 
|  |  | 
|  | # Placeholder signal. Needed to register the settings interface. | 
|  | @dbus.service.signal(DBUS_NAME, signature='s') | 
|  | def SettingsUpdated(self, sname): | 
|  | pass | 
|  |  | 
|  | def validate_regex(self, regex, value): | 
|  | if not re.compile(regex).search(value): | 
|  | raise ValueError, "Invalid input. Data does not satisfy regex" | 
|  |  | 
|  | def validate_range(self, min, max, value): | 
|  | if value not in range(min, max): | 
|  | raise ValueError, "Invalid input. Data not in allowed range" | 
|  |  | 
|  | def validate_list_ignore_case(self, lst, value): | 
|  | if value.lower() not in map(lambda val: val.lower(), lst): | 
|  | raise ValueError, "Invalid input. Data not in allowed values" | 
|  |  | 
|  | # validate host network configuration | 
|  | # need  "ipaddress=,prefix=,gateway=,mac=,addr_type=" | 
|  | # Must be able to handle any order | 
|  | def validate_net_config(self, value): | 
|  | if self.adminmode: | 
|  | return | 
|  |  | 
|  | # Need all of these to be given by the user. | 
|  | user_config = [] | 
|  | all_config = ['ipaddress', 'prefix', 'gateway', 'mac', 'addr_type'] | 
|  |  | 
|  | # This has a hard data format mentioned above so no blanks allowed. | 
|  | if value.count(" ") or value.count("=") != 5: | 
|  | raise ValueError, "Invalid Network Data. No white spaces allowed" | 
|  |  | 
|  | config = value.split(',') | 
|  | for key_value in config: | 
|  | key , value = key_value.split('=') | 
|  | if not key or not value: | 
|  | raise ValueError, "Invalid key or Data" | 
|  |  | 
|  | # Add the current key seen so we can compare at the end to see | 
|  | # if all values have been given | 
|  | user_config.append(key.lower()) | 
|  |  | 
|  | if key.lower() == 'ipaddress' or key.lower() == 'gateway': | 
|  | IP(value) | 
|  |  | 
|  | elif key.lower() == 'mac': | 
|  | regex = '([a-fA-F0-9]{2}[:|\-]?){6}' | 
|  | self.validate_regex(regex, value) | 
|  |  | 
|  | elif key.lower() == 'prefix': | 
|  | self.validate_range(0, 33, int(value)) | 
|  |  | 
|  | elif key.lower() == 'addr_type': | 
|  | allowed = ["STATIC", "DYNAMIC"] | 
|  | self.validate_list_ignore_case(allowed, value) | 
|  |  | 
|  | # Did user pass everything ?? | 
|  | if set(all_config) - set(user_config): | 
|  | raise ValueError, "Invalid Network Data. All information is mandatory" | 
|  |  | 
|  | # Validate to see if the changes are in order | 
|  | def input_validator(self, iface, proprty, value): | 
|  | settings = s.SETTINGS | 
|  | shk = {} | 
|  | for key in settings[iface].iterkeys(): | 
|  | if proprty == settings[iface][key]['name']: | 
|  | shk = settings[iface][key] | 
|  | break | 
|  |  | 
|  | # User entered key is not present | 
|  | if not shk: raise KeyError, "Invalid Property" | 
|  |  | 
|  | if shk['validation'] == 'list': | 
|  | self.validate_list_ignore_case(shk['allowed'], value) | 
|  |  | 
|  | elif shk['validation'] == 'range': | 
|  | self.validate_range(shk['min'], shk['max']+1, value) | 
|  |  | 
|  | elif shk['validation'] == 'regex': | 
|  | self.validate_regex(shk['regex'], value) | 
|  |  | 
|  | elif shk['validation'] == 'custom': | 
|  | getattr(self, shk['method'])(value) | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) | 
|  |  | 
|  | bus = get_dbus() | 
|  | obj = HostSettingsObject(bus, OBJ_NAME, s.SETTINGS, "/var/lib/obmc/") | 
|  | mainloop = gobject.MainLoop() | 
|  |  | 
|  | obj.unmask_signals() | 
|  | name = dbus.service.BusName(DBUS_NAME, bus) | 
|  | print "Running HostSettingsService" | 
|  | mainloop.run() | 
|  |  | 
|  | # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 |