Exemple #1
0
def create_resources(client, filenames):
    """Create resources using their JSON or YAML descriptions.

    :param client: an instance of ironic client;
    :param filenames: a list of filenames containing JSON or YAML resources
        definitions.
    :raises: ClientException if any operation during files processing/resource
        creation fails.
    """
    errors = []
    resources = []
    for resource_file in filenames:
        try:
            resource = load_from_file(resource_file)
            jsonschema.validate(resource, _CREATE_SCHEMA)
            resources.append(resource)
        except (exc.ClientException, jsonschema.ValidationError) as e:
            errors.append(e)
    if errors:
        raise exc.ClientException('While validating the resources file(s), the'
                                  ' following error(s) were encountered:\n%s' %
                                  '\n'.join(six.text_type(e) for e in errors))
    for r in resources:
        errors.extend(create_chassis(client, r.get('chassis', [])))
        errors.extend(create_nodes(client, r.get('nodes', [])))
    if errors:
        raise exc.ClientException('During resources creation, the following '
                                  'error(s) were encountered:\n%s' %
                                  '\n'.join(six.text_type(e) for e in errors))
Exemple #2
0
def load_from_file(filename):
    """Deserialize JSON or YAML from file.

    :param filename: name of the file containing JSON or YAML.
    :returns: a dictionary deserialized from JSON or YAML.
    :raises: ClientException if the file can not be loaded or if its contents
        is not a valid JSON or YAML, or if the file extension is not supported.
    """
    try:
        with open(filename) as f:
            if filename.endswith('.yaml'):
                return yaml.safe_load(f)
            elif filename.endswith('.json'):
                return json.load(f)
            else:
                # The file is neither .json, nor .yaml, raise an exception
                raise exc.ClientException(
                    'Cannot process file "%(file)s" - it must have .json or '
                    '.yaml extension.' % {'file': filename})
    except IOError as e:
        raise exc.ClientException('Cannot read file "%(file)s" due to '
                                  'error: %(err)s' %
                                  {'err': e, 'file': filename})
    except (ValueError, yaml.YAMLError) as e:
        # json.load raises only ValueError
        raise exc.ClientException('File "%(file)s" is invalid due to error: '
                                  '%(err)s' % {'err': e, 'file': filename})
def create_ports(client, port_list, node_uuid):
    """Create ports from dictionaries.

    :param client: ironic client instance.
    :param port_list: list of dictionaries to be POSTed to /ports
        endpoint.
    :param node_uuid: UUID of a node the ports should be associated with.
    :returns: array of exceptions encountered during creation.
    """
    errors = []
    for port in port_list:
        port_node_uuid = port.get('node_uuid')
        if port_node_uuid and port_node_uuid != node_uuid:
            errors.append(
                exc.ClientException(
                    'Cannot create a port as part of node %(node_uuid)s '
                    'because the port %(port)s has a different node UUID '
                    'specified.', {
                        'node_uuid': node_uuid,
                        'port': port
                    }))
            continue
        port['node_uuid'] = node_uuid
        port_uuid, error = create_single_port(client, **port)
        if error:
            errors.append(error)
    return errors
Exemple #4
0
def create_portgroups(client, portgroup_list, node_uuid):
    """Create port groups from dictionaries.

    :param client: ironic client instance.
    :param portgroup_list: list of dictionaries to be POSTed to /portgroups
        endpoint, if some of them contain "ports" key, its content is POSTed
        separately to /ports endpoint.
    :param node_uuid: UUID of a node the port groups should be associated with.
    :returns: array of exceptions encountered during creation.
    """
    errors = []
    for portgroup in portgroup_list:
        portgroup_node_uuid = portgroup.get('node_uuid')
        if portgroup_node_uuid and portgroup_node_uuid != node_uuid:
            errors.append(exc.ClientException(
                'Cannot create a port group as part of node %(node_uuid)s '
                'because the port group %(portgroup)s has a different node '
                'UUID specified.',
                {'node_uuid': node_uuid,
                 'portgroup': portgroup}))
            continue
        portgroup['node_uuid'] = node_uuid
        portgroup_uuid, error = create_single_portgroup(client, **portgroup)
        if error:
            errors.append(error)
        ports = portgroup.get('ports')
        # Port group UUID == None means that port group creation failed, don't
        # create the ports inside it
        if ports is not None and portgroup_uuid is not None:
            errors.extend(create_ports(client, ports, node_uuid,
                                       portgroup_uuid=portgroup_uuid))
    return errors
def create_nodes(client, node_list, chassis_uuid=None):
    """Create nodes from dictionaries.

    :param client: ironic client instance.
    :param node_list: list of dictionaries to be POSTed to /nodes
        endpoint, if some of them contain "ports" key, its content is POSTed
        separately to /ports endpoint.
    :param chassis_uuid: UUID of a chassis the nodes should be associated with.
    :returns: array of exceptions encountered during creation.
    """
    errors = []
    for node in node_list:
        if chassis_uuid is not None:
            node_chassis_uuid = node.get('chassis_uuid')
            if node_chassis_uuid and node_chassis_uuid != chassis_uuid:
                errors.append(
                    exc.ClientException(
                        'Cannot create a node as part of chassis %(chassis_uuid)s '
                        'because the node %(node)s has a different chassis UUID '
                        'specified.' % {
                            'chassis_uuid': chassis_uuid,
                            'node': node
                        }))
                continue
            node['chassis_uuid'] = chassis_uuid
        node_uuid, error = create_single_node(client, **node)
        if error:
            errors.append(error)
        ports = node.get('ports')
        # Node UUID == None means that node creation failed, don't
        # create the ports inside it
        if ports is not None and node_uuid is not None:
            errors.extend(create_ports(client, ports, node_uuid=node_uuid))
    return errors
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)", parsed_args)
        baremetal_client = self.app.client_manager.baremetal

        if not parsed_args.node and not parsed_args.resource_class:
            raise exc.ClientException(
                _('--resource-class is required except when --node is used'))

        field_list = [
            'name', 'uuid', 'extra', 'resource_class', 'traits',
            'candidate_nodes', 'node', 'owner'
        ]
        fields = dict((k, v) for (k, v) in vars(parsed_args).items()
                      if k in field_list and v is not None)

        fields = utils.args_array_to_dict(fields, 'extra')
        allocation = baremetal_client.allocation.create(**fields)
        if parsed_args.wait_timeout is not None:
            allocation = baremetal_client.allocation.wait(
                allocation.uuid, timeout=parsed_args.wait_timeout)

        data = dict([(f, getattr(allocation, f, ''))
                     for f in res_fields.ALLOCATION_DETAILED_RESOURCE.fields])

        return self.dict2columns(data)
 def test_create_nodes_exception(self, mock_create_ports):
     node = {'driver': 'fake', 'ports': ['list of ports']}
     self.client.node.create.side_effect = exc.ClientException('bar')
     errs = create_resources.create_nodes(self.client, [node])
     self.assertIsInstance(errs[0], exc.ClientException)
     self.assertEqual(1, len(errs))
     self.client.node.create.assert_called_once_with(driver='fake')
     self.assertFalse(mock_create_ports.called)
 def test_create_chassis_exception(self, mock_create_nodes):
     chassis = {'description': 'fake', 'nodes': ['list of nodes']}
     self.client.chassis.create.side_effect = exc.ClientException('bar')
     errs = create_resources.create_chassis(self.client, [chassis])
     self.client.chassis.create.assert_called_once_with(description='fake')
     self.assertFalse(mock_create_nodes.called)
     self.assertEqual(1, len(errs))
     self.assertIsInstance(errs[0], exc.ClientException)
Exemple #9
0
    def test_retries_on_ironicclient_error(self):
        self.call.side_effect = [ironic_exc.ClientException('boom')] * 3 + [
            mock.sentinel.result
        ]

        result = ir_utils.call_with_retries(self.call, 'meow', answer=42)
        self.assertEqual(result, mock.sentinel.result)
        self.call.assert_called_with('meow', answer=42)
        self.assertEqual(4, self.call.call_count)
 def test_create_single_node_raises_client_exception(self):
     params = {'driver': 'fake'}
     e = exc.ClientException('foo')
     self.client.node.create.side_effect = e
     res, err = create_resources.create_single_node(self.client, **params)
     self.assertIsNone(res)
     self.assertIsInstance(err, exc.ClientException)
     self.assertIn('Unable to create the node', str(err))
     self.client.node.create.assert_called_once_with(driver='fake')
Exemple #11
0
 def test_retries_on_ironicclient_error_with_failure(self):
     self.call.side_effect = ironic_exc.ClientException('boom')
     self.assertRaisesRegexp(ironic_exc.ClientException,
                             'boom',
                             ir_utils.call_with_retries,
                             self.call,
                             'meow',
                             answer=42)
     self.call.assert_called_with('meow', answer=42)
     self.assertEqual(5, self.call.call_count)
 def test_create_portgroups_exception(self, mock_create_ports):
     portgroup = {'name': 'fake', 'ports': ['list of ports']}
     portgroup_posted = {'name': 'fake', 'node_uuid': 'fake-node-uuid'}
     self.client.portgroup.create.side_effect = exc.ClientException('bar')
     errs = create_resources.create_portgroups(self.client, [portgroup],
                                               node_uuid='fake-node-uuid')
     self.client.portgroup.create.assert_called_once_with(
         **portgroup_posted)
     self.assertFalse(mock_create_ports.called)
     self.assertEqual(1, len(errs))
     self.assertIsInstance(errs[0], exc.ClientException)
 def test_create_resources_ironic_fails_to_create(self, mock_load,
                                                  mock_validate,
                                                  mock_chassis, mock_nodes):
     mock_nodes.return_value = [exc.ClientException('cannot create that')]
     mock_chassis.return_value = []
     resources_files = ['file.json']
     self.assertRaises(exc.ClientException,
                       create_resources.create_resources, self.client,
                       resources_files)
     mock_load.assert_has_calls([mock.call('file.json')])
     mock_validate.assert_called_once_with(ironic_pov_invalid_json,
                                           mock.ANY)
     mock_chassis.assert_called_once_with(self.client, [])
     mock_nodes.assert_called_once_with(self.client,
                                        ironic_pov_invalid_json['nodes'])
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)", parsed_args)

        baremetal_client = self.app.client_manager.baremetal

        failures = []
        for node in parsed_args.nodes:
            try:
                baremetal_client.node.delete(node)
                print(_('Deleted node %s') % node)
            except exc.ClientException as e:
                failures.append(_("Failed to delete node %(node)s: %(error)s")
                                % {'node': node, 'error': e})

        if failures:
            raise exc.ClientException("\n".join(failures))
Exemple #15
0
 def wrapper(client, **params):
     uuid = None
     error = None
     try:
         uuid = create_method(client, **params)
     except exc.InvalidAttribute as e:
         error = exc.InvalidAttribute(
             'Cannot create the %(resource)s with attributes '
             '%(params)s. One or more attributes are invalid: %(err)s' %
             {'params': params, 'resource': resource_type, 'err': e}
         )
     except Exception as e:
         error = exc.ClientException(
             'Unable to create the %(resource)s with the specified '
             'attributes: %(params)s. The error is: %(error)s' %
             {'error': e, 'resource': resource_type, 'params': params})
     return uuid, error
Exemple #16
0
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)", parsed_args)

        baremetal_client = self.app.client_manager.baremetal

        failures = []
        for chassis in parsed_args.chassis:
            try:
                baremetal_client.chassis.delete(chassis)
                print(_('Deleted chassis %s') % chassis)
            except exc.ClientException as e:
                failures.append(_("Failed to delete chassis %(chassis)s: "
                                  "%(error)s")
                                % {'chassis': chassis, 'error': e})

        if failures:
            raise exc.ClientException("\n".join(failures))
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)", parsed_args)

        baremetal_client = self.app.client_manager.baremetal

        failures = []
        for portgroup in parsed_args.portgroups:
            try:
                baremetal_client.portgroup.delete(portgroup)
                print(_('Deleted port group %s') % portgroup)
            except exc.ClientException as e:
                failures.append(_("Failed to delete port group %(portgroup)s: "
                                  " %(error)s")
                                % {'portgroup': portgroup, 'error': e})

        if failures:
            raise exc.ClientException("\n".join(failures))
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)", parsed_args)

        baremetal_client = self.app.client_manager.baremetal

        failures = []
        for allocation in parsed_args.allocations:
            try:
                baremetal_client.allocation.delete(allocation)
                print(_('Deleted allocation %s') % allocation)
            except exc.ClientException as e:
                failures.append(
                    _("Failed to delete allocation "
                      "%(allocation)s:  %(error)s") % {
                          'allocation': allocation,
                          'error': e
                      })

        if failures:
            raise exc.ClientException("\n".join(failures))
Exemple #19
0
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)", parsed_args)

        baremetal_client = self.app.client_manager.baremetal

        failures = []
        for volume_target in parsed_args.volume_targets:
            try:
                baremetal_client.volume_target.delete(volume_target)
                print(_('Deleted volume target %s') % volume_target)
            except exc.ClientException as e:
                failures.append(
                    _("Failed to delete volume target "
                      "%(volume_target)s: %(error)s") % {
                          'volume_target': volume_target,
                          'error': e
                      })

        if failures:
            raise exc.ClientException("\n".join(failures))
Exemple #20
0
    def take_action(self, parsed_args):
        self.log.debug("take_action(%s)", parsed_args)

        baremetal_client = self.app.client_manager.baremetal

        failures = []
        for template in parsed_args.templates:
            try:
                baremetal_client.deploy_template.delete(template)
                print(_('Deleted deploy template %s') % template)
            except exc.ClientException as e:
                failures.append(
                    _("Failed to delete deploy template "
                      "%(template)s: %(error)s") % {
                          'template': template,
                          'error': e
                      })

        if failures:
            raise exc.ClientException("\n".join(failures))