11import json
22import logging
3- import os
43
5- from .http import HttpMixin , use_admin_auth , endpoint
6- from .exceptions import StackException
4+ from .http import use_admin_auth , endpoint
5+ from .exceptions import BlueprintException , StackException
6+
7+ from .blueprint import BlueprintMixin
8+ from .formula import FormulaMixin
9+ from .profile import ProfileMixin
10+ from .provider import ProviderMixin
11+ from .region import RegionMixin
12+ from .settings import SettingsMixin
13+ from .stack import StackMixin
14+
15+ from .version import _parse_version_string
716
817logger = logging .getLogger (__name__ )
918
1019
11- class StackdIO (HttpMixin ):
20+ class StackdIO (BlueprintMixin , FormulaMixin , ProfileMixin ,
21+ ProviderMixin , RegionMixin , StackMixin , SettingsMixin ):
1222
13- def __init__ (self ,
14- protocol = "https" ,
15- host = "localhost" ,
16- port = 443 ,
17- base_url = None ,
18- auth = None ,
19- auth_admin = None ,
23+ def __init__ (self , protocol = "https" , host = "localhost" , port = 443 ,
24+ base_url = None , auth = None , auth_admin = None ,
2025 verify = False ):
2126 """auth_admin is optional, only needed for creating provider, profile,
2227 and base security groups"""
@@ -33,112 +38,16 @@ def __init__(self,
3338 self .auth = auth
3439 self .auth_admin = auth_admin
3540
41+ _ , self .version = _parse_version_string (self .get_version ())
42+
3643 @endpoint ("" )
3744 def get_root (self ):
3845 """Get the api root"""
3946 return self ._get (endpoint , jsonify = True )
4047
41-
42- @use_admin_auth
43- @endpoint ("providers/" )
44- def create_provider (self , ** kwargs ):
45- """Create a provider"""
46-
47- form_data = {
48- "title" : None ,
49- "account_id" : None ,
50- "provider_type" : None ,
51- "access_key_id" : None ,
52- "secret_access_key" : None ,
53- "keypair" : None ,
54- "security_groups" : None ,
55- "route53_domain" : None ,
56- "default_availability_zone" : None ,
57- "private_key" : None
58- }
59-
60- for key in form_data .keys ():
61- form_data [key ] = kwargs .get (key )
62-
63- return self ._post (endpoint , data = json .dumps (form_data ), jsonify = True )
64-
65-
66- @endpoint ("providers/" )
67- def get_provider (self , title , provider_name ):
68- """Look for and return a provider"""
69-
70- result = self ._get (endpoint , jsonify = True )
71- for provider in result ['results' ]:
72- if provider .get ("title" ) == title and \
73- provider .get ("provider_type_name" ) == provider_name :
74-
75- return provider
76-
77- raise StackException ("Provider %s not found" % title )
78-
79-
80- @use_admin_auth
81- @endpoint ("providers/" )
82- def create_profile (self , title , image_id , ssh_user , cloud_provider ,
83- default_instance_size = None ):
84- """Create a profile"""
85- data = {
86- "title" : title ,
87- "image_id" : image_id ,
88- "ssh_user" : ssh_user ,
89- "cloud_provider" : cloud_provider ,
90- "default_instance_size" : default_instance_size
91- }
92- return self ._post (endpoint , data = json .dumps (data ), jsonify = True )
93-
94-
95- @endpoint ("profiles/" )
96- def get_profile (self , title , cloud_provider ):
97- """Look for and return a profile"""
98-
99- result = self ._get (endpoint , jsonify = True )
100-
101- for profile in result ['results' ]:
102- if profile .get ("title" ) == title and \
103- profile .get ("cloud_provider" ) == cloud_provider :
104- return profile
105-
106- return None
107-
108-
109- @endpoint ("formulas/" )
110- def import_formula (self , formula_uri , public = True ):
111- """Import a formula"""
112- data = {
113- "uri" : formula_uri ,
114- "public" : public ,
115- }
116- return self ._post (endpoint , data = json .dumps (data ), jsonify = True )
117-
118-
119- @endpoint ("blueprints/" )
120- def create_blueprint (self , blueprint , provider = "ec2" ):
121- """Create a blueprint"""
122-
123- # check the provided blueprint to see if we need to look up any ids
124- for host in blueprint ["hosts" ]:
125- if isinstance (host ["size" ], str ):
126- host ["size" ] = self .get_instance_id (host ["size" ], provider )
127-
128- if isinstance (host ["zone" ], str ):
129- host ["zone" ] = self .get_zone (host ["zone" ], provider )
130-
131- if isinstance (host ["cloud_profile" ], str ):
132- host ["cloud_profile" ] = self .get_profile_id (host ["cloud_profile" ])
133-
134- for component in host ["formula_components" ]:
135- if isinstance (component ["id" ], (tuple , list )):
136- component ["id" ] = self .get_component_id (
137- self .get_formula (component ["id" ][0 ]),
138- component ["id" ][1 ])
139-
140- return self ._post (endpoint , data = json .dumps (blueprint ), jsonify = True )
141-
48+ @endpoint ("version/" )
49+ def get_version (self ):
50+ return self ._get (endpoint , jsonify = True )['version' ]
14251
14352 @endpoint ("blueprints/{blueprint_id}/" )
14453 def delete_blueprint (self , blueprint_id ):
@@ -161,7 +70,6 @@ def create_security_group(self, name, description, cloud_provider, is_default=Tr
16170 }
16271 return self ._post (endpoint , data = json .dumps (data ), jsonify = True )
16372
164-
16573 @endpoint ("settings/" )
16674 def get_public_key (self ):
16775 """Get the public key for the logged in uesr"""
@@ -182,140 +90,6 @@ def set_public_key(self, public_key):
18290 }
18391 return self ._put (endpoint , data = json .dumps (data ), jsonify = True )
18492
185-
186- @endpoint ("formulas/" )
187- def get_formulas (self ):
188- """Return all formulas"""
189- return self ._get (endpoint , jsonify = True )['results' ]
190-
191-
192- def get_formula (self , title ):
193- """Get a formula that matches title"""
194-
195- for formula in self .get_formulas ():
196- if formula .get ("title" ) == title :
197- return formula
198-
199- raise StackException ("Formula %s not found" % title )
200-
201-
202- def get_formula_id (self , title ):
203- """Get the id for a formula that matches title. If component_title is
204- provided, find and return the component id"""
205-
206- formula = self .get_formula (title )
207- return formula .get ("id" )
208-
209-
210- def get_component_id (self , formula , component_title ):
211- """Get the id for a component from formula_id that matches title"""
212-
213- for component in formula .get ("components" ):
214- if component .get ("title" ) == component_title :
215- return component .get ("id" )
216-
217- raise StackException ("Component %s not found for formula %s" %
218- (component_title , formula .get ("title" )))
219-
220-
221- @endpoint ("providers/" )
222- def get_provider_id (self , slug , title = False ):
223- """Get the id for a provider that matches slug. If title is True will
224- look at title instead."""
225-
226- result = self ._get (endpoint , jsonify = True )
227-
228- for provider in result ['results' ]:
229- if provider .get ("slug" if not title else "title" ) == slug :
230- return provider .get ("id" )
231-
232- raise StackException ("Provider %s not found" % slug )
233-
234-
235- @endpoint ("profiles/" )
236- def get_profile_id (self , slug , title = False ):
237- """Get the id for a profile that matches slug. If title is True will look
238- at title instead."""
239-
240- result = self ._get (endpoint , jsonify = True )
241-
242- for profile in result ['results' ]:
243- if profile .get ("slug" if not title else "title" ) == slug :
244- return profile .get ("id" )
245-
246- return StackException ("Provider %s not found" % slug )
247-
248-
249- @endpoint ("stacks/" )
250- def get_stacks (self ):
251- """Return a list of all stacks"""
252- return self ._get (endpoint , jsonify = True )['results' ]
253-
254-
255- @endpoint ("stacks/{stack_id}/" )
256- def get_stack (self , stack_id ):
257- """Get stack info"""
258- result = self ._get (endpoint , none_on_404 = True , jsonify = True )
259- if result is None :
260- raise StackException ("Stack %s not found" % stack_id )
261- else :
262- return result
263-
264-
265- @endpoint ("stacks/{stack_id}/history/" )
266- def get_stack_history (self , stack_id ):
267- """Get stack info"""
268- result = self ._get (endpoint , none_on_404 = True , jsonify = True )
269- if result is None :
270- raise StackException ("Stack %s not found" % stack_id )
271- else :
272- return result
273-
274-
275- @endpoint ("stacks/" )
276- def get_stack_id (self , title ):
277- """Find a stack id"""
278-
279- result = self ._get (endpoint , jsonify = True )
280- try :
281- for stack in result ['results' ]:
282- if stack .get ("title" ) == title :
283- return stack .get ("id" )
284- except TypeError , e :
285- logger .error ("Error querying stacks: %s" , e )
286-
287- raise StackException ("Stack %s not found" % title )
288-
289-
290- @endpoint ("stacks/{stack_id}/hosts/" )
291- def get_stack_hosts (self , stack_id ):
292- """Get a list of all stack hosts"""
293- return self ._get (endpoint , jsonify = True )['results' ]
294-
295-
296- @endpoint ("blueprints/" )
297- def get_blueprints (self ):
298- """Returns all the blueprints"""
299- return self ._get (endpoint , jsonify = True )['results' ]
300-
301-
302- @endpoint ("blueprints/{blueprint_id}/" )
303- def get_blueprint (self , blueprint_id ):
304- """Return info for a specific blueprint_id"""
305- return self ._get (endpoint , jsonify = True )
306-
307-
308- @endpoint ("blueprints/" )
309- def get_blueprint_id (self , title ):
310- """Get the id for a blueprint that matches title"""
311- result = self ._get (endpoint , params = {"title" : title }, jsonify = True )
312-
313- if not result .get ('count' ) == 1 :
314- raise StackException ("Blueprint %s not found" % title )
315-
316- return result ['results' ][0 ]['id' ]
317-
318-
31993 @endpoint ("instance_sizes/" )
32094 def get_instance_id (self , instance_id , provider_type = "ec2" ):
32195 """Get the id for an instance_id. The instance_id parameter is the
@@ -330,88 +104,3 @@ def get_instance_id(self, instance_id, provider_type="ec2"):
330104
331105 raise StackException ("Instance type %s from provider %s not found" %
332106 (instance_id , provider_type ))
333-
334-
335- @endpoint ("provider_types/" )
336- def get_provider_type (self , type_name ):
337- """Get the id for the provider specified by type_name"""
338-
339- result = self ._get (endpoint , jsonify = True )
340- for provider_type in result ['results' ]:
341- if provider_type .get ("type_name" ) == type_name :
342- return provider_type .get ("id" )
343-
344- raise StackException ("Provider type %s not found" % type_name )
345-
346-
347- @endpoint ("zones/" )
348- def get_zone (self , title , type_name = "ec2" ):
349- """Get a zone id for title"""
350-
351- provider_type = self .get_provider_type (type_name )
352- result = self ._get (endpoint , jsonify = True )
353- for zone in result ['results' ]:
354- if zone .get ("title" ) == title and \
355- zone .get ("provider_type" ) == provider_type :
356- return zone .get ("id" )
357-
358- raise StackException ("Zone %s not found for %s" % (title , type_name ))
359-
360-
361- @endpoint ("stacks/" )
362- def launch_stack (self , stack_data ):
363- """Launch a stack as described by stack_data"""
364- return self ._post (endpoint , data = json .dumps (stack_data ), jsonify = True )
365-
366-
367- @endpoint ("stacks/{stack_id}/hosts/" )
368- def describe_hosts (self , stack_id , key = "fqdn" , ec2 = False ):
369- """Retrieve a list of info about a stack. Defaults to the id for each
370- host, but you can specify any available key. Setting ec2=True will
371- force it to inspect the ec2_metadata field."""
372-
373- EC2 = "ec2_metadata"
374- result = self ._get (endpoint , jsonify = True )
375-
376- stack_details = []
377-
378- for host in result ['results' ]:
379- if not ec2 :
380- host_details = host .get (key )
381- else :
382- host_details = host .get (EC2 ).get (key )
383-
384- if host_details :
385- stack_details .append (host_details )
386-
387- if stack_details :
388- return stack_details
389-
390- raise StackException ("Key %s for stack %s not available" % (key , stack_id ))
391-
392-
393- @endpoint ("stacks/{stack_id}/" )
394- def delete_stack (self , stack_id ):
395- """Destructively delete a stack forever."""
396- # make sure the stack exists
397- self .get_stack (stack_id )
398- return self ._delete (endpoint , jsonify = True )
399-
400-
401- @endpoint ("stacks/{stack_id}/action/" )
402- def get_valid_actions (self , stack_id ):
403- return self ._get (endpoint , jsonify = True )['available_actions' ]
404-
405-
406- @endpoint ("stacks/{stack_id}/action/" )
407- def do_action (self , stack_id , action ):
408- """Execute an action on a stack"""
409- valid_actions = self .get_valid_actions (stack_id )
410-
411- if action not in valid_actions :
412- raise StackException ("Invalid action, must be one of %s" %
413- ", " .join (valid_actions ))
414-
415- data = {"action" : action }
416-
417- return self ._post (endpoint , data = json .dumps (data ), jsonify = True )
0 commit comments