diff --git a/kiwi/defaults.py b/kiwi/defaults.py index 56a5531e7b3..067f71e4d5d 100644 --- a/kiwi/defaults.py +++ b/kiwi/defaults.py @@ -1341,7 +1341,8 @@ def get_disk_format_types(): """ return [ 'gce', 'qcow2', 'vmdk', 'ova', 'vmx', 'vhd', 'vhdx', - 'vhdfixed', 'vdi', 'vagrant.libvirt.box', 'vagrant.virtualbox.box' + 'vhdfixed', 'vdi', 'vagrant.libvirt.box', 'vagrant.virtualbox.box', + 'vagrant.vmware_desktop.box' ] @staticmethod diff --git a/kiwi/schema/kiwi.rnc b/kiwi/schema/kiwi.rnc index e045d2a01e7..e998854ec22 100644 --- a/kiwi/schema/kiwi.rnc +++ b/kiwi/schema/kiwi.rnc @@ -2565,7 +2565,8 @@ div { "lsilogic" | "lsisas1068" | "legacyESX" | - "pvscsi" + "pvscsi" | + "sata" } k.vmdisk.id.attribute = ## The disk ID / device for the VM disk (vmdk only) @@ -3539,7 +3540,7 @@ div { ] k.vagrantconfig.provider.attribute = ## The vagrant provider for this box - attribute provider { "libvirt" | "virtualbox" } + attribute provider { "libvirt" | "virtualbox" | "vmware" } k.vagrantconfig.virtualbox_guest_additions_present.attribute = ## Guest additions are present in this box attribute virtualbox_guest_additions_present { xsd:boolean } diff --git a/kiwi/schema/kiwi.rng b/kiwi/schema/kiwi.rng index 654d70bc294..98e9ea777f4 100644 --- a/kiwi/schema/kiwi.rng +++ b/kiwi/schema/kiwi.rng @@ -3864,6 +3864,7 @@ by the VM (ova only) lsisas1068 legacyESX pvscsi + sata @@ -5316,6 +5317,7 @@ and setup the system disk. libvirt virtualbox + vmware diff --git a/kiwi/storage/subformat/__init__.py b/kiwi/storage/subformat/__init__.py index 75ca857c17b..eaaabc9aeb6 100644 --- a/kiwi/storage/subformat/__init__.py +++ b/kiwi/storage/subformat/__init__.py @@ -49,6 +49,7 @@ def new( 'ova': 'Ova', 'vagrant_libvirt': 'VagrantLibVirt', 'vagrant_virtualbox': 'VagrantVirtualBox', + 'vagrant_vmware': 'VagrantVMware', 'base': 'Base' } module_namespace: Optional[str] = None diff --git a/kiwi/storage/subformat/template/vmware_settings.py b/kiwi/storage/subformat/template/vmware_settings.py index 82b90c6aa29..07d0850159b 100644 --- a/kiwi/storage/subformat/template/vmware_settings.py +++ b/kiwi/storage/subformat/template/vmware_settings.py @@ -37,12 +37,25 @@ def __init__(self): guestOS = "${guest_os}" ''').strip() + self.cr + self.pcie_bridge = dedent(''' + pciBridge0.functions = "8" + pciBridge0.pciSlotNumber = "17" + pciBridge0.present = "true" + pciBridge0.virtualDev = "pcieRootPort" + ''').strip() + self.cr + self.ide_disk = dedent(''' ide${disk_id}:0.present = "true" ide${disk_id}:0.fileName= "${vmdk_file}" ide${disk_id}:0.redo = "" ''').strip() + self.cr + self.sata_disk = dedent(''' + sata${disk_id}.present = "true" + sata${disk_id}:0.present = "true" + sata${disk_id}:0.fileName = "${vmdk_file}" + ''').strip() + self.cr + self.scsi_disk = dedent(''' scsi${disk_id}.present = "true" scsi${disk_id}.sharedBus = "none" @@ -130,6 +143,7 @@ def get_template( """ template_data = self.header template_data += self.defaults + template_data += self.pcie_bridge if memory_setup: template_data += self.memory @@ -137,10 +151,13 @@ def get_template( if cpu_setup: template_data += self.number_of_cpus - if disk_controller == 'ide': - template_data += self.ide_disk - else: - template_data += self.scsi_disk + controller_funcs = { + 'ide': self.ide_disk, + 'sata': self.sata_disk, + } + + # All except ide and sata ontrollers are a form of scsi + template_data += controller_funcs.get(disk_controller, self.scsi_disk) if network_setup: for nic_id, nic_setup in list(network_setup.items()): diff --git a/kiwi/storage/subformat/vagrant_base.py b/kiwi/storage/subformat/vagrant_base.py index 3f15996ec57..d745326627d 100644 --- a/kiwi/storage/subformat/vagrant_base.py +++ b/kiwi/storage/subformat/vagrant_base.py @@ -18,6 +18,7 @@ import json import os.path +from pathlib import PurePath from kiwi.utils.temporary import Temporary from typing import ( Dict, Optional, List @@ -33,6 +34,8 @@ KiwiFormatSetupError ) +VagrantConfigDict = Dict['str', xml_parse.vagrantconfig] + class DiskFormatVagrantBase(DiskFormatBase): """ @@ -74,7 +77,8 @@ class DiskFormatVagrantBase(DiskFormatBase): * :meth:`get_additional_vagrant_config_settings` """ - def post_init(self, custom_args: Dict['str', xml_parse.vagrantconfig]): + + def post_init(self, custom_args: VagrantConfigDict): """ vagrant disk format post initialization method @@ -96,10 +100,10 @@ def post_init(self, custom_args: Dict['str', xml_parse.vagrantconfig]): raise KiwiFormatSetupError( 'no vagrantconfig provided' ) - self.vagrantconfig = custom_args['vagrantconfig'] - self.vagrant_post_init() + self.vagrantconfig = custom_args.pop('vagrantconfig') + self.vagrant_post_init(custom_args) - def vagrant_post_init(self) -> None: + def vagrant_post_init(self, custom_args: VagrantConfigDict = None) -> None: """ Vagrant provider specific post initialization method @@ -221,6 +225,18 @@ def get_additional_vagrant_config_settings(self) -> str: """ return '' + def _stage_box_file(self, temp_dir: str, format: str) -> str: + file_path = self.get_target_file_path_for_format(format) + file_name = PurePath(file_path).name + box_file = os.sep.join([temp_dir, file_name]) + Command.run( + [ + 'mv', file_path, + box_file + ] + ) + return box_file + def _create_box_metadata(self): metadata = self.get_additional_metadata() or {} metadata['provider'] = self.provider diff --git a/kiwi/storage/subformat/vagrant_libvirt.py b/kiwi/storage/subformat/vagrant_libvirt.py index 53433e43acc..aa4eaec85b8 100644 --- a/kiwi/storage/subformat/vagrant_libvirt.py +++ b/kiwi/storage/subformat/vagrant_libvirt.py @@ -22,7 +22,9 @@ ) # project -from kiwi.storage.subformat.vagrant_base import DiskFormatVagrantBase +from kiwi.storage.subformat.vagrant_base import ( + DiskFormatVagrantBase, VagrantConfigDict +) from kiwi.storage.subformat.qcow2 import DiskFormatQcow2 from kiwi.command import Command @@ -31,7 +33,7 @@ class DiskFormatVagrantLibVirt(DiskFormatVagrantBase): """ **Create a vagrant box for the libvirt provider** """ - def vagrant_post_init(self) -> None: + def vagrant_post_init(self, custom_args: VagrantConfigDict = None) -> None: self.image_format = 'vagrant.libvirt.box' self.provider = 'libvirt' diff --git a/kiwi/storage/subformat/vagrant_virtualbox.py b/kiwi/storage/subformat/vagrant_virtualbox.py index acf38f14bdb..56e804995aa 100644 --- a/kiwi/storage/subformat/vagrant_virtualbox.py +++ b/kiwi/storage/subformat/vagrant_virtualbox.py @@ -24,7 +24,9 @@ from kiwi.storage.subformat.template.virtualbox_ovf import ( VirtualboxOvfTemplate ) -from kiwi.storage.subformat.vagrant_base import DiskFormatVagrantBase +from kiwi.storage.subformat.vagrant_base import ( + DiskFormatVagrantBase, VagrantConfigDict +) from kiwi.storage.subformat.vmdk import DiskFormatVmdk from kiwi.command import Command @@ -34,7 +36,7 @@ class DiskFormatVagrantVirtualBox(DiskFormatVagrantBase): **Create a vagrant box for the virtualbox provider** """ - def vagrant_post_init(self) -> None: + def vagrant_post_init(self, custom_args: VagrantConfigDict = None) -> None: self.provider = 'virtualbox' self.image_format = 'vagrant.virtualbox.box' diff --git a/kiwi/storage/subformat/vagrant_vmware.py b/kiwi/storage/subformat/vagrant_vmware.py new file mode 100644 index 00000000000..82f25f2df5b --- /dev/null +++ b/kiwi/storage/subformat/vagrant_vmware.py @@ -0,0 +1,99 @@ +# Copyright (c) 2019 SUSE Linux GmbH. All rights reserved. +# +# This file is part of kiwi. +# +# kiwi is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# kiwi is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kiwi. If not, see +# + +# from textwrap import dedent +from typing import ( + List, Dict +) + +# project +from kiwi.storage.subformat.vagrant_base import (DiskFormatVagrantBase, + VagrantConfigDict) +from kiwi.storage.subformat.vmdk import DiskFormatVmdk + +from kiwi.exceptions import ( + KiwiTemplateError +) + + +class DiskFormatVagrantVMware(DiskFormatVagrantBase): + """ + **Create a vagrant box for the vmware provider** + """ + + def vagrant_post_init(self, custom_args: VagrantConfigDict = None) -> None: + self.image_format = 'vagrant.vmware_desktop.box' + self.provider = 'vmware_desktop' + self.custom_args = custom_args + + def create_box_img(self, temp_image_dir: str) -> List[str]: + """ + Creates the vmdk disk image for the vmware_desktop vagrant provider + + :param str temp_image_dir: + Path to the temporary directory used to build the box image + + :return: + A list of files relevant for the vmware box to be + included in the vagrant box + + :rtype: list + """ + vmdk = DiskFormatVmdk( + self.xml_state, self.root_dir, self.target_dir, + custom_args=self.custom_args + ) + try: + vmdk.create_image_format() + box_image = self._stage_box_file(temp_image_dir, vmdk.image_format) + settings_file = self._stage_box_file(temp_image_dir, 'vmx') + except KiwiTemplateError as e: + # TODO: handle + raise e + + return [box_image, settings_file] + + def get_additional_metadata(self) -> Dict: + """ + Provide box metadata needed to create the box in vagrant + + :return: + Returns a dictionary containing the virtual image format + + :rtype: dict + """ + return { + 'format': 'vmdk' + } + + def get_additional_vagrant_config_settings(self) -> str: + """ + Returns settings for the vmware provider + + :return: + ruby code to be evaluated as string + + :rtype: str + """ + # return dedent(''' + # config.vm.synced_folder ".", "/vagrant", type: "rsync" + # config.vm.provider :libvirt do |libvirt| + # libvirt.driver = "kvm" + # end + # ''').strip() + return '' diff --git a/kiwi/storage/subformat/vmdk.py b/kiwi/storage/subformat/vmdk.py index ebd20ca3b03..7978706e587 100644 --- a/kiwi/storage/subformat/vmdk.py +++ b/kiwi/storage/subformat/vmdk.py @@ -146,7 +146,7 @@ def _create_vmware_settings_file(self): if disk_setup: disk_controller = disk_setup.get_controller() or disk_controller disk_id = disk_setup.get_id() - if not disk_controller == 'ide': + if disk_controller not in ['ide', 'sata']: template_record['scsi_controller_name'] = disk_controller if disk_id: template_record['disk_id'] = disk_id