Package elisa :: Package core :: Module config_upgrader
[hide private]
[frames] | no frames]

Source Code for Module elisa.core.config_upgrader

  1  # -*- coding: utf-8 -*- 
  2  # Elisa - Home multimedia server 
  3  # Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com). 
  4  # All rights reserved. 
  5  # 
  6  # This file is available under one of two license agreements. 
  7  # 
  8  # This file is licensed under the GPL version 3. 
  9  # See "LICENSE.GPL" in the root of this distribution including a special 
 10  # exception to use Elisa with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Elisa is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Elisa" in the root directory of this distribution package 
 15  # for details on that license. 
 16   
 17  """ 
 18  Module responsible for managing Elisa config file upgrades 
 19  """ 
 20   
 21  __maintainer__ = 'Philippe Normand <philippe@fluendo.com>' 
 22   
 23  from elisa.core import log, config, media_uri 
 24  import os, datetime 
 25  from distutils.version import LooseVersion 
 26   
27 -class ConfigUpgrader(log.Loggable):
28
29 - def __init__(self, current_config, default_config):
30 log.Loggable.__init__(self) 31 self._current_config = current_config 32 self._current_version = self._get_version(current_config) 33 self._default_config = default_config 34 self._new_config_fname = 'elisa_new.conf' 35 36 today = datetime.date.today().isoformat() 37 self._today = self._current_config.get_option('install_date', 38 section='general', 39 default=today)
40
41 - def _get_version(self, cfg):
42 version = cfg.get_option('version', section='general') 43 if version is None: 44 version = '0.1.7' 45 46 cfg_version = LooseVersion(version) 47 return cfg_version
48
49 - def update_for(self, version):
50 cfg = self._current_config 51 version_str = '.'.join([str(i) for i in version]) 52 updated = False 53 self.info("Trying to upgrade from %s to %s", self._current_version, 54 version_str) 55 56 if self._current_version == '0.1.7': 57 cfg = self._update_0_1_to_0_3_1() 58 updated = True 59 60 if self._current_version == '0.3.1': 61 if version in ((0, 3, 1, 1),(0, 3, 2)): 62 cfg = self._update_0_3_1_to_0_3_2(cfg) 63 updated = True 64 65 if self._current_version == '0.3.2': 66 if version in ((0, 3, 2, 1),(0, 3, 3)): 67 cfg = self._update_0_3_2_to_0_3_3(cfg) 68 updated = True 69 70 if updated: 71 cfg.set_option('install_date', self._today, section='general') 72 cfg.set_option('version', version_str, section='general') 73 74 full_path = os.path.join(cfg.get_config_dir(), 75 self._current_config.get_filename()) 76 cfg.set_filename(full_path) 77 if os.path.exists(self._new_config_fname): 78 os.unlink(self._new_config_fname) 79 self.info("Updated config to %s", cfg.get_filename()) 80 else: 81 self.info("No update needed") 82 return cfg
83
84 - def _extend_list(self, items_list, items_to_add):
85 for item in items_to_add: 86 if item not in items_list: 87 items_list.append(item) 88 return items_list
89
90 - def _backup(self, version=None, cfg=None):
91 if version is None: 92 if self._current_version is None: 93 version = (0, 1, 7) 94 else: 95 version = str(self._current_version).split('.') 96 97 version = '.'.join([str(i) for i in version]) 98 99 if not cfg: 100 cfg = self._current_config 101 102 full_path = os.path.join(cfg.get_config_dir(), 103 'elisa_%s.bak' % version) 104 self.info("Doing a backup to the old config on %s", full_path) 105 cfg.write(full_path)
106
107 - def _update_0_3_2_to_0_3_3(self, cfg=None):
108 self.info('Upgrading from 0.3.2 to 0.3.3') 109 self._backup((0, 3, 2), cfg) 110 if not cfg: 111 cfg = self._current_config 112 113 # copy media locations 114 paths = {} 115 paths['audio'] = cfg.get_option('locations', 116 section='base:audio_activity', 117 default=[]) 118 paths['video'] = cfg.get_option('locations', 119 section='base:video_activity', 120 default=[]) 121 paths['image'] = cfg.get_option('locations', 122 section='base:image_activity', 123 default=[]) 124 all_locations = [] 125 for media_type, locations in paths.iteritems(): 126 for location in locations: 127 cfg.set_option('only_media', [media_type,], 128 section=location) 129 if location not in all_locations: 130 all_locations.append(location) 131 132 cfg.set_option('locations', locations, 133 section='xmlmenu:locations_builder') 134 135 def rename(optname, mapping, section='general'): 136 contents = cfg.get_option(optname, section=section) 137 for old_name, new_name in mapping.iteritems(): 138 if old_name in contents: 139 contents.remove(old_name) 140 contents.append(new_name) 141 cfg.rename_section(old_name, new_name)
142 143 # rename media_providers 144 mp_map = {'coherence_plugin:upnp_media': 'coherence:upnp_media', 145 'media_bad:ipod_media': 'ipod:ipod_media', 146 'media_bad:daap_media': 'daap:daap_media', 147 'media_bad:mmslist_media': 'webtv:mmslist_media', 148 'media_good:elisa_media': 'media_db:elisa_media', 149 'media_good:gnomevfs_media': 'gvfs:gnomevfs_media', 150 'media_ugly:podcatcher_media': 'aggregator:podcatcher_media', 151 'media_ugly:shoutcast_media': 'shoutcast:shoutcast_media', 152 } 153 rename('media_providers', mp_map) 154 155 # rename metadata_providers 156 md_map = {'media_good:amazon_covers': 'amazon:amazon_covers', 157 'media_good:cover_cache': 'album_art:cover_cache', 158 'media_good:gst_metadata': 'gstreamer:gst_metadata_client', 159 'media_good:cover_in_dir': 'album_art:cover_in_dir', 160 } 161 rename('metadata_providers', md_map) 162 163 # rename service_providers 164 service_map = {'coherence_plugin:upnp_media_server': 'coherence:upnp_media_server', 165 'coherence_plugin:coherence_service': 'coherence:coherence_service', 166 'services_good:lastfm_scrobbler': 'lastfm:lastfm_scrobbler', 167 'services_good:twisted_pb': 'twisted:twisted_pb', 168 'services_good:http_server': 'httpd:http_server', 169 } 170 rename('service_providers', service_map) 171 172 # rename input_providers 173 ip_map = {'input_good:lirc_input': 'lirc:lirc_input', 174 'input_good:raw_input': 'base:raw_input', 175 'input_bad:bluetooth_input': 'bluetooth:bluetooth_input', 176 'input_bad:webcam_input': 'webcam:webcam_input', 177 } 178 backends = cfg.get_option('backends', section='general', default=[]) 179 frontends = cfg.get_option('frontends', section='general', default=[]) 180 181 for section_name in backends + frontends: 182 rename('input_providers', ip_map, section=section_name) 183 184 # add missing default media_providers 185 media_providers = cfg.get_option('media_providers', section='general', 186 default=[]) 187 media_providers = self._extend_list(media_providers, 188 ['daap:daap_media', 189 'youtube:youtube_media',]) 190 cfg.set_option('media_providers', media_providers, section='general') 191 192 # add missing metadata_providers 193 metadata_providers = cfg.get_option('metadata_providers', 194 section='general', default=[]) 195 if 'media_good:taglib_metadata' in metadata_providers: 196 metadata_providers.remove('media_good:taglib_metadata') 197 metadata_providers = self._extend_list(metadata_providers, 198 ['gstreamer:gst_metadata_client', 199 'album_art:cover_in_dir', 200 'amazon:amazon_covers']) 201 cfg.set_option('metadata_providers', metadata_providers, 202 section='general') 203 204 # add missing service_providers 205 service_providers = cfg.get_option('service_providers', 206 section='general', default=[]) 207 service_providers = self._extend_list(service_providers, 208 ['gnome:gnome_screensaver_service',]) 209 cfg.set_option('service_providers', service_providers, 210 section='general') 211 212 # add missing themes 213 themes = ['raval:tango_theme', 'raval:poblenou_theme', 214 'raval:chris_theme'] 215 cfg_themes = cfg.get_option('themes', 216 section='theme_switcher:theme_switcher_activity', 217 default=[]) 218 cfg_themes = self._extend_list(cfg_themes,themes) 219 cfg.set_option('themes',cfg_themes, 220 section='theme_switcher:theme_switcher_activity') 221 222 # fix backend config 223 backend_section = cfg.get_section('backend1') 224 backend_section['activity'] = 'raval:elisa_activity' 225 backend_section['controller'] = 'raval:elisa_controller' 226 backend_section['mvc_mappings'] = 'raval:data/raval_mvc_mappings.conf' 227 cfg.set_section('backend1', backend_section) 228 229 # fix frontend config 230 frontend_section = cfg.get_section('frontend1') 231 frontend_section['theme'] = 'raval:tango_theme' 232 cfg.set_section('frontend1', frontend_section) 233 234 # rename some sections... 235 sections_to_rename = {'poblenou:elisa_controller': 'raval:elisa_controller', 236 'base:player_controller': 'raval:player_controller' 237 } 238 for old_name, new_name in sections_to_rename.iteritems(): 239 cfg.rename_section(old_name, new_name) 240 241 # remove sections not used anymore 242 sections_to_remove = ['base:main_menu_activity', 243 'base:audio_activity', 'base:video_activity', 244 'base:image_activity', 'elisa_view'] 245 for path in sections_to_remove: 246 cfg.del_section(path) 247 248 self._current_version = '0.3.3' 249 return cfg
250
251 - def _update_0_3_1_to_0_3_2(self, cfg=None):
252 self.info('Upgrading from 0.3.1 to 0.3.2') 253 self._backup((0, 3, 1), cfg) 254 if not cfg: 255 cfg = self._current_config 256 257 def upgrade_paths(opt_name, mapping, section='general'): 258 259 old_option = cfg.get_option(opt_name,section=section) 260 for old_path, new_path in mapping.iteritems(): 261 if old_path in old_option: 262 old_option.remove(old_path) 263 old_option.append(new_path) 264 265 old_path_section = cfg.get_section(old_path) 266 if old_path_section: 267 cfg.set_section(new_path, old_path_section) 268 cfg.del_section(old_path) 269 270 cfg.set_option(opt_name, old_option, section=section)
271 272 # upgrade media_providers paths 273 media_providers = {'base:upnp_media': 'coherence_plugin:upnp_media', 274 'base:elisa_media': 'media_good:elisa_media', 275 'base:gnomevfs_media': 'media_good:gnomevfs_media', 276 'base:ipod_media': 'media_bad:ipod_media', 277 'base:mmslist_media': 'media_good:mmslist_media', 278 'base:shoutcast_media': 'media_ugly:shoutcast_media', 279 'base:daap_media': 'media_bad:daap_media', 280 'base:audiocd': 'audiocd:audiocd_media'} 281 upgrade_paths('media_providers', media_providers) 282 283 # new media_providers 284 new_media_providers = ['fspot:fspot_media','stage6:stage_media', 285 'media_ugly:shoutcast_media', 286 'flickr:flickr_media'] 287 media_providers = cfg.get_option('media_providers', section='general') 288 for mp in new_media_providers: 289 if mp not in media_providers: 290 media_providers.append(mp) 291 cfg.set_option('media_providers', media_providers) 292 293 # upgrade metadata_providers paths 294 metadata_providers = {'base:gst_metadata':'media_good:gst_metadata', 295 'base:taglib_metadata': 'media_good:taglib_metadata', 296 'base:cover_in_dir':'media_good:cover_in_dir', 297 'base:cover_cache': 'media_good:cover_cache', 298 'base:amazon_covers':'media_good:amazon_covers'} 299 upgrade_paths('metadata_providers', metadata_providers) 300 301 # upgrade service_providers paths 302 service_providers = {'lastfm:audioscrobbler_service':'services_good:lastfm_scrobbler', 303 'base:hal_service':'hal:hal_service', 304 'base:twisted_pb':'services_good:twisted_pb', 305 'base:http_server':'services_good:http_server', 306 'base:coherence_service':'coherence_plugin:coherence_service', 307 'base:upnp_media_server':'coherence_plugin:upnp_media_server', 308 'base:upnp_media_renderer':'coherence_plugin:upnp_media_renderer' 309 } 310 upgrade_paths('service_providers', service_providers) 311 312 # new service_providers 313 new_service_providers = ['coherence_plugin:coherence_service', 314 ] 315 service_providers = cfg.get_option('service_providers', 316 section='general') 317 for sp in new_service_providers: 318 if sp not in service_providers: 319 service_providers.append(sp) 320 cfg.set_option('service_providers', service_providers) 321 322 # upgrade input_providers paths 323 input_providers = {'base:lirc_input':'input_good:lirc_input', 324 'base:raw_input': 'input_good:raw_input', 325 'base:bluetooth_input':'input_bad:bluetooth_input'} 326 upgrade_paths('input_providers', input_providers, 'backend1') 327 upgrade_paths('input_providers', input_providers, 'frontend1') 328 329 # upgrade main menu 330 menu_activities = ['base:audio_activity', 'base:video_activity', 331 'base:image_activity', 'base:config_activity', 332 'base:service_activity'] 333 cfg.set_option('menu_activities', menu_activities, 334 section='base:main_menu_activity') 335 336 # upgrade services menu 337 service_activities = ['service:about_activity'] 338 cfg.set_option('service_activities', service_activities, 339 section='base:service_activity') 340 cfg.del_section('service:service_activity') 341 342 # upgrade player and dvd controller 343 cfg.del_section('base:player_controller') 344 cfg.del_section('dvd:dvd_player_controller') 345 346 cfg.set_option('version', '0.3.2', section='general') 347 self._current_version = '0.3.2' 348 return cfg 349
350 - def _update_0_1_to_0_3_1(self):
351 self.info('Upgrading from 0.1.x to 0.3.1') 352 self._backup() 353 cfg = config.Config(self._new_config_fname, self._default_config) 354 355 # media locations options have migrated to activities 356 activity_map = {'plugins.music': 'base:audio_activity', 357 'plugins.movies': 'base:video_activity', 358 'plugins.pictures': 'base:image_activity' 359 } 360 for old_section, new_section in activity_map.iteritems(): 361 locations = self._current_config.get_option('locations', 362 section=old_section, 363 default=[]) 364 new_locations = [] 365 location_labels = {} 366 for location in locations: 367 368 # meta:// URIs not supported anymore 369 if location.startswith('meta'): 370 continue 371 372 # FIXME: location/* not supported yet 373 if location.endswith('*'): 374 location = location[:-1] 375 376 location = location.decode('utf-8') 377 location_uri = media_uri.MediaUri(location) 378 379 # label parameter removed 380 label = location_uri.get_param('label') 381 if label: 382 location_uri.del_param('label') 383 location_labels[str(location_uri)] = label 384 385 new_locations.append(str(location_uri)) 386 387 cfg.set_option('locations', new_locations, section=new_section) 388 activity_section = cfg.get_section(new_section) 389 for location, label in location_labels.iteritems(): 390 activity_section[location] = {'label': str(label)} 391 392 # start_fullscreen option moved to elisa_controller 393 start_fullscreen = self._current_config.get_option('start_fullscreen', 394 default='0') 395 controller_section = cfg.get_section('poblenou:elisa_controller') 396 controller_section['start_fullscreen'] = str(start_fullscreen) 397 398 # media_manager 399 media_manager_opts = self._current_config.get_section('media_manager') 400 media_scanner_section = cfg.get_section('media_scanner') 401 try: 402 media_scanner_section['enabled'] = str(media_manager_opts['enable_cache']) 403 except KeyError: 404 self.warning("enable_cache option not found in old config") 405 406 try: 407 media_scanner_section['database'] = media_manager_opts['db_name'] 408 except KeyError: 409 self.warning("db_name option not found in old config") 410 411 for timebased in ('fivemin', 'hourly', 'daily', 'weekly'): 412 opt_name = '%s_location_updates' % timebased 413 try: 414 media_scanner_section[opt_name] = media_manager_opts[opt_name] 415 except KeyError: 416 self.warning("%s option not found in old config", opt_name) 417 continue 418 419 self._current_version = '0.3.1' 420 return cfg
421