summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMuayyad Alsadi <alsadi@ojuba.org>2009-07-28 22:35:50 +0100
committerRichard Hughes <richard@hughsie.com>2009-07-28 22:36:21 +0100
commit3a75f454a53294a62a8f1eb93d0c3e53cc02a966 (patch)
tree97f97766a229a039e55d95a0d385201bcb36a959
parent816307af5d6f4f424ccf84f98621f6dc72380413 (diff)
Add the start of MediaManager code for external media handling
Signed-off-by: Richard Hughes <richard@hughsie.com>
-rw-r--r--backends/yum/Makefile.am1
-rwxr-xr-xbackends/yum/yumBackend.py107
-rw-r--r--backends/yum/yumMediaManager.py84
3 files changed, 191 insertions, 1 deletions
diff --git a/backends/yum/Makefile.am b/backends/yum/Makefile.am
index a91c5b0cd..b5f61d1b0 100644
--- a/backends/yum/Makefile.am
+++ b/backends/yum/Makefile.am
@@ -3,6 +3,7 @@ dist_helper_DATA = \
yum-comps-groups.conf \
yumBackend.py \
yumComps.py \
+ yumMediaManager.py \
yumFilter.py
plugindir = $(PK_PLUGIN_DIR)
diff --git a/backends/yum/yumBackend.py b/backends/yum/yumBackend.py
index b26ba0c1a..0bccc8475 100755
--- a/backends/yum/yumBackend.py
+++ b/backends/yum/yumBackend.py
@@ -15,20 +15,26 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-# Copyright (C) 2007-2008
+# Copyright (C) 2007-2009
# Tim Lauridsen <timlau@fedoraproject.org>
# Seth Vidal <skvidal@fedoraproject.org>
# Luke Macken <lmacken@redhat.com>
# James Bowes <jbowes@dangerouslyinc.com>
# Robin Norwood <rnorwood@redhat.com>
# Richard Hughes <richard@hughsie.com>
+#
+# MediaGrabber:
+# Based on the logic of pirut by Jeremy Katz <katzj@redhat.com>
+# Rewritten by Muayyad Alsadi <alsadi@ojuba.org>
# imports
from packagekit.backend import *
from packagekit.progress import *
+from packagekit.enums import *
from packagekit.package import PackagekitPackage
import yum
from urlgrabber.progress import BaseMeter, format_number
+from urlgrabber.grabber import URLGrabber, URLGrabError
from yum.rpmtrans import RPMBaseCallback
from yum.constants import *
from yum.update_md import UpdateMetadata
@@ -52,6 +58,7 @@ import ConfigParser
from yumFilter import *
from yumComps import *
+from yumMediaManager import MediaManager
# Global vars
yumbase = None
@@ -2805,6 +2812,7 @@ class PackageKitYumBase(yum.YumBase):
self.missingGPGKey = None
self.dsCallback = DepSolveCallback(backend)
self.backend = backend
+ self.mediagrabber = self.MediaGrabber
# Setup Repo GPG support callbacks
try:
self.repos.confirm_func = self._repo_gpg_confirm
@@ -2816,6 +2824,103 @@ class PackageKitYumBase(yum.YumBase):
else:
raise PkError(ERROR_INTERNAL_ERROR, _format_str(traceback.format_exc()))
+ def MediaGrabber(self, *args, **kwargs):
+ """
+ Handle physical media.
+
+ This module can be summarized like this:
+ For all media:
+ - Lock it
+ - If not mounted: mount it
+ - If it's the wanted media: break
+ - If no media found: ask the user to insert it and loop again
+ ....
+ Release the media
+ """
+ media_id = kwargs["mediaid"]
+ disc_number = kwargs["discnum"]
+ name = kwargs["name"]
+ discs_s = ''
+ found = False
+
+ manager = MediaManager()
+ media = None
+ found = False
+
+ # loop over and over, retry because the user might insert disc #2 when we need disc #5
+ while 1:
+ # check for the needed media in every media provided by yumMediaManager
+ for media in manager:
+ # mnt now holds the mount point
+ mnt = media.acquire()
+ found = False
+
+ # if not mounted skip this media for this loop
+ if not mnt:
+ continue
+
+ # load ".discinfo" from the media and parse it
+ if os.path.exists("%s/.discinfo" %(mnt,)):
+ f = open("%s/.discinfo" %(mnt,), "r")
+ lines = f.readlines()
+ f.close()
+ theid = lines[0].strip()
+ discs_s = lines[3].strip()
+
+ # if discs_s == ALL then no need to match disc number
+ if discs_s != 'ALL':
+ discs = map(lambda x: int(x), discs_s.split(","))
+ samenum = disc_number in discs
+ else:
+ samenum = True
+
+ # if the media is different or of different number skip it and loop over
+ if media_id != theid or not samenum:
+ continue
+
+ # the actual copying is done by URLGrabber
+ ug = URLGrabber(checkfunc = kwargs["checkfunc"])
+ try:
+ ug.urlgrab("%s/%s" %(mnt, kwargs["relative"]),
+ kwargs["local"], text=kwargs["text"],
+ range=kwargs["range"], copy_local=1)
+ except (IOError, URLGrabError):
+ pass
+ else:
+ found = True
+
+ # if we found it end the for loop
+ if found:
+ break
+
+ # if we found it end the while loop
+ if found:
+ break
+
+ # construct human readable media_text
+ if disc_number:
+ media_text = "%s #%d" % (name, disc_number)
+ else:
+ media_text = name
+
+ # see http://lists.freedesktop.org/archives/packagekit/2009-May/004808.html
+ # and http://cgit.freedesktop.org/packagekit/commit/?id=79e8736197b552a5ce206a712cd3b6c80cf2e86d
+ self.backend.media_change_required(MEDIA_TYPE_DISC, name, media_text)
+ self.backend.error(ERROR_MEDIA_CHANGE_REQUIRED,
+ "Insert media labeled '%s' or disable media repos" % media_text,
+ exit = False)
+ break
+
+ # if we got a media object destruct it to release the media (which will unmount and unlock if needed)
+ if media:
+ del media
+
+ # I guess we come here when the user in PK clicks cancel
+ if not found:
+ # yumRepo will catch this
+ raise yum.Errors.MediaError, "The disc was not inserted"
+ return kwargs["local"]
+
def _repo_gpg_confirm(self, keyData):
""" Confirm Repo GPG signature import """
if not keyData:
diff --git a/backends/yum/yumMediaManager.py b/backends/yum/yumMediaManager.py
new file mode 100644
index 000000000..9f1db4336
--- /dev/null
+++ b/backends/yum/yumMediaManager.py
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Copyright (C) 2009
+# Muayyad Saleh Alsadi <alsadi@ojuba.org>
+
+"""
+This is a module for dealing with removable media
+NOTE: releasing (unmounting and unlocking) is done when media is destructed
+"""
+
+class MediaDevice(object):
+ """
+ You should just use acquire() to get the mount point (the implementation is
+ supposed to be smart enough to return mount point when it's already mounted)
+ You don't need to manually call release(), just destruct MediaDevice object
+ and the implementation should do that if needed.
+ """
+ def __init__(self, media_id):
+ """
+ media_id argument is the implementation-specific id, provided by MediaManager.
+ """
+ self._unmount_needed = False
+ self._unlocked_needed = False
+ raise NotImplemented
+
+ def __del__(self):
+ if self._unmount_needed:
+ self.unmount()
+ if self._unlocked_needed:
+ self.unlock()
+
+ def is_removable(self):
+ raise NotImplemented
+
+ def is_mounted(self):
+ raise NotImplemented
+
+ def is_locked(self):
+ raise NotImplemented
+
+ def get_mount_point(self):
+ raise NotImplemented
+
+ def lock(self):
+ raise NotImplemented
+
+ def unlock(self):
+ raise NotImplemented
+
+ def mount(self):
+ raise NotImplemented
+
+ def unmount(self):
+ raise NotImplemented
+
+ def acquire(self):
+ raise NotImplemented
+
+ def release(self):
+ raise NotImplemented
+
+class MediaManager (object):
+ """Just iterate over an instance of this class to get MediaDevice objects"""
+ def __init__(self):
+ raise NotImplemented
+
+ def __iter__(self):
+ raise NotImplemented
+