~ubuntu-branches/ubuntu/vivid/ironic/vivid-updates

« back to all changes in this revision

Viewing changes to ironic/api/controllers/v1/node.py

  • Committer: Package Import Robot
  • Author(s): Adam Gandelman, Adam Gandelman, James Page
  • Date: 2014-04-04 11:54:02 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20140404115402-wz51btzqxomdizv0
Tags: 2014.1~rc1-0ubuntu1
[ Adam Gandelman ]
* debian/ironic-common.postinst: Fix syntax preventing postinst
  from running.
* debian/ironic-api.install: Create missing .install, install
  ironic-api to /usr/bin/ironic-api.
* debian/patches/set_logdir.patch: Set log_dir to /var/log/ironic/ in
  sample config, causing both daemons to log to respective files there.
* debian/{rules, ironic-common.install}: Install ironic.conf.sample
  as /etc/ironic/ironic.conf.
* Fail build if test suite fails, limit testing concurrency to 1.
* debian/control: Add missing alembic, python-lockfile dependencies.

[ James Page ]
* d/control: Add Vcs-* fields for ubuntu-server-dev branches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
from wsme import types as wtypes
25
25
import wsmeext.pecan as wsme_pecan
26
26
 
27
 
from ironic.api.controllers.v1 import base
 
27
from ironic.api.controllers import base
 
28
from ironic.api.controllers import link
28
29
from ironic.api.controllers.v1 import collection
29
 
from ironic.api.controllers.v1 import link
30
30
from ironic.api.controllers.v1 import port
31
31
from ironic.api.controllers.v1 import types
32
32
from ironic.api.controllers.v1 import utils as api_utils
34
34
from ironic.common import states as ir_states
35
35
from ironic.common import utils
36
36
from ironic import objects
37
 
from ironic.openstack.common import excutils
38
 
from ironic.openstack.common import log
39
37
 
40
38
 
41
39
CONF = cfg.CONF
42
40
CONF.import_opt('heartbeat_timeout', 'ironic.conductor.manager',
43
41
                group='conductor')
44
42
 
45
 
LOG = log.getLogger(__name__)
46
 
 
47
43
 
48
44
class NodePatchType(types.JsonPatchType):
49
45
 
114
110
            setattr(states, attr, getattr(rpc_node, attr))
115
111
        return states
116
112
 
 
113
    @classmethod
 
114
    def sample(cls):
 
115
        sample = cls(target_power_state=ir_states.POWER_ON,
 
116
                     target_provision_state=ir_states.ACTIVE,
 
117
                     last_error=None,
 
118
                     console_enabled=False,
 
119
                     provision_updated_at=None,
 
120
                     power_state=ir_states.POWER_ON,
 
121
                     provision_state=None)
 
122
        return sample
 
123
 
117
124
 
118
125
class NodeStatesController(rest.RestController):
119
126
 
191
198
        rpc_node = objects.Node.get_by_uuid(pecan.request.context, node_uuid)
192
199
        topic = pecan.request.rpcapi.get_topic_for(rpc_node)
193
200
 
194
 
        if rpc_node.target_provision_state is not None:
195
 
            msg = _('Node %s is already being provisioned.') % rpc_node['uuid']
196
 
            LOG.exception(msg)
197
 
            raise wsme.exc.ClientSideError(msg, status_code=409)  # Conflict
198
 
 
199
201
        if target == rpc_node.provision_state:
200
202
            msg = (_("Node %(node)s is already in the '%(state)s' state.") %
201
203
                   {'node': rpc_node['uuid'], 'state': target})
202
 
            LOG.exception(msg)
203
204
            raise wsme.exc.ClientSideError(msg, status_code=400)
 
205
 
 
206
        if target == ir_states.ACTIVE:
 
207
            processing = rpc_node.target_provision_state is not None
 
208
        elif target == ir_states.DELETED:
 
209
            processing = (rpc_node.target_provision_state is not None and
 
210
                        rpc_node.provision_state != ir_states.DEPLOYWAIT)
 
211
        else:
 
212
            raise exception.InvalidStateRequested(state=target, node=node_uuid)
 
213
 
 
214
        if processing:
 
215
            msg = (_('Node %s is already being provisioned or decommissioned.')
 
216
                   % rpc_node.uuid)
 
217
            raise wsme.exc.ClientSideError(msg, status_code=409)  # Conflict
 
218
 
204
219
        # Note that there is a race condition. The node state(s) could change
205
220
        # by the time the RPC call is made and the TaskManager manager gets a
206
221
        # lock.
211
226
        elif target == ir_states.DELETED:
212
227
            pecan.request.rpcapi.do_node_tear_down(
213
228
                    pecan.request.context, node_uuid, topic)
214
 
        else:
215
 
            raise exception.InvalidStateRequested(state=target, node=node_uuid)
216
229
        # FIXME(lucasagomes): Currently WSME doesn't support returning
217
230
        # the Location header. Once it's implemented we should use the
218
231
        # Location to point to the /states subresource of this node so
605
618
            e.code = 400
606
619
            raise e
607
620
 
608
 
        try:
609
 
            new_node = pecan.request.dbapi.create_node(node.as_dict())
610
 
        except Exception as e:
611
 
            with excutils.save_and_reraise_exception():
612
 
                LOG.exception(e)
 
621
        new_node = pecan.request.dbapi.create_node(node.as_dict())
 
622
 
613
623
        return Node.convert_with_links(new_node)
614
624
 
615
625
    @wsme.validate(types.uuid, [NodePatchType])
656
666
            e.code = 400
657
667
            raise e
658
668
 
659
 
        try:
660
 
            new_node = pecan.request.rpcapi.update_node(
661
 
                    pecan.request.context, rpc_node, topic)
662
 
        except Exception as e:
663
 
            with excutils.save_and_reraise_exception():
664
 
                LOG.exception(e)
 
669
        new_node = pecan.request.rpcapi.update_node(
 
670
                         pecan.request.context, rpc_node, topic)
665
671
 
666
672
        return Node.convert_with_links(new_node)
667
673