Documentation ¶
Index ¶
Constants ¶
View Source
const (
DefaultGetTimeout = 30 * time.Minute
)
View Source
const QemuCMD = "qemu-img"
Variables ¶
View Source
var Cmd = &cobra.Command{ Use: "qcow2ova", Short: "Convert the qcow2 image to ova format", Long: `Convert the qcow2 image to ova format Examples: # Downloads the coreos image from remote site and converts into ova type with name rhcos-461.ova.gz pvsadm image qcow2ova --image-name rhcos-461 --image-dist coreos --image-url https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/4.6/4.6.1/rhcos-4.6.1-ppc64le-openstack.ppc64le.qcow2.gz # Converts the CentOS image from the local filesystem with size 50GB pvsadm image qcow2ova --image-name centos-82 --image-dist centos --image-size 50 --image-url /root/CentOS-8-GenericCloud-8.2.2004-20200611.2.ppc64le.qcow2 # Converts the RHEL image from local filesystem pvsadm image qcow2ova --image-name rhel-82-29oct --image-dist rhel --rhn-user joesmith@example.com --rhn-password someValidPassword --image-url ./rhel-8.2-update-2-ppc64le-kvm.qcow2 # Converts the CentOS image from the local filesystem with OS password set pvsadm image qcow2ova --image-name centos-82 --image-dist centos --os-password s0meC0mplexPassword --image-url /root/CentOS-8-GenericCloud-8.2.2004-20200611.2.ppc64le.qcow2 # Converts the CentOS image from the local filesystem without OS password pvsadm image qcow2ova --image-name centos-82 --image-dist centos --image-url /root/CentOS-8-GenericCloud-8.2.2004-20200611.2.ppc64le.qcow2 --skip-os-password # Customize the image preparation script for RHEL/CentOS distro, e.g: add additional yum repository or packages, change name servers etc. # Step 1 - Dump the default image preparation template pvsadm image qcow2ova --prep-template-default > image-prep.template # Step 2 - Make the necessary changes to the above generated template file(bash shell script) - image-prep.template # Step 3 - Run the qcow2ova with the modified image preparation template pvsadm image qcow2ova --image-name centos-82 --image-dist centos --image-url /root/CentOS-8-GenericCloud-8.2.2004-20200611.2.ppc64le.qcow2 --prep-template image-prep.template # Customize the cloud config and Convert image with user defined cloud config template. # Step 1 - Dump the default cloud config template pvsadm image qcow2ova --cloud-config-default > user_cloud.config # Step 2 - Make the necessary changes to the above generated template file - user_cloud.config # Step 3 - Run the qcow2ova with the modified cloud config template pvsadm image qcow2ova --image-name centos-82 --image-dist centos --image-url /root/CentOS-8-GenericCloud-8.2.2004-20200611.2.ppc64le.qcow2 --cloud-config user_cloud.config Qcow2 images location: # CentOS 8: https://cloud.centos.org/centos/8-stream/ppc64le/images/ # CentOS 9: https://cloud.centos.org/centos/9-stream/ppc64le/images/ # Old Centos: https://cloud.centos.org/centos/8/ppc64le/images/ # RHEL image: https://access.redhat.com/downloads/content/279/ver=/rhel---8/8.3/ppc64le/product-software # RHCOS images: https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/ `, PreRunE: func(cmd *cobra.Command, args []string) error { opt := pkg.ImageCMDOptions if opt.PrepTemplateDefault { fmt.Println(prep.SetupTemplate) os.Exit(0) } if opt.CloudConfigDefault { fmt.Println(prep.CloudConfig) os.Exit(0) } if opt.PrepTemplate != "" { if strings.ToLower(opt.ImageDist) == "coreos" { return fmt.Errorf("--prep-template option is not supported for coreos distro") } else { klog.V(2).Info("Overriding with the user defined image preparation template.") content, err := os.ReadFile(opt.PrepTemplate) if err != nil { return err } prep.SetupTemplate = string(content) } } if opt.CloudConfig != "" { klog.V(2).Info("Overriding with the user defined cloud config.") content, err := os.ReadFile(opt.CloudConfig) if err != nil { return err } prep.CloudConfig = string(content) } if !utils.Contains([]string{"rhel", "centos", "coreos"}, strings.ToLower(opt.ImageDist)) { klog.Errorln("--image-dist is a mandatory flag and one of these [rhel, centos, coreos]") os.Exit(1) } if opt.ImageDist == "rhel" && (opt.RHNUser == "" || opt.RHNPassword == "") { var err error klog.Warning("rhn-user and rhn-password options are mandatory when image-dist is rhel, please enter the details") validate := func(input string) error { if len(strings.TrimSpace(input)) == 0 { return fmt.Errorf("input can't be empty string") } return nil } if opt.RHNUser == "" { prompt := promptui.Prompt{ Label: "Enter the RHN Username", Validate: validate, } opt.RHNUser, err = prompt.Run() if err != nil { return err } } if opt.RHNPassword == "" { prompt := promptui.Prompt{ Label: "Enter the RHN Password", Mask: '•', Validate: validate, } opt.RHNPassword, err = prompt.Run() if err != nil { return err } } } if opt.ImageDist != "coreos" && opt.OSPassword == "" && !opt.OSPasswordSkip { var err error opt.OSPassword, err = GeneratePassword(12) if err != nil { return err } passwordfile, err := os.Create("password.txt") if err != nil { klog.Errorf("failed to create password file, err: %v", err) return err } defer passwordfile.Close() passwordfile.WriteString(fmt.Sprintf("Root Password : %s", opt.OSPassword)) cwd, err := os.Getwd() if err != nil { return err } klog.Infof("Autogenerated OS root password is updated in %s", filepath.Join(cwd, passwordfile.Name())) } return validate.Validate() }, RunE: func(cmd *cobra.Command, args []string) error { opt := pkg.ImageCMDOptions tmpDir, err := os.MkdirTemp(opt.TempDir, "qcow2ova") if err != nil { return fmt.Errorf("failed to create a temprory directory: %v", err) } defer os.RemoveAll(tmpDir) mnt := filepath.Join(tmpDir, "mnt") err = os.Mkdir(mnt, 0755) if err != nil { return err } cwd, err := os.Getwd() if err != nil { return err } c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) go func() { <-c klog.Info("Received an interrupt, exiting.") prep.ExitChroot() prep.UmountHostPartitions(mnt) _ = prep.Umount(mnt) _ = os.RemoveAll(tmpDir) os.Exit(1) }() image, err := getImage(tmpDir, opt.ImageURL, 0) if err != nil { return fmt.Errorf("failed to download the %s into %s, error: %v", opt.ImageURL, tmpDir, err) } klog.V(1).Infof("downloaded/copied the file at: %s", image) var qcow2Img string checkGzip, err := utils.IsGzip(image) if err != nil { return fmt.Errorf("failed to detect the image filetype: %v", err) } if checkGzip { klog.V(1).Infof("Image %s is in gzip format, extracting it", image) qcow2Img = filepath.Join(tmpDir, ova.VolName+".qcow2") err = utils.GunzipIt(image, qcow2Img) if err != nil { return err } klog.V(1).Info("Extract complete") } else { qcow2Img = image } ovaImgDir := filepath.Join(tmpDir, "ova-img-dir") err = os.Mkdir(ovaImgDir, 0755) if err != nil { return err } volumeDiskName := fmt.Sprintf("%s-%s", opt.ImageName, ova.VolNameRaw) rawImg := filepath.Join(ovaImgDir, volumeDiskName) klog.Infof("Converting Qcow2(%s) image to raw(%s) format", qcow2Img, rawImg) err = qemuImgConvertQcow2Raw(qcow2Img, rawImg) if err != nil { return err } klog.Info("Conversion completed") klog.Infof("Resizing the image %s to %dG", rawImg, opt.ImageSize) err = qemuImgResize("-f", "raw", rawImg, fmt.Sprintf("%dG", opt.ImageSize)) if err != nil { return err } klog.Info("Resize completed") klog.Info("Preparing the image") err = prep.Prepare4capture(mnt, rawImg, opt.ImageDist, opt.RHNUser, opt.RHNPassword, opt.OSPassword) if err != nil { return fmt.Errorf("failed while preparing the image for %s distro, err: %v", opt.ImageDist, err) } klog.Info("Preparation completed") klog.Info("Creating an OVA bundle") ovafile := filepath.Join(tmpDir, opt.ImageName+".ova") if err := ova.CreateTarArchive(ovaImgDir, ovafile, opt.TargetDiskSize, opt.ImageDist, volumeDiskName); err != nil { return fmt.Errorf("failed to create ova bundle, err: %v", err) } klog.Infof("OVA bundle creation completed: %s", ovafile) klog.Info("Compressing an OVA file") ovaGZfile := filepath.Join(cwd, opt.ImageName+".ova.gz") err = utils.GzipIt(ovafile, ovaGZfile) if err != nil { return err } klog.Info("OVA file Compression completed") fmt.Printf("\n\nSuccessfully converted Qcow2 image to OVA format, find at %s\nOS root password: %s\n", ovaGZfile, opt.OSPassword) return nil }, }
Functions ¶
func GeneratePassword ¶
GeneratePassword generates the password of length n
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.