TritonDataCenter / TritonDataCenter/sdc-cloudapi

CreateMachineDisk doesn't work

Open Beginner friendly
#156 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
8
Forks
22
Avg merge
3d 9h
Merged PRs (30d)
1

Description

Client add disk:

❯ which tt
tt: aliased to triton

❯ tt inst get test-disks | jq .disk
102400
❯ tt inst get test-disks | jq .disks
[
  {
    "size": 10240,
    "block_size": 8192,
    "boot": true,
    "image": "ede15ae3-a2ed-4636-a4d5-c130cbd9c297",
    "id": "33ee02e6-9239-4acb-913f-3bf6f88e3c42"
  },
  {
    "size": 10240,
    "block_size": 4096,
    "id": "12f0e114-abfc-4972-95dd-b7071e95b72a"
  }
]
❯ tt inst get test-disks | jq .state
"stopped"
❯ tt inst disk add test-disks 20480
triton instance disk add: error (InternalError): Internal Error

CloudAPI error:

[2026-08-22T02:22:35.598Z] ERROR: cloudapi/456881 on e49bd1aa-2c21-4850-86dc-61d8d9c9f192: unexpected error (req_id=6951be18-eae1-4e32-be59-f5d9988ce998)
    InvalidArgumentError: Cannot set block_size and image_uuid.

[root@e49bd1aa-2c21-4850-86dc-61d8d9c9f192 (us-southeast-1:cloudapi0) /opt/smartdc/cloudapi]# cat package.json | json version
9.20.0

createDisk iterates over every disk of the instance when adding a new disk and hits the error condition where a disk being added cannot have a block_size specified when it has an image. Looks like this check already exists in lib/machines.js, not sure we need it in lib/endpoints/disks.js

https://github.com/TritonDataCenter/sdc-cloudapi/blob/master/lib/endpoints/disks.js#L93

function createDisk(req, res, next) {
    assert.ok(req.sdc);

    var log = req.log;
    var headers = { 'x-request-id': req.getId() };
    var context = { caller: req._auditCtx };
    var origin = req.params.origin || 'cloudapi';
    var vmUuid = req.vm.uuid;
    var ownerUuid = req.account.uuid;
    var size = req.params.size;
    var pciSlot = req.params.pci_slot;

    req.vm.disks = req.vm.disks || [];

    if (req.vm.brand !== 'bhyve') {
        next(InvalidArgumentError('Disk Creation is supported only for ' +
            'BHYVE VMs'));
        return;
    }

    if (req.vm.state !== 'stopped') {
        next(new InvalidArgumentError('VM must be stopped'));
        return;
    }

    if (!size) {
        next(new MissingParameterError('size must be specified'));
        return;
    }

    if (size !== 'remaining' && isNaN(+size)) {
        next(new InvalidArgumentError('size must be a number'));
        return;
    }

    if (pciSlot !== undefined && !PCI_SLOT_RE.test(pciSlot)) {
        next(new InvalidArgumentError('pci_slot has wrong format'));
        return;
    }

    if (req.vm.disks.length >= MAX_ALLOWED_VM_DISKS) {
        next(new InvalidArgumentError('A maximum of ' + MAX_ALLOWED_VM_DISKS +
            ' disks per VM are supported'));
        return;
    }

    // Check requested block size, if any.
    req.vm.disks.forEach(function vrs(disk, i) {
        if (disk.hasOwnProperty('block_size')) {
            if (disk.hasOwnProperty('image_uuid')) {
                throw new InvalidArgumentError(
                    'Cannot set block_size and image_uuid.'
                );
            }
            if (!diskValidation.validRecordSize(disk.block_size)) {
                throw new InvalidArgumentError(
                    'Invalid block_size: ' + disk.block_size +
                    ' on disk: ' + i + '. Must be 512-131072 and ' +
                    'a power of 2.'
                );
            }
        }
    });

    if (pciSlot) {
        var diskId = getDiskUuid(vmUuid, pciSlot);
    }

    if (size === 'remaining') {
        if (!req.vm.flexible_disk_size) {
            next(new InvalidArgumentError('remaining is only supported for ' +
                'VMs created with flexible_disk_size packages'));
            return;
        }

        var disksSum = req.vm.disks.reduce(function sumDisk(sum, disk) {
            return (sum + Number(disk.size) || 0);
        }, 0);
        size = req.vm.flexible_disk_size - disksSum;
    }

    req.sdc.vmapi.createDisk({
        uuid: vmUuid,
        owner_uuid: ownerUuid,
        disk_uuid: diskId,
        pci_slot: pciSlot,
        size: size,
        origin: origin,
        context: context
    }, {
        log: log,
        headers: headers
    }, function createDiskCb(err, job) {
        if (err) {
            next(err);
            return;
        }

        var login = req.account.login;
        log.debug({
            request: format('POST /%s/machines/%s/disks -> ok', login, vmUuid),
            job: job
        });

        if (!pciSlot) {
            res.send(202);
            next();
            return;
        }

        var location = '/' + login + '/machines/' + vmUuid + '/disks/' + diskId;
        res.header('Location', location);

        var disk = {
            uuid: diskId,
            pci_slot: pciSlot,
            size: size,
            boot: false,
            state: 'creating'
        };

        res.send(translate(disk));

        next();
    });
}

https://github.com/TritonDataCenter/sdc-cloudapi/blob/master/lib/machines.js#L565

                // Check requested block size, if any.
                disks.forEach(function vrs(disk, i) {
                    if (disk.hasOwnProperty('block_size')) {
                        if (disk.hasOwnProperty('image_uuid')) {
                            throw new InvalidArgumentError(
                                'Cannot set block_size and image_uuid.'
                            );
                        }
                        if (!diskValidation.validRecordSize(disk.block_size)) {
                            throw new InvalidArgumentError(
                                'Invalid block_size: ' + disk.block_size +
                                ' on disk: ' + i + '. Must be 512-131072 and ' +
                                'a power of 2.'
                            );
                        }
                    }
                });

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in lib/endpoints/disks.js at createDisk and compare its disk validation with the existing check in lib/machines.js. Reproduce the stopped BHYVE VM case with an image-backed disk, then verify that adding a disk no longer returns the block_size/image_uuid error while the intended validation remains covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
api, backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.