jbc@sdZddlmZddlZddlZddlZddlmZddlm Z dZ ej e Z ej deZ dZd ZejeZd Zd Zdd Zd ZddddZdZdddZdZdZdS(s< Mounts ------ **Summary:** configure mount points and swap files 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. 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. ``[ sda1 ]`` or ``[ sda1, null ]``). The ``mount_default_fields`` config key allows default options to be specified for the values in a ``mounts`` entry that are not specified, aside from the ``fs_spec`` and the ``fs_file``. If specified, this must be a list containing 7 values. It defaults to:: mount_default_fields: [none, none, "auto", "defaults,nobootwait", "0", "2"] On a systemd booted system that default is the mostly equivalent:: mount_default_fields: [none, none, "auto", "defaults,nofail,x-systemd.requires=cloud-init.service", "0", "2"] Note that `nobootwait` is an upstart specific boot option that somewhat equates to the more standard `nofail`. 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. **Internal name:** ``cc_mounts`` **Module frequency:** per instance **Supported distros:** all **Config keys**:: 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: size: <"auto"/size in bytes> maxsize: i(t whitespaceN(t type_utils(tutils&^([x]{0,1}[shv]d[a-z][0-9]*|sr[0-9]+)$s[%s]+s /etc/fstabscomment=cloudconfigcCsM|dkrtSx6d D].}|j|r|jddkrtSqWtS( Ntamitroottswapt ephemeraltebst:i(RRR(RR(tTruet startswithtfindtFalse(tnametenumname((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pytis_meta_device_nameTs   $cCs^t|d|fd|fg}x4|D],}d||f}tjj|r*|Sq*WdS(Nsp%ss-part%ss%s%s(tstrtostpathtexiststNone(t device_pathtpartition_numbertpotential_suffixestsuffixtpotential_partition_device((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pyt_get_nth_partition_for_device`s cCstjj|jdd}tjjd|}|dk rqtjj|tjj|jdd}ntjj|S(Nt/is /sys/block/(RRtrealpathtsplittjoinRR(Rtpartition_patht device_nametsys_path((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pyt_is_block_devicejs   (cCs3|jd||}|dkr8d}|jdntj|\}}t|r|}||}|sudS|jdsd|f}n|jd||ntj|rd|f}nd}|dkrt|d}nt||}|dkr dSt ||r/|dk r+|S|SdS( Ns+Attempting to determine the real name of %sRt ephemeral0s2Adjusted mount option from ephemeral to ephemeral0Rs/dev/%ssMapped metadata name %s to %si( tdebugRtexpand_dotted_devnameRRR tDEVICE_NAME_REtmatchRR"(t startnamet transformertlogtdevnameRRtorigR((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pytsanitize_devnamess8       c s|dkrtjd}ndd}idd6|d6|d6}|dkrk|dkrk|}n|rtj|}|j|j}||d<|dkrtt|d |}q||d krt|d }qn|dkr|}n||d /usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pytscsdS(Ni((R4(tGB(s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pyR5scSs|S(N((R4((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pyR5sicsdS(Ni((R4(R6(s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pyR5si@cSs|dS(Ni((R4((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pyR5sitsizeis%s MBsCsuggest %s swap for %s memory with '%s' disk given max=%s [max=%s]'i@i( RRt read_meminfoRtstatvfstf_frsizetf_bfreetmintinttitemst isinstancetLOGR$(tmemsizetmaxsizetfsystsugg_maxtinfoR9R0tformulasR7ttoptfunctMBtpinfotktv((R6s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pytsuggested_swapsizesX              csdfd}tjj|}tj|tj|dd kri|||dncy|||dWnLtjk r}tj||d|tjd|||dnXtj |d ytj d |gWn$tjk rtj |nXd S( sSize is in MiB.s6Failed to create swapfile '%s' of size %sMB via %s: %scstjd|||dkr;ddd||g}n,|dkrgddd|dd |g}nytj|d tWn<tjk r}tj||||tj|nXdS( Ns3Creating swapfile in '%s' on fstype '%s' using '%s't fallocates-ls%sMtdds if=/dev/zerosof=%ssbs=1Mscount=%stcapture(R@R$RtsubpR tProcessExecutionErrortwarningtdel_file(tfnameR7tmethodtcmdte(terrmsgtfstype(s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pyt create_swaps    itxfstbtrfsRORNsWill attempt with dd.itmkswapN(R\R]( RRtdirnameRt ensure_dirtget_mount_infoRRR@RStchmodRQRT(RUR7R[tswap_dirRX((RYRZs>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pytcreate_swapfiles&    c Cstjj|}t|jdkrytjd}Wntk r_tj ddSXtj |t d|d|d|}ntt |d}|stj d dStj tj d d d td||g|S(s fname: full path string of filename to setup size: the size to create. set to "auto" for recommended maxsize: the maximum size tautoR.s)Not creating swap: failed to read meminfoNRCRBRAiis'Not creating swap: suggested size was 0tmsgsSetting up swap fileRHtargsi(RRR_RtlowerRR8tIOErrorR@R$R`RMR=tlog_timeRd(RUR7RBRcRAtmibsize((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pytsetup_swapfiles"      c Cst|ts tjddS|jdd}|jdd}|jdd}|o_|sstjddStjj |r.tjj d stjd ||Sy[xDt j d j D]-}|j |d rtjd ||SqWtjd |Wq.tk r*tjd||SXnykt|tr^|dkr^t j|}nt|trt j|}ntd|d|d|SWn#tk r}tjd|nXdS(sdhandle the swap config, calling setup_swap if necessary. return None or (filename, size) s%input for swap config was not a dict.tfilenames /swap.imgR7iRBsno need to setup swapNs /proc/swapss:swap file %s exists, but no /proc/swaps exists, being safet sswap file %s already in uses+swap file %s exists, but not in /proc/swapss.swap file %s exists. Error reading /proc/swapsReRUsfailed to setup swap: %s(R?tdictR@RSRtgetR$RRRRt load_filet splitlinesR t ExceptionRt human2bytesRl(tswapcfgRUR7RBtlineRX((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pythandle_swapcfg+sB      c+Cs\d}|jj}|r$d}nddd|ddg}|jd|}ddd|d ddgd d d d ddgg}g} d |kr|d } ntjd| g} i} g} x~tjtj D]g} t | kr| j | qnyt j | }Wntk r$nX| | |d<| j | qWxVtt| D]B}t| |ts|jd|dtj| |qWnt| |d}t||j|}||kr|jd||fn|dkr |jd|qWn)|| kr4|jd|| |qWn|| |d %ss#Ignoring nonexistent named mount %ss&Device %s already defined in fstab: %sschanged default device %s => %ss+Ignoring nonexistent default named mount %ss-Not including %s, already previously includeds$Skipping nonexistent device named %ss No modifications to fstab neededs%s,%siRs t mountpoints Failed to make '%s' config-mountRns- s+ s%s s tswapons-asNo changes to /etc/fstab made.sChanges to fstab: %stmountt systemctls daemon-reloads#Activating swap and mounts with: %ssActivate mounts: %s:tPASStFAIL((tdistrot uses_systemdRRpR@R$RRqt FSTAB_PATHRrt MNT_COMMENTtappendtWSRRstrangetlenR?tlistRSRtobj_nameRR-tdevice_name_to_deviceRER R RwR RR}R>R`tlogexctsubtextendt write_fileRQRR(+t_nametcfgtcloudR*t_argst def_mnt_optsRtdefvalstdefmntstcfgmntt fstab_linest fstab_devst fstab_removedRvttokstitstartt sanitizedtjtdefmntt cfgmnt_hastcfgmtactlistR4tswaprettcc_linestneedswaptneed_mount_alltdirsRKRLt mount_pointstdtntsaddstsdropstdroptaddtsopstcontentst activate_cmdstfmtRW((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pythandleXs           $          "      %%&*   (t__doc__tstringRtloggingtos.pathRtret cloudinitRRtDEVICE_NAME_FILTERtcompileR&RRRt getLoggert__name__R@RRRR"R-RMRdRlRwR(((s>/usr/lib/python2.7/site-packages/cloudinit/config/cc_mounts.pyt?s*    (G , -