3 \meN @szUdZddlZddlZddlZddlZddlmZddlmZddl m Z m Z m Z ddl mZddlmZddlmZmZdd lmZd Zed Zd gZd ddeeeedgegdZeeeZdZejeZdZejeZejdeZdZ dZ!d0Z"d1Z#ej$e%Z&ddZ'ddZ(ddZ)d2d d!Z*d3d"d#Z+d4d$d%Z,e-e-dd&d'd(Z.d5d)d*Z/d+d,Z0e-eee1dd-d.d/Z2dS)6z-Mounts: Configure mount points and swap filesN) whitespace)dedent)subp type_utilsutil)Cloud)Config) MetaSchema get_meta_doc) PER_INSTANCEa This module can add or remove mountpoints from ``/etc/fstab`` as well as configure swap. The ``mounts`` config key takes a list of fstab entries to add. Each entry is specified as a list of ``[ fs_spec, fs_file, fs_vfstype, fs_mntops, fs-freq, fs_passno ]``. For more information on these options, consult the manual for ``/etc/fstab``. When specifying the ``fs_spec``, if the device name starts with one of ``xvd``, ``sd``, ``hd``, or ``vd``, the leading ``/dev`` may be omitted. Any mounts that do not appear to either an attached block device or network resource will be skipped with a log like "Ignoring nonexistent mount ...". Cloud-init will attempt to add the following mount directives if available and unconfigured in `/etc/fstab`:: mounts: - ["ephemeral0", "/mnt", "auto","defaults,nofail,x-systemd.requires=cloud-init.service", "0", "2"] - ["swap", "none", "swap", "sw", "0", "0"] In order to remove a previously listed mount, an entry can be added to the `mounts` list containing ``fs_spec`` for the device to be removed but no mountpoint (i.e. ``[ swap ]`` or ``[ swap, null ]``). The ``mount_default_fields`` config key allows default values to be specified for the fields in a ``mounts`` entry that are not specified, aside from the ``fs_spec`` and the ``fs_file`` fields. If specified, this must be a list containing 6 values. It defaults to:: mount_default_fields: [none, none, "auto","defaults,nofail,x-systemd.requires=cloud-init.service", "0", "2"] Non-systemd init systems will vary in ``mount_default_fields``. Swap files can be configured by setting the path to the swap file to create with ``filename``, the size of the swap file with ``size`` maximum size of the swap file if using an ``size: auto`` with ``maxsize``. By default no swap file is created. .. note:: If multiple mounts are specified where a subsequent mount's mountpoint is inside of a previously declared mount's mountpoint (i.e. the 1st mount has a mountpoint of ``/abc`` and the 2nd mount has a mountpoint of ``/abc/def``) then this will not work as expected - ``cc_mounts`` first creates the directories for all the mountpoints **before** it starts to perform any mounts and so the sub-mountpoint directory will not be created correctly inside the parent mountpoint. For systems using util-linux's ``mount`` program this issue can be worked around by specifying ``X-mount.mkdir`` as part of a ``fs_mntops`` value for the subsequent mount entry. a< # Mount ephemeral0 with "noexec" flag, /dev/sdc with mount_default_fields, # and /dev/xvdh with custom fs_passno "0" to avoid fsck on the mount. # Also provide an automatically sized swap with a max size of 10485760 # bytes. mounts: - [ /dev/ephemeral0, /mnt, auto, "defaults,noexec" ] - [ sdc, /opt/data ] - [ xvdh, /opt/data, auto, "defaults,nofail", "0", "0" ] mount_default_fields: [None, None, auto, "defaults,nofail", "0", "2"] swap: filename: /my/swapfile size: auto maxsize: 10485760 allZ cc_mountsZMountsz%Configure mount points and swap filesz # Create a 2 GB swap file at /swapfile using human-readable values swap: filename: /swapfile size: 2G maxsize: 2G )idnametitle descriptiondistrosZexamplesZ frequencyZactivate_by_schema_keysz&^([x]{0,1}[shv]d[a-z][0-9]*|sr[0-9]+)$z^.+:.*z[%s]+z /etc/fstabzcomment=cloudconfigcCs:|d kr dSx(d D] }|j|r|jdd krdSqWd S) NamirootswapT ephemeralebs:F)rrr)rr) startswithfind)rZenumnamer/usr/lib/python3.6/cc_mounts.pyis_meta_device_names  r!cCstj|rdSdS)NTF)NETWORK_NAME_REmatch)rrrr is_network_devices r$cCsHt|d|fd|fg}x(|D] }d||f}tjj|r |Sq WdS)Nzp%sz-part%sz%s%s)strospathexists) device_pathpartition_numberZpotential_suffixessuffixZpotential_partition_devicerrr _get_nth_partition_for_devices    r,cCsXtjj|jdd}tjjd|}|dk rLtjj|tjj|jdd}tjj|S)N/rz /sys/block/rr)r&r'realpathsplitjoinr()r)partition_pathZ device_nameZsys_pathrrr _is_block_devices r2cCs tjd||}|dkr&d}tjdt|r2|Stj|\}}|}|rj|j||}||krjtjd||t|r||}|sdS|jdsd|f}tjd||ntj |rd|f}d}|dkrt |d }nt ||}|dkrdSt ||r|dk r|S|SdS) Nz+Attempting to determine the real name of %sr ephemeral0z2Adjusted mount option from ephemeral to ephemeral0zMapped device alias %s to %sr-z/dev/%szMapped metadata name %s to %sr) LOGdebugr$rZexpand_dotted_devnamegetr!rDEVICE_NAME_REr#r,r2)Z startnameZ transformeraliasesZdevnamer)r*Zorigr1rrr sanitize_devnamesD          r9c Csh|dkrtjd}|d}d||d}|dkr>|dkr>|}nd|rtj|}|j|j}||d<|dkr|tt|d|}q||dkrt|d}n |dkr|}||d<|dtkr|}n,|d tkrdt}nt t j |tt}t||}||d <i} x<|j D]0\} } t | tr.d | t| | <n| | | <qWtjd | d | d | d| d| d|S)NtotalrZna)availmax_inmemr;g?maxsizez%s MBzCsuggest %s swap for %s memory with '%s' disk given max=%s [max=%s]'r=r<)r read_meminfor&statvfsf_frsizef_bfreeminintGBroundmathZsqrtitems isinstanceMBr4r5) memsizemaxsizefsysZsugg_maxinforCr;ZminsizerAZpinfokvrrr suggested_swapsizesJ           rT)fnamerAreturncsdfdd}tjj|}tj|tj|ddkr`tjddd|gtjd d |gd krtjdkr|||dn>y|||dWn,tjk rt j d|||dYnXtjj |rtj |dytjd|gWn$tjk rtj |YnXdS)zSize is in MiB.z6Failed to create swapfile '%s' of size %sMB via %s: %scstjd|||dkr*ddd||g}n|dkrHddd|dd |g}ytj|d d WnBtjk r}z$tj||||tj|WYdd}~XnXdS) Nz3Creating swapfile in '%s' on fstype '%s' using '%s' fallocatez-lz%sMddz if=/dev/zerozof=%szbs=1Mzcount=%sT)Zcapture)r4r5rProcessExecutionErrorrQrdel_file)rUrAmethodcmde)errmsgfstyperr create_swap!s&  z$create_swapfile..create_swaprZbtrfstruncatez-s0Zchattrz+CZxfsr>rXrWz4fallocate swap creation failed, will attempt with ddiZmkswapN)r>rc)r&r'dirnamer ensure_dirZget_mount_inforZkernel_versionrYr4rQr(chmodrZ)rUrAr`swap_dirr)r^r_r create_swapfiles,      rhcCstjj|}t|jdkrdytjd}Wntk rJtj ddSXtj |t |||d}tt |d }|stj ddStj tj d t||gd |S) z fname: full path string of filename to setup size: the size to create. set to "auto" for recommended maxsize: the maximum size autor:z)Not creating swap: failed to read meminfoN)rPrOrNrrz'Not creating swap: suggested size was 0zSetting up swap file)msgfuncargsi)r&r'rdr%lowerrrBIOErrorr4r5rerTrGZlog_timerh)rUrArOrgrNZmibsizerrr setup_swapfileVs(      rocCsZt|tstjddS|jdd}|jdd}|jdd}|oB|sRtjddStjj|rtjjd sztjd ||SyFx4t j d j D]"}|j |d rtjd ||SqWtjd |Wn t k rtjd||SXyBt|to|dkrt j|}t|trt j|}t|||dSt k rT}ztjd|WYdd}~XnXdS)zahandle the swap config, calling setup_swap if necessary. return None or (filename, size) z%input for swap config was not a dict.Nfilenamez /swap.imgrArrOzno need to setup swapz /proc/swapsz:swap file %s exists, but no /proc/swaps exists, being safe zswap file %s already in usez+swap file %s exists, but not in /proc/swapsz.swap file %s exists. Error reading /proc/swapsri)rUrArOzfailed to setup swap: %s)rLdictr4warningr6r5r&r'r(r load_file splitlinesr Exceptionr%Z human2bytesro)ZswapcfgrUrArOliner]rrr handle_swapcfgxsD            rx)rcfgcloudrlrVc$ sXd}|jj}|rd}ddd|ddg}|jd|}ddd|d ddgd d d d ddgg}g}d |krj|d }tjd|g} i} g} tjjtrxdt j tj D]R} t | kr| j | qytj| } Wntk rYnX| | | d<| j | qW|jdi}xtt|D]}t||tsFtjd|dtj||qt||d}t||j|d}||kr~tjd|||dkrtjd|qn || krtjd|| |q|||d<xJtt||D]6}|||dkrqnt||||||<qWqWxtt|D]}x^tt|D]N}t|||krb||j ||n"|||dkr8|||||<q8W||ddkr&x8t|D],}||d||dkrd||d<qWq&Wx|D]}|d}t||j|d}||krtjd|||dkr2tjd|qn || krRtjd|| |q||d<d}x&|D]}|d|dkrdd}PqdW|rtjd|q|j |qWg}x8|D]0}|ddkrtjd|dn |j |qWt|jd i}|r|j |d d d ddgt|dkr2tjddSg}d}d}g}xb|D]Z} d| d t f| d <| dd krrd}| djd r|j | d|j d!j| qHWd"d#t jj D}xX|D]P}yt j!|Wn$tk rt j"td$|YnX| r||krd}qWd%d#|Dd&d#| Dfd'd#Dfd(d#D}| j#|d)d*j| } t j$t| g}!|r|!j d+d,gt|dkrtjd-ntjd.|d}|r|!j d/d,g|r|!j d0d1gd2}"xj|!D]b}#d3d4j|#}"yt%j%|#tj|"d5Wn2t%j&k rLtj|"d6t j"t|"d6YnXqWdS)7Nzdefaults,nobootwaitz=defaults,nofail,x-systemd.requires=cloud-init.service,_netdevrirb2Zmount_default_fieldsr3z/mntrZnoneswmountszmounts configuration is %srdevice_aliasesz,Mount option %s not a list, got a %s insteadr)r8zchanged %s => %sz#Ignoring nonexistent named mount %sz&Device %s already defined in fstab: %szchanged default device %s => %sz+Ignoring nonexistent default named mount %sFTz-Not including %s, already previously includedz$Skipping nonexistent device named %sz No modifications to fstab neededz%s,%srr- cSs g|]\}}d|kr|dqS)Z mountpointr).0rRrSrrr Jszhandle..z Failed to make '%s' config-mountcSsg|]}tjd|qS)rq)WSsub)rnrrr rWscSsg|]}tjd|qS)rq)rr)rrrrr rXscsg|]}|krd|qS)z- r)rZdrop)saddsrr rZscsg|]}|krd|qS)z+ r)radd)sdropsrr r[sz%s  Zswaponz-azNo changes to /etc/fstab made.zChanges to fstab: %sZmountZ systemctlz daemon-reloadz#Activating swap and mounts with: %szActivate mounts: %s:rqZPASSZFAIL)'Zdistro uses_systemdr6r4r5r&r'r( FSTAB_PATHrrtru MNT_COMMENTappendrr/rvrangelenrLlistrsrZobj_namer%r9Zdevice_name_to_devicerQrxrr0r~rKreZlogexcextendZ write_filerrY)$rryrzrlZ def_mnt_optsrZdefvalsZdefmntsZcfgmntZ fstab_linesZ fstab_devsZ fstab_removedrwZtoksristartZ sanitizedjZdefmntZ cfgmnt_hasZcfgmZactlistxZswapretZcc_linesZneedswapZneed_mount_alldirsZ mount_pointsdZsopscontentsZ activate_cmdsZfmtr\r)rrr handles"             $                    rii@)N)N)NNN)NN)3__doc__ZloggingrJr&restringrtextwraprZ cloudinitrrrZcloudinit.cloudrZcloudinit.configrZcloudinit.config.schemar r Zcloudinit.settingsr ZMODULE_DESCRIPTIONZexamplermetaZDEVICE_NAME_FILTERcompiler7ZNETWORK_NAME_FILTERr"rrrrMrHZ getLogger__name__r4r!r$r,r2r9rTr%rhrorxrrrrrr  s\     5      1 9: "0