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