func()

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
}