reorganized
[sfa.git] / sfa / openstack / osaggregate.py
1 from nova.exception import ImageNotFound
2 from sfa.util.faults import SfaAPIError
3 from sfa.rspecs.rspec import RSpec
4 from sfa.rspecs.elements.hardware_type import HardwareType
5 from sfa.rspecs.elements.node import Node
6 from sfa.rspecs.elements.sliver import Sliver
7 from sfa.rspecs.elements.login import Login
8 from sfa.rspecs.elements.disk_image import DiskImage
9 from sfa.rspecs.elements.services import Services
10 from sfa.util.xrn import Xrn
11 from sfa.util.osxrn import OSXrn
12 from sfa.rspecs.version_manager import VersionManager
13
14
15 class OSAggregate:
16
17     def __init__(self, driver):
18         self.driver = driver
19
20     def instance_to_sliver(self, instance, slice_xrn=None):
21         # should include? 
22         # * instance.image_ref
23         # * instance.kernel_id
24         # * instance.ramdisk_id 
25         import nova.db.sqlalchemy.models
26         name=None
27         type=None
28         sliver_id = None
29         if isinstance(instance, dict):
30             # this is an isntance type dict
31             name = instance['name']
32             type = instance['name'] 
33         elif isinstance(instance, nova.db.sqlalchemy.models.Instance):
34             # this is an object that describes a running instance
35             name = instance.display_name
36             type = instance.instance_type.name
37         else:
38             raise SfaAPIError("instnace must be an instance_type dict or" + \
39                                " a nova.db.sqlalchemy.models.Instance object")
40         if slice_xrn:
41             xrn = Xrn(slice_xrn, 'slice')
42             sliver_id = xrn.get_sliver_id(instance.project_id, instance.hostname, instance.id)     
43     
44         sliver = Sliver({'slice_id': sliver_id,
45                          'name': name,
46                          'type': 'plos-' + type,
47                          'tags': []})
48         return sliver
49
50     def get_disk_images(self, image_id=None):
51         # get image records
52         if image_id:
53             try:
54                 images = [self.driver.shell.image_manager.show(image_id)]
55             except ImageNotFound:
56                 images = []
57         else:
58             images = self.driver.shell.image_manager.detail()
59             
60         disk_images = []
61         # create disk image objects 
62         for image in images:
63             if image['container_format'] == 'ami':
64                 img = DiskImage()
65                 img['name'] = image['name']
66                 img['description'] = image['name']
67                 img['os'] = image['name']
68                 img['version'] = image['name']
69                 disk_images.append(img)
70         return disk_images
71
72     def get_rspec(self, slice_xrn=None, version=None, options={}):
73         version_manager = VersionManager()
74         version = version_manager.get_version(version)
75         if not slice_xrn:
76             rspec_version = version_manager._get_version(version.type, version.version, 'ad')
77             nodes = self.get_aggregate_nodes()
78         else:
79             rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
80             nodes = self.get_slice_nodes(slice_xrn)
81         rspec = RSpec(version=rspec_version, user_options=options)
82         rspec.version.add_nodes(nodes)
83         return rspec.toxml()
84
85     def get_slice_nodes(self, slice_xrn):
86         name = OSXrn(xrn = slice_xrn).name
87         instances = self.driver.shell.db.instance_get_all_by_project(name)
88         rspec_nodes = []
89         for instance in instances:
90             rspec_node = Node()
91             xrn = OSXrn(instance.hostname, 'node')
92             rspec_node['component_id'] = xrn.urn
93             rspec_node['component_name'] = xrn.name
94             rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()   
95             sliver = self.instance_to_sliver(instance)
96             sliver['disk_images'] = self.get_disk_images(instance.image_ref) 
97             rspec_node['slivers'] = [sliver]
98             rspec_nodes.append(rspec_node)
99         return rspec_nodes
100
101     def get_aggregate_nodes(self):
102                 
103         zones = self.driver.shell.db.zone_get_all()
104         if not zones:
105             zones = ['cloud']
106         else:
107             zones = [zone.name for zone in zones]
108
109         # available sliver/instance/vm types
110         instances = self.driver.shell.db.instance_type_get_all().values()
111         # available images
112         disk_images = self.get_disk_images()
113         
114         rspec_nodes = []
115         for zone in zones:
116             rspec_node = Node()
117             xrn = OSXrn(zone, 'node')
118             rspec_node['component_id'] = xrn.urn
119             rspec_node['component_name'] = xrn.name
120             rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()
121             rspec_node['exclusive'] = 'false'
122             rspec_node['hardware_types'] = [HardwareType({'name': 'plos-pc'}),
123                                                 HardwareType({'name': 'pc'})]
124             slivers = []
125             for instance in instances:
126                 sliver = self.instance_to_sliver(instance)
127                 sliver['disk_images'] = disk_images
128                 slivers.append(sliver)
129         
130             rspec_node['slivers'] = slivers
131             rspec_nodes.append(rspec_node) 
132
133         return rspec_nodes 
134
135
136     def verify_slice(self, slicename, users, options={}):
137         """
138         Create the slice if it doesn't alredy exist  
139         """
140         import nova.exception.ProjectNotFound
141         try:
142             slice = self.driver.shell.auth_manager.get_project(slicename)
143         except nova.exception.ProjectNotFound:
144             # convert urns to user names
145             usernames = [Xrn(user['urn']).get_leaf() for user in users]
146             # assume that the first user is the project manager
147             proj_manager = usernames[0] 
148             self.driver.shell.auth_manager.create_project(slicename, proj_manager)
149
150     def verify_slice_users(self, slicename, users, options={}):
151         """
152         Add requested users to the specified slice.  
153         """
154         
155         # There doesn't seem to be an effcient way to 
156         # look up all the users of a project, so lets not  
157         # attempt to remove stale users . For now lets just
158         # ensure that the specified users exist     
159         for user in users:
160             username = Xrn(user['urn']).get_leaf()
161             try:
162                 self.driver.shell.auth_manager.get_user(username)
163             except nova.exception.UserNotFound:
164                 self.driver.shell.auth_manager.create_user(username)
165             self.verify_user_keys(username, user['keys'], options)
166
167     def verify_user_keys(self, username, keys, options={}):
168         """
169         Add requested keys.
170         """
171         append = options.get('append', True)    
172         existing_keys = self.driver.shell.db.key_pair_get_all_by_user(username)
173         existing_pub_keys = [key.public_key for key in existing_keys]
174         removed_pub_keys = set(existing_pub_keys).difference(keys)
175         added_pub_keys = set(keys).difference(existing_pub_keys)
176
177         # add new keys
178         for public_key in added_pub_keys:
179             key = {}
180             key['user_id'] = username
181             key['name'] =  username
182             key['public'] = public_key
183             self.driver.shell.db.key_pair_create(key)
184
185         # remove old keys
186         if not append:
187             for key in existing_keys:
188                 if key.public_key in removed_pub_keys:
189                     self.driver.shell.db.key_pair_destroy(username, key.name)
190             
191     def verify_instances(self, slicename, rspec):
192         rsepc = RSpec(rspec)
193         nodes = rspec.version.get_nodes_with_slivers()
194         old_instances = self.driver.shell.db.instance_get_all_by_project(name)
195         for node in nodes:
196             for slivers in node.get('slivers', []):
197                 pass
198                 # get instance type
199                 # get image
200                 # start instance