1
# vim: tabstop=4 shiftwidth=4 softtabstop=4 expandtab
2
# Copyright [2010] [Anso Labs, LLC]
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
8
# http://www.apache.org/licenses/LICENSE-2.0
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.
17
Datastore Model objects for Compute Instances, with
18
InstanceDirectory manager.
20
# Create a new instance?
21
>>> InstDir = InstanceDirectory()
22
>>> inst = InstDir.new()
25
>>> inst = InstDir['i-123']
26
>>> inst['ip'] = "192.168.0.3"
27
>>> inst['owner_id'] = "projectA"
33
>>> InstDir.all.next()
40
from nova import vendor
42
from nova import datastore
43
from nova import flags
44
from nova import utils
50
# TODO(ja): singleton instance of the directory
51
class InstanceDirectory(object):
52
"""an api for interacting with the global state of instances """
54
self.keeper = datastore.Keeper(FLAGS.instances_prefix)
56
def get(self, instance_id):
57
""" returns an instance object for a given id """
58
return Instance(instance_id)
60
def __getitem__(self, item):
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)
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:
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:
81
def by_volume(self, volume_id):
82
""" returns the instance a volume is attached to """
85
def exists(self, instance_id):
86
if instance_id in self.keeper['instances']:
92
""" returns a list of all instances """
93
instances = self.keeper['instances']
95
for instance_id in self.keeper['instances']:
96
yield Instance(instance_id)
99
""" returns an empty Instance object, with ID """
100
instance_id = utils.generate_uid('i')
101
return self.get(instance_id)
105
class Instance(object):
106
""" Wrapper around stored properties of an instance """
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]
115
self.initial_state = self.state
117
self.state = {'state' : 'pending',
118
'instance_id' : instance_id,
119
'node_name' : 'unassigned',
120
'owner_id' : 'unassigned' }
123
def __redis_key(self):
124
""" Magic string for instance keys """
125
return 'instance:%s' % self.instance_id
128
return "<Instance:%s>" % self.instance_id
130
def get(self, item, default):
131
return self.state.get(item, default)
133
def __getitem__(self, item):
134
return self.state[item]
136
def __setitem__(self, item, val):
137
self.state[item] = val
138
return self.state[item]
140
def __delitem__(self, item):
141
""" We don't support this """
142
raise Exception("Silly monkey, Instances NEED all their properties.")
145
""" update the directory with the state from this instance
146
make sure you've set the owner_id before you call save
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]
154
for key, val in self.state.iteritems():
155
# if (not self.initial_state.has_key(key)
156
# or self.initial_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'],
162
self.keeper.set_add('instances', self.instance_id)
163
self.initial_state = self.state
167
""" deletes all related records from datastore.
168
does NOT do anything to running libvirt state.
170
self.keeper.set_remove('project:%s:instances' % self.state['owner_id'],
172
del self.keeper[self.__redis_key]
173
self.keeper.set_remove('instances', self.instance_id)
178
""" returns a list of attached volumes """
182
def reservation(self):
183
""" Returns a reservation object """
186
# class Reservation(object):
187
# """ ORM wrapper for a batch of launched instances """
188
# def __init__(self):
191
# def userdata(self):
196
# class NodeDirectory(object):
197
# def __init__(self):
201
if __name__ == "__main__":