in internal/system/discovery.go [381:611]
func (d *Discovery) discoverSAPSystems(ctx context.Context, cp *ipb.CloudProperties, config *cpb.Configuration) []*spb.SapDiscovery {
instanceURI := fmt.Sprintf("projects/%s/zones/%s/instances/%s", cp.GetProjectId(), cp.GetZone(), cp.GetInstanceName())
log.CtxLogger(ctx).Debug("Discovering current host")
hostInstanceResources := d.CloudDiscoveryInterface.DiscoverComputeResources(ctx, nil, "", []string{instanceURI}, cp)
log.CtxLogger(ctx).Debugw("Host Resources", "hostResources", hostInstanceResources)
var instanceResource *spb.SapDiscovery_Resource
var instanceNetwork string
// Find the instance resource and its subnetwork
for _, r := range hostInstanceResources {
if r.GetResourceKind() == spb.SapDiscovery_Resource_RESOURCE_KIND_INSTANCE && strings.Contains(r.ResourceUri, cp.GetInstanceName()) {
log.CtxLogger(ctx).Debugf("Instance Resource: %v", r)
instanceResource = r
}
if r.GetResourceKind() == spb.SapDiscovery_Resource_RESOURCE_KIND_NETWORK {
instanceNetwork = r.ResourceUri
}
if instanceResource != nil && instanceNetwork != "" {
break
}
}
if instanceResource == nil {
log.CtxLogger(ctx).Debug("No instance resource found")
}
if fileInfo, err := d.OSStatReader(systemDiscoveryOverride); fileInfo != nil && err == nil {
log.CtxLogger(ctx).Info("Discovering system from override file")
return d.discoverOverrideSystem(ctx, systemDiscoveryOverride, instanceResource)
}
log.CtxLogger(ctx).Info("Starting host discovery")
hostResourceNames := d.HostDiscoveryInterface.DiscoverCurrentHost(ctx)
log.CtxLogger(ctx).Debugw("Host Resource Names", "names", hostResourceNames)
log.CtxLogger(ctx).Infow("Discovering other host resources")
hostResources := d.CloudDiscoveryInterface.DiscoverComputeResources(ctx, instanceResource, instanceNetwork, hostResourceNames, cp)
hostResources = removeDuplicates(append(hostResources, hostInstanceResources...))
log.CtxLogger(ctx).Debugw("Host Resources", "hostResources", hostResources)
sapSystems := []*spb.SapDiscovery{}
log.CtxLogger(ctx).Info("Starting SAP Discovery")
sapDetails := d.SapDiscoveryInterface.DiscoverSAPApps(ctx, d.GetSAPInstances(), config.GetDiscoveryConfiguration())
log.CtxLogger(ctx).Debugw("SAP Details", "details", sapDetails)
for _, s := range sapDetails {
system := &spb.SapDiscovery{}
if s.AppComponent != nil {
log.CtxLogger(ctx).Info("Discovering cloud resources for app")
appRes := d.CloudDiscoveryInterface.DiscoverComputeResources(ctx, instanceResource, instanceNetwork, s.AppHosts, cp)
log.CtxLogger(ctx).Debugf("App Resources: %v", appRes)
if s.AppOnHost {
appRes = append(appRes, hostResources...)
log.CtxLogger(ctx).Debugf("App On Host Resources: %v", appRes)
}
if s.AppComponent.GetApplicationProperties().GetNfsUri() != "" {
log.CtxLogger(ctx).Info("Discovering cloud resources for app NFS")
nfsRes := d.CloudDiscoveryInterface.DiscoverComputeResources(ctx, instanceResource, instanceNetwork, []string{s.AppComponent.GetApplicationProperties().GetNfsUri()}, cp)
if len(nfsRes) > 0 {
appRes = append(appRes, nfsRes...)
s.AppComponent.GetApplicationProperties().NfsUri = nfsRes[0].GetResourceUri()
}
}
if s.AppComponent.GetApplicationProperties().GetAscsUri() != "" {
log.CtxLogger(ctx).Info("Discovering cloud resources for app ASCS")
ascsRes := d.CloudDiscoveryInterface.DiscoverComputeResources(ctx, instanceResource, instanceNetwork, []string{s.AppComponent.GetApplicationProperties().GetAscsUri()}, cp)
if len(ascsRes) > 0 {
log.CtxLogger(ctx).Debugw("ASCS Resources", "res", ascsRes)
appRes = append(appRes, ascsRes...)
s.AppComponent.GetApplicationProperties().AscsUri = ascsRes[0].GetResourceUri()
}
}
if len(s.AppComponent.GetHaHosts()) > 0 {
haRes := d.CloudDiscoveryInterface.DiscoverComputeResources(ctx, instanceResource, instanceNetwork, s.AppComponent.GetHaHosts(), cp)
// Find the instances
var haURIs []string
for _, res := range haRes {
if res.GetResourceKind() == spb.SapDiscovery_Resource_RESOURCE_KIND_INSTANCE {
haURIs = append(haURIs, res.GetResourceUri())
}
}
appRes = append(appRes, haRes...)
s.AppComponent.HaHosts = haURIs
}
s.AppComponent.HostProject = cp.GetNumericProjectId()
s.AppComponent.Resources = removeDuplicates(appRes)
system.ApplicationLayer = s.AppComponent
}
if s.DBComponent != nil {
log.CtxLogger(ctx).Info("Discovering cloud resources for database")
dbRes := d.CloudDiscoveryInterface.DiscoverComputeResources(ctx, instanceResource, instanceNetwork, s.DBHosts, cp)
log.CtxLogger(ctx).Debugw("Database Resources", "res", dbRes)
if s.DBOnHost {
dbRes = removeDuplicates(append(dbRes, hostResources...))
}
if s.DBDiskMap != nil {
log.CtxLogger(ctx).Debugw("DB Disk Map", "map", s.DBDiskMap)
for mountPath, deviceNames := range s.DBDiskMap {
for _, deviceName := range deviceNames {
// instanceResource instance properties disk mounts is a list of the attached disks with
// where name is the disk's source and mountPoint is the device name.
mount := &spb.SapDiscovery_Resource_InstanceProperties_DiskMount{
MountPoint: mountPath,
}
for _, disk := range instanceResource.InstanceProperties.DiskDeviceNames {
if strings.Contains(deviceName, disk.GetDeviceName()) {
log.CtxLogger(ctx).Debugw("Disk for device name", "disk", disk, "mountPath", mountPath, "deviceName", deviceName)
mount.DiskNames = append(mount.DiskNames, disk.GetSource())
}
}
if len(mount.DiskNames) > 0 {
instanceResource.InstanceProperties.DiskMounts = append(instanceResource.InstanceProperties.DiskMounts, mount)
}
}
}
}
// Make a resource map for quicker lookup
resourcesByType := make(map[spb.SapDiscovery_Resource_ResourceKind][]*spb.SapDiscovery_Resource)
resourceByURI := make(map[string]*spb.SapDiscovery_Resource)
for _, r := range dbRes {
resourcesByType[r.GetResourceKind()] = append(resourcesByType[r.GetResourceKind()], r)
resourceByURI[r.GetResourceUri()] = r
}
log.CtxLogger(ctx).Debugw("Resources by type", "resources", resourcesByType)
log.CtxLogger(ctx).Debugw("Resources by URI", "resources", resourceByURI)
// Find the load balancer groups
var lbGroups []loadBalancerGroup
for _, lb := range resourcesByType[spb.SapDiscovery_Resource_RESOURCE_KIND_BACKEND_SERVICE] {
log.CtxLogger(ctx).Debugw("LB", "lb", lb)
lbGroup := loadBalancerGroup{lbRes: lb, instanceURIs: []string{}}
for _, related := range lb.RelatedResources {
rr := resourceByURI[related]
if rr.GetResourceKind() == spb.SapDiscovery_Resource_RESOURCE_KIND_INSTANCE {
log.CtxLogger(ctx).Debugw("LB Instance", "instance", rr)
lbGroup.instanceURIs = append(lbGroup.instanceURIs, related)
} else if rr.GetResourceKind() == spb.SapDiscovery_Resource_RESOURCE_KIND_INSTANCE_GROUP {
log.CtxLogger(ctx).Debugw("LB Instance Group", "instanceGroup", rr)
for _, igr := range rr.RelatedResources {
igres := resourceByURI[igr]
if igres.GetResourceKind() == spb.SapDiscovery_Resource_RESOURCE_KIND_INSTANCE {
log.CtxLogger(ctx).Debugw("LB Instance in Group", "instance", igres)
lbGroup.instanceURIs = append(lbGroup.instanceURIs, igr)
}
}
}
}
log.CtxLogger(ctx).Debugw("LB Group", "group", lbGroup)
lbGroups = append(lbGroups, lbGroup)
}
log.CtxLogger(ctx).Debugw("LB Groups", "groups", lbGroups)
if s.DBComponent.GetDatabaseProperties().GetSharedNfsUri() != "" {
log.CtxLogger(ctx).Debug("Discovering cloud resources for database NFS")
nfsRes := d.CloudDiscoveryInterface.DiscoverComputeResources(ctx, instanceResource, instanceNetwork, []string{s.DBComponent.GetDatabaseProperties().GetSharedNfsUri()}, cp)
if len(nfsRes) > 0 {
dbRes = append(dbRes, nfsRes...)
s.DBComponent.GetDatabaseProperties().SharedNfsUri = nfsRes[0].GetResourceUri()
}
}
s.DBComponent.Resources = removeDuplicates(dbRes)
if s.DBInstance != nil && s.DBInstance.HanaReplicationTree != nil {
log.CtxLogger(ctx).Debug("Discovering cloud resources for database replication sites")
primarySite := d.discoverReplicationSite(ctx, s.DBInstance.HanaReplicationTree, s.DBComponent.GetSid(), instanceResource, instanceNetwork, lbGroups, cp)
primarySite.Component.Properties = s.DBComponent.Properties
s.DBComponent = primarySite.Component
// Find the site this instance belongs to.
addHostResourcesforSite(ctx, s.DBComponent, dbRes, cp)
}
for _, r := range s.DBComponent.GetResources() {
if r.GetResourceKind() == spb.SapDiscovery_Resource_RESOURCE_KIND_INSTANCE {
if r.InstanceProperties == nil {
r.InstanceProperties = &spb.SapDiscovery_Resource_InstanceProperties{}
}
r.InstanceProperties.InstanceRole |= spb.SapDiscovery_Resource_InstanceProperties_INSTANCE_ROLE_DATABASE
}
}
log.CtxLogger(ctx).Debug("Done discovering DB")
s.DBComponent.HostProject = cp.GetNumericProjectId()
system.DatabaseLayer = s.DBComponent
}
if len(s.InstanceProperties) > 0 {
for _, iProp := range s.InstanceProperties {
log.CtxLogger(ctx).Debugw("Discovering instance properties", "props", iProp)
res := d.CloudDiscoveryInterface.DiscoverComputeResources(ctx, instanceResource, instanceNetwork, []string{iProp.VirtualHostname}, cp)
log.CtxLogger(ctx).Debugf("Discovered instance properties: %s", res)
if res == nil {
continue
}
for _, r := range res {
if r.GetResourceKind() == spb.SapDiscovery_Resource_RESOURCE_KIND_INSTANCE {
if r.InstanceProperties == nil {
r.InstanceProperties = &spb.SapDiscovery_Resource_InstanceProperties{}
}
if iProp.VirtualHostname != "" {
r.InstanceProperties.VirtualHostname = iProp.VirtualHostname
}
r.InstanceProperties.InstanceRole |= iProp.InstanceRole
appInstances := make(map[string]*spb.SapDiscovery_Resource_InstanceProperties_AppInstance)
for _, app := range r.InstanceProperties.AppInstances {
appInstances[app.GetName()] = app
}
for _, app := range iProp.AppInstances {
if _, ok := appInstances[app.GetName()]; !ok {
r.InstanceProperties.AppInstances = append(r.InstanceProperties.AppInstances, app)
appInstances[app.GetName()] = app
}
}
log.CtxLogger(ctx).Debugw("Adding instance properties to resource", "resource_uri", r.ResourceUri, "instance_properties", r.InstanceProperties)
}
}
if (iProp.InstanceRole & spb.SapDiscovery_Resource_InstanceProperties_INSTANCE_ROLE_DATABASE) != 0 {
log.CtxLogger(ctx).Debug("Instance properties are for a database instance")
if system.GetDatabaseLayer() != nil {
system.DatabaseLayer.Resources = removeDuplicates(append(system.GetDatabaseLayer().Resources, res...))
}
}
if (iProp.InstanceRole & spb.SapDiscovery_Resource_InstanceProperties_INSTANCE_ROLE_ASCS_ERS_APP_SERVER) != 0 {
log.CtxLogger(ctx).Debug("Instance properties are for a application instance")
if system.GetApplicationLayer() != nil {
system.ApplicationLayer.Resources = removeDuplicates(append(system.GetApplicationLayer().Resources, res...))
}
}
}
}
system.WorkloadProperties = s.WorkloadProperties
system.ProjectNumber = cp.GetNumericProjectId()
system.UpdateTime = timestamppb.Now()
sapSystems = append(sapSystems, system)
}
log.CtxLogger(ctx).Debug("Done discovering systems")
return sapSystems
}