Files
main/network/connection/NetworkManager/files/migrate-comar-network-profiles
T

607 lines
22 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2009-2010 TUBITAK/UEKAE
# Licensed under the GNU General Public License, version 2.
# See the file http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#
#
#
# A migration script to transform COMAR based network profiles into NetworkManager based network profiles.
#
# The main purpose of the script is help Pardus 2009 users to be able to use their network profiles in Pardus 2011
# without any effort when they upgrade their system.
#
# A few words about how stuff works. COMAR based network manager keeps profile settings under /etc/network with two
# files: net_tools which includes ethernet profile settings and wireless_tools which includes wireless profile settings.
# On the other hand, NetworkManager keeps each profile settings in an individual file under /etc/NetworkManager/system-connections.
#
# This script simply reads your old profile files and try to create a new profile file compatible with NetworkManager for each profile.
#
#
import os
import ConfigParser
default_nameservers = []
default_resolv_conf_file = "/etc/resolv.default.conf"
lan_config_file = "/etc/network/net_tools"
wlan_config_file = "/etc/network/wireless_tools"
migration_sign = "/etc/network/.migrated"
NetworkManager_conf_dir = "/etc/NetworkManager/system-connections"
def is_migrated_before():
"""Make this tool run once; so after migration, touch a file named '.migrated'
under old network manager profiles dir. Check it first and then try to migrate profiles.
"""
global migration_sign
if os.path.exists(migration_sign):
return True
else:
return False
def get_default_nameservers():
"""Read once default name servers in resolve.default.conf, if 'name_mode' in
given profile was set to default, supply these values in the new profile file
"""
global default_nameservers
if len(default_nameservers) == 0:
if os.path.exists(default_resolv_conf_file):
with open(default_resolv_conf_file) as f:
nameservers_file = f.readlines()
for line in nameservers_file:
if not line.startswith("#") and line.startswith("nameserver"):
ns = line.split()[-1]
default_nameservers.append(ns)
#If we can't find default.resolv.conf, supply default Pardus DNS servers
else:
default_nameservers = ["193.140.100.210", "193.140.100.215", "193.140.100.220"]
return default_nameservers
class PardusNetworkProfile:
"""Represents COMAR based network profiles that we have been using in Pardus' network
manager. We have two types of network profiles specified: wired or wireless
"""
def __init__(self, name, connection_type, settings):
self.profile_name = name
self.connection_type = connection_type
self.device = "none"
self.net_mode = "none"
self.name_mode = "none"
self.state = "none"
self.name_server = "none"
self.net_address = "none"
self.net_mask = "none"
self.net_gateway = "none"
self.remote = "none"
self.auth = "none"
self.auth_password = "none"
self.set_attributes(settings)
def set_attributes(self, settings):
"""We receive profile settings as dictionary type in 'settings'
Map each key-value pairs for each object.
"""
for key, value in settings.items():
self.__dict__[key] = value
def get_profile_name(self):
return self.profile_name
def get_connection_type(self):
return self.connection_type
def get_device(self):
return self.device
def get_net_mode(self):
return self.net_mode
def get_name_mode(self):
return self.name_mode
def get_state(self):
return self.state
def get_name_server(self):
return self.name_server
def get_net_address(self):
return self.net_address
def get_net_mask(self):
return self.net_mask
def get_net_gateway(self):
return self.net_gateway
def get_remote(self):
return self.remote
def get_auth(self):
return self.auth
def get_auth_password(self):
return self.auth_password
class NetworkManagerProfile:
"""Represents network profiles used in NetworkManager. In NetworkManager,
settings are kept in a seperate file for each profile.
"""
def __init__(self, name, pardus_profile):
"""Each section is kept in corresponding class attribute"""
self.cfg = ConfigParser.ConfigParser()
self.connection = Connection(pardus_profile)
self.ipv4 = IpV4(pardus_profile)
self.ipv6 = IpV6(pardus_profile)
self._802_3_ethernet = self.set_802_3_ethernet(pardus_profile)
self._802_11_wireless = self.set_802_11_wireless(pardus_profile)
self._802_11_wireless_security = self.set_802_11_wireless_security(pardus_profile)
self.create_config()
def set_802_3_ethernet(self, pardus_profile):
"""If this is a wired (802-3-ethernet) profile, set _802_3_ethernet
attribute.
"""
if pardus_profile.connection_type == "802-3-ethernet":
return _802_3_Ethernet(pardus_profile)
else:
return "none"
def set_802_11_wireless(self, pardus_profile):
"""If this is a wireless (802-11-wirelesss) profile, set
_802_11_wireless attribute."""
if pardus_profile.connection_type == "802-11-wireless":
return _802_11_Wireless(pardus_profile)
else:
return "none"
def set_802_11_wireless_security(self, pardus_profile):
"""If the wireless connection has any security restrictions, create a
802-11-wireless-security section with corresponding values.
"""
if pardus_profile.get_connection_type() == "802-11-wireless": #Check if it is a wlan profile
if pardus_profile.get_auth() == "none":
self._802_11_wireless.security = "none"
return "none"
else:
self._802_11_wireless.security = "802-11-wireless-security"
return _802_11_Wireless_Security(pardus_profile)
else:
return "none"
def create_config(self):
"""Create sections and options in the prfoile's config file by calling
each options corresponding method.
"""
#FIXME: Try to do it over loops ie. self[attr].set_config()
for attr, value in self.__dict__.items():
if attr == "connection":
self.connection.set_config(self.cfg)
if attr == "ipv4":
self.ipv4.set_config(self.cfg)
if attr == "ipv6":
self.ipv6.set_config(self.cfg)
if attr == "_802_3_ethernet" and not value == "none":
self._802_3_ethernet.set_config(self.cfg)
if attr == "_802_11_wireless" and not value == "none":
self._802_11_wireless.set_config(self.cfg)
if attr == "_802_11_wireless_security" and not value == "none":
self._802_11_wireless_security.set_config(self.cfg)
def write_config(self):
"""Write settings to profile file"""
#Before writing to file we must convert underscores to dashes, moreover _id must be written as id, and _type as type
if not os.path.exists(NetworkManager_conf_dir):
os.makedirs(NetworkManager_conf_dir, mode=0755)
profile_path = os.path.join("%s" % NetworkManager_conf_dir, self.connection._id)
with open(profile_path, "wb") as configfile:
self.cfg.write(configfile)
def set_ownership(self):
"""NetworkManager is smart enough to understand whether a configuration file is valid
by checking its permissions"""
os.chmod(os.path.join("%s" % NetworkManager_conf_dir, self.connection._id), 0600)
class Connection:
"""Instances of Connection class represent essential properties of a network connection to identify itself."""
def __init__(self, pardus_profile):
self.name = "connection"
self._id = pardus_profile.get_profile_name()
self.uuid = self.set_uuid(device = pardus_profile.get_device())
self._type = pardus_profile.get_connection_type()
self.autoconnect = self.set_autoconnect(pardus_profile)
self.timestamp = "none"
self.read_only = "false"
def set_autoconnect(self, profile):
"""Set profile activation at startup"""
if str(profile.get_state()) == "down":
return "false"
else:
return "none" #NM set this 'true' as default if we dont set anything
def set_uuid(self, device):
"""Generate random type UUID"""
import uuid
return str(uuid.uuid4())
def set_config(self, cfg):
"""One single config file will be used to write settings"""
cfg.add_section(self.name)
for attr, value in self.__dict__.items():
if value not in ["false", "none"] and attr != "name":
#Before creating config file _id must be id, and _type must be type
if attr == "_id" or attr == "_type" : attr = attr.split("_")[-1]
#There isnt any underscore in config options, replace them with dashes if found any
attr = attr.replace("_", "-")
cfg.set(self.name, attr, value)
class IpV4:
"""Instances of IpV4 class represent IPv4 based properties of a connection."""
def __init__(self, pardus_profile):
self.name = "ipv4"
self.dns_search = "none"
self.routes = "none"
self.ignore_auto_routes = "false"
self.ignore_auto_dns = "false"
self.dhcp_client_id = "none"
self.dhcp_send_hostname = "false"
self.dhcp_hostname = "none"
self.never_default = "false"
self.method = pardus_profile.get_net_mode() # auto or manual, same as in NM
self.addresses1 = self.set_addresses(pardus_profile) # NM uses array of IPv4 address structures. We have only one for each iface
self.dns = self.set_dns(pardus_profile)
def set_dns(self, pardus_profile):
"""Decide whether to use default, custom or auto (DHCP assigned) nameservers"""
if pardus_profile.get_name_mode() == "default":
default_nameservers = ";".join( get_default_nameservers())
default_nameservers = default_nameservers + ";" # Make sure addresses end with ';'
self.ignore_auto_dns = "true"
return str(default_nameservers)
elif pardus_profile.get_name_mode() == "custom":
name_server = str(pardus_profile.get_name_server())
name_server = name_server + ";"
self.ignore_auto_dns = "true"
return str(name_server)
else:
# Nothing done in auto option
return "none"
def set_addresses(self, pardus_profile):
"""Set network addresses from given settings"""
addresses = []
if self.method == "manual":
net_mask = self.calculate_prefix(pardus_profile.get_net_mask())
addresses.append(str(pardus_profile.get_net_address()))
addresses.append(str(net_mask))
addresses.append(str(pardus_profile.get_net_gateway()))
addresses = ";".join(addresses)
addresses = addresses + ";" # Make sure addresses end with ';'
return addresses
else:
return "none"
def decimal2binary(self, n):
"""Convert decimal octet value to binary format"""
octet = ["0", "0", "0", "0", "0", "0", "0", "0"]
index = 0
if n < 0 or n > 255:
raise ValueError, "Octet value must be between [0-255]"
if n == 0:
return "".join(octet)
while n > 0:
octet[index] = str((n % 2))
index += 1
n = n >> 1
octet.reverse()
return "".join(octet)
def calculate_prefix(self, net_mask):
"""Convert netmask value to CIDR prefix type which is between [1-32] as told in NM spec
See http://mail.gnome.org/archives/networkmanager-list/2008-August/msg00076.html"""
octets = net_mask.split(".")
octet_in_binary = []
netmask_value = 0
for octet in octets:
ret = self.decimal2binary(int(octet))
octet_in_binary.append(ret)
for i in "".join(octet_in_binary):
if int(i) == 1 : netmask_value += 1
return netmask_value
def set_config(self, cfg):
"""One single config file will be used to write settings"""
cfg.add_section(self.name)
for attr, value in self.__dict__.items():
if value not in ["false", "none"] and attr != "name":
attr = attr.replace("_", "-")
cfg.set(self.name, attr, value)
class IpV6:
"""Instances of IpV6 class represent IPv6 based properties of a connection."""
def __init__(self, pardus_profile):
self.name = "ipv6"
self.method = "none"
self.dns = "none"
self.dns_search = "none"
self.addresses = "none"
self.routes = "none"
self.ignore_auto_routes = "false"
self.ignore_auto_dns = "false"
self.dhcp_client_id = "none"
self.dhcp_send_hostname = "none"
self.dhcp_hostname = "none"
self.never_default = "false"
self.set_method()
def set_method(self):
"""Ignoring by default for nowadays"""
self.method = "ignore"
def set_config(self, cfg):
"""One single config file will be used to write settings"""
cfg.add_section(self.name)
for attr, value in self.__dict__.items():
if value not in ["false", "none"] and attr != "name":
attr = attr.replace("_", "-")
cfg.set(self.name, attr, value)
class _802_3_Ethernet:
"""Instances of _802_3_Ethernet class represent options related with ethernet device."""
def __init__(self, pardus_profile):
self.name = "802-3-ethernet"
self.port = "none"
self.speed = "none" #0
self.duplex = "full"
self.auto_negotiate = "false"
self.mac_address = self.set_mac_address(pardus_profile.get_device())
self.mtu = "none" #0
def set_mac_address(self, iface):
"""Return MAC addresses of given interface on the machine"""
if os.path.exists("/sys/class/net/%s" % iface):
return open("/sys/class/net/%s/address" % iface).read().strip()
return "none"
def set_config(self, cfg):
"""One single config file will be used to write settings"""
cfg.add_section(self.name)
for attr, value in self.__dict__.items():
if value not in ["false", "none"] and attr != "name":
attr = attr.replace("_", "-")
cfg.set(self.name, attr, value)
class _802_11_Wireless:
"""Instances of _802_11_Wireless class represent options related with wireless device."""
def __init__(self, pardus_profile):
self.name = "802-11-wireless"
self.ssid = self.set_ssid(pardus_profile)
self.band = "none"
self.channel = "0"
self.bssid = "none"
self.rate = "0"
self.tx_power = "0"
self.mtu = "0"
self.seen_bssids = "none"
self.security = "none"
self.mode = self.set_mode(pardus_profile)
self.mac_address = self.set_mac_address(pardus_profile.get_device())
def set_mac_address(self, iface):
"""Return MAC addresses of given interface on the machine"""
if os.path.exists("/sys/class/net/%s" % iface):
return open("/sys/class/net/%s/address" % iface).read().strip()
return "none"
def set_mode(self, pardus_profile):
"""One of 'infrastructure' or 'adhoc'. If blank, infrastructure is assumed"""
#TODO: How to determine mode (adhoc or infrastructure) from old profile settings
return "infrastructure"
def set_ssid(self, pardus_profile):
"""Set ssid value"""
if pardus_profile.connection_type == "802-11-wireless":
return str(pardus_profile.get_remote())
else:
return "none"
def set_config(self, cfg):
"""One single config file will be used to write settings"""
cfg.add_section(self.name)
for attr, value in self.__dict__.items():
if value not in ["false", "none", "0"] and attr != "name":
attr = attr.replace("_", "-")
cfg.set(self.name, attr, value)
class _802_11_Wireless_Security:
"""Instances of _802_11_Wireless_Security class represent authentication properties and operations
used in order to be included in networks requiring them.
"""
def __init__(self, pardus_profile):
self.name = "802-11-wireless-security"
self.key_mgmt = "none"
self.wep_tx_keyidx = "0"
self.auth_alg = "none"
self.proto = "none"
self.pairwise = "none"
self.group = "none"
self.leap_username = "none"
self.wep_key0 = "none"
self.wep_key1 = "none"
self.wep_key2 = "none"
self.wep_key3 = "none"
self.psk = "none"
self.leap_password = "none"
self.wep_key_type = "0"
self.set_up_wireless_security(pardus_profile)
def set_up_wireless_security(self, pardus_profile):
"""WEP, WPA or none type security based operations"""
if pardus_profile.get_auth() in ["wep", "wepascii"]:
self.set_wep(pardus_profile)
elif pardus_profile.get_auth() == "wpa-psk":
self.set_wpa(pardus_profile)
else:
return
def set_wpa(self, pardus_profile):
"""Set up WPA based networks"""
self.key_mgmt = "wpa-psk"
self.psk = str(pardus_profile.get_auth_password())
def set_wep(self, pardus_profile):
"""Set up WEP based networks"""
self.auth_alg = "open" #TODO: or 'shared' ??
self.key_mgmt = "None" # Which stands for WEP based key management
self.wep_key0 = str(pardus_profile.get_auth_password()) # Default index
self.wep_key_type = "1" # Interpret WEP keys as hex or ascii keys
def set_config(self, cfg):
"""One single config file will be used to write settings"""
cfg.add_section(self.name)
for attr, value in self.__dict__.items():
if value not in ["false", "none", "0"] and attr != "name":
attr = attr.replace("_", "-")
# key-mgmt=none is a mandatory assignment for WEP based
# configurations. As we set all class members' default value
# to 'none', and then filter to set config file with non-none
# values, key-mgmt is set to 'None' intentionally to pass that
# filtering, and its value is set later on by lowercasing to
# hack around this situation.
if attr == "key-mgmt":
value = value.lower()
cfg.set(self.name, attr, value)
class Migrator:
"""Read COMAR based network profiles we have been using in Pardus' network manager and
transform them into NetworkManager profile type.
"""
def __init__(self):
self.pardus_profiles = []
self.network_manager_profiles = []
self.lan_config_path = lan_config_file
self.wlan_config_path = wlan_config_file
self.read_pardus_profiles()
def read_pardus_profiles(self):
"""Read wired/wireless profile settings, create PardusNetworkProfile
object for each one, and store them in a list.
"""
self.lan_config = ConfigParser.ConfigParser()
self.lan_config.read(self.lan_config_path)
connection_type = "802-3-ethernet"
for section in self.lan_config.sections():
lan_settings = {}
for option in self.lan_config.options(section):
if option == "device":
#To strip device name from long device string
lan_settings[option] = self.lan_config.get(section, option).split("_")[-1]
else:
lan_settings[option] = self.lan_config.get(section, option)
p = PardusNetworkProfile(section, connection_type, lan_settings)
self.pardus_profiles.append(p)
self.wlan_config = ConfigParser.ConfigParser()
self.wlan_config.read(self.wlan_config_path)
connection_type = "802-11-wireless"
for section in self.wlan_config.sections():
wlan_settings = {}
for option in self.wlan_config.options(section):
if option == "device":
wlan_settings[option] = self.wlan_config.get(section, option).split("_")[-1]
else:
wlan_settings[option] = self.wlan_config.get(section, option)
p = PardusNetworkProfile(section, connection_type, wlan_settings)
self.pardus_profiles.append(p)
def transform_profiles(self):
"""Convert Pardus' network profiles to NetworkManager profiles"""
if len(self.pardus_profiles) > 0: # Make sure we have some profiles to migrate
for profile in self.pardus_profiles:
network_manager_profile = NetworkManagerProfile(profile.get_profile_name, profile)
self.network_manager_profiles.append(network_manager_profile)
def write_network_manager_profiles(self):
"""Create profile file for each NetworkManager profile and change ownerships to 0600"""
if len(self.network_manager_profiles) > 0: # Make sure we have some profiles to migrate
for profile in self.network_manager_profiles:
profile.write_config()
profile.set_ownership()
with open(migration_sign, "w") as f:
pass
if __name__ == "__main__":
print "DEBUG: Checking whether network profiles migrated..."
if not is_migrated_before():
m = Migrator()
m.transform_profiles()
m.write_network_manager_profiles()
print "DEBUG: Network profiles migration completed successfully!"
else:
print "DEBUG: Network profiles migration seems already done before. Nothing done this time!"