def wmTestCloudConnection(self): try: sAccountID = uiCommon.getAjaxArg("sAccountID") sCloudID = uiCommon.getAjaxArg("sCloudID") c = cloud.Cloud() c.FromID(sCloudID) if c.ID is None: return "{\"result\":\"fail\",\"error\":\"Failed to get Cloud details for Cloud ID [" + sCloudID + "].\"}" ca = cloud.CloudAccount() ca.FromID(sAccountID) if ca.ID is None: return "{\"result\":\"fail\",\"error\":\"Failed to get Cloud Account details for Cloud Account ID [" + sAccountID + "].\"}" # get the test cloud object type for this provider cot = c.Provider.GetObjectTypeByName(c.Provider.TestObject) if cot is not None: if not cot.ID: return "{\"result\":\"fail\",\"error\":\"Cannot find definition for requested object type [" + c.Provider.TestObject + "].\"}" else: return "{\"result\":\"fail\",\"error\":\"GetCloudObjectType failed for [" + c.Provider.TestObject + "].\"}" # different providers libs have different methods for building a url url = "" if c.Provider.Name.lower() == "openstack": """not yet implemented""" #ACWebMethods.openstackMethods acOS = new ACWebMethods.openstackMethods() #sXML = acOS.GetCloudObjectsAsXML(c.ID, cot, 0000BYREF_ARG0000sErr, null) else: #Amazon aws, Eucalyptus, and OpenStackAws import aws awsi = aws.awsInterface() url, err = awsi.BuildURL(ca, c, cot) if err: return "{\"result\":\"fail\",\"error\":\"" + uiCommon.packJSON( err) + "\"}" if not url: return "{\"result\":\"fail\",\"error\":\"Unable to build API URL.\"}" result, err = uiCommon.HTTPGet(url, 30) if err: return "{\"result\":\"fail\",\"error\":\"" + uiCommon.packJSON( err) + "\"}" return "{\"result\":\"success\",\"response\":\"" + uiCommon.packJSON( result) + "\"}" except Exception: uiCommon.log_nouser(traceback.format_exc(), 0) return traceback.format_exc()
def wmTestCloudConnection(self): try: sAccountID = uiCommon.getAjaxArg("sAccountID") sCloudID = uiCommon.getAjaxArg("sCloudID") c = cloud.Cloud() c.FromID(sCloudID) if c.ID is None: return "{\"result\":\"fail\",\"error\":\"Failed to get Cloud details for Cloud ID [" + sCloudID + "].\"}" ca = cloud.CloudAccount() ca.FromID(sAccountID) if ca.ID is None: return "{\"result\":\"fail\",\"error\":\"Failed to get Cloud Account details for Cloud Account ID [" + sAccountID + "].\"}" # get the test cloud object type for this provider cot = c.Provider.GetObjectTypeByName(c.Provider.TestObject) if cot is not None: if not cot.ID: return "{\"result\":\"fail\",\"error\":\"Cannot find definition for requested object type [" + c.Provider.TestObject + "].\"}" else: return "{\"result\":\"fail\",\"error\":\"GetCloudObjectType failed for [" + c.Provider.TestObject + "].\"}" # different providers libs have different methods for building a url url = "" if c.Provider.Name.lower() =="openstack": """not yet implemented""" #ACWebMethods.openstackMethods acOS = new ACWebMethods.openstackMethods() #sXML = acOS.GetCloudObjectsAsXML(c.ID, cot, 0000BYREF_ARG0000sErr, null) else: #Amazon aws, Eucalyptus, and OpenStackAws import aws awsi = aws.awsInterface() url, err = awsi.BuildURL(ca, c, cot); if err: return "{\"result\":\"fail\",\"error\":\"" + uiCommon.packJSON(err) +"\"}" if not url: return "{\"result\":\"fail\",\"error\":\"Unable to build API URL.\"}" result, err = uiCommon.HTTPGet(url, 30) if err: return "{\"result\":\"fail\",\"error\":\"" + uiCommon.packJSON(err) + "\"}" return "{\"result\":\"success\",\"response\":\"" + uiCommon.packJSON(result) + "\"}" except Exception: uiCommon.log_nouser(traceback.format_exc(), 0) return traceback.format_exc()
def GetCloudObjectsAsList(sAccountID, sCloudID, sObjectType): try: log("Querying the cloud for %s" % sObjectType, 4) import cloud # first, get the cloud c = cloud.Cloud() c.FromID(sCloudID) if c is None: return None, "Unable to get Cloud for ID [" + sCloudID + "]" cot = c.Provider.GetObjectTypeByName(sObjectType) if cot is not None: if not cot.ID: return None, "Cannot find definition for requested object type [" + sObjectType + "]" else: return None, "GetCloudObjectType failed for [" + sObjectType + "]" # ok, kick out if there are no properties for this type if not cot.Properties: return None, "No properties defined for type [" + sObjectType + "]" # All good, let's hit the API sXML = "" import aws if c.Provider.Name.lower() =="openstack": """not yet implemented""" #ACWebMethods.openstackMethods acOS = new ACWebMethods.openstackMethods() #sXML = acOS.GetCloudObjectsAsXML(c.ID, cot, 0000BYREF_ARG0000sErr, null) else: #Amazon aws, Eucalyptus, and OpenStackAws awsi = aws.awsInterface() sXML, err = awsi.GetCloudObjectsAsXML(sAccountID, sCloudID, cot) if err: return None, err if not sXML: return None, "GetCloudObjectsAsXML returned an empty document." # Got results, objectify them. # OK look, all this namespace nonsense is annoying. Every AWS result I've witnessed HAS a namespace # (which messes up all our xpaths) # but I've yet to see a result that actually has two namespaces # which is the only scenario I know of where you'd need them at all. # So... to eliminate all namespace madness # brute force... parse this text and remove anything that looks like [ xmlns="<crud>"] and it's contents. sXML = RemoveDefaultNamespacesFromXML(sXML) xDoc = ET.fromstring(sXML) if xDoc is None: return None, "API Response XML document is invalid." log(sXML, 4) # FIRST ,we have to find which properties are the 'id' value. That'll be the key for our dictionary. # an id can be a composite of several property values # this is just so we can kick back an error if no IsID exists. # we build the actual id from values near the end sIDColumnName = "" for prop in cot.Properties: if prop.IsID: sIDColumnName += prop.Name # no sIDColumnName means we can't continue if not sIDColumnName: return None, "ID column(s) not defined for Cloud Object Type" + cot.Name # for each result in the xml # for each column xRecords = xDoc.findall(cot.XMLRecordXPath) if len(xRecords): for xRecord in xRecords: record_id = "" row = [] for prop in cot.Properties: # NOW PAY ATTENTION. # the CloudObjectTypeProperty class has a 'Value' attribute. # but, we obviously can't set that property of THIS instance (prop) # because it's gonna get changed each time. # so, we create a clone of that property here, and give that copy the actual value, # then append the copy to 'row', not the one we're looping here. # cosmic? yes... it is. newprop = copy.copy(prop) log("looking for property [%s]" % newprop.Name, 4) # ok look, the property may be an xml attribute, or it might be an element. # if there is an XPath value on the column, that means it's an element. # the absence of an XPath means we'll look for an attribute. # NOTE: the attribute we're looking for is the 'name' of this property # which is the DataColumn.name. if not newprop.XPath: xa = xRecord.attrib[newprop.Name] if xa is not None: log(" -- found (attribute) - [%s]" % xa, 4) newprop.Value = xa row.append(newprop) else: # if it's a tagset column put the tagset xml in it # for all other columns, they get a lookup xeProp = xRecord.find(newprop.XPath) if xeProp is not None: # does this column have the extended property "ValueIsXML"? bAsXML = (True if newprop.ValueIsXML else False) if bAsXML: newprop.Value = ET.tostring(xeProp) log(" -- found (as xml) - [%s]" % newprop.Value, 4) else: newprop.Value = xeProp.text log(" -- found - [%s]" % newprop.Value, 4) # just because it's missing from the data doesn't mean we can omit the property # it just has an empty value. row.append(newprop) if newprop.IsID: if not newprop.Value: return None, "A property [%s] cannot be defined as an 'ID', and have an empty value." % newprop.Name else: log("[%s] is part of the ID... so [%s] becomes part of the ID" % (newprop.Name, newprop.Value), 4) record_id += (newprop.Value if newprop.Value else "") # an id is required if not record_id: return None, "Unable to construct an 'id' from property values." cot.Instances[record_id] = row return cot.Instances, None else: return None, "" except Exception: log_nouser(traceback.format_exc(), 4) return None, None
def GetCloudObjectsAsList(sAccountID, sCloudID, sObjectType): try: log("Querying the cloud for %s" % sObjectType, 4) import cloud # first, get the cloud c = cloud.Cloud() c.FromID(sCloudID) if c is None: return None, "Unable to get Cloud for ID [" + sCloudID + "]" cot = c.Provider.GetObjectTypeByName(sObjectType) if cot is not None: if not cot.ID: return None, "Cannot find definition for requested object type [" + sObjectType + "]" else: return None, "GetCloudObjectType failed for [" + sObjectType + "]" # ok, kick out if there are no properties for this type if not cot.Properties: return None, "No properties defined for type [" + sObjectType + "]" # All good, let's hit the API sXML = "" import aws if c.Provider.Name.lower() == "openstack": """not yet implemented""" #ACWebMethods.openstackMethods acOS = new ACWebMethods.openstackMethods() #sXML = acOS.GetCloudObjectsAsXML(c.ID, cot, 0000BYREF_ARG0000sErr, null) else: #Amazon aws, Eucalyptus, and OpenStackAws awsi = aws.awsInterface() sXML, err = awsi.GetCloudObjectsAsXML(sAccountID, sCloudID, cot) if err: return None, err if not sXML: return None, "GetCloudObjectsAsXML returned an empty document." # Got results, objectify them. # OK look, all this namespace nonsense is annoying. Every AWS result I've witnessed HAS a namespace # (which messes up all our xpaths) # but I've yet to see a result that actually has two namespaces # which is the only scenario I know of where you'd need them at all. # So... to eliminate all namespace madness # brute force... parse this text and remove anything that looks like [ xmlns="<crud>"] and it's contents. sXML = RemoveDefaultNamespacesFromXML(sXML) xDoc = ET.fromstring(sXML) if xDoc is None: return None, "API Response XML document is invalid." log(sXML, 4) # FIRST ,we have to find which properties are the 'id' value. That'll be the key for our dictionary. # an id can be a composite of several property values # this is just so we can kick back an error if no IsID exists. # we build the actual id from values near the end sIDColumnName = "" for prop in cot.Properties: if prop.IsID: sIDColumnName += prop.Name # no sIDColumnName means we can't continue if not sIDColumnName: return None, "ID column(s) not defined for Cloud Object Type" + cot.Name # for each result in the xml # for each column xRecords = xDoc.findall(cot.XMLRecordXPath) if len(xRecords): for xRecord in xRecords: record_id = "" row = [] for prop in cot.Properties: # NOW PAY ATTENTION. # the CloudObjectTypeProperty class has a 'Value' attribute. # but, we obviously can't set that property of THIS instance (prop) # because it's gonna get changed each time. # so, we create a clone of that property here, and give that copy the actual value, # then append the copy to 'row', not the one we're looping here. # cosmic? yes... it is. newprop = copy.copy(prop) log("looking for property [%s]" % newprop.Name, 4) # ok look, the property may be an xml attribute, or it might be an element. # if there is an XPath value on the column, that means it's an element. # the absence of an XPath means we'll look for an attribute. # NOTE: the attribute we're looking for is the 'name' of this property # which is the DataColumn.name. if not newprop.XPath: xa = xRecord.attrib[newprop.Name] if xa is not None: log(" -- found (attribute) - [%s]" % xa, 4) newprop.Value = xa row.append(newprop) else: # if it's a tagset column put the tagset xml in it # for all other columns, they get a lookup xeProp = xRecord.find(newprop.XPath) if xeProp is not None: # does this column have the extended property "ValueIsXML"? bAsXML = (True if newprop.ValueIsXML else False) if bAsXML: newprop.Value = ET.tostring(xeProp) log( " -- found (as xml) - [%s]" % newprop.Value, 4) else: newprop.Value = xeProp.text log(" -- found - [%s]" % newprop.Value, 4) # just because it's missing from the data doesn't mean we can omit the property # it just has an empty value. row.append(newprop) if newprop.IsID: if not newprop.Value: return None, "A property [%s] cannot be defined as an 'ID', and have an empty value." % newprop.Name else: log( "[%s] is part of the ID... so [%s] becomes part of the ID" % (newprop.Name, newprop.Value), 4) record_id += (newprop.Value if newprop.Value else "") # an id is required if not record_id: return None, "Unable to construct an 'id' from property values." cot.Instances[record_id] = row return cot.Instances, None else: return None, "" except Exception: log_nouser(traceback.format_exc(), 4) return None, None