// 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. package org.apache.cloudstack.engine.datacenter.entity.api.db.dao; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Random; import javax.inject.Inject; import javax.naming.ConfigurationException; import javax.persistence.TableGenerator; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity; import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State; import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State.Event; import org.apache.cloudstack.engine.datacenter.entity.api.db.EngineDataCenterVO; import com.cloud.org.Grouping; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SequenceFetcher; import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.db.UpdateBuilder; import com.cloud.utils.net.NetUtils; /** * @config * {@table * || Param Name | Description | Values | Default || * || mac.address.prefix | prefix to attach to all public and private mac addresses | number | 06 || * } **/ @Component(value = "EngineDataCenterDao") public class EngineDataCenterDaoImpl extends GenericDaoBase<EngineDataCenterVO, Long> implements EngineDataCenterDao { private static final Logger s_logger = Logger.getLogger(EngineDataCenterDaoImpl.class); protected SearchBuilder<EngineDataCenterVO> NameSearch; protected SearchBuilder<EngineDataCenterVO> ListZonesByDomainIdSearch; protected SearchBuilder<EngineDataCenterVO> PublicZonesSearch; protected SearchBuilder<EngineDataCenterVO> ChildZonesSearch; protected SearchBuilder<EngineDataCenterVO> DisabledZonesSearch; protected SearchBuilder<EngineDataCenterVO> TokenSearch; protected SearchBuilder<EngineDataCenterVO> StateChangeSearch; protected SearchBuilder<EngineDataCenterVO> UUIDSearch; protected long _prefix; protected Random _rand = new Random(System.currentTimeMillis()); protected TableGenerator _tgMacAddress; @Inject protected DcDetailsDao _detailsDao; @Override public EngineDataCenterVO findByName(String name) { SearchCriteria<EngineDataCenterVO> sc = NameSearch.create(); sc.setParameters("name", name); return findOneBy(sc); } @Override public EngineDataCenterVO findByToken(String zoneToken) { SearchCriteria<EngineDataCenterVO> sc = TokenSearch.create(); sc.setParameters("zoneToken", zoneToken); return findOneBy(sc); } @Override public List<EngineDataCenterVO> findZonesByDomainId(Long domainId) { SearchCriteria<EngineDataCenterVO> sc = ListZonesByDomainIdSearch.create(); sc.setParameters("domainId", domainId); return listBy(sc); } @Override public List<EngineDataCenterVO> findZonesByDomainId(Long domainId, String keyword) { SearchCriteria<EngineDataCenterVO> sc = ListZonesByDomainIdSearch.create(); sc.setParameters("domainId", domainId); if (keyword != null) { SearchCriteria<EngineDataCenterVO> ssc = createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%"); sc.addAnd("name", SearchCriteria.Op.SC, ssc); } return listBy(sc); } @Override public List<EngineDataCenterVO> findChildZones(Object[] ids, String keyword) { SearchCriteria<EngineDataCenterVO> sc = ChildZonesSearch.create(); sc.setParameters("domainid", ids); if (keyword != null) { SearchCriteria<EngineDataCenterVO> ssc = createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%"); sc.addAnd("name", SearchCriteria.Op.SC, ssc); } return listBy(sc); } @Override public List<EngineDataCenterVO> listPublicZones(String keyword) { SearchCriteria<EngineDataCenterVO> sc = PublicZonesSearch.create(); if (keyword != null) { SearchCriteria<EngineDataCenterVO> ssc = createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%"); sc.addAnd("name", SearchCriteria.Op.SC, ssc); } //sc.setParameters("domainId", domainId); return listBy(sc); } @Override public List<EngineDataCenterVO> findByKeyword(String keyword) { SearchCriteria<EngineDataCenterVO> ssc = createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%"); return listBy(ssc); } @Override public String[] getNextAvailableMacAddressPair(long id) { return getNextAvailableMacAddressPair(id, 0); } @Override public String[] getNextAvailableMacAddressPair(long id, long mask) { SequenceFetcher fetch = SequenceFetcher.getInstance(); long seq = fetch.getNextSequence(Long.class, _tgMacAddress, id); seq = seq | _prefix | ((id & 0x7f) << 32); seq |= mask; seq |= ((_rand.nextInt(Short.MAX_VALUE) << 16) & 0x00000000ffff0000l); String[] pair = new String[2]; pair[0] = NetUtils.long2Mac(seq); pair[1] = NetUtils.long2Mac(seq | 0x1l << 39); return pair; } @Override public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { if (!super.configure(name, params)) { return false; } String value = (String)params.get("mac.address.prefix"); _prefix = (long)NumbersUtil.parseInt(value, 06) << 40; return true; } protected EngineDataCenterDaoImpl() { super(); NameSearch = createSearchBuilder(); NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ); NameSearch.done(); ListZonesByDomainIdSearch = createSearchBuilder(); ListZonesByDomainIdSearch.and("domainId", ListZonesByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ); ListZonesByDomainIdSearch.done(); PublicZonesSearch = createSearchBuilder(); PublicZonesSearch.and("domainId", PublicZonesSearch.entity().getDomainId(), SearchCriteria.Op.NULL); PublicZonesSearch.done(); ChildZonesSearch = createSearchBuilder(); ChildZonesSearch.and("domainid", ChildZonesSearch.entity().getDomainId(), SearchCriteria.Op.IN); ChildZonesSearch.done(); DisabledZonesSearch = createSearchBuilder(); DisabledZonesSearch.and("allocationState", DisabledZonesSearch.entity().getAllocationState(), SearchCriteria.Op.EQ); DisabledZonesSearch.done(); TokenSearch = createSearchBuilder(); TokenSearch.and("zoneToken", TokenSearch.entity().getZoneToken(), SearchCriteria.Op.EQ); TokenSearch.done(); StateChangeSearch = createSearchBuilder(); StateChangeSearch.and("id", StateChangeSearch.entity().getId(), SearchCriteria.Op.EQ); StateChangeSearch.and("state", StateChangeSearch.entity().getState(), SearchCriteria.Op.EQ); StateChangeSearch.done(); UUIDSearch = createSearchBuilder(); UUIDSearch.and("uuid", UUIDSearch.entity().getUuid(), SearchCriteria.Op.EQ); UUIDSearch.done(); _tgMacAddress = _tgs.get("macAddress"); assert _tgMacAddress != null : "Couldn't get mac address table generator"; } @Override @DB public boolean update(Long zoneId, EngineDataCenterVO zone) { TransactionLegacy txn = TransactionLegacy.currentTxn(); txn.start(); boolean persisted = super.update(zoneId, zone); if (!persisted) { return persisted; } saveDetails(zone); txn.commit(); return persisted; } @Override public void loadDetails(EngineDataCenterVO zone) { Map<String, String> details = _detailsDao.findDetails(zone.getId()); zone.setDetails(details); } @Override public void saveDetails(EngineDataCenterVO zone) { Map<String, String> details = zone.getDetails(); if (details == null) { return; } _detailsDao.persist(zone.getId(), details); } @Override public List<EngineDataCenterVO> listDisabledZones() { SearchCriteria<EngineDataCenterVO> sc = DisabledZonesSearch.create(); sc.setParameters("allocationState", Grouping.AllocationState.Disabled); List<EngineDataCenterVO> dcs = listBy(sc); return dcs; } @Override public List<EngineDataCenterVO> listEnabledZones() { SearchCriteria<EngineDataCenterVO> sc = DisabledZonesSearch.create(); sc.setParameters("allocationState", Grouping.AllocationState.Enabled); List<EngineDataCenterVO> dcs = listBy(sc); return dcs; } @Override public EngineDataCenterVO findByTokenOrIdOrName(String tokenOrIdOrName) { EngineDataCenterVO result = findByToken(tokenOrIdOrName); if (result == null) { result = findByName(tokenOrIdOrName); if (result == null) { try { Long dcId = Long.parseLong(tokenOrIdOrName); return findById(dcId); } catch (NumberFormatException nfe) { s_logger.debug("Cannot parse " + tokenOrIdOrName + " into long. " + nfe); } } } return result; } @Override public boolean remove(Long id) { TransactionLegacy txn = TransactionLegacy.currentTxn(); txn.start(); EngineDataCenterVO zone = createForUpdate(); zone.setName(null); update(id, zone); boolean result = super.remove(id); txn.commit(); return result; } @Override public boolean updateState(State currentState, Event event, State nextState, DataCenterResourceEntity zoneEntity, Object data) { EngineDataCenterVO vo = findById(zoneEntity.getId()); Date oldUpdatedTime = vo.getLastUpdated(); SearchCriteria<EngineDataCenterVO> sc = StateChangeSearch.create(); sc.setParameters("id", vo.getId()); sc.setParameters("state", currentState); UpdateBuilder builder = getUpdateBuilder(vo); builder.set(vo, "state", nextState); builder.set(vo, "lastUpdated", new Date()); int rows = update(vo, sc); if (rows == 0 && s_logger.isDebugEnabled()) { EngineDataCenterVO dbDC = findByIdIncludingRemoved(vo.getId()); if (dbDC != null) { StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); str.append(": DB Data={id=").append(dbDC.getId()).append("; state=").append(dbDC.getState()).append(";updatedTime=").append(dbDC.getLastUpdated()); str.append(": New Data={id=") .append(vo.getId()) .append("; state=") .append(nextState) .append("; event=") .append(event) .append("; updatedTime=") .append(vo.getLastUpdated()); str.append(": stale Data={id=") .append(vo.getId()) .append("; state=") .append(currentState) .append("; event=") .append(event) .append("; updatedTime=") .append(oldUpdatedTime); } else { s_logger.debug("Unable to update dataCenter: id=" + vo.getId() + ", as there is no such dataCenter exists in the database anymore"); } } return rows > 0; } }