123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607 |
- #!/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!"
|