1let call, 2 vmRef, 3 vmIp, 4 host = window.location.host 5 6function _handleUserError(error) { 7 alert( 8 typeof error === 'object' && !(error instanceof Error) 9 ? JSON.stringify(error, null, 2) 10 : (error && error.message) || error 11 ) 12} 13 14function setStep(previousStep, nextStep) { 15 $(`#${previousStep}`).css({ display: 'none' }) 16 $(`#${nextStep}`).css({ display: 'block' }) 17} 18 19function _jsonRpcCall(url, method, params) { 20 console.log(`-> ${method}(${JSON.stringify(params)})`) 21 return window 22 .fetch(url, { 23 body: JSON.stringify({ 24 id: 0, 25 jsonrpc: '2.0', 26 method, 27 params 28 }), 29 method: 'POST', 30 headers: new Headers({ 31 Accept: 'application/json', 32 'Content-Type': 'application/json' 33 }) 34 }) 35 .then(res => { 36 if (!res.ok) { 37 throw res.status 38 } 39 return res.json().then(json => { 40 if (json.result !== undefined) { 41 console.log(`<- ${JSON.stringify(json.result)}`) 42 return json.result 43 } 44 console.error(`<x ${JSON.stringify(json.error)}`) 45 throw json.error 46 }) 47 }) 48} 49function _call(method, params) { 50 return _jsonRpcCall(`//${host}/jsonrpc`, method, params).catch(error => { 51 if (error && error.message === 'HOST_IS_SLAVE') { 52 console.log('Host is slave, changing host to master', error.data[0]) 53 host = error.data[0] 54 return _call(method, params) 55 } 56 throw error 57 }) 58} 59 60function connect() { 61 $('#connect fieldset').attr('disabled', true) 62 _call('session.login_with_password', [ 63 'root', 64 $('#pwd').val(), 65 '2.3', 66 'XOA deploy' 67 ]) 68 .then(sessionRef => { 69 call = (method, ...params) => _call(method, [sessionRef].concat(params)) 70 }) 71 .then(() => 72 Promise.all([ 73 call('SR.get_all_records'), 74 call('pool.get_all_records'), 75 call('network.get_all_records'), 76 call('PIF.get_all_records') 77 ]) 78 ) 79 .then(([srs, pools, networks, pifs]) => { 80 setStep('connect', 'config') 81 const selectSr = $('#srs') 82 let sr 83 Object.keys(srs).forEach(srRef => { 84 sr = srs[srRef] 85 if (sr.content_type !== 'iso' && sr.physical_size > 0) { 86 selectSr.append( 87 $('<option/>') 88 .val(srRef) 89 .text( 90 `${sr.name_label} - ${Math.round( 91 (sr.physical_size - sr.physical_utilisation) / 92 Math.pow(1024, 3) 93 )} GiB left` 94 ) 95 ) 96 } 97 }) 98 const { default_SR } = pools[Object.keys(pools)[0]] 99 if (default_SR !== undefined) { 100 selectSr.val(default_SR) 101 } 102 const selectNetwork = $('#networks') 103 let network 104 Object.keys(networks).forEach(networkRef => { 105 network = networks[networkRef] 106 selectNetwork.append( 107 $('<option/>') 108 .val(networkRef) 109 .data('mtu', network.MTU) 110 .text(network.name_label) 111 ) 112 }) 113 const managementPif = Object.values(pifs).find(pif => pif.management) 114 if (managementPif && managementPif.network !== undefined) { 115 selectNetwork.val(managementPif.network) 116 } 117 }) 118 .catch(err => { 119 $('#connect fieldset').attr('disabled', false) 120 this._handleUserError(err) 121 }) 122} 123 124function deploy() { 125 const status = text => $('#deploy').text(text) 126 $('i.fa-spinner.fa-pulse').css({ display: 'inherit' }) 127 const srRef = $('#srs').val() 128 status('Deploying XOAâ¦') 129 $('#accounts fieldset').attr('disabled', true) 130 let registrationToken 131 const updaterEmail = $('#updaterEmail').val() 132 const updaterPwd = $('#updaterPwd').val() 133 Promise.resolve() 134 .then(() => { 135 if (updaterEmail && updaterPwd) { 136 return _jsonRpcCall('https://xen-orchestra.com/api', 'registerXoa', { 137 email: updaterEmail, 138 password: updaterPwd 139 }).then(_registrationToken => { 140 registrationToken = _registrationToken 141 }) 142 } 143 }) 144 .then(() => 145 call( 146 'VM.import', 147 'http://xoa.io:8888/', 148 srRef, 149 false, // full_restore 150 false // force 151 ) 152 ) 153 .then(([_vmRef]) => { 154 vmRef = _vmRef 155 status('Configuring XOAâ¦') 156 const promises = [] 157 const ip = $('#ip').val() 158 if (ip) { 159 promises.push( 160 call('VM.add_to_xenstore_data', vmRef, 'vm-data/ip', ip), 161 call( 162 'VM.add_to_xenstore_data', 163 vmRef, 164 'vm-data/netmask', 165 $('#netmask').val() || '255.255.255.0' 166 ), 167 call( 168 'VM.add_to_xenstore_data', 169 vmRef, 170 'vm-data/gateway', 171 $('#gateway').val() || '' 172 ), 173 call( 174 'VM.add_to_xenstore_data', 175 vmRef, 176 'vm-data/dns', 177 $('#dns').val() || '8.8.8.8' 178 ) 179 ) 180 } 181 const email = $('#adminEmail').val() 182 const password = $('#adminPwd').val() 183 if (email && password) { 184 promises.push( 185 call( 186 'VM.add_to_xenstore_data', 187 vmRef, 188 'vm-data/admin-account', 189 JSON.stringify({ email, password }) 190 ) 191 ) 192 } 193 if (registrationToken) { 194 promises.push( 195 call( 196 'VM.add_to_xenstore_data', 197 vmRef, 198 'vm-data/xoa-updater-credentials', 199 JSON.stringify({ email: updaterEmail, registrationToken }) 200 ) 201 ) 202 } 203 const xoaPwd = $('#xoaPwd').val()
204 if (xoaPwd) { 205 promises.push( 206 call( 207 'VM.add_to_xenstore_data', 208 vmRef, 209 'vm-data/system-account-xoa-password', 210 xoaPwd 211 ) 212 ) 213 } 214 promises.push( 215 call( 216 'VM.add_to_xenstore_data', 217 vmRef, 218 'vm-data/xen-servers', 219 JSON.stringify([{ 220 allowUnauthorized: true, 221 host, 222 password: $('#pwd').val(), 223 username: 'root' 224 }]) 225 ) 226 ) 227 228 const network = $('#networks').val() 229 const MTU = $('#networks') 230 .find(':selected') 231 .data('mtu') 232 promises.push( 233 call('VM.get_VIFs', vmRef) 234 .then(([vifRef]) => call('VIF.destroy', vifRef)) 235 .then(() => call('VM.get_allowed_VIF_devices', vmRef)) 236 .then(devices => 237 call('VIF.create', { 238 device: devices[0], 239 MAC: '', 240 MTU, 241 network, 242 other_config: {}, 243 qos_algorithm_params: {}, 244 qos_algorithm_type: '', 245 VM: vmRef 246 }) 247 ) 248 ) 249 250 return Promise.all(promises) 251 }) 252 .then(() => { 253 status('Starting XOAâ¦') 254 return call( 255 'VM.start', 256 vmRef, 257 false, // start_paused 258 false // force 259 ) 260 }) 261 .then(() => call('VM.get_guest_metrics', vmRef)) 262 .then(metricsRef => { 263 status('Almost thereâ¦') 264 let attempts = 120 265 const waitForIp = () => { 266 return call('VM_guest_metrics.get_networks', metricsRef).then( 267 networks => { 268 if (networks && networks['0/ip'] !== undefined) { 269 return networks['0/ip'] 270 } 271 if (attempts-- === 0) { 272 throw 'XOA not responding' 273 } 274 return new Promise((resolve, reject) => 275 setTimeout(() => waitForIp().then(resolve, reject), 1e3) 276 ) 277 } 278 ) 279 } 280 return waitForIp() 281 }) 282 .then(ip => { 283 vmIp = ip 284 return Promise.all( 285 [ 286 'admin-account', 287 'dns', 288 'gateway', 289 'ip', 290 'netmask', 291 'xen-servers', 292 'xoa-updater-credentials' 293 ].map(key => 294 call('VM.remove_from_xenstore_data', vmRef, `vm-data/${key}`) 295 ) 296 ) 297 }) 298 .then(() => { 299 status('XOA is ready! Redirectingâ¦') 300 setTimeout(() => { 301 window.location = `http://${$('#ip').val() || vmIp}` 302 }, 3e3) 303 }) 304 .catch(err => { 305 $('#accounts fieldset').attr('disabled', false) 306 $('i.fa-spinner.fa-pulse').css({ display: 'none' }) 307 status('Deploy') 308 this._handleUserError(err) 309 }) 310}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.