Commit 7d9ce68b authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

add UpdateNF operation

parent 7e46eca2
......@@ -60,8 +60,7 @@ void NFInstanceIDDocumentApiImpl::register_nf_instance(
response.headers().add < Pistache::Http::Header::Location
> (m_address + base + nrf_cfg.sbi_api_version + "/nf-instances/"
+ nfInstanceID);
response.send(Pistache::Http::Code::Ok, json_data.dump().c_str());
response.send(Pistache::Http::Code(http_code), json_data.dump().c_str());
}
void NFInstanceIDDocumentApiImpl::update_nf_instance(
const std::string &nfInstanceID, const std::vector<PatchItem> &patchItem,
......
......@@ -54,10 +54,10 @@ void from_json(const nlohmann::json &j, PatchItem &o) {
}
}
PatchOperation PatchItem::getOp() const {
std::string PatchItem::getOp() const {
return m_Op;
}
void PatchItem::setOp(PatchOperation const &value) {
void PatchItem::setOp(std::string const &value) {
m_Op = value;
}
std::string PatchItem::getPath() const {
......
......@@ -43,8 +43,8 @@ class PatchItem {
/// <summary>
///
/// </summary>
PatchOperation getOp() const;
void setOp(PatchOperation const &value);
std::string getOp() const;
void setOp(std::string const &value);
/// <summary>
///
/// </summary>
......@@ -68,7 +68,7 @@ class PatchItem {
friend void to_json(nlohmann::json &j, const PatchItem &o);
friend void from_json(const nlohmann::json &j, PatchItem &o);
protected:
PatchOperation m_Op;
std::string m_Op;
std::string m_Path;
......
......@@ -56,6 +56,20 @@ static const std::vector<std::string> nf_type_e2str = { "NF_TYPE_NRF",
"NF_TYPE_N3IWF", "NF_TYPE_AF", "NF_TYPE_UDSF", "NF_TYPE_BSF", "NF_TYPE_CHF",
"NF_TYPE_NWDAF", "NF_TYPE_UNKNOWN" };
typedef enum patch_op_type_s {
PATCH_OP_ADD = 0,
PATCH_OP_REMOVE = 1,
PATCH_OP_REPLACE = 2,
PATCH_OP_MOVE = 3,
PATCH_OP_COPY = 4,
PATCH_OP_TEST = 5,
PATCH_OP_UNKNOWN = 6
} patch_op_type_t;
static const std::vector<std::string> patch_op_type_e2str = { "ADD", "REMOVE",
"REPLACE", "MOVE", "COPY", "TEST", "UNKNOWN" };
typedef struct s_nssai // section 28.4, TS23.003
{
uint8_t sST;
......
......@@ -35,70 +35,17 @@
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include "api_conversions.hpp"
#include "string.hpp"
#include "nrf.h"
#include "AmfInfo.h"
#include "api_conversions.hpp"
#include "logger.hpp"
#include "nrf.h"
#include "string.hpp"
using namespace oai::nrf::model;
using namespace oai::nrf::app;
using namespace oai::nrf;
//------------------------------------------------------------------------------
/*
bool api_conv::profile_api_to_amf_profile(const NFProfile &api_profile,
std::shared_ptr<amf_profile> &profile) {
Logger::nrf_app().debug(
"Convert a NF profile generated from OpenAPI to an AMF profile (profile name %s)",
api_profile.getNfInstanceName().c_str());
profile.get()->set_nf_instance_name(api_profile.getNfInstanceName());
Logger::nrf_app().debug("AMF profile, instance name %s",
profile.get()->get_nf_instance_name().c_str());
profile.get()->set_nf_status(api_profile.getNfStatus());
Logger::nrf_app().debug("AMF profile, status %s",
profile.get()->get_nf_status().c_str());
profile.get()->set_nf_heartBeat_timer(api_profile.getHeartBeatTimer());
Logger::nrf_app().debug("AMF profile, status %d",
profile.get()->get_nf_hertBeat_timer());
profile.get()->set_nf_priority(api_profile.getPriority());
Logger::nrf_app().debug("AMF profile, priority %d",
profile.get()->get_nf_priority());
profile.get()->set_nf_capacity(api_profile.getCapacity());
Logger::nrf_app().debug("AMF profile, capacity %d",
profile.get()->get_nf_capacity());
//SNSSAIs
std::vector<Snssai> snssai = api_profile.getSNssais();
for (auto s : snssai) {
snssai_t sn = { };
sn.sD = s.getSd();
sn.sST = s.getSst();
profile.get()->add_snssai(sn);
Logger::nrf_app().debug("AMF profile, snssai %d, %s", sn.sST,
sn.sD.c_str());
}
std::vector < std::string > ipv4_addr_str = api_profile.getIpv4Addresses();
for (auto address : ipv4_addr_str) {
struct in_addr addr4 = { };
unsigned char buf_in_addr[sizeof(struct in_addr)];
if (inet_pton(AF_INET, util::trim(address).c_str(), buf_in_addr) == 1) {
memcpy(&addr4, buf_in_addr, sizeof(struct in_addr));
} else {
Logger::nrf_app().warn("NF IPv4 Addr conversion: Bad value %s",
util::trim(address).c_str());
}
Logger::nrf_app().debug("AMF profile, IPv4 Addr %s", address.c_str());
profile.get()->add_nf_ipv4_addresses(addr4);
}
return true;
}
*/
//------------------------------------------------------------------------------
bool api_conv::profile_api_to_amf_profile(
const NFProfile &api_profile, std::shared_ptr<nrf_profile> &profile) {
......@@ -191,35 +138,7 @@ bool api_conv::profile_api_to_amf_profile(
}
}
/*
if (api_profile.getNfType().compare("AMF") == 0) {
Logger::nrf_app().debug("............AMF profile, AMF Info");
profile.get()->set_nf_type("AMF");
amf_info_t info = { };
AmfInfo amf_info_api = api_profile.getAmfInfo();
info.amf_region_id = amf_info_api.getAmfRegionId();
info.amf_set_id = amf_info_api.getAmfSetId();
Logger::nrf_app().debug("............AMF Set ID: %s, AMF Region ID: %s",
info.amf_set_id.c_str(),
info.amf_region_id.c_str());
for (auto g : amf_info_api.getGuamiList()) {
guami_t guami = { };
guami.amf_id = g.getAmfId();
guami.plmn.mcc = g.getPlmnId().getMcc();
guami.plmn.mnc = g.getPlmnId().getMnc();
info.guami_list.push_back(guami);
Logger::nrf_app().debug("............AMF GUAMI, AMF_ID: %s",
guami.amf_id.c_str());
Logger::nrf_app().debug("....................., PLMN (MCC: %s, MNC: %s)",
guami.plmn.mcc.c_str(), guami.plmn.mnc.c_str());
}
(std::static_pointer_cast < amf_profile > (profile)).get()->add_amf_info(
info);
}
*/
return true;
}
......@@ -268,3 +187,21 @@ nf_type_t api_conv::string_to_nf_type(const std::string &str) {
//default
return NF_TYPE_UNKNOWN;
}
//------------------------------------------------------------------------------
patch_op_type_t api_conv::string_to_patch_operation(const std::string &str) {
if (str.compare("add") == 0)
return PATCH_OP_ADD;
if (str.compare("copy") == 0)
return PATCH_OP_COPY;
if (str.compare("move") == 0)
return PATCH_OP_MOVE;
if (str.compare("remove") == 0)
return PATCH_OP_REMOVE;
if (str.compare("replace") == 0)
return PATCH_OP_REPLACE;
if (str.compare("test") == 0)
return PATCH_OP_TEST;
//default
return PATCH_OP_UNKNOWN;
}
......@@ -41,10 +41,29 @@ namespace oai {
namespace nrf {
namespace api_conv {
/*
* Convert a json-type profile to a NF profile
* @param [const NFProfile &] NFProfile: Json-type profile from OpenAPITool
* @param [std::shared_ptr<nrf_profile> &] profile: NF profile
* @return true if successful, otherwise, return false
*/
bool profile_api_to_amf_profile(const NFProfile &api_profile,
std::shared_ptr<nrf_profile> &profile);
/*
* Convert a string to nf type
* @param [const std::string &] str: string input
* @return the corresponding nf_type
*/
nf_type_t string_to_nf_type(const std::string &str);
/*
* Convert a string to Patch operation
* @param [const std::string &] str: string input
* @return the corresponding Patch operation
*/
patch_op_type_t string_to_patch_operation(const std::string &str);
} // namespace api_conv
}
}
......
......@@ -57,105 +57,36 @@ void nrf_app::handle_register_nf_instance(
//Check if nfInstanceID is a valid UUID (version 4)
//TODO
//Create NF and store
/*
std::shared_ptr<nrf_profile> sn = { };
sn = find_nf_profile(nf_instance_id);
if (sn.get() != nullptr) {
if (sn.get()->get_nf_type() == NF_TYPE_AMF) {
std::shared_ptr<amf_profile> sa = std::static_pointer_cast
< amf_profile > (sn);
if (!api_conv::profile_api_to_amf_profile(nf_profile, sa)) {
//error, TODO
Logger::nrf_app().warn(
"Cannot convert a NF profile generated from OpenAPI to an AMF profile (profile ID %s)",
nf_instance_id.c_str());
}
update_nf_profile(nf_instance_id, sa);
}
//if (is_profile_exist(nf_instance_id)) {
//if (find_nf_profile(nf_instance_id, sn)) {
//if a profile exist with this ID, return error
//sa = std::static_pointer_cast <amf_profile> (sn);
//update_nf_profile(nf_instance_id, sa);
} else {
//create a new NF profile
Logger::nrf_app().debug("NF Profile with (ID %s, NF type %s)",
nf_instance_id.c_str(), nf_profile.getNfType().c_str());
std::shared_ptr<amf_profile> sa = { };
if (nf_profile.getNfType().compare("AMF") == 0) {
sa = std::shared_ptr < amf_profile
> (new amf_profile(nf_instance_id));
if (!api_conv::profile_api_to_amf_profile(nf_profile, sa)) {
//error, TODO
}
}
add_nf_profile(nf_instance_id, sa);
}
*/
/*
//create/Update NF profile
Logger::nrf_app().debug("NF Profile with (ID %s, NF type %s)",
nf_instance_id.c_str(), nf_profile.getNfType().c_str());
if (nf_profile.getNfType().compare("AMF") == 0) {
std::shared_ptr<amf_profile> sa = { };
sa = std::shared_ptr < amf_profile > (new amf_profile(nf_instance_id));
if (!api_conv::profile_api_to_amf_profile(nf_profile, sa)) {
//error, TODO
Logger::nrf_app().warn(
"Cannot convert a NF profile generated from OpenAPI to an AMF profile (profile ID %s)",
nf_instance_id.c_str());
http_code = 412; //Precondition Failed
} else {
add_nf_profile(nf_instance_id, sa);
http_code = 200;
}
}
*/
nf_type_t type = api_conv::string_to_nf_type(nf_profile.getNfType());
//Create a new NF profile or Update an existing NF profile
Logger::nrf_app().debug("NF Profile with (ID %s, NF type %s)",
nf_instance_id.c_str(),
nf_profile.getNfType().c_str());
std::shared_ptr<nrf_profile> sn = { };
switch (type) {
case NF_TYPE_AMF:
case NF_TYPE_AMF: {
sn = std::make_shared<amf_profile>();
}
break;
case NF_TYPE_SMF:
//TODO
case NF_TYPE_SMF: {
//TODO:
}
break;
default:
default: {
sn = std::make_shared<nrf_profile>();
}
}
/*
if (nf_profile.getNfType().compare("AMF") == 0) {
sn = std::make_shared<amf_profile>();
} else if (nf_profile.getNfType().compare("SMF") == 0) {
//TODO:
} else {
//default
sn = std::make_shared<nrf_profile>();
}
*/
//convert to nrf_profile
if (api_conv::profile_api_to_amf_profile(nf_profile, sn)) {
add_nf_profile(nf_instance_id, sn);
http_code = HTTP_STATUS_CODE_201_CREATED;
Logger::nrf_app().debug("Added NF Profile to the DB");
if (nf_profile.getNfType().compare("AMF") == 0)
std::static_pointer_cast < amf_profile > (sn).get()->display();
} else {
//error
Logger::nrf_app().warn(
......@@ -164,16 +95,9 @@ void nrf_app::handle_register_nf_instance(
http_code = HTTP_STATUS_CODE_412_PRECONDITION_FAILED;
}
//For Debug purpose
/* std::vector < std::shared_ptr < nrf_profile >> profiles = { };
find_nf_profiles("AMF", profiles);
for (auto profile : profiles) {
(std::static_pointer_cast < amf_profile > (profile)).get()->display();
}
*/
}
//------------------------------------------------------------------------------
void nrf_app::handle_update_nf_instance(const std::string &nf_instance_id,
const std::vector<PatchItem> &patchItem,
int &http_code,
......@@ -185,30 +109,53 @@ void nrf_app::handle_update_nf_instance(const std::string &nf_instance_id,
//Find the profile corresponding to the instance ID
std::shared_ptr<nrf_profile> sn = { };
sn = find_nf_profile(nf_instance_id);
if (sn.get() != nullptr) {
//if (find_nf_profile(nf_instance_id, sn)) {
//if a profile exist with this ID, return error
//sa = std::static_pointer_cast <amf_profile> (sn);
//update_nf_profile(nf_instance_id, sa);
//std::shared_ptr<amf_profile> sa = { };
if (sn.get()->get_nf_type() == NF_TYPE_AMF) {
std::shared_ptr<amf_profile> sa = std::static_pointer_cast < amf_profile
> (sn);
update_nf_profile(nf_instance_id, sa);
for (auto p : patchItem) {
patch_op_type_t op = api_conv::string_to_patch_operation(p.getOp());
std::string path = p.getPath().substr(1);
switch (op) {
case PATCH_OP_REPLACE: {
switch (sn.get()->get_nf_type()) {
case NF_TYPE_AMF: {
Logger::nrf_app().debug("Update a AMF profile");
if (std::static_pointer_cast < amf_profile
> (sn)->replace_profile_info(path, p.getValue()))
update_nf_profile(nf_instance_id, sn);
}
break;
case NF_TYPE_SMF: {
}
break;
default: {
Logger::nrf_app().warn("Unknown NF type!");
}
}
}
case PATCH_OP_ADD: {
}
break;
default: {
Logger::nrf_app().warn("Requested operation is not valid!");
}
}
}
//add_nf_profile(nf_instance_id, sa);
} else {
Logger::nrf_app().debug("NF Profile with ID %s does not exit",
nf_instance_id.c_str());
}
//location header - URI of created resource: can be used with ID - UUID
}
//------------------------------------------------------------------------------
void nrf_app::handle_get_nf_instances(const std::string &nf_type,
const uint32_t limit_item, int &http_code,
const uint32_t &limit_item,
int &http_code,
const uint8_t http_version) {
Logger::nrf_app().info(
"Handle Retrieve a collection of NF Instances (HTTP version %d)",
......@@ -217,13 +164,14 @@ void nrf_app::handle_get_nf_instances(const std::string &nf_type,
std::vector < std::shared_ptr < nrf_profile >> profiles = { };
nf_type_t type = api_conv::string_to_nf_type(nf_type);
find_nf_profiles(type, profiles);
if (profiles.size() == 0) {
Logger::nrf_app().debug("No profile found with type %s", nf_type.c_str());
}
for (auto profile : profiles) {
(std::static_pointer_cast < amf_profile > (profile)).get()->display();
}
}
//------------------------------------------------------------------------------
......@@ -244,7 +192,7 @@ bool nrf_app::add_nf_profile(const std::string &profile_id,
profile_id.c_str());
instance_id2nrf_profile.emplace(profile_id, p);
}*/
//Create or update if profile exist
//Create or update if profile exist
instance_id2nrf_profile[profile_id] = p;
return true;
}
......@@ -253,7 +201,7 @@ bool nrf_app::add_nf_profile(const std::string &profile_id,
bool nrf_app::update_nf_profile(const std::string &profile_id,
const std::shared_ptr<nrf_profile> &p) {
std::unique_lock lock(m_instance_id2nrf_profile);
//if profile with this id exist, return false
//if profile with this id exist, return false
if (instance_id2nrf_profile.count(profile_id) > 0) {
//if not, update to the list
Logger::nrf_app().info("Update a NF profile to the list (profile ID %s)",
......@@ -304,12 +252,10 @@ void nrf_app::find_nf_profiles(
const nf_type_t &nf_type,
std::vector<std::shared_ptr<nrf_profile>> &profiles) const {
for (auto profile : instance_id2nrf_profile) {
//std::string type = profile.second.get()->get_nf_type();
if (profile.second.get()->get_nf_type() == nf_type) {
profiles.push_back(profile.second);
}
}
//return true;
}
//------------------------------------------------------------------------------
......@@ -329,13 +275,13 @@ bool nrf_app::is_profile_exist(const std::string &profile_id) const {
//------------------------------------------------------------------------------
bool nrf_app::remove_nf_profile(std::shared_ptr<nrf_profile> &snp) {
//TODO
//TODO
return true;
}
//------------------------------------------------------------------------------
bool nrf_app::remove_nf_profile(std::string &profile_id) {
//TODO
//TODO
return true;
}
......@@ -48,14 +48,38 @@ class nrf_app {
nrf_app(nrf_app const&) = delete;
void operator=(nrf_app const&) = delete;
/*
* Handle a Register NF Instance request
* @param [const std::string &] nf_instance_id: Instance ID
* @param [const oai::nrf::model::NFProfile &] nf_profile: NF profile
* @param [int &] http_code: HTTP code used to return to the consumer
* @param [const uint8_t] http_version: HTTP version
* @return void
*/
void handle_register_nf_instance(const std::string &nf_instance_id,
const oai::nrf::model::NFProfile &nf_profile,
int &http_code, const uint8_t http_version);
/*
* Handle a Get NF Instance Information
* @param [const std::string &] nf_type: NF's type
* @param [const uint32_t &] limit_item: Maximum number of items returned
* @param [int &] http_code: HTTP code used to return to the consumer
* @param [const uint8_t] http_version: HTTP version
* @return void
*/
void handle_get_nf_instances(const std::string &nf_type,
const uint32_t limit_item, int &http_code,
const uint32_t &limit_item, int &http_code,
const uint8_t http_version);
/*
* Handle a Update NF Instance request
* @param [const std::string &] nf_instance_id: Instance ID
* @param [const std::vector<PatchItem> &] patchItem: List of modifications need to be applied
* @param [int &] http_code: HTTP code used to return to the consumer
* @param [const uint8_t] http_version: HTTP version
* @return void
*/
void handle_update_nf_instance(const std::string &nf_instance_id,
const std::vector<PatchItem> &patchItem,
int &http_code, const uint8_t http_version);
......@@ -93,11 +117,23 @@ class nrf_app {
bool find_nf_profile(const std::string &profile_id,
std::shared_ptr<nrf_profile> &p) const;
/*
* Find a list of nf profiles with a type
* @param [const nf_type_t &] nf_type: Type of NF profile
* @param [std::vector<std::shared_ptr<nrf_profile>> &] profiles: Store list of corresponding profiles
* @return shared pointer to the profile if found
*/
void find_nf_profiles(
const nf_type_t &nf_type,
std::vector<std::shared_ptr<nrf_profile>> &profiles) const;
/*
* Check if a profile with an ID exist
* @param [const std::string &] profile_id: Profile ID
* @return true if profile exist, otherwise, return false
*/
bool is_profile_exist(const std::string &profile_id) const;
/*
* Remove a nf profile from the list
* @param [std::shared_ptr<nrf_profile> &] snp: profile to be removed
......
......@@ -29,6 +29,7 @@
#include "nrf_profile.hpp"
#include "logger.hpp"
#include "api_conversions.hpp"
using namespace std;
using namespace oai::nrf::app;
......@@ -181,6 +182,59 @@ void nrf_profile::display() {
}
}
bool nrf_profile::replace_profile_info(const std::string &path,
const std::string &value) {
Logger::nrf_app().debug("Replace member %s with new value %s", path.c_str(),
value.c_str());
if (path.compare("nfInstanceName") == 0) {
nf_instance_name = value;
return true;
}
if (path.compare("nfStatus") == 0) {
nf_status = value;
return true;
}
if (path.compare("nfStatus") == 0) {
nf_status = value;
return true;
}
if (path.compare("nfType") == 0) {
nf_type = api_conv::string_to_nf_type(value);
return true;
}
if (path.compare("heartBeatTimer") == 0) {
try {
heartBeat_timer = std::stoi(value);
return true;
} catch (const std::exception &err) {
return false;
}
}
if (path.compare("priority") == 0) {
try {
priority = (uint16_t) std::stoi(value);
return true;
} catch (const std::exception &err) {
return false;
}
}
if (path.compare("capacity") == 0) {
try {
capacity = (uint16_t) std::stoi(value);
return true;
} catch (const std::exception &err) {
return false;
}
}
Logger::nrf_app().debug("Member (%s) not found!", path.c_str());
return false;
}
//------------------------------------------------------------------------------
void amf_profile::add_amf_info(const amf_info_t &info) {
amf_info = info;
......@@ -208,3 +262,10 @@ void amf_profile::display() {
}
}
bool amf_profile::replace_profile_info(const std::string &path,
const std::string &value) {
nrf_profile::replace_profile_info(path, value);
//TODO with AMF part
}
......@@ -62,7 +62,8 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
nf_status = "";
}
nrf_profile(const nf_type_t type)
:nf_type(type),
:
nf_type(type),
heartBeat_timer(0),
snssais(),
ipv4_addresses(),
......@@ -80,7 +81,7 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
ipv4_addresses(),
priority(0),
capacity(0),
nf_type(NF_TYPE_UNKNOWN){
nf_type(NF_TYPE_UNKNOWN) {
nf_instance_name = "";
nf_status = "";
}
......@@ -268,6 +269,14 @@ class nrf_profile : public std::enable_shared_from_this<nrf_profile> {
*/
void display();
/*
* Update a new value for a member of NF profile
* @param [const std::string &] path: member name
* @param [const std::string &] value: new value
* @return void
*/
bool replace_profile_info(const std::string &path, const std::string &value);
protected:
//From NFProfile (Section 6.1.6.2.2@3GPP TS 29.510 V16.0.0 (2019-06))
std::string nf_instance_id;
......@@ -377,8 +386,22 @@ class amf_profile : public nrf_profile {
* @return void
*/
void get_amf_info(amf_info_t &infos) const;
/*
* Print related-information for an AMF profile
* @param void
* @return void:
*/
void display();
/*
* Update a new value for a member of AMF profile
* @param [const std::string &] path: member name
* @param [const std::string &] value: new value
* @return void
*/
bool replace_profile_info(const std::string &path, const std::string &value);
private:
amf_info_t amf_info;
};
......
......@@ -2,4 +2,5 @@ curl -X PUT -H "Content-Type: application/json" -d @amf_registration.json http:/
curl -X GET "http://192.168.1.23/nnrf-nfm/v1/nf-instances?nf-type="serviceId1"&limit=100"
curl -X PATCH -H "Content-Type: application/json" http://192.168.1.88/nnrf-nfm/v1/nf-instances/343a924e-6494-4927-860b-d45692c95c2d -d '[{"op":"replace","path":"...", "from":"", "value": "value" }]'
curl -X PATCH -H "Content-Type: application/json" http://192.168.1.88/nnrf-nfm/v1/nf-instances/343a924e-6494-4927-860b-d45692c95c2d -d '[{"op":"replace","path":"/nfInstanceName", "value": "NEW NAME"}]'
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment