Created
August 2, 2015 18:37
-
-
Save phaus/616c8f9fbf24f85168ee to your computer and use it in GitHub Desktop.
snippets for https://github.com/joyent/sdc-docker/issues/48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"execution": "failed", | |
"chain_results": [ | |
{ | |
"result": "All parameters OK!", | |
"error": "", | |
"name": "common.validate_params", | |
"started_at": "2015-08-02T18:16:48.867Z", | |
"finished_at": "2015-08-02T18:16:48.871Z" | |
}, | |
{ | |
"result": "Action set", | |
"error": "", | |
"name": "workflow.set_job_action", | |
"started_at": "2015-08-02T18:16:48.897Z", | |
"finished_at": "2015-08-02T18:16:48.901Z" | |
}, | |
{ | |
"result": "Image has generate_passwords=true but no users found", | |
"error": "", | |
"name": "imgapi.generate_passwords", | |
"started_at": "2015-08-02T18:16:48.932Z", | |
"finished_at": "2015-08-02T18:16:48.936Z" | |
}, | |
{ | |
"result": "Networks are valid", | |
"error": "", | |
"name": "napi.validate_networks", | |
"started_at": "2015-08-02T18:16:48.962Z", | |
"finished_at": "2015-08-02T18:16:48.977Z" | |
}, | |
{ | |
"result": "OK", | |
"error": "", | |
"name": "cnapi.check_manual_server_nics", | |
"started_at": "2015-08-02T18:16:49.003Z", | |
"finished_at": "2015-08-02T18:16:49.009Z" | |
}, | |
{ | |
"result": "OK", | |
"error": "", | |
"name": "dapi.get_allocation_ticket", | |
"started_at": "2015-08-02T18:16:49.035Z", | |
"finished_at": "2015-08-02T18:16:49.084Z" | |
}, | |
{ | |
"result": "OK", | |
"error": "", | |
"name": "dapi.wait_allocation_ticket", | |
"started_at": "2015-08-02T18:16:49.111Z", | |
"finished_at": "2015-08-02T18:16:49.116Z" | |
}, | |
{ | |
"result": "", | |
"error": { | |
"message": "No compute resources available", | |
"statusCode": 409, | |
"body": { | |
"code": "NoAllocatableServersError", | |
"message": "No compute resources available" | |
}, | |
"restCode": "NoAllocatableServersError", | |
"name": "NoAllocatableServersError" | |
}, | |
"name": "dapi.get_allocation", | |
"started_at": "2015-08-02T18:16:49.143Z", | |
"finished_at": "2015-08-02T18:16:49.167Z" | |
} | |
], | |
"params": { | |
"firewall_enabled": true, | |
"owner_uuid": "4a8de98d-20c2-4db4-a4d9-69b23e687d99", | |
"hostname": "ff8da53202cd", | |
"alias": "hungry_sammet", | |
"internal_metadata": { | |
"docker:id": "ff8da53202cd42f592ab071d763b308a65a837d6952c45169d7999fe11c78624", | |
"docker:attach_stdout": true, | |
"docker:attach_stderr": true, | |
"docker:noipmgmtd": true, | |
"docker:cmd": "[]", | |
"docker:entrypoint": "[\"bin/2fact-demo\"]", | |
"docker:env": "[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"LANG=C.UTF-8\",\"JAVA_VERSION=8u45\",\"JAVA_DEBIAN_VERSION=8u45-b14-2~bpo8+2\",\"CA_CERTIFICATES_JAVA_VERSION=20140324\"]", | |
"docker:workdir": "/opt/docker", | |
"docker:user": "daemon", | |
"docker:linkHosts": "", | |
"docker:linkEnv": "[]" | |
}, | |
"tags": { | |
"sdc_docker": true | |
}, | |
"autoboot": false, | |
"docker": true, | |
"restart_init": false, | |
"tmpfs": 0, | |
"filesystems": [ | |
], | |
"networks": [ | |
{ | |
"primary": true, | |
"ipv4_uuid": "37801ade-a5b8-4343-8ccb-4eb3ba1a59a8", | |
"ipv4_count": 1, | |
"uuid": "37801ade-a5b8-4343-8ccb-4eb3ba1a59a8" | |
} | |
], | |
"billing_id": "e8e519e8-99f1-6e85-8f25-85a0956a6115", | |
"image_uuid": "f95df90f-892d-84f5-faa9-5409d8603709", | |
"brand": "lx", | |
"init_name": "/native/usr/vm/sbin/dockerinit", | |
"kernel_version": "3.13.0", | |
"firewall_rules": [ | |
{ | |
"enabled": true, | |
"owner_uuid": "4a8de98d-20c2-4db4-a4d9-69b23e687d99", | |
"rule": "FROM tag sdc_docker TO tag sdc_docker ALLOW tcp PORT all", | |
"uuid": "477a7a8c-73a8-47a6-8a68-a6253acf7d6a", | |
"version": "1438525968989.010367" | |
}, | |
{ | |
"enabled": true, | |
"owner_uuid": "4a8de98d-20c2-4db4-a4d9-69b23e687d99", | |
"rule": "FROM tag sdc_docker TO tag sdc_docker ALLOW udp PORT all", | |
"uuid": "60f5f551-2b35-4d1a-9940-8440192b7fc3", | |
"version": "1438525969000.010367" | |
} | |
], | |
"sync": true, | |
"server_uuid": "", | |
"cpu_cap": 100, | |
"max_lwps": 4000, | |
"max_physical_memory": 1024, | |
"max_swap": 4096, | |
"quota": 25, | |
"zfs_io_priority": 64, | |
"ram": 1024, | |
"cpu_shares": 64, | |
"package": { | |
"name": "sample-1G", | |
"version": "1.0.0", | |
"active": true, | |
"cpu_cap": 100, | |
"max_lwps": 4000, | |
"max_physical_memory": 1024, | |
"max_swap": 4096, | |
"quota": 25600, | |
"zfs_io_priority": 64, | |
"fss": 64, | |
"billing_tag": "sample-1G", | |
"uuid": "e8e519e8-99f1-6e85-8f25-85a0956a6115", | |
"created_at": "2015-08-02T12:47:12.486Z", | |
"updated_at": "2015-08-02T12:47:12.486Z", | |
"default": true, | |
"v": 1 | |
}, | |
"image": { | |
"v": 2, | |
"uuid": "f95df90f-892d-84f5-faa9-5409d8603709", | |
"owner": "930896af-bf8c-48d4-885c-6573a94b1853", | |
"name": "docker-layer", | |
"version": "e85de6baa069", | |
"state": "active", | |
"disabled": false, | |
"public": false, | |
"published_at": "2015-07-01T15:53:22.452Z", | |
"type": "docker", | |
"os": "linux", | |
"files": [ | |
{ | |
"sha1": "96e379fb98bd1b401c6ee52230c11d38251572cf", | |
"size": 32, | |
"compression": "none" | |
} | |
], | |
"description": "/bin/sh -c #(nop) CMD []", | |
"origin": "6288563b-cb30-d505-a4dc-82022a905dd6", | |
"tags": { | |
"docker:repo": "phaus/2fact-demo", | |
"docker:id": "e85de6baa06978980ebf0d432a331d050f3a6276acdd2ea6dd2762c0dd2229a0", | |
"docker:architecture": "amd64", | |
"docker:config": { | |
"Cmd": [ | |
], | |
"Entrypoint": [ | |
"bin/2fact-demo" | |
], | |
"Env": [ | |
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", | |
"LANG=C.UTF-8", | |
"JAVA_VERSION=8u45", | |
"JAVA_DEBIAN_VERSION=8u45-b14-2~bpo8+2", | |
"CA_CERTIFICATES_JAVA_VERSION=20140324" | |
], | |
"WorkingDir": "/opt/docker" | |
} | |
} | |
}, | |
"sdc_nat_pool": "f0145ce1-8e5a-457a-8298-5cc80d62b00c", | |
"task": "provision", | |
"vm_uuid": "ff8da532-02cd-42f5-92ab-071d763b308a", | |
"current_state": "provisioning", | |
"x-request-id": "d9b72ee5-ae60-4c81-ad93-08b533acd4c1" | |
}, | |
"image_uuid": "f95df90f-892d-84f5-faa9-5409d8603709", | |
"server_uuid": "", | |
"task": "provision", | |
"target": "/provision-ff8da532-02cd-42f5-92ab-071d763b308a", | |
"vm_uuid": "ff8da532-02cd-42f5-92ab-071d763b308a", | |
"workflow": "9acfaa62-47ae-4638-85b2-ce4daf619e74", | |
"exec_after": null, | |
"num_attempts": 0, | |
"name": "provision-7.2.5", | |
"version": "7.2.5", | |
"timeout": 3810, | |
"workflow_uuid": "9acfaa62-47ae-4638-85b2-ce4daf619e74", | |
"created_at": "2015-08-02T18:16:48.635Z", | |
"onerror_results": [ | |
{ | |
"result": "No NICs were provisioned", | |
"error": "", | |
"name": "napi.cleanup_nics", | |
"started_at": "2015-08-02T18:16:49.193Z", | |
"finished_at": "2015-08-02T18:16:49.197Z" | |
}, | |
{ | |
"result": "Set post back state as failed", | |
"error": "", | |
"name": "set_post_back_failed", | |
"started_at": "2015-08-02T18:16:49.224Z", | |
"finished_at": "2015-08-02T18:16:49.228Z" | |
}, | |
{ | |
"result": "Posted job results back to specified URLs", | |
"error": "", | |
"name": "common.post_back", | |
"started_at": "2015-08-02T18:16:49.254Z", | |
"finished_at": "2015-08-02T18:16:49.280Z" | |
}, | |
{ | |
"result": "OK", | |
"error": "", | |
"name": "cnapi.cleanup_allocation_ticket", | |
"started_at": "2015-08-02T18:16:49.309Z", | |
"finished_at": "2015-08-02T18:16:49.331Z" | |
}, | |
{ | |
"result": "OK", | |
"error": "", | |
"name": "cnapi.cleanup_vm_ticket", | |
"started_at": "2015-08-02T18:16:49.357Z", | |
"finished_at": "2015-08-02T18:16:49.361Z" | |
}, | |
{ | |
"result": "No ticket to release", | |
"error": "", | |
"name": "cnapi.release_fabric_nat_ticket", | |
"started_at": "2015-08-02T18:16:49.399Z", | |
"finished_at": "2015-08-02T18:16:49.404Z" | |
}, | |
{ | |
"result": "", | |
"error": "Error executing job", | |
"name": "On error", | |
"started_at": "2015-08-02T18:16:49.431Z", | |
"finished_at": "2015-08-02T18:16:49.436Z" | |
} | |
], | |
"oncancel_results": [ | |
], | |
"started": 1438539408867, | |
"action": "provision", | |
"nicTags": "[\"sdc_overlay\"]", | |
"allocationTicket": "{\"uuid\":\"90ef150f-d7a3-4cce-b846-794d4ac5131f\",\"server_uuid\":\"34393433-3239-435a-3230-323738504237\",\"scope\":\"vm-allocate\",\"id\":\"global\",\"expires_at\":\"2015-08-02T18:17:49.055Z\",\"created_at\":\"2015-08-02T18:16:49.064Z\",\"updated_at\":\"2015-08-02T18:16:49.064Z\",\"status\":\"active\",\"action\":\"allocate\",\"extra\":{}}", | |
"postBackState": "failed", | |
"elapsed": 0.599, | |
"uuid": "23cdfd31-7556-4484-911a-c2e2ab3e1171", | |
"chain": [ | |
{ | |
"name": "common.validate_params", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function validateParams(job, cb) {\n if (napiUrl === undefined) {\n return cb('No NAPI parameters provided');\n }\n\n if (ufdsUrl === undefined || ufdsDn === undefined ||\n ufdsPassword === undefined) {\n return cb('No UFDS parameters provided');\n }\n\n if (cnapiUrl === undefined) {\n return cb('No CNAPI URL provided');\n }\n\n if (fwapiUrl === undefined) {\n return cb('No FWAPI URL provided');\n }\n\n if (imgapiUrl === undefined) {\n return cb('No IMGAPI URL provided');\n }\n\n if (sapiUrl === undefined) {\n return cb('No SAPI URL provided');\n }\n\n if (job.params['owner_uuid'] === undefined) {\n return cb('\\'owner_uuid\\' is required');\n }\n\n if (job.params.brand === undefined) {\n return cb('VM \\'brand\\' is required');\n }\n\n return cb(null, 'All parameters OK!');\n}" | |
}, | |
{ | |
"name": "workflow.set_job_action", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function setJobAction(job, cb) {\n job.action = 'provision';\n return cb(null, 'Action set');\n}", | |
"modules": { | |
} | |
}, | |
{ | |
"name": "imgapi.generate_passwords", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function generatePasswords(job, cb) {\n var log = job.log;\n var execFile = childProcess.execFile;\n var PWD_LENGTH = 12;\n var APG_COMMAND = '/opt/local/bin/apg';\n var APG_ARGS = [\n '-m', PWD_LENGTH,\n '-M', 'SCNL',\n '-n', 1,\n '-E', '\"\\'@$%&*/.:[]\\\\'\n ];\n\n if (job.params.image['generate_passwords'] === false) {\n return cb(null, 'No need to generate passwords for image');\n }\n\n if (job.params.image.users === undefined ||\n !Array.isArray(job.params.image.users)) {\n return cb(null, 'Image has generate_passwords=true but no users found');\n }\n\n if (job.params['internal_metadata'] === undefined) {\n job.params['internal_metadata'] = {};\n }\n\n var users = job.params.image.users;\n var name;\n var password;\n\n async.mapSeries(users, function (user, next) {\n name = user.name + '_pw';\n if (job.params['internal_metadata'][name] === undefined) {\n execFile(APG_COMMAND, APG_ARGS, function (err, stdout, stderr) {\n if (err) {\n log.info({ err: err }, 'Error generating random password');\n return next(err);\n }\n\n password = stdout.toString().replace(/\\n|\\r/g, '');\n job.params['internal_metadata'][name] = password;\n return next();\n });\n } else {\n return next();\n }\n }, function (err) {\n if (err) {\n cb(err, 'Could not generate passwords');\n } else {\n cb(null, 'Passwords generated for Image');\n }\n });\n}", | |
"modules": { | |
"childProcess": "child_process", | |
"async": "async" | |
} | |
}, | |
{ | |
"name": "napi.validate_networks", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function validateNetworks(job, cb) {\n var networks = job.params.networks;\n\n // add-nics also calls this function, but if macs are provided we don't\n // necessarily need to progress further\n if (job.params.macs && !networks) {\n return cb();\n }\n\n var newNetworks = [];\n if (!networks) {\n return cb('Networks are required');\n }\n\n var napi = new sdcClients.NAPI({\n url: napiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n job.nicTags = [];\n\n // - Resolve network names to uuids when applicable\n // - Repopulate job.params.networks\n // - Returns cb(err, uuid). uuid is present when name was resolved to uuid\n function getNetwork(netId, callback) {\n /*JSSTYLED*/\n var UUID_RE = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;\n var netFn, poolFn;\n var params;\n\n // Network can be either by name or uuid\n if (UUID_RE.test(netId)) {\n params = netId;\n netFn = napi.getNetwork;\n poolFn = napi.getNetworkPool;\n } else {\n params = { name: netId };\n netFn = napi.listNetworks;\n poolFn = napi.listNetworkPools;\n }\n\n netFn.call(napi, params, function (err, nets) {\n // If network is not found then it might be a network pool\n if (err && err.name !== 'ResourceNotFoundError') {\n return callback(err);\n }\n\n // Did we get the network from list or get?\n var net = (Array.isArray(nets) ? nets[0] : nets);\n // No net if NAPI returns an empty array or if we got a 404\n if (net) {\n job.nicTags.push(net.nic_tag);\n return callback(null, net.uuid);\n }\n\n // We might be trying to provision on a network pool, so\n // try that instead\n poolFn.call(napi, params, function (err2, pools) {\n if (err2) {\n return callback(err2);\n }\n\n // NAPI-121: listNetworkPools should accept a name\n if (Array.isArray(pools)) {\n pools = pools.filter(function (pool) {\n return pool.name === netId;\n });\n if (pools.length) {\n job.nicTags.push(pools[0].nic_tag);\n callback(null, pools[0].uuid);\n } else {\n callback(new Error('No such Network Pool with ' +\n 'name: ' + netId));\n }\n } else {\n job.nicTags.push(pools.nic_tag);\n callback(null, pools.uuid);\n }\n });\n });\n }\n\n async.mapSeries(networks, function (network, next) {\n var netId;\n if (network.ipv4_uuid !== undefined) {\n netId = network.ipv4_uuid;\n } else if (network.name !== undefined) {\n netId = network.name;\n }\n\n getNetwork(netId, function (err, uuid) {\n if (err) {\n next(err);\n } else {\n network.uuid = uuid;\n network.ipv4_uuid = uuid;\n newNetworks.push(network);\n next();\n }\n });\n\n }, function (err2) {\n if (err2) {\n cb(err2);\n } else {\n job.params.networks = newNetworks;\n job.log.info({ nicTags: job.nicTags }, 'NIC Tags retrieved');\n cb(null, 'Networks are valid');\n }\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients", | |
"async": "async" | |
} | |
}, | |
{ | |
"name": "cnapi.check_manual_server_nics", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function checkManualServerNics(job, cb) {\n var serverUuid = job.params['server_uuid'];\n\n if (!serverUuid) {\n return cb();\n }\n\n var headers = { 'x-request-id': job.params['x-request-id'] };\n var cnapi = new sdcClients.CNAPI({ url: cnapiUrl, headers: headers });\n\n return cnapi.getServer(serverUuid, function (err, server) {\n if (err) {\n return cb(err);\n }\n\n var nicTags = job.nicTags;\n var interfaces = server.sysinfo['Network Interfaces'];\n var found = 0;\n var vnics = server.sysinfo['Virtual Network Interfaces'] || {};\n\n Object.keys(interfaces).forEach(function (iname) {\n var serverTags = interfaces[iname]['NIC Names'];\n\n for (var i = 0; i < nicTags.length; i++) {\n if (serverTags.indexOf(nicTags[i]) !== -1) {\n found++;\n }\n }\n });\n\n Object.keys(vnics).forEach(function (iname) {\n var serverTags = vnics[iname]['Overlay Nic Tags'] || [];\n\n for (var i = 0; i < nicTags.length; i++) {\n if (serverTags.indexOf(nicTags[i]) !== -1) {\n found++;\n }\n }\n });\n\n if (found == nicTags.length) {\n return cb(null, 'Manual server meets NIC Tag requirements');\n } else {\n job.log.info({\n nicTags: nicTags,\n found: found,\n interfaces: interfaces,\n vnics: vnics\n }, 'Missing manual server nic tags');\n return cb('Manual server does not meet NIC Tag requirements');\n }\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "dapi.get_allocation_ticket", | |
"timeout": 30, | |
"retry": 1, | |
"body": "function acquireAllocationTicket(job, cb) {\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n // Find the headnode\n cnapi.listServers({ headnode: true }, function (err, headnodes) {\n if (err) {\n cb(err);\n return;\n }\n\n if (!headnodes || !headnodes.length) {\n cb(new Error('no headnodes returned'));\n return;\n }\n\n var newTicket = {\n scope: 'vm-allocate',\n id: 'global',\n expires_at: (new Date(\n Date.now() + 60 * 1000).toISOString()),\n action: 'allocate',\n workflow_job_uuid: job.uuid\n };\n\n cnapi.waitlistTicketCreate(headnodes[0].uuid, newTicket, onCreate);\n });\n\n\n function onCreate(err, ticket) {\n if (err) {\n cb(err);\n return;\n }\n\n cnapi.waitlistTicketGet(\n ticket.uuid, function (geterr, getticket)\n {\n if (geterr) {\n cb(geterr);\n return;\n }\n job.allocationTicket = getticket;\n cb();\n });\n }\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "dapi.wait_allocation_ticket", | |
"timeout": 120, | |
"retry": 1, | |
"body": "function waitOnAllocationTicket(job, cb) {\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n var allocationTicket = job.allocationTicket;\n\n if (allocationTicket.status === 'active') {\n return cb();\n }\n\n cnapi.waitlistTicketWait(allocationTicket.uuid, cb);\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "dapi.get_allocation", | |
"timeout": 30, | |
"retry": 1, | |
"body": "function getAllocation(job, cb) {\n var nicTags = job.nicTags;\n var pkg = job.params.package;\n var img = job.params.image;\n\n if (!nicTags) {\n return cb('NIC tags are required');\n }\n\n if (!img) {\n return cb('Image is required');\n }\n\n if (job.params['server_uuid']) {\n cb(null, 'Server UUID present, no need to get allocation from DAPI');\n return;\n }\n\n // There is no sdc-client for CNAPI's DAPI yet\n var cnapi = restify.createJsonClient({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n var payload = {\n vm: job.params,\n image: img,\n package: pkg,\n nic_tags: nicTags\n };\n\n job.log.info({ dapiPayload: payload }, 'Payload sent to DAPI');\n\n return cnapi.post('/allocate', payload, function (err, req, res, body) {\n if (err) {\n return cb(err);\n }\n\n job.params['server_uuid'] = body.server.uuid;\n job.params.imgapiPeers = body.imgapiPeers;\n job.server_uuid = body.server.uuid;\n return cb(null, 'VM allocated to Server ' + body.server.uuid);\n });\n}", | |
"modules": { | |
"restify": "restify" | |
} | |
}, | |
{ | |
"name": "cnapi.acquire_vm_ticket", | |
"timeout": 30, | |
"retry": 1, | |
"body": "function acquireVMTicket(job, cb) {\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n var server_uuid = job.params.server_uuid;\n var newTicket = {\n scope: 'vm',\n id: job.params.vm_uuid,\n expires_at: (new Date(\n Date.now() + 600 * 1000).toISOString()),\n action: job.action\n };\n\n if (job.action === 'provision') {\n newTicket.extra = {\n workflow_job_uuid: job.uuid,\n owner_uuid: job.params.owner_uuid,\n max_physical_memory: job.params.max_physical_memory,\n cpu_cap: job.params.cpu_cap,\n quota: job.params.quota,\n brand: job.params.brand\n };\n\n if (job.params.brand === 'kvm' && job.params.image) {\n newTicket.extra.image_size = job.params.image.image_size;\n }\n }\n\n cnapi.waitlistTicketCreate(server_uuid, newTicket, onCreate);\n\n function onCreate(err, ticket) {\n if (err) {\n cb(err);\n return;\n }\n\n // look up ticket, ensure it's not expired etc\n cnapi.waitlistTicketGet(ticket.uuid,\n function (geterr, getticket) {\n if (geterr) {\n cb(geterr);\n return;\n }\n job.ticket = getticket;\n job.log.info(\n { ticket: getticket }, 'ticket status after wait');\n cb();\n });\n }\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "dapi.release_allocation_ticket", | |
"timeout": 30, | |
"retry": 1, | |
"body": "function releaseAllocationTicket(job, cb) {\n if (!job.allocationTicket) {\n return cb();\n }\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n cnapi.waitlistTicketRelease(job.allocationTicket.uuid, function (err) {\n if (err) {\n job.log.warn({err: err, ticket: job.ticket},\n 'error releasing CNAPI waitlist allocation ticket');\n return;\n }\n cb();\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "cnapi.wait_on_vm_ticket", | |
"timeout": 120, | |
"retry": 1, | |
"body": "function waitOnVMTicket(job, cb) {\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n var ticket = job.ticket;\n\n if (ticket.status === 'active') {\n cb();\n return;\n }\n cnapi.waitlistTicketWait(job.ticket.uuid, cb);\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "napi.provision_nics", | |
"timeout": 20, | |
"retry": 1, | |
"body": "function provisionNics(job, cb) {\n var networks = job.params.networks;\n if (networks === undefined) {\n cb('Networks are required');\n return;\n }\n\n var napi = new sdcClients.NAPI({\n url: napiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n // Every NIC we provision is added to this array\n var nics = [];\n var primaryFound = false;\n job.params.fabricNatNics = [];\n\n networks.forEach(function (net) {\n if (net.primary)\n primaryFound = true;\n // Make absolutely sure we're never overriding NAPI's network\n // owner checks:\n delete net.check_owner;\n });\n\n if (!primaryFound && networks.length > 0)\n networks[0].primary = true;\n\n // Return a new copy for every time we provision a new NIC and avoid\n // accidentally reusing an object\n function nicParams() {\n return {\n owner_uuid: job.params.owner_uuid,\n belongs_to_uuid: job.params.uuid || job.params.vm_uuid,\n belongs_to_type: 'zone'\n };\n }\n\n // If this is a nic on a fabric, has no gateway provisioned, and the network\n // requests an internet NAT, add it\n function addFabricNatNic(fNic) {\n if (fNic && fNic.fabric && fNic.gateway && !fNic.gateway_provisioned &&\n fNic.ip !== fNic.gateway && fNic.internet_nat) {\n job.params.fabricNatNics.push(fNic);\n }\n }\n\n // Get current list of NICs that might have been provisioned ahead of time\n napi.listNics(nicParams(), function (err, res) {\n if (err) {\n cb(err);\n return;\n }\n return asyncProvisionNics(res);\n });\n\n function asyncProvisionNics(currentNics) {\n async.mapSeries(networks, function (network, next) {\n // If there is at least one provisioned NIC in one of the networks\n // provided, skip napi.provisionNic for this network\n var netNics = currentNics.filter(function (nic) {\n return (nic.network_uuid && nic.network_uuid ===\n network.ipv4_uuid);\n });\n\n if (netNics.length > 0) {\n nics = nics.concat(netNics);\n next();\n return;\n }\n\n var antiSpoofParams = ['allow_dhcp_spoofing', 'allow_ip_spoofing',\n 'allow_mac_spoofing', 'allow_restricted_traffic'];\n var params = nicParams();\n params.cn_uuid = job.params.server_uuid;\n if (network.ipv4_ips !== undefined)\n params.ip = network.ipv4_ips[0];\n if (network.primary !== undefined)\n params.primary = network.primary;\n\n antiSpoofParams.forEach(function (spoofParam) {\n if (network.hasOwnProperty(spoofParam)) {\n params[spoofParam] = network[spoofParam];\n }\n });\n\n napi.provisionNic(network.ipv4_uuid, params,\n function (suberr, nic) {\n if (suberr) {\n next(suberr);\n } else {\n nics.push(nic);\n addFabricNatNic(nic);\n next();\n }\n });\n }, function (err2) {\n if (err2) {\n cb(err2);\n } else {\n job.params.nics = nics;\n job.log.info({ nics: job.params.nics }, 'NICs allocated');\n\n cb(null, 'NICs allocated');\n }\n });\n }\n}", | |
"modules": { | |
"sdcClients": "sdc-clients", | |
"async": "async" | |
} | |
}, | |
{ | |
"name": "cnapi.acquire_fabric_nat_tickets", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function acquireFabricTickets(job, cb) {\n if (!job.params.fabricNatNics || job.params.fabricNatNics.length === 0) {\n return cb(null, 'No fabric NATs to provision');\n }\n\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n var nics = [];\n var netuuids = [];\n\n job.params.fabricNatTickets = [];\n\n // Uniquify, just in case\n for (var n in job.params.fabricNatNics) {\n if (netuuids.indexOf(job.params.fabricNatNics[n].network_uuid) === -1) {\n nics.push(job.params.fabricNatNics[n]);\n netuuids.push(job.params.fabricNatNics[n].network_uuid);\n }\n }\n\n cnapi.listServers({ headnode: true }, function (listErr, cns) {\n if (listErr) {\n cb(listErr);\n return;\n }\n\n if (!cns || cns.length === 0) {\n cb(new Error('Headnode not found in CNAPI'));\n return;\n }\n\n if (cns.length > 1) {\n job.params.headnodes = cns;\n cb(new Error('More than 1 headnode found in CNAPI'));\n return;\n }\n\n async.mapSeries(nics, function (nic, next) {\n var newTicket = {\n scope: 'fabric_nat',\n id: nic.network_uuid,\n expires_at: (new Date(\n Date.now() + 600 * 1000).toISOString())\n };\n\n cnapi.waitlistTicketCreate(cns[0].uuid, newTicket, onCreate);\n\n function onCreate(err, ticket) {\n if (err) {\n next(err);\n return;\n }\n\n // look up ticket, ensure it's not expired or invalid\n cnapi.waitlistTicketGet(ticket.uuid,\n function (geterr, getticket) {\n if (geterr) {\n next(geterr);\n return;\n }\n\n job.params.fabricNatTickets.push({\n nic: nic,\n ticket: getticket\n });\n job.log.info(\n { nic: nic, ticket: getticket },\n 'ticket status after create');\n next();\n });\n }\n }, function (sErr) {\n if (sErr) {\n cb(sErr);\n } else {\n cb(null, 'Fabric nat tickets acquired');\n }\n });\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients", | |
"async": "async" | |
} | |
}, | |
{ | |
"name": "napi.provision_fabric_nats", | |
"timeout": 120, | |
"retry": 1, | |
"body": "function provisionFabricNats(job, cb) {\n if (!job.params.fabricNatTickets ||\n job.params.fabricNatTickets.length === 0) {\n return cb(null, 'No fabric NATs to provision');\n }\n\n if (!job.params.sdc_nat_pool) {\n return cb(null, 'No fabric NAT pool configured for provisioning');\n }\n\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n var napi = new sdcClients.NAPI({\n url: napiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n var natSvc;\n var sapi = new sdcClients.SAPI({\n log: job.log.child({ component: 'sapi' }),\n url: sapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n function releaseTicket(tErr, ticket, tCb) {\n cnapi.waitlistTicketRelease(ticket.uuid, function (relErr) {\n if (relErr) {\n job.log.error({ ticket: ticket, err: relErr },\n 'Error releasing ticket');\n }\n\n if (tErr) {\n tCb(tErr);\n return;\n }\n\n tCb(relErr);\n return;\n });\n }\n\n /*\n * Provision a new NAT zone through SAPI on two networks:\n * - the configured NAT network pool\n * - the fabric network that needs a NAT zone\n */\n function provisionNatZone(tick, done) {\n var fabricNic = tick.nic;\n\n // If we were waiting on a ticket because another NAT zone was being\n // provisioned and it succeeded, we don't need to provision another.\n napi.getNetwork(fabricNic.network_uuid, function (netErr, fNet) {\n if (netErr) {\n return done(netErr);\n }\n\n if (fNet.gateway_provisioned) {\n job.log.debug({ ticket: tick.ticket.uuid, net: fNet },\n 'Network already has gateway provisioned');\n tick.gateway_provisioned = true;\n return releaseTicket(null, tick.ticket, done);\n }\n\n var instParams = {\n metadata: {\n 'com.joyent:ipnat_subnet': fNet.subnet\n },\n params: {\n alias: 'nat-' + fabricNic.network_uuid,\n internal_metadata: {\n 'com.joyent:ipnat_owner': job.params.owner_uuid\n },\n networks: [\n {\n uuid: job.params.sdc_nat_pool,\n primary: true,\n allow_ip_spoofing: true\n },\n {\n uuid: fabricNic.network_uuid,\n ip: fabricNic.gateway,\n allow_ip_spoofing: true\n }\n ],\n ticket: tick.ticket.uuid\n }\n };\n\n sapi.createInstanceAsync(natSvc, instParams,\n function _afterSapiProv(createErr, inst) {\n if (createErr) {\n return releaseTicket(createErr, tick.ticket, done);\n }\n\n job.log.info({ instance: inst, natSvc: natSvc },\n 'Created NAT instance');\n\n tick.job_uuid = inst.job_uuid;\n tick.vm_uuid = inst.uuid;\n return done();\n });\n });\n }\n\n sapi.listServices({ name: 'nat' }, function (sapiErr, svcs) {\n if (sapiErr) {\n return cb(sapiErr);\n }\n\n if (!svcs || svcs.length === 0) {\n return cb(new Error('No \"nat\" service found in SAPI'));\n }\n\n if (svcs.length > 1) {\n return cb(new Error('More than one \"nat\" service found in SAPI'));\n }\n\n natSvc = svcs[0].uuid;\n job.log.info({ svc: natSvc, svcs: svcs }, 'svcs');\n\n async.forEach(job.params.fabricNatTickets, function (tick, next) {\n if (tick.ticket.status === 'active') {\n return provisionNatZone(tick, next);\n }\n\n cnapi.waitlistTicketWait(tick.ticket.uuid,\n function _afterWait(tErr) {\n if (tErr) {\n next(tErr);\n } else {\n provisionNatZone(tick, next);\n }\n });\n\n }, function (aErr) {\n if (aErr) {\n cb(aErr);\n } else {\n cb(null, 'Provisioned fabric NATs');\n }\n });\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients", | |
"async": "async" | |
} | |
}, | |
{ | |
"name": "prepare_payload", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function preparePayload(job, cb) {\n job.params.jobid = job.uuid;\n\n var params = job.params;\n var i, j, nic;\n var payload = { uuid: params['vm_uuid'], image: job.params.image };\n var wantResolvers = true;\n\n if (payload.image.hasOwnProperty('tags') &&\n payload.image.tags.hasOwnProperty('kernel_version') &&\n !params.hasOwnProperty('kernel_version')) {\n\n params['kernel_version'] = payload.image.tags.kernel_version;\n }\n\n if (payload.image.type === 'lx-dataset') {\n params['brand'] = 'lx';\n }\n\n var keys = [ 'alias', 'autoboot', 'billing_id', 'brand', 'cpu_cap',\n 'cpu_shares', 'customer_metadata', 'delegate_dataset', 'dns_domain',\n 'docker', 'firewall_enabled', 'firewall_rules', 'fs_allowed',\n 'hostname', 'indestructible_zoneroot', 'indestructible_delegated',\n 'init_name', 'internal_metadata', 'kernel_version', 'limit_priv',\n 'maintain_resolvers', 'max_locked_memory', 'max_lwps', 'max_msg_ids',\n 'max_physical_memory', 'max_shm_memory', 'max_sem_ids', 'max_shm_ids',\n 'max_swap', 'mdata_exec_timeout', 'nics',\n 'owner_uuid', 'package_name', 'package_version', 'quota', 'ram',\n 'resolvers', 'vcpus', 'zfs_data_compression', 'zfs_io_priority',\n 'tags', 'tmpfs'\n ];\n\n for (i = 0; i < keys.length; i++) {\n var key = keys[i];\n if (params[key] !== undefined) {\n payload[key] = params[key];\n }\n }\n\n // Per OS-2520 we always want to be setting archive_on_delete in SDC\n payload['archive_on_delete'] = true;\n\n // If internal_metadata.set_resolvers === false, we always want\n // to leave the resolvers as empty\n if (params.internal_metadata !== undefined &&\n typeof (params.internal_metadata) === 'object' &&\n params.internal_metadata.set_resolvers === false) {\n wantResolvers = false;\n }\n\n // Add resolvers and routes in the order of the networks\n var resolver;\n var resolvers = [];\n var routes = {};\n for (i = 0; i < params.nics.length; i++) {\n nic = params.nics[i];\n\n if (nic['resolvers'] !== undefined &&\n Array.isArray(nic['resolvers'])) {\n for (j = 0; j < nic['resolvers'].length; j++) {\n resolver = nic['resolvers'][j];\n if (resolvers.indexOf(resolver) === -1) {\n resolvers.push(resolver);\n }\n }\n }\n\n if (nic['routes'] !== undefined &&\n typeof (nic['routes']) === 'object') {\n for (var r in nic['routes']) {\n if (!routes.hasOwnProperty(r)) {\n routes[r] = nic['routes'][r];\n }\n }\n }\n }\n\n if (wantResolvers && !payload.resolvers) {\n payload['resolvers'] = resolvers;\n }\n\n if (Object.keys(routes).length !== 0) {\n payload['routes'] = routes;\n }\n\n if (params['brand'] === 'kvm') {\n payload.disks = params.disks;\n\n ['disk_driver', 'nic_driver', 'cpu_type'].forEach(function (field) {\n if (params[field]) {\n payload[field] = params[field];\n } else {\n payload[field] = job.params.image[field];\n }\n });\n } else {\n payload['image_uuid'] = params['image_uuid'];\n\n if (params['filesystems'] !== undefined) {\n payload['filesystems'] = params['filesystems'];\n }\n }\n\n if (params.imgapiPeers !== undefined) {\n payload.imgapiPeers = params.imgapiPeers;\n }\n\n job.params.payload = payload;\n cb(null, 'Payload prepared successfully');\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "cnapi.ensure_image", | |
"timeout": 300, | |
"retry": 1, | |
"body": "function ensureImage(job, cb) {\n var commonHeaders = { 'x-request-id': job.params['x-request-id'] };\n var cnapi = new sdcClients.CNAPI({ url: cnapiUrl, headers: commonHeaders });\n\n var ensurePayload = {};\n\n if (job.params['brand'] === 'kvm') {\n ensurePayload.image_uuid = job.params.payload.disks[0].image_uuid;\n } else {\n ensurePayload.image_uuid = job.params.image_uuid;\n }\n\n if (job.params.imgapiPeers !== undefined) {\n ensurePayload.imgapiPeers = job.params.imgapiPeers;\n }\n\n cnapi.ensureImage(job.params['server_uuid'], ensurePayload,\n function (error, task) {\n if (error) {\n return cb(error);\n }\n\n job.taskId = task.id;\n return cb(null, 'Ensure image task queued!');\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "cnapi.poll_task_ensure_image", | |
"timeout": 3600, | |
"retry": 1, | |
"body": "function pollTask(job, cb) {\n if (job.params['skip_zone_action']) {\n cb(null, 'Skipping pollTask');\n return;\n }\n\n if (!job.taskId) {\n cb('No taskId provided');\n return;\n }\n\n if (!cnapiUrl) {\n cb('No CNAPI URL provided');\n return;\n }\n\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n // Repeat checkTask until task has finished\n checkTask();\n\n function checkTask() {\n cnapi.getTask(job.taskId, onCnapi);\n\n function onCnapi(err, task) {\n if (err) {\n cb(err);\n } else if (task.status == 'failure') {\n cb(new Error(getErrorMesage(task)));\n } else if (task.status == 'complete') {\n // Tasks that modify VM state should add a .vm to the task\n // with something like \"self.finish({ vm: machine });\"\n if (task.history && task.history.length > 0 &&\n task.history[0].name === 'finish' &&\n task.history[0].event &&\n task.history[0].event.vm) {\n\n job.finished_vm = task.history[0].event.vm;\n job.log.debug({vm_uuid: job.finished_vm.uuid},\n 'finish() returned VM');\n }\n\n cb(null, 'Job succeeded!');\n } else {\n if (job.timeToDie) {\n job.log.error('pollTask.checkTask.onCnapi called after task'\n + 'completion, breaking loop');\n return;\n }\n setTimeout(checkTask, 1000);\n }\n }\n }\n\n function getErrorMesage(task) {\n var message;\n var details = [];\n\n if (task.history !== undefined && task.history.length) {\n for (var i = 0; i < task.history.length; i++) {\n var event = task.history[i];\n if (event.name && event.name === 'error' && event.event &&\n event.event.error) {\n var err = event.event.error;\n if (typeof (err) === 'string') {\n message = err;\n if (event.event.details && event.event.details.error) {\n message += ', ' + event.event.details.error;\n }\n } else {\n message = err.message;\n }\n } else if (event.name && event.name === 'finish' &&\n event.event && event.event.log && event.event.log.length) {\n for (var j = 0; j < event.event.log.length; j++) {\n var logEvent = event.event.log[j];\n if (logEvent.level && logEvent.level === 'error') {\n details.push(logEvent.message);\n }\n }\n }\n }\n }\n\n // Apparently the task doesn't have any message for us...\n if (message === undefined) {\n message = 'Unexpected error occured';\n } else if (details.length) {\n message += ': ' + details.join(', ');\n }\n\n return message;\n }\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "cnapi.wait_for_fabric_nat_provisions", | |
"timeout": 600, | |
"retry": 1, | |
"body": "function waitForFabricNatProvisions(job, cb) {\n if (!job.params.fabricNatTickets ||\n job.params.fabricNatTickets.length === 0) {\n return cb(null, 'No fabric NATs provisioned');\n }\n\n // Filter out tickets that didn't end up needing a gateway provisioned\n var toWaitFor = job.params.fabricNatTickets.filter(function (t) {\n return !t.gateway_provisioned;\n });\n\n if (toWaitFor.length === 0) {\n return cb(null, 'No fabric NAT provisions left to wait for');\n }\n\n var vmapi = new sdcClients.VMAPI({\n url: vmapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n function checkVm(tick, done) {\n var uuid = tick.vm_uuid;\n vmapi.getVm({ uuid: uuid }, onVmapi);\n\n function onVmapi(err, vm, req, res) {\n if (err) {\n cb(err);\n\n } else if (vm.state === 'running') {\n done();\n\n } else if (vm.state === 'failed') {\n done(new Error(\n 'NAT zone \"' + vm.uuid + '\" failed to provision'));\n\n } else {\n setTimeout(checkVm, 1000, tick, done);\n }\n }\n }\n\n async.forEach(toWaitFor, checkVm, function (aErr) {\n if (aErr) {\n cb(aErr);\n } else {\n cb(null, 'Fabric NATs running');\n }\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients", | |
"async": "async" | |
} | |
}, | |
{ | |
"name": "cnapi.provision_vm", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function provision(job, cb) {\n delete job.params.skip_zone_action;\n\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n job.params.jobid = job.uuid;\n\n // autoboot=false means we want the machine to not to boot after provision\n if (job.params.autoboot === false || job.params.autoboot === 'false') {\n job.expects = 'stopped';\n } else {\n job.expects = 'running';\n }\n\n var server = job.params['server_uuid'];\n\n return cnapi.createVm(server, job.params.payload, function (err, task) {\n if (err) {\n return cb(err);\n } else {\n job.taskId = task.id;\n // As soon was we reach this point, we don't want to clean up NICs\n // when a provision fails\n job.markAsFailedOnError = false;\n return cb(null, 'Provision task: ' + task.id + ' queued!');\n }\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "cnapi.poll_task", | |
"timeout": 3600, | |
"retry": 1, | |
"body": "function pollTask(job, cb) {\n if (job.params['skip_zone_action']) {\n cb(null, 'Skipping pollTask');\n return;\n }\n\n if (!job.taskId) {\n cb('No taskId provided');\n return;\n }\n\n if (!cnapiUrl) {\n cb('No CNAPI URL provided');\n return;\n }\n\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n // Repeat checkTask until task has finished\n checkTask();\n\n function checkTask() {\n cnapi.getTask(job.taskId, onCnapi);\n\n function onCnapi(err, task) {\n if (err) {\n cb(err);\n } else if (task.status == 'failure') {\n cb(new Error(getErrorMesage(task)));\n } else if (task.status == 'complete') {\n // Tasks that modify VM state should add a .vm to the task\n // with something like \"self.finish({ vm: machine });\"\n if (task.history && task.history.length > 0 &&\n task.history[0].name === 'finish' &&\n task.history[0].event &&\n task.history[0].event.vm) {\n\n job.finished_vm = task.history[0].event.vm;\n job.log.debug({vm_uuid: job.finished_vm.uuid},\n 'finish() returned VM');\n }\n\n cb(null, 'Job succeeded!');\n } else {\n if (job.timeToDie) {\n job.log.error('pollTask.checkTask.onCnapi called after task'\n + 'completion, breaking loop');\n return;\n }\n setTimeout(checkTask, 1000);\n }\n }\n }\n\n function getErrorMesage(task) {\n var message;\n var details = [];\n\n if (task.history !== undefined && task.history.length) {\n for (var i = 0; i < task.history.length; i++) {\n var event = task.history[i];\n if (event.name && event.name === 'error' && event.event &&\n event.event.error) {\n var err = event.event.error;\n if (typeof (err) === 'string') {\n message = err;\n if (event.event.details && event.event.details.error) {\n message += ', ' + event.event.details.error;\n }\n } else {\n message = err.message;\n }\n } else if (event.name && event.name === 'finish' &&\n event.event && event.event.log && event.event.log.length) {\n for (var j = 0; j < event.event.log.length; j++) {\n var logEvent = event.event.log[j];\n if (logEvent.level && logEvent.level === 'error') {\n details.push(logEvent.message);\n }\n }\n }\n }\n }\n\n // Apparently the task doesn't have any message for us...\n if (message === undefined) {\n message = 'Unexpected error occured';\n } else if (details.length) {\n message += ': ' + details.join(', ');\n }\n\n return message;\n }\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "vmapi.put_vm", | |
"timeout": 120, | |
"retry": 1, | |
"body": "function putVm(job, cb) {\n var vmapi;\n\n /*\n * Checks (polls) the state of a machine in VMAPI. It is used for provisions\n * and VM actions such as reboot and shutdown.\n *\n * IMPORTANT: this function an all uses of job.expects are deprecated and\n * will be removed in a future version after everyone is updated\n * past the old agent tasks that don't pass back the VMs. It is\n * being replaced with the putVm function and is now only called\n * from there.\n */\n function checkState(_job, _cb) {\n if (_job.params['skip_zone_action']) {\n _cb(null, 'Skipping checkState');\n return;\n }\n\n // For now don't fail the job if this parameter is not present\n if (!_job.expects) {\n _cb(null, 'No \\'expects\\' state parameter provided');\n return;\n }\n\n if (!_job.params['vm_uuid']) {\n _cb('No VM UUID provided');\n return;\n }\n\n if (!vmapiUrl) {\n _cb('No VMAPI URL provided');\n return;\n }\n\n var _vmapi = new sdcClients.VMAPI({\n url: vmapiUrl,\n headers: { 'x-request-id': _job.params['x-request-id'] }\n });\n\n // Repeat checkVm until VM data is updated\n checkVm();\n\n function checkVm() {\n _vmapi.getVm({ uuid: _job.params['vm_uuid'] }, onVmapi);\n\n function onVmapi(err, vm, req, res) {\n if (err) {\n _cb(err);\n } else if (vm.state == _job.expects) {\n _cb(null, 'VM is now ' + _job.expects);\n } else {\n if (_job.timeToDie) {\n _job.log.error('checkState.checkVm.onVmapi called after'\n + ' task completion, breaking loop');\n return;\n }\n setTimeout(checkVm, 1000);\n }\n }\n }\n }\n\n if (!job.finished_vm) {\n job.log.warn({req_id: job.params['x-request-id']},\n 'putVM() called but job.finished_vm is missing');\n\n checkState(job, cb);\n //\n // When checkState is removed:\n //\n // cb(null, 'job has no finished_vm, nothing to post to VMAPI');\n return;\n }\n\n if (!vmapiUrl) {\n cb(new Error('No VMAPI URL provided'));\n return;\n }\n\n job.log.debug({vmobj: job.finished_vm}, 'putVM() putting VM to VMAPI');\n\n //\n // Borrowed from vm-agent lib/vmapi-client.js\n //\n // DO NOT TRY THIS AT HOME!\n //\n // afaict the reason sdcClients does not have a putVm function in the first\n // place is that this is not something API clients should generally be\n // doing. WE need to do it, and vm-agent needs to do it, but other clients\n // should not be doing it unless they're absolutely sure that what they're\n // PUTing is the current state.\n //\n // We know that here because cn-agent tasks just did a VM.load for us.\n //\n sdcClients.VMAPI.prototype.putVm = function (vm, callback) {\n var log = job.log;\n var opts = { path: '/vms/' + vm.uuid };\n\n this.client.put(opts, vm, function (err, req, res) {\n if (err) {\n log.error(err, 'Could not update VM %s', vm.uuid);\n return callback(err);\n }\n\n log.info('VM (uuid=%s, state=%s, last_modified=%s) updated @ VMAPI',\n vm.uuid, vm.state, vm.last_modified);\n return callback();\n });\n };\n\n vmapi = new sdcClients.VMAPI({\n log: job.log,\n url: vmapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n vmapi.putVm(job.finished_vm, function (err) {\n if (err) {\n cb(err);\n return;\n }\n\n cb(null, 'put VM ' + job.finished_vm.uuid + ' to VMAPI');\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "fwapi.update", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function updateFwapi(job, cb) {\n var fwapi = new sdcClients.FWAPI({\n url: fwapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n var jobParams = job.params.payload || job.params;\n var type;\n var update = {};\n var vmProps = ['add_nics', 'firewall_enabled', 'nics', 'remove_ips',\n 'remove_nics', 'remove_tags', 'set_tags', 'tags'];\n\n if (job.params.task === 'provision') {\n type = 'vm.add';\n } else {\n type = (job.params.task === 'destroy') ? 'vm.delete' : 'vm.update';\n }\n\n vmProps.forEach(function (prop) {\n if (jobParams.hasOwnProperty(prop)) {\n update[prop] = jobParams[prop];\n }\n });\n\n job.log.info({ jobParams: jobParams, update: update }, 'update params');\n\n if (Object.keys(update).length === 0 && job.params.task !== 'destroy') {\n return cb(null, 'No properties affecting FWAPI found: not updating');\n }\n\n update.owner_uuid = jobParams.owner_uuid;\n update.server_uuid = jobParams.server_uuid;\n update.type = type;\n update.uuid = jobParams.uuid || jobParams.vm_uuid || job.params.vm_uuid;\n\n return fwapi.createUpdate(update, function (err, obj) {\n if (err) {\n job.log.warn(err, 'Error sending update to FWAPI');\n return cb(null, 'Error updating FWAPI');\n }\n\n return cb(null, 'Updated FWAPI with update UUID: ' + obj.update_uuid);\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "cnapi.release_vm_ticket", | |
"timeout": 60, | |
"retry": 1, | |
"body": "function releaseVMTicket(job, cb) {\n if (!job.ticket) {\n return cb();\n }\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n cnapi.waitlistTicketRelease(job.ticket.uuid, function (err) {\n if (err) {\n job.log.warn({err: err, ticket: job.ticket},\n 'error releasing CNAPI waitlist VM ticket');\n }\n cb(err);\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "cnapi.release_fabric_nat_ticket", | |
"timeout": 60, | |
"retry": 1, | |
"body": "function releaseFabricTicket(job, cb) {\n if (!job.params.ticket) {\n return cb(null, 'No ticket to release');\n }\n\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n cnapi.waitlistTicketRelease(job.params.ticket, function (err) {\n if (err) {\n if (err.code === 'ResourceNotFound') {\n cb(null, 'Ticket released');\n } else {\n cb(err);\n }\n\n return;\n }\n\n cb(null, 'Released ticket ' + job.params.ticket);\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
} | |
], | |
"onerror": [ | |
{ | |
"name": "napi.cleanup_nics", | |
"timeout": 10, | |
"retry": 1, | |
"body": "function cleanupNics(job, cb) {\n // If this is false it means that cnapi.pollTask succeeded, so the VM exists\n // physically wether its provision failed or not\n if (job.markAsFailedOnError === false) {\n return cb(null, 'markAsFailedOnError was set to false, ' +\n 'won\\'t cleanup VM NICs');\n }\n\n var nics = job.params['add_nics'] || job.params['nics'];\n if (nics === undefined) {\n return cb(null, 'No NICs were provisioned');\n }\n\n var napi = new sdcClients.NAPI({\n url: napiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n async.mapSeries(nics, function (nic, next) {\n napi.deleteNic(nic.mac, function (err) {\n if (err) {\n next(err);\n } else {\n next();\n }\n });\n }, function (err2) {\n if (err2) {\n cb(err2);\n } else {\n cb(null, 'NICs removed');\n }\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients", | |
"async": "async" | |
} | |
}, | |
{ | |
"name": "set_post_back_failed", | |
"body": "function setPostBackFailed(job, cb) {\n // If this is false it means that cnapi.pollTask succeeded, so the VM exists\n // physically wether its provision failed or not\n if (job.markAsFailedOnError === false) {\n return cb(null, 'markAsFailedOnError was set to false, ' +\n 'won\\'t set postBackState for VM');\n }\n\n job.postBackState = 'failed';\n return cb(null, 'Set post back state as failed');\n}", | |
"modules": { | |
} | |
}, | |
{ | |
"name": "common.post_back", | |
"body": "function postBack(job, cb) {\n if (job.markAsFailedOnError === false) {\n return cb(null, 'markAsFailedOnError was set to false, ' +\n 'won\\'t postBack provision failure to VMAPI');\n }\n\n var urls = job.params['post_back_urls'];\n var vmapiPath = vmapiUrl + '/job_results';\n\n // By default, post back to VMAPI\n if (urls === undefined || !Array.isArray(urls)) {\n urls = [ vmapiPath ];\n } else {\n urls.push(vmapiPath);\n }\n\n var obj = clone(job.params);\n obj.execution = job.postBackState || 'succeeded';\n\n async.mapSeries(urls, function (url, next) {\n var p = urlModule.parse(url);\n var api = restify.createJsonClient({\n url: p.protocol + '//' + p.host,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n api.post(p.pathname, obj, onResponse);\n\n function onResponse(err, req, res) {\n return next(err);\n }\n\n }, function (err2) {\n if (err2) {\n var errObject = { err: err2, urls: urls };\n job.log.info(errObject, 'Error posting back to URLs');\n cb(null, 'Could not post back job results. See /info object');\n } else {\n cb(null, 'Posted job results back to specified URLs');\n }\n });\n\n // Shallow clone for the job.params object\n function clone(theObj) {\n if (null === theObj || 'object' != typeof (theObj)) {\n return theObj;\n }\n\n var copy = theObj.constructor();\n\n for (var attr in theObj) {\n if (theObj.hasOwnProperty(attr)) {\n copy[attr] = theObj[attr];\n }\n }\n return copy;\n }\n}", | |
"modules": { | |
"async": "async", | |
"restify": "restify", | |
"urlModule": "url" | |
} | |
}, | |
{ | |
"name": "cnapi.cleanup_allocation_ticket", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
}, | |
"body": "function releaseAllocationTicket(job, cb) {\n if (!job.allocationTicket) {\n return cb();\n }\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n cnapi.waitlistTicketRelease(job.allocationTicket.uuid, function (err) {\n if (err) {\n job.log.warn({err: err, ticket: job.ticket},\n 'error releasing CNAPI waitlist allocation ticket');\n return;\n }\n cb();\n });\n}" | |
}, | |
{ | |
"name": "cnapi.cleanup_vm_ticket", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
}, | |
"body": "function releaseVMTicket(job, cb) {\n if (!job.ticket) {\n return cb();\n }\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n cnapi.waitlistTicketRelease(job.ticket.uuid, function (err) {\n if (err) {\n job.log.warn({err: err, ticket: job.ticket},\n 'error releasing CNAPI waitlist VM ticket');\n }\n cb(err);\n });\n}" | |
}, | |
{ | |
"name": "cnapi.release_fabric_nat_ticket", | |
"timeout": 60, | |
"retry": 1, | |
"body": "function releaseFabricTicket(job, cb) {\n if (!job.params.ticket) {\n return cb(null, 'No ticket to release');\n }\n\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n cnapi.waitlistTicketRelease(job.params.ticket, function (err) {\n if (err) {\n if (err.code === 'ResourceNotFound') {\n cb(null, 'Ticket released');\n } else {\n cb(err);\n }\n\n return;\n }\n\n cb(null, 'Released ticket ' + job.params.ticket);\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
}, | |
{ | |
"name": "On error", | |
"body": "function (job, cb) {\n return cb('Error executing job');\n }" | |
} | |
], | |
"oncancel": [ | |
{ | |
"name": "vmapi.refresh_vm", | |
"modules": { | |
"restify": "restify" | |
}, | |
"body": "function refreshVm(job, cb) {\n if (!job.params['vm_uuid']) {\n cb('No VM UUID provided');\n return;\n }\n\n if (!vmapiUrl) {\n cb('No VMAPI URL provided');\n return;\n }\n\n var vmapi = restify.createJsonClient({\n url: vmapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n var path = '/vms/' + job.params['vm_uuid'] + '?sync=true';\n\n vmapi.get(path, onVmapi);\n\n function onVmapi(err, req, res, vm) {\n if (err) {\n cb(err);\n } else {\n cb(null, 'VM data refreshed, new VM state is ' + vm.state);\n }\n }\n}" | |
}, | |
{ | |
"name": "cnapi.cleanup_vm_ticket", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
}, | |
"body": "function releaseVMTicket(job, cb) {\n if (!job.ticket) {\n return cb();\n }\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n cnapi.waitlistTicketRelease(job.ticket.uuid, function (err) {\n if (err) {\n job.log.warn({err: err, ticket: job.ticket},\n 'error releasing CNAPI waitlist VM ticket');\n }\n cb(err);\n });\n}" | |
}, | |
{ | |
"name": "cnapi.cleanup_allocation_ticket", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
}, | |
"body": "function releaseAllocationTicket(job, cb) {\n if (!job.allocationTicket) {\n return cb();\n }\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n cnapi.waitlistTicketRelease(job.allocationTicket.uuid, function (err) {\n if (err) {\n job.log.warn({err: err, ticket: job.ticket},\n 'error releasing CNAPI waitlist allocation ticket');\n return;\n }\n cb();\n });\n}" | |
}, | |
{ | |
"name": "cnapi.release_fabric_nat_ticket", | |
"timeout": 60, | |
"retry": 1, | |
"body": "function releaseFabricTicket(job, cb) {\n if (!job.params.ticket) {\n return cb(null, 'No ticket to release');\n }\n\n var cnapi = new sdcClients.CNAPI({\n url: cnapiUrl,\n headers: { 'x-request-id': job.params['x-request-id'] }\n });\n\n cnapi.waitlistTicketRelease(job.params.ticket, function (err) {\n if (err) {\n if (err.code === 'ResourceNotFound') {\n cb(null, 'Ticket released');\n } else {\n cb(err);\n }\n\n return;\n }\n\n cb(null, 'Released ticket ' + job.params.ticket);\n });\n}", | |
"modules": { | |
"sdcClients": "sdc-clients" | |
} | |
} | |
] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"firewall_enabled": true, | |
"owner_uuid": "4a8de98d-20c2-4db4-a4d9-69b23e687d99", | |
"hostname": "ff8da53202cd", | |
"alias": "hungry_sammet", | |
"internal_metadata": { | |
"docker:id": "ff8da53202cd42f592ab071d763b308a65a837d6952c45169d7999fe11c78624", | |
"docker:attach_stdout": true, | |
"docker:attach_stderr": true, | |
"docker:noipmgmtd": true, | |
"docker:cmd": "[]", | |
"docker:entrypoint": "[\"bin/2fact-demo\"]", | |
"docker:env": "[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"LANG=C.UTF-8\",\"JAVA_VERSION=8u45\",\"JAVA_DEBIAN_VERSION=8u45-b14-2~bpo8+2\",\"CA_CERTIFICATES_JAVA_VERSION=20140324\"]", | |
"docker:workdir": "/opt/docker", | |
"docker:user": "daemon", | |
"docker:linkHosts": "", | |
"docker:linkEnv": "[]" | |
}, | |
"tags": { | |
"sdc_docker": true | |
}, | |
"autoboot": false, | |
"docker": true, | |
"restart_init": false, | |
"tmpfs": 0, | |
"filesystems": [ | |
], | |
"networks": [ | |
{ | |
"primary": true, | |
"ipv4_uuid": "37801ade-a5b8-4343-8ccb-4eb3ba1a59a8", | |
"ipv4_count": 1, | |
"uuid": "37801ade-a5b8-4343-8ccb-4eb3ba1a59a8" | |
} | |
], | |
"billing_id": "e8e519e8-99f1-6e85-8f25-85a0956a6115", | |
"image_uuid": "f95df90f-892d-84f5-faa9-5409d8603709", | |
"brand": "lx", | |
"init_name": "/native/usr/vm/sbin/dockerinit", | |
"kernel_version": "3.13.0", | |
"firewall_rules": [ | |
{ | |
"enabled": true, | |
"owner_uuid": "4a8de98d-20c2-4db4-a4d9-69b23e687d99", | |
"rule": "FROM tag sdc_docker TO tag sdc_docker ALLOW tcp PORT all", | |
"uuid": "477a7a8c-73a8-47a6-8a68-a6253acf7d6a", | |
"version": "1438525968989.010367" | |
}, | |
{ | |
"enabled": true, | |
"owner_uuid": "4a8de98d-20c2-4db4-a4d9-69b23e687d99", | |
"rule": "FROM tag sdc_docker TO tag sdc_docker ALLOW udp PORT all", | |
"uuid": "60f5f551-2b35-4d1a-9940-8440192b7fc3", | |
"version": "1438525969000.010367" | |
} | |
], | |
"sync": true, | |
"server_uuid": "", | |
"cpu_cap": 100, | |
"max_lwps": 4000, | |
"max_physical_memory": 1024, | |
"max_swap": 4096, | |
"quota": 25, | |
"zfs_io_priority": 64, | |
"ram": 1024, | |
"cpu_shares": 64, | |
"package": { | |
"name": "sample-1G", | |
"version": "1.0.0", | |
"active": true, | |
"cpu_cap": 100, | |
"max_lwps": 4000, | |
"max_physical_memory": 1024, | |
"max_swap": 4096, | |
"quota": 25600, | |
"zfs_io_priority": 64, | |
"fss": 64, | |
"billing_tag": "sample-1G", | |
"uuid": "e8e519e8-99f1-6e85-8f25-85a0956a6115", | |
"created_at": "2015-08-02T12:47:12.486Z", | |
"updated_at": "2015-08-02T12:47:12.486Z", | |
"default": true, | |
"v": 1 | |
}, | |
"image": { | |
"v": 2, | |
"uuid": "f95df90f-892d-84f5-faa9-5409d8603709", | |
"owner": "930896af-bf8c-48d4-885c-6573a94b1853", | |
"name": "docker-layer", | |
"version": "e85de6baa069", | |
"state": "active", | |
"disabled": false, | |
"public": false, | |
"published_at": "2015-07-01T15:53:22.452Z", | |
"type": "docker", | |
"os": "linux", | |
"files": [ | |
{ | |
"sha1": "96e379fb98bd1b401c6ee52230c11d38251572cf", | |
"size": 32, | |
"compression": "none" | |
} | |
], | |
"description": "/bin/sh -c #(nop) CMD []", | |
"origin": "6288563b-cb30-d505-a4dc-82022a905dd6", | |
"tags": { | |
"docker:repo": "phaus/2fact-demo", | |
"docker:id": "e85de6baa06978980ebf0d432a331d050f3a6276acdd2ea6dd2762c0dd2229a0", | |
"docker:architecture": "amd64", | |
"docker:config": { | |
"Cmd": [ | |
], | |
"Entrypoint": [ | |
"bin/2fact-demo" | |
], | |
"Env": [ | |
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", | |
"LANG=C.UTF-8", | |
"JAVA_VERSION=8u45", | |
"JAVA_DEBIAN_VERSION=8u45-b14-2~bpo8+2", | |
"CA_CERTIFICATES_JAVA_VERSION=20140324" | |
], | |
"WorkingDir": "/opt/docker" | |
} | |
} | |
}, | |
"sdc_nat_pool": "f0145ce1-8e5a-457a-8298-5cc80d62b00c", | |
"task": "provision", | |
"vm_uuid": "ff8da532-02cd-42f5-92ab-071d763b308a", | |
"current_state": "provisioning", | |
"x-request-id": "d9b72ee5-ae60-4c81-ad93-08b533acd4c1" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment