~ntt-pf-lab/nova/monkey_patch_notification

« back to all changes in this revision

Viewing changes to nova/compute/model.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4 expandtab
 
2
# Copyright [2010] [Anso Labs, LLC]
 
3
#
 
4
#    Licensed under the Apache License, Version 2.0 (the "License");
 
5
#    you may not use this file except in compliance with the License.
 
6
#    You may obtain a copy of the License at
 
7
#
 
8
#        http://www.apache.org/licenses/LICENSE-2.0
 
9
#
 
10
#    Unless required by applicable law or agreed to in writing, software
 
11
#    distributed under the License is distributed on an "AS IS" BASIS,
 
12
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
#    See the License for the specific language governing permissions and
 
14
#    limitations under the License.
 
15
 
 
16
"""
 
17
Datastore Model objects for Compute Instances, with
 
18
InstanceDirectory manager.
 
19
 
 
20
# Create a new instance?
 
21
>>> InstDir = InstanceDirectory()
 
22
>>> inst = InstDir.new()
 
23
>>> inst.destroy()
 
24
True
 
25
>>> inst = InstDir['i-123']
 
26
>>> inst['ip'] = "192.168.0.3"
 
27
>>> inst['owner_id'] = "projectA"
 
28
>>> inst.save()
 
29
True
 
30
 
 
31
>>> InstDir['i-123']
 
32
<Instance:i-123>
 
33
>>> InstDir.all.next()
 
34
<Instance:i-123>
 
35
 
 
36
>>> inst.destroy()
 
37
True
 
38
"""
 
39
 
 
40
from nova import vendor
 
41
 
 
42
from nova import datastore
 
43
from nova import flags
 
44
from nova import utils
 
45
 
 
46
 
 
47
FLAGS = flags.FLAGS
 
48
 
 
49
 
 
50
# TODO(ja): singleton instance of the directory
 
51
class InstanceDirectory(object):
 
52
    """an api for interacting with the global state of instances """
 
53
    def __init__(self):
 
54
        self.keeper = datastore.Keeper(FLAGS.instances_prefix)
 
55
 
 
56
    def get(self, instance_id):
 
57
        """ returns an instance object for a given id """
 
58
        return Instance(instance_id)
 
59
 
 
60
    def __getitem__(self, item):
 
61
        return self.get(item)
 
62
 
 
63
    def by_project(self, project):
 
64
        """ returns a list of instance objects for a project """
 
65
        for instance_id in self.keeper['project:%s:instances' % project]:
 
66
            yield Instance(instance_id)
 
67
 
 
68
    def by_node(self, node_id):
 
69
        """ returns a list of instances for a node """
 
70
        for instance in self.all:
 
71
            if instance['node_name'] == node_id:
 
72
                yield instance
 
73
 
 
74
    def by_ip(self, ip_address):
 
75
        """ returns an instance object that is using the IP """
 
76
        for instance in self.all:
 
77
            if instance['private_dns_name'] == ip_address:
 
78
                return instance
 
79
        return None
 
80
 
 
81
    def by_volume(self, volume_id):
 
82
        """ returns the instance a volume is attached to """
 
83
        pass
 
84
 
 
85
    def exists(self, instance_id):
 
86
        if instance_id in self.keeper['instances']:
 
87
            return True
 
88
        return False
 
89
 
 
90
    @property
 
91
    def all(self):
 
92
        """ returns a list of all instances """
 
93
        instances = self.keeper['instances']
 
94
        if instances != None:
 
95
            for instance_id in self.keeper['instances']:
 
96
                yield Instance(instance_id)
 
97
 
 
98
    def new(self):
 
99
        """ returns an empty Instance object, with ID """
 
100
        instance_id = utils.generate_uid('i')
 
101
        return self.get(instance_id)
 
102
 
 
103
 
 
104
 
 
105
class Instance(object):
 
106
    """ Wrapper around stored properties of an instance """
 
107
 
 
108
    def __init__(self, instance_id):
 
109
        """ loads an instance from the datastore if exists """
 
110
        self.keeper = datastore.Keeper(FLAGS.instances_prefix)
 
111
        self.instance_id = instance_id
 
112
        self.initial_state = {}
 
113
        self.state = self.keeper[self.__redis_key]
 
114
        if self.state:
 
115
            self.initial_state = self.state
 
116
        else:
 
117
            self.state = {'state' : 'pending',
 
118
                          'instance_id' : instance_id,
 
119
                          'node_name' : 'unassigned',
 
120
                          'owner_id' : 'unassigned' }
 
121
 
 
122
    @property
 
123
    def __redis_key(self):
 
124
        """ Magic string for instance keys """
 
125
        return 'instance:%s' % self.instance_id
 
126
 
 
127
    def __repr__(self):
 
128
        return "<Instance:%s>" % self.instance_id
 
129
 
 
130
    def get(self, item, default):
 
131
        return self.state.get(item, default)
 
132
 
 
133
    def __getitem__(self, item):
 
134
        return self.state[item]
 
135
 
 
136
    def __setitem__(self, item, val):
 
137
        self.state[item] = val
 
138
        return self.state[item]
 
139
 
 
140
    def __delitem__(self, item):
 
141
        """ We don't support this """
 
142
        raise Exception("Silly monkey, Instances NEED all their properties.")
 
143
 
 
144
    def save(self):
 
145
        """ update the directory with the state from this instance
 
146
            make sure you've set the owner_id before you call save
 
147
            for the first time.
 
148
        """
 
149
        # TODO(ja): implement hmset in redis-py and use it
 
150
        # instead of multiple calls to hset
 
151
        state = self.keeper[self.__redis_key]
 
152
        if not state:
 
153
            state = {}
 
154
        for key, val in self.state.iteritems():
 
155
            # if (not self.initial_state.has_key(key)
 
156
            # or self.initial_state[key] != val):
 
157
                state[key] = val
 
158
        self.keeper[self.__redis_key] = state
 
159
        if self.initial_state == {}:
 
160
            self.keeper.set_add('project:%s:instances' % self.state['owner_id'],
 
161
                                self.instance_id)
 
162
            self.keeper.set_add('instances', self.instance_id)
 
163
        self.initial_state = self.state
 
164
        return True
 
165
 
 
166
    def destroy(self):
 
167
        """ deletes all related records from datastore.
 
168
         does NOT do anything to running libvirt state.
 
169
        """
 
170
        self.keeper.set_remove('project:%s:instances' % self.state['owner_id'],
 
171
                               self.instance_id)
 
172
        del self.keeper[self.__redis_key]
 
173
        self.keeper.set_remove('instances', self.instance_id)
 
174
        return True
 
175
 
 
176
    @property
 
177
    def volumes(self):
 
178
        """ returns a list of attached volumes """
 
179
        pass
 
180
 
 
181
    @property
 
182
    def reservation(self):
 
183
        """ Returns a reservation object """
 
184
        pass
 
185
 
 
186
# class Reservation(object):
 
187
#     """ ORM wrapper for a batch of launched instances """
 
188
#     def __init__(self):
 
189
#         pass
 
190
#
 
191
#     def userdata(self):
 
192
#         """ """
 
193
#         pass
 
194
#
 
195
#
 
196
# class NodeDirectory(object):
 
197
#     def __init__(self):
 
198
#         pass
 
199
#
 
200
 
 
201
if __name__ == "__main__":
 
202
    import doctest
 
203
    doctest.testmod()