|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
# Copyright 2008-2016 Mir Calculate. http://www.calculate-linux.org
|
|
|
#
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
# You may obtain a copy of the License at
|
|
|
#
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
#
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
# See the License for the specific language governing permissions and
|
|
|
# limitations under the License.
|
|
|
|
|
|
import os
|
|
|
from os import path, R_OK
|
|
|
import platform
|
|
|
import re
|
|
|
import errno
|
|
|
from calculate.lib.utils.dracut import Dracut
|
|
|
from calculate.lib.datavars import Variable, ReadonlyVariable
|
|
|
from calculate.lib.utils.files import (readFile, process, listDirectory,
|
|
|
pathJoin)
|
|
|
from calculate.lib.utils.mount import isMount, Mounts
|
|
|
from calculate.lib.utils.system import SystemType
|
|
|
import calculate.lib.utils.device as device
|
|
|
from calculate.lib.utils.device import loadEfiVars
|
|
|
from calculate.lib.utils.common import getKernelUid, getValueFromCmdLine, \
|
|
|
CmdlineParams
|
|
|
|
|
|
|
|
|
|
|
|
class VariableOsArchMachine(ReadonlyVariable):
|
|
|
"""
|
|
|
Computer architecture (i686,x86_64)
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
return platform.machine()
|
|
|
|
|
|
|
|
|
class VariableOsArchMachineGentoo(ReadonlyVariable):
|
|
|
"""
|
|
|
Архитектура пакетов
|
|
|
"""
|
|
|
source_arch = "os_arch_machine"
|
|
|
|
|
|
def get(self):
|
|
|
map_arch = {'x86_64': 'amd64', 'i686': 'x86', 'i386': 'x86'}
|
|
|
arch = self.Get(self.source_arch)
|
|
|
return map_arch.get(arch, arch)
|
|
|
|
|
|
|
|
|
class VariableOsRootDev(ReadonlyVariable):
|
|
|
"""
|
|
|
Root partition of current system
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
"""Root filesystem device"""
|
|
|
record = readFile('/proc/cmdline').strip()
|
|
|
re_resRealRoot = re.search('(?:^|\s)real_root=(\S+)(\s|$)', record)
|
|
|
re_resFakeRoot = re.search('(?:^|\s)root=(\S+)(\s|$)', record)
|
|
|
# param real_root priority that root
|
|
|
re_res = re_resRealRoot or re_resFakeRoot
|
|
|
if re_res:
|
|
|
rootparam = re_res.group(1)
|
|
|
# check root for /dev/sd view
|
|
|
if re.match("^/dev/[a-z]+.*$", rootparam):
|
|
|
return device.udev.get_device_info(
|
|
|
name=rootparam.strip()).get('DEVNAME', rootparam)
|
|
|
# check root set by uuid
|
|
|
if re.match("^UUID=.*$", rootparam):
|
|
|
uuid = rootparam[5:].strip("\"'")
|
|
|
blkid_process = process('/sbin/blkid', '-c', '/dev/null', '-U',
|
|
|
uuid)
|
|
|
if blkid_process.success():
|
|
|
return device.udev.get_device_info(
|
|
|
name=blkid_process.read().strip()).get('DEVNAME', '')
|
|
|
# check root set by label
|
|
|
if re.match("^LABEL=.*$", rootparam):
|
|
|
uuid = rootparam[6:].strip("\"'")
|
|
|
blkid_process = process('/sbin/blkid', '-c', '/dev/null', '-L',
|
|
|
uuid)
|
|
|
if blkid_process.success():
|
|
|
return device.udev.get_device_info(
|
|
|
name=blkid_process.read().strip()).get('DEVNAME', '')
|
|
|
# get device mounted to root
|
|
|
df_process = process('df', '/', envdict={'LANG': 'C'})
|
|
|
if df_process.failed():
|
|
|
return ""
|
|
|
df_lines = df_process.readlines()
|
|
|
if len(df_lines) > 1:
|
|
|
root_dev = df_lines[1].split(" ")[0].strip()
|
|
|
if root_dev:
|
|
|
return {
|
|
|
'none': '/dev/ram0',
|
|
|
'overlay': '/dev/ram0',
|
|
|
}.get(root_dev, root_dev)
|
|
|
return ""
|
|
|
|
|
|
|
|
|
class VariableOsMapperRootDev(ReadonlyVariable):
|
|
|
"""
|
|
|
Название диска через devicemapper если возможно
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
rootdev = self.Get('os_root_dev')
|
|
|
dev_links = device.udev.get_device_info(
|
|
|
name=rootdev).get("DEVLINKS", "")
|
|
|
if dev_links:
|
|
|
mapper_name = filter(lambda x: "/dev/mapper" in x,
|
|
|
dev_links.split())
|
|
|
if mapper_name:
|
|
|
return mapper_name[0]
|
|
|
return rootdev
|
|
|
|
|
|
|
|
|
class RootType(object):
|
|
|
"""
|
|
|
Типы загруженной системы
|
|
|
"""
|
|
|
|
|
|
class Value(object):
|
|
|
HDD = "hdd"
|
|
|
LiveCD = "livecd"
|
|
|
USB_HDD = "usb-hdd"
|
|
|
LiveFlash = "flash"
|
|
|
IsoScanGrub = "isoscan-grub"
|
|
|
IsoScanFlash = "isoscan-flash"
|
|
|
NetBoot = "nfs"
|
|
|
|
|
|
HDD = (Value.HDD,)
|
|
|
LiveCD = (Value.LiveCD,)
|
|
|
USB_HDD = (Value.USB_HDD,)
|
|
|
HDDs = (Value.HDD, Value.USB_HDD,)
|
|
|
LiveFlash = (Value.LiveFlash,)
|
|
|
IsoScanGrub = (Value.IsoScanGrub,)
|
|
|
IsoScanFlash = (Value.IsoScanFlash,)
|
|
|
NetBoot = (Value.NetBoot,)
|
|
|
Live = (Value.LiveCD, Value.LiveFlash, Value.IsoScanFlash,
|
|
|
Value.IsoScanGrub, Value.NetBoot)
|
|
|
IsoScan = (Value.IsoScanFlash, Value.IsoScanGrub)
|
|
|
|
|
|
RebuildAvailable = (Value.LiveFlash, Value.IsoScanFlash)
|
|
|
Grubable = (Value.HDD, Value.USB_HDD, Value.IsoScanGrub)
|
|
|
|
|
|
|
|
|
class VariableOsRootType(ReadonlyVariable):
|
|
|
"""
|
|
|
Root type (ram, hdd, usb-hdd, livecd)
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
"""Root device type (ram, hdd, livecd)"""
|
|
|
extended_type = self.Get('os_root_type_ext')
|
|
|
if extended_type in RootType.Live:
|
|
|
return "livecd"
|
|
|
if extended_type in RootType.USB_HDD:
|
|
|
return "usb-hdd"
|
|
|
return "hdd"
|
|
|
|
|
|
|
|
|
class VariableClIsoscanPath(ReadonlyVariable):
|
|
|
"""
|
|
|
Образ с которого загружена система
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
return getValueFromCmdLine(CmdlineParams.IsoscanFile) or ""
|
|
|
|
|
|
|
|
|
class VariableClIsoscanBasePath(ReadonlyVariable):
|
|
|
"""
|
|
|
Путь куда монтируется устройство isoscan
|
|
|
"""
|
|
|
value = Dracut.IsoScanPath
|
|
|
|
|
|
|
|
|
class VariableClIsoscanFullpath(ReadonlyVariable):
|
|
|
"""
|
|
|
Путь в системе до образа с которого загружена система
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
isoscan_path = self.Get('cl_isoscan_path')
|
|
|
if isoscan_path:
|
|
|
isoscan_base_path = self.Get('cl_isoscan_base_path')
|
|
|
return pathJoin(isoscan_base_path, isoscan_path)
|
|
|
return ""
|
|
|
|
|
|
|
|
|
class VariableOsRootFlashDev(ReadonlyVariable):
|
|
|
"""
|
|
|
Флешка с которой загружена система
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
root_type = self.Get('os_root_type_ext')
|
|
|
if root_type in RootType.LiveFlash:
|
|
|
mounts = Mounts()
|
|
|
return mounts.getBy(mounts.NAME, where=mounts.DIR,
|
|
|
eq=Dracut.IsoLive)
|
|
|
elif root_type in RootType.IsoScanFlash:
|
|
|
mounts = Mounts()
|
|
|
return mounts.getBy(mounts.NAME, where=mounts.DIR,
|
|
|
eq=Dracut.IsoScanPath)
|
|
|
return ""
|
|
|
|
|
|
|
|
|
class VariableOsRootTypeExt(ReadonlyVariable):
|
|
|
"""
|
|
|
Расширенный тип загруженной системы
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
def link2pair(linkfile):
|
|
|
"""Return pair (target,link) from link"""
|
|
|
basedir = path.dirname(linkfile)
|
|
|
targetfile = os.readlink(linkfile)
|
|
|
return path.normpath(os.path.join(basedir, targetfile)), linkfile
|
|
|
|
|
|
root_dev = self.Get("os_root_dev")
|
|
|
if root_dev:
|
|
|
if "/dev/nfs" in root_dev:
|
|
|
return RootType.Value.NetBoot
|
|
|
|
|
|
if "/dev/ram" in root_dev:
|
|
|
record = readFile('/proc/cmdline').strip()
|
|
|
if self.Get('cl_isoscan_path'):
|
|
|
grub_cfg = path.join(
|
|
|
path.dirname(self.Get('cl_isoscan_fullpath')),
|
|
|
"grub.cfg")
|
|
|
if path.exists(grub_cfg):
|
|
|
return RootType.Value.IsoScanGrub
|
|
|
else:
|
|
|
return RootType.Value.IsoScanFlash
|
|
|
elif "root=live:UUID" in record:
|
|
|
return RootType.Value.LiveFlash
|
|
|
return RootType.Value.LiveCD
|
|
|
|
|
|
id_dict = dict(map(link2pair,
|
|
|
filter(lambda x: path.islink(x),
|
|
|
map(lambda x: path.join('/dev/disk/by-id',
|
|
|
x),
|
|
|
listDirectory('/dev/disk/by-id')))))
|
|
|
if "usb-" in id_dict.get(root_dev, ""):
|
|
|
return RootType.Value.USB_HDD
|
|
|
return RootType.Value.HDD
|
|
|
|
|
|
|
|
|
class VariableClChrootStatus(ReadonlyVariable):
|
|
|
"""
|
|
|
Is chroot active
|
|
|
"""
|
|
|
|
|
|
def isChroot(self, pid):
|
|
|
"""Detect chroot mode by different mountinfo"""
|
|
|
if not os.access('/proc/self/mountinfo', R_OK) or \
|
|
|
not os.access('/proc/1/mountinfo', R_OK):
|
|
|
return False
|
|
|
infos = [readFile(x) for x in ('/proc/1/mountinfo',
|
|
|
'/proc/self/mountinfo')]
|
|
|
return infos[0] != infos[1]
|
|
|
|
|
|
def get(self):
|
|
|
try:
|
|
|
return "on" if self.isChroot(os.getpid()) else "off"
|
|
|
except Exception:
|
|
|
return "off"
|
|
|
|
|
|
|
|
|
class VariableClKernelUid(Variable):
|
|
|
"""
|
|
|
Kernel UID get by UUID of root device
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
return getKernelUid(self.Get('os_root_dev'))
|
|
|
|
|
|
|
|
|
class VariableOsScratch(ReadonlyVariable):
|
|
|
"""
|
|
|
Is current system scratch
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
"""Current system is scratch"""
|
|
|
if self.Get('os_root_type') == 'livecd':
|
|
|
return "on" if isMount('/mnt/scratch/workspace') else "off"
|
|
|
else:
|
|
|
return "on" if isMount('/mnt/scratch') else "off"
|
|
|
|
|
|
|
|
|
class VariableOsUefiSet(ReadonlyVariable):
|
|
|
"""
|
|
|
Current loaded system
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
loadEfiVars()
|
|
|
if device.sysfs.exists(device.sysfs.Path.Efi):
|
|
|
return "on"
|
|
|
else:
|
|
|
return "off"
|
|
|
|
|
|
|
|
|
class VariableClUsedAction(ReadonlyVariable):
|
|
|
"""
|
|
|
Переменная содержит все найденные при обработке шаблонов
|
|
|
событийные переменные (ac_)
|
|
|
"""
|
|
|
type = "table"
|
|
|
|
|
|
def get(self):
|
|
|
return []
|
|
|
|
|
|
|
|
|
class VariableClSystemBootSet(ReadonlyVariable):
|
|
|
"""
|
|
|
Система находится в стадии загрузки
|
|
|
"""
|
|
|
type = "bool"
|
|
|
|
|
|
def get(self):
|
|
|
if os.readlink('/proc/self/fd/0') == '/dev/console':
|
|
|
return "on"
|
|
|
else:
|
|
|
return "off"
|
|
|
|
|
|
|
|
|
class VariableClLivePath(Variable):
|
|
|
"""
|
|
|
Путь до образов из которых будет формировать live меню для grub
|
|
|
"""
|
|
|
value = "/var/calculate/linux"
|
|
|
|
|
|
class VariableOsSubsystem(Variable):
|
|
|
"""
|
|
|
Получить подтип системы (lxc, uml, openvz и т.д.)
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
return SystemType.detect()
|
|
|
|
|
|
|
|
|
class VariableClRootReadonly(ReadonlyVariable):
|
|
|
"""
|
|
|
"""
|
|
|
type = "bool"
|
|
|
|
|
|
def get(self):
|
|
|
check_fn = '/var/tmp/.calculate-rw-check-%d' % os.getpid()
|
|
|
try:
|
|
|
with open(check_fn,'w') as f:
|
|
|
pass
|
|
|
os.unlink(check_fn)
|
|
|
except (IOError,OSError) as e:
|
|
|
if e.errno == errno.EROFS:
|
|
|
return "on"
|
|
|
return "off"
|