fix: 1. ldap sync remove domain/user errors 2. esxi compatibility issues

This commit is contained in:
Qiu Jian
2019-06-29 14:20:38 +08:00
parent d5f4e5eecf
commit acae166062
20 changed files with 348 additions and 213 deletions
+6
View File
@@ -99,6 +99,12 @@ func (model *SResourceBase) MarkDelete() error {
return nil
}
func (model *SResourceBase) MarkUnDelete() error {
model.Deleted = false
model.DeletedAt = time.Time{}
return nil
}
func (model *SResourceBase) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return DeleteModel(ctx, userCred, model.GetIResourceModel())
}
+16
View File
@@ -21,6 +21,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/stringutils"
"yunion.io/x/pkg/utils"
@@ -395,6 +396,21 @@ func (model *SStandaloneResourceBase) ClearSchedDescCache() error {
return nil
}
func (model *SStandaloneResourceBase) AppendDescription(userCred mcclient.TokenCredential, msg string) error {
_, err := Update(model.GetIStandaloneModel(), func() error {
if len(model.Description) > 0 {
model.Description += ";"
}
model.Description += msg
return nil
})
if err != nil {
return errors.Wrap(err, "db.Update")
}
OpsLog.LogEvent(model, "append_desc", msg, userCred)
return nil
}
/*
func (model SStandaloneResourceBase) GetExternalId() string {
return model.ExternalId
+1 -1
View File
@@ -437,7 +437,7 @@ type ICloudHostNetInterface interface {
GetIndex() int8
IsLinkUp() tristate.TriState
GetIpAddr() string
GetMtu() int16
GetMtu() int32
GetNicType() string
}
+1 -1
View File
@@ -3858,7 +3858,7 @@ func (host *SHost) SyncHostExternalNics(ctx context.Context, userCred mcclient.T
for i := 0; i < len(adds); i += 1 {
extNic := adds[i].netif
err = host.addNetif(ctx, userCred, extNic.GetMac(), "", extNic.GetIpAddr(), 0, extNic.GetNicType(), extNic.GetIndex(),
extNic.IsLinkUp(), extNic.GetMtu(), false, "", "", false, true)
extNic.IsLinkUp(), int16(extNic.GetMtu()), false, "", "", false, true)
if err != nil {
result.AddError(err)
} else {
+76 -23
View File
@@ -106,14 +106,14 @@ func (self *SLDAPDriver) syncDomains(ctx context.Context, cli *ldaputils.SLDAPCl
if err != nil {
return errors.Wrap(err, "searchLDAP")
}
domainLocalIds := make([]string, len(entries))
domainIds := make([]string, len(entries))
for i := range entries {
domainInfo := self.entry2Domain(entries[i])
domainLocalIds[i] = domainInfo.Id
domain, err := self.syncDomainInfo(ctx, domainInfo)
if err != nil {
return errors.Wrap(err, "syncDomainInfo")
}
domainIds[i] = domain.Id
userIdMap, err := self.syncUsers(ctx, cli, domain.Id, domainInfo.DN)
if err != nil {
return errors.Wrap(err, "syncUsers")
@@ -123,10 +123,40 @@ func (self *SLDAPDriver) syncDomains(ctx context.Context, cli *ldaputils.SLDAPCl
return errors.Wrap(err, "syncGroups")
}
}
// remove any obsolete domain Id_mappings
err = models.IdmappingManager.DeleteAny(self.IdpId, api.IdMappingEntityDomain, domainLocalIds, nil)
// remove any obsolete domains
obsoleteDomainIds, err := models.IdmappingManager.FetchPublicIdsExcludes(self.IdpId, api.IdMappingEntityDomain, domainIds)
if err != nil {
log.Errorf("delete remvoed remote domain fail %s", err)
return errors.Wrap(err, "models.IdmappingManager.FetchPublicIdsExcludes")
}
for _, obsoleteDomainId := range obsoleteDomainIds {
obsoleteDomain, err := models.DomainManager.FetchDomainById(obsoleteDomainId)
if err != nil {
log.Errorf("models.DomainManager.FetchDomainById error %s", err)
continue
}
obsoleteDomain.AppendDescription(models.GetDefaultAdminCred(), "domain source removed")
// unlink with Idp
err = obsoleteDomain.UnlinkIdp(self.IdpId)
if err != nil {
log.Errorf("obsoleteDomain.UnlinkIdp error %s", err)
continue
}
// remove any user and groups
err = obsoleteDomain.DeleteUserGroups(ctx, models.GetDefaultAdminCred())
if err != nil {
log.Errorf("domain.DeleteUserGroups error %s", err)
continue
}
err = obsoleteDomain.ValidateDeleteCondition(ctx)
if err != nil {
log.Errorf("obsoleteDomain.ValidateDeleteCondition error %s", err)
continue
}
err = obsoleteDomain.Delete(ctx, models.GetDefaultAdminCred())
if err != nil {
log.Errorf("obsoleteDomain.Delete error %s", err)
continue
}
}
return nil
}
@@ -215,29 +245,40 @@ func (self *SLDAPDriver) syncUsers(ctx context.Context, cli *ldaputils.SLDAPClie
if err != nil {
return nil, errors.Wrap(err, "searchLDAP")
}
userLocalIds := make([]string, len(entries))
userIds := make([]string, len(entries))
userIdMap := make(map[string]string)
for i := range entries {
userInfo := self.entry2User(entries[i])
userLocalIds[i] = userInfo.Id
userId, err := self.syncUserDB(ctx, userInfo, domainId)
if err != nil {
return nil, errors.Wrap(err, "syncUserDB")
}
userIds[i] = userId
if self.ldapConfig.GroupMembersAreIds {
userIdMap[userInfo.Id] = userId
} else {
userIdMap[userInfo.DN] = userId
}
}
deleteUsrIds, err := models.UserManager.FetchUserLocalIdsInDomain(domainId, userLocalIds)
deleteUsers, err := models.UserManager.FetchUsersInDomain(domainId, userIds)
if err != nil {
return nil, errors.Wrap(err, "models.UserManager.FetchUserIdsInDomain")
}
if len(deleteUsrIds) > 0 {
err = models.IdmappingManager.DeleteAny(self.IdpId, api.IdMappingEntityUser, nil, deleteUsrIds)
for i := range deleteUsers {
err := deleteUsers[i].UnlinkIdp(self.IdpId)
if err != nil {
log.Errorf("delete removed remote user fail %s", err)
log.Errorf("deleteUser.UnlinkIdp error %s", err)
continue
}
err = deleteUsers[i].ValidateDeleteCondition(ctx)
if err != nil {
log.Errorf("deleteUser.ValidateDeleteCondition error %s", err)
continue
}
err = deleteUsers[i].Delete(ctx, models.GetDefaultAdminCred())
if err != nil {
log.Errorf("deleteUser.Delete error %s", err)
continue
}
}
return userIdMap, nil
@@ -272,7 +313,7 @@ func registerNonlocalUser(ctx context.Context, ui SUserInfo, userId string, doma
return errors.Wrap(err, "db.NewModelObject")
}
user := userObj.(*models.SUser)
q := models.UserManager.Query().Equals("id", userId)
q := models.UserManager.RawQuery().Equals("id", userId)
err = q.First(user)
if err != nil && err != sql.ErrNoRows {
return errors.Wrap(err, "Query user")
@@ -281,6 +322,7 @@ func registerNonlocalUser(ctx context.Context, ui SUserInfo, userId string, doma
// update
_, err := db.Update(user, func() error {
copyUserInfo(ui, userId, domainId, user)
user.MarkUnDelete()
return nil
})
if err != nil {
@@ -325,32 +367,43 @@ func (self *SLDAPDriver) syncGroups(ctx context.Context, cli *ldaputils.SLDAPCli
if err != nil {
return errors.Wrap(err, "searchLDAP")
}
groupLocalIds := make([]string, len(entries))
groupIds := make([]string, len(entries))
for i := range entries {
groupInfo := self.entry2Group(entries[i])
groupLocalIds[i] = groupInfo.Id
err := self.syncGroupDB(ctx, groupInfo, domainId, userIdMap)
groupId, err := self.syncGroupDB(ctx, groupInfo, domainId, userIdMap)
if err != nil {
return errors.Wrap(err, "syncGroupDB")
}
groupIds[i] = groupId
}
deleteGroupIds, err := models.GroupManager.FetchGroupLocalIdsInDomain(domainId, groupLocalIds)
deleteGroups, err := models.GroupManager.FetchGroupsInDomain(domainId, groupIds)
if err != nil {
return errors.Wrap(err, "models.GroupManager.FetchGroupIdsInDomain")
return errors.Wrap(err, "models.GroupManager.FetchGroupsInDomain")
}
if len(groupLocalIds) > 0 {
err = models.IdmappingManager.DeleteAny(self.IdpId, api.IdMappingEntityGroup, nil, deleteGroupIds)
for i := range deleteGroups {
err := deleteGroups[i].UnlinkIdp(self.IdpId)
if err != nil {
log.Errorf("delete removed remote group fail %s", err)
log.Errorf("deleteGroup.UnlinkIdp error %s", err)
continue
}
err = deleteGroups[i].ValidateDeleteCondition(ctx)
if err != nil {
log.Errorf("deleteGroup.ValidateDeleteCondition error %s", err)
continue
}
err = deleteGroups[i].Delete(ctx, models.GetDefaultAdminCred())
if err != nil {
log.Errorf("deleteGroup.Delete error %s", err)
continue
}
}
return nil
}
func (self *SLDAPDriver) syncGroupDB(ctx context.Context, groupInfo SGroupInfo, domainId string, userIdMap map[string]string) error {
func (self *SLDAPDriver) syncGroupDB(ctx context.Context, groupInfo SGroupInfo, domainId string, userIdMap map[string]string) (string, error) {
grp, err := models.GroupManager.RegisterExternalGroup(ctx, self.IdpId, domainId, groupInfo.Id, groupInfo.Name)
if err != nil {
return errors.Wrap(err, "GroupManager.RegisterExternalGroup")
return "", errors.Wrap(err, "GroupManager.RegisterExternalGroup")
}
userIds := make([]string, 0)
for _, userExtId := range groupInfo.Members {
@@ -359,5 +412,5 @@ func (self *SLDAPDriver) syncGroupDB(ctx context.Context, groupInfo SGroupInfo,
}
}
models.UsergroupManager.SyncGroupUsers(ctx, models.GetDefaultAdminCred(), grp.Id, userIds)
return nil
return grp.Id, nil
}
+46
View File
@@ -261,6 +261,52 @@ func (manager *SAssignmentManager) projectAddUser(ctx context.Context, userCred
return err
}
func (manager *SAssignmentManager) batchRemove(actorId string, typeStrs []string) error {
q := manager.Query()
q = q.In("type", typeStrs)
q = q.Equals("actor_id", actorId)
q = q.IsFalse("inherited")
assigns := make([]SAssignment, 0)
err := db.FetchModelObjects(manager, q, &assigns)
if err != nil && err != sql.ErrNoRows {
return errors.Wrap(err, "db.FetchModelObjects")
}
for i := range assigns {
_, err := db.Update(&assigns[i], func() error {
assigns[i].MarkDelete()
return nil
})
if err != nil {
return errors.Wrap(err, "db.Update")
}
}
return nil
}
func (manager *SAssignmentManager) projectRemoveAllUser(ctx context.Context, userCred mcclient.TokenCredential, user *SUser) error {
if user.IsAdminUser() {
return httperrors.NewForbiddenError("sysadmin is protected")
}
if user.Id == userCred.GetUserId() {
return httperrors.NewForbiddenError("cannot remove current user from current project")
}
err := manager.batchRemove(user.Id, []string{api.AssignmentUserProject, api.AssignmentUserDomain})
if err != nil {
return errors.Wrap(err, "manager.batchRemove")
}
db.OpsLog.LogEvent(user, "leave_all_projects", user.GetShortDesc(ctx), userCred)
return nil
}
func (manager *SAssignmentManager) projectRemoveAllGroup(ctx context.Context, userCred mcclient.TokenCredential, group *SGroup) error {
err := manager.batchRemove(group.Id, []string{api.AssignmentGroupProject, api.AssignmentGroupDomain})
if err != nil {
return errors.Wrap(err, "manager.batchRemove")
}
db.OpsLog.LogEvent(group, "leave_all_projects", group.GetShortDesc(ctx), userCred)
return nil
}
func (manager *SAssignmentManager) projectRemoveUser(ctx context.Context, userCred mcclient.TokenCredential, project *SProject, user *SUser, role *SRole) error {
if project.IsAdminProject() && user.IsAdminUser() && role.IsSystemRole() {
return httperrors.NewForbiddenError("sysadmin is protected")
+48 -34
View File
@@ -215,6 +215,9 @@ func (domain *SDomain) GetIdpCount() (int, error) {
}
func (domain *SDomain) ValidatePurgeCondition(ctx context.Context) error {
if domain.Id == api.DEFAULT_DOMAIN_ID {
return httperrors.NewForbiddenError("cannot delete default domain")
}
if domain.Enabled.IsTrue() {
return httperrors.NewInvalidStatusError("domain is enabled")
}
@@ -230,28 +233,17 @@ func (domain *SDomain) ValidatePurgeCondition(ctx context.Context) error {
if policyCnt > 0 {
return httperrors.NewNotEmptyError("domain is in use by policy")
}
if domain.Id == api.DEFAULT_DOMAIN_ID {
return httperrors.NewForbiddenError("cannot delete default domain")
}
return nil
}
func (domain *SDomain) ValidateDeleteCondition(ctx context.Context) error {
// usrCnt, _ := domain.GetUserCount()
// if usrCnt > 0 {
// return httperrors.NewNotEmptyError("domain is in use")
// }
// grpCnt, _ := domain.GetGroupCount()
// if grpCnt > 0 {
// return httperrors.NewNotEmptyError("domain is in use")
// }
if domain.IsReadOnly() {
return httperrors.NewForbiddenError("readonly")
}
err := domain.ValidatePurgeCondition(ctx)
if err != nil {
return err
}
if domain.IsReadOnly() {
return httperrors.NewForbiddenError("readonly")
}
return domain.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
}
@@ -259,9 +251,6 @@ func (domain *SDomain) ValidateUpdateCondition(ctx context.Context) error {
if domain.Id == api.DEFAULT_DOMAIN_ID {
return httperrors.NewForbiddenError("default domain is protected")
}
// if domain.IsReadOnly() {
// return httperrors.NewForbiddenError("readonly")
// }
return domain.SStandaloneResourceBase.ValidateUpdateCondition(ctx)
}
@@ -278,13 +267,6 @@ func (domain *SDomain) ValidateUpdateData(ctx context.Context, userCred mcclient
return domain.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
}
/*func (domain *SDomain) isReadOnly() bool {
if domain.GetDriver() == api.IdentityDriverSQL {
return false
}
return true
}*/
func (domain *SDomain) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := domain.SStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query)
return domainExtra(domain, extra)
@@ -339,19 +321,19 @@ func (domain *SDomain) getGroups() ([]SGroup, error) {
return grps, nil
}
func (domain *SDomain) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
func (domain *SDomain) DeleteUserGroups(ctx context.Context, userCred mcclient.TokenCredential) error {
usrs, err := domain.getUsers()
if err != nil {
return errors.Wrap(err, "domain.getUsers")
}
for i := range usrs {
err = usrs[i].ValidatePurgeCondition(ctx)
err = usrs[i].ValidateDeleteCondition(ctx)
if err != nil {
return errors.Wrap(err, "usr.ValidatePurgeCondition")
return errors.Wrap(err, "usr.ValidateDeleteCondition")
}
err = usrs[i].purge(ctx, userCred)
err = usrs[i].Delete(ctx, userCred)
if err != nil {
return errors.Wrap(err, "usr.purge")
return errors.Wrap(err, "usr.Delete")
}
}
grps, err := domain.getGroups()
@@ -359,16 +341,24 @@ func (domain *SDomain) purge(ctx context.Context, userCred mcclient.TokenCredent
return errors.Wrap(err, "domain.getGroups")
}
for i := range grps {
err = grps[i].ValidatePurgeCondition(ctx)
err = grps[i].ValidateDeleteCondition(ctx)
if err != nil {
return errors.Wrap(err, "grp.ValidatePurgeCondition")
return errors.Wrap(err, "grp.ValidateDeleteCondition")
}
err = grps[i].purge(ctx, userCred)
err = grps[i].Delete(ctx, userCred)
if err != nil {
return errors.Wrap(err, "grp.purge")
return errors.Wrap(err, "grp.Delete")
}
}
return domain.Delete(ctx, userCred)
return nil
}
func (domain *SDomain) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
err := domain.DeleteUserGroups(ctx, userCred)
if err != nil {
return errors.Wrap(err, "domain.DeleteUserGroups")
}
return domain.SStandaloneResourceBase.Delete(ctx, userCred)
}
func (domain *SDomain) getIdmapping() (*SIdmapping, error) {
@@ -402,3 +392,27 @@ func (domain *SDomain) PostDelete(ctx context.Context, userCred mcclient.TokenCr
domain.SStandaloneResourceBase.PostDelete(ctx, userCred)
logclient.AddActionLogWithContext(ctx, domain, logclient.ACT_DELETE, nil, userCred, true)
}
func (domain *SDomain) UnlinkIdp(idpId string) error {
usrs, err := domain.getUsers()
if err != nil {
return errors.Wrap(err, "domain.getUsers")
}
for i := range usrs {
err = usrs[i].UnlinkIdp(idpId)
if err != nil {
return errors.Wrap(err, "usr.UnlinkIdp")
}
}
grps, err := domain.getGroups()
if err != nil {
return errors.Wrap(err, "domain.getGroups")
}
for i := range grps {
err = grps[i].UnlinkIdp(idpId)
if err != nil {
return errors.Wrap(err, "grp.UnlinkIdp")
}
}
return IdmappingManager.deleteAny(idpId, api.IdMappingEntityDomain, domain.Id)
}
+22 -33
View File
@@ -19,7 +19,6 @@ import (
"database/sql"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
@@ -123,37 +122,25 @@ func (group *SGroup) GetProjectCount() (int, error) {
return q.CountWithError()
}
func (group *SGroup) ValidatePurgeCondition(ctx context.Context) error {
prjCnt, _ := group.GetProjectCount()
if prjCnt > 0 {
return httperrors.NewNotEmptyError("group joins project")
}
return nil
}
func (group *SGroup) ValidateDeleteCondition(ctx context.Context) error {
// usrCnt, _ := group.GetUserCount()
// if usrCnt > 0 {
// return httperrors.NewNotEmptyError("group contains user")
// }
err := group.ValidatePurgeCondition(ctx)
if err != nil {
return err
}
if group.IsReadOnly() {
return httperrors.NewForbiddenError("readonly")
}
return group.SIdentityBaseResource.ValidateDeleteCondition(ctx)
}
func (group *SGroup) PostDelete(ctx context.Context, userCred mcclient.TokenCredential) {
group.SIdentityBaseResource.PostDelete(ctx, userCred)
err := UsergroupManager.delete("", group.Id)
func (group *SGroup) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
err := AssignmentManager.projectRemoveAllGroup(ctx, userCred, group)
if err != nil {
log.Errorf("PasswordManager.delete fail %s", err)
return
return errors.Wrap(err, "AssignmentManager.projectRemoveAllGroup")
}
err = UsergroupManager.delete("", group.Id)
if err != nil {
return errors.Wrap(err, "UsergroupManager.delete")
}
return group.SIdentityBaseResource.Delete(ctx, userCred)
}
func (group *SGroup) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
@@ -250,14 +237,6 @@ func (manager *SGroupManager) NamespaceScope() rbacutils.TRbacScope {
return rbacutils.ScopeDomain
}
func (group *SGroup) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
err := UsergroupManager.delete("", group.Id)
if err != nil {
return errors.Wrap(err, "UsergroupManager.delete")
}
return group.Delete(ctx, userCred)
}
func (group *SGroup) getIdmapping() (*SIdmapping, error) {
return IdmappingManager.FetchEntity(group.Id, api.IdMappingEntityGroup)
}
@@ -275,6 +254,16 @@ func (manager *SGroupManager) FetchCustomizeColumns(ctx context.Context, userCre
return expandIdpAttributes(rows, objs, fields, api.IdMappingEntityGroup)
}
func (manager *SGroupManager) FetchGroupLocalIdsInDomain(domainId string, excludes []string) ([]string, error) {
return fetchLocalIdsInDomain(manager, domainId, excludes)
func (manager *SGroupManager) FetchGroupsInDomain(domainId string, excludes []string) ([]SGroup, error) {
q := manager.Query().Equals("domain_id", domainId).NotIn("id", excludes)
grps := make([]SGroup, 0)
err := db.FetchModelObjects(manager, q, &grps)
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "db.FetchModelObjects")
}
return grps, nil
}
func (group *SGroup) UnlinkIdp(idpId string) error {
return IdmappingManager.deleteAny(idpId, api.IdMappingEntityGroup, group.Id)
}
+28 -7
View File
@@ -125,19 +125,16 @@ func (manager *SIdmappingManager) FetchEntity(idStr string, entType string) (*SI
}
func (manager *SIdmappingManager) deleteByIdpId(idpId string) error {
return manager.DeleteAny(idpId, "", nil, nil)
return manager.deleteAny(idpId, "", "")
}
func (manager *SIdmappingManager) DeleteAny(idpId string, entityType string, excludeLocalIds []string, includeLocalIds []string) error {
func (manager *SIdmappingManager) deleteAny(idpId string, entityType string, publicId string) error {
q := manager.Query().Equals("domain_id", idpId)
if len(entityType) > 0 {
q = q.Equals("entity_type", entityType)
}
if len(excludeLocalIds) > 0 {
q = q.NotIn("local_id", excludeLocalIds)
}
if len(includeLocalIds) > 0 {
q = q.In("local_id", includeLocalIds)
if len(publicId) > 0 {
q = q.Equals("public_id", publicId)
}
idmappings := make([]SIdmapping, 0)
err := db.FetchModelObjects(manager, q, &idmappings)
@@ -154,3 +151,27 @@ func (manager *SIdmappingManager) DeleteAny(idpId string, entityType string, exc
}
return nil
}
func (manager *SIdmappingManager) FetchPublicIdsExcludes(idpId string, entityType string, excludes []string) ([]string, error) {
q := manager.Query("public_id").Equals("domain_id", idpId)
q = q.Equals("entity_type", entityType)
q = q.NotIn("public_id", excludes)
rows, err := q.Rows()
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "q.Rows")
}
if rows == nil {
return nil, nil
}
defer rows.Close()
ret := make([]string, 0)
for rows.Next() {
var idStr string
err = rows.Scan(&idStr)
if err != nil {
return nil, errors.Wrap(err, "rows.Scan")
}
ret = append(ret, idStr)
}
return ret, nil
}
+3 -3
View File
@@ -625,11 +625,11 @@ func (self *SIdentityProvider) Purge(ctx context.Context, userCred mcclient.Toke
for i := range domains {
err = domains[i].ValidatePurgeCondition(ctx)
if err != nil {
return errors.Wrap(err, "domain.ValidateDeleteCondition")
return errors.Wrap(err, "domain.ValidatePurgeCondition")
}
err = domains[i].purge(ctx, userCred)
err = domains[i].Delete(ctx, userCred)
if err != nil {
return errors.Wrap(err, "purge domain")
return errors.Wrap(err, "delete domain")
}
}
err = self.deleteConfig(ctx, userCred)
+3
View File
@@ -186,5 +186,8 @@ func (policy *SPolicy) ValidateDeleteCondition(ctx context.Context) error {
if policy.IsPublic {
return httperrors.NewInvalidStatusError("cannot delete shared policy")
}
if policy.Enabled.IsTrue() {
return httperrors.NewInvalidStatusError("cannot delete enabled policy")
}
return policy.SEnabledIdentityBaseResource.ValidateDeleteCondition(ctx)
}
+7 -7
View File
@@ -255,6 +255,13 @@ func (proj *SProject) GetGroupCount() (int, error) {
}
func (proj *SProject) ValidateDeleteCondition(ctx context.Context) error {
if proj.IsAdminProject() {
return httperrors.NewForbiddenError("cannot delete system project")
}
external, _ := proj.getExternalResources()
if len(external) > 0 {
return httperrors.NewNotEmptyError("project contains external resources")
}
usrCnt, _ := proj.GetUserCount()
if usrCnt > 0 {
return httperrors.NewNotEmptyError("project contains user")
@@ -263,13 +270,6 @@ func (proj *SProject) ValidateDeleteCondition(ctx context.Context) error {
if grpCnt > 0 {
return httperrors.NewNotEmptyError("project contains group")
}
external, _ := proj.getExternalResources()
if len(external) > 0 {
return httperrors.NewNotEmptyError("project contains external resources")
}
if proj.IsAdminProject() {
return httperrors.NewForbiddenError("cannot delete system project")
}
return proj.SIdentityBaseResource.ValidateDeleteCondition(ctx)
}
+6 -6
View File
@@ -179,6 +179,12 @@ func (role *SRole) IsSystemRole() bool {
}
func (role *SRole) ValidateDeleteCondition(ctx context.Context) error {
if role.IsPublic {
return httperrors.NewInvalidStatusError("cannot delete shared role")
}
if role.IsSystemRole() {
return httperrors.NewForbiddenError("cannot delete system role")
}
usrCnt, _ := role.GetUserCount()
if usrCnt > 0 {
return httperrors.NewNotEmptyError("role is being assigned to user")
@@ -187,12 +193,6 @@ func (role *SRole) ValidateDeleteCondition(ctx context.Context) error {
if grpCnt > 0 {
return httperrors.NewNotEmptyError("role is being assigned to group")
}
if role.IsPublic {
return httperrors.NewInvalidStatusError("cannot delete shared role")
}
if role.IsSystemRole() {
return httperrors.NewForbiddenError("cannot delete system role")
}
return role.SIdentityBaseResource.ValidateDeleteCondition(ctx)
}
+29 -82
View File
@@ -472,52 +472,40 @@ func (user *SUser) PostUpdate(ctx context.Context, userCred mcclient.TokenCreden
}
}
func (user *SUser) ValidatePurgeCondition(ctx context.Context) error {
prjCnt, _ := user.GetProjectCount()
if prjCnt > 0 {
return httperrors.NewNotEmptyError("user joins project")
}
func (user *SUser) ValidateDeleteCondition(ctx context.Context) error {
if user.IsAdminUser() {
return httperrors.NewForbiddenError("cannot delete system user")
}
return nil
}
func (user *SUser) ValidateDeleteCondition(ctx context.Context) error {
// grpCnt, _ := user.GetGroupCount()
// if grpCnt > 0 {
// return httperrors.NewNotEmptyError("group contains user")
// }
err := user.ValidatePurgeCondition(ctx)
if err != nil {
return err
}
if user.IsReadOnly() {
return httperrors.NewForbiddenError("readonly")
}
return user.SIdentityBaseResource.ValidateDeleteCondition(ctx)
}
func (user *SUser) PostDelete(ctx context.Context, userCred mcclient.TokenCredential) {
user.SEnabledIdentityBaseResource.PostDelete(ctx, userCred)
localUser, err := LocalUserManager.delete(user.Id, user.DomainId)
func (user *SUser) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
err := AssignmentManager.projectRemoveAllUser(ctx, userCred, user)
if err != nil {
log.Errorf("LocalUserManager.delete fail %s", err)
return
}
err = PasswordManager.delete(localUser.Id)
if err != nil {
log.Errorf("PasswordManager.delete fail %s", err)
return
return errors.Wrap(err, "AssignmentManager.projectRemoveAllUser")
}
err = UsergroupManager.delete(user.Id, "")
if err != nil {
log.Errorf("UsergroupManager.delete fail %s", err)
return
return errors.Wrap(err, "UsergroupManager.delete")
}
localUser, err := LocalUserManager.delete(user.Id, user.DomainId)
if err != nil {
return errors.Wrap(err, "LocalUserManager.delete")
}
if localUser != nil {
err = PasswordManager.delete(localUser.Id)
if err != nil {
return errors.Wrap(err, "PasswordManager.delete")
}
}
return user.SEnabledIdentityBaseResource.Delete(ctx, userCred)
}
func (user *SUser) UpdateInContext(ctx context.Context, userCred mcclient.TokenCredential, ctxObjs []db.IModel, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
@@ -619,27 +607,6 @@ func (manager *SUserManager) NamespaceScope() rbacutils.TRbacScope {
return rbacutils.ScopeDomain
}
func (user *SUser) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
localUser, err := LocalUserManager.delete(user.Id, user.DomainId)
if err != nil {
return errors.Wrap(err, "LocalUserManager.delete")
}
if localUser != nil {
err = PasswordManager.delete(localUser.Id)
if err != nil {
return errors.Wrap(err, "PasswordManager.delete")
}
}
err = UsergroupManager.delete(user.Id, "")
if err != nil {
return errors.Wrap(err, "UsergroupManager.delete")
}
return user.Delete(ctx, userCred)
}
func (user *SUser) getIdmapping() (*SIdmapping, error) {
return IdmappingManager.FetchEntity(user.Id, api.IdMappingEntityUser)
}
@@ -657,36 +624,16 @@ func (manager *SUserManager) FetchCustomizeColumns(ctx context.Context, userCred
return expandIdpAttributes(rows, objs, fields, api.IdMappingEntityUser)
}
func (manager *SUserManager) FetchUserLocalIdsInDomain(domainId string, excludes []string) ([]string, error) {
return fetchLocalIdsInDomain(manager, domainId, excludes)
func (manager *SUserManager) FetchUsersInDomain(domainId string, excludes []string) ([]SUser, error) {
q := manager.Query().Equals("domain_id", domainId).NotIn("id", excludes)
usrs := make([]SUser, 0)
err := db.FetchModelObjects(manager, q, &usrs)
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "db.FetchModelObjects")
}
return usrs, nil
}
func fetchLocalIdsInDomain(manager db.IModelManager, domainId string, excludes []string) ([]string, error) {
idmappings := IdmappingManager.Query().SubQuery()
users := manager.Query().SubQuery()
q := idmappings.Query(idmappings.Field("local_id"))
q = q.Join(users, sqlchemy.AND(
sqlchemy.Equals(idmappings.Field("entity_type"), manager.Keyword()),
sqlchemy.Equals(idmappings.Field("public_id"), users.Field("id")),
))
q = q.Filter(sqlchemy.Equals(users.Field("domain_id"), domainId))
q = q.Filter(sqlchemy.NotIn(idmappings.Field("local_id"), excludes))
rows, err := q.Rows()
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "query")
}
if rows == nil {
return nil, nil
}
defer rows.Close()
ret := make([]string, 0)
for rows.Next() {
var idStr string
err = rows.Scan(&idStr)
if err != nil {
return nil, errors.Wrap(err, "scan")
}
ret = append(ret, idStr)
}
return ret, nil
func (user *SUser) UnlinkIdp(idpId string) error {
return IdmappingManager.deleteAny(idpId, api.IdMappingEntityUser, user.Id)
}
+2 -1
View File
@@ -21,8 +21,9 @@ import (
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/util/rbacutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
const REGION_ZONE_SEP = '-'
+9 -4
View File
@@ -22,12 +22,13 @@ import (
"github.com/vmware/govmomi/vim25/types"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
var DATACENTER_PROPS = []string{"name", "parent", "datastore"}
var DATACENTER_PROPS = []string{"name", "parent", "datastore", "network"}
type SDatacenter struct {
SManagedObject
@@ -86,9 +87,13 @@ func (dc *SDatacenter) scanDatastores() error {
return err
}
}
dc.istorages = make([]cloudprovider.ICloudStorage, len(stores))
dc.istorages = make([]cloudprovider.ICloudStorage, 0)
for i := 0; i < len(stores); i += 1 {
dc.istorages[i] = NewDatastore(dc.manager, &stores[i], dc)
ds := NewDatastore(dc.manager, &stores[i], dc)
dsId := ds.GetGlobalId()
if len(dsId) > 0 {
dc.istorages = append(dc.istorages, ds)
}
}
}
return nil
@@ -97,7 +102,7 @@ func (dc *SDatacenter) scanDatastores() error {
func (dc *SDatacenter) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
err := dc.scanDatastores()
if err != nil {
return nil, err
return nil, errors.Wrap(err, "dc.scanDatastores")
}
return dc.istorages, nil
}
+18
View File
@@ -318,15 +318,33 @@ func (self *SHost) fetchNicInfo() []SHostNicInfo {
nicInfoList = append(nicInfoList, info)
}
findMaster := false
for _, nic := range moHost.Config.Network.Vnic {
mac := netutils.FormatMacAddr(nic.Spec.Mac)
pnic := findHostNicByMac(nicInfoList, mac)
if pnic != nil {
findMaster = true
pnic.IpAddr = nic.Spec.Ip.IpAddress
if nic.Spec.Portgroup == "Management Network" {
pnic.NicType = api.NIC_TYPE_ADMIN
}
pnic.LinkUp = true
pnic.Mtu = nic.Spec.Mtu
}
}
if !findMaster && len(nicInfoList) > 0 {
// no match pnic found for master nic
// choose the first pnic
pnic := &nicInfoList[0]
for _, nic := range moHost.Config.Network.Vnic {
if nic.Spec.Portgroup == "Management Network" {
pnic.NicType = api.NIC_TYPE_ADMIN
pnic.IpAddr = nic.Spec.Ip.IpAddress
pnic.LinkUp = true
pnic.Mtu = nic.Spec.Mtu
break
}
}
}
+2 -2
View File
@@ -25,7 +25,7 @@ type SHostNicInfo struct {
Index int8
LinkUp bool
IpAddr string
Mtu int16
Mtu int32
NicType string
}
@@ -56,7 +56,7 @@ func (nic *SHostNicInfo) GetIpAddr() string {
return nic.IpAddr
}
func (nic *SHostNicInfo) GetMtu() int16 {
func (nic *SHostNicInfo) GetMtu() int32 {
return nic.Mtu
}
+10 -8
View File
@@ -33,6 +33,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -66,7 +67,7 @@ func (self *SDatastore) getDatastore() *mo.Datastore {
func (self *SDatastore) GetGlobalId() string {
volId, err := self.getVolumeId()
if err != nil {
log.Fatalf("datastore global ID error %s", err)
log.Errorf("get datastore global ID error %s", err)
}
return volId
}
@@ -119,13 +120,11 @@ func (self *SDatastore) getVolumeId() (string, error) {
case *types.VmfsDatastoreInfo:
if fsInfo.Vmfs.Local == nil || *fsInfo.Vmfs.Local {
host, err := self.getLocalHost()
if err != nil {
return "", err
if err == nil {
return fmt.Sprintf("%s:%s", host.GetAccessIp(), fsInfo.Vmfs.Uuid), nil
}
return fmt.Sprintf("%s:%s", host.GetAccessIp(), fsInfo.Vmfs.Uuid), nil
} else {
return fsInfo.Vmfs.Uuid, nil
}
return fsInfo.Vmfs.Uuid, nil
case *types.NasDatastoreInfo:
return fmt.Sprintf("%s:%s", fsInfo.Nas.RemoteHost, fsInfo.Nas.RemotePath), nil
}
@@ -196,7 +195,7 @@ func (self *SDatastore) GetAttachedHosts() ([]cloudprovider.ICloudHost, error) {
func (self *SDatastore) getLocalHost() (cloudprovider.ICloudHost, error) {
hosts, err := self.GetAttachedHosts()
if err != nil {
return nil, err
return nil, errors.Wrap(err, "self.GetAttachedHosts")
}
if len(hosts) == 1 {
return hosts[0], nil
@@ -286,7 +285,10 @@ func (self *SDatastore) isLocalVMFS() bool {
switch vmfsInfo := moStore.Info.(type) {
case *types.VmfsDatastoreInfo:
if vmfsInfo.Vmfs.Local == nil || *vmfsInfo.Vmfs.Local == true {
return true
_, err := self.getLocalHost()
if err == nil {
return true
}
}
}
return false
+15 -1
View File
@@ -22,6 +22,8 @@ import (
"gopkg.in/ldap.v3"
"github.com/pkg/errors"
"yunion.io/x/log"
)
var (
@@ -31,6 +33,7 @@ var (
binaryAttributes = []string{
"objectGUID",
"objectSid",
}
)
@@ -120,7 +123,7 @@ func (cli *SLDAPClient) Search(base string, objClass string, condition map[strin
searches.WriteString(k)
searches.WriteString("=")
if isBinaryAttr(k) {
v = toBinary(v)
v = toBinarySearchString(v)
}
searches.WriteString(v)
searches.WriteString(")")
@@ -138,6 +141,8 @@ func (cli *SLDAPClient) Search(base string, objClass string, condition map[strin
queryScope = ldap.ScopeWholeSubtree
}
log.Debugf("ldapSearch: %s", searchStr)
searchRequest := ldap.NewSearchRequest(
base, // The base dn to search
queryScope, ldap.NeverDerefAliases, 0, 0, false,
@@ -171,6 +176,15 @@ func toBinary(val string) string {
}
}
func toBinarySearchString(val string) string {
ret := strings.Builder{}
for i := 0; i < len(val); i += 2 {
ret.WriteString(`\`)
ret.WriteString(val[i : i+2])
}
return ret.String()
}
func toHex(val string) string {
return hex.EncodeToString([]byte(val))
}