package main import ( "fmt" "strconv" "strings" "unicode" "devel.mephi.ru/dyokunev/go-sdapi/sdApi1" "devel.mephi.ru/dyokunev/go-sdapi/sdApi11" "devel.mephi.ru/dyokunev/go-sdapi/sdApi12" "devel.mephi.ru/iacherepanov/openstack-gophercloud" "devel.mephi.ru/iacherepanov/openstack-gophercloud/openstack" "devel.mephi.ru/iacherepanov/openstack-gophercloud/openstack/identity/v3/projects" "devel.mephi.ru/iacherepanov/openstack-gophercloud/openstack/identity/v3/users" "github.com/alyu/configparser" asuModels "devel.mephi.ru/dyokunev/go-asu-models" api11Models "devel.mephi.ru/dyokunev/go-sd-models/api11" api12Models "devel.mephi.ru/dyokunev/go-sd-models/api12" ) // H E L P E R S func checkErr(err error) { if err != nil { panic(err) } } func pointerFromBool(b bool) *bool { return &b } func capitalize(str string) string { runes := []rune(str) runes[0] = unicode.ToUpper(runes[0]) return string(runes) } // O P E N S T A C K C L I E N T type OpenstackIdentityClient struct { client *gophercloud.ServiceClient config *configparser.Configuration domainID string userRoleID string adminRoleID string cloudAdminID string } func initIdentityClient() OpenstackIdentityClient { config, err := configparser.Read("./project_and_roles.conf") checkErr(err) section, err := config.Section("openstack") checkErr(err) domainID := section.ValueOf("projects_domain_id") userRoleID := section.ValueOf("user_role_id") adminRoleID := section.ValueOf("admin_role_id") cloudAdminID := section.ValueOf("cloud_admin_id") opts := gophercloud.AuthOptions{ IdentityEndpoint: section.ValueOf("identity_endpoint"), DomainName: section.ValueOf("domain_name"), TenantName: section.ValueOf("project_name"), Username: section.ValueOf("username"), Password: section.ValueOf("password"), } provider, err := openstack.AuthenticatedClient(opts) checkErr(err) client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{ Region: section.ValueOf("region"), }) checkErr(err) osclient := OpenstackIdentityClient{ client: client, config: config, domainID: domainID, userRoleID: userRoleID, adminRoleID: adminRoleID, cloudAdminID: cloudAdminID, } return osclient } func (osclient OpenstackIdentityClient) getProjects() []projects.Project { listOpts := projects.ListOpts{ DomainID: osclient.domainID, Enabled: pointerFromBool(true), IsDomain: pointerFromBool(false), } allPages, err := projects.List(osclient.client, listOpts).AllPages() checkErr(err) allProjects, err := projects.ExtractProjects(allPages) checkErr(err) return allProjects } func (osclient OpenstackIdentityClient) getProjectsMap() map[int]projects.Project { allProjects := osclient.getProjects() return projectsToMap(allProjects) } func projectsToMap(allProjects []projects.Project) map[int]projects.Project { projectsMap := map[int]projects.Project{} for _, project := range allProjects { if project.Extra["PersNumber"] == nil { panic(fmt.Sprintf("Project %s has no persNumber", project.Name)) } persNumber := int(project.Extra["PersNumber"].(float64)) projectsMap[persNumber] = project } return projectsMap } func (osclient OpenstackIdentityClient) getOpenstackUsers() []users.User { listOpts := users.ListOpts{ DomainID: osclient.domainID, Enabled: pointerFromBool(true), } allPages, err := users.List(osclient.client, listOpts).AllPages() checkErr(err) allUsers, err := users.ExtractUsers(allPages) checkErr(err) return allUsers } func (osclient OpenstackIdentityClient) getOpenstackUsersMap() map[string]users.User { allUsers := osclient.getOpenstackUsers() openstackUsersMap := map[string]users.User{} for _, user := range allUsers { openstackUsersMap[user.Name] = user } return openstackUsersMap } func (osclient OpenstackIdentityClient) getOpenstackUsersMapByID() map[string]users.User { allUsers := osclient.getOpenstackUsers() openstackUsersMapByID := map[string]users.User{} for _, user := range allUsers { openstackUsersMapByID[user.ID] = user } return openstackUsersMapByID } func makeUpdateOpts(unit asuModels.Unit, domainID string) projects.UpdateOpts { updateOpts := projects.UpdateOpts{ DomainID: domainID, Enabled: pointerFromBool(true), IsDomain: pointerFromBool(false), Name: fmt.Sprintf("%s [%v]", *unit.BriefName, *unit.PersNumber), Description: *unit.Name, Extra: map[string]interface{}{ "ParentPersNumber": unit.ParentId}, } return updateOpts } func makeCreateOpts(unit asuModels.Unit, domainID string) projects.CreateOpts { createOpts := projects.CreateOpts{ DomainID: domainID, Enabled: pointerFromBool(true), IsDomain: pointerFromBool(false), Name: fmt.Sprintf("%s [%v]", *unit.BriefName, *unit.PersNumber), Description: *unit.Name, Extra: map[string]interface{}{ "PersNumber": unit.PersNumber, "ParentPersNumber": unit.ParentId}, } return createOpts } // U N I T S func getAllUnits(config *configparser.Configuration) asuModels.Units { section, err := config.Section("sd.mephi.ru") checkErr(err) sdApi1.SetApiKey(section.ValueOf("api1_key")) allUnits, err := sdApi1.GetUnits() checkErr(err) return allUnits } func getCleanUnitsPersNumberMap(config *configparser.Configuration) map[int]asuModels.Unit { allUnits := getAllUnits(config) idToPersNum := map[int]int{} cleanUnits := map[int]asuModels.Unit{} // Get all not nil units without duplicates for _, unit := range allUnits { if unit.PersNumber == nil || unit.IsHidden == 1 || unit.Name == nil || unit.BriefName == nil { continue } idToPersNum[unit.Id] = *unit.PersNumber existingUnit, ok := cleanUnits[*unit.PersNumber] if !ok { cleanUnits[*unit.PersNumber] = unit } else { cleanUnits[*unit.PersNumber] = newestUnit(existingUnit, unit) } } for persNumber, unit := range cleanUnits { // Change parent ID to parent persNumber if unit.ParentId != nil { parentPersNumber := idToPersNum[*unit.ParentId] unit.ParentId = &parentPersNumber } // Clean names *unit.Name = strings.Join(strings.Fields(*unit.Name), " ") *unit.Name = capitalize(*unit.Name) *unit.BriefName = strings.Join(strings.Fields(*unit.BriefName), " ") *unit.BriefName = strings.ToUpper(*unit.BriefName) cleanUnits[persNumber] = unit } return cleanUnits } func getCleanUnitsCodeMap(config *configparser.Configuration) map[int]asuModels.Unit { units := getCleanUnitsPersNumberMap(config) codeToUnitsMap := map[int]asuModels.Unit{} for _, unit := range units { codeToUnitsMap[unitCodeToInt(unit.Code)] = unit } return codeToUnitsMap } func unitCodeToInt(code string) int { var numCode int code = strings.Replace(code, " ", "", -1) numCode, err := strconv.Atoi(code) checkErr(err) return numCode } func newestUnit(unit1 asuModels.Unit, unit2 asuModels.Unit) asuModels.Unit { if unit1.CreateOrderDate != nil && unit2.CreateOrderDate != nil { if unit1.CreateOrderDate.Unix() > unit2.CreateOrderDate.Unix() { return unit1 } return unit2 } return unit1 } // P E O P L E func getPeople(config *configparser.Configuration) api11Models.People { section, err := config.Section("sd.mephi.ru") checkErr(err) sdApi11.SetApiKey(section.ValueOf("api11_key")) people, err := sdApi11.GetPeople() checkErr(err) return people } func getPeopleMap(config *configparser.Configuration) map[int]api11Models.Person { people := getPeople(config) return peopleToMap(people) } func peopleToMap(people api11Models.People) map[int]api11Models.Person { peopleMap := map[int]api11Models.Person{} for _, person := range people { peopleMap[person.Id] = person } return peopleMap } // R O L E S func getRoles(config *configparser.Configuration) api12Models.Roles { section, err := config.Section("sd.mephi.ru") checkErr(err) sdApi12.SetApiKey(section.ValueOf("api12_key")) heads, err := sdApi12.GetRoles(api12Models.Role{ServiceName: "voip", RoleName: "head"}) checkErr(err) openstack_users, err := sdApi12.GetRoles(api12Models.Role{ServiceName: "voip", RoleName: "openstack_user"}) checkErr(err) openstack_admins, err := sdApi12.GetRoles(api12Models.Role{ServiceName: "voip", RoleName: "openstack_admin"}) checkErr(err) roles := append(heads, openstack_users...) roles = append(roles, openstack_admins...) return roles }