backend/server/importlib/Makefile | 2
backend/server/importlib/debPackage.py | 152 ++++++++++++
backend/server/importlib/mpmSource.py | 4
backend/server/rhnPackageUpload.py | 27 +-
backend/spacewalk-backend.spec | 8
backend/spacewalk/common/rhn_deb.py | 148 +++++++++++
backend/spacewalk/common/rhn_mpm.py | 4
backend/upload_server/handlers/package_push/package_push.py | 2
rel-eng/packages/spacewalk-backend | 2
9 files changed, 337 insertions(+), 12 deletions(-)
New commits:
commit 36c281ebd9bd11e357a3878c6e3a892f9397e4f0
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Fri Apr 30 13:44:56 2010 +0200
Automatic commit of package [spacewalk-backend] release [1.1.10-1].
diff --git a/backend/spacewalk-backend.spec b/backend/spacewalk-backend.spec
index c84d256..fe09cec 100644
--- a/backend/spacewalk-backend.spec
+++ b/backend/spacewalk-backend.spec
@@ -8,7 +8,7 @@ Name: spacewalk-backend
Summary: Common programs needed to be installed on the Spacewalk servers/proxies
Group: Applications/Internet
License: GPLv2
-Version: 1.1.9
+Version: 1.1.10
Release: 1%{?dist}
URL:
https://fedorahosted.org/spacewalk
Source0:
https://fedorahosted.org/releases/s/p/spacewalk/%{name}-%{version}.tar.gz
@@ -632,6 +632,9 @@ rm -f %{rhnconf}/rhnSecret.py*
# $Id$
%changelog
+* Fri Apr 30 2010 Miroslav Suchý <msuchy(a)redhat.com> 1.1.10-1
+- Support for uploading deb packages (lukas.durfina(a)gmail.com)
+
* Fri Apr 30 2010 Jan Pazdziora 1.1.9-1
- 585233 - use log2stderr instead of the (debugging) print.
- 585233 - fix the logic handling has_comps and missing comps_last_modified.
diff --git a/rel-eng/packages/spacewalk-backend b/rel-eng/packages/spacewalk-backend
index 6ae0e0e..e3c9b5e 100644
--- a/rel-eng/packages/spacewalk-backend
+++ b/rel-eng/packages/spacewalk-backend
@@ -1 +1 @@
-1.1.9-1 backend/
+1.1.10-1 backend/
commit aa2b087df2bdb42680493bbbedd11d29a1a74af0
Author: Lukáš Ďurfina <lukas.durfina(a)gmail.com>
Date: Sat Apr 10 20:47:23 2010 +0200
Support for uploading deb packages
diff --git a/backend/server/importlib/Makefile b/backend/server/importlib/Makefile
index 84d5414..bda76a9 100644
--- a/backend/server/importlib/Makefile
+++ b/backend/server/importlib/Makefile
@@ -8,7 +8,7 @@ SUBDIR = server/importlib
FILES = __init__ archImport backendLib backendOracle backend \
blacklistImport \
- channelImport errataCache errataImport headerSource importLib \
+ channelImport debPackage errataCache errataImport headerSource importLib \
kickstartImport mpmSource \
packageImport productNamesImport packageUpload userAuth
diff --git a/backend/server/importlib/debPackage.py
b/backend/server/importlib/debPackage.py
new file mode 100644
index 0000000..ed22ca7
--- /dev/null
+++ b/backend/server/importlib/debPackage.py
@@ -0,0 +1,152 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2010 Red Hat, Inc.
+#
+# This software is licensed to you under the GNU General Public License,
+# version 2 (GPLv2). There is NO WARRANTY for this software, express or
+# implied, including the implied warranties of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+# along with this software; if not, see
+#
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# Red Hat trademarks are not licensed under GPLv2. No permission is
+# granted to use or replicate Red Hat trademarks that are incorporated
+# in this software or its documentation.
+#
+#
+# Converts headers to the intermediate format
+#
+
+import headerSource
+import os
+import time
+import string
+from importLib import File, Dependency, ChangeLog, Channel, \
+ IncompletePackage, Package, SourcePackage
+from backendLib import gmtime, localtime
+from types import ListType, TupleType, IntType
+
+
+class debBinaryPackage(headerSource.rpmBinaryPackage):
+
+ def __init__(self, header, size, checksum_type, checksum, path=None, org_id=None,
+ channels=[]):
+
+ headerSource.rpmBinaryPackage.__init__(self)
+
+ self.tagMap = headerSource.rpmBinaryPackage.tagMap.copy()
+
+ # Remove already-mapped tags
+ self._already_mapped = [
+ 'rpm_version', 'payload_size', 'payload_format',
+ 'package_group', 'build_time', 'build_host'
+ ]
+
+ for t in self._already_mapped:
+ if self.tagMap.has_key(t):
+ del self.tagMap[t]
+
+ # XXX is seems to me that this is the place that 'source_rpm' is getting
+ # set
+ for f in self.keys():
+ field = f
+ if self.tagMap.has_key(f):
+ field = self.tagMap[f]
+ if not field:
+ # Unsupported
+ continue
+
+ # get the db field value from the header
+ val = header[field]
+ if f == 'build_time':
+ if val is not None and isinstance(val, IntType):
+ # A UNIX timestamp
+ val = gmtime(val)
+ elif val:
+ # Convert to strings
+ if isinstance(val, unicode):
+ val = unicode.encode(val, 'utf-8')
+ else:
+ val = str(val)
+ elif val == []:
+ val = None
+ self[f] = val
+
+ self['package_size'] = size
+ self['checksum_type'] = checksum_type
+ self['checksum'] = checksum
+ self['path'] = path
+ self['org_id'] = org_id
+ self['header_start'] = None
+ self['header_end'] = None
+ self['last_modified'] = localtime(time.time())
+ if self['sigmd5']:
+ self['sigchecksum_type'] = 'md5'
+ self['sigchecksum'] = self['sigmd5']
+ del(self['sigmd5'])
+
+ # Fix some of the information up
+ vendor = self['vendor']
+ if vendor is None:
+ self['vendor'] = 'Debian'
+ payloadFormat = self['payload_format']
+ if payloadFormat is None:
+ self['payload_format'] = 'ar'
+ if self['payload_size'] is None:
+ self['payload_size'] = 0
+
+ # Populate file information
+ self._populateFiles(header)
+ # Populate dependency information
+ self._populateDependencyInformation(header)
+ # Populate changelogs
+ self._populateChangeLog(header)
+ # Channels
+ self._populateChannels(channels)
+
+ self['source_rpm'] = None
+
+ group = self.get('package_group', '')
+ if group == '' or group is None:
+ self['package_group'] = 'NoGroup'
+
+
+ def _populateFiles(self, header):
+ files = []
+ #for f in header.get('files', []):
+ # fc = headerSource.rpmFile()
+ # fc.populate(f)
+ # files.append(fc)
+ self['files'] = files
+
+ def _populateDependencyInformation(self, header):
+ mapping = {
+ 'provides' : headerSource.rpmProvides,
+ 'requires' : headerSource.rpmRequires,
+ 'conflicts' : headerSource.rpmConflicts,
+ 'obsoletes' : headerSource.rpmObsoletes,
+ }
+ for k, dclass in mapping.items():
+ l = []
+ #for dinfo in header.get(k, []):
+ # finst = dclass()
+ # finst.populate(dinfo)
+ # l.append(finst)
+ self[k] = l
+
+ def _populateChangeLog(self, header):
+ l = []
+ #for cinfo in header.get('changelog', []):
+ # cinst = headerSource.rpmChangeLog()
+ # cinst.populate(cinfo)
+ # l.append(cinst)
+ self['changelog'] = l
+
+ def _populateChannels(self, channels):
+ l = []
+ for channel in channels:
+ dict = {'label' : channel}
+ obj = Channel()
+ obj.populate(dict)
+ l.append(obj)
+ self['channels'] = l
diff --git a/backend/server/importlib/mpmSource.py
b/backend/server/importlib/mpmSource.py
index a7224b9..4bc27a4 100644
--- a/backend/server/importlib/mpmSource.py
+++ b/backend/server/importlib/mpmSource.py
@@ -18,6 +18,7 @@
#
import headerSource
+import debPackage
from importLib import SolarisPatchInfo, \
SolarisPatchPackagesInfo, SolarisPatchSetInfo, \
SolarisPatchSetMember, SolarisPackageInfo
@@ -219,6 +220,9 @@ def create_package(header, size, checksum_type, checksum, relpath,
org_id, heade
checksum_type=checksum_type, checksum=checksum,
relpath=relpath, org_id=org_id, header_start=header_start,
header_end=header_end, channels=channels)
+ if header.packaging == 'deb':
+ return debPackage.debBinaryPackage(header, size=size,
checksum_type=checksum_type, checksum=checksum, path=relpath,
+ org_id=org_id, channels=channels)
if header.is_source:
raise NotImplementedError()
p = mpmBinaryPackage()
diff --git a/backend/server/rhnPackageUpload.py b/backend/server/rhnPackageUpload.py
index 24d07e0..6c3e3a6 100644
--- a/backend/server/rhnPackageUpload.py
+++ b/backend/server/rhnPackageUpload.py
@@ -19,7 +19,7 @@ import os
import tempfile
from common import CFG, log_debug, rhnFault, UserDictCase
-from spacewalk.common import rhn_mpm
+from spacewalk.common import rhn_mpm, rhn_deb
from spacewalk.common.checksum import getFileChecksum
from spacewalk.common.rhn_rpm import get_header_byte_range
@@ -40,11 +40,14 @@ def source_match(v1, v2):
return 0
-def write_temp_file(req, buffer_size):
+def write_temp_file(req, buffer_size, packaging=None):
""" Write request to temporary file (write max. buffer_size at once).
Returns the file object.
"""
- t = tempfile.TemporaryFile()
+ suffix = ''
+ if packaging == 'deb':
+ suffix = '.deb'
+ t = tempfile.NamedTemporaryFile(suffix=suffix)
while 1:
buf = req.read(buffer_size)
if not buf:
@@ -148,6 +151,8 @@ def push_package(header, payload_stream, checksum_type, checksum,
org_id=None, f
raise rhnFault(50, "Package upload failed: %s" % e)
except importLib.FileConflictError:
raise rhnFault(50, "File already exists")
+ except:
+ raise rhnFault(50, "File error")
pkg = mpmSource.create_package(header, size=payload_size,
checksum_type=checksum_type, checksum=checksum,
@@ -290,13 +295,19 @@ def _key_ids(sigs):
return l
def load_package(package_stream):
- try:
- header, payload_stream = rhn_mpm.load(file=package_stream)
- except rhn_mpm.InvalidPackageError, e:
- raise rhnFault(50, "Unable to load package", explain=0)
+ if package_stream.name.endswith('.deb'):
+ try:
+ header, payload_stream = rhn_deb.load(filename=package_stream.name)
+ except:
+ raise rhnFault(50, "Unable to load package", explain=0)
+ else:
+ try:
+ header, payload_stream = rhn_mpm.load(file=package_stream)
+ except:
+ raise rhnFault(50, "Unable to load package", explain=0)
payload_stream.seek(0, 0)
- if header.packaging == "mpm":
+ if header.packaging == "mpm" or header.packaging == "deb":
header.header_start = header.header_end = 0
(header_start, header_end) = (0, 0)
else:
diff --git a/backend/spacewalk-backend.spec b/backend/spacewalk-backend.spec
index 71466cb..c84d256 100644
--- a/backend/spacewalk-backend.spec
+++ b/backend/spacewalk-backend.spec
@@ -18,6 +18,8 @@ Requires: python, rpm-python
# /etc/rhn is provided by spacewalk-proxy-common or by spacewalk-config
Requires: /etc/rhn
Requires: rhnlib >= 1.8
+# for Debian support
+Requires: python-debian
Requires: %{name}-libs = %{version}-%{release}
BuildRequires: /usr/bin/msgfmt
BuildRequires: /usr/bin/docbook2man
@@ -382,6 +384,7 @@ rm -f %{rhnconf}/rhnSecret.py*
%{rhnroot}/server/importlib/backendOracle.py*
%{rhnroot}/server/importlib/blacklistImport.py*
%{rhnroot}/server/importlib/channelImport.py*
+%{rhnroot}/server/importlib/debPackage.py*
%{rhnroot}/server/importlib/errataCache.py*
%{rhnroot}/server/importlib/errataImport.py*
%{rhnroot}/server/importlib/headerSource.py*
diff --git a/backend/spacewalk/common/rhn_deb.py b/backend/spacewalk/common/rhn_deb.py
new file mode 100644
index 0000000..b108ecb
--- /dev/null
+++ b/backend/spacewalk/common/rhn_deb.py
@@ -0,0 +1,148 @@
+#
+# Copyright (c) 2010 Red Hat, Inc.
+#
+# This software is licensed to you under the GNU General Public License,
+# version 2 (GPLv2). There is NO WARRANTY for this software, express or
+# implied, including the implied warranties of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+# along with this software; if not, see
+#
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# Red Hat trademarks are not licensed under GPLv2. No permission is
+# granted to use or replicate Red Hat trademarks that are incorporated
+# in this software or its documentation.
+#
+#
+# Meta-package manager
+#
+# $Id$
+#
+# Author: Lukas Durfina <lukas.durfina(a)gmail.com>
+
+import os
+import gzip
+import cStringIO
+import tempfile
+from rhn.rpclib import xmlrpclib
+
+from debian import debfile
+import struct
+
+from types import ListType, TupleType, DictType
+
+DEB_CHECKSUM_TYPE = 'md5' # FIXME: this should be a configuration option
+
+def get_package_header(filename=None, file=None, fd=None):
+ return load(filename=filename, file=file, fd=fd)[0]
+
+# Loads DEB and returns its header and its payload
+def load(filename=None, file=None, fd=None):
+ if (filename is None):
+ raise ValueError, "filename has to be passed"
+ if (filename is None and file is None and fd is None):
+ raise ValueError, "No parameters passed"
+
+ if filename is not None:
+ f = open(filename)
+ elif file is not None:
+ f = file
+ else: # fd is not None
+ f = os.fdopen(os.dup(fd), "r")
+
+ f.seek(0, 0)
+ return load_deb(f, filename)
+
+def load_deb(stream, filename):
+
+ # Dup the file descriptor, we don't want it to get closed before we read
+ # the payload
+ newfd = os.dup(stream.fileno())
+ stream = os.fdopen(newfd, "r")
+
+ stream.flush()
+ stream.seek(0, 0)
+
+
+ try:
+ #header = rhn_deb.get_package_header(file=stream)
+ header = deb_Header(filename)
+ except:
+ raise InvalidPackageError(e)
+ stream.seek(0, 0)
+
+ return header, stream
+
+class deb_Header:
+ "Wrapper class for an deb header - we need to store a flag is_source"
+ def __init__(self, name):
+ self.hdr = {}
+ self.packaging = 'deb'
+ self.signatures = []
+ self.name = ''
+ self.version = 0
+ self.release = 0
+ self.arch = 'all'
+ self.is_source = 0
+ self.deb = None
+
+ try:
+ self.deb = debfile.DebFile(name)
+ except Exception, e:
+ raise InvalidPackageError(e)
+
+ try:
+ # Fill info about package
+ self.name = self.deb.debcontrol().get_as_string('Package')
+ self.arch = self.deb.debcontrol().get_as_string('Architecture') +
'-deb'
+ version = self.deb.debcontrol().get_as_string('Version')
+ version_tmpArr = version.split('-')
+ if len(version_tmpArr) == 1:
+ self.version = version
+ self.release = "X"
+ else:
+ self.version = version_tmpArr[0]
+ self.release = version_tmpArr[1]
+ except Exception, e:
+ raise InvalidPackageError(e)
+
+ def checksum_type(self):
+ return DEB_CHECKSUM_TYPE
+
+ def is_signed(self):
+ return 0
+
+ def __getitem__(self, name):
+ name = str(name)
+ if name == 'name':
+ return self.name
+ elif name == 'arch':
+ return self.arch
+ elif name == 'release':
+ return self.release
+ elif name == 'version':
+ return self.version
+ elif name == 'epoch':
+ return ''
+ elif name == 'summary':
+ return
self.deb.debcontrol().get_as_string('Description').splitlines()[0]
+ elif name == 'vendor':
+ return self.deb.debcontrol().get_as_string('Maintainer')
+ elif name == 'package_group':
+ return self.deb.debcontrol().get_as_string('Section')
+ if self.deb.debcontrol().has_key(name):
+ return self.deb.debcontrol().get_as_string(name)
+ else:
+ return None
+"""
+ def __setitem__(self, name, item):
+ self.hdr[name] = item
+
+ def __delitem__(self, name):
+ del self.hdr[name]
+
+ def __getattr__(self, name):
+ return getattr(self.hdr, name)
+"""
+
+class InvalidPackageError(Exception):
+ pass
diff --git a/backend/spacewalk/common/rhn_mpm.py b/backend/spacewalk/common/rhn_mpm.py
index 7868a79..12bea83 100644
--- a/backend/spacewalk/common/rhn_mpm.py
+++ b/backend/spacewalk/common/rhn_mpm.py
@@ -58,6 +58,8 @@ def load(filename=None, file=None, fd=None):
return load_rpm(f)
except InvalidPackageError:
raise e
+ except:
+ raise e
return p.header, p.payload_stream
@@ -83,6 +85,8 @@ def load_rpm(stream):
raise apply(InvalidPackageError, e.args)
except rhn_rpm.error, e:
raise InvalidPackageError(e)
+ except:
+ raise InvalidPackageError
stream.seek(0, 0)
return header, stream
diff --git a/backend/upload_server/handlers/package_push/package_push.py
b/backend/upload_server/handlers/package_push/package_push.py
index e1b1052..e3dac16 100644
--- a/backend/upload_server/handlers/package_push/package_push.py
+++ b/backend/upload_server/handlers/package_push/package_push.py
@@ -108,7 +108,7 @@ class PackagePush(basePackageUpload.BasePackageUpload):
if ret != apache.OK:
return ret
- temp_stream = rhnPackageUpload.write_temp_file(req, 16384)
+ temp_stream = rhnPackageUpload.write_temp_file(req, 16384, self.packaging)
header, payload_stream, header_start, header_end = \
rhnPackageUpload.load_package(temp_stream)