1#!/usr/bin/env python 2# 3# Test ssh image creation 4# 5# Copyright (C) 2018 Red Hat, Inc. 6# 7# Creator/Owner: Kevin Wolf <kwolf@redhat.com> 8# 9# This program is free software; you can redistribute it and/or modify 10# it under the terms of the GNU General Public License as published by 11# the Free Software Foundation; either version 2 of the License, or 12# (at your option) any later version. 13# 14# This program is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17# GNU General Public License for more details. 18# 19# You should have received a copy of the GNU General Public License 20# along with this program. If not, see <http://www.gnu.org/licenses/>. 21# 22 23import iotests 24import subprocess 25import re 26 27iotests.verify_image_format(supported_fmts=['raw']) 28iotests.verify_protocol(supported=['ssh']) 29 30def filter_hash(qmsg): 31 def _filter(key, value): 32 if key == 'hash' and re.match('[0-9a-f]+', value): 33 return 'HASH' 34 return value 35 return iotests.filter_qmp(qmsg, _filter) 36 37def blockdev_create(vm, options): 38 result = vm.qmp_log('blockdev-create', job_id='job0', options=options, 39 filters=[iotests.filter_qmp_testfiles, filter_hash]) 40 41 if 'return' in result: 42 assert result['return'] == {} 43 vm.run_job('job0') 44 iotests.log("") 45 46with iotests.FilePath('t.img') as disk_path, \ 47 iotests.VM() as vm: 48 49 remote_path = iotests.remote_filename(disk_path) 50 51 # 52 # Successful image creation (defaults) 53 # 54 iotests.log("=== Successful image creation (defaults) ===") 55 iotests.log("") 56 57 vm.launch() 58 blockdev_create(vm, { 'driver': 'ssh', 59 'location': { 60 'path': disk_path, 61 'server': { 62 'host': '127.0.0.1', 63 'port': '22' 64 } 65 }, 66 'size': 4194304 }) 67 vm.shutdown() 68 69 iotests.img_info_log(remote_path) 70 iotests.log("") 71 iotests.img_info_log(disk_path) 72 73 # 74 # Test host-key-check options 75 # 76 iotests.log("=== Test host-key-check options ===") 77 iotests.log("") 78 79 vm.launch() 80 blockdev_create(vm, { 'driver': 'ssh', 81 'location': { 82 'path': disk_path, 83 'server': { 84 'host': '127.0.0.1', 85 'port': '22' 86 }, 87 'host-key-check': { 88 'mode': 'none' 89 } 90 }, 91 'size': 8388608 }) 92 vm.shutdown() 93 94 iotests.img_info_log(remote_path) 95 96 vm.launch() 97 blockdev_create(vm, { 'driver': 'ssh', 98 'location': { 99 'path': disk_path, 100 'server': { 101 'host': '127.0.0.1', 102 'port': '22' 103 }, 104 'host-key-check': { 105 'mode': 'known_hosts' 106 } 107 }, 108 'size': 4194304 }) 109 vm.shutdown() 110 111 iotests.img_info_log(remote_path) 112 113 keys = subprocess.check_output( 114 'ssh-keyscan 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + 115 'cut -d" " -f3', 116 shell=True).rstrip().decode('ascii').split('\n') 117 118 # Mappings of base64 representations to digests 119 md5_keys = {} 120 sha1_keys = {} 121 122 for key in keys: 123 md5_keys[key] = subprocess.check_output( 124 'echo %s | base64 -d | md5sum -b | cut -d" " -f1' % key, 125 shell=True).rstrip().decode('ascii') 126 127 sha1_keys[key] = subprocess.check_output( 128 'echo %s | base64 -d | sha1sum -b | cut -d" " -f1' % key, 129 shell=True).rstrip().decode('ascii') 130 131 vm.launch() 132 133 # Find correct key first 134 matching_key = None 135 for key in keys: 136 result = vm.qmp('blockdev-add', 137 driver='ssh', node_name='node0', path=disk_path, 138 server={ 139 'host': '127.0.0.1', 140 'port': '22', 141 }, host_key_check={ 142 'mode': 'hash', 143 'type': 'md5', 144 'hash': md5_keys[key], 145 }) 146 147 if 'error' not in result: 148 vm.qmp('blockdev-del', node_name='node0') 149 matching_key = key 150 break 151 152 if matching_key is None: 153 vm.shutdown() 154 iotests.notrun('Did not find a key that fits 127.0.0.1') 155 156 blockdev_create(vm, { 'driver': 'ssh', 157 'location': { 158 'path': disk_path, 159 'server': { 160 'host': '127.0.0.1', 161 'port': '22' 162 }, 163 'host-key-check': { 164 'mode': 'hash', 165 'type': 'md5', 166 'hash': 'wrong', 167 } 168 }, 169 'size': 2097152 }) 170 blockdev_create(vm, { 'driver': 'ssh', 171 'location': { 172 'path': disk_path, 173 'server': { 174 'host': '127.0.0.1', 175 'port': '22' 176 }, 177 'host-key-check': { 178 'mode': 'hash', 179 'type': 'md5', 180 'hash': md5_keys[matching_key], 181 } 182 }, 183 'size': 8388608 }) 184 vm.shutdown() 185 186 iotests.img_info_log(remote_path) 187 188 vm.launch() 189 blockdev_create(vm, { 'driver': 'ssh', 190 'location': { 191 'path': disk_path, 192 'server': { 193 'host': '127.0.0.1', 194 'port': '22' 195 }, 196 'host-key-check': { 197 'mode': 'hash', 198 'type': 'sha1', 199 'hash': 'wrong', 200 } 201 }, 202 'size': 2097152 }) 203 blockdev_create(vm, { 'driver': 'ssh', 204 'location': { 205 'path': disk_path, 206 'server': { 207 'host': '127.0.0.1', 208 'port': '22' 209 }, 210 'host-key-check': { 211 'mode': 'hash', 212 'type': 'sha1', 213 'hash': sha1_keys[matching_key], 214 } 215 }, 216 'size': 4194304 }) 217 vm.shutdown() 218 219 iotests.img_info_log(remote_path) 220 221 # 222 # Invalid path and user 223 # 224 iotests.log("=== Invalid path and user ===") 225 iotests.log("") 226 227 vm.launch() 228 blockdev_create(vm, { 'driver': 'ssh', 229 'location': { 230 'path': '/this/is/not/an/existing/path', 231 'server': { 232 'host': '127.0.0.1', 233 'port': '22' 234 }, 235 'host-key-check': { 236 'mode': 'none' 237 } 238 }, 239 'size': 4194304 }) 240 blockdev_create(vm, { 'driver': 'ssh', 241 'location': { 242 'path': disk_path, 243 'user': 'invalid user', 244 'server': { 245 'host': '127.0.0.1', 246 'port': '22' 247 }, 248 'host-key-check': { 249 'mode': 'none' 250 } 251 }, 252 'size': 4194304 }) 253 vm.shutdown() 254