mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
The Extensions Framework in Apache CloudStack is designed to provide a flexible and standardised mechanism for integrating external systems and custom workflows into CloudStack’s orchestration process. By defining structured hook points during key operations—such as virtual machine deployment, resource preparation, and lifecycle events—the framework allows administrators and developers to extend CloudStack’s behaviour without modifying its core codebase.
419 lines
13 KiB
Python
419 lines
13 KiB
Python
#!/cygdrive/c/Python27
|
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import os.path
|
|
import sys
|
|
from xml.dom import minidom
|
|
from xml.parsers.expat import ExpatError
|
|
import difflib
|
|
|
|
|
|
ROOT_ADMIN = 'r'
|
|
|
|
user_to_func = {
|
|
ROOT_ADMIN: 'populateForApi',
|
|
}
|
|
|
|
|
|
user_to_cns = {
|
|
ROOT_ADMIN: 'allCommandNames',
|
|
}
|
|
|
|
|
|
dirname_to_user = {
|
|
'apis': ROOT_ADMIN,
|
|
}
|
|
|
|
|
|
dirname_to_dirname = {
|
|
'apis': 'apis',
|
|
}
|
|
|
|
|
|
known_categories = {
|
|
'Cisco' : 'External Device',
|
|
'SystemVm': 'System VM',
|
|
'VirtualMachine': 'Virtual Machine',
|
|
'VM': 'Virtual Machine',
|
|
'Vnf': 'Virtual Network Functions',
|
|
'VnfTemplate': 'Virtual Network Functions',
|
|
'GuestSubnet': 'Routing',
|
|
'HypervisorGuestOsNames': 'Guest OS',
|
|
'Domain': 'Domain',
|
|
'Template': 'Template',
|
|
'Iso': 'ISO',
|
|
'Volume': 'Volume',
|
|
'Vlan': 'VLAN',
|
|
'IpAddress': 'Address',
|
|
'PortForwarding': 'Firewall',
|
|
'Firewall': 'Firewall',
|
|
'StaticNat': 'NAT',
|
|
'IpForwarding': 'NAT',
|
|
'Host': 'Host',
|
|
'HostTags': 'Host',
|
|
'OutOfBandManagement': 'Out-of-band Management',
|
|
'Cluster': 'Cluster',
|
|
'Account': 'Account',
|
|
'Role': 'Role',
|
|
'Snapshot': 'Snapshot',
|
|
'User': 'User',
|
|
'UserData': 'User Data',
|
|
'Os': 'Guest OS',
|
|
'ServiceOffering': 'Service Offering',
|
|
'DiskOffering': 'Disk Offering',
|
|
'LoadBalancer': 'Load Balancer',
|
|
'SslCert': 'SSL Certificates',
|
|
'Router': 'Router',
|
|
'Configuration': 'Configuration',
|
|
'Capabilities': 'Configuration',
|
|
'Pod': 'Pod',
|
|
'ManagementNetworkIpRange': 'Pod',
|
|
'PublicIpRange': 'Network',
|
|
'Zone': 'Zone',
|
|
'Vmware' : 'Zone',
|
|
'NetworkOffering': 'Network Offering',
|
|
'NetworkACL': 'Network ACL',
|
|
'NetworkAclItem': 'Network ACL',
|
|
'Network': 'Network',
|
|
'CiscoNexus': 'Network',
|
|
'OpenDaylight': 'Network',
|
|
'createServiceInstance': 'Network',
|
|
'addGloboDnsHost': 'Network',
|
|
'TungstenFabric': 'Tungsten',
|
|
'listNsxControllers': 'NSX',
|
|
'addNsxController': 'NSX',
|
|
'deleteNsxController': 'NSX',
|
|
'NetrisProvider': 'Netris',
|
|
'Vpn': 'VPN',
|
|
'Limit': 'Resource Limit',
|
|
'Netscaler': 'Netscaler',
|
|
'NetscalerControlCenter': 'Netscaler',
|
|
'NetscalerLoadBalancer': 'Netscaler',
|
|
'SolidFire': 'SolidFire',
|
|
'PaloAlto': 'Palo Alto',
|
|
'ResourceCount': 'Limit',
|
|
'CloudIdentifier': 'Cloud Identifier',
|
|
'InstanceGroup': 'VM Group',
|
|
'StorageMaintenance': 'Storage Pool',
|
|
'StoragePool': 'Storage Pool',
|
|
'StorageProvider': 'Storage Pool',
|
|
'StorageScope' : 'Storage Pool',
|
|
'updateStorageCapabilities' : 'Storage Pool',
|
|
'SecurityGroup': 'Security Group',
|
|
'SSH': 'SSH',
|
|
'AsyncJob': 'Async job',
|
|
'Certificate': 'Certificate',
|
|
'Hypervisor': 'Configuration',
|
|
'Alert': 'Alert',
|
|
'Event': 'Event',
|
|
'login': 'Authentication',
|
|
'logout': 'Authentication',
|
|
'saml': 'Authentication',
|
|
'getSPMetadata': 'Authentication',
|
|
'listIdps': 'Authentication',
|
|
'authorizeSamlSso': 'Authentication',
|
|
'listSamlAuthorization': 'Authentication',
|
|
'oauthlogin': 'Authentication',
|
|
'deleteOauthProvider': 'Oauth',
|
|
'listOauthProvider': 'Oauth',
|
|
'registerOauthProvider': 'Oauth',
|
|
'updateOauthProvider': 'Oauth',
|
|
'quota': 'Quota',
|
|
'emailTemplate': 'Quota',
|
|
'Capacity': 'System Capacity',
|
|
'NetworkDevice': 'Network Device',
|
|
'ExternalLoadBalancer': 'Ext Load Balancer',
|
|
'ExternalFirewall': 'Ext Firewall',
|
|
'Usage': 'Usage',
|
|
'TrafficMonitor': 'Network',
|
|
'TrafficType': 'Network',
|
|
'Product': 'Product',
|
|
'LB': 'Load Balancer',
|
|
'ldap': 'LDAP',
|
|
'Ldap': 'LDAP',
|
|
'Swift': 'Image Store',
|
|
'S3' : 'S3',
|
|
'SecondaryStorage': 'Image Store',
|
|
'Project': 'Project',
|
|
'Lun': 'Storage',
|
|
'Pool': 'Pool',
|
|
'VPC': 'VPC',
|
|
'VPCOffering': 'VPC Offering',
|
|
'PrivateGateway': 'VPC',
|
|
'migrateVpc': 'VPC',
|
|
'Simulator': 'simulator',
|
|
'StaticRoute': 'VPC',
|
|
'Tags': 'Resource tags',
|
|
'Icon': 'Resource Icon',
|
|
'NiciraNvpDevice': 'Nicira NVP',
|
|
'BrocadeVcsDevice': 'Brocade VCS',
|
|
'BigSwitchBcfDevice': 'BigSwitch BCF',
|
|
'AutoScale': 'AutoScale',
|
|
'Counter': 'AutoScale',
|
|
'Condition': 'AutoScale',
|
|
'Api': 'API Discovery',
|
|
'ApiLimit': 'Configuration',
|
|
'Region': 'Region',
|
|
'Detail': 'Resource metadata',
|
|
'addIpToNic': 'Nic',
|
|
'removeIpFromNic': 'Nic',
|
|
'updateVmNicIp': 'Nic',
|
|
'listNics':'Nic',
|
|
'AffinityGroup': 'Affinity Group',
|
|
'ImageStore': 'Image Store',
|
|
'addImageStore': 'Image Store',
|
|
'listImageStore': 'Image Store',
|
|
'deleteImageStore': 'Image Store',
|
|
'createSecondaryStagingStore': 'Image Store',
|
|
'deleteSecondaryStagingStore': 'Image Store',
|
|
'listSecondaryStagingStores': 'Image Store',
|
|
'updateImageStore': 'Image Store',
|
|
'downloadImageStoreObject': 'Image Store',
|
|
'InternalLoadBalancer': 'Internal LB',
|
|
'DeploymentPlanners': 'Configuration',
|
|
'ObjectStore': 'Image Store',
|
|
'PortableIp': 'Portable IP',
|
|
'dedicateHost': 'Dedicate Resources',
|
|
'releaseDedicatedHost': 'Dedicate Resources',
|
|
'Baremetal' : 'Baremetal',
|
|
'UCS' : 'UCS',
|
|
'Ucs' : 'UCS',
|
|
'CacheStores' : 'Cache Stores',
|
|
'CacheStore' : 'Cache Store',
|
|
'OvsElement' : 'Ovs Element',
|
|
'StratosphereSsp' : 'Misc Network Service Providers',
|
|
'Metrics' : 'Metrics',
|
|
'listClustersMetrics': 'Cluster',
|
|
'VpnUser': 'VPN',
|
|
'listZonesMetrics': 'Metrics',
|
|
'Infrastructure' : 'Metrics',
|
|
'listRegisteredServicePackages': 'Load Balancer',
|
|
'listNsVpx' : 'Load Balancer',
|
|
'destroyNsVPx': 'Load Balancer',
|
|
'deployNetscalerVpx' : 'Load Balancer',
|
|
'stopNetScalerVpx' : 'Load Balancer',
|
|
'deleteServicePackageOffering' : 'Load Balancer',
|
|
'destroyNsVpx' : 'Load Balancer',
|
|
'startNsVpx' : 'Load Balancer',
|
|
'listAnnotations' : 'Annotations',
|
|
'addAnnotation' : 'Annotations',
|
|
'removeAnnotation' : 'Annotations',
|
|
'updateAnnotationVisibility' : 'Annotations',
|
|
'CA': 'Certificate',
|
|
'listElastistorInterface': 'Misc',
|
|
'cloudian': 'Cloudian',
|
|
'Sioc' : 'Sioc',
|
|
'Diagnostics': 'Diagnostics',
|
|
'Management': 'Management',
|
|
'Backup' : 'Backup and Recovery',
|
|
'Restore' : 'Backup and Recovery',
|
|
'UnmanagedInstance': 'Virtual Machine',
|
|
'KubernetesSupportedVersion': 'Kubernetes Service',
|
|
'KubernetesCluster': 'Kubernetes Service',
|
|
'Rolling': 'Rolling Maintenance',
|
|
'importVsphereStoragePolicies' : 'vSphere storage policies',
|
|
'listVsphereStoragePolicies' : 'vSphere storage policies',
|
|
'ConsoleEndpoint': 'Console Endpoint',
|
|
'importVm': 'Virtual Machine',
|
|
'revertToVMSnapshot': 'Virtual Machine',
|
|
'listQuarantinedIp': 'IP Quarantine',
|
|
'updateQuarantinedIp': 'IP Quarantine',
|
|
'removeQuarantinedIp': 'IP Quarantine',
|
|
'Shutdown': 'Maintenance',
|
|
'Maintenance': 'Maintenance',
|
|
'addObjectStoragePool': 'Object Store',
|
|
'listObjectStoragePools': 'Object Store',
|
|
'deleteObjectStoragePool': 'Object Store',
|
|
'updateObjectStoragePool': 'Object Store',
|
|
'createBucket': 'Object Store',
|
|
'updateBucket': 'Object Store',
|
|
'deleteBucket': 'Object Store',
|
|
'listBuckets': 'Object Store',
|
|
'listVmsForImport': 'Virtual Machine',
|
|
'SharedFS': 'Shared FileSystem',
|
|
'SharedFileSystem': 'Shared FileSystem',
|
|
'Webhook': 'Webhook',
|
|
'Webhooks': 'Webhook',
|
|
'purgeExpungedResources': 'Resource',
|
|
'forgotPassword': 'Authentication',
|
|
'resetPassword': 'Authentication',
|
|
'BgpPeer': 'BGP Peer',
|
|
'createASNRange': 'AS Number Range',
|
|
'listASNRange': 'AS Number Range',
|
|
'deleteASNRange': 'AS Number Range',
|
|
'listASNumbers': 'AS Number',
|
|
'releaseASNumber': 'AS Number',
|
|
'addNodesToKubernetesCluster': 'Kubernetes Service',
|
|
'removeNodesFromKubernetesCluster': 'Kubernetes Service',
|
|
'configureStorageAccess': 'Storage Access Groups',
|
|
'listStorageAccessGroups': 'Storage Access Groups',
|
|
'listGuiThemes': 'GUI Theme',
|
|
'createGuiTheme': 'GUI Theme',
|
|
'updateGuiTheme': 'GUI Theme',
|
|
'removeGuiTheme': 'GUI Theme',
|
|
'Extension' : 'Extension',
|
|
'Extensions' : 'Extension',
|
|
'CustomAction' : 'Extension',
|
|
'CustomActions' : 'Extension'
|
|
}
|
|
|
|
|
|
categories = {}
|
|
|
|
|
|
def choose_category(fn):
|
|
possible_known_categories = []
|
|
for k, v in known_categories.items():
|
|
if k in fn:
|
|
possible_known_categories.append(k)
|
|
|
|
if len(possible_known_categories) > 0:
|
|
close_matches = difflib.get_close_matches(fn, possible_known_categories, n=1, cutoff=0.1)
|
|
if len(close_matches) > 0:
|
|
return known_categories[close_matches[0]]
|
|
else:
|
|
return known_categories[possible_known_categories[0]]
|
|
raise Exception('Need to add a category for %s to %s:known_categories' %
|
|
(fn, __file__))
|
|
|
|
|
|
for f in sys.argv:
|
|
dirname, fn = os.path.split(f)
|
|
if not fn.endswith('.xml'):
|
|
continue
|
|
if fn.endswith('Summary.xml') and fn != 'quotaSummary.xml':
|
|
continue
|
|
if fn.endswith('SummarySorted.xml'):
|
|
continue
|
|
if fn == 'alert_types.xml':
|
|
continue
|
|
if dirname.startswith('./'):
|
|
dirname = dirname[2:]
|
|
try:
|
|
with open(f) as data:
|
|
dom = minidom.parse(data)
|
|
name = dom.getElementsByTagName('name')[0].firstChild.data
|
|
isAsync = dom.getElementsByTagName('isAsync')[0].firstChild.data
|
|
isDeprecated = dom.getElementsByTagName('isDeprecated')[0].firstChild.data
|
|
category = choose_category(fn)
|
|
if category not in categories:
|
|
categories[category] = []
|
|
categories[category].append({
|
|
'name': name,
|
|
'dirname': dirname_to_dirname[dirname],
|
|
'async': isAsync == 'true',
|
|
'deprecated': isDeprecated == 'true',
|
|
'user': dirname_to_user[dirname],
|
|
})
|
|
except ExpatError as e:
|
|
pass
|
|
except IndexError as e:
|
|
print(fn)
|
|
|
|
|
|
def xml_for(command):
|
|
name = command['name']
|
|
isAsync = command['async'] and ' (A)' or ''
|
|
isDeprecated = command['deprecated'] and ' (D)' or ''
|
|
dirname = command['dirname']
|
|
return '''<xsl:if test="name=\'%(name)s\'">
|
|
<li><a href="%(dirname)s/%(name)s.html"><xsl:value-of select="name"/>%(isAsync)s %(isDeprecated)s</a></li>
|
|
</xsl:if>
|
|
''' % locals()
|
|
|
|
|
|
def write_xml(out, user):
|
|
with open(out, 'w') as f:
|
|
cat_strings = []
|
|
for category in categories.keys():
|
|
strings = []
|
|
for command in categories[category]:
|
|
if command['user'] == user:
|
|
strings.append(xml_for(command))
|
|
if strings:
|
|
all_strings = ''.join(strings)
|
|
cat_strings.append((len(strings), category, all_strings))
|
|
|
|
cat_strings.sort(reverse=True)
|
|
|
|
i = 0
|
|
for _1, category, all_strings in cat_strings:
|
|
if i == 0:
|
|
f.write('<div class="apismallsections">\n')
|
|
f.write('''<div class="apismallbullet_box">
|
|
<h5>%(category)s</h5>
|
|
<ul>
|
|
<xsl:for-each select="commands/command">
|
|
%(all_strings)s
|
|
</xsl:for-each>
|
|
</ul>
|
|
</div>
|
|
|
|
''' % locals())
|
|
if i == 3:
|
|
f.write('</div>\n')
|
|
i = 0
|
|
else:
|
|
i += 1
|
|
if i != 0:
|
|
f.write('</div>\n')
|
|
|
|
|
|
def java_for(command, user):
|
|
name = command['name']
|
|
cns = user_to_cns[user]
|
|
return '''%(cns)s.add("%(name)s");
|
|
''' % locals()
|
|
|
|
|
|
def java_for_user(user):
|
|
strings = []
|
|
for category in categories.keys():
|
|
for command in categories[category]:
|
|
if command['user'] == user:
|
|
strings.append(java_for(command, user))
|
|
func = user_to_func[user]
|
|
all_strings = ''.join(strings)
|
|
return '''
|
|
public void %(func)s() {
|
|
%(all_strings)s
|
|
}
|
|
''' % locals()
|
|
|
|
|
|
def write_java(out):
|
|
with open(out, 'w') as f:
|
|
f.write('''/* Generated using gen_toc.py. Do not edit. */
|
|
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
|
|
public class XmlToHtmlConverterData {
|
|
Set<String> allCommandNames = new HashSet<String>();
|
|
''')
|
|
f.write(java_for_user(ROOT_ADMIN) + "\n")
|
|
|
|
f.write('''
|
|
}
|
|
|
|
''')
|
|
|
|
|
|
write_xml('generatetoc_include.xsl', ROOT_ADMIN)
|
|
write_java('XmlToHtmlConverterData.java')
|