summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSoonKyu Park <sk7.park@samsung.com>2019-12-26 14:12:17 +0900
committerSoonKyu Park <sk7.park@samsung.com>2019-12-26 14:12:17 +0900
commitff5819fa88cf0522c567925aa5919eb300c628f8 (patch)
treeb61ed2bca94da2d79fcc5a1ec95bca119960c9d5
parent190d64daadbdd442f9388b31bff028ae87237d22 (diff)
parent52732d20f9940e9d7a743d2537ce0e033a5cf698 (diff)
downloadmic-ff5819fa88cf0522c567925aa5919eb300c628f8.tar.gz
mic-ff5819fa88cf0522c567925aa5919eb300c628f8.tar.bz2
mic-ff5819fa88cf0522c567925aa5919eb300c628f8.zip
Change-Id: I6aa8025c850312f6a03f446f7876310900b277da
-rwxr-xr-x[-rw-r--r--]ChangeLog89
-rwxr-xr-x[-rw-r--r--]README.rst0
-rwxr-xr-x[-rw-r--r--]debian/changelog101
-rw-r--r--debian/control2
-rwxr-xr-xdebian/rules2
-rwxr-xr-x[-rw-r--r--]doc/RELEASE_NOTES189
-rw-r--r--etc/bash_completion.d/mic.sh2
-rw-r--r--etc/mic.conf.in1
-rw-r--r--etc/zsh_completion.d/_mic8
-rw-r--r--mic/3rdparty/pykickstart/base.py3
-rwxr-xr-x[-rw-r--r--]mic/3rdparty/pykickstart/commands/partition.py4
-rw-r--r--mic/3rdparty/pykickstart/constants.py2
-rw-r--r--mic/3rdparty/pykickstart/handlers/control.py3
-rwxr-xr-x[-rw-r--r--]mic/3rdparty/pykickstart/options.py10
-rw-r--r--mic/3rdparty/pykickstart/parser.py30
-rw-r--r--mic/3rdparty/pykickstart/sections.py50
-rwxr-xr-x[-rw-r--r--]mic/__init__.py2
-rw-r--r--mic/bootstrap.py61
-rw-r--r--mic/chroot.py8
-rwxr-xr-xmic/cmd_create.py16
-rwxr-xr-x[-rw-r--r--]mic/conf.py32
-rwxr-xr-xmic/imager/baseimager.py222
-rwxr-xr-x[-rw-r--r--]mic/imager/loop.py71
-rwxr-xr-xmic/kickstart/__init__.py77
-rw-r--r--mic/kickstart/custom_commands/__init__.py4
-rw-r--r--mic/kickstart/custom_commands/micrepo.py24
-rwxr-xr-x[-rw-r--r--]mic/kickstart/custom_commands/partition.py14
-rw-r--r--mic/msger.py2
-rw-r--r--mic/pluginbase.py5
-rw-r--r--mic/rt_util.py8
-rwxr-xr-x[-rw-r--r--]mic/utils/fs_related.py90
-rwxr-xr-xmic/utils/misc.py54
-rw-r--r--mic/utils/proxy.py24
-rw-r--r--mic/utils/rpmmisc.py28
-rwxr-xr-x[-rw-r--r--]packaging/mic.changes77
-rwxr-xr-x[-rw-r--r--]packaging/mic.spec2
-rw-r--r--plugins/backend/zypppkgmgr.py23
-rwxr-xr-x[-rw-r--r--]plugins/imager/fs_plugin.py14
-rwxr-xr-x[-rw-r--r--]plugins/imager/loop_plugin.py14
-rwxr-xr-x[-rw-r--r--]plugins/imager/qcow_plugin.py13
-rwxr-xr-xplugins/imager/raw_plugin.py11
-rw-r--r--tests/test_configmgr.py3
-rwxr-xr-xtools/mic29
43 files changed, 1307 insertions, 117 deletions
diff --git a/ChangeLog b/ChangeLog
index 7a3cfb8..7e587d7 100644..100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,92 @@
+Release 0.28.6 - Fri Feb. 15 2019 - Jin Xiao <jin.xiao@samsung.com>
+=====================================================================
+ * new distribution support: Ubuntu 18.04.
+
+Release 0.28.5 - Wed 0ct. 31 2018 - Jin Xiao <jin.xiao@samsung.com>
+=====================================================================
+ * Add %env section support.
+
+Release 0.28.4 - Fri Sep. 28 2018 - Jin Xiao <jin.xiao@samsung.com>
+=====================================================================
+ * add new option --fslabel in part section.
+
+Release 0.28.3 - Fri Sep. 14 2018 - Jin Xiao <jin.xiao@samsung.com>
+=====================================================================
+ * Revert "ext4 images are created with inode size 256 bytes".
+
+Release 0.28.2 - Fri Aug. 03 2018 - Jin Xiao <jin.xiao@samsung.com>
+=====================================================================
+ * remove tmp dir in runscript period.
+ * ext4 images are created with inode size 256 bytes.
+ * Add locale related environment varibale because language is not set to one specified in ks file.
+
+Release 0.28.1 - Fri May. 11 2018 - Jin Xiao <jin.xiao@samsung.com>
+=====================================================================
+ * Check exit status of vdfs image creation
+ * Change the user and root passwd hash algorithm order to avoid user name same as root name.
+
+Release 0.28 - Fri April. 13 2018 - Jin Xiao <jin.xiao@samsung.com>
+=====================================================================
+ * Apply btrfs mount options "--fsoptions=compress"
+ * In Tizen, losetup command support '-f' option, change '--find' to '-f'
+ * Fix issue, set blocksize by parsing "-b [BLOCKSIZE]" from extoptions in ks file
+
+Release 0.27.9 - Fri Mar. 23 2018 - Xiaojuan Mao <xiaojuan.mao@samsung.com>
+=====================================================================
+ * Added ATTACHMENT_PATHS env and IMG_DIR_PATH env
+ * Revert "call copy_attachment() after configure() and move attachment files"
+
+Release 0.27.8 - Fri Jan. 26 2018 - Xiaojuan Mao <xiaojuan.mao@samsung.com>
+=====================================================================
+ * Use SHA512 instead of MD5 to encrypt root password
+ * Fix the bug that use local mic-bootstrap to run mic.
+ * Support local mic-bootstrap rpm package to run mic.
+ * Another method of install tpk.
+ * The value of fstype is not cpio, an image is generated by cpio.
+ * When increase rpm release number, user can use --local-pkgs-path to install local pkgs.
+ * use the value of --pack-to option as filename to match all outputs
+ * support both %runscript and %post-umount to perform scripts before packaging
+ * support multiple mic execution at same time
+ * add --use-mic-in-bootstrap option
+ * Display all rpm debug messages with --rpm-debug
+ * call copy_attachment() after configure() and move attachment files
+ * Add init_expand option to partition
+ * add no_shrink option to partition, fix parameter of disk.expand()
+ * Setup environment to perform signing script
+ * if post scripts fails, CreatorError is raised to catch script errors such as signing error
+ * use registered qemu emulator filename if already registered.
+
+Release 0.27.7 - Fri Sep. 15 2017 - Yuhuan Yang <yuhuan.yang@samsung.com>
+=====================================================================
+ * Timezone setting change
+ * Run certain script before creation of tar.gz image
+ * Locally built mic-bootstrap using gbs cannot be used in mic
+ * Add new option of tpk_install
+ * Amend mic cr option of run_script
+ * Add new option of --run_script
+ * fix the bug that modify the order of generating image by cpio
+ * Modify the order of generating image by cpio
+
+Release 0.27.6 - Fri Jun 30 2017 - Xiaojuan Mao <xiaojuan.mao@samsung.com>
+=====================================================================
+ * Use cpio gzip in mic.
+ * fix corrupted log messages in log file
+ * change installed package name length from 20 to 50
+ * print warning message for detecting rpm post script...
+ * display all rpm debug messages in debug mode
+ * display filesystem size of each images
+ * add SIGTERM handler for exit gracefully
+ * change tpk install error message format
+ * print package name, before install
+ * Modify the arguments that use cpio to generate image.
+ * Solve mic hang issue, add timeout to show failure.
+ * Solve issue:mic has error when env no_proxy is 165.xx.xxx...
+ * Change the order of generating image by cpio.
+
+Release 0.27.5 - Fri Apr 28 2017 - Yuhuan Yang <yuhuan.yang@samsung.com>
+=====================================================================
+ * Solve image not clean after created, use e2fsck to clean image, relevant issue is NJTS-179 in JIRA.
+
Release 0.27.4 - Wed Apr 5 2017 - SoonKyu Park <sk7.park@samsung.com>
=====================================================================
* Fixup changelog that causes errors
diff --git a/README.rst b/README.rst
index 99b2778..99b2778 100644..100755
--- a/README.rst
+++ b/README.rst
diff --git a/debian/changelog b/debian/changelog
index 6a35c66..a10a43a 100644..100755
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,104 @@
+mic (0.28.6) unstable; urgency=low
+ * new distribution support: Ubuntu 18.04.
+
+ -- Jin Xiao <jin.xiao@samsung.com> Fri, 15 Feb 2019 15:00:00 +0800
+
+mic (0.28.5) unstable; urgency=low
+ * Add %env section support.
+
+ -- Jin Xiao <jin.xiao@samsung.com> Wed, 31 Oct 2018 15:00:00 +0800
+
+mic (0.28.4) unstable; urgency=low
+ * add new option --fslabel in part section.
+
+ -- Jin Xiao <jin.xiao@samsung.com> Fri, 28 Sep 2018 15:00:00 +0800
+
+mic (0.28.3) unstable; urgency=low
+ * Revert "ext4 images are created with inode size 256 bytes".
+
+ -- Jin Xiao <jin.xiao@samsung.com> Fri, 14 Sep 2018 15:00:00 +0800
+
+mic (0.28.2) unstable; urgency=low
+ * remove tmp dir in runscript period.
+ * ext4 images are created with inode size 256 bytes.
+ * Add locale related environment varibale because language is not set to one specified in ks file.
+
+ -- Jin Xiao <jin.xiao@samsung.com> Fri, 03 Aug 2018 15:00:00 +0800
+
+mic (0.28.1) unstable; urgency=low
+ * Check exit status of vdfs image creation
+ * Change the user and root passwd hash algorithm order to avoid user name same as root name.
+
+ -- Jin Xiao <jin.xiao@samsung.com> Fri, 11 May 2018 15:00:00 +0800
+
+mic (0.28) unstable; urgency=low
+ * Apply btrfs mount options "--fsoptions=compress"
+ * In Tizen, losetup command support '-f' option, change '--find' to '-f'
+ * Fix issue, set blocksize by parsing "-b [BLOCKSIZE]" from extoptions in ks file
+
+ -- Jin Xiao <jin.xiao@samsung.com> Fri, 13 April 2018 15:00:00 +0800
+
+mic (0.27.9) unstable; urgency=low
+ * Added ATTACHMENT_PATHS env and IMG_DIR_PATH env
+ * Revert "call copy_attachment() after configure() and move attachment files"
+
+ -- Xiaojuan Mao <xiaojuan.mao@samsung.com> Fri, 23 Mar 2018 15:00:00 +0800
+
+mic (0.27.8) unstable; urgency=low
+ * Use SHA512 instead of MD5 to encrypt root password
+ * Fix the bug that use local mic-bootstrap to run mic.
+ * Support local mic-bootstrap rpm package to run mic.
+ * Another method of install tpk.
+ * The value of fstype is not cpio, an image is generated by cpio.
+ * When increase rpm release number, user can use --local-pkgs-path to install local pkgs.
+ * use the value of --pack-to option as filename to match all outputs
+ * support both %runscript and %post-umount to perform scripts before packaging
+ * support multiple mic execution at same time
+ * add --use-mic-in-bootstrap option
+ * Display all rpm debug messages with --rpm-debug
+ * call copy_attachment() after configure() and move attachment files
+ * Add init_expand option to partition
+ * add no_shrink option to partition, fix parameter of disk.expand()
+ * Setup environment to perform signing script
+ * if post scripts fails, CreatorError is raised to catch script errors such as signing error
+ * use registered qemu emulator filename if already registered.
+
+ -- Xiaojuan Mao <xiaojuan.mao@samsung.com> Fri, 26 Jan 2018 17:00:00 +0800
+
+mic (0.27.7) unstable; urgency=low
+ * Timezone setting change
+ * Run certain script before creation of tar.gz image
+ * Locally built mic-bootstrap using gbs cannot be used in mic
+ * Add new option of tpk_install
+ * Amend mic cr option of run_script
+ * Add new option of --run_script
+ * fix the bug that modify the order of generating image by cpio
+ * Modify the order of generating image by cpio
+
+ -- Yuhuan Yang <yuhuan.yang@samsung.com> Fri, 15 Sep 2017 15:00:00 +0800
+
+mic (0.27.6) unstable; urgency=low
+ * Use cpio gzip in mic.
+ * fix corrupted log messages in log file
+ * change installed package name length from 20 to 50
+ * print warning message for detecting rpm post script...
+ * display all rpm debug messages in debug mode
+ * display filesystem size of each images
+ * add SIGTERM handler for exit gracefully
+ * change tpk install error message format
+ * print package name, before install
+ * Modify the arguments that use cpio to generate image.
+ * Solve mic hang issue, add timeout to show failure.
+ * Solve issue:mic has error when env no_proxy is 165.xx.xxx...
+ * Change the order of generating image by cpio.
+
+ -- Xiaojuan Mao <xiaojuan.mao@samsung.com> Fri, 30 Jun 2017 15:00:00 +0800
+
+mic (0.27.5) unstable; urgency=low
+ * Solve image not clean after created, use e2fsck to clean image, relevant issue is NJTS-179 in JIRA.
+
+ -- Yuhuan Yang <yuhuan.yang@samsung.com> Fri, 28 Apr 2017 15:00:00 +0800
+
mic (0.27.4) unstable; urgency=low
* Fixup changelog that causes errors
* Merge add mipsel register on binfmt_misc && Add support of qemu-mipsel patch
diff --git a/debian/control b/debian/control
index 8d921f5..72cc18e 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: mic
Section: devel
Priority: extra
Maintainer: Jian-feng Ding <jian-feng.ding@intel.com>
-Build-Depends: debhelper (>= 7.0.15), cdbs, python-dev, python-support, python-docutils
+Build-Depends: debhelper (>= 7.0.15), cdbs, python-dev, dh-python, python-docutils
Standards-Version: 3.8.0
Homepage: http://www.tizen.org
diff --git a/debian/rules b/debian/rules
index 41a13a9..b877fe9 100755
--- a/debian/rules
+++ b/debian/rules
@@ -45,7 +45,7 @@ binary-indep: build install
dh_strip
dh_compress
dh_fixperms
- dh_pysupport
+ dh_python2
dh_installdeb
dh_shlibdeps
dh_gencontrol
diff --git a/doc/RELEASE_NOTES b/doc/RELEASE_NOTES
index 4f0dd82..290ba61 100644..100755
--- a/doc/RELEASE_NOTES
+++ b/doc/RELEASE_NOTES
@@ -1,3 +1,192 @@
+MIC Image Creator 0.28.6 Release Notes
+======================================
+Released Feb 15 2019
+
+This release note documents the changes included in the new release. And
+the release contains new features.
+
+new features
+--------------------------
+ * new distribution support: Ubuntu 18.04.
+
+MIC Image Creator 0.28.5 Release Notes
+======================================
+Released Oct 31 2018
+
+This release note documents the changes included in the new release. And
+the release contains new features.
+
+new features
+--------------------------
+ * Add %env section support.
+
+MIC Image Creator 0.28.4 Release Notes
+======================================
+Released Sep 28 2018
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+
+new features
+--------------------------
+ * add new option --fslabel in part section.
+
+MIC Image Creator 0.28.3 Release Notes
+======================================
+Released Sep 14 2018
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+
+Bug Fixes
+--------------------------
+ * Revert "ext4 images are created with inode size 256 bytes".
+
+MIC Image Creator 0.28.2 Release Notes
+======================================
+Released Aug 03 2018
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+
+New Features & Enhancements
+--------------------------
+ * remove tmp dir in runscript period.
+ * ext4 images are created with inode size 256 bytes.
+ * Add locale related environment varibale because language is not set to one specified in ks file.
+
+MIC Image Creator 0.28.1 Release Notes
+======================================
+Released May 11 2018
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+
+New Features & Enhancements
+--------------------------
+ * Check exit status of vdfs image creation
+ * Change the user and root passwd hash algorithm order to avoid user name same as root name.
+
+MIC Image Creator 0.28 Release Notes
+======================================
+Released April 13 2018
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+
+New Features & Enhancements
+--------------------------
+ * Apply btrfs mount options "--fsoptions=compress"
+
+Bug Fixes
+---------
+ * In Tizen, losetup command support '-f' option, change '--find' to '-f'
+ * Fix issue, set blocksize by parsing "-b [BLOCKSIZE]" from extoptions in ks file
+
+MIC Image Creator 0.27.9 Release Notes
+======================================
+Released Mar 23 2018
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+New Features & Enhancements
+--------------------------
+ * Added ATTACHMENT_PATHS env and IMG_DIR_PATH env
+
+Bug Fixes
+---------
+ * Revert "call copy_attachment() after configure() and move attachment files"
+
+MIC Image Creator 0.27.8 Release Notes
+======================================
+Released Jan 26 2018
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+New Features & Enhancements
+--------------------------
+ * Use SHA512 instead of MD5 to encrypt root password
+ * Support local mic-bootstrap rpm package to run mic.
+ * Another method of install tpk.
+ * The value of fstype is not cpio, an image is generated by cpio.
+ * When increase rpm release number, user can use --local-pkgs-path to install local pkgs.
+ * use the value of --pack-to option as filename to match all outputs
+ * support both %runscript and %post-umount to perform scripts before packaging
+ * support multiple mic execution at same time
+ * add --use-mic-in-bootstrap option
+ * Display all rpm debug messages with --rpm-debug
+ * call copy_attachment() after configure() and move attachment files
+ * Add init_expand option to partition
+ * add no_shrink option to partition, fix parameter of disk.expand()
+ * Setup environment to perform signing script
+ * if post scripts fails, CreatorError is raised to catch script errors such as signing error
+ * use registered qemu emulator filename if already registered.
+
+Bug Fixes
+---------
+ * Fix the bug that use local mic-bootstrap to run mic.
+
+MIC Image Creator 0.27.7 Release Notes
+======================================
+Released Sep 15 2017
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+
+New Features & Enhancements
+--------------------------
+ * Timezone setting change
+ * Run certain script before creation of tar.gz image
+ * Locally built mic-bootstrap using gbs cannot be used in mic
+ * Add new option of tpk_install
+ * Amend mic cr option of run_script
+ * Add new option of --run_script
+ * Modify the order of generating image by cpio
+
+Bug Fixes
+---------
+ * fix the bug that modify the order of generating image by cpio
+
+MIC Image Creator 0.27.6 Release Notes
+======================================
+Released Jun 30 2017
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+
+New Features & Enhancements
+--------------------------
+ * Use cpio gzip in mic.
+ * fix corrupted log messages in log file
+ * change installed package name length from 20 to 50
+ * print warning message for detecting rpm post script...
+ * display all rpm debug messages in debug mode
+ * display filesystem size of each images
+ * add SIGTERM handler for exit gracefully
+ * change tpk install error message format
+ * print package name, before install
+ * Modify the arguments that use cpio to generate image.
+ * Solve mic hang issue, add timeout to show failure.
+ * Solve issue:mic has error when env no_proxy is 165.xx.xxx...
+ * Change the order of generating image by cpio.
+
+Bug Fixes
+---------
+
+MIC Image Creator 0.27.5 Release Notes
+======================================
+Released Apr 28 2017
+
+This release note documents the changes included in the new release. And
+the release contains new features, enhancements and bug fixes.
+
+New Features & Enhancements
+--------------------------
+ * Solve image not clean after created, use e2fsck to clean image, relevant issue is NJTS-179 in JIRA.
+
+Bug Fixes
+---------
+
MIC Image Creator 0.27.4 Release Notes
======================================
Released Apr 5 2017
diff --git a/etc/bash_completion.d/mic.sh b/etc/bash_completion.d/mic.sh
index 1cd19c9..4f467ca 100644
--- a/etc/bash_completion.d/mic.sh
+++ b/etc/bash_completion.d/mic.sh
@@ -139,10 +139,12 @@ __mic_complete_val()
compress_image_values="
gz
bz2
+ lzo
"
compress_disk_image_values="
gz
bz2
+ lzo
"
declare -F _split_longopt &>/dev/null && _split_longopt
diff --git a/etc/mic.conf.in b/etc/mic.conf.in
index 3d41eff..81907ff 100644
--- a/etc/mic.conf.in
+++ b/etc/mic.conf.in
@@ -10,6 +10,7 @@ tmpdir= /var/tmp/mic
cachedir= /var/tmp/mic/cache
outdir= ./mic-output
runtime=bootstrap
+#use_mic_in_bootstrap = yes
pkgmgr = auto
diff --git a/etc/zsh_completion.d/_mic b/etc/zsh_completion.d/_mic
index a8e80c0..8615572 100644
--- a/etc/zsh_completion.d/_mic
+++ b/etc/zsh_completion.d/_mic
@@ -117,8 +117,8 @@ _mic() {
_arguments \
$common_ops \
'--shrink[Whether to shrink loop images to minimal size]' \
- "--compress-image=[Compress all loop images with \'gz\' or \'bz2\']: :(gz bz2)" \
- "--compress-disk-image=[Same with --compress-image]: :(gz bz2)" \
+ "--compress-image=[Compress all loop images with \'gz\' or \'bz2\' or \'lzo\']: :(gz bz2 lzo)" \
+ "--compress-disk-image=[Same with --compress-image]: :(gz bz2 lzo)" \
&& ret=0
;;
(raw)
@@ -126,8 +126,8 @@ _mic() {
$common_ops \
"--fstab-entry=[Set fstab entry, \'name\' means using device names, \'uuid\' means using filesystem uuid]: :(name uuid)" \
'--generate-bmap[also generate the block map file]' \
- '--compress-image=[Compress all raw images before package]: :(gz bz2)' \
- '--compress-disk-image=[Same with --compress-image]: :(gz bz2)' \
+ '--compress-image=[Compress all raw images before package]: :(gz bz2 lzo)' \
+ '--compress-disk-image=[Same with --compress-image]: :(gz bz2 lzo)' \
&& ret=0
;;
(help)
diff --git a/mic/3rdparty/pykickstart/base.py b/mic/3rdparty/pykickstart/base.py
index e6c8f56..e3597df 100644
--- a/mic/3rdparty/pykickstart/base.py
+++ b/mic/3rdparty/pykickstart/base.py
@@ -46,7 +46,7 @@ import types
import warnings
from pykickstart.errors import *
from pykickstart.ko import *
-from pykickstart.parser import Packages
+from pykickstart.parser import Packages,TpkPackages
from pykickstart.version import versionToString
###
@@ -253,6 +253,7 @@ class BaseHandler(KickstartObject):
# everything else I can think of.
self.scripts = []
self.packages = Packages()
+ self.tpk_packages = TpkPackages()
self.platform = ""
# These will be set by the dispatcher.
diff --git a/mic/3rdparty/pykickstart/commands/partition.py b/mic/3rdparty/pykickstart/commands/partition.py
index e65e012..5dbd4d4 100644..100755
--- a/mic/3rdparty/pykickstart/commands/partition.py
+++ b/mic/3rdparty/pykickstart/commands/partition.py
@@ -102,6 +102,7 @@ class FC4_PartData(FC3_PartData):
self.bytesPerInode = kwargs.get("bytesPerInode", 4096)
self.fsopts = kwargs.get("fsopts", "")
self.label = kwargs.get("label", "")
+ self.fslabel = kwargs.get("fslabel", "")
def _getArgsAsStr(self):
retval = FC3_PartData._getArgsAsStr(self)
@@ -112,6 +113,8 @@ class FC4_PartData(FC3_PartData):
retval += " --fsoptions=\"%s\"" % self.fsopts
if self.label != "":
retval += " --label=%s" % self.label
+ if self.fslabel != "":
+ retval += " --fslabel=%s" % self.fslabel
return retval
@@ -279,6 +282,7 @@ class FC4_Partition(FC3_Partition):
type="int", nargs=1)
op.add_option("--fsoptions", dest="fsopts")
op.add_option("--label", dest="label")
+ op.add_option("--fslabel", dest="fslabel")
return op
class RHEL5_Partition(FC4_Partition):
diff --git a/mic/3rdparty/pykickstart/constants.py b/mic/3rdparty/pykickstart/constants.py
index 5e12fc8..050d124 100644
--- a/mic/3rdparty/pykickstart/constants.py
+++ b/mic/3rdparty/pykickstart/constants.py
@@ -39,6 +39,8 @@ SELINUX_PERMISSIVE = 2
KS_SCRIPT_PRE = 0
KS_SCRIPT_POST = 1
KS_SCRIPT_TRACEBACK = 2
+KS_SCRIPT_RUN = 3
+KS_SCRIPT_UMOUNT = 4
KS_WAIT = 0
KS_REBOOT = 1
diff --git a/mic/3rdparty/pykickstart/handlers/control.py b/mic/3rdparty/pykickstart/handlers/control.py
index d8c8f2b..119e32f 100644
--- a/mic/3rdparty/pykickstart/handlers/control.py
+++ b/mic/3rdparty/pykickstart/handlers/control.py
@@ -19,6 +19,7 @@
#
from pykickstart.version import *
from pykickstart.commands import *
+from mic.kickstart.custom_commands.micrepo import *
# This map is keyed on kickstart syntax version as provided by
# pykickstart.version. Within each sub-dict is a mapping from command name
@@ -217,6 +218,7 @@ commandMap = {
"raid": raid.FC5_Raid,
"reboot": reboot.FC6_Reboot,
"repo": repo.FC6_Repo,
+ "tpk_repo": Mic_Tpk_Repo,
"rootpw": rootpw.FC3_RootPw,
"selinux": selinux.FC3_SELinux,
"services": services.FC6_Services,
@@ -1087,6 +1089,7 @@ dataMap = {
"PartData": partition.FC4_PartData,
"RaidData": raid.FC5_RaidData,
"RepoData": repo.FC6_RepoData,
+ "TpkRepoData": Mic_Tpk_RepoData,
"UserData": user.FC6_UserData,
"VolGroupData": volgroup.FC3_VolGroupData,
"ZFCPData": zfcp.FC3_ZFCPData,
diff --git a/mic/3rdparty/pykickstart/options.py b/mic/3rdparty/pykickstart/options.py
index 341c5d7..d971d92 100644..100755
--- a/mic/3rdparty/pykickstart/options.py
+++ b/mic/3rdparty/pykickstart/options.py
@@ -137,11 +137,11 @@ def _check_ksboolean(option, opt, value):
raise OptionValueError(_("Option %(opt)s: invalid boolean value: %(value)r") % mapping)
def _check_string(option, opt, value):
- if len(value) > 2 and value.startswith("--"):
- mapping = {"opt": opt, "value": value}
- raise OptionValueError(_("Option %(opt)s: invalid string value: %(value)r") % mapping)
- else:
- return value
+ #if len(value) > 2 and value.startswith("--"):
+ #mapping = {"opt": opt, "value": value}
+ #raise OptionValueError(_("Option %(opt)s: invalid string value: %(value)r") % mapping)
+ # else:
+ return value
# Creates a new Option class that supports several new attributes:
# - required: any option with this attribute must be supplied or an exception
diff --git a/mic/3rdparty/pykickstart/parser.py b/mic/3rdparty/pykickstart/parser.py
index 840a448..46495f6 100644
--- a/mic/3rdparty/pykickstart/parser.py
+++ b/mic/3rdparty/pykickstart/parser.py
@@ -30,7 +30,6 @@ This module exports several important classes:
KickstartParser - The kickstart file parser state machine.
"""
-
from collections import Iterator
import os
import shlex
@@ -202,6 +201,10 @@ class Script(KickstartObject):
retval += '\n%post'
elif self.type == constants.KS_SCRIPT_TRACEBACK:
retval += '\n%traceback'
+ elif self.type == constants.KS_SCRIPT_RUN:
+ retval += '\n%runscript'
+ elif self.type == constants.KS_SCRIPT_UMOUNT:
+ retval += '\n%post-umount'
if self.interp != "/bin/sh" and self.interp != "":
retval += " --interpreter=%s" % self.interp
@@ -291,6 +294,7 @@ class Packages(KickstartObject):
self.groupList = []
self.handleMissing = constants.KS_MISSING_PROMPT
self.packageList = []
+ self.tpk_packageList = []
self.instLangs = None
def __str__(self):
@@ -405,7 +409,25 @@ class Packages(KickstartObject):
self.packageList = list(existingPackageSet)
self.excludedList = list(existingExcludedSet)
-
+class TpkPackages(KickstartObject):
+ """A class representing the %tpk_packages section of the kickstart file."""
+ def __init__(self, *args, **kwargs):
+ KickstartObject.__init__(self, *args, **kwargs)
+ self.tpk_packageList = []
+ def __str__(self):
+ tpk_pkgs = ""
+ retval = "\n%tpk_packages"
+ p = self.packageList
+ p.sort()
+ for pkg in p:
+ tpk_pkgs += "%s\n" % pkg
+ return retval + "\n" +tpk_pkgs
+ def add(self, tpkPackageList):
+ tpk_PackageSet = set(self.tpk_packageList)
+ for tpk_pkg in tpkPackageList:
+ stripped = tpk_pkg.strip()
+ tpk_PackageSet.add(stripped)
+ self.tpk_packageList = list(tpk_PackageSet)
###
### PARSER
###
@@ -699,4 +721,8 @@ class KickstartParser:
self.registerSection(PreScriptSection(self.handler, dataObj=Script))
self.registerSection(PostScriptSection(self.handler, dataObj=Script))
self.registerSection(TracebackScriptSection(self.handler, dataObj=Script))
+ self.registerSection(RunScriptSection(self.handler, dataObj=Script))
+ self.registerSection(PostUmountScriptSection(self.handler, dataObj=Script))
self.registerSection(PackageSection(self.handler))
+ self.registerSection(TpkPackageSection(self.handler))
+
diff --git a/mic/3rdparty/pykickstart/sections.py b/mic/3rdparty/pykickstart/sections.py
index 44df856..c360a90 100644
--- a/mic/3rdparty/pykickstart/sections.py
+++ b/mic/3rdparty/pykickstart/sections.py
@@ -30,6 +30,7 @@ is necessary is to create a new subclass of Section and call
parser.registerSection with an instance of your new class.
"""
from constants import *
+from errors import *
from options import KSOptionParser
from version import *
@@ -194,6 +195,36 @@ class TracebackScriptSection(ScriptSection):
ScriptSection._resetScript(self)
self._script["type"] = KS_SCRIPT_TRACEBACK
+class RunScriptSection(ScriptSection):
+ sectionOpen = "%runscript"
+
+ def _resetScript(self):
+ ScriptSection._resetScript(self)
+ self._script["type"] = KS_SCRIPT_RUN
+
+ def finalize(self):
+ ScriptSection.finalize(self)
+ if self.handler:
+ for s in self.handler.scripts:
+ if s.type == KS_SCRIPT_UMOUNT:
+ raise KickstartError("%runscript and %post-umount " \
+ "can not be defined together")
+
+class PostUmountScriptSection(ScriptSection):
+ sectionOpen = "%post-umount"
+
+ def _resetScript(self):
+ ScriptSection._resetScript(self)
+ self._script["type"] = KS_SCRIPT_UMOUNT
+
+ def finalize(self):
+ ScriptSection.finalize(self)
+ if self.handler:
+ for s in self.handler.scripts:
+ if s.type == KS_SCRIPT_RUN:
+ raise KickstartError("%runscript and %post-umount " \
+ "can not be defined together")
+
class PackageSection(Section):
sectionOpen = "%packages"
@@ -203,7 +234,6 @@ class PackageSection(Section):
(h, s, t) = line.partition('#')
line = h.rstrip()
-
self.handler.packages.add([line])
def handleHeader(self, lineno, args):
@@ -242,3 +272,21 @@ class PackageSection(Section):
if opts.instLangs:
self.handler.packages.instLangs = opts.instLangs
+
+class TpkPackageSection(Section):
+ sectionOpen = "%tpk_packages"
+
+ def handleLine(self, line):
+ if not self.handler:
+ return
+
+ (h, s, t) = line.partition('#')
+ line = h.rstrip()
+ self.handler.tpk_packages.add([line])
+
+ def handleHeader(self, lineno, args):
+ """Process the arguments to the %tpk_packages header and set attributes
+ on the Version's TpkPackages instance appropriate. This method may be
+ overridden in a subclass if necessary.
+ """
+ Section.handleHeader(self, lineno, args)
diff --git a/mic/__init__.py b/mic/__init__.py
index e91b81d..ab5cb7a 100644..100755
--- a/mic/__init__.py
+++ b/mic/__init__.py
@@ -16,7 +16,7 @@
import os, sys
-__version__ = "0.27.4"
+__version__ = "0.28.6"
cur_path = os.path.dirname(__file__) or '.'
sys.path.insert(0, cur_path + '/3rdparty')
diff --git a/mic/bootstrap.py b/mic/bootstrap.py
index 5cfa8c7..c3e8471 100644
--- a/mic/bootstrap.py
+++ b/mic/bootstrap.py
@@ -22,10 +22,13 @@ import tempfile
import shutil
import subprocess
import rpm
+import glob
+
from mic import msger
from mic.utils import errors, proxy, misc
from mic.utils.rpmmisc import readRpmHeader, RPMInstallCallback
from mic.chroot import cleanup_mounts, setup_chrootenv, cleanup_chrootenv
+from mic.conf import configmgr
PATH_BOOTSTRAP = "/usr/sbin:/usr/bin:/sbin:/bin"
@@ -87,6 +90,21 @@ class MiniBackend(object):
if not pkg in self.dlpkgs:
self.dlpkgs.append(pkg)
+ def _get_local_packages(self, pkg):
+ """Return local mic-bootstrap rpm path."""
+ cropts = configmgr.create
+ if cropts['local_pkgs_path']:
+ if os.path.isdir(cropts['local_pkgs_path']):
+ pkglist = glob.glob(
+ os.path.join(cropts['local_pkgs_path'], pkg + '*.rpm'))
+ if len(pkglist) > 1:
+ raise errors.BootstrapError("Many %s packages in folder, put only one %s package in it." % (pkg, pkg))
+ elif len(pkglist) == 1:
+ return ''.join(pkglist)
+ elif os.path.splitext(cropts['local_pkgs_path'])[-1] == '.rpm':
+ if cropts['local_pkgs_path'].find(pkg) >= 0:
+ return cropts['local_pkgs_path']
+ return None
def runInstall(self):
# FIXME: check space
self.downloadPkgs()
@@ -105,7 +123,9 @@ class MiniBackend(object):
def downloadPkgs(self):
nonexist = []
for pkg in self.dlpkgs:
- localpth = misc.get_package(pkg, self.repomd, self.arch)
+ localpth = self._get_local_packages(pkg)
+ if localpth is None:
+ localpth = misc.get_package(pkg, self.repomd, self.arch)
if localpth:
self.localpkgs[pkg] = localpth
elif pkg in self.optionals:
@@ -244,6 +264,34 @@ class Bootstrap(object):
except:
pass
+ def sync_hostfile(rootdir):
+ try:
+ # sync host info to bootstrap
+ if os.path.exists(rootdir + "/etc/hosts"):
+ os.unlink(rootdir + "/etc/hosts")
+ shutil.copyfile("/etc/hosts", rootdir + "/etc/hosts")
+ except:
+ pass
+
+ def sync_signfile(rootdir,homedir):
+ if os.path.exists(homedir + "/.sign"):
+ signfile = rootdir + homedir + "/.sign"
+ try:
+ # sync sign info to bootstrap
+ if os.path.exists(signfile):
+ if os.path.isdir(signfile):
+ shutil.rmtree(signfile)
+ else:
+ os.unlink(signfile)
+ try:
+ shutil.copytree(homedir + "/.sign", signfile)
+ except OSError as exc:
+ if exc.errno == errno.ENOTDIR:
+ shutil.copy(homedir + "/.sign", signfile)
+ else: raise
+ except:
+ pass
+
if not rootdir:
rootdir = self.rootdir
@@ -254,6 +302,11 @@ class Bootstrap(object):
env = os.environ
env['PATH'] = "%s:%s" % (PATH_BOOTSTRAP, env['PATH'])
+ cropts = configmgr.create
+ if cropts["ks"]:
+ lang = cropts["ks"].handler.lang.lang
+ env['LANG'] = lang
+ env['LC_ALL'] = lang
retcode = 0
gloablmounts = None
@@ -262,6 +315,12 @@ class Bootstrap(object):
gloablmounts = setup_chrootenv(rootdir, bindmounts)
sync_timesetting(rootdir)
sync_passwdfile(rootdir)
+ sync_hostfile(rootdir)
+ env['SUDO_USER'] = 'root'
+ if 'SUDO_USER' in env:
+ sync_signfile(rootdir, os.path.expanduser('~' + env['SUDO_USER']))
+ else:
+ sync_signfile(rootdir, os.path.expanduser('~'))
retcode = subprocess.call(cmd, preexec_fn=mychroot, env=env, shell=shell)
except (OSError, IOError):
# add additional information to original exception
diff --git a/mic/chroot.py b/mic/chroot.py
index a2bafdf..a8a41db 100644
--- a/mic/chroot.py
+++ b/mic/chroot.py
@@ -304,9 +304,11 @@ def chroot(chrootdir, bindmounts = None, execute = "/bin/bash"):
arch = ELF_arch(chrootdir)
if arch == "arm":
- qemu_emulator = misc.setup_qemu_emulator(chrootdir, "arm")
+ qemu_emulators = misc.setup_qemu_emulator(chrootdir, "arm")
+ elif arch == "mipsel":
+ qemu_emulators = misc.setup_qemu_emulator(chrootdir, "mipsel")
else:
- qemu_emulator = None
+ qemu_emulators = []
savefs_before_chroot(chrootdir, None)
@@ -324,5 +326,5 @@ def chroot(chrootdir, bindmounts = None, execute = "/bin/bash"):
finally:
cleanup_chrootenv(chrootdir, bindmounts, globalmounts)
- if qemu_emulator:
+ for qemu_emulator in qemu_emulators:
os.unlink(chrootdir + qemu_emulator)
diff --git a/mic/cmd_create.py b/mic/cmd_create.py
index 54fdbde..203d08d 100755
--- a/mic/cmd_create.py
+++ b/mic/cmd_create.py
@@ -76,6 +76,13 @@ def main(parser, args, argv):
msger.set_loglevel('DEBUG')
+ if args.rpm_debug:
+ try:
+ import rpm
+ rpm.setVerbosity(rpm.RPMLOG_DEBUG)
+ except ImportError:
+ pass
+
#check the imager type
createrClass = None
for subcmd, klass in pluginmgr.get_plugins('imager').iteritems():
@@ -144,6 +151,9 @@ def main(parser, args, argv):
if args.runtime:
configmgr.set_runtime(args.runtime)
+ if args.use_mic_in_bootstrap:
+ configmgr.create['use_mic_in_bootstrap'] = args.use_mic_in_bootstrap
+
if args.pack_to is not None:
configmgr.create['pack_to'] = args.pack_to
@@ -189,7 +199,11 @@ def main(parser, args, argv):
if args.ignore_ksrepo:
configmgr.create['ignore_ksrepo'] = args.ignore_ksrepo
-
+ if args.run_script:
+ configmgr.create['run_script'] = args.run_script
+ if args.tpk_install:
+ configmgr.create['tpk_install'] = args.tpk_install
+
creater = createrClass()
creater.do_create(args)
diff --git a/mic/conf.py b/mic/conf.py
index d844c65..9299cfe 100644..100755
--- a/mic/conf.py
+++ b/mic/conf.py
@@ -71,10 +71,14 @@ class ConfigMgr(object):
"check_pkgs": [],
"repourl": {},
"localrepos": [], # save localrepos
+ "localtpkrepos":[],
"runtime": "bootstrap",
"extrarepos": {},
"ignore_ksrepo": False,
"strict_mode": False,
+ "run_script": None,
+ "tpk_install": None,
+ "use_mic_in_bootstrap": False,
},
'chroot': {
"saveto": None,
@@ -192,6 +196,13 @@ class ConfigMgr(object):
packages = packages.split()
self.bootstrap['packages'] = packages
+ if type(self.create['use_mic_in_bootstrap']) != 'bool':
+ use_mic_in_bootstrap = str(self.create['use_mic_in_bootstrap'])
+ if use_mic_in_bootstrap.lower() in ('on', 'yes', 'true', '1'):
+ self.create['use_mic_in_bootstrap'] = True
+ else:
+ self.create['use_mic_in_bootstrap'] = False
+
def _parse_kickstart(self, ksconf=None):
if not ksconf:
return
@@ -216,6 +227,12 @@ class ConfigMgr(object):
self.create['release'],
self.create['name'])
self.create['name'] = self.create['release'] + '_' + self.create['name']
+ if self.create['pack_to'] is not None:
+ if '@NAME@' in self.create['pack_to']:
+ self.create['pack_to'] = self.create['pack_to'].replace('@NAME@', self.create['name'])
+ self.create['name'] = misc.strip_archive_suffix(self.create['pack_to'])
+ if self.create['name'] is None:
+ raise errors.CreatorError("Not supported archive file format: %s" % self.create['pack_to'])
if not self.create['logfile']:
self.create['logfile'] = os.path.join(self.create['destdir'],
@@ -223,6 +240,13 @@ class ConfigMgr(object):
self.create['releaselog'] = True
self.set_logfile()
+ elif self.create['pack_to'] is not None:
+ if '@NAME@' in self.create['pack_to']:
+ self.create['pack_to'] = self.create['pack_to'].replace('@NAME@', self.create['name'])
+ self.create['name'] = misc.strip_archive_suffix(self.create['pack_to'])
+ if self.create['name'] is None:
+ raise errors.CreatorError("Not supported archive file format: %s" % self.create['pack_to'])
+
msger.info("Retrieving repo metadata:")
ksrepos = kickstart.get_repos(ks,
self.create['extrarepos'],
@@ -239,6 +263,14 @@ class ConfigMgr(object):
self.create['repomd'] = misc.get_metadata_from_repos(
ksrepos,
self.create['cachedir'])
+ kstpkrepos = kickstart.get_tpkrepos(ks)
+ if kstpkrepos:
+ for tpk_repo in kstpkrepos:
+ if hasattr(tpk_repo,'baseurl') and tpk_repo.baseurl.startswith("file:"):
+ tpk_repourl = tpk_repo.baseurl.replace('file:','')
+ tpk_repourl = "/%s" % tpk_repourl.lstrip('/')
+ self.create['localtpkrepos'].append(tpk_repourl)
+
msger.raw(" DONE")
target_archlist, archlist = misc.get_arch(self.create['repomd'])
diff --git a/mic/imager/baseimager.py b/mic/imager/baseimager.py
index 0812023..7df75cf 100755
--- a/mic/imager/baseimager.py
+++ b/mic/imager/baseimager.py
@@ -1,4 +1,3 @@
-
#!/usr/bin/python -tt
#
# Copyright (c) 2007 Red Hat Inc.
@@ -28,15 +27,18 @@ import tarfile
import glob
import json
from datetime import datetime
-
import rpm
-
+import time
from mic import kickstart
from mic import msger, __version__ as VERSION
-from mic.utils.errors import CreatorError, Abort
+from mic.utils.errors import CreatorError, KsError, Abort
from mic.utils import misc, grabber, runner, fs_related as fs
from mic.chroot import kill_proc_inchroot
from mic.archive import get_archive_suffixes
+from mic.conf import configmgr
+from mic.utils.grabber import myurlgrab
+#post script max run time
+MAX_RUN_TIME = 120
class BaseImageCreator(object):
"""Installs a system to a chroot directory.
@@ -87,6 +89,7 @@ class BaseImageCreator(object):
self.pack_to = None
self.repourl = {}
self.multiple_partitions = False
+ self._imgdir = None
# If the kernel is save to the destdir when copy_kernel cmd is called.
self._need_copy_kernel = False
@@ -113,8 +116,6 @@ class BaseImageCreator(object):
self.destdir = os.path.abspath(os.path.expanduser(self.destdir))
if self.pack_to:
- if '@NAME@' in self.pack_to:
- self.pack_to = self.pack_to.replace('@NAME@', self.name)
(tar, ext) = os.path.splitext(self.pack_to)
if ext in (".gz", ".bz2", ".lzo", ".bz") and tar.endswith(".tar"):
ext = ".tar" + ext
@@ -142,16 +143,25 @@ class BaseImageCreator(object):
self.image_format = None
- # Save qemu emulator file name in order to clean up it finally
- self.qemu_emulator = None
+ # Save qemu emulator file names in order to clean up it finally
+ self.qemu_emulators = []
# No ks provided when called by convertor, so skip the dependency check
if self.ks:
+ if hasattr(self.ks.handler, "env"):
+ for n, v in kickstart.get_env(self.ks):
+ msger.debug("Setting up envvar %s = %s" % (n, v))
+ os.environ[n] = v
# If we have btrfs partition we need to check necessary tools
for part in self.ks.handler.partition.partitions:
if part.fstype and part.fstype == "btrfs":
self._dep_checks.append("mkfs.btrfs")
break
+ if part.cpioopts:
+ if part.fstype == "cpio":
+ part.fstype = "ext4"
+ else:
+ raise KsError("The '--fstype' in ks file need to set 'cpio' when you want to generate image by cpio.")
if len(self.ks.handler.partition.partitions) > 1:
self.multiple_partitions = True
@@ -505,6 +515,9 @@ class BaseImageCreator(object):
if not in_chroot:
env["INSTALL_ROOT"] = self._instroot
env["IMG_NAME"] = self._name
+ env['ATTACHMENT_PATHS'] = ' '.join(self._attachment)
+ if self._imgdir:
+ env['IMG_DIR_PATH'] = str(self._imgdir)
return env
@@ -702,7 +715,7 @@ class BaseImageCreator(object):
return self.cachedir
def __sanity_check(self):
- """Ensure that the config we've been given is sane."""
+ """Ensure that the config we've been given is same."""
if not (kickstart.get_packages(self.ks) or
kickstart.get_groups(self.ks)):
raise CreatorError("No packages or groups specified")
@@ -763,6 +776,23 @@ class BaseImageCreator(object):
runner.show('umount -l %s' % self.workdir)
+ def cp_tpk(self):
+ #Add tpk-install option
+ createopts = configmgr.create
+ if createopts['tpk_install']:
+ path = createopts['tpk_install']
+ file_list = os.listdir(path)
+ for f in file_list:
+ sub = os.path.splitext(f)[1]
+ if sub != ".tpk":
+ raise CreatorError("Not all files in the path: "+path +" is tpk")
+
+ tpk_dir = "/usr/apps/.preload-tpk"
+ fs.makedirs(self._instroot + "/usr/apps")
+ fs.makedirs(self._instroot + tpk_dir)
+ for f in file_list:
+ shutil.copy(path+"/"+f,self._instroot + tpk_dir)
+
def mount(self, base_on = None, cachedir = None):
"""Setup the target filesystem in preparation for an install.
@@ -803,7 +833,7 @@ class BaseImageCreator(object):
if self.target_arch and self.target_arch.startswith("arm") or \
self.target_arch == "aarch64":
- self.qemu_emulator = misc.setup_qemu_emulator(self._instroot,
+ self.qemu_emulators = misc.setup_qemu_emulator(self._instroot,
self.target_arch)
self.get_cachedir(cachedir)
@@ -829,6 +859,7 @@ class BaseImageCreator(object):
# get size of available space in 'instroot' fs
self._root_fs_avail = misc.get_filesystem_avail(self._instroot)
+ self.cp_tpk()
def unmount(self):
"""Unmounts the target filesystem.
@@ -843,8 +874,8 @@ class BaseImageCreator(object):
if not os.path.islink(mtab):
os.unlink(self._instroot + "/etc/mtab")
- if self.qemu_emulator:
- os.unlink(self._instroot + self.qemu_emulator)
+ for qemu_emulator in self.qemu_emulators:
+ os.unlink(self._instroot + qemu_emulator)
except OSError:
pass
@@ -945,9 +976,9 @@ class BaseImageCreator(object):
for pkg in self._excluded_pkgs:
pkg_manager.deselectPackage(pkg)
- def __localinst_packages(self, pkg_manager):
+ """def __localinst_packages(self, pkg_manager):
for rpm_path in self._get_local_packages():
- pkg_manager.installLocal(rpm_path)
+ pkg_manager.installLocal(rpm_path)"""
def __preinstall_packages(self, pkg_manager):
if not self.ks:
@@ -1027,9 +1058,8 @@ class BaseImageCreator(object):
def showErrorInfo(filepath):
if os.path.isfile(filepath):
- msger.info("The error install package info:")
for line in open(filepath):
- msger.info(line)
+ msger.info("The error install package info: %s" % line)
else:
msger.info("%s is not found." % filepath)
@@ -1063,6 +1093,7 @@ class BaseImageCreator(object):
if 'debuginfo' in self.install_pkgs:
pkg_manager.install_debuginfo = True
+
for repo in kickstart.get_repos(self.ks, repo_urls, self.ignore_ksrepo):
(name, baseurl, mirrorlist, inc, exc,
proxy, proxy_username, proxy_password, debuginfo,
@@ -1086,7 +1117,7 @@ class BaseImageCreator(object):
self.__select_packages(pkg_manager)
self.__select_groups(pkg_manager)
self.__deselect_packages(pkg_manager)
- self.__localinst_packages(pkg_manager)
+ #self.__localinst_packages(pkg_manager)
self.__check_packages(pkg_manager)
BOOT_SAFEGUARD = 256L * 1024 * 1024 # 256M
@@ -1129,20 +1160,132 @@ class BaseImageCreator(object):
except:
pass
+ def tpkinstall(self):
+ if self.ks:
+ tpk_pkgs = kickstart.get_tpkpackages(self.ks)
+ tpk_repoList = kickstart.get_tpkrepos(self.ks)
+ if tpk_repoList and tpk_pkgs:
+ tpk_dir = "/usr/apps/.preload-tpk"
+ fs.makedirs(self._instroot + "/usr/apps")
+ fs.makedirs(self._instroot + tpk_dir)
+ for pkg in tpk_pkgs:
+ flag = 0
+ for tpk_repo in tpk_repoList:
+ if hasattr(tpk_repo,'baseurl') and tpk_repo.baseurl.startswith("file:"):
+ tpk_repourl = tpk_repo.baseurl.replace('file:','')
+ tpk_repourl = "/%s" % tpk_repourl.lstrip('/')
+ tpk_pkgpath = tpk_repourl + "/"+ pkg
+ if os.path.isfile(tpk_pkgpath):
+ shutil.copy(tpk_pkgpath,self._instroot + tpk_dir)
+ flag = 1
+ break
+ elif hasattr(tpk_repo,'baseurl'):
+ url = tpk_repo.baseurl.join(pkg)
+ filename = self._instroot+tpk_dir+"/"+pkg
+ if tpk_repo.baseurl.startswith("http:"):
+ import urllib
+ status = urllib.urlopen(url).code
+ if status == 200:
+ filename = myurlgrab(url.full, filename, None)
+ flag = 1
+ break
+ elif status == 404 or status == None:
+ continue
+ #url is ok, then download, url wrong, check other url.
+ elif tpk_repo.baseurl.startswith("https:") :
+ try:
+ flag = 1
+ filename = myurlgrab(url.full, filename, None)
+ except CreatorError:
+ continue
+ if flag == 0:
+ raise CreatorError("Tpk package missing.")
+
def postinstall(self):
self.copy_attachment()
+ def _get_sign_scripts_env(self):
+ """Return an environment dict for %post-umount scripts.
+
+ This is the hook where subclasses may specify some environment
+ variables for %post-umount scripts by return a dict containing the
+ desired environment.
+ """
+
+ env = {}
+
+ # Directory path of images
+ if self._imgdir:
+ env['IMG_DIR_PATH'] = str(self._imgdir)
+
+ imgfiles = []
+ imgpaths = []
+ for item in self._instloops:
+ imgfiles.append(item['name'])
+ if self._imgdir:
+ imgpaths.append(os.path.join(self._imgdir, item['name']))
+
+ # Images file name
+ env['IMG_FILES'] = ' '.join(imgfiles)
+
+ # Absolute path of images
+ env['IMG_PATHS'] = ' '.join(imgpaths)
+
+ return env
+
+ def run_sign_scripts(self):
+ if kickstart.get_sign_scripts(self.ks)==[]:
+ return
+ msger.info("Running sign scripts ...")
+ if os.path.exists(self._instroot + "/tmp"):
+ shutil.rmtree(self._instroot + "/tmp")
+ os.mkdir (self._instroot + "/tmp", 0755)
+ for s in kickstart.get_sign_scripts(self.ks):
+ (fd, path) = tempfile.mkstemp(prefix = "ks-runscript-",
+ dir = self._instroot + "/tmp")
+ s.script = s.script.replace("\r", "")
+ os.write(fd, s.script)
+ if s.interp == '/bin/sh' or s.interp == '/bin/bash':
+ os.write(fd, '\n')
+ os.write(fd, 'exit 0\n')
+ os.close(fd)
+ os.chmod(path, 0700)
+
+ env = self._get_sign_scripts_env()
+ oldoutdir = os.getcwd()
+ os.chdir(self._imgdir)
+ try:
+ try:
+ p = subprocess.Popen([s.interp, path],
+ env = env,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.STDOUT)
+ while p.poll() == None:
+ msger.info(p.stdout.readline().strip())
+ if p.returncode != 0:
+ raise CreatorError("Failed to execute %%sign script "
+ "with '%s'" % (s.interp))
+ except OSError, (err, msg):
+ raise CreatorError("Failed to execute %%sign script "
+ "with '%s' : %s" % (s.interp, msg))
+ finally:
+ os.chdir(oldoutdir)
+ os.unlink(path)
+
def __run_post_scripts(self):
- msger.info("Running scripts ...")
+ msger.info("Running post scripts ...")
if os.path.exists(self._instroot + "/tmp"):
shutil.rmtree(self._instroot + "/tmp")
os.mkdir (self._instroot + "/tmp", 0755)
for s in kickstart.get_post_scripts(self.ks):
- (fd, path) = tempfile.mkstemp(prefix = "ks-script-",
+ (fd, path) = tempfile.mkstemp(prefix = "ks-postscript-",
dir = self._instroot + "/tmp")
s.script = s.script.replace("\r", "")
os.write(fd, s.script)
+ if s.interp == '/bin/sh' or s.interp == '/bin/bash':
+ os.write(fd, '\n')
+ os.write(fd, 'exit 0\n')
os.close(fd)
os.chmod(path, 0700)
@@ -1157,6 +1300,7 @@ class BaseImageCreator(object):
preexec = self._chroot
script = "/tmp/" + os.path.basename(path)
+ start_time = time.time()
try:
try:
p = subprocess.Popen([s.interp, script],
@@ -1166,6 +1310,12 @@ class BaseImageCreator(object):
stderr = subprocess.STDOUT)
while p.poll() == None:
msger.info(p.stdout.readline().strip())
+ end_time = time.time()
+ if (end_time - start_time)/60 > MAX_RUN_TIME:
+ raise CreatorError("Your post script is executed more than "+MAX_RUN_TIME+"mins, please check it!")
+ if p.returncode != 0:
+ raise CreatorError("Failed to execute %%post script "
+ "with '%s'" % (s.interp))
except OSError, (err, msg):
raise CreatorError("Failed to execute %%post script "
"with '%s' : %s" % (s.interp, msg))
@@ -1202,8 +1352,8 @@ class BaseImageCreator(object):
kickstart.TimezoneConfig(self._instroot).apply(ksh.timezone)
#kickstart.AuthConfig(self._instroot).apply(ksh.authconfig)
kickstart.FirewallConfig(self._instroot).apply(ksh.firewall)
- kickstart.RootPasswordConfig(self._instroot).apply(ksh.rootpw)
kickstart.UserConfig(self._instroot).apply(ksh.user)
+ kickstart.RootPasswordConfig(self._instroot).apply(ksh.rootpw)
kickstart.ServicesConfig(self._instroot).apply(ksh.services)
kickstart.XConfig(self._instroot).apply(ksh.xconfig)
kickstart.NetworkConfig(self._instroot).apply(ksh.network)
@@ -1250,6 +1400,38 @@ class BaseImageCreator(object):
pass
self._instloops.remove(item)
+ def create_cpio_image(self):
+ for item in self._instloops:
+ if item['cpioopts']:
+ msger.info("Create image by cpio.")
+ tmp_cpio = self.__builddir + "/tmp-cpio"
+ if not os.path.exists(tmp_cpio):
+ os.mkdir(tmp_cpio)
+ tmp_cpio_imgfile = os.path.join(tmp_cpio, item['name'])
+ try:
+ cpiocmd = fs.find_binary_path('cpio')
+ if cpiocmd:
+ oldoutdir = os.getcwd()
+ os.chdir(os.path.join(self._instroot, item['mountpoint'].lstrip('/')))
+ # find . | cpio --create --'format=newc' | gzip > ../ramdisk.img
+ runner.show('find . | cpio --create %s | gzip > %s' % (item['cpioopts'], tmp_cpio_imgfile))
+ os.chdir(oldoutdir)
+ except OSError, (errno, msg):
+ raise CreatorError("Create image by cpio error: %s" % msg)
+
+ def copy_cpio_image(self):
+ for item in self._instloops:
+ if item['cpioopts']:
+ tmp_cpio = self.__builddir + "/tmp-cpio"
+ msger.info("Copy cpio image from %s to %s." %(tmp_cpio, self._imgdir))
+ try:
+ shutil.copyfile(os.path.join(tmp_cpio, item['name']),os.path.join(self._imgdir, item['name']))
+ except IOError:
+ raise CreatorError("Copy cpio image error")
+ os.remove(os.path.join(tmp_cpio, item['name']))
+ if not os.listdir(tmp_cpio):
+ shutil.rmtree(tmp_cpio, ignore_errors=True)
+
def package(self, destdir = "."):
"""Prepares the created image for final delivery.
diff --git a/mic/imager/loop.py b/mic/imager/loop.py
index c0620a4..eb9f381 100644..100755
--- a/mic/imager/loop.py
+++ b/mic/imager/loop.py
@@ -20,7 +20,7 @@ import glob
import shutil
from mic import kickstart, msger
-from mic.utils.errors import CreatorError, MountError
+from mic.utils.errors import CreatorError, MountError, VdfsError
from mic.utils import misc, runner, fs_related as fs
from mic.imager.baseimager import BaseImageCreator
from mic.archive import packing, compressing
@@ -141,6 +141,9 @@ class LoopImageCreator(BaseImageCreator):
part.fstype = "ext4"
label = part.label
+ fslabel = part.fslabel
+ if fslabel == '':
+ fslabel = label
mp = part.mountpoint
if mp == '/':
# the base image
@@ -157,17 +160,22 @@ class LoopImageCreator(BaseImageCreator):
allloops.append({
'mountpoint': mp,
'label': label,
+ 'fslabel':fslabel,
'name': imgname,
'size': part.size or 4096L * 1024 * 1024,
'fstype': part.fstype or 'ext3',
+ 'fsopts': part.fsopts or None,
'aft_fstype': aft_fstype or None,
'extopts': part.extopts or None,
'vdfsopts': part.vdfsopts or None,
'squashfsopts': part.squashfsopts or None,
+ 'cpioopts': part.cpioopts or None,
'loop': None, # to be created in _mount_instroot
'uuid': part.uuid or None,
'kspart' : part,
'exclude_image' : part.exclude_image or None,
+ 'no_shrink': part.no_shrink or False,
+ 'init_expand': part.init_expand or False,
})
self._instloops = allloops
@@ -177,6 +185,7 @@ class LoopImageCreator(BaseImageCreator):
self._instloops = []
self._imgdir = None
+ self._umountdir = None
if self.ks:
self.__image_size = kickstart.get_image_size(self.ks,
@@ -308,10 +317,14 @@ class LoopImageCreator(BaseImageCreator):
"""
minsize = 0
for item in self._instloops:
- if item['name'] == self._img_name:
- minsize = item['loop'].resparse(size)
- else:
- item['loop'].resparse(size)
+ if not item['cpioopts']:
+ if item['no_shrink']:
+ item['loop'].resparse()
+ continue
+ if item['name'] == self._img_name:
+ minsize = item['loop'].resparse(size)
+ else:
+ item['loop'].resparse(size)
return minsize
@@ -328,7 +341,6 @@ class LoopImageCreator(BaseImageCreator):
# Actual implementation
#
def _mount_instroot(self, base_on=None):
-
if base_on and os.path.isfile(base_on):
self._imgdir = os.path.dirname(base_on)
imgname = os.path.basename(base_on)
@@ -353,6 +365,7 @@ class LoopImageCreator(BaseImageCreator):
for loop in self._instloops:
fstype = loop['fstype']
+ fsopt = loop['fsopts']
mp = os.path.join(self._instroot, loop['mountpoint'].lstrip('/'))
size = loop['size'] * 1024L * 1024L
imgname = loop['name']
@@ -372,7 +385,8 @@ class LoopImageCreator(BaseImageCreator):
mp,
fstype,
self._blocksize,
- loop['label'],
+ loop['fslabel'],
+ fsopt,
fsuuid = loop['uuid'])
if fstype in ("ext2", "ext3", "ext4"):
@@ -381,7 +395,7 @@ class LoopImageCreator(BaseImageCreator):
try:
msger.verbose('Mounting image "%s" on "%s"' % (imgname, mp))
fs.makedirs(mp)
- loop['loop'].mount()
+ loop['loop'].mount(fsopt, init_expand=loop['init_expand'])
# Make an autogenerated uuid avaialble in _get_post_scripts_env()
if loop['kspart'] and loop['kspart'].uuid is None and \
loop['loop'].uuid:
@@ -397,6 +411,15 @@ class LoopImageCreator(BaseImageCreator):
except:
pass
+ def _get_sign_scripts_env(self):
+ env = BaseImageCreator._get_sign_scripts_env(self)
+
+ # Directory path of %post-umounts scripts
+ if self._umountdir:
+ env['UMOUNT_SCRIPTS_PATH'] = str(self._umountdir)
+
+ return env
+
def _stage_final_image(self):
if self.pack_to or self.shrink_image:
@@ -436,7 +459,10 @@ class LoopImageCreator(BaseImageCreator):
fullpathmkvdfs = "mkfs.vdfs" #find_binary_path("mkfs.vdfs")
runner.show("%s --help" % fullpathmkvdfs)
# fs.mkvdfs(mountpoint, self._outdir+"/"+item['label']+fs_suffix, vdfsopts)
- runner.show('%s %s -r %s %s' % (fullpathmkvdfs, vdfsopts, mountpoint, self._imgdir+"/"+item['label']+fs_suffix))
+ ret = runner.show('%s %s -r %s %s' % (fullpathmkvdfs, vdfsopts, mountpoint, self._imgdir+"/"+item['label']+fs_suffix))
+ if ret != 0:
+ runner.show("mkfs.vdfs return error")
+ raise VdfsError("' %s' exited with error (%d)" % (fullpathmkvdfs, ret))
runner.show('umount %s' % mountpoint)
# os.unlink(mountpoint)
@@ -444,8 +470,10 @@ class LoopImageCreator(BaseImageCreator):
runner.show('ls -al %s' % self._imgdir)
if item['fstype'] == "ext4":
- runner.show('/sbin/tune2fs -O ^huge_file,extents,uninit_bg %s '
+ if not item['cpioopts']:
+ runner.show('/sbin/tune2fs -O ^huge_file,extents,uninit_bg %s '
% imgfile)
+ runner.quiet(["/sbin/e2fsck", "-f", "-y", imgfile])
self.image_files.setdefault('partitions', {}).update(
{item['mountpoint']: item['label']})
if self.compress_image:
@@ -455,6 +483,12 @@ class LoopImageCreator(BaseImageCreator):
else:
self.image_files.setdefault('image_files', []).append(item['name'])
+ for item in os.listdir(self._imgdir):
+ imgfile = os.path.join(self._imgdir, item)
+ imgsize = os.path.getsize(imgfile)
+ msger.info("filesystem size of %s : %s bytes" % (item, imgsize))
+
+ self.run_sign_scripts()
if not self.pack_to:
for item in os.listdir(self._imgdir):
shutil.move(os.path.join(self._imgdir, item),
@@ -490,6 +524,23 @@ class LoopImageCreator(BaseImageCreator):
msger.verbose("Copy attachment %s to %s" % (item, dpath))
shutil.copy(item, dpath)
+ def move_post_umount_scripts(self):
+ scripts_dir = self._instroot + "/var/tmp/post_umount_scripts"
+ if not os.path.exists(scripts_dir):
+ return
+ self._umountdir = self._mkdtemp("umount")
+ msger.info("Moving post umount scripts...")
+ for item in os.listdir(scripts_dir):
+ spath = os.path.join(scripts_dir, item)
+ dpath = os.path.join(self._umountdir, item)
+ msger.verbose("Move post umount scripts %s to %s" % (spath, dpath))
+ shutil.move(spath, dpath)
+ shutil.rmtree(scripts_dir)
+
+ def postinstall(self):
+ BaseImageCreator.postinstall(self)
+ self.move_post_umount_scripts()
+
def create_manifest(self):
if self.compress_image:
self.image_files.update({'compress': self.compress_image})
diff --git a/mic/kickstart/__init__.py b/mic/kickstart/__init__.py
index fb0e4d8..4cf9bd7 100755
--- a/mic/kickstart/__init__.py
+++ b/mic/kickstart/__init__.py
@@ -70,6 +70,22 @@ class AttachmentSection(kssections.Section):
def handleHeader(self, lineno, args):
kssections.Section.handleHeader(self, lineno, args)
+class EnvSection(kssections.Section):
+ sectionOpen = "%env"
+
+ def handleLine(self, line):
+ if not self.handler:
+ return
+
+ (h, s, t) = line.partition('#')
+ line = h.rstrip()
+ (n, s, v) = line.partition('=')
+ self.handler.env.append((n, v))
+
+ def handleHeader(self, lineno, args):
+ self.handler.env = []
+ kssections.Section.handleHeader(self, lineno, args)
+
def apply_wrapper(func):
def wrapper(*kargs, **kwargs):
try:
@@ -100,11 +116,13 @@ def read_kickstart(path):
using_version = ksversion.DEVEL
commandMap[using_version]["desktop"] = desktop.Mic_Desktop
commandMap[using_version]["repo"] = micrepo.Mic_Repo
+ commandMap[using_version]["tpk_repo"] = micrepo.Mic_Tpk_Repo
commandMap[using_version]["bootloader"] = micboot.Mic_Bootloader
commandMap[using_version]["part"] = partition.Mic_Partition
commandMap[using_version]["partition"] = partition.Mic_Partition
commandMap[using_version]["installerfw_plugins"] = installerfw.Mic_installerfw
dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
+ dataMap[using_version]["Tpk_RepoData"] = micrepo.Mic_Tpk_RepoData
dataMap[using_version]["PartData"] = partition.Mic_PartData
superclass = ksversion.returnClassForVersion(version=using_version)
@@ -117,6 +135,7 @@ def read_kickstart(path):
ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False)
ks.registerSection(PrepackageSection(ks.handler))
ks.registerSection(AttachmentSection(ks.handler))
+ ks.registerSection(EnvSection(ks.handler))
try:
ks.readKickstart(path)
@@ -200,16 +219,23 @@ class TimezoneConfig(KickstartConfig):
f.write("ZONE=\"" + tz + "\"\n")
f.write("UTC=" + utc + "\n")
f.close()
+ if not os.path.exists("/opt/etc"):
+ fs.makedirs("/opt/etc")
tz_source = "/usr/share/zoneinfo/%s" % (tz)
+ tz_midst = "/opt/etc/localtime"
tz_dest = "/etc/localtime"
try:
- cpcmd = fs.find_binary_inchroot('ln', self.instroot)
- if cpcmd:
- self.call([cpcmd, "-s", tz_source, tz_dest])
+ lncmd = fs.find_binary_inchroot('ln', self.instroot)
+ if lncmd:
+ self.call([lncmd, "-s", tz_source, tz_midst])
+ self.call([lncmd, "-s", tz_midst, tz_dest])
else:
- cpcmd = fs.find_binary_path('ln')
- subprocess.call([cpcmd, "-s",
+ lncmd = fs.find_binary_path('ln')
+ subprocess.call([lncmd, "-s",
self.path(tz_source),
+ self.path(tz_midst)])
+ subprocess.call([lncmd, "-s",
+ self.path(tz_midst),
self.path(tz_dest)])
except (IOError, OSError), (errno, msg):
raise errors.KsError("Timezone setting error: %s" % msg)
@@ -256,7 +282,7 @@ class RootPasswordConfig(KickstartConfig):
p1 = subprocess.Popen(["/bin/echo", "root:%s" %password],
stdout = subprocess.PIPE,
preexec_fn = self.chroot)
- p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-m"],
+ p2 = subprocess.Popen(["/usr/sbin/chpasswd", "-c","SHA512"],
stdin = p1.stdout,
stdout = subprocess.PIPE,
preexec_fn = self.chroot)
@@ -765,9 +791,32 @@ def get_repos(ks, repo_urls=None, ignore_ksrepo=False):
repo.get('user', None),
repo.get('passwd', None))
repos[name] = Repo(**repo)
-
return repos.values()
+TpkRepoType = collections.namedtuple("TpkRepo",
+ "name, baseurl,proxy,proxy_username,proxy_password,ssl_verify")
+
+def TpkRepo(name, baseurl, proxy=None,proxy_username=None, proxy_password=None,ssl_verify=None):
+ return TpkRepoType(name, baseurl,proxy,proxy_username,proxy_password,ssl_verify)
+
+
+def get_tpkrepos(ks):
+ tpkrepos = {}
+ for tpkrepodata in ks.handler.tpk_repo.tpkRepoList:
+ tpkrepo = {}
+ for field in TpkRepoType._fields:
+ if hasattr(tpkrepodata, field) and getattr(tpkrepodata, field):
+ tpkrepo[field] = getattr(tpkrepodata, field)
+
+ if hasattr(tpkrepodata, 'baseurl') and getattr(tpkrepodata, 'baseurl'):
+ tpkrepo['baseurl'] = SafeURL(getattr(tpkrepodata, 'baseurl'),getattr(tpkrepodata, 'user',None),getattr(tpkrepodata, 'passwd',None))
+
+ if 'name' in tpkrepo:
+ tpkrepos[tpkrepo['name']] = TpkRepo(**tpkrepo)
+
+ return tpkrepos.values()
+
+
def convert_method_to_repo(ks):
try:
ks.handler.repo.methodToRepo()
@@ -777,12 +826,18 @@ def convert_method_to_repo(ks):
def get_attachment(ks, required=()):
return ks.handler.attachment.packageList + list(required)
+def get_env(ks, required=()):
+ return ks.handler.env
+
def get_pre_packages(ks, required=()):
return ks.handler.prepackages.packageList + list(required)
def get_packages(ks, required=()):
return ks.handler.packages.packageList + list(required)
+def get_tpkpackages(ks):
+ return ks.handler.tpk_packages.tpk_packageList
+
def get_groups(ks, required=()):
return ks.handler.packages.groupList + list(required)
@@ -813,6 +868,14 @@ def get_post_scripts(ks):
scripts.append(s)
return scripts
+def get_sign_scripts(ks):
+ scripts = []
+ for s in ks.handler.scripts:
+ if (s.type == ksparser.KS_SCRIPT_RUN or \
+ s.type == ksparser.KS_SCRIPT_UMOUNT):
+ scripts.append(s)
+ return scripts
+
def add_repo(ks, repostr):
args = repostr.split()
repoobj = ks.handler.repo.parse(args[1:])
diff --git a/mic/kickstart/custom_commands/__init__.py b/mic/kickstart/custom_commands/__init__.py
index 5f4c440..381c917 100644
--- a/mic/kickstart/custom_commands/__init__.py
+++ b/mic/kickstart/custom_commands/__init__.py
@@ -1,5 +1,5 @@
from desktop import Mic_Desktop
-from micrepo import Mic_Repo, Mic_RepoData
+from micrepo import Mic_Repo, Mic_RepoData,Mic_Tpk_Repo, Mic_Tpk_RepoData
from partition import Mic_Partition
from installerfw import Mic_installerfw
@@ -7,6 +7,8 @@ __all__ = (
"Mic_Desktop",
"Mic_Repo",
"Mic_RepoData",
+ "Mic_Tpk_Repo",
+ "Mic_Tpk_RepoData",
"Mic_Partition",
"Mic_installerfw",
)
diff --git a/mic/kickstart/custom_commands/micrepo.py b/mic/kickstart/custom_commands/micrepo.py
index b38ae77..25cdae9 100644
--- a/mic/kickstart/custom_commands/micrepo.py
+++ b/mic/kickstart/custom_commands/micrepo.py
@@ -50,6 +50,14 @@ class Mic_RepoData(F14_RepoData):
return retval
+class Mic_Tpk_RepoData(Mic_RepoData):
+ "Mic customized tpk repo data"
+ def __init__(self, *args, **kw):
+ Mic_RepoData.__init__(self, *args, **kw)
+ def __str__(self):
+ retval = Mic_RepoData._getArgsAsStr(self)
+ retval = "tpk_repo " + retval
+ return retval
class Mic_Repo(F14_Repo):
"Mic customized repo command"
@@ -71,3 +79,19 @@ class Mic_Repo(F14_Repo):
op.add_option("--priority", type="int")
op.add_option("--ssl_verify", default=None)
return op
+
+
+class Mic_Tpk_Repo(Mic_Repo):
+ def __init__(self, writePriority=0, *args, **kwargs):
+ Mic_Repo.__init__(self, writePriority, *args, **kwargs)
+ self.op = self._getParser()
+
+ self.tpkRepoList = kwargs.get("tpkRepoList", [])
+
+ def _getParser(self):
+ op = Mic_Repo._getParser(self)
+ return op
+
+ def dataList(self):
+ return self.tpkRepoList
+
diff --git a/mic/kickstart/custom_commands/partition.py b/mic/kickstart/custom_commands/partition.py
index 1d31c11..341e8dc 100644..100755
--- a/mic/kickstart/custom_commands/partition.py
+++ b/mic/kickstart/custom_commands/partition.py
@@ -31,6 +31,9 @@ class Mic_PartData(FC4_PartData):
self.exclude_image = kwargs.get("exclude_from_image", False)
self.vdfsopts = kwargs.get("vdfsopts", None)
self.squashfsopts = kwargs.get("squashfsopts", None)
+ self.cpioopts = kwargs.get("cpioopts", None)
+ self.no_shrink = kwargs.get("no_shrink", False)
+ self.init_expand = kwargs.get("init_expand", False)
def _getArgsAsStr(self):
retval = FC4_PartData._getArgsAsStr(self)
@@ -49,7 +52,12 @@ class Mic_PartData(FC4_PartData):
retval += " --vdfsoptions=%s" % self.vdfsopts
if self.squashfsopts:
retval += " --squashfsoptions=%s" % self.squashfsopts
-
+ if self.cpioopts:
+ retval += " --cpiooptions=%s" % self.cpioopts
+ if self.no_shrink:
+ retval += " --no-shrink"
+ if self.init_expand:
+ retval += " --init-expand"
return retval
class Mic_Partition(FC4_Partition):
@@ -73,4 +81,8 @@ class Mic_Partition(FC4_Partition):
default=None)
op.add_option("--squashfsoptions", type="string", action="store", dest="squashfsopts",
default=None)
+ op.add_option("--cpiooptions", type="string", action="store", dest="cpioopts",
+ default=None)
+ op.add_option("--no-shrink", action="store_true", dest="no_shrink", default=False)
+ op.add_option("--init-expand", action="store_true", dest="init_expand", default=False)
return op
diff --git a/mic/msger.py b/mic/msger.py
index 49bdc2f..31ac9bd 100644
--- a/mic/msger.py
+++ b/mic/msger.py
@@ -133,6 +133,7 @@ class RedirectedStderr(object):
""" Truncate the tempfile to size zero """
if self.tmpfile:
os.ftruncate(self.tmpfile.fileno(), 0)
+ os.lseek(self.tmpfile.fileno(), 0, os.SEEK_SET)
def redirect(self):
""" Redirect stderr to the temp file """
@@ -154,6 +155,7 @@ class RedirectedStderr(object):
self.tmpfile.seek(0, 0)
self.value = self.tmpfile.read()
os.ftruncate(self.tmpfile.fileno(), 0)
+ os.lseek(self.tmpfile.fileno(), 0, os.SEEK_SET)
return self.value
return None
diff --git a/mic/pluginbase.py b/mic/pluginbase.py
index 541ac8a..ffdd993 100644
--- a/mic/pluginbase.py
+++ b/mic/pluginbase.py
@@ -86,11 +86,6 @@ class ImagerPlugin(_Plugin):
class BackendPlugin(_Plugin):
mic_plugin_type="backend"
- # suppress the verbose rpm warnings
- if msger.get_loglevel() != 'debug':
- import rpm
- rpm.setVerbosity(rpm.RPMLOG_ERR)
-
def addRepository(self):
pass
diff --git a/mic/rt_util.py b/mic/rt_util.py
index 3897efc..61b0bb2 100644
--- a/mic/rt_util.py
+++ b/mic/rt_util.py
@@ -104,7 +104,11 @@ def bootstrap_mic(argv=None):
rootdir = os.path.join(rootdir, "bootstrap")
bsenv.dirsetup(rootdir)
- sync_mic(rootdir, plugin=cropts['plugin_dir'])
+ if cropts['use_mic_in_bootstrap']:
+ msger.info("No copy host mic")
+ else:
+ msger.info("Copy host mic to bootstrap")
+ sync_mic(rootdir, plugin=cropts['plugin_dir'])
#FIXME: sync the ks file to bootstrap
if "/" == os.path.dirname(os.path.abspath(configmgr._ksconf)):
@@ -144,6 +148,8 @@ def get_bindmounts(cropts):
for lrepo in cropts['localrepos']:
binddirs.append(lrepo)
+ for ltpkrepo in cropts['localtpkrepos']:
+ binddirs.append(ltpkrepo)
bindlist = map(expath, filter(None, binddirs))
bindlist += map(os.path.dirname, map(expath, filter(None, bindfiles)))
diff --git a/mic/utils/fs_related.py b/mic/utils/fs_related.py
index 54f68da..11f6801 100644..100755
--- a/mic/utils/fs_related.py
+++ b/mic/utils/fs_related.py
@@ -18,6 +18,7 @@
from __future__ import with_statement
import os
+import re
import sys
import errno
import stat
@@ -304,6 +305,17 @@ class LoopbackDisk(Disk):
rc = runner.show([self.losetupcmd, "-d", self.device])
self.device = None
+ def reread_size(self):
+ if self.device is None:
+ return
+ msger.debug("Reread size %s" % self.device)
+ rc = runner.show([self.losetupcmd, "-c", self.device])
+ # XXX: (WORKAROUND) re-setup loop device when losetup isn't support '-c' option.
+ if rc != 0:
+ msger.debug("Fail to reread size, Try to re-setup loop device to reread the size of the file associated")
+ runner.show([self.losetupcmd, "-d", self.device])
+ runner.show([self.losetupcmd, self.device, self.lofile])
+
class SparseLoopbackDisk(LoopbackDisk):
"""A Disk backed by a sparse file via the loop module."""
def __init__(self, lofile, size):
@@ -345,10 +357,13 @@ class SparseLoopbackDisk(LoopbackDisk):
os.close(fd)
def create(self):
+ if self.device is not None:
+ return
+
self.expand(create = True)
LoopbackDisk.create(self)
-class Mount:
+class Mount(object):
"""A generic base class to deal with mounting things."""
def __init__(self, mountdir):
self.mountdir = mountdir
@@ -440,10 +455,25 @@ class ExtDiskMount(DiskMount):
self.uuid = fsuuid or str(uuid.uuid4())
self.skipformat = skipformat
self.fsopts = fsopts
- self.extopts = None
+ self.__extopts = None
self.dumpe2fs = find_binary_path("dumpe2fs")
self.tune2fs = find_binary_path("tune2fs")
+ def __get_extopts(self):
+ return self.__extopts
+
+ def __set_extopts(self, val):
+ if val is None:
+ self.__extopts = None
+ else:
+ m = re.search(r'-b\s*(?P<blocksize>\d+)', val)
+ if m:
+ self.blocksize = int(m.group('blocksize'))
+ val = val.replace(m.group(), '')
+ self.__extopts = val
+
+ extopts = property(__get_extopts, __set_extopts)
+
def __parse_field(self, output, field):
for line in output.split("\n"):
if line.startswith(field + ":"):
@@ -459,8 +489,8 @@ class ExtDiskMount(DiskMount):
msger.verbose("Formating %s filesystem on %s" % (self.fstype, self.disk.device))
cmdlist = [self.mkfscmd, "-F", "-L", self.fslabel, "-m", "1", "-b",
str(self.blocksize), "-U", self.uuid]
- if self.extopts:
- cmdlist.extend(self.extopts.split())
+ if self.__extopts:
+ cmdlist.extend(self.__extopts.split())
cmdlist.extend([self.disk.device])
rc, errout = runner.runtool(cmdlist, catch=2)
@@ -468,7 +498,7 @@ class ExtDiskMount(DiskMount):
raise MountError("Error creating %s filesystem on disk %s:\n%s" %
(self.fstype, self.disk.device, errout))
- if not self.extopts:
+ if not self.__extopts:
msger.debug("Tuning filesystem on %s" % self.disk.device)
runner.show([self.tune2fs, "-c0", "-i0", "-Odir_index", "-ouser_xattr,acl", self.disk.device])
@@ -483,11 +513,14 @@ class ExtDiskMount(DiskMount):
return
if size > current_size:
- self.disk.expand(size)
+ self.disk.expand(size=size)
self.__fsck()
resize2fs(self.disk.lofile, size)
+ if size and size != os.stat(self.disk.lofile)[stat.ST_SIZE]:
+ raise MountError("Failed to resize filesystem %s to " % (self.disk.lofile, size))
+
return size
def __create(self):
@@ -502,8 +535,13 @@ class ExtDiskMount(DiskMount):
else:
self.__format_filesystem()
- def mount(self, options = None):
+ def mount(self, options = None, init_expand = False):
self.__create()
+ if init_expand:
+ expand_size = long(self.disk.size * 1.5)
+ msger.info("Initial partition size expanded : %ld -> %ld" % (self.disk.size, expand_size))
+ self.__resize_filesystem(expand_size)
+ self.disk.reread_size()
DiskMount.mount(self, options)
def __fsck(self):
@@ -517,21 +555,8 @@ class ExtDiskMount(DiskMount):
def __resize_to_minimal(self):
msger.info("Resizing filesystem to minimal ...")
self.__fsck()
-
- #
- # Use a binary search to find the minimal size
- # we can resize the image to
- #
- bot = 0
- top = self.__get_size_from_filesystem()
- while top != (bot + 1):
- t = bot + ((top - bot) / 2)
-
- if not resize2fs(self.disk.lofile, t):
- top = t
- else:
- bot = t
- return top
+ resize2fs(self.disk.lofile, 0)
+ return self.__get_size_from_filesystem()
def resparse(self, size = None):
self.cleanup()
@@ -580,7 +605,7 @@ class VfatDiskMount(DiskMount):
return
if size > current_size:
- self.disk.expand(size)
+ self.disk.expand(size=size)
self.__fsck()
@@ -599,8 +624,13 @@ class VfatDiskMount(DiskMount):
else:
self.__format_filesystem()
- def mount(self, options = None):
+ def mount(self, options = None, init_expand = False):
self.__create()
+ if init_expand:
+ expand_size = long(self.disk.size * 1.5)
+ msger.info("Initial partition size expanded : %ld -> %ld" % (self.disk.size, expand_size))
+ self.__resize_filesystem(expand_size)
+ self.disk.reread_size()
DiskMount.mount(self, options)
def __fsck(self):
@@ -685,7 +715,7 @@ class BtrfsDiskMount(DiskMount):
return
if size > current_size:
- self.disk.expand(size)
+ self.disk.expand(size=size)
self.__fsck()
return size
@@ -702,8 +732,13 @@ class BtrfsDiskMount(DiskMount):
else:
self.__format_filesystem()
- def mount(self, options = None):
+ def mount(self, options = None, init_expand = False):
self.__create()
+ if init_expand:
+ expand_size = long(self.disk.size * 1.5)
+ msger.info("Initial partition size expanded : %ld -> %ld" % (self.disk.size, expand_size))
+ self.__resize_filesystem(expand_size)
+ self.disk.reread_size()
DiskMount.mount(self, options)
def __fsck(self):
@@ -959,7 +994,7 @@ def get_loop_device(losetupcmd, lofile):
clean_loop_devices()
# provide an avaible loop device
- rc, out = runner.runtool([losetupcmd, "--find"])
+ rc, out = runner.runtool([losetupcmd, "-f"])
if rc == 0 and out:
loopdev = out.split()[0]
devinst.register(loopdev)
@@ -990,7 +1025,6 @@ def get_loop_device(losetupcmd, lofile):
try:
fcntl.flock(fp, fcntl.LOCK_UN)
fp.close()
- os.unlink(DEVICE_LOCKFILE)
except:
pass
diff --git a/mic/utils/misc.py b/mic/utils/misc.py
index f7693b2..be14d01 100755
--- a/mic/utils/misc.py
+++ b/mic/utils/misc.py
@@ -41,6 +41,7 @@ except ImportError:
xmlparse = cElementTree.parse
from mic import msger
+from mic.archive import get_archive_suffixes
from mic.utils.errors import CreatorError, SquashfsError
from mic.utils.fs_related import find_binary_path, makedirs
from mic.utils.grabber import myurlgrab
@@ -619,7 +620,8 @@ def get_metadata_from_repos(repos, cachedir):
"proxies":proxies,
"patterns":filepaths['patterns'],
"comps":filepaths['comps'],
- "repokey":repokey})
+ "repokey":repokey,
+ "priority":repo.priority})
return my_repo_metadata
@@ -697,6 +699,7 @@ def get_arch(repometadata):
def get_package(pkg, repometadata, arch = None):
ver = ""
+ priority = 99
target_repo = None
if not arch:
arches = []
@@ -714,6 +717,16 @@ def get_package(pkg, repometadata, arch = None):
for elm in root.getiterator("%spackage" % ns):
if elm.find("%sname" % ns).text == pkg:
if elm.find("%sarch" % ns).text in arches:
+ if repo["priority"] != None:
+ tmpprior = int(repo["priority"])
+ if tmpprior < priority:
+ priority = tmpprior
+ location = elm.find("%slocation" % ns)
+ pkgpath = "%s" % location.attrib['href']
+ target_repo = repo
+ break
+ elif tmpprior > priority:
+ break
version = elm.find("%sversion" % ns)
tmpver = "%s-%s" % (version.attrib['ver'], version.attrib['rel'])
if tmpver > ver:
@@ -886,6 +899,7 @@ def is_statically_linked(binary):
return ", statically linked, " in runner.outs(['file', binary])
def setup_qemu_emulator(rootdir, arch):
+ qemu_emulators = []
# mount binfmt_misc if it doesn't exist
if not os.path.exists("/proc/sys/fs/binfmt_misc"):
modprobecmd = find_binary_path("modprobe")
@@ -928,18 +942,13 @@ def setup_qemu_emulator(rootdir, arch):
if not os.path.exists(rootdir + "/usr/bin"):
makedirs(rootdir + "/usr/bin")
shutil.copy(qemu_emulator, rootdir + qemu_emulator)
+ qemu_emulators.append(qemu_emulator)
# disable selinux, selinux will block qemu emulator to run
if os.path.exists("/usr/sbin/setenforce"):
msger.info('Try to disable selinux')
runner.show(["/usr/sbin/setenforce", "0"])
- # unregister it if it has been registered and is a dynamically-linked executable
- if os.path.exists(node):
- qemu_unregister_string = "-1\n"
- with open(node, "w") as fd:
- fd.write(qemu_unregister_string)
-
# register qemu emulator for interpreting other arch executable file
if not os.path.exists(node):
if arch == "aarch64":
@@ -948,10 +957,29 @@ def setup_qemu_emulator(rootdir, arch):
qemu_arm_string = ":mipsel:M::\\x7fELF\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x08\\x00:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xfe\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfe\\xff\\xff\\xff:%s:\n" % qemu_emulator
else:
qemu_arm_string = ":arm:M::\\x7fELF\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x28\\x00:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfa\\xff\\xff\\xff:%s:\n" % qemu_emulator
+
with open("/proc/sys/fs/binfmt_misc/register", "w") as fd:
fd.write(qemu_arm_string)
-
- return qemu_emulator
+ else:
+ flags = ""
+ interpreter = ""
+ with open(node, "r") as fd:
+ for line in fd.readlines():
+ if line.startswith("flags:"):
+ flags = line[len("flags:"):].strip()
+ elif line.startswith("interpreter"):
+ interpreter = line[len("interpreter"):].strip()
+
+ if flags == "P" and interpreter.endswith("-binfmt"):
+ # copy binfmt wrapper when preserve-argv[0] flag is enabled
+ shutil.copy(os.path.realpath(interpreter), rootdir + interpreter)
+ qemu_emulators.append(interpreter)
+ elif not flags and interpreter != qemu_emulator:
+ # create symlink as registered qemu emulator
+ os.symlink(qemu_emulator, rootdir + interpreter)
+ qemu_emulators.append(interpreter)
+
+ return qemu_emulators
def SrcpkgsDownload(pkgs, repometadata, instroot, cachedir):
def get_source_repometadata(repometadata):
@@ -1017,3 +1045,11 @@ def strip_end(text, suffix):
if not text.endswith(suffix):
return text
return text[:-len(suffix)]
+
+def strip_archive_suffix(filename):
+ for suffix in get_archive_suffixes():
+ if filename.endswith(suffix):
+ return filename[:-len(suffix)]
+ else:
+ msger.warning("Not supported archive file format: %s" % filename)
+ return None
diff --git a/mic/utils/proxy.py b/mic/utils/proxy.py
index acb05e4..438f529 100644
--- a/mic/utils/proxy.py
+++ b/mic/utils/proxy.py
@@ -18,6 +18,7 @@
import os
import re
import urlparse
+from mic import msger
_my_proxies = {}
_my_noproxy = None
@@ -101,6 +102,28 @@ def _set_noproxy_list():
_my_noproxy_list = []
if not _my_noproxy:
return
+
+ #solve in /etc/enviroment contains command like `echo 165.xxx.xxx.{1..255} | sed 's/ /,/g'``
+ _my_noproxy_bak = _my_noproxy
+ start = _my_noproxy.find("`")
+ while(start < len(_my_noproxy) and start != -1):
+ start = _my_noproxy.find("`",start)
+ end = _my_noproxy.find("`",start+1)
+ cmd = _my_noproxy[start+1:end]
+ pstr = _my_noproxy[start:end+1]
+ start = end + 1
+
+ _my_noproxy=_my_noproxy.replace(pstr,len(pstr)*" ")
+ try:
+ c_result = os.popen(cmd).readlines()
+ if len(c_result) == 0:
+ continue
+ except Exception,e:
+ msger.warning(str(e))
+ continue
+ to_list = c_result[0].strip("\n").split(",")
+ _my_noproxy_list.extend(to_list)
+
for item in _my_noproxy.split(","):
item = item.strip()
if not item:
@@ -134,6 +157,7 @@ def _set_noproxy_list():
ip &= netmask
_my_noproxy_list.append({"match":2, "needle":ip, "netmask":netmask})
+ _my_noproxy = _my_noproxy_bak
def _isnoproxy(url):
host = urlparse.urlparse(url)[1]
diff --git a/mic/utils/rpmmisc.py b/mic/utils/rpmmisc.py
index 351f2b8..eb481f8 100644
--- a/mic/utils/rpmmisc.py
+++ b/mic/utils/rpmmisc.py
@@ -75,10 +75,10 @@ class RPMInstallCallback:
fmt_bar = "%-" + width + "s"
if progress:
bar = fmt_bar % (self.mark * int(marks * (percent / 100.0)), )
- fmt = "%-10.10s: %-20.20s " + bar + " " + done
+ fmt = "%-10.10s: %-50.50s " + bar + " " + done
else:
bar = fmt_bar % (self.mark * marks, )
- fmt = "%-10.10s: %-20.20s " + bar + " " + done
+ fmt = "%-10.10s: %-50.50s " + bar + " " + done
return fmt
def _logPkgString(self, hdr):
@@ -112,6 +112,13 @@ class RPMInstallCallback:
rpmloc = h
hdr = readRpmHeader(self.ts, h)
+ m = re.match("(.*)-(\d+.*)-(\d+\.\d+)\.(.+)\.rpm", os.path.basename(rpmloc))
+ if m:
+ pkgname = m.group(1)
+ else:
+ pkgname = os.path.basename(rpmloc)
+ msger.info("Next install: %s " % pkgname)
+
handle = self._makeHandle(hdr)
fd = os.open(rpmloc, os.O_RDONLY)
self.callbackfilehandles[handle]=fd
@@ -188,6 +195,20 @@ class RPMInstallCallback:
elif what == rpm.RPMCALLBACK_REPACKAGE_PROGRESS:
pass
+ elif what == rpm.RPMCALLBACK_SCRIPT_ERROR:
+ if h is not None:
+ try:
+ hdr, rpmloc = h
+ except:
+ rpmloc = h
+
+ m = re.match("(.*)-(\d+.*)-(\d+\.\d+)\.(.+)\.rpm", os.path.basename(rpmloc))
+ if m:
+ pkgname = m.group(1)
+ else:
+ pkgname = os.path.basename(rpmloc)
+
+ msger.warning('(%s) Post script failed' % pkgname)
def readRpmHeader(ts, filename):
""" Read an rpm header. """
@@ -301,6 +322,7 @@ archPolicies = {
"armv5tejl": "armv5tejl:armv5tel:armv5l:armv4tl:armv4l:armv3l",
"armv5tel": "armv5tel:armv5l:armv4tl:armv4l:armv3l",
"armv5l": "armv5l:armv4tl:armv4l:armv3l",
+ "mipsel": "mipsel",
}
# dict mapping arch -> ( multicompat, best personality, biarch personality )
@@ -334,6 +356,8 @@ arches = {
#itanium
"ia64": "noarch",
+
+ "mipsel": "mipsel",
}
def isMultiLibArch(arch=None):
diff --git a/packaging/mic.changes b/packaging/mic.changes
index 935ed3a..a2de735 100644..100755
--- a/packaging/mic.changes
+++ b/packaging/mic.changes
@@ -1,3 +1,80 @@
+* Fri Feb 15 2019 Jin Xiao <jin.xiao@samsung.com> - 0.28.6
+ * new distribution support: Ubuntu 18.04.
+
+* Wed Oct 31 2018 Jin Xiao <jin.xiao@samsung.com> - 0.28.5
+ * Add %env section support.
+
+* Fri Sep 28 2018 Jin Xiao <jin.xiao@samsung.com> - 0.28.4
+ * add new option --fslabel in part section.
+
+* Fri Sep 14 2018 Jin Xiao <jin.xiao@samsung.com> - 0.28.3
+ * Revert "ext4 images are created with inode size 256 bytes".
+
+* Fri Aug 03 2018 Jin Xiao <jin.xiao@samsung.com> - 0.28.2
+ * remove tmp dir in runscript period.
+ * ext4 images are created with inode size 256 bytes.
+ * Add locale related environment varibale because language is not set to one specified in ks file.
+
+* Fri May 11 2018 Jin Xiao <jin.xiao@samsung.com> - 0.28.1
+ * Check exit status of vdfs image creation
+ * Change the user and root passwd hash algorithm order to avoid user name same as root name.
+
+* Fri April 13 2018 Jin Xiao <jin.xiao@samsung.com> - 0.28
+ * Apply btrfs mount options "--fsoptions=compress"
+ * In Tizen, losetup command support '-f' option, change '--find' to '-f'
+ * Fix issue, set blocksize by parsing "-b [BLOCKSIZE]" from extoptions in ks file
+
+* Fri Mar 23 2018 Xiaojuan Mao <xiaojuan.mao@samsung.com> - 0.27.9
+ * Added ATTACHMENT_PATHS env and IMG_DIR_PATH env
+ * Revert "call copy_attachment() after configure() and move attachment files"
+
+* Fri Jan 26 2018 Xiaojuan Mao <xiaojuan.mao@samsung.com> - 0.27.8
+ * Use SHA512 instead of MD5 to encrypt root password
+ * Fix the bug that use local mic-bootstrap to run mic.
+ * Support local mic-bootstrap rpm package to run mic.
+ * Another method of install tpk.
+ * The value of fstype is not cpio, an image is generated by cpio.
+ * When increase rpm release number, user can use --local-pkgs-path to install local pkgs.
+ * use the value of --pack-to option as filename to match all outputs
+ * support both %runscript and %post-umount to perform scripts before packaging
+ * support multiple mic execution at same time
+ * add --use-mic-in-bootstrap option
+ * Display all rpm debug messages with --rpm-debug
+ * call copy_attachment() after configure() and move attachment files
+ * Add init_expand option to partition
+ * add no_shrink option to partition, fix parameter of disk.expand()
+ * Setup environment to perform signing script
+ * if post scripts fails, CreatorError is raised to catch script errors such as signing error
+ * use registered qemu emulator filename if already registered.
+
+* Fri Sep 15 2017 Yuhuan Yang <yuhuan.yang@samsung.com> - 0.27.7
+ * Timezone setting change
+ * Run certain script before creation of tar.gz image
+ * Locally built mic-bootstrap using gbs cannot be used in mic
+ * Add new option of tpk_install
+ * Amend mic cr option of run_script
+ * Add new option of --run_script
+ * fix the bug that modify the order of generating image by cpio
+ * Modify the order of generating image by cpio
+
+* Fri Jun 30 2017 Xiaojuan Mao <xiaojuan.mao@samsung.com> - 0.27.6
+ * Use cpio gzip in mic.
+ * fix corrupted log messages in log file
+ * change installed package name length from 20 to 50
+ * print warning message for detecting rpm post script...
+ * display all rpm debug messages in debug mode
+ * display filesystem size of each images
+ * add SIGTERM handler for exit gracefully
+ * change tpk install error message format
+ * print package name, before install
+ * Modify the arguments that use cpio to generate image.
+ * Solve mic hang issue, add timeout to show failure.
+ * Solve issue:mic has error when env no_proxy is 165.xx.xxx...
+ * Change the order of generating image by cpio.
+
+* Fri Apr 28 2017 Yuhuan Yang <yuhuan.yang@samsung.com> - 0.27.5
+ * Solve image not clean after created, use e2fsck to clean image, relevant issue is NJTS-179 in JIRA.
+
* Wed Apr 5 2017 SoonKyu Park <sk7.park@samsung.com> - 0.27.4
* Fixup changelog that causes errors
* Merge add mipsel register on binfmt_misc && Add support of qemu-mipsel patch
diff --git a/packaging/mic.spec b/packaging/mic.spec
index d78e67b..fdbe655 100644..100755
--- a/packaging/mic.spec
+++ b/packaging/mic.spec
@@ -9,7 +9,7 @@
Name: mic
Summary: Image Creator for Linux Distributions
-Version: 0.27.4
+Version: 0.28.6
Release: 0
Group: Development/Tools
License: GPLv2
diff --git a/plugins/backend/zypppkgmgr.py b/plugins/backend/zypppkgmgr.py
index 9358cbe..77b942e 100644
--- a/plugins/backend/zypppkgmgr.py
+++ b/plugins/backend/zypppkgmgr.py
@@ -19,6 +19,7 @@ import os
import shutil
import urlparse
import rpm
+import glob
import zypp
if not hasattr(zypp, 'PoolQuery') or \
@@ -33,7 +34,7 @@ from mic.utils import misc, rpmmisc, runner, fs_related
from mic.utils.grabber import myurlgrab, TextProgress
from mic.utils.proxy import get_proxy_for
from mic.utils.errors import CreatorError, RepoError, RpmError
-from mic.imager.baseimager import BaseImageCreator
+from mic.conf import configmgr
class RepositoryStub:
def __init__(self):
@@ -463,10 +464,30 @@ class Zypp(BackendPlugin):
def checkPackage(self, pkg):
self.check_pkgs.append(pkg)
+ def _get_local_packages(self):
+ """Return a list of rpm path to be local installed.
+ This is the hook where subclasses may specify a set of rpms which
+ it requires to be installed locally.
+ This returns an empty list by default.
+ Note, subclasses should usually chain up to the base class
+ implementation of this hook.
+ """
+ cropts = configmgr.create
+ if cropts['local_pkgs_path']:
+ if os.path.isdir(cropts['local_pkgs_path']):
+ return glob.glob(
+ os.path.join(cropts['local_pkgs_path'], '*.rpm'))
+ elif os.path.splitext(cropts['local_pkgs_path'])[-1] == '.rpm':
+ return [cropts['local_pkgs_path']]
+ return []
+ def __localinst_packages(self):
+ for rpm_path in self._get_local_packages():
+ self.installLocal(rpm_path)
def runInstall(self, checksize = 0):
os.environ["HOME"] = "/"
os.environ["LD_PRELOAD"] = ""
self.buildTransaction()
+ self.__localinst_packages()
todo = zypp.GetResolvablesToInsDel(self.Z.pool())
installed_pkgs = todo._toInstall
diff --git a/plugins/imager/fs_plugin.py b/plugins/imager/fs_plugin.py
index d74530f..c639211 100644..100755
--- a/plugins/imager/fs_plugin.py
+++ b/plugins/imager/fs_plugin.py
@@ -15,8 +15,9 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+import subprocess
from mic import chroot, msger, rt_util
-from mic.utils import misc, errors, fs_related
+from mic.utils import misc, errors, fs_related, runner
from mic.imager import fs
from mic.conf import configmgr
from mic.plugin import pluginmgr
@@ -92,10 +93,10 @@ class FsPlugin(ImagerPlugin):
creator.check_depend_tools()
creator.mount(None, creatoropts["cachedir"])
creator.install()
+ creator.tpkinstall()
#Download the source packages ###private options
if args.include_src:
installed_pkgs = creator.get_installed_packages()
- msger.info('--------------------------------------------------')
msger.info('Generating the image with source rpms included ...')
if not misc.SrcpkgsDownload(installed_pkgs, creatoropts["repomd"],
creator._instroot, creatoropts["cachedir"]):
@@ -115,6 +116,15 @@ class FsPlugin(ImagerPlugin):
finally:
creator.cleanup()
+ #Run script of --run_script after image created
+ if creatoropts['run_script']:
+ cmd = creatoropts['run_script']
+ try:
+ runner.show(cmd)
+ except OSError,err:
+ msger.warning(str(err))
+
+
msger.info("Finished.")
return 0
diff --git a/plugins/imager/loop_plugin.py b/plugins/imager/loop_plugin.py
index 1830230..0b94f0e 100644..100755
--- a/plugins/imager/loop_plugin.py
+++ b/plugins/imager/loop_plugin.py
@@ -16,11 +16,12 @@
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import os
+import subprocess
import shutil
import tempfile
from mic import chroot, msger, rt_util
-from mic.utils import misc, fs_related, errors
+from mic.utils import misc, fs_related, errors, runner
from mic.conf import configmgr
from mic.plugin import pluginmgr
from mic.imager.loop import LoopImageCreator, load_mountpoints
@@ -100,9 +101,12 @@ class LoopPlugin(ImagerPlugin):
creator.check_depend_tools()
creator.mount(None, creatoropts["cachedir"])
creator.install()
+ creator.tpkinstall()
creator.configure(creatoropts["repomd"])
creator.copy_kernel()
+ creator.create_cpio_image()
creator.unmount()
+ creator.copy_cpio_image()
creator.package(creatoropts["destdir"])
creator.create_manifest()
@@ -117,6 +121,14 @@ class LoopPlugin(ImagerPlugin):
finally:
creator.cleanup()
+ #Run script of --run_script after image created
+ if creatoropts['run_script']:
+ cmd = creatoropts['run_script']
+ try:
+ runner.show(cmd)
+ except OSError,err:
+ msger.warning(str(err))
+
msger.info("Finished.")
return 0
diff --git a/plugins/imager/qcow_plugin.py b/plugins/imager/qcow_plugin.py
index 8acf572..d6758c5 100644..100755
--- a/plugins/imager/qcow_plugin.py
+++ b/plugins/imager/qcow_plugin.py
@@ -15,6 +15,7 @@
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import os
+import subprocess
import shutil
from mic import msger, rt_util
@@ -131,9 +132,12 @@ class QcowPlugin(ImagerPlugin):
creator.check_depend_tools()
creator.mount(None, creatoropts["cachedir"])
creator.install()
+ creator.tpkinstall()
creator.configure(creatoropts["repomd"])
creator.copy_kernel()
+ creator.create_cpio_image()
creator.unmount()
+ creator.copy_cpio_image()
creator.package(creatoropts["destdir"])
creator.create_manifest()
@@ -148,6 +152,15 @@ class QcowPlugin(ImagerPlugin):
finally:
creator.cleanup()
+ #Run script of --run_script after image created
+ if creatoropts['run_script']:
+ cmd = creatoropts['run_script']
+ try:
+ runner.show(cmd)
+ except OSError,err:
+ msger.warning(str(err))
+
+
msger.info("Finished.")
return 0
diff --git a/plugins/imager/raw_plugin.py b/plugins/imager/raw_plugin.py
index 09a9714..e954b7b 100755
--- a/plugins/imager/raw_plugin.py
+++ b/plugins/imager/raw_plugin.py
@@ -16,6 +16,7 @@
# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import os
+import subprocess
import shutil
import re
import tempfile
@@ -98,6 +99,7 @@ class RawPlugin(ImagerPlugin):
creator.check_depend_tools()
creator.mount(None, creatoropts["cachedir"])
creator.install()
+ creator.tpkinstall()
creator.configure(creatoropts["repomd"])
creator.copy_kernel()
creator.unmount()
@@ -113,6 +115,15 @@ class RawPlugin(ImagerPlugin):
finally:
creator.cleanup()
+ #Run script of --run_script after image created
+ if creatoropts['run_script']:
+ cmd = creatoropts['run_script']
+ try:
+ runner.show(cmd)
+ except OSError,err:
+ msger.warning(str(err))
+
+
msger.info("Finished.")
return 0
diff --git a/tests/test_configmgr.py b/tests/test_configmgr.py
index 2f15f10..08c3744 100644
--- a/tests/test_configmgr.py
+++ b/tests/test_configmgr.py
@@ -64,7 +64,8 @@ class ConfigMgrTest(unittest.TestCase):
'primary': '%s/test/primary.sqlite' % cachedir,
'proxies': None,
'repokey': None,
- 'repomd': '%s/test/repomd.xml' % cachedir}]
+ 'repomd': '%s/test/repomd.xml' % cachedir,
+ 'priority': None}]
self.configmgr._ksconf = KSCONF
self.assertTrue(isinstance(self.configmgr.create['ks'], KickstartParser))
#self.assertEqual(self.configmgr.create['name'], 'test')
diff --git a/tools/mic b/tools/mic
index 26df153..6cbfb45 100755
--- a/tools/mic
+++ b/tools/mic
@@ -27,6 +27,7 @@
'create, chroot, convert' and also some parameters for command 'mic'.
"""
import os
+import signal
import sys
import errno
@@ -54,7 +55,7 @@ def chroot_parser(parser):
help = "command which will be executed in chroot environment")
parser.set_defaults(alias="ch")
return parser
-
+
@subparser
def create_parser(parser):
"""create an image
@@ -64,15 +65,15 @@ def create_parser(parser):
"""
parent_parser = ArgumentParser(add_help=False)
- parent_parser.add_argument('ksfile', help='Path of ksfile');
+ parent_parser.add_argument('ksfile', help='Path of ksfile')
parent_parser.add_argument('--logfile', dest='logfile', default=None,
help='Path of logfile')
parent_parser.add_argument('-c', '--config', dest='config', default=None,
- help='Specify config file for mic')
+ help='Specify config file for mic')
parent_parser.add_argument('-k', '--cachedir', action='store',
dest='cachedir', default=None,
help='Cache directory to store the downloaded')
- parent_parser.add_argument('-o', '--outdir', action='store', dest='outdir',
+ parent_parser.add_argument('-o', '--outdir', action='store', dest='outdir',
default=None, help='Output directory')
parent_parser.add_argument('-A', '--arch', dest='arch', default=None,
help='Specify repo architecture')
@@ -123,7 +124,12 @@ def create_parser(parser):
dest='strict_mode', default=False,
help='Abort creation of image, if there are some errors'
' during rpm installation. ')
-
+ parent_parser.add_argument('--use-mic-in-bootstrap', action='store_true',
+ dest='use_mic_in_bootstrap', default=False,
+ help='This option works in bootstrap runtime mode,'
+ ' Use mic in bootstrap to create image.'
+ ' By default, copy host mic to bootstrap and use it.')
+
parent_parser.add_argument('-d', '--debug', action='store_true',
help='debug output')
parent_parser.add_argument('-v', '--verbose', action='store_true',
@@ -131,6 +137,11 @@ def create_parser(parser):
parent_parser.add_argument('-i', '--interactive', action='store_true',
dest='interactive', default=True,
help='interactive output')
+ parent_parser.add_argument('--run_script', action='store', dest='run_script',
+ default=None, help='Run script on local PC after image created')
+ parent_parser.add_argument('--tpk_install', action='store', dest='tpk_install',
+ default=None, help='Copy tpk file to /usr/apps/.preload-tpk')
+ parent_parser.add_argument('--rpm-debug', action='store_true', dest='rpm_debug', help='Set debug mode for rpm install')
parser.set_defaults(alias="cr")
@@ -195,6 +206,12 @@ def main(argv):
return True
return False
+ def sigterm_handler(signal, frame):
+ raise errors.Abort('\nSIGTERM catched, program aborted.')
+
+ # Add SIGTERM handler for exit gracefully
+ signal.signal(signal.SIGTERM, sigterm_handler)
+
# Create top level parser
epilog = "Try 'mic SUBCOMMAND --help' for help on a specific subcommand."
description = "mic - the Image Creation tool"
@@ -262,7 +279,7 @@ def main(argv):
if args.debug:
try:
import rpm
- rpm.setVerbosity(rpm.RPMLOG_NOTICE)
+ rpm.setVerbosity(rpm.RPMLOG_DEBUG)
except ImportError:
pass