3 \mep @sUdZddlZddlZddlZddlmZddlmZmZddl m Z ddl m Z ddl mZmZddlmZdd lmZejd Zejd Zejd Zejd ZejdZejdZejdZddiZejeZdZ ddde egeedgddgdZ!e!ee!Ze"e e e#ddddZ$ddZ%d d!Z&dTd"d#Z'dUd%d&Z(d'd(Z)dVd)d*Z*d+d,Z+d-d.Z,dWd0d1Z-d2d3Z.d4d5Z/d6d7Z0d8d9Z1d:d;Z2dd?Z4d@dAZ5dBdCZ6dDdEZ7dFdGZ8dHdIZ9dJdKZ:dLdMZ;dNdOZdS)Xz1Disk Setup: Configure partitions and filesystems.N)dedent)subputil)Cloud)Config) MetaSchema get_meta_doc) ALL_DISTROS) PER_INSTANCEZsfdiskZsgdiskZlsblkZblkidZblockdevZ partprobeZwipefsZLANGCaiThis module is able to configure simple partition tables and filesystems. .. note:: for more detail about configuration options for disk setup, see the disk setup example .. note:: if a swap partition is being created via ``disk_setup`` then a ``fs_entry`` entry is also needed in order for mkswap to be run, otherwise when swap activation is later attempted it will fail. For convenience, aliases can be specified for disks using the ``device_aliases`` config key, which takes a dictionary of alias: path mappings. There are automatic aliases for ``swap`` and ``ephemeral``, where ``swap`` will always refer to the active swap partition and ``ephemeral`` will refer to the block device of the ephemeral image. Disk partitioning is done using the ``disk_setup`` directive. This config directive accepts a dictionary where each key is either a path to a block device or an alias specified in ``device_aliases``, and each value is the configuration options for the device. File system configuration is done using the ``fs_setup`` directive. This config directive accepts a list of filesystem configs. Z cc_disk_setupz Disk Setupz$Configure partitions and filesystemsan device_aliases: my_alias: /dev/sdb swap_disk: /dev/sdc disk_setup: my_alias: table_type: gpt layout: [50, 50] overwrite: true swap_disk: table_type: gpt layout: [[100, 82]] overwrite: true /dev/sdd: table_type: mbr layout: true overwrite: true fs_setup: - label: fs1 filesystem: ext4 device: my_alias.1 cmd: mkfs -t %(filesystem)s -L %(label)s %(device)s - label: fs2 device: my_alias.2 filesystem: ext4 - label: swap device: swap_disk.1 filesystem: swap - label: fs3 device: /dev/sdd1 filesystem: ext4 mounts: - ["my_alias.1", "/mnt1"] - ["my_alias.2", "/mnt2"] - ["swap_disk.1", "none", "swap", "sw", "0", "0"] - ["/dev/sdd1", "/mnt3"] disk_setupfs_setup)idnametitle descriptionZdistrosZ frequencyZexamplesZactivate_by_schema_keys)rcfgcloudargsreturnc s|jdifdd}|jd}t|trt||tjdt|x|jD]~\}}t|tsrtjd|qRy*tjdt j tjd|t ||fd WqRt k r}zt j td |WYd d }~XqRXqRW|jd } t| trtjd t| t| |x| D]}t|ts*tjd|q y2tjd|jd} t j tjd| t|fd Wn4t k r}zt j td|WYd d }~XnXq Wd S)z[ See doc/examples/cloud-config-disk-setup.txt for documentation on the format. device_aliasescsj|}j|p|p|S)N)getZdevice_name_to_device)Zcandr)rr#/usr/lib/python3.6/cc_disk_setup.pyalias_to_deviceys zhandle..alias_to_devicer zPartitioning disks: %szInvalid disk definition for %sz!Creating new partition table/diskzCreating partition on %s)Zlogfuncmsgfuncrz Failed partitioning operation %sNr zsetting up filesystems: %sz"Invalid file system definition: %szCreating new filesystem.devicezCreating fs for %sz%Failed during filesystem operation %s)r isinstancedictupdate_disk_setup_devicesLOGdebugstritemswarningrZlog_timemkpart Exceptionlogexclistupdate_fs_setup_devicesmkfs) rrrrrr disk definitioner rr)rrrhandlersJ       &        r/cCsxt|D]t}||}|dks ||kr(q ||krDtjd||||=||||<t||trj|||d<||=tjd||q WdS)Nz0Replacing %s in disk_setup for translation of %s _orignamez,updated disk_setup device entry '%s' to '%s')r)r!inforrr")r tformerorignameZ transformedrrrr s$  r cCsx|D]}t|ts"tjd|q|jd}|dkr6qtj|\}}||}|dk rx|}tjd|||||d<||d<|rd|krtjd||||d|d<||d<qWdS)Nz"entry in disk_setup not a dict: %srz%s is mapped to disk=%s part=%sr0 partitionzKPartition '%s' from dotted device name '%s' overrides 'partition' key in %sZ _partition)rrr!r%rrZexpand_dotted_devnamer")r r2r-r3ZdevpartZtformedrrrr*s0      r*ccsDtj|}|r||d}x$dd|DD]\}}||fVq*WdS)zd Returns the key/value pairs of output sent as string like: FOO='BAR' HOME='127.0.0.1' NcSsg|]}|jdqS)=)split).0xrrr sz"value_splitter..)shlexr7)valuesstartZ_valueskeyvaluerrrvalue_splitters   r@Fc cstddd|g}|r|jdd}ytj|\}}Wn4tk rf}ztd||f|WYdd}~XnXdd|jjD}xB|D]:}ddddd }x t|D]\} } | || j<qW|VqWdS) a Enumerate the elements of a child device. Parameters: device: the kernel device name nodeps : don't enumerate children devices Return a dict describing the disk: type: the entry type, i.e disk or part fstype: the filesystem type, if it exists label: file system label, if it exists name: the device name, i.e. sda z--pairsz--outputzNAME,TYPE,FSTYPE,LABELz--nodepsNz"Failed during disk check for %s %scSs g|]}t|jdkr|qS)r)lenr7)r8r9rrrr:sz"enumerate_disk..)rtypefstypelabel) LSBLK_CMDappendrr' RuntimeErrorstrip splitlinesr@lower) rnodepsZ lsblk_cmdr1_errr.partsr5dr>r?rrrenumerate_disks.   rOcCs.x(t|ddD]}d|kr|djSqWdS)z@ Return the device type of the device by calling lsblk. T)rKrBN)rOrJ)rrNrrr device_type&srPc CsXd}y t|}Wn tk r0tjd|dSX|rB|dkrBdS| rT|dkrTdSdS)z0 Check if the device is a valid device. zQuery against device %s failedFr5Tr,)rPr'r!r%)rr4Zd_typerrris_device_valid1s   rRc Csd \}}}}tdd|g}ytj|ddgd\}}Wn4tk rf}ztd||f|WYdd}~XnX|rt|jdkrxLt|dd D]<\}} |jd kr| }q|jd kr| }q|jd kr| }qW|||fS)z Check if the device has a filesystem on it Output of blkid is generally something like: /dev/sda: LABEL="Backup500G" UUID="..." TYPE="ext4" Return values are device, label, type, uuid Nz-cz /dev/nullr)rcsz"Failed during disk check for %s %s)r=rDrBuuid)NNNN) BLKID_CMDrr'rGrArIr@rJ) routrDfs_typerVZ blkid_cmdrLr.r>r?rrrcheck_fsCs$      rZcCst|\}}}|S)z7 Returns true if the device has a file system. )rZ)r_rYrrr is_filesystemcsr\TcCs|dkr d}|sddg}d}xt|D]}|d|krN|dkrNd|ddfS|d|kr|rj|d |ksp| rd|dd fS|d |kr&|d dks|drd }|d dkrq&|ds&d|ddfSq&W|s|dfStjd d S)a Find a device that is either matches the spec, or the first The return is value is (, ) where the device is the device to use and the bool is whether the device matches the fs_type and label. Note: This works with GPT partition tables! NrQr,r5FrCz/dev/%srrDTrBz5Failed to find device during available device search.)NF)rOr!r%)rrYrDZ valid_targets label_match replace_fsZraw_device_usedrNrrrfind_device_nodeks,    r_cCs2ttt|dkrdSt|\}}}|r.dSdS)z Check if the device is currently used. Returns true if the device has either a file system or a partition entry is no filesystem found on the disk. rUTF)rAr)rOrZ)rr[ check_fstyperrr is_disk_useds racCsry,tjtd|g\}}tjtd|g\}}Wn4tk r`}ztd||f|WYdd}~XnXt|t|S)Nz --getsize64z--getsszFailed to get %s size %s)r BLKDEV_CMDr'rGint)rZ size_in_bytesr[Z sector_sizer.rrr get_hdd_sizes $rdc Cst|td|g}ytj|d|d\}}Wn4tk r`}ztd||f|WYdd}~XnXg}x|jD]}|j}t|dkrqp||dkrp|d jdkrqpd} x@t t dt|d d D]&} || j r|| d kr|| } PqW|j | qpW|S)z Returns true if the partition layout matches the one on the disk Layout should be a list of values. At this time, this only verifies that the number of partitions and their labels is correct. z-lz%s )dataz(Error running partition command on %s %sNrrUextendedemptyT)reverse/)rfrg) read_parttbl SFDISK_CMDrr'rGrIr7rArJsortedrangeisdigitrF) rlayoutprt_cmdrXrLr. found_layoutline_lineZ type_labelr9rrrcheck_partition_mbr_layouts.    ruc Cstd|g}ytj|td\}}Wn4tk rT}ztd||f|WYdd}~XnXt|j}x|D]}|jjdrhPqhWdd|D}g} x8|D]0} t | dkr| j dr| d d } | j | qW| S) Nz-p)Z update_envz(Error running partition command on %s %sNumbercSsg|]}|jjdqS))rHr7)r8rsrrrr:sz.check_partition_gpt_layout..Z00rrS) SGDISK_CMDr LANG_C_ENVr'rGiterrIrH startswithrAendswithrF) rrprqrXrLr.Z out_linesrsZcodesZcleanedcoderrrcheck_partition_gpt_layouts$      rcCsd|krt||}nd|kr(t||}ntdtjd||||t|trd|r`t|dkr`dSdSt|t|krdd |D}tjd ||x2t||D]$\}}|d k rt |t |krdSqWdSdS) z See if the partition lay out matches. This is future a future proofing function. In order to add support for other disk layout schemes, add a function called check_partition_%s_layout gptmbrzUnable to determine table typez6called check_partition_%s_layout(%s, %s), returned: %srUTFcSs*g|]"}t|ttfr"t|dndqS)rUN)rtupler)r#)r8r9rrrr:2sz*check_partition_layout..zLayout types=%s. Found types=%sN) rrurGr!r"rboolrAzipr#) table_typerrprrZ layout_typesZitypeZftyperrrcheck_partition_layouts0    rc Cst|t rt|trdSt|dkr0t|tssz             %5& 2    2 ').9G