Begin to support to boot from volume for Ubuntu distro. Change-Id: I001a3bf439c579697f57fcaa33940f5803391cfd
		
			
				
	
	
		
			601 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			601 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright 2015 IBM Corp.
 | 
						|
#
 | 
						|
#    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 abc
 | 
						|
 | 
						|
from oslo_config import cfg
 | 
						|
from oslo_log import log as logging
 | 
						|
import six
 | 
						|
 | 
						|
from nova.i18n import _
 | 
						|
from nova.virt.zvm import exception
 | 
						|
 | 
						|
CONF = cfg.CONF
 | 
						|
 | 
						|
LOG = logging.getLogger(__name__)
 | 
						|
 | 
						|
 | 
						|
@six.add_metaclass(abc.ABCMeta)
 | 
						|
class LinuxDist(object):
 | 
						|
    """Linux distribution base class
 | 
						|
 | 
						|
    Due to we need to interact with linux dist and inject different files
 | 
						|
    according to the dist version. Currently only RHEL and SLES are supported
 | 
						|
    """
 | 
						|
 | 
						|
    def create_network_configuration_files(self, file_path, network_info,
 | 
						|
                                           base_vdev):
 | 
						|
        """Generate network configuration files to instance."""
 | 
						|
        device_num = 0
 | 
						|
        cfg_files = []
 | 
						|
        cmd_strings = ''
 | 
						|
        udev_cfg_str = ''
 | 
						|
        dns_cfg_str = ''
 | 
						|
        route_cfg_str = ''
 | 
						|
        cmd_str = None
 | 
						|
        file_path = self._get_network_file_path()
 | 
						|
        file_name_route = file_path + 'routes'
 | 
						|
 | 
						|
        file_name_dns = self._get_dns_filename()
 | 
						|
        for vif in network_info:
 | 
						|
            file_name = self._get_device_filename(device_num)
 | 
						|
            network = vif['network']
 | 
						|
            (cfg_str, cmd_str, dns_str,
 | 
						|
                route_str) = self._generate_network_configuration(network,
 | 
						|
                                                base_vdev, device_num)
 | 
						|
            target_net_conf_file_name = file_path + file_name
 | 
						|
            cfg_str_for_log = cfg_str.replace('\n', ' ')
 | 
						|
            LOG.debug('Network configure file[%s] content is: %s',
 | 
						|
                    (target_net_conf_file_name, cfg_str_for_log))
 | 
						|
            cfg_files.append((target_net_conf_file_name, cfg_str))
 | 
						|
            udev_cfg_str += self._get_udev_configuration(device_num,
 | 
						|
                                '0.0.' + str(base_vdev).zfill(4))
 | 
						|
            if cmd_str is not None:
 | 
						|
                cmd_strings += cmd_str
 | 
						|
            if len(dns_str) > 0:
 | 
						|
                dns_cfg_str += dns_str
 | 
						|
            if len(route_str) > 0:
 | 
						|
                route_cfg_str += route_str
 | 
						|
            base_vdev = str(hex(int(base_vdev, 16) + 3))[2:]
 | 
						|
            device_num += 1
 | 
						|
 | 
						|
        if len(dns_cfg_str) > 0:
 | 
						|
            cfg_files.append((file_name_dns, dns_cfg_str))
 | 
						|
        self._append_udev_info(cfg_files, file_name_route, route_cfg_str,
 | 
						|
                               udev_cfg_str)
 | 
						|
        return cfg_files, cmd_strings
 | 
						|
 | 
						|
    def _generate_network_configuration(self, network, vdev, device_num):
 | 
						|
        ip_v4 = dns_str = ''
 | 
						|
 | 
						|
        subnets_v4 = [s for s in network['subnets'] if s['version'] == 4]
 | 
						|
 | 
						|
        if len(subnets_v4[0]['ips']) > 0:
 | 
						|
            ip_v4 = subnets_v4[0]['ips'][0]['address']
 | 
						|
        if len(subnets_v4[0]['dns']) > 0:
 | 
						|
            for dns in subnets_v4[0]['dns']:
 | 
						|
                dns_str += 'nameserver ' + dns['address'] + '\n'
 | 
						|
        netmask_v4 = str(subnets_v4[0].as_netaddr().netmask)
 | 
						|
        gateway_v4 = subnets_v4[0]['gateway']['address'] or ''
 | 
						|
        broadcast_v4 = str(subnets_v4[0].as_netaddr().broadcast)
 | 
						|
        device = self._get_device_name(device_num)
 | 
						|
        address_read = str(vdev).zfill(4)
 | 
						|
        address_write = str(hex(int(vdev, 16) + 1))[2:].zfill(4)
 | 
						|
        address_data = str(hex(int(vdev, 16) + 2))[2:].zfill(4)
 | 
						|
        subchannels = '0.0.%s' % address_read.lower()
 | 
						|
        subchannels += ',0.0.%s' % address_write.lower()
 | 
						|
        subchannels += ',0.0.%s' % address_data.lower()
 | 
						|
 | 
						|
        cfg_str = self._get_cfg_str(device, broadcast_v4, gateway_v4,
 | 
						|
                                    ip_v4, netmask_v4, address_read,
 | 
						|
                                    subchannels)
 | 
						|
        cmd_str = self._get_cmd_str(address_read, address_write,
 | 
						|
                                    address_data)
 | 
						|
        route_str = self._get_route_str(gateway_v4)
 | 
						|
 | 
						|
        return cfg_str, cmd_str, dns_str, route_str
 | 
						|
 | 
						|
    def assemble_zfcp_srcdev(self, fcp, wwpn, lun):
 | 
						|
        path = '/dev/disk/by-path/ccw-0.0.%(fcp)s-zfcp-0x%(wwpn)s:0x%(lun)s'
 | 
						|
        srcdev = path % {'fcp': fcp, 'wwpn': wwpn, 'lun': lun}
 | 
						|
        return srcdev
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def _get_network_file_path(self):
 | 
						|
        """Get network file configuration path."""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def get_change_passwd_command(self, admin_password):
 | 
						|
        """construct change password command
 | 
						|
 | 
						|
        :admin_password: the password to be changed to
 | 
						|
        """
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
 | 
						|
                     netmask_v4, address_read, subchannels):
 | 
						|
        """construct configuration file of network device."""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def _get_device_filename(self, device_num):
 | 
						|
        """construct the name of a network device file."""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def _get_route_str(self, gateway_v4):
 | 
						|
        """construct a router string."""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def _get_cmd_str(self, address_read, address_write, address_data):
 | 
						|
        """construct network startup command string."""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def _get_dns_filename(self):
 | 
						|
        """construct the name of dns file."""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def get_znetconfig_contents(self):
 | 
						|
        """construct znetconfig file will be called during first boot."""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def _get_device_name(self, device_num):
 | 
						|
        """construct the name of a network device."""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def _get_udev_configuration(self, device, dev_channel):
 | 
						|
        """construct udev configuration info."""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def _append_udev_info(self, cfg_files, file_name_route, route_cfg_str,
 | 
						|
                          udev_cfg_str):
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def get_scp_string(self, root, fcp, wwpn, lun):
 | 
						|
        """construct scp_data string for ipl parameter"""
 | 
						|
        pass
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    def get_zipl_script_lines(self, image, ramdisk, root, fcp, wwpn, lun):
 | 
						|
        """construct the lines composing the script to generate
 | 
						|
           the /etc/zipl.conf file
 | 
						|
        """
 | 
						|
        pass
 | 
						|
 | 
						|
 | 
						|
class rhel(LinuxDist):
 | 
						|
    def _get_network_file_path(self):
 | 
						|
        return '/etc/sysconfig/network-scripts/'
 | 
						|
 | 
						|
    def get_change_passwd_command(self, admin_password):
 | 
						|
        return 'echo %s|passwd --stdin root' % admin_password
 | 
						|
 | 
						|
    def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
 | 
						|
                     netmask_v4, address_read, subchannels):
 | 
						|
        cfg_str = 'DEVICE=\"' + device + '\"\n'
 | 
						|
        cfg_str += 'BOOTPROTO=\"static\"\n'
 | 
						|
        cfg_str += 'BROADCAST=\"' + broadcast_v4 + '\"\n'
 | 
						|
        cfg_str += 'GATEWAY=\"' + gateway_v4 + '\"\n'
 | 
						|
        cfg_str += 'IPADDR=\"' + ip_v4 + '\"\n'
 | 
						|
        cfg_str += 'NETMASK=\"' + netmask_v4 + '\"\n'
 | 
						|
        cfg_str += 'NETTYPE=\"qeth\"\n'
 | 
						|
        cfg_str += 'ONBOOT=\"yes\"\n'
 | 
						|
        cfg_str += 'PORTNAME=\"PORT' + address_read + '\"\n'
 | 
						|
        cfg_str += 'OPTIONS=\"layer2=1\"\n'
 | 
						|
        cfg_str += 'SUBCHANNELS=\"' + subchannels + '\"\n'
 | 
						|
        return cfg_str
 | 
						|
 | 
						|
    def _get_route_str(self, gateway_v4):
 | 
						|
        return ''
 | 
						|
 | 
						|
    def _get_cmd_str(self, address_read, address_write, address_data):
 | 
						|
        return ''
 | 
						|
 | 
						|
    def _get_dns_filename(self):
 | 
						|
        return '/etc/resolv.conf'
 | 
						|
 | 
						|
    def _get_device_name(self, device_num):
 | 
						|
        return 'eth' + str(device_num)
 | 
						|
 | 
						|
    def _get_udev_configuration(self, device, dev_channel):
 | 
						|
        return ''
 | 
						|
 | 
						|
    def _append_udev_info(self, cfg_files, file_name_route, route_cfg_str,
 | 
						|
                          udev_cfg_str):
 | 
						|
        pass
 | 
						|
 | 
						|
 | 
						|
class rhel6(rhel):
 | 
						|
    def get_znetconfig_contents(self):
 | 
						|
        return '\n'.join(('cio_ignore -R',
 | 
						|
                          'znetconf -R -n',
 | 
						|
                          'udevadm trigger',
 | 
						|
                          'udevadm settle',
 | 
						|
                          'sleep 2',
 | 
						|
                          'znetconf -A',
 | 
						|
                          'service network restart',
 | 
						|
                          'cio_ignore -u'))
 | 
						|
 | 
						|
    def _get_device_filename(self, device_num):
 | 
						|
        return 'ifcfg-eth' + str(device_num)
 | 
						|
 | 
						|
    def _get_device_name(self, device_num):
 | 
						|
        return 'eth' + str(device_num)
 | 
						|
 | 
						|
    def get_scp_string(self, root, fcp, wwpn, lun):
 | 
						|
        return ("=root=%(root)s selinux=0 zfcp.allow_lun_scan=0 "
 | 
						|
                "rd_ZFCP=0.0.%(fcp)s,0x%(wwpn)s,0x%(lun)s") % {
 | 
						|
                'root': root, 'fcp': fcp, 'wwpn': wwpn, 'lun': lun}
 | 
						|
 | 
						|
    def get_zipl_script_lines(self, image, ramdisk, root, fcp, wwpn, lun):
 | 
						|
        return ['#!/bin/bash\n',
 | 
						|
                ('echo -e "[defaultboot]\\n'
 | 
						|
                 'timeout=5\\n'
 | 
						|
                 'default=boot-from-volume\\n'
 | 
						|
                 'target=/boot/\\n'
 | 
						|
                 '[boot-from-volume]\\n'
 | 
						|
                 'image=%(image)s\\n'
 | 
						|
                 'ramdisk=%(ramdisk)s\\n'
 | 
						|
                 'parameters=\\"root=%(root)s '
 | 
						|
                 'rd_ZFCP=0.0.%(fcp)s,0x%(wwpn)s,0x%(lun)s '
 | 
						|
                 'zfcp.allow_lun_scan=0 selinux=0\\""'
 | 
						|
                 '>/etc/zipl_volume.conf\n'
 | 
						|
                 'zipl -c /etc/zipl_volume.conf')
 | 
						|
                % {'image': image, 'ramdisk': ramdisk, 'root': root,
 | 
						|
                   'fcp': fcp, 'wwpn': wwpn, 'lun': lun}]
 | 
						|
 | 
						|
 | 
						|
class rhel7(rhel):
 | 
						|
    def get_znetconfig_contents(self):
 | 
						|
        return '\n'.join(('cio_ignore -R',
 | 
						|
                          'znetconf -R -n',
 | 
						|
                          'udevadm trigger',
 | 
						|
                          'udevadm settle',
 | 
						|
                          'sleep 2',
 | 
						|
                          'znetconf -A',
 | 
						|
                          'cio_ignore -u'))
 | 
						|
 | 
						|
    def _get_device_filename(self, device_num):
 | 
						|
        # Construct a device like ifcfg-enccw0.0.1000, ifcfg-enccw0.0.1003
 | 
						|
        base = int(CONF.zvm_default_nic_vdev, 16)
 | 
						|
        device = str(hex(base + device_num * 3))[2:]
 | 
						|
        return 'ifcfg-enccw0.0.' + str(device).zfill(4)
 | 
						|
 | 
						|
    def _get_device_name(self, device_num):
 | 
						|
        # Construct a device like enccw0.0.1000, enccw0.0.1003
 | 
						|
        base = int(CONF.zvm_default_nic_vdev, 16)
 | 
						|
        device = str(hex(base + device_num * 3))[2:]
 | 
						|
        return 'enccw0.0.' + str(device).zfill(4)
 | 
						|
 | 
						|
    def get_scp_string(self, root, fcp, wwpn, lun):
 | 
						|
        return ("=root=%(root)s selinux=0 zfcp.allow_lun_scan=0 "
 | 
						|
                "rd.zfcp=0.0.%(fcp)s,0x%(wwpn)s,0x%(lun)s") % {
 | 
						|
                'root': root, 'fcp': fcp, 'wwpn': wwpn, 'lun': lun}
 | 
						|
 | 
						|
    def get_zipl_script_lines(self, image, ramdisk, root, fcp, wwpn, lun):
 | 
						|
        return ['#!/bin/bash\n',
 | 
						|
                ('echo -e "[defaultboot]\\n'
 | 
						|
                 'timeout=5\\n'
 | 
						|
                 'default=boot-from-volume\\n'
 | 
						|
                 'target=/boot/\\n'
 | 
						|
                 '[boot-from-volume]\\n'
 | 
						|
                 'image=%(image)s\\n'
 | 
						|
                 'ramdisk=%(ramdisk)s\\n'
 | 
						|
                 'parameters=\\"root=%(root)s '
 | 
						|
                 'rd.zfcp=0.0.%(fcp)s,0x%(wwpn)s,0x%(lun)s '
 | 
						|
                 'zfcp.allow_lun_scan=0 selinux=0\\""'
 | 
						|
                 '>/etc/zipl_volume.conf\n'
 | 
						|
                 'zipl -c /etc/zipl_volume.conf')
 | 
						|
                % {'image': image, 'ramdisk': ramdisk, 'root': root,
 | 
						|
                   'fcp': fcp, 'wwpn': wwpn, 'lun': lun}]
 | 
						|
 | 
						|
 | 
						|
class sles(LinuxDist):
 | 
						|
    def _get_network_file_path(self):
 | 
						|
        return '/etc/sysconfig/network/'
 | 
						|
 | 
						|
    def _get_cidr_from_ip_netmask(self, ip, netmask):
 | 
						|
        netmask_fields = netmask.split('.')
 | 
						|
        bin_str = ''
 | 
						|
        for octet in netmask_fields:
 | 
						|
            bin_str += bin(int(octet))[2:].zfill(8)
 | 
						|
        mask = str(len(bin_str.rstrip('0')))
 | 
						|
        cidr_v4 = ip + '/' + mask
 | 
						|
        return cidr_v4
 | 
						|
 | 
						|
    def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
 | 
						|
                     netmask_v4, address_read, subchannels):
 | 
						|
        cidr_v4 = self._get_cidr_from_ip_netmask(ip_v4, netmask_v4)
 | 
						|
        cfg_str = "BOOTPROTO=\'static\'\n"
 | 
						|
        cfg_str += "IPADDR=\'%s\'\n" % cidr_v4
 | 
						|
        cfg_str += "BROADCAST=\'%s\'\n" % broadcast_v4
 | 
						|
        cfg_str += "STARTMODE=\'onboot\'\n"
 | 
						|
        cfg_str += ("NAME=\'OSA Express Network card (%s)\'\n" %
 | 
						|
                    address_read)
 | 
						|
        return cfg_str
 | 
						|
 | 
						|
    def _get_route_str(self, gateway_v4):
 | 
						|
        route_str = 'default %s - -\n' % gateway_v4
 | 
						|
        return route_str
 | 
						|
 | 
						|
    def _get_cmd_str(self, address_read, address_write, address_data):
 | 
						|
        cmd_str = 'qeth_configure -l 0.0.%s ' % address_read.lower()
 | 
						|
        cmd_str += '0.0.%(write)s 0.0.%(data)s 1\n' % {'write':
 | 
						|
                address_write.lower(), 'data': address_data.lower()}
 | 
						|
        return cmd_str
 | 
						|
 | 
						|
    def _get_dns_filename(self):
 | 
						|
        return '/etc/resolv.conf'
 | 
						|
 | 
						|
    def _get_device_filename(self, device_num):
 | 
						|
        return 'ifcfg-eth' + str(device_num)
 | 
						|
 | 
						|
    def _get_device_name(self, device_num):
 | 
						|
        return 'eth' + str(device_num)
 | 
						|
 | 
						|
    def _append_udev_info(self, cfg_files, file_name_route, route_cfg_str,
 | 
						|
                          udev_cfg_str):
 | 
						|
        udev_file_name = '/etc/udev/rules.d/70-persistent-net.rules'
 | 
						|
        cfg_files.append((udev_file_name, udev_cfg_str))
 | 
						|
        if len(route_cfg_str) > 0:
 | 
						|
            cfg_files.append((file_name_route, route_cfg_str))
 | 
						|
 | 
						|
    def _get_udev_configuration(self, device, dev_channel):
 | 
						|
        cfg_str = 'SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"qeth\",'
 | 
						|
        cfg_str += ' KERNELS==\"%s\", ATTR{type}==\"1\",' % dev_channel
 | 
						|
        cfg_str += ' KERNEL==\"eth*\", NAME=\"eth%s\"\n' % device
 | 
						|
 | 
						|
        return cfg_str
 | 
						|
 | 
						|
    def get_scp_string(self, root, fcp, wwpn, lun):
 | 
						|
        return ("=root=%(root)s zfcp.allow_lun_scan=0 "
 | 
						|
                "zfcp.device=0.0.%(fcp)s,0x%(wwpn)s,0x%(lun)s") % {
 | 
						|
                'root': root, 'fcp': fcp, 'wwpn': wwpn, 'lun': lun}
 | 
						|
 | 
						|
    def get_zipl_script_lines(self, image, ramdisk, root, fcp, wwpn, lun):
 | 
						|
        return ['#!/bin/bash\n',
 | 
						|
                ('echo -e "[defaultboot]\\n'
 | 
						|
                 'default=boot-from-volume\\n'
 | 
						|
                 '[boot-from-volume]\\n'
 | 
						|
                 'image=%(image)s\\n'
 | 
						|
                 'target = /boot/zipl\\n'
 | 
						|
                 'ramdisk=%(ramdisk)s\\n'
 | 
						|
                 'parameters=\\"root=%(root)s '
 | 
						|
                 'zfcp.device=0.0.%(fcp)s,0x%(wwpn)s,0x%(lun)s '
 | 
						|
                 'zfcp.allow_lun_scan=0\\""'
 | 
						|
                 '>/etc/zipl_volume.conf\n'
 | 
						|
                 'mkinitrd\n'
 | 
						|
                 'zipl -c /etc/zipl_volume.conf')
 | 
						|
                % {'image': image, 'ramdisk': ramdisk, 'root': root,
 | 
						|
                   'fcp': fcp, 'wwpn': wwpn, 'lun': lun}]
 | 
						|
 | 
						|
 | 
						|
class sles11(sles):
 | 
						|
    def get_znetconfig_contents(self):
 | 
						|
        return '\n'.join(('cio_ignore -R',
 | 
						|
                          'znetconf -R -n',
 | 
						|
                          'sleep 2',
 | 
						|
                          'udevadm trigger',
 | 
						|
                          'udevadm settle',
 | 
						|
                          'sleep 2',
 | 
						|
                          'znetconf -A',
 | 
						|
                          'service network restart',
 | 
						|
                          'cio_ignore -u'))
 | 
						|
 | 
						|
    def get_change_passwd_command(self, admin_password):
 | 
						|
        return 'echo %s|passwd --stdin root' % admin_password
 | 
						|
 | 
						|
 | 
						|
class sles12(sles):
 | 
						|
    def get_znetconfig_contents(self):
 | 
						|
        remove_route = 'rm -f %s/ifroute-eth*' % self._get_network_file_path()
 | 
						|
        return '\n'.join(('cio_ignore -R',
 | 
						|
                          'znetconf -R -n',
 | 
						|
                          'sleep 2',
 | 
						|
                          remove_route,
 | 
						|
                          'udevadm trigger',
 | 
						|
                          'udevadm settle',
 | 
						|
                          'sleep 2',
 | 
						|
                          'znetconf -A',
 | 
						|
                          'cio_ignore -u'))
 | 
						|
 | 
						|
    def get_change_passwd_command(self, admin_password):
 | 
						|
        return "echo 'root:%s' | chpasswd" % admin_password
 | 
						|
 | 
						|
 | 
						|
class ubuntu(LinuxDist):
 | 
						|
    def create_network_configuration_files(self, file_path, network_info,
 | 
						|
                                           base_vdev):
 | 
						|
        """Generate network configuration files to instance."""
 | 
						|
        cfg_files = []
 | 
						|
        cmd_strings = ''
 | 
						|
        network_config_file_name = self._get_network_file()
 | 
						|
        network_cfg_str = 'auto lo\n'
 | 
						|
        network_cfg_str += 'iface lo inet loopback\n'
 | 
						|
 | 
						|
        for vif in network_info:
 | 
						|
            network_hw_config_fname = self._get_device_filename(base_vdev)
 | 
						|
            network_hw_config_str = self._get_network_hw_config_str(base_vdev)
 | 
						|
            cfg_files.append((network_hw_config_fname, network_hw_config_str))
 | 
						|
            network = vif['network']
 | 
						|
            (cfg_str, dns_str) = self._generate_network_configuration(network,
 | 
						|
                base_vdev)
 | 
						|
            LOG.debug('Network configure file content is: %s' % cfg_str)
 | 
						|
            network_cfg_str += cfg_str
 | 
						|
            if len(dns_str) > 0:
 | 
						|
                network_cfg_str += dns_str
 | 
						|
            base_vdev = str(hex(int(base_vdev, 16) + 3))[2:]
 | 
						|
        cfg_files.append((network_config_file_name, network_cfg_str))
 | 
						|
        return cfg_files, cmd_strings
 | 
						|
 | 
						|
    def _get_network_file(self):
 | 
						|
        return '/etc/network/interfaces'
 | 
						|
 | 
						|
    def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
 | 
						|
                     netmask_v4):
 | 
						|
        cfg_str = 'auto ' + device + '\n'
 | 
						|
        cfg_str += 'iface ' + device + ' inet static\n'
 | 
						|
        cfg_str += 'address ' + ip_v4 + '\n'
 | 
						|
        cfg_str += 'netmask ' + netmask_v4 + '\n'
 | 
						|
        cfg_str += 'broadcast ' + broadcast_v4 + '\n'
 | 
						|
        cfg_str += 'gateway ' + gateway_v4 + '\n'
 | 
						|
        return cfg_str
 | 
						|
 | 
						|
    def _generate_network_configuration(self, network, vdev):
 | 
						|
        ip_v4 = dns_str = ''
 | 
						|
        subnets_v4 = [s for s in network['subnets'] if s['version'] == 4]
 | 
						|
 | 
						|
        if len(subnets_v4[0]['ips']) > 0:
 | 
						|
            ip_v4 = subnets_v4[0]['ips'][0]['address']
 | 
						|
        if len(subnets_v4[0]['dns']) > 0:
 | 
						|
            for dns in subnets_v4[0]['dns']:
 | 
						|
                dns_str += 'dns-nameservers ' + dns['address'] + '\n'
 | 
						|
        netmask_v4 = str(subnets_v4[0].as_netaddr().netmask)
 | 
						|
        gateway_v4 = subnets_v4[0]['gateway']['address'] or ''
 | 
						|
        broadcast_v4 = str(subnets_v4[0].as_netaddr().broadcast)
 | 
						|
        device = self._get_device_name(vdev)
 | 
						|
        cfg_str = self._get_cfg_str(device, broadcast_v4, gateway_v4,
 | 
						|
                                    ip_v4, netmask_v4)
 | 
						|
        return cfg_str, dns_str
 | 
						|
 | 
						|
    def _get_route_str(self, gateway_v4):
 | 
						|
        return ''
 | 
						|
 | 
						|
    def _get_cmd_str(self, address_read, address_write, address_data):
 | 
						|
        return ''
 | 
						|
 | 
						|
    def _get_device_name(self, device_num):
 | 
						|
        return 'enc' + str(device_num)
 | 
						|
 | 
						|
    def _get_dns_filename(self):
 | 
						|
        return ''
 | 
						|
 | 
						|
    def _get_device_filename(self, device_num):
 | 
						|
        return '/etc/sysconfig/hardware/config-ccw-0.0.' + str(device_num)
 | 
						|
 | 
						|
    def _get_network_hw_config_str(self, base_vdev):
 | 
						|
        ccwgroup_chans_str = ' '.join((
 | 
						|
                            '0.0.' + str(hex(int(base_vdev, 16)))[2:],
 | 
						|
                            '0.0.' + str(hex(int(base_vdev, 16) + 1))[2:],
 | 
						|
                            '0.0.' + str(hex(int(base_vdev, 16) + 2))[2:]))
 | 
						|
        return '\n'.join(('CCWGROUP_CHANS=(' + ccwgroup_chans_str + ')',
 | 
						|
                          'QETH_OPTIONS=layer2'))
 | 
						|
 | 
						|
    def _get_network_file_path(self):
 | 
						|
        pass
 | 
						|
 | 
						|
    def get_znetconfig_contents(self):
 | 
						|
        return '\n'.join(('cio_ignore -R',
 | 
						|
                          'znetconf -R -n',
 | 
						|
                          'sleep 2',
 | 
						|
                          'udevadm trigger',
 | 
						|
                          'udevadm settle',
 | 
						|
                          'sleep 2',
 | 
						|
                          'znetconf -A',
 | 
						|
                          '/etc/init.d/networking restart',
 | 
						|
                          'cio_ignore -u'))
 | 
						|
 | 
						|
    def _get_udev_configuration(self, device, dev_channel):
 | 
						|
        return ''
 | 
						|
 | 
						|
    def _append_udev_info(self, cfg_files, file_name_route, route_cfg_str,
 | 
						|
                          udev_cfg_str):
 | 
						|
        pass
 | 
						|
 | 
						|
    def get_scp_string(self, root, fcp, wwpn, lun):
 | 
						|
        # Although the content is the same as SLES, I don't want to merge them.
 | 
						|
        # Because they are NOT logically related, and it's very likely that
 | 
						|
        # they evolve separately in the future.
 | 
						|
        return ("=root=%(root)s zfcp.allow_lun_scan=0 "
 | 
						|
                "zfcp.device=0.0.%(fcp)s,0x%(wwpn)s,0x%(lun)s") % {
 | 
						|
                'root': root, 'fcp': fcp, 'wwpn': wwpn, 'lun': lun}
 | 
						|
 | 
						|
    def get_zipl_script_lines(self, image, ramdisk, root, fcp, wwpn, lun):
 | 
						|
        return ['#!/bin/bash\n',
 | 
						|
                ('echo -e "[defaultboot]\\n'
 | 
						|
                 'default=boot-from-volume\\n'
 | 
						|
                 '[boot-from-volume]\\n'
 | 
						|
                 'image=%(image)s\\n'
 | 
						|
                 'target = /boot/zipl\\n'
 | 
						|
                 'ramdisk=%(ramdisk)s\\n'
 | 
						|
                 'parameters=\\"root=%(root)s '
 | 
						|
                 'zfcp.device=0.0.%(fcp)s,0x%(wwpn)s,0x%(lun)s '
 | 
						|
                 'zfcp.allow_lun_scan=0\\""'
 | 
						|
                 '>/etc/zipl_volume.conf\n'
 | 
						|
                 'mkinitrd\n'
 | 
						|
                 'zipl -c /etc/zipl_volume.conf')
 | 
						|
                % {'image': image, 'ramdisk': ramdisk, 'root': root,
 | 
						|
                   'fcp': fcp, 'wwpn': wwpn, 'lun': lun}]
 | 
						|
 | 
						|
    def assemble_zfcp_srcdev(self, fcp, wwpn, lun):
 | 
						|
        path = '/dev/disk/by-path/ccw-0.0.%(fcp)s-fc-0x%(wwpn)s-lun-%(lun)s'
 | 
						|
        lun = int(lun[0:4], 16)
 | 
						|
        srcdev = path % {'fcp': fcp, 'wwpn': wwpn, 'lun': lun}
 | 
						|
        return srcdev
 | 
						|
 | 
						|
 | 
						|
class ubuntu16(ubuntu):
 | 
						|
 | 
						|
    def get_change_passwd_command(self, admin_password):
 | 
						|
        return "echo 'root:%s' | chpasswd" % admin_password
 | 
						|
 | 
						|
 | 
						|
class ListDistManager(object):
 | 
						|
    def get_linux_dist(self, os_version):
 | 
						|
        distro, release = self.parse_dist(os_version)
 | 
						|
        return globals()[distro + release]
 | 
						|
 | 
						|
    def _parse_release(self, os_version, distro, remain):
 | 
						|
        supported = {'rhel': ['6', '7'],
 | 
						|
                     'sles': ['11', '12'],
 | 
						|
                     'ubuntu': ['16']}
 | 
						|
        releases = supported[distro]
 | 
						|
 | 
						|
        for r in releases:
 | 
						|
            if remain.startswith(r):
 | 
						|
                return r
 | 
						|
        else:
 | 
						|
            msg = _('Can not handle os: %s') % os_version
 | 
						|
            raise exception.ZVMImageError(msg=msg)
 | 
						|
 | 
						|
    def parse_dist(self, os_version):
 | 
						|
        """Separate os and version from os_version.
 | 
						|
 | 
						|
        Possible return value are only:
 | 
						|
        ('rhel', x.y) and ('sles', x.y) where x.y may not be digits
 | 
						|
        """
 | 
						|
        supported = {'rhel': ['rhel', 'redhat', 'red hat'],
 | 
						|
                    'sles': ['suse', 'sles'],
 | 
						|
                    'ubuntu': ['ubuntu']}
 | 
						|
        os_version = os_version.lower()
 | 
						|
        for distro, patterns in supported.items():
 | 
						|
            for i in patterns:
 | 
						|
                if os_version.startswith(i):
 | 
						|
                    # Not guarrentee the version is digital
 | 
						|
                    remain = os_version.split(i, 2)[1]
 | 
						|
                    release = self._parse_release(os_version, distro, remain)
 | 
						|
                    return distro, release
 | 
						|
 | 
						|
        msg = _('Can not handle os: %s') % os_version
 | 
						|
        raise exception.ZVMImageError(msg=msg)
 |