def add_virtiogt(self, paths): """ Move virtiogt msis into the local virtio-win direct tree """ virtiodir = os.path.join(self.LOCAL_DIRECT_DIR, self.virtio_basedir) for path in paths: shellcomm("cp %s %s" % (path, virtiodir))
def main(): options = parse_args() output_dir = options.output_dir if not os.path.exists(output_dir): os.mkdir(output_dir) if os.listdir(output_dir): fail("%s is not empty." % output_dir) shellcomm("git submodule init") shellcomm("git submodule update") driverdir = os.path.abspath(options.driverdir) vdagent_x64_msi = os.path.abspath(options.vdagent_x64_msi) vdagent_x86_msi = os.path.abspath(options.vdagent_x86_msi) qxlwddm_x64_msi = os.path.abspath(options.qxlwddm_x64_msi) qxlwddm_x86_msi = os.path.abspath(options.qxlwddm_x86_msi) ga_x64_msi = os.path.abspath(options.ga_x64_msi) ga_x86_msi = os.path.abspath(options.ga_x86_msi) win_fsp_msi = os.path.abspath(options.win_fsp_msi) os.chdir("virtio-win-guest-tools-installer") shellcomm("git clean -xdf") shellcomm( "./automation/build-artifacts.sh %s %s %s %s %s %s %s %s %s" % (driverdir, vdagent_x64_msi, vdagent_x86_msi, qxlwddm_x64_msi, qxlwddm_x86_msi, ga_x64_msi, ga_x86_msi, win_fsp_msi, options.nvr)) shellcomm("mv ./exported-artifacts/* %s" % output_dir) return 0
def _prep_qxldod_msi(driver_input_dir, msi_dst_dir): """ """ msi_dir = os.path.join(driver_input_dir, "spice-qxl-wddm-dod/w10/") for msifile in glob.glob(os.path.join(msi_dir, "*.msi")): if (re.search("QxlWddmDod_", msifile)): shellcomm("cp -r %s %s" % (msifile, msi_dst_dir))
def add_virtiowin_media(self, paths): """ Move iso/vfd media to the local tree. Set up symlinks and htaccess magic for the non-versioned links """ virtiodir = os.path.join( self.LOCAL_DIRECT_DIR, self.virtio_basedir) if os.path.exists(virtiodir): fail("dir=%s already exists? Make sure we aren't " "overwriting anything." % virtiodir) os.mkdir(virtiodir) htaccess = "" for versionfile, symlink in paths: shellcomm("cp %s %s" % (versionfile, virtiodir)) shellcomm("cp %s %s" % (symlink, virtiodir)) htaccess += _make_redirect( os.path.join(self.HTTP_DIRECT_DIR, self.virtio_basedir), os.path.basename(symlink), os.path.basename(versionfile)) # Write .htaccess, redirecting symlinks to versioned files, so # nobody ends up with unversioned files locally, since that # will make for crappy bug reports open(os.path.join(virtiodir, ".htaccess"), "w").write(htaccess)
def _prep_spice_vdagent_msi(msi_dst_dir): """ Find and copy spice-vdagent-x64(x86).msi to a new directory to be used later on by make-installer.py """ for msifile in glob.glob(os.path.join(NEW_BUILDS_DIR, "*.msi")): if (re.search("spice-vdagent-", msifile)): shellcomm("cp -r %s %s" % (msifile, msi_dst_dir))
def _prep_win_fsp_msi(msi_dst_dir): """ Find and copy winfsp.msi to a new directory to be used later on by make-installer.py """ for msifile in glob.glob(os.path.join(NEW_BUILDS_DIR, "*.msi")): if (re.search("winfsp-", msifile)): shellcomm("cp -r %s %s" % (msifile, msi_dst_dir))
def _run_createrepo(): """ Run yum createrepo """ for rpmdir in ["latest", "stable", "srpms"]: #shellcomm("rm -rf %s" % # os.path.join(LOCAL_REPO_DIR, rpmdir, "repodata")) shellcomm("createrepo_c %s --update > /dev/null" % os.path.join(LocalRepo.LOCAL_REPO_DIR, rpmdir))
def add_rpms(self, paths): """ Add the build RPM to the local tree """ for path in paths: dest = "rpms" if path.endswith(".src.rpm"): dest = "srpms" shellcomm("cp %s %s/%s" % (path, self.LOCAL_REPO_DIR, dest))
def extract_files(filename): """ Passed in either a zip, tar.gz, or RPM, extract the contents, including the contents of any contained vfd or iso files. Move these to a temp directory for easy comparison. """ output_dir = tempfile.mkdtemp(prefix="virtio-win-archive-compare-") atexit.register(lambda: shutil.rmtree(output_dir)) # Extract the content if os.path.isdir(filename): shutil.copytree(filename, os.path.join(output_dir, "dircopy")) else: extract_dir = os.path.join(output_dir, "extracted-archive") os.mkdir(extract_dir) if os.path.isdir(filename): pass elif filename.endswith(".zip"): shellcomm("unzip %s -d %s > /dev/null" % (filename, extract_dir)) elif filename.endswith(".tar.gz"): shellcomm("tar -xvf %s --directory %s > /dev/null" % (filename, extract_dir)) elif filename.endswith(".rpm"): shellcomm("cd %s && rpm2cpio %s | cpio -idm --quiet" % (extract_dir, filename)) else: fail("Unexpected filename %s, only expecting .zip, *.tar.gz, .rpm, " "or a directory" % filename) # Find .vfd files mediafiles = [] for root, dirs, files in os.walk(output_dir): dummy = dirs mediafiles += [ os.path.join(root, name) for name in files if name.endswith(".vfd") or name.endswith(".iso") ] # Extract vfd file contents with guestfish for mediafile in mediafiles: if os.path.islink(mediafile): continue media_out_dir = os.path.join( output_dir, os.path.basename(mediafile) + "-extracted") os.mkdir(media_out_dir) shellcomm( "guestfish --ro --add %s --mount /dev/sda:/ glob copy-out '/*' %s" " > /dev/null" % (mediafile, media_out_dir)) shellcomm("chmod -R 777 %s" % media_out_dir) return output_dir
def add_link(src, link): fullsrc = os.path.join(self.LOCAL_DIRECT_DIR, src) linkpath = os.path.join(self.LOCAL_DIRECT_DIR, link) if not os.path.exists(fullsrc): fail("Nonexistent link src=%s for target=%s" % (fullsrc, linkpath)) if os.path.exists(linkpath): os.unlink(linkpath) shellcomm("ln -s %s %s" % (src, linkpath)) return _make_redirect(self.HTTP_DIRECT_DIR, link, src)
def add_qemuga(self, paths): """ Move qemuga msis into the local tree """ qemugadir = os.path.join(self.LOCAL_DIRECT_DIR, self.qemuga_basedir) if os.path.exists(qemugadir): print("qemuga has already been uploaded, skipping: %s" % os.path.basename(qemugadir)) return os.mkdir(qemugadir) for path in paths: shellcomm("cp %s %s" % (path, qemugadir))
def _rpmbuild(spec, rpm_src_dir, rpm_build_dir, rpm_output_dir): """ Perform the rpmbuild command """ shellcomm("cd {topdir} && rpmbuild -ba --noclean " "--define '_topdir {topdir}' " "--define '_sourcedir {topdir}' " "--define '_specdir {topdir}' " "--define '_builddir {builddir}' " "--define '_buildrootdir {builddir}' " "--define '_rpmdir {outputdir}' " "--define '_srcrpmdir {outputdir}' {spec}".format( topdir=rpm_src_dir, builddir=rpm_build_dir, outputdir=rpm_output_dir, spec=spec.basename))
def add_pkg_build_input(self, buildversions): """ Upload the NEW_BUILDS_DIR content we used, so people can reproduce the build if they need to """ pkg_input_topdir = os.path.join(self.LOCAL_DIRECT_DIR, "virtio-win-pkg-scripts-input") pkg_input_dir = os.path.join(pkg_input_topdir, self.virtio_release_str) if os.path.exists(pkg_input_dir): print("%s exists, not changing content." % pkg_input_dir) else: os.mkdir(pkg_input_dir) for filename in glob.glob(buildversions.NEW_BUILDS_DIR + "/*"): shellcomm("cp %s %s" % (filename, pkg_input_dir)) _add_relative_link(pkg_input_topdir, os.path.basename(pkg_input_dir), "latest-build")
def main(): options = parse_args() # Parse new package versions buildversions = BuildVersions() # Do some RPM buildroot prep rpm_src_dir = _tempdir('rpmbuild-src') _prep_rpm_src_dir(buildversions, rpm_src_dir) # Call public scripts to generate the virtio .zip driver_input_dir = _tempdir("make-driver-dir-input") _prep_driver_dir_input(driver_input_dir) # Build the driver dir/iso dir layout driver_output_dir = _tempdir("make-driver-dir-output") shellcomm("./make-driver-dir.py %s --output-dir %s" % (driver_input_dir, driver_output_dir)) # Generate RPM input archive + vfd + iso shellcomm("./make-virtio-win-rpm-archive.py %s %s" % (buildversions.virtio_rpm_str, driver_output_dir)) shellcomm("mv *.tar.gz %s" % rpm_src_dir) # Alter and save spec + changelog spec = Spec(buildversions) _prompt_for_rpm_changelog(buildversions, spec) spec.write_changes(rpm_src_dir) # Call rpmbuild rpm_build_dir = _tempdir('rpmbuild-buildroot') rpm_output_dir = _tempdir('rpmbuild-output') _rpmbuild(spec, rpm_src_dir, rpm_build_dir, rpm_output_dir) if options.rpm_only: print("RPMs can be found in: %s" % rpm_output_dir) return 0 # Trigger make-repo.py cmd = ("./make-repo.py --rpm-output %s --rpm-buildroot %s" % (rpm_output_dir, rpm_build_dir)) print("\n\n") print(cmd) if yes_or_no("Run that make-repo.py command? (y/n): "): shellcomm(cmd) print() print() print("Don't forget to:") print("- Commit all the spec file changes") print("- If this is a stable build, update the STABLE_RPMS list in") print(" this scripts code and re-run with --repo-only") print("- Delete any local tmp* dirs") print() return 0
def _rpmbuild(spec, rpm_src_dir, rpm_build_dir, rpm_output_dir): """ Perform the rpmbuild command """ shellcomm("cd {topdir} && rpmbuild -ba --noclean " "--define '_topdir {topdir}' " "--define '_sourcedir {topdir}' " "--define '_specdir {topdir}' " "--define '_builddir {builddir}' " "--define '_buildrootdir {builddir}' " "--define '_rpmdir {outputdir}' " "--define '_srcrpmdir {outputdir}' " "--define '_source_payload w6.xzdio' " "--define '_binary_payload w6.xzdio' " "--with fedora_defaults " "{spec}".format(topdir=rpm_src_dir, builddir=rpm_build_dir, outputdir=rpm_output_dir, spec=spec.basename))
def _add_relative_link(topdir, srcname, linkname): """ Create symlink for passed paths, but using relative path resolution """ srcpath = os.path.join(topdir, srcname) linkpath = os.path.join(topdir, linkname) if not os.path.exists(srcpath): fail("Nonexistent link src=%s for target=%s" % (srcpath, linkpath)) srcrelpath = os.path.relpath(srcname, os.path.dirname(linkname)) if os.path.exists(linkpath): if (os.path.islink(linkpath) and os.readlink(linkpath) == srcrelpath): print("link path=%s already points to src=%s, nothing to do" % (linkpath, srcrelpath)) return os.unlink(linkpath) shellcomm("ln -s %s %s" % (srcrelpath, linkpath))
def main(): options = parse_args() origdir = extract_files(os.path.abspath(options.orig)) newdir = extract_files(os.path.abspath(options.new)) print() print() print("tree diff:") shellcomm("""bash -c 'diff -rup <(cd %s; tree) <(cd %s; tree)'""" % (origdir, newdir)) if not options.treeonly: print() print() print("file diff:") shellcomm(r"diff -rup --exclude \*.vfd --exclude \*.iso %s %s" % (origdir, newdir)) return 0
def _generate_repos(): """ Create repo trees, run createrepo_c """ LOCAL_REPO_DIR = LocalRepo.LOCAL_REPO_DIR # Generate stable symlinks for stablever in STABLE_RPMS: filename = "virtio-win-%s.noarch.rpm" % stablever _add_relative_link(LOCAL_REPO_DIR, "rpms/%s" % filename, "stable/%s" % filename) # Generate latest symlinks for fullpath in glob.glob(os.path.join(LOCAL_REPO_DIR, "rpms", "*.rpm")): filename = os.path.basename(fullpath) _add_relative_link(LOCAL_REPO_DIR, "rpms/%s" % filename, "latest/%s" % filename) # Generate repodata for rpmdir in ["latest", "stable", "srpms"]: #shellcomm("rm -rf %s" % # os.path.join(LOCAL_REPO_DIR, rpmdir, "repodata")) shellcomm("createrepo_c %s --update > /dev/null" % os.path.join(LOCAL_REPO_DIR, rpmdir)) def cp(srcpath, dstpath): # Copy, but not if content is unchanged if (os.path.exists(dstpath) and open(srcpath).read() == open(dstpath).read()): print("%s is up to date, skipping." % dstpath) return shutil.copy(srcpath, dstpath) # Put the repo file in place cp("data/virtio-win.repo", os.path.join(LocalRepo.LOCAL_ROOT_DIR, "virtio-win.repo")) # Use the RPM changelog as a changelog file for the whole tree cp("data/rpm_changelog", os.path.join(LocalRepo.LOCAL_ROOT_DIR, "CHANGELOG"))
def _run_rsync(reverse, dry): rsync = "rsync --archive --verbose --compress --progress " if dry: rsync += "--dry-run " remote = ("%[email protected]:~/virtgroup/virtio-win" % LocalRepo.HOSTED_USERNAME) local = LocalRepo.LOCAL_ROOT_DIR if reverse: src = remote dst = local else: src = local dst = remote # Put the RPMs in place shellcomm("%s --exclude repodata %s/ %s" "" % (rsync, src, dst)) # Overwrite the repodata and remove stale files shellcomm("%s --delete %s/ %s" % (rsync, src, dst))
def _prep_driver_dir_input(driver_input_dir): """ Extract NEW_BUILDS_DIR/ content, apply some fix ups, so we can run make-driver-dir.py against it """ # Extract virtio/qxl/... build archives for zipfile in glob.glob(os.path.join(NEW_BUILDS_DIR, "*.zip")): if zipfile.endswith("-sources.zip"): continue zipbasename = os.path.basename(zipfile) is_qxl_old = bool(re.match(r"^qxl_.*$", zipbasename)) is_qxl_dod = bool(re.match( r"^spice-qxl-wddm-dod-\d+\.\d+.zip$", zipbasename)) # Unpack qxl_* to $dir/qxl/ # Unpack latest qxlwddm to $dir/spice-qxl-wddm-dod/ # Unpack 8.1 compat qxlwddm to $dir/, which because of the # .zip layout becomes $dir/spice-qxl-wddm-dod-8.1-compatible/ unzipdest = driver_input_dir if is_qxl_old: unzipdest = os.path.join(driver_input_dir, "qxl") elif is_qxl_dod: unzipdest = os.path.join(driver_input_dir, "spice-qxl-wddm-dod") shellcomm("unzip %s -d %s" % (zipfile, unzipdest)) # Copy static data/old-drivers/ content into place shellcomm("cp -r data/old-drivers/xp-viostor/* %s" % driver_input_dir) shellcomm("cp -r data/old-drivers/xp-qxl/* %s/qxl" % driver_input_dir)
def _run_rsync(reverse, dry): def _cmd(opts, src, dst): rsync = "rsync " rsync += "--archive --verbose --compress --progress " if not reverse: # There is no virtmaint-sig user, so we use our user rsync += "--chown=%s:virtmaint-sig " % LocalRepo.HOSTED_USERNAME # Set dirs to 775 and files to 664 rsync += "--chmod=D775,F664 " if dry: rsync += "--dry-run " rsync += "%s %s/ %s" % (opts, src, dst) if dry: # Filter out uninteresting repoadata updates rsync += " | grep -Ev 'repodata/.+'" return rsync remote = ("%[email protected]:/srv/groups/virt/virtio-win" % LocalRepo.HOSTED_USERNAME) local = LocalRepo.LOCAL_ROOT_DIR if reverse: src = remote dst = local else: src = local dst = remote # Put the RPMs in place. Skip yum repodata until RPMs # are inplace, to prevent users seeing an inconsistent repo shellcomm(_cmd("--exclude repodata", src, dst)) # Overwrite the repodata and remove stale files args = "" # This says we only want to sync repodata/* and below, so we # avoid possibly deleting anything else args += '--include "*/" --include "repodata/*" --exclude "*" ' args += "--delete" shellcomm(_cmd(args, src, dst))
def add_virtiowin_media(self, isopath, rpmpath, srpmpath): """ Move iso media to the local tree. Set up symlinks and htaccess magic for the non-versioned links """ virtiodir = os.path.join( self.LOCAL_DIRECT_DIR, self.virtio_basedir) if os.path.exists(virtiodir): fail("dir=%s already exists? Make sure we aren't " "overwriting anything." % virtiodir) os.mkdir(virtiodir) htaccess = "" def add_stable_path(path, stablename): versionname = os.path.basename(path) _add_relative_link(virtiodir, versionname, stablename) nonlocal htaccess htaccess += _make_redirect( os.path.join(self.HTTP_DIRECT_DIR, self.virtio_basedir), stablename, versionname) def add_rpm(path, stablename): # RPMs are already in the repo tree, so symlink the full path _add_relative_link(virtiodir, os.path.relpath(path, virtiodir), os.path.basename(path)) add_stable_path(path, stablename) add_rpm(rpmpath, "virtio-win.noarch.rpm") add_rpm(srpmpath, "virtio-win.src.rpm") shellcomm("cp %s %s" % (isopath, virtiodir)) add_stable_path(isopath, "virtio-win.iso") # Write .htaccess, redirecting symlinks to versioned files, so # nobody ends up with unversioned files locally, since that # will make for crappy bug reports open(os.path.join(virtiodir, ".htaccess"), "w").write(htaccess)
def _prep_rpm_src_dir(buildversions, rpm_src_dir): """ Do our fedora specific RPM buildroot preparation, like renaming some content to match the spec file, and moving NEW_BUILDS_DIR content into place. """ # Copy source archives to the RPM builddir shellcomm("cp %s/*-sources.zip %s" % (NEW_BUILDS_DIR, rpm_src_dir)) shellcomm("cp %s/*.rpm %s" % (NEW_BUILDS_DIR, rpm_src_dir)) # Extract the qemu-ga-win RPM to a tempdir, rename the .msi files # and zip them up into the form virtio-win.spec is expecting. # Yeah this is rediculous... qemu_ga_extractdir = _tempdir('mingw-qemu-ga-rpm-extracted') os.chdir(qemu_ga_extractdir) shellcomm("rpm2cpio %s/qemu-ga-win*.noarch.rpm | cpio -idmv" % NEW_BUILDS_DIR) shellcomm("find . -name qemu-ga-x86_64.msi " r"-exec mv '{}' qemu-ga-x64.msi \;") shellcomm("find . -name qemu-ga-i386.msi " r"-exec mv '{}' qemu-ga-x86.msi \;") shellcomm(r"mkdir {qemuga} && cp *.msi {qemuga} && " "zip -9 -r {rpmdir}/{qemuga}-installers.zip {qemuga} && " "rm -rf {qemuga}".format( qemuga=buildversions.qemu_ga_str, rpmdir=rpm_src_dir)) os.chdir(TOP_DIR)
def addpath(srcpath, repodir): dstpath = os.path.join(self.LOCAL_REPO_DIR, repodir, os.path.basename(srcpath)) shellcomm("cp %s %s" % (srcpath, dstpath)) return dstpath
def main(): options = parse_args() # Parse new package versions buildversions = BuildVersions() # Do some RPM buildroot prep rpm_src_dir = _tempdir('rpmbuild-src') _prep_rpm_src_dir(buildversions, rpm_src_dir) # Call public scripts to generate the virtio .zip driver_input_dir = _tempdir("make-driver-dir-input") _prep_driver_dir_input(driver_input_dir) # Build the driver dir/iso dir layout driver_output_dir = _tempdir("make-driver-dir-output") shellcomm("./make-driver-dir.py %s --output-dir %s" % (driver_input_dir, driver_output_dir)) spec = Spec(buildversions) # Build the driver installer installer_output_dir = _tempdir("make-installer-output") spice_dir = _tempdir("spice-extracted") winfsp_dir = _tempdir("make-winfsp-output") _prep_spice_vdagent_msi(spice_dir) _prep_qxldod_msi(driver_input_dir, spice_dir) _prep_win_fsp_msi(winfsp_dir) spice_vdagent_x64_msi = _find_msi(spice_dir, 'spice-vdagent-', 'x64') spice_vdagent_x86_msi = _find_msi(spice_dir, 'spice-vdagent-', 'x86') spice_driver_x64_msi = _find_msi(spice_dir, 'QxlWddmDod_', 'x64') spice_driver_x86_msi = _find_msi(spice_dir, 'QxlWddmDod_', 'x86') qemu_ga_agent_dir = os.path.join(TOP_TEMP_DIR, "mingw-qemu-ga-rpm-extracted") qemu_ga_agent_x64_msi = _find_msi(qemu_ga_agent_dir, 'qemu-ga-', 'x64') qemu_ga_agent_x86_msi = _find_msi(qemu_ga_agent_dir, 'qemu-ga-', 'x86') win_fsp_msi = _find_msi(winfsp_dir, 'winfsp-', '') shellcomm( "./make-installer.py %s %s %s %s %s %s %s %s %s --output-dir %s" % (spec.newversion, driver_output_dir, spice_vdagent_x64_msi, spice_vdagent_x86_msi, spice_driver_x64_msi, spice_driver_x86_msi, qemu_ga_agent_x64_msi, qemu_ga_agent_x86_msi, win_fsp_msi, installer_output_dir)) shellcomm("cp %s/* %s" % (installer_output_dir, rpm_src_dir)) # Generate RPM input archive + vfd + iso shellcomm("./make-virtio-win-rpm-archive.py %s %s" % (buildversions.virtio_rpm_str, driver_output_dir)) shellcomm("mv *.tar.gz %s" % rpm_src_dir) # Alter and save spec + changelog _prompt_for_rpm_changelog(buildversions, spec) spec.write_changes(rpm_src_dir) # Call rpmbuild rpm_build_dir = _tempdir('rpmbuild-buildroot') rpm_output_dir = _tempdir('rpmbuild-output') _rpmbuild(spec, rpm_src_dir, rpm_build_dir, rpm_output_dir) if options.rpm_only: print("RPMs can be found in: %s" % rpm_output_dir) return 0 # Trigger make-repo.py cmd = ("./make-repo.py --rpm-output %s --rpm-buildroot %s" % (rpm_output_dir, rpm_build_dir)) print("\n\n") print(cmd) if yes_or_no("Run that make-repo.py command? (y/n): "): shellcomm(cmd) print() print() print("Don't forget to:") print("- Commit all the spec file changes") print("- If this is a stable build, update the STABLE_RPMS list in") print(" this scripts code and re-run with --repo-only") print("- Delete any local tmp* dirs") print() return 0
def _generate_repos(): """ Create repo trees, run createrepo_c """ LOCAL_REPO_DIR = LocalRepo.LOCAL_REPO_DIR # Generate stable symlinks shellcomm("rm -rf %s/*" % os.path.join(LOCAL_REPO_DIR, "stable")) for stablever in STABLE_RPMS: filename = "virtio-win-%s.noarch.rpm" % stablever fullpath = os.path.join(LOCAL_REPO_DIR, "rpms", filename) if not os.path.exists(fullpath): fail("Didn't find stable RPM path %s" % fullpath) shellcomm("ln -s ../rpms/%s %s" % (filename, os.path.join(LOCAL_REPO_DIR, "stable", os.path.basename(fullpath)))) # Generate latest symlinks shellcomm("rm -rf %s/*" % os.path.join(LOCAL_REPO_DIR, "latest")) for fullpath in glob.glob(os.path.join(LOCAL_REPO_DIR, "rpms", "*.rpm")): filename = os.path.basename(fullpath) shellcomm("ln -s ../rpms/%s %s" % (filename, os.path.join(LOCAL_REPO_DIR, "latest", os.path.basename(fullpath)))) # Generate repodata for rpmdir in ["latest", "stable", "srpms"]: shellcomm("rm -rf %s" % os.path.join(LOCAL_REPO_DIR, rpmdir, "repodata")) shellcomm("createrepo_c %s > /dev/null" % os.path.join(LOCAL_REPO_DIR, rpmdir)) # Put the repo file in place shellcomm("cp -f data/virtio-win.repo %s" % LocalRepo.LOCAL_ROOT_DIR) # Use the RPM changelog as a changelog file for the whole tree shellcomm("cp -f data/rpm_changelog %s/CHANGELOG" % LocalRepo.LOCAL_ROOT_DIR)