public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            CopyStatus copyStatus = CopyStatus.Success;


            foreach (var region in azureRegions)
            {
                ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                         .SetBasePath(Directory.GetCurrentDirectory())
                                                         .AddEnvironmentVariables()
                                                         .Build(),
                                                         region
                                                         );

                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region);

                try
                {
                    var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName);

                    // Access to container
                    ListContainerSasInput input = new ListContainerSasInput()
                    {
                        Permissions = AssetContainerPermission.ReadWrite,
                        ExpiryTime  = DateTime.Now.AddHours(6).ToUniversalTime()
                    };

                    var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime);

                    string uploadSasUrl             = responseListSas.AssetContainerSasUrls.First();
                    var    sasUri                   = new Uri(uploadSasUrl);
                    var    destinationBlobContainer = new CloudBlobContainer(sasUri);

                    List <IListBlobItem>  blobsresult       = new List <IListBlobItem>();
                    BlobContinuationToken continuationToken = null;
                    do
                    {
                        var responseList = await destinationBlobContainer.ListBlobsSegmentedAsync(null, true, BlobListingDetails.Metadata, null, continuationToken, null, null);

                        continuationToken = responseList.ContinuationToken;
                        blobsresult.AddRange(responseList.Results);
                    }while (continuationToken != null);

                    foreach (var dest in blobsresult)
                    {
                        var destBlob = dest as CloudBlob;
                        await destBlob.FetchAttributesAsync();

                        if (destBlob.CopyState.Status == CopyStatus.Aborted || destBlob.CopyState.Status == CopyStatus.Failed)

                        {
                            // Log the copy status description for diagnostics and restart copy
                            await destBlob.StartCopyAsync(destBlob.CopyState.Source);

                            copyStatus = CopyStatus.Pending;
                        }

                        else if (destBlob.CopyState.Status == CopyStatus.Pending)
                        {
                            // We need to continue waiting for this pending copy
                            // However, let us log copy state for diagnostics
                            copyStatus = CopyStatus.Pending;
                        }

                        // else we completed this pending copy
                    }
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }
            }

            var response = new JObject
            {
                { "success", true },
                { "copyStatus", copyStatus.ToString() },
                { "isRunning", (copyStatus == CopyStatus.Pending) },
                { "isSuccessful", (copyStatus == CopyStatus.Success) },

                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response
                       ));
        }
Example #2
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var generalOutputInfos = new List <GeneralOutputInfo>();

            var liveEventName = (string)data.liveEventName;

            if (liveEventName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON"));
            }

            // default settings
            var eventInfoFromCosmos = new LiveEventSettingsInfo
            {
                LiveEventName = liveEventName
            };

            // Load config from Cosmos
            try
            {
                var setting = await CosmosHelpers.ReadSettingsDocument(liveEventName);

                eventInfoFromCosmos = setting ?? eventInfoFromCosmos;

                if (setting == null)
                {
                    log.LogWarning("Settings not read from Cosmos.");
                }
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            // init default
            var deleteAsset = (data.deleteAsset != null) ? (bool)data.deleteAsset : true;

            var uniquenessAssets = Guid.NewGuid().ToString().Substring(0, 13);

            string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13);

            var manifestName = liveEventName.ToLower();

            if (data.archiveWindowLength != null)
            {
                eventInfoFromCosmos.ArchiveWindowLength = (int)data.archiveWindowLength;
            }

            var cencKey = new StreamingLocatorContentKey();
            var cbcsKey = new StreamingLocatorContentKey();

            if (!deleteAsset) // we need to regenerate the keys if the user wants to keep the asset as keys cannot be reused for more than one asset
            {
                try
                {
                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             null);

                    MediaServicesHelpers.LogInformation(log, "Irdeto call...");

                    cencKey = await IrdetoHelpers.GenerateAndRegisterCENCKeyToIrdeto(liveEventName, config);

                    cbcsKey = await IrdetoHelpers.GenerateAndRegisterCBCSKeyToIrdeto(liveEventName, config);

                    MediaServicesHelpers.LogInformation(log, "Irdeto call done.");
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex, "Irdeto response error"));
                }
            }

            var clientTasks = new List <Task <LiveEventEntry> >();

            // list of locators guid for the new locators
            var locatorGuids = new List <Guid>();

            for (int i = 0; i < 10; i++)
            {
                locatorGuids.Add(Guid.NewGuid());
            }

            foreach (var region in azureRegions)
            {
                var task = Task <LiveEventEntry> .Run(async() =>
                {
                    Asset asset           = null;
                    LiveEvent liveEvent   = null;
                    LiveOutput liveOutput = null;

                    bool reuseKeys                = false;
                    string storageAccountName     = null;
                    var streamingLocatorsPolicies = new Dictionary <string, string>(); // locator name, policy name


                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             region
                                                             );

                    MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                    MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                    var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);
                    // Set the polling interval for long running operations to 2 seconds.
                    // The default value is 30 seconds for the .NET client SDK
                    client.LongRunningOperationRetryTimeout = 2;

                    // let's check that the channel exists
                    liveEvent = await client.LiveEvents.GetAsync(config.ResourceGroup, config.AccountName, liveEventName);
                    if (liveEvent == null)
                    {
                        throw new Exception("Error : live event does not exist !");
                    }

                    if (liveEvent.ResourceState != LiveEventResourceState.Running && liveEvent.ResourceState != LiveEventResourceState.Stopped)
                    {
                        throw new Exception("Error : live event should be in Running or Stopped state !");
                    }

                    // get live output(s) - it should be one
                    var myLiveOutputs = client.LiveOutputs.List(config.ResourceGroup, config.AccountName, liveEventName);

                    // get the names of the streaming policies. If not possible, recreate it
                    if (myLiveOutputs.FirstOrDefault() != null)
                    {
                        asset = client.Assets.Get(config.ResourceGroup, config.AccountName,
                                                  myLiveOutputs.First().AssetName);

                        var streamingLocatorsNames = client.Assets.ListStreamingLocators(config.ResourceGroup, config.AccountName, asset.Name).StreamingLocators.Select(l => l.Name);
                        foreach (var locatorName in streamingLocatorsNames)
                        {
                            var locator =
                                client.StreamingLocators.Get(config.ResourceGroup, config.AccountName, locatorName);
                            if (locator != null)
                            {
                                streamingLocatorsPolicies.Add(locatorName, locator.StreamingPolicyName);
                                if (locator.StreamingPolicyName != PredefinedStreamingPolicy.ClearStreamingOnly) // let's backup the keys to reuse them
                                {
                                    if (deleteAsset)                                                             // we reuse the keys. Only possible if the previous asset is deleted
                                    {
                                        reuseKeys = true;
                                        var keys  = client.StreamingLocators.ListContentKeys(config.ResourceGroup, config.AccountName, locatorName).ContentKeys;
                                        cencKey   = keys.Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCenc).FirstOrDefault();
                                        cbcsKey   = keys.Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCbcs).FirstOrDefault();
                                    }
                                }
                            }
                        }

                        if (streamingLocatorsPolicies.Count == 0) // no way to get the streaming policy, let's read Cosmos or create a new one
                        {
                            MediaServicesHelpers.LogInformation(log, "Trying to read streaming policy from Cosmos.", region);
                            string streamingPolicyName = null;
                            // Load streaming policy info from Cosmos
                            try
                            {
                                var info = await CosmosHelpers.ReadStreamingPolicyDocument(new StreamingPolicyInfo(false)
                                {
                                    AMSAccountName = config.AccountName
                                });

                                if (info == null)
                                {
                                    log.LogWarning("Streaming policy not read from Cosmos.");
                                }
                                else
                                {
                                    streamingPolicyName = info.StreamingPolicyName;
                                }
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Error reading Cosmos DB", ex);
                            }


                            // STREAMING POLICY CREATION
                            if (streamingPolicyName == null) // not found in Cosmos let's create a new one
                            {
                                StreamingPolicy streamingPolicy;
                                MediaServicesHelpers.LogInformation(log, "Creating streaming policy.", region);
                                try
                                {
                                    streamingPolicy = await IrdetoHelpers.CreateStreamingPolicyIrdeto(config, client, uniquenessPolicyName);
                                    streamingLocatorsPolicies.Add("", streamingPolicy.Name);
                                }
                                catch (Exception ex)
                                {
                                    throw new Exception("Streaming policy creation error", ex);
                                }

                                try
                                {
                                    if (!await CosmosHelpers.CreateOrUpdatePolicyDocument(new StreamingPolicyInfo(false)
                                    {
                                        AMSAccountName = config.AccountName,
                                        StreamingPolicyName = streamingPolicy.Name
                                    }))
                                    {
                                        log.LogWarning("Cosmos access not configured or error.");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    throw new Exception("Streaming policy write error to Cosmos", ex);
                                }
                            }
                            else
                            {
                                streamingLocatorsPolicies.Add("", streamingPolicyName);
                            }
                        }
                    }

                    // let's purge all live output for now
                    foreach (var p in myLiveOutputs)
                    {
                        var assetName = p.AssetName;

                        var thisAsset = client.Assets.Get(config.ResourceGroup, config.AccountName, p.AssetName);
                        if (thisAsset != null)
                        {
                            storageAccountName = thisAsset.StorageAccountName; // let's backup storage account name to create the new asset here
                        }
                        MediaServicesHelpers.LogInformation(log, "deleting live output : " + p.Name, region);
                        await client.LiveOutputs.DeleteAsync(config.ResourceGroup, config.AccountName, liveEvent.Name, p.Name);
                        if (deleteAsset)
                        {
                            MediaServicesHelpers.LogInformation(log, "deleting asset : " + assetName, region);
                            await client.Assets.DeleteAsync(config.ResourceGroup, config.AccountName, assetName);
                        }
                    }

                    if (liveEvent.ResourceState == LiveEventResourceState.Running)
                    {
                        MediaServicesHelpers.LogInformation(log, "reseting live event : " + liveEvent.Name, region);
                        await client.LiveEvents.ResetAsync(config.ResourceGroup, config.AccountName, liveEvent.Name);
                    }
                    else
                    {
                        MediaServicesHelpers.LogInformation(log, "Skipping the reset of live event " + liveEvent.Name + " as it is stopped.", region);
                    }

                    // LIVE OUTPUT CREATION
                    MediaServicesHelpers.LogInformation(log, "Live output creation...", region);

                    try
                    {
                        MediaServicesHelpers.LogInformation(log, "Asset creation...", region);
                        asset = await client.Assets.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName,
                                                                        "asset-" + uniquenessAssets, new Asset(storageAccountName: storageAccountName));

                        Hls hlsParam = null;
                        liveOutput   = new LiveOutput(asset.Name, TimeSpan.FromMinutes(eventInfoFromCosmos.ArchiveWindowLength),
                                                      null, "output-" + uniquenessAssets, null, null, manifestName,
                                                      hlsParam);

                        MediaServicesHelpers.LogInformation(log, "create live output...", region);
                        await client.LiveOutputs.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveOutput.Name, liveOutput);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("live output creation error", ex);
                    }

                    try
                    {
                        // streaming locator(s) creation
                        MediaServicesHelpers.LogInformation(log, "Locator creation...", region);
                        int i = 0;
                        foreach (var entryLocPol in streamingLocatorsPolicies)
                        {
                            StreamingLocator locator = null;
                            var streamingLocatorGuid = locatorGuids[i]; // same locator for the two ouputs if 2 live event namle created
                            var uniquenessLocator    = streamingLocatorGuid.ToString().Substring(0, 13);
                            var streamingLocatorName = "locator-" + uniquenessLocator;

                            if (entryLocPol.Value == PredefinedStreamingPolicy.ClearStreamingOnly)
                            {
                                locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid);
                            }
                            else // DRM content
                            {
                                MediaServicesHelpers.LogInformation(log, "creating DRM locator : " + streamingLocatorName, region);

                                if (!reuseKeys)
                                {
                                    MediaServicesHelpers.LogInformation(log, "using new keys.", region);

                                    locator = await IrdetoHelpers.SetupDRMAndCreateLocatorWithNewKeys(
                                        config, entryLocPol.Value, streamingLocatorName, client, asset, cencKey, cbcsKey, streamingLocatorGuid);
                                }
                                else // no need to create new keys, let's use the exiting one
                                {
                                    MediaServicesHelpers.LogInformation(log, "using existing keys.", region);

                                    locator = await IrdetoHelpers.SetupDRMAndCreateLocatorWithExistingKeys(
                                        config, entryLocPol.Value, streamingLocatorName, client, asset, cencKey, cbcsKey, streamingLocatorGuid);
                                }
                            }
                            MediaServicesHelpers.LogInformation(log, "locator : " + streamingLocatorName, region);
                            i++;
                        }

                        await client.Assets.UpdateAsync(config.ResourceGroup, config.AccountName, asset.Name, asset);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("locator creation error", ex);
                    }

                    var generalOutputInfo =
                        GenerateInfoHelpers.GenerateOutputInformation(config, client, new List <LiveEvent> {
                        liveEvent
                    });

                    if (!await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(generalOutputInfo.LiveEvents[0]))
                    {
                        MediaServicesHelpers.LogWarning(log, "Cosmos access not configured.", region);
                    }

                    return(generalOutputInfo.LiveEvents[0]);
                });

                clientTasks.Add(task);
            }

            try
            {
                Task.WaitAll(clientTasks.ToArray());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new GeneralOutputInfo {
                Success = true, LiveEvents = clientTasks.Select(i => i.Result).ToList()
            }, Formatting.Indented)
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var           prefixAssetName = (string)data.prefixAssetName ?? "asset-";
            var           assetName       = (string)data.assetName ?? prefixAssetName + Guid.NewGuid().ToString().Substring(0, 13);
            List <string> containers      = new List <string>();
            List <string> containerPaths  = new List <string>();

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }


            foreach (var region in azureRegions)
            {
                ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                         .SetBasePath(Directory.GetCurrentDirectory())
                                                         .AddEnvironmentVariables()
                                                         .Build(),
                                                         region
                                                         );

                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region);

                string storageName = (data.baseStorageName != null) ? (string)data.baseStorageName + config.AzureRegionCode : null;

                Asset asset = new Asset()
                {
                    StorageAccountName = storageName, AlternateId = data.alternateId, Description = data.description
                };

                try
                {
                    asset = client.Assets.CreateOrUpdate(config.ResourceGroup, config.AccountName, assetName, asset);
                    asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName);

                    // Access to container
                    ListContainerSasInput input = new ListContainerSasInput()
                    {
                        Permissions = AssetContainerPermission.Read,
                        ExpiryTime  = DateTime.Now.AddMinutes(5).ToUniversalTime()
                    };

                    var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime);

                    string uploadSasUrl = responseListSas.AssetContainerSasUrls.First();
                    var    sasUri       = new Uri(uploadSasUrl);
                    var    container    = new CloudBlobContainer(sasUri);

                    containerPaths.Add(container.Uri.ToString());
                    containers.Add(asset.Container);
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }
            }

            var response = new JObject
            {
                { "success", true },
                { "assetName", assetName },
                { "containerPath", new JArray(containerPaths) },
                { "container", new JArray(containers) },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var generalOutputInfos = new List <GeneralOutputInfo>();

            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }

            var fileName = (string)data.fileName;
            ManifestGenerated smildata = null;

            VodSemaphore semaphore = null;

            if (data.semaphore != null)
            {
                semaphore = VodSemaphore.FromJson((string)data.semaphore);
            }

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }


            foreach (var region in azureRegions)
            {
                ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                         .SetBasePath(Directory.GetCurrentDirectory())
                                                         .AddEnvironmentVariables()
                                                         .Build(),
                                                         region
                                                         );

                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region);
                var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName);

                if (asset == null)
                {
                    throw new Exception($"Asset {asset}  does not exist.");
                }

                // Access to container
                ListContainerSasInput input = new ListContainerSasInput()
                {
                    Permissions = AssetContainerPermission.ReadWriteDelete,
                    ExpiryTime  = DateTime.Now.AddHours(2).ToUniversalTime()
                };

                var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime);

                string uploadSasUrl = responseListSas.AssetContainerSasUrls.First();

                var sasUri    = new Uri(uploadSasUrl);
                var container = new CloudBlobContainer(sasUri);

                // Manifest generate
                smildata = (semaphore == null) ? await ManifestHelpers.LoadAndUpdateManifestTemplate(asset, container, execContext, fileName)
                                                : await ManifestHelpers.LoadAndUpdateManifestTemplateUsingSemaphore(semaphore, execContext, fileName);

                // if not file name passed, then we use the one generated based on mp4 files names
                if (fileName == null)
                {
                    fileName = smildata.FileName;
                }

                var blob = container.GetBlockBlobReference(fileName);

                using (Stream s = ManifestHelpers.GenerateStreamFromString(smildata.Content))
                {
                    await blob.UploadFromStreamAsync(s);
                }
            }

            var response = new JObject
            {
                { "success", true },
                { "fileName", fileName },
                { "manifestContent", smildata.Content },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response
                       ));
        }
Example #5
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }


            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }


            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            // semaphore file (json structure)
            VodSemaphore semaphore = null;

            if (data.semaphore != null)
            {
                semaphore = VodSemaphore.FromJson((string)data.semaphore);
            }


            // init default
            var    streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created
            var    uniquenessLocator    = streamingLocatorGuid.ToString().Substring(0, 13);
            var    streamingLocatorName = "locator-" + uniquenessLocator;
            string locatorPath          = string.Empty;

            string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13);

            // Default content id and semaphare value
            string irdetoContentId = null;

            if (semaphore != null && semaphore.DrmContentId != null) // semaphore data has higher priority
            {
                irdetoContentId = semaphore.DrmContentId;
            }
            else if (data.defaultIrdetoContentId != null)
            {
                irdetoContentId = (string)data.defaultIrdetoContentId;
            }

            var clientTasks = new List <Task <AssetEntry> >();

            foreach (var region in azureRegions)
            {
                var task = Task <AssetEntry> .Run(async() =>
                {
                    Asset asset = null;

                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             region
                                                             );

                    MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                    MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                    var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);
                    // Set the polling interval for long running operations to 2 seconds.
                    // The default value is 30 seconds for the .NET client SDK
                    client.LongRunningOperationRetryTimeout = 2;

                    // let's get the asset
                    try
                    {
                        MediaServicesHelpers.LogInformation(log, "Getting asset.", region);
                        asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, assetName);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Error when retreving asset by name", ex);
                    }


                    // Locator creation
                    try
                    {
                        StreamingLocator locator = null;
                        locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid);

                        MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Error when creating the locator", ex);
                    }


                    // let's build info for the live event and output

                    AssetEntry assetEntry = await GenerateInfoHelpers.GenerateAssetInformation(config, client, asset, semaphore, irdetoContentId, region);

                    var locatorPath2 = assetEntry.StreamingLocators.Where(l => l.StreamingLocatorName == streamingLocatorName).First().Urls.Where(u => u.Protocol == OutputProtocol.SmoothStreaming.ToString()).First().Url;
                    var uriloc       = new Uri(locatorPath2);
                    locatorPath      = uriloc.Scheme + "://" + uriloc.Host + "/" + uriloc.Segments[1];

                    if (!await CosmosHelpers.CreateOrUpdateAssetDocument(assetEntry))
                    {
                        log.LogWarning("Cosmos access not configured.");
                    }

                    return(assetEntry);
                });

                clientTasks.Add(task);
            }

            try
            {
                Task.WaitAll(clientTasks.ToArray());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new VodAssetInfoSimple {
                CreatedLocatorName = streamingLocatorName, CreatedLocatorPath = locatorPath, Success = true, Asset = clientTasks.Select(i => i.Result).First()
            }, Formatting.Indented)
                       ));
        }
Example #6
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            ConfigWrapper config             = null;
            var           generalOutputInfos = new List <GeneralOutputInfo>();

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            foreach (var region in azureRegions)
            {
                try
                {
                    config = new ConfigWrapper(new ConfigurationBuilder()
                                               .SetBasePath(Directory.GetCurrentDirectory())
                                               .AddEnvironmentVariables()
                                               .Build(),
                                               region
                                               );
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }
                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                var liveEvents = client.LiveEvents.List(config.ResourceGroup, config.AccountName);

                // object to store the output of the function
                var generalOutputInfo = new GeneralOutputInfo();

                // let's list live events
                try
                {
                    generalOutputInfo = GenerateInfoHelpers.GenerateOutputInformation(config, client, liveEvents.ToList());
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }

                try
                {
                    var success = new List <bool>();
                    foreach (var le in generalOutputInfo.LiveEvents)
                    {
                        success.Add(await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(le));
                    }

                    if (success.Any(b => b == false))
                    {
                        log.LogWarning("Cosmos access not configured.");
                    }
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }

                generalOutputInfos.Add(generalOutputInfo);
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new GeneralOutputInfo {
                Success = true, LiveEvents = generalOutputInfos.SelectMany(i => i.LiveEvents).ToList()
            }, Formatting.Indented)
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }


            var liveEventName = (string)data.liveEventName;

            if (liveEventName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON"));
            }

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            // init default
            var uniquenessAssets = Guid.NewGuid().ToString().Substring(0, 13);

            var streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created
            var uniquenessLocator    = streamingLocatorGuid.ToString().Substring(0, 13);
            var streamingLocatorName = "locator-" + uniquenessLocator;

            var manifestName = liveEventName.ToLower();

            var clientTasks = new List <Task <LiveEventEntry> >();

            foreach (var region in azureRegions)
            {
                var task = Task <LiveEventEntry> .Run(async() =>
                {
                    Asset asset           = null;
                    LiveOutput liveOutput = null;

                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             region
                                                             );

                    MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                    MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                    var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);
                    // Set the polling interval for long running operations to 2 seconds.
                    // The default value is 30 seconds for the .NET client SDK
                    client.LongRunningOperationRetryTimeout = 2;

                    // let's check that the channel exists
                    var liveEvent = await client.LiveEvents.GetAsync(config.ResourceGroup, config.AccountName, liveEventName);
                    if (liveEvent == null)
                    {
                        throw new Exception($"Live event {liveEventName} does not exist.");
                    }

                    var outputs =
                        await client.LiveOutputs.ListAsync(config.ResourceGroup, config.AccountName, liveEventName);

                    if (outputs.FirstOrDefault() != null)
                    {
                        liveOutput = outputs.FirstOrDefault();
                        asset      = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName,
                                                                  liveOutput.AssetName);
                    }

                    if (asset == null)
                    {
                        throw new Exception("Error - asset not found");
                    }

                    try
                    {
                        // streaming locator creation
                        MediaServicesHelpers.LogInformation(log, "Locator creation...", region);

                        var locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid);

                        MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region);

                        if (liveOutput != null)
                        {
                            await client.Assets.UpdateAsync(config.ResourceGroup, config.AccountName, asset.Name, asset);
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("locator creation error", ex);
                    }

                    // object to store the output of the function
                    var generalOutputInfo = new GeneralOutputInfo();

                    // let's build info for the live event and output

                    generalOutputInfo =
                        GenerateInfoHelpers.GenerateOutputInformation(config, client, new List <LiveEvent> {
                        liveEvent
                    });

                    if (!await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(generalOutputInfo.LiveEvents[0]))
                    {
                        MediaServicesHelpers.LogWarning(log, "Cosmos access not configured.", region);
                    }

                    return(generalOutputInfo.LiveEvents[0]);
                });

                clientTasks.Add(task);
            }

            try
            {
                Task.WaitAll(clientTasks.ToArray());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new GeneralOutputInfo {
                Success = true, LiveEvents = clientTasks.Select(i => i.Result).ToList()
            }, Formatting.Indented)
                       ));
        }
Example #8
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var generalOutputInfos = new List <GeneralOutputInfo>();

            var liveEventName = (string)data.liveEventName;

            if (liveEventName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON"));
            }

            var deleteAsset = true;

            if (data.deleteAsset != null)
            {
                deleteAsset = (bool)data.deleteAsset;
            }

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            var clientTasks = new List <Task>();

            foreach (var region in azureRegions)
            {
                Task task = Task.Run(async() =>
                {
                    Task LiveOutputsDeleteTask = null;
                    Task LiveEventStopTask     = null;

                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             region
                                                             );

                    MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                    MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                    var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);
                    // Set the polling interval for long running operations to 2 seconds.
                    // The default value is 30 seconds for the .NET client SDK
                    client.LongRunningOperationRetryTimeout = 2;

                    MediaServicesHelpers.LogInformation(log, "live event : " + liveEventName, region);
                    var liveEvent = client.LiveEvents.Get(config.ResourceGroup, config.AccountName, liveEventName);

                    if (liveEvent == null)
                    {
                        throw new Exception($"Live event {liveEventName}  does not exist.");
                    }

                    // let's purge all live output for now
                    var ps = client.LiveOutputs.List(config.ResourceGroup, config.AccountName, liveEventName);
                    foreach (var p in ps)
                    {
                        var assetName = p.AssetName;
                        var asset     = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName);

                        // let's store name of the streaming policy
                        string streamingPolicyName = null;
                        var streamingLocatorsNames = client.Assets.ListStreamingLocators(config.ResourceGroup, config.AccountName, assetName).StreamingLocators.Select(l => l.Name);

                        foreach (var locatorName in streamingLocatorsNames)
                        {
                            if (locatorName != null)
                            {
                                var streamingLocator = await client.StreamingLocators.GetAsync(config.ResourceGroup,
                                                                                               config.AccountName, locatorName);

                                if (streamingLocator != null)
                                {
                                    streamingPolicyName = streamingLocator.StreamingPolicyName;
                                }
                            }
                        }

                        MediaServicesHelpers.LogInformation(log, "deleting live output : " + p.Name, region);
                        LiveOutputsDeleteTask = client.LiveOutputs.DeleteAsync(config.ResourceGroup, config.AccountName, liveEvent.Name, p.Name);

                        if (deleteAsset)
                        {
                            MediaServicesHelpers.LogInformation(log, "deleting asset : " + assetName, region);
                            await client.Assets.DeleteAsync(config.ResourceGroup, config.AccountName, assetName);
                            if (streamingPolicyName != null && streamingPolicyName.StartsWith(liveEventName)
                                ) // let's delete the streaming policy if custom
                            {
                                MediaServicesHelpers.LogInformation(log, "deleting streaming policy : " + streamingPolicyName, region);
                                await client.StreamingPolicies.DeleteAsync(config.ResourceGroup, config.AccountName,
                                                                           streamingPolicyName);
                            }
                        }
                    }

                    if (LiveOutputsDeleteTask != null)
                    {
                        await LiveOutputsDeleteTask;                                   // live output deletion task
                    }
                    if (liveEvent.ResourceState == LiveEventResourceState.Running)
                    {
                        MediaServicesHelpers.LogInformation(log, "stopping live event : " + liveEvent.Name, region);
                        LiveEventStopTask = client.LiveEvents.StopAsync(config.ResourceGroup, config.AccountName, liveEvent.Name);
                    }
                    else if (liveEvent.ResourceState == LiveEventResourceState.Stopping)
                    {
                        var liveevt = liveEvent;
                        while (liveevt.ResourceState == LiveEventResourceState.Stopping)
                        {
                            Thread.Sleep(2000);
                            liveevt = client.LiveEvents.Get(config.ResourceGroup, config.AccountName, liveEvent.Name);
                        }
                    }

                    if (LiveEventStopTask != null)
                    {
                        await LiveEventStopTask;                               // live event stop task
                    }
                    MediaServicesHelpers.LogInformation(log, "deleting live event : " + liveEventName, region);
                    await client.LiveEvents.DeleteAsync(config.ResourceGroup, config.AccountName, liveEventName);

                    if (!await CosmosHelpers.DeleteGeneralInfoDocument(new LiveEventEntry
                    {
                        LiveEventName = liveEventName,
                        AMSAccountName = config.AccountName
                    }))
                    {
                        MediaServicesHelpers.LogWarning(log, "Error when deleting Cosmos document.", region);
                    }
                });

                clientTasks.Add(task);
            }

            try
            {
                Task.WaitAll(clientTasks.ToArray());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var response = new JObject
            {
                { "liveEventName", liveEventName },
                { "success", true },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response.ToString()
                       ));
        }
Example #9
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            AssetEntry assetEntry1 = null;

            if (data.assetMain != null)
            {
                assetEntry1 = ((JObject)data?.assetMain).ToObject <AssetEntry>();
            }

            AssetEntry assetEntry2 = null;

            if (data.assetSub != null)
            {
                assetEntry2 = ((JObject)data?.assetSub).ToObject <AssetEntry>();
            }

            string newHostName = (string)data.cdnHostName;

            if (string.IsNullOrWhiteSpace(newHostName))
            {
                newHostName = null;
            }

            VodResource vodResource = new VodResource()
            {
                Urn          = assetEntry1.Urn,
                ResourceList = new List <ResourceList>(),
                MainAsset    = assetEntry1
            };


            var subtitlesList = new List <Subtitles>();

            if (assetEntry2 != null)
            {
                var locator2      = assetEntry2.StreamingLocators.FirstOrDefault();
                var subtitlesUrl  = locator2?.Urls.Where(p => p.Protocol == "Download");
                var subtitlesSema = assetEntry2?.Semaphore.Files.Where(f => f.CopyToSubAsset);

                var query = from subInfo in subtitlesSema
                            join sub in subtitlesUrl on subInfo.FileName equals(new Uri(sub.Url)).Segments[(new Uri(sub.Url)).Segments.Length - 1]
                            select new Subtitles
                {
                    Url = MediaServicesHelpers.UpdateHostNameIfNeeded(newHostName, sub.Url), TextLanguage = subInfo.TextLanguage, TextTitle = subInfo.TextTitle
                };
                subtitlesList = query.ToList();
            }

            var locator1 = assetEntry1.StreamingLocators.FirstOrDefault();

            var resDashCsf = new ResourceList()
            {
                Url            = MediaServicesHelpers.UpdateHostNameIfNeeded(newHostName, locator1?.Urls.Where(u => u.Protocol == "DashCsf").FirstOrDefault()?.Url),
                Protocol       = "DASH",
                MimeType       = "application/dash+xml",
                VideoCodec     = "H264",
                AudioCodec     = "AAC",
                MediaContainer = "MP4",
                Quality        = "SD",
                Live           = false,
                DrmList        = new List <DrmList>()
                {
                    new DrmList()
                    {
                        Type = "PlayReady", LicenseUrl = locator1?.Drm?.Where(d => d.Type == "PlayReady").FirstOrDefault()?.LicenseUrl
                    },
                    new DrmList()
                    {
                        Type = "Widevine", LicenseUrl = locator1?.Drm?.Where(d => d.Type == "Widevine").FirstOrDefault()?.LicenseUrl
                    }
                },
                SubTitles = subtitlesList
            };

            vodResource.ResourceList.Add(resDashCsf);

            var resHlsTs = new ResourceList()
            {
                Url            = MediaServicesHelpers.UpdateHostNameIfNeeded(newHostName, locator1?.Urls.Where(u => u.Protocol == "HlsTs").FirstOrDefault()?.Url),
                Protocol       = "HLS",
                MimeType       = "application/x-mpegURL",
                VideoCodec     = "H264",
                AudioCodec     = "AAC",
                MediaContainer = "MP4",
                Quality        = "SD",
                Live           = false,
                DrmList        = new List <DrmList>()
                {
                    new DrmList()
                    {
                        Type           = "FairPlay",
                        LicenseUrl     = locator1.Drm.Where(d => d.Type == "FairPlay").FirstOrDefault().LicenseUrl,
                        CertificateUrl = locator1.Drm.Where(d => d.Type == "FairPlay").FirstOrDefault().CertificateUrl
                    },
                },
                SubTitles = subtitlesList
            };

            vodResource.ResourceList.Add(resHlsTs);


            // let's write it to Cosmos
            if (!await CosmosHelpers.CreateOrUpdateVODResourceDocument(vodResource))
            {
                log.LogWarning("Cosmos access not configured.");
            }


            return(new OkObjectResult(
                       JsonConvert.SerializeObject(vodResource, Formatting.Indented)
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }

            var vttContent = (string)data.vttContent;

            if (vttContent == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass vttContent in the input object"));
            }

            var vttFileName = (string)data.vttFileName;

            if (vttFileName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass vttFileName in the input object"));
            }


            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            foreach (var region in azureRegions)
            {
                ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                         .SetBasePath(Directory.GetCurrentDirectory())
                                                         .AddEnvironmentVariables()
                                                         .Build(),
                                                         region
                                                         );

                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region);

                try
                {
                    var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName);

                    // Access to container
                    ListContainerSasInput input = new ListContainerSasInput()
                    {
                        Permissions = AssetContainerPermission.ReadWrite,
                        ExpiryTime  = DateTime.Now.AddHours(6).ToUniversalTime()
                    };

                    var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime);

                    string uploadSasUrl             = responseListSas.AssetContainerSasUrls.First();
                    var    sasUri                   = new Uri(uploadSasUrl);
                    var    destinationBlobContainer = new CloudBlobContainer(sasUri);

                    var destinationBlob = destinationBlobContainer.GetBlockBlobReference(vttFileName);

                    // Base 64 decoding
                    byte[] dataVtt       = Convert.FromBase64String(vttContent);
                    string decodedString = Encoding.UTF8.GetString(dataVtt);

                    // Uploading data
                    await destinationBlob.UploadTextAsync(decodedString);
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }
            }

            var response = new JObject
            {
                { "success", true },
                { "assetName", assetName },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }

            if (data.fileNames == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass fileNames in the input object"));
            }

            var sourceStorageAccountName = (string)data.sourceStorageAccountName;

            if (sourceStorageAccountName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass sourceStorageAccountName in the input object"));
            }

            var sourceStorageAccountKey = (string)data.sourceStorageAccountKey;

            if (sourceStorageAccountKey == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass sourceStorageAccountKey in the input object"));
            }

            var sourceContainer = (string)data.sourceContainer;

            if (sourceContainer == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass sourceContainer in the input object"));
            }

            bool missingBlob = false;

            List <string> containers     = new List <string>();
            List <string> containerPaths = new List <string>();

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            // Setup blob container
            CloudBlobContainer sourceBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(sourceStorageAccountName, sourceStorageAccountKey, (string)data.sourceContainer);

            foreach (var region in azureRegions)
            {
                ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                         .SetBasePath(Directory.GetCurrentDirectory())
                                                         .AddEnvironmentVariables()
                                                         .Build(),
                                                         region
                                                         );

                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region);

                try
                {
                    var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName);

                    // Access to container
                    ListContainerSasInput input = new ListContainerSasInput()
                    {
                        Permissions = AssetContainerPermission.ReadWrite,
                        ExpiryTime  = DateTime.Now.AddHours(6).ToUniversalTime()
                    };

                    var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime);

                    string uploadSasUrl             = responseListSas.AssetContainerSasUrls.First();
                    var    sasUri                   = new Uri(uploadSasUrl);
                    var    destinationBlobContainer = new CloudBlobContainer(sasUri);
                    containers.Add(asset.Container);


                    if (data.fileNames != null)
                    {
                        int indexFile = 1;
                        foreach (var file in data.fileNames)
                        {
                            string fileName = (string)file;

                            CloudBlob sourceBlob = sourceBlobContainer.GetBlockBlobReference(fileName);

                            if (data.wait != null && (bool)data.wait && (indexFile == 1))
                            {
                                for (int i = 1; i <= 3; i++) // let's wait 3 times 5 seconds (15 seconds)
                                {
                                    if (await sourceBlob.ExistsAsync())
                                    {
                                        break;
                                    }

                                    log.LogInformation("Waiting 5 s...");
                                    System.Threading.Thread.Sleep(5 * 1000);
                                    sourceBlob = sourceBlobContainer.GetBlockBlobReference(fileName);
                                }
                            }

                            if (await sourceBlob.ExistsAsync() && sourceBlob.Properties.Length > 0)
                            {
                                if (data.flattenPath != null && (bool)data.flattenPath)
                                {
                                    fileName = Path.GetFileName(fileName);
                                }

                                CloudBlob destinationBlob = destinationBlobContainer.GetBlockBlobReference(fileName);

                                CopyBlobHelpers.CopyBlobAsync(sourceBlob, destinationBlob);
                            }
                            else
                            {
                                missingBlob = true;
                                log.LogWarning("Missing blob :" + fileName);
                            }
                            indexFile++;
                        }
                    }
                    containers.Add(asset.Container);
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }
            }

            var response = new JObject
            {
                { "success", true },
                { "assetName", assetName },
                { "container", new JArray(containers) },
                { "missingBlob", missingBlob },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var generalOutputInfos = new List <GeneralOutputInfo>();

            var liveEventName = (string)data.liveEventName;

            if (liveEventName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON"));
            }

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            var clientTasks = new List <Task <LiveEventEntry> >();

            foreach (var region in azureRegions)
            {
                var task = Task <LiveEventEntry> .Run(async() =>
                {
                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             region
                                                             );

                    MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                    MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                    var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);
                    // Set the polling interval for long running operations to 2 seconds.
                    // The default value is 30 seconds for the .NET client SDK
                    client.LongRunningOperationRetryTimeout = 2;

                    // LIVE EVENT STOP
                    MediaServicesHelpers.LogInformation(log, "Live event stopping...", region);

                    // let's check that the channel exists
                    var liveEvent = await client.LiveEvents.GetAsync(config.ResourceGroup, config.AccountName, liveEventName);
                    if (liveEvent == null)
                    {
                        throw new Exception($"Live event {liveEventName} does not exist.");
                    }

                    if (liveEvent.ResourceState == LiveEventResourceState.Stopped)
                    {
                        throw new Exception($"Live event {liveEventName} already stopped !");
                    }

                    await client.LiveEvents.StopAsync(config.ResourceGroup, config.AccountName, liveEventName);

                    var generalOutputInfo = GenerateInfoHelpers.GenerateOutputInformation(config, client, new List <LiveEvent> {
                        liveEvent
                    });

                    if (!await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(generalOutputInfo.LiveEvents[0]))
                    {
                        MediaServicesHelpers.LogWarning(log, "Cosmos access not configured.", region);
                    }

                    return(generalOutputInfo.LiveEvents[0]);
                });

                clientTasks.Add(task);
            }

            try
            {
                Task.WaitAll(clientTasks.ToArray());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new GeneralOutputInfo {
                Success = true, LiveEvents = clientTasks.Select(i => i.Result).ToList()
            }, Formatting.Indented)
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }

            List <string> fileNames = new List <string>();

            ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                     .SetBasePath(Directory.GetCurrentDirectory())
                                                     .AddEnvironmentVariables()
                                                     .Build(),
                                                     null
                                                     );

            MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, null);

            var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

            // Set the polling interval for long running operations to 2 seconds.
            // The default value is 30 seconds for the .NET client SDK
            client.LongRunningOperationRetryTimeout = 2;

            MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, null);

            Asset asset = new Asset();

            try
            {
                asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, assetName);

                ListContainerSasInput input = new ListContainerSasInput()
                {
                    Permissions = AssetContainerPermission.Read,
                    ExpiryTime  = DateTime.Now.AddHours(2).ToUniversalTime()
                };

                var responseAssetContSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, assetName, input.Permissions, input.ExpiryTime);

                string uploadSasUrl = responseAssetContSas.AssetContainerSasUrls.First();
                Uri    sasUri       = new Uri(uploadSasUrl);
                var    container    = new CloudBlobContainer(sasUri);


                BlobContinuationToken continuationToken = null;
                var blobs = new List <IListBlobItem>();

                do
                {
                    BlobResultSegment segment = await container.ListBlobsSegmentedAsync(null, false, BlobListingDetails.Metadata, null, continuationToken, null, null);

                    blobs.AddRange(segment.Results);

                    foreach (IListBlobItem blob in segment.Results)
                    {
                        if (blob.GetType() == typeof(CloudBlockBlob))
                        {
                            CloudBlockBlob bl = (CloudBlockBlob)blob;
                            fileNames.Add(bl.Name);
                        }
                    }
                    continuationToken = segment.ContinuationToken;
                }while (continuationToken != null);
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var response = new JObject
            {
                { "success", true },
                { "assetName", assetName },
                { "assetId", asset.AssetId },
                { "fileNames", new JArray(fileNames) },
                { "container", asset.Container },
                { "storageAccountName", asset.StorageAccountName },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response
                       ));
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }


            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }


            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            // semaphore file (json structure)
            VodSemaphore semaphore = null;

            if (data.semaphore != null)
            {
                semaphore = VodSemaphore.FromJson((string)data.semaphore);
            }


            // init default
            var streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created
            var uniquenessLocator    = streamingLocatorGuid.ToString().Substring(0, 13);
            var streamingLocatorName = "locator-" + uniquenessLocator;

            string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13);

            // useDRM init
            var useDRM = true;

            if (data.useDRM != null)
            {
                useDRM = (bool)data.useDRM;
            }
            else if (semaphore != null & semaphore.ClearStream != null)
            {
                useDRM = !(bool)semaphore.ClearStream;
            }


            // Default content id and semaphare value
            string irdetoContentId = null;

            if (semaphore != null && semaphore.DrmContentId != null) // semaphore data has higher priority
            {
                irdetoContentId = semaphore.DrmContentId;
            }
            else if (data.defaultIrdetoContentId != null)
            {
                irdetoContentId = (string)data.defaultIrdetoContentId;
            }

            DateTime?startTime = null;
            DateTime?endTime   = null;

            try
            {
                if (semaphore != null && semaphore.StartTime != null)
                {
                    startTime = DateTime.ParseExact(semaphore.StartTime, AssetEntry.DateFormat, System.Globalization.CultureInfo.InvariantCulture);
                }
                if (semaphore != null && semaphore.EndTime != null)
                {
                    endTime = DateTime.ParseExact(semaphore.EndTime, AssetEntry.DateFormat, System.Globalization.CultureInfo.InvariantCulture);
                }
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }


            var cencKey = new StreamingLocatorContentKey();
            var cbcsKey = new StreamingLocatorContentKey();

            if (useDRM)
            {
                try
                {
                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             null);

                    MediaServicesHelpers.LogInformation(log, "Irdeto call...");

                    cencKey = await IrdetoHelpers.GenerateAndRegisterCENCKeyToIrdeto(irdetoContentId, config);

                    cbcsKey = await IrdetoHelpers.GenerateAndRegisterCBCSKeyToIrdeto(irdetoContentId, config);

                    MediaServicesHelpers.LogInformation(log, "Irdeto call done.");
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex, "Irdeto response error"));
                }
            }

            var clientTasks = new List <Task <AssetEntry> >();

            foreach (var region in azureRegions)
            {
                var task = Task <AssetEntry> .Run(async() =>
                {
                    Asset asset = null;
                    StreamingPolicy streamingPolicy = null;

                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             region
                                                             );

                    MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                    MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                    var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);
                    // Set the polling interval for long running operations to 2 seconds.
                    // The default value is 30 seconds for the .NET client SDK
                    client.LongRunningOperationRetryTimeout = 2;

                    if (useDRM)
                    {
                        MediaServicesHelpers.LogInformation(log, "Trying to read streaming policy from Cosmos.", region);
                        string streamingPolicyName = null;
                        // Load streaming policy info from Cosmos
                        try
                        {
                            var info = await CosmosHelpers.ReadStreamingPolicyDocument(new StreamingPolicyInfo(true)
                            {
                                AMSAccountName = config.AccountName
                            });

                            if (info == null)
                            {
                                log.LogWarning("Streaming policy not read from Cosmos.");
                            }
                            else
                            {
                                streamingPolicyName = info.StreamingPolicyName;
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("Error reading Cosmos DB", ex);
                        }


                        // STREAMING POLICY CREATION
                        if (streamingPolicyName == null) // not found in Cosmos let's create a new one
                        {
                            MediaServicesHelpers.LogInformation(log, "Creating streaming policy.", region);
                            try
                            {
                                streamingPolicy = await IrdetoHelpers.CreateStreamingPolicyIrdeto(config, client, uniquenessPolicyName);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Streaming policy creation error", ex);
                            }

                            try
                            {
                                if (!await CosmosHelpers.CreateOrUpdatePolicyDocument(new StreamingPolicyInfo(true)
                                {
                                    AMSAccountName = config.AccountName,
                                    StreamingPolicyName = streamingPolicy.Name
                                }))
                                {
                                    log.LogWarning("Cosmos access not configured or error.");
                                }
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Streaming policy write error to Cosmos", ex);
                            }
                        }
                        else
                        {
                            MediaServicesHelpers.LogInformation(log, "Getting streaming policy in AMS.", region);
                            try
                            {
                                streamingPolicy = await client.StreamingPolicies.GetAsync(config.ResourceGroup, config.AccountName, streamingPolicyName);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Error when getting streaming policy " + streamingPolicy, ex);
                            }
                        }
                    }


                    // let's get the asset
                    try
                    {
                        MediaServicesHelpers.LogInformation(log, "Getting asset.", region);
                        asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, assetName);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Error when retreving asset by name", ex);
                    }


                    // Locator creation
                    try
                    {
                        StreamingLocator locator = null;
                        if (useDRM)
                        {
                            locator = await IrdetoHelpers.SetupDRMAndCreateLocatorWithNewKeys(config, streamingPolicy.Name,
                                                                                              streamingLocatorName, client, asset, cencKey, cbcsKey, streamingLocatorGuid, irdetoContentId, startTime, endTime);
                        }
                        else // no DRM
                        {
                            locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid, startTime, endTime);
                        }

                        MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Error when creating the locator", ex);
                    }


                    // let's build info for the live event and output

                    AssetEntry assetEntry = await GenerateInfoHelpers.GenerateAssetInformation(config, client, asset, semaphore, irdetoContentId, region);

                    if (!await CosmosHelpers.CreateOrUpdateAssetDocument(assetEntry))
                    {
                        log.LogWarning("Cosmos access not configured.");
                    }

                    return(assetEntry);
                });

                clientTasks.Add(task);
            }

            try
            {
                Task.WaitAll(clientTasks.ToArray());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new VodAssetInfo {
                Success = true, Assets = clientTasks.Select(i => i.Result).ToList()
            }, Formatting.Indented)
                       ));
        }
Example #15
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }


            var generalOutputInfos = new List <GeneralOutputInfo>();

            var liveEventName = (string)data.liveEventName;

            if (liveEventName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON"));
            }

            // default settings
            var eventInfoFromCosmos = new LiveEventSettingsInfo()
            {
                LiveEventName = liveEventName
            };

            // Load config from Cosmos
            try
            {
                var setting = await CosmosHelpers.ReadSettingsDocument(liveEventName);

                eventInfoFromCosmos = setting ?? eventInfoFromCosmos;

                if (setting == null)
                {
                    log.LogWarning("Settings not read from Cosmos.");
                }
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            // init default
            var uniquenessAssets = Guid.NewGuid().ToString().Substring(0, 13);

            var streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created
            var uniquenessLocator    = streamingLocatorGuid.ToString().Substring(0, 13);
            var streamingLocatorName = "locator-" + uniquenessLocator;

            string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13);

            var manifestName = liveEventName.ToLower();

            var useDRM = data.useDRM != null ? (bool)data.useDRM : true;

            if (data.archiveWindowLength != null)
            {
                eventInfoFromCosmos.ArchiveWindowLength = (int)data.archiveWindowLength;
            }

            if (data.inputProtocol != null && ((string)data.inputProtocol).ToUpper() == "RTMP")
            {
                eventInfoFromCosmos.InputProtocol = LiveEventInputProtocol.RTMP;
            }

            if (data.liveEventAutoStart != null)
            {
                eventInfoFromCosmos.AutoStart = (bool)data.liveEventAutoStart;
            }

            if (data.InputACL != null)
            {
                eventInfoFromCosmos.LiveEventInputACL = (List <string>)data.InputACL;
            }

            if (data.PreviewACL != null)
            {
                eventInfoFromCosmos.LiveEventPreviewACL = (List <string>)data.PreviewACL;
            }

            if (data.lowLatency != null)
            {
                eventInfoFromCosmos.LowLatency = (bool)data.lowLatency;
            }

            if (data.useStaticHostname != null)
            {
                eventInfoFromCosmos.UseStaticHostname = (bool)data.useStaticHostname;
            }

            var cencKey = new StreamingLocatorContentKey();
            var cbcsKey = new StreamingLocatorContentKey();

            if (useDRM)
            {
                try
                {
                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             null);

                    MediaServicesHelpers.LogInformation(log, "Irdeto call...");

                    cencKey = await IrdetoHelpers.GenerateAndRegisterCENCKeyToIrdeto(liveEventName, config);

                    cbcsKey = await IrdetoHelpers.GenerateAndRegisterCBCSKeyToIrdeto(liveEventName, config);

                    MediaServicesHelpers.LogInformation(log, "Irdeto call done.");
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex, "Irdeto response error"));
                }
            }

            var clientTasks = new List <Task <LiveEventEntry> >();

            foreach (var region in azureRegions)
            {
                var task = Task <LiveEventEntry> .Run(async() =>
                {
                    Asset asset                     = null;
                    LiveEvent liveEvent             = null;
                    LiveOutput liveOutput           = null;
                    StreamingPolicy streamingPolicy = null;
                    string storageName              = null;

                    ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                             .SetBasePath(Directory.GetCurrentDirectory())
                                                             .AddEnvironmentVariables()
                                                             .Build(),
                                                             region
                                                             );

                    MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                    MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                    if (eventInfoFromCosmos.BaseStorageName != null)
                    {
                        storageName = eventInfoFromCosmos.BaseStorageName + config.AzureRegionCode;
                    }

                    if (data.storageAccountName != null)
                    {
                        storageName = (string)data.storageAccountName;
                    }

                    var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);
                    // Set the polling interval for long running operations to 2 seconds.
                    // The default value is 30 seconds for the .NET client SDK
                    client.LongRunningOperationRetryTimeout = 2;

                    // LIVE EVENT CREATION
                    MediaServicesHelpers.LogInformation(log, "Live event creation...", region);

                    // let's check that the channel does not exist already
                    liveEvent = await client.LiveEvents.GetAsync(config.ResourceGroup, config.AccountName, liveEventName);
                    if (liveEvent != null)
                    {
                        throw new Exception("Error : live event already exists !");
                    }

                    // IP ACL for preview URL
                    var ipsPreview = new List <IPRange>();
                    if (eventInfoFromCosmos.LiveEventPreviewACL == null ||
                        eventInfoFromCosmos.LiveEventPreviewACL.Count == 0)
                    {
                        MediaServicesHelpers.LogInformation(log, "preview all", region);
                        var ip = new IPRange
                        {
                            Name = "AllowAll", Address = IPAddress.Parse("0.0.0.0").ToString(), SubnetPrefixLength = 0
                        };
                        ipsPreview.Add(ip);
                    }
                    else
                    {
                        foreach (var ipacl in eventInfoFromCosmos.LiveEventPreviewACL)
                        {
                            var ipaclcomp = ipacl.Split('/'); // notation can be "192.168.0.1" or "192.168.0.1/32"
                            var subnet    = ipaclcomp.Count() > 1 ? Convert.ToInt32(ipaclcomp[1]) : 0;
                            var ip        = new IPRange
                            {
                                Name               = "ip",
                                Address            = IPAddress.Parse(ipaclcomp[0]).ToString(),
                                SubnetPrefixLength = subnet
                            };
                            ipsPreview.Add(ip);
                        }
                    }

                    var liveEventPreview = new LiveEventPreview
                    {
                        AccessControl = new LiveEventPreviewAccessControl(new IPAccessControl(ipsPreview))
                    };

                    // IP ACL for input URL
                    var ipsInput = new List <IPRange>();

                    if (eventInfoFromCosmos.LiveEventInputACL == null || eventInfoFromCosmos.LiveEventInputACL.Count == 0)
                    {
                        MediaServicesHelpers.LogInformation(log, "input all", region);
                        var ip = new IPRange
                        {
                            Name = "AllowAll", Address = IPAddress.Parse("0.0.0.0").ToString(), SubnetPrefixLength = 0
                        };
                        ipsInput.Add(ip);
                    }
                    else
                    {
                        foreach (var ipacl in eventInfoFromCosmos.LiveEventInputACL)
                        {
                            var ipaclcomp = ipacl.Split('/'); // notation can be "192.168.0.1" or "192.168.0.1/32"
                            var subnet    = ipaclcomp.Count() > 1 ? Convert.ToInt32(ipaclcomp[1]) : 0;
                            var ip        = new IPRange
                            {
                                Name               = "ip",
                                Address            = IPAddress.Parse(ipaclcomp[0]).ToString(),
                                SubnetPrefixLength = subnet
                            };
                            ipsInput.Add(ip);
                        }
                    }

                    var liveEventInput = new LiveEventInput(
                        eventInfoFromCosmos.InputProtocol,
                        accessControl: new LiveEventInputAccessControl(new IPAccessControl(ipsInput)),
                        accessToken: config.LiveIngestAccessToken
                        );

                    liveEvent = new LiveEvent(
                        name: liveEventName,
                        location: config.Region,
                        description: "",
                        useStaticHostname: eventInfoFromCosmos.UseStaticHostname,
                        encoding: new LiveEventEncoding {
                        EncodingType = LiveEventEncodingType.None
                    },
                        input: liveEventInput,
                        preview: liveEventPreview,
                        streamOptions: new List <StreamOptionsFlag?>
                    {
                        // Set this to Default or Low Latency
                        eventInfoFromCosmos.LowLatency?StreamOptionsFlag.LowLatency: StreamOptionsFlag.Default
                    }
                        );


                    liveEvent = await client.LiveEvents.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName,
                                                                    liveEvent, eventInfoFromCosmos.AutoStart);
                    MediaServicesHelpers.LogInformation(log, "Live event created.", region);


                    if (useDRM)
                    {
                        MediaServicesHelpers.LogInformation(log, "Trying to read streaming policy from Cosmos.", region);
                        string streamingPolicyName = null;
                        // Load streaming policy info from Cosmos
                        try
                        {
                            var info = await CosmosHelpers.ReadStreamingPolicyDocument(new StreamingPolicyInfo(false)
                            {
                                AMSAccountName = config.AccountName
                            });

                            if (info == null)
                            {
                                log.LogWarning("Streaming policy not read from Cosmos.");
                            }
                            else
                            {
                                streamingPolicyName = info.StreamingPolicyName;
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("Error reading Cosmos DB", ex);
                        }


                        // STREAMING POLICY CREATION
                        if (streamingPolicyName == null) // not found in Cosmos let's create a new one
                        {
                            MediaServicesHelpers.LogInformation(log, "Creating streaming policy.", region);
                            try
                            {
                                streamingPolicy = await IrdetoHelpers.CreateStreamingPolicyIrdeto(config, client, uniquenessPolicyName);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Streaming policy creation error", ex);
                            }

                            try
                            {
                                if (!await CosmosHelpers.CreateOrUpdatePolicyDocument(new StreamingPolicyInfo(false)
                                {
                                    AMSAccountName = config.AccountName,
                                    StreamingPolicyName = streamingPolicy.Name
                                }))
                                {
                                    log.LogWarning("Cosmos access not configured or error.");
                                }
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Streaming policy write error to Cosmos", ex);
                            }
                        }
                        else
                        {
                            MediaServicesHelpers.LogInformation(log, "Getting streaming policy in AMS.", region);
                            try
                            {
                                streamingPolicy = await client.StreamingPolicies.GetAsync(config.ResourceGroup, config.AccountName, streamingPolicyName);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Error when getting streaming policy " + streamingPolicy, ex);
                            }
                        }
                    }

                    // LIVE OUTPUT CREATION
                    MediaServicesHelpers.LogInformation(log, "Live output creation...", region);

                    try
                    {
                        MediaServicesHelpers.LogInformation(log, "Asset creation...", region);

                        asset = await client.Assets.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName,
                                                                        "asset-" + uniquenessAssets,
                                                                        new Asset(storageAccountName: storageName));

                        Hls hlsParam = null;

                        liveOutput = new LiveOutput(asset.Name, TimeSpan.FromMinutes(eventInfoFromCosmos.ArchiveWindowLength),
                                                    null, "output-" + uniquenessAssets, null, null, manifestName,
                                                    hlsParam); //we put the streaming locator in description
                        MediaServicesHelpers.LogInformation(log, "await task...", region);

                        MediaServicesHelpers.LogInformation(log, "create live output...", region);
                        await client.LiveOutputs.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName,
                                                             liveOutput.Name, liveOutput);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("live output creation error", ex);
                    }


                    try
                    {
                        // let's get the asset
                        // in v3, asset name = asset if in v2 (without prefix)
                        MediaServicesHelpers.LogInformation(log, "Asset configuration.", region);

                        StreamingLocator locator = null;
                        if (useDRM)
                        {
                            locator = await IrdetoHelpers.SetupDRMAndCreateLocatorWithNewKeys(config, streamingPolicy.Name,
                                                                                              streamingLocatorName, client, asset, cencKey, cbcsKey, streamingLocatorGuid, liveEventName);
                        }
                        else // no DRM
                        {
                            locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid);
                        }

                        MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("locator creation error", ex);
                    }

                    // let's build info for the live event and output

                    var generalOutputInfo =
                        GenerateInfoHelpers.GenerateOutputInformation(config, client, new List <LiveEvent> {
                        liveEvent
                    });

                    if (!await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(generalOutputInfo.LiveEvents[0]))
                    {
                        log.LogWarning("Cosmos access not configured.");
                    }

                    return(generalOutputInfo.LiveEvents[0]);
                });

                clientTasks.Add(task);
            }

            try
            {
                Task.WaitAll(clientTasks.ToArray());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            return(new OkObjectResult(
                       JsonConvert.SerializeObject(new GeneralOutputInfo {
                Success = true, LiveEvents = clientTasks.Select(i => i.Result).ToList()
            }, Formatting.Indented)
                       ));
        }
Example #16
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var assetNameStartsWith = (string)data.assetNameStartsWith;

            if (assetNameStartsWith == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetNameStartsWith in the JSON"));
            }

            List <string> assets = new List <string>();

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }


            foreach (var region in azureRegions)
            {
                ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                         .SetBasePath(Directory.GetCurrentDirectory())
                                                         .AddEnvironmentVariables()
                                                         .Build(),
                                                         region
                                                         );

                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                MediaServicesHelpers.LogInformation(log, "asset name starts : " + assetNameStartsWith, region);

                try
                {
                    ODataQuery <Asset> query  = new ODataQuery <Asset>();
                    string             search = "'" + assetNameStartsWith + "'";
                    query.Filter  = "name gt " + search.Substring(0, search.Length - 2) + char.ConvertFromUtf32(char.ConvertToUtf32(search, search.Length - 2) - 1) + new string('z', 262 - search.Length) + "'" + " and name lt " + search.Substring(0, search.Length - 1) + new string('z', 262 - search.Length) + "'";
                    query.OrderBy = "Properties/Created";
                    var assetsResult = client.Assets.List(config.ResourceGroup, config.AccountName, query);

                    assets = assetsResult.Select(a => a.Name).ToList();
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }
            }

            var response = new JObject
            {
                { "success", true },
                { "assetNames", new JArray(assets) },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response
                       ));
        }
Example #17
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var streamingLocatorName = (string)data.streamingLocatorName;

            if (streamingLocatorName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass streamingLocatorName in the JSON"));
            }


            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            foreach (var region in azureRegions)
            {
                ConfigWrapper config = null;

                try
                {
                    config = new ConfigWrapper(new ConfigurationBuilder()
                                               .SetBasePath(Directory.GetCurrentDirectory())
                                               .AddEnvironmentVariables()
                                               .Build(),
                                               region
                                               );
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }

                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                try
                {
                    client.StreamingLocators.Delete(config.ResourceGroup, config.AccountName, streamingLocatorName);
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }
            }

            var response = new JObject
            {
                { "streamingLocatorName", streamingLocatorName },
                { "success", true },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response.ToString()
                       ));
        }
Example #18
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            bool success = true;

            var requestBody = new StreamReader(req.Body).ReadToEnd();

            LiveEventSettingsInfo settings = null;

            try
            {
                settings = (LiveEventSettingsInfo)JsonConvert.DeserializeObject(requestBody,
                                                                                typeof(LiveEventSettingsInfo));
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }


            ConfigWrapper config = null;

            try
            {
                config = new ConfigWrapper(
                    new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddEnvironmentVariables()
                    .Build()
                    );
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            log.LogInformation("config loaded.");

            try
            {
                if (!await CosmosHelpers.CreateOrUpdateSettingsDocument(settings))
                {
                    log.LogWarning("Cosmos access not configured or error.");
                    success = false;
                }
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var response = new JObject
            {
                { "Success", success },
                {
                    "OperationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response.ToString()
                       ));
        }