You are here

Feed aggregator

Before claiming that a function doesn't work, you should check what you're passing to it and what it returns

MSDN Blogs - 8 hours 49 min ago

Before claiming that a function doesn't work, you should check what you're passing to it and what it returns, because it may be that the function is behaving just fine and the problem is elsewhere.

The Get­Current­DirectoryW function does not appear to support directories with Unicode characters in their names.

wchar_t currentDirectory[MAX_PATH]; GetCurrentDirectoryW(MAX_PATH, currentDirectory); wcout << currentDirectory << endl;

The correct directory name is obtained if it contains only ASCII characters in its name, but it truncates the string at the first non-ASCII character.

If you step through the code in the debugger, you'll see that the Get­Current­DirectoryW function is working just fine. The buffer is filled with the current directory, including the non-ASCII characters. The problem is that the wcout stream stops printing the directory name at the first non-ASCII characters. And that's because the default locale for wcout is the "C" locale, and the "C" locale is "the minimal environment for C translation." The "C" locale is useless for actual work involving, you know, locales. You will have to do some language-specific munging to get the characters to reach the screen in the format you want, the details of which are not the point of today's topic.

In other words, the bug was not in the Get­Current­DirectoryW function. It was in what you did with the result of the Get­Current­DirectoryW function.

Here's another example of thinking the problem is in a function when it isn't:

The Set­Window­TextW function does not appear to support Unicode, despite its name.

wstring line; wifstream file("test"); // this file is in Unicode getline(file, line); SetWindowTextW(hwnd, line.c_str());

If you look at the line variable before you even get around to calling Set­Window­TextW, you'll see that it does not contain the text from your Unicode file. The problem is that the default wifstream reads the text as an 8-bit file, and then internally converts it (according to the lame "C" locale) to Unicode. If the original file is already Unicode, you're doing a double conversion and things don't go well. You then pass this incorrectly-converted string to Set­Window­TextW, which naturally displays something different from what you intended.

Again, the point is not to delve into the intricacies of wifstream. The point is that the problem occurred even before you called Set­Window­TextW. The observed behavior, then, is simple a case of Garbage In, Garbage Out.

Here's another example from a few years ago.

BHM is now officially available for BizTalk Server 2010 and BizTalk Server 2013

MSDN Blogs - 9 hours 6 min ago

BizTalk Health Monitor is a snap-in which can be used to monitor a BizTalk environment. For more information about BHM, see this link.

BHM was originally released with BizTalk Server 2013 R2 and now we have released a standalone version of BHM for use with BizTalk Server 2010 and BizTalk Server 2013. You can download the standalone version of BHM from this link. The registration process of BHM is same as it was for BizTalk 2013 R2. Visit this link for more details.

BHM has been tested and is supported on BizTalk 2010, BizTalk 2013 and BizTalk 2013 R2. It may work for other versions of BizTalk Server, however it won’t be officially supported.

Happy Birthday, Office!

MSDN Blogs - 11 hours 46 min ago

25 Jahre: das entspricht einer Silberhochzeit, der Reifezeit eines sehr edlen Single-Malt-Whiskeys, zwei bis drei „Goldenen Generationen“ im Weltfußball, drei bis vier Bausparverträgen – und eben der Karriere eines der beliebtesten Bürosoftwarepakete des Globus. Denn über eine Milliarde Nutzer verwendet heutzutage Office. Im Geschäftsleben stellen Microsoft Word, Excel, PowerPoint, Access und Outlook den Standard für die Wissensarbeit dar, sorgen für mehr Produktivität, Zeitersparnis und erleichtern vernetztes Arbeiten. Und auch in Schule und Studium, im privaten Alltag und dem täglichen Familienleben nimmt Office seit 25 Jahren eine prägende Rolle ein.

Dass Microsoft trotz des Erfolgs seiner Produkte nicht stehen bleibt, beweist Office 365 mit seinen zahlreichen Features, die die Kommunikation und Kollaboration im Schullalltag revolutionieren. Neben den alt-bewährten und bekannten Office Produkten stellt O365 mit seinen zahlreichen Möglichkeiten des Active Directory eine echte Erleichterung für die Schul- und IT-Verwaltung dar. Klassen und Zentralkalender können mit Office 365 Kalender Use schnell und und kompliziert angelegt und verwaltet werden und Sharepoint, Lync und Exchange machen die gemeinsame Projektarbeit im Unterricht  zum Kinderspiel. Zahlreiche Apps erlauben den Schülern zusätzlich Kalender, Notizbücher und Outlook von verschiedenen Endgeräten aus abzurufen.

Viele Produkte von Office 365 können Bildungseinrichtungen kostenlos nutzen und darüber hinaus ermöglicht der FWU-Vertrag allgemein- und berufsbildenden Schulen Software zu deutlich reduzierten Preisen zu lizensieren. Des Weiteren können Schüler im Rahmen des Student Advantage Benefit Programm die aktuelle Office Desktop-Version gratis  herunterladen. Seit Dezember 2013 gilt diese Option für alle Bildungseinrichtungen ohne Zusatzkosten, die sämtliche Vollzeitmitarbeiter mit Office 365 ProPlus oder Office Professional lizensiert haben.

Mehr Informationen zu Office 365 für Bildungseinrichtungen, den Bezugsoptionen und den zahlreichen Features finden Sie hier.

Lync Server 2013 Client Policy の DGRefreshInterval

MSDN Blogs - 12 hours 14 min ago

こんばんは。japan Lync Support Team です。

 

Lync Server 2013 の Client Policy に DGRefreshInterval があります。

Technet にはパラメーターの説明として、以下のように記述があります。

抜粋

Lync が連絡先リスト内で "展開された" 配布グループのメンバーシップ リストを自動更新するまで待機する時間を示します (配布グループの展開とは、そのグループ内のメンバーをすべて表示することです)。DGRefreshInterval には、30 ~ 28,800 秒 (8 時間) の任意の整数値を設定できます。既定値は 28,800 秒です。

この設定は、Office Communications Server 2007 R2 のグループ ポリシー設定 "各配布グループのメンバーシップを更新する時間間隔" と同等です。

 

しかし、実際に設定するときは、hh:mm:ss の形式で設定する必要があります。

例えば、以下のように設定します。

 

なお、Technet の記載通りに 5分= 300 秒という計算で設定すると、設定が正常に動作せず、

リフレッシュをし続け、正常に動作しなくなります。

 

弊社ドキュメントの不備によりご迷惑をお掛けし申し訳ございません。

 

 

Windows 8: The Perfect Fit for Business & Education (Video)

MSDN Blogs - 12 hours 32 min ago

Windows 8 is more than an operating system; it opens the door to a plethora of new devices that can change the way you and your company do business. Whatever device you're using - desktop PC, laptop or tablet, Windows 8 provides all the power and applications to get the job done. Whether you're researching a lesson plan for your students, or examining a patient's records after a major operation, there's a Windows 8 device that fits the bill.

[Announcement] ODataLib 6.6.0 Release

MSDN Blogs - 13 hours 26 min ago

We are happy to announce that the ODL 6.6.0 is released and available on nuget along with the source code oncodeplex (please read the git history for the v6.6.0 code info and all previous version). Detailed release notes are listed below.

Bug Fix
  • Fix a bug that Client cannot serialize/deserialize a collection property whose element type is abstract complex type, but the element value is concrete 
New Features
    • Add Instance Annotation on ODataProperty and ODataComplexValue

    • UrlParser supports some Arithmetic Operators and built-in functions
      1. Support add, sub operators between DatetimeOffset and Duration
      2. Support the negation operator for duration
      3. Support following built-in functions
    • ODL supports advertising functions/actions which bound to a collection of entities in payload by using name/value pairs of title and target

 


Call to Action

You and your team are highly welcomed to try out this new version if you are interested in the new features and fixes above. For any feature request, issue or idea please feel free to reach out to us atodatafeedback@microsoft.com.

Turn off Notification Hub in Azure Mobile Service to use Legacy Push

MSDN Blogs - 13 hours 31 min ago

Currently when you create a new Windows Azure Mobile Service to send push notification(detailed information can be found in Get started with push notifications in Mobile Services ),  the  notification hub is by default integrated with your mobile service, we really want people to move away from the legacy push, however, for the rare cases where people still want to use legacy push, so how can we do that?

The default change to use Notification Hub for push only applies when creating a mobile service via the portal.  We can make one with the CLI resulting in one not using notification hubs. If you install the AzureCLI and run:  "azure mobile create <appname>" , and follow the prompts, you can then continue to use the scripts in the old way.

After you installed the Azure CLI, run command prompt with administrator privilege(you can do this via pressing windows logo key + X key, and choose “Command Prompt(Admin)”), then type following commands:

  1. azure account download , which will navigate you to the web browser to download the setting profile
  2. azure account import “path\**.publishsetting” , which will import your azure account credential
  3. azure mobile create <appname>

      
 
  
  
  
  
  
  
  
  
  
  
  
  
 
 
 


 

ALM Rangers @ TR19 … day 4 impressions … what about day 3?

MSDN Blogs - 15 hours 14 min ago

Sorry, day three my laptop imploded an hour before our session, leaving me wondering what I have done to the digital bits and bytes, being absent minded during our session and spending the afternoon and evening convincing my laptop to reboot. Sorry, that too day 3 with it and until João Paulo Rodrigues shares the pictures he took on my behalf, it will remain to be a mystery.

Day 4, however, was more than fun … enjoy the snapshots:
You should recognise William Bartholomew, Robert Bernstein and Willy-Peter Schaub.

Robert and I also experimented in ways to  assimilate ALM Rangers in future … wear Application Lifecycle Management (ALM) or ALM Rangers with pride  Arrrrrrr!

 

Tomorrow is a day of meetings, preparing for the Leading SAFe workshop weekend. This TR week has been absolutely great, with interesting sessions, and phenomenal colleagues. Looking forward to meeting 3 more ALM Rangers over the weekend for a fun workshop … and yes, there will be Pizza.

Introducing the Visual Studio ALM Rangers (aka.ms/vsarindex)

MSDN Blogs - Thu, 07/31/2014 - 23:59

This is an index of all Distinguished, Honorary, Active, Associate and Stakeholder ALM Rangers from around the world. Bookmark it so that you can come back and take note of the introductions as they are posted and any changes in status. For more information see Understanding the Visual Studio ALM Rangers.

 141 + 41 Associate = 182 active around the

Visual Studio ALM Rangers

Active ALM Rangers, who are contributing as product owners, project leads, backup project leads, contributors, reviewers and/or mentors.  

  1. Aaron Bjork
  2. Abhimanyu Singhal
  3. Adam Gilmore
  4. Alan Wills
  5. Alexander Vanwynsberghe
  6. André Dias
  7. Anil Chandra Lingam
  8. Anisha Pindoria
  9. Anna Galaeva
  10. Anthony Borton
  11. Babu George Padamadan
  12. Bijan Javidi
  13. Bill Heys
  14. Bipin Puthiyaveetil
  15. Bob Hardister
  16. Brian Blackman
  17. Brian Keller
  18. Brian Minisi
  19. Brian Randell
  20. Caroline Williams
  21. Carsten Düllmann
  22. Casey O'Mara
  23. Cesar Solis Brito
  24. Charles Sterling
  25. Chris Burrows
  26. Chris Margraff
  27. Christian Nielsen
  28. Christofer Löf
  29. Cissy Ho
  30. Cláudio Bernardo Leite B. R. da Silva
  31. Clementino Mendonca
  32. Dan Hellem
  33. Dan Marzolini
  34. Daniel Oliveira
  35. Danny Crone
  36. Darren Rich
  37. Dave Crook
  38. Dave McKinstry
  39. David Hay
  40. David Pitcher
  41. David V. Corbin
  42. Dmitry Andreev
  43. Edward Fry
  44. Eric Golpe
  45. Esteban Garcia
  46. Ethem Azun
  47. Etienne Tremblay
  48. Fabio Stawinski
  49. Francisco Xavier Fagas Albarracin
  50. Giulio Vian
  51. Gordon Beeming
  52. Grant Holliday
  53. Hamid Shahid
  54. Hassan Fadili
  55. Hosam Kamel
  56. Jahangeer Mohammed
  57. Jakob Ehn
  58. James Waletzky
  59. Jason Singh
  60. Jeff Bramwell
  61. Jeff Levinson
  62. Jelle Druyts
  63. Jesse Houwing
  64. Jim Szubryt
  65. John Bergman
  66. John Spinella
  67. Jon Guerin
  68. Joseph Abukhader
  69. Josh Sommer
  70. Kris Lankford
  71. Krithika Sambamoorthy
  72. Lennart Jansson
  73. Leonard S. Woody III
  74. Manish Ahuja
  75. Marcus Fernandez
  76. Mario Contreras
  77. Mark Nichols
  78. Martin Hinshelwood
  79. Martin Kulov
  80. Mathew Aniyan
  81. Mathias Olausson
  82. Mattias Sköld
  83. Mehmet Aras
  84. Michael Fourie
  85. Micheal Learned
  86. Mike Abrahamson
  87. Mike Douglas
  88. Mohideen Abdul Kader Sandhu Muzafargani
  89. Nicholas Hauenstein
  90. Niel Zeeman  
  91. Oliver Hilgers
  92. Olivier Dupont
  93. Osmar Landin
  94. Patricia Wagner
  95. Paul Meyer
  96. Petr Moravek
  97. Philip Haugaard
  98. Pierre Donyegro
  99. Pramod Vasanth
  100. Prasanna Ramkumar
  101. Raul Guerrero Carreon
  102. Rex Tang
  103. Richard Albrecht
  104. Richard Fennell
  105. Richard Florance
  106. Richard Hundhausen
  107. Rob Jarratt
  108. Rob Maher
  109. Robert Bernstein
  110. Robert MacLean
  111. Roy Robertson
  112. Rui Melo
  113. Ryan Frazier
  114. Shawn Cicoria
  115. Stefan Mieth
  116. Steven Borg
  117. Stuart Preston
  118. Suliman AlBattat
  119. Susan Ferrell
  120. Svetlana Kostinsky
  121. Taavi Koosaar
  122. Tarun Arora
  123. Ted Malone
  124. Thomas Isler
  125. Thomas Schissler
  126. Tiago Pascoal
  127. Tim Star
  128. Tina Erwee
  129. Tomas Scott
  130. Tommy Sundling
  131. Tony Feissle
  132. Tony Whitter
  133. Utkarsh Shigihalli
  134. Vinicius Hana
  135. Vinicius Moura
  136. Vladimir Gusarov
  137. Vlatko Ivanovski
  138. William Bartholomew
  139. William H. Salazar
  140. Willy-Peter Schaub
  141. Wouter de Kort

Associate ALM Ranger

Individuals who are associated to and working with the ALM Rangers community. All ALM Rangers (re-)start as associates, before moving into the active category. ( * = new )

  1. Alan Morais
  2. Amit Gupta
  3. Andrew Clear
  4. Bandar Alsharfi
  5. Barry Paquet
  6. Baruch Frei
  7. Ben Roscorla
  8. Brian Messerich
  9. Bryon Root
  10. Calvin Clark
  11. Cosmin Dumitru
  12. Doug Owens
  13. Edgar Vega Calderon
  14. Evgeniy Berenshtein
  15. Georg Drobny
  16. Janice Choi
  17. Javier Arguello
  18. Jesper Fernström
  19. João Paulo Rodrigues
  20. Kiran Kumar Dodda
  21. Kiran Kumar Grandhe
  22. Kirushna Kumaar
  23. Lalit Patel
  24. Leandro Prado
  25. Malcolm Hyson
  26. Masashi Fujiwara
  27. Michael Wiley
  28. Michel Perfetti
  29. Nirav Khandhedia
  30. Paul Laberge
  31. Peter Oreland
  32. Rajesh Podapati
  33. Ranjit Gupta
  34. Sahaswaranamam Subramanian
  35. Shawn McLean
  36. Soung Bae
  37. Stephan Dekker
  38. Sumeet Deshpande
  39. Takeo Hoyama
  40. Wanderson Lima
  41. Yang Zheng

PO/PG ALM Rangers

ALM Rangers who are full-filling a product owner or product group interface role and actively supporting the ALM Rangers.

  1. Alan Wills
  2. Anna Galaeva
  3. Bijan Javidi
  4. Bill Essary
  5. Brian Harry
  6. Brian Keller
  7. Charles Sterling
  8. Chris Patterson
  9. Chris Wishart
  10. Ed Blankenship
  11. Ed Holloway
  12. Ewald Hofman
  13. Gregg Boer
  14. Hakan Eskici
  15. Jean-Marc Prieur
  16. Jeff Jurvis
  17. Jim Lamb
  18. Joshua Weber
  19. Keith Bankston
  20. Mario Rodriguez
  21. Mathew Aniyan
  22. Matthew Mitrik
  23. Prachi Bora
  24. Ravi Shanker
  25. Roopesh Nair
  26. Susan Ferrell
  27. Tom Lindeman
  28. Vijay Machiraju
  29. Willy-Peter Schaub

    Distinguished ALM Rangers

    Individuals who have excelled, have shipped as least one successful ALM Rangers project as the primary Project Lead and are actively mentoring other ALM Rangers. (* indicates number of times Ranger achieved the criteria)

    1. Bijan Javidi **
    2. Bob Hardister  *
    3. Brian Blackman  ***
    4. Casey O'Mara *
    5. David Pitcher  *
    6. Ethem Azun *
    7. Francisco Xavier Fagas Albarracin *
    8. Jim Szubryt  **
    9. John Spinella  *
    10. Mathias Olausson  *
    11. Mattias Sköld  *
    12. Michael Fourie  **
    13. Micheal Learned  *
    14. Paul Meyer *
    15. Pramod Vasanth  **
    16. Rob Jarratt  ***
    17. Robert Bernstein **
    18. Robert MacLean  **
    19. Tommy Sundling
    20. Tony Whitter **
    21. Willy-Peter Schaub  ***

    Honorary ALM Rangers

    ALM Rangers who have retired from an active position, but have actively contributed invaluable passion and contributions to the ALM Ranger community.

    1. Alison Clark
    2. Andrea Scripa
    3. Ben Amodio
    4. Bill Essary
    5. Bill Heys
    6. Buck Hodges
    7. David Caufield
    8. Eric Charran
    9. Erwyn van der Meer
    10. James Pickell
    11. Jeff Beehler
    12. John Jacob
    13. Justin Marks
    14. Kerry Gates
    15. Larry Duff
    16. Larry Guger
    17. Lenny Fenster
    18. Mike Schimmel
    19. Neno Loje
    20. Tim Omta
    21. Zayd Kara

    Scrum / Ruck Masters

    ALM Rangers who have been certified as Visual Studio ALM Ranger Scrum Ruck Masters, who are the face of the “Scrum/Ruck” process, who guide, mentor and coach the project leads and teams.

    1. Anisha Pindoria
    2. Brian Blackman
    3. Jahangeer Mohammed
    4. John Bergman
    5. Willy-Peter Schaub

    Stakeholder ALM Rangers

    ALM Rangers who are part of the leadership or are strategically and actively supporting the ALM Rangers.

    1. Amit Chatterjee
    2. Anand Kamat
    3. Bijan Javidi
    4. Bill Essary
    5. Brian Harry
    6. Claude Remillard
    7. Clemri Steyn
    8. Jeff Jurvis
    9. Nicole Herskowitz
    10. Sam Guckenheimer
    11. Willy-Peter Schaub

    This page replaces the outdated index page: Introducing the Visual Studio ALM Rangers ... an index to all Rangers covered on this blog.

    シンプルな Azure Web Sites のデプロイメント

    MSDN Blogs - Thu, 07/31/2014 - 23:20

    このポストは、7 月 28 日に投稿した Simple Azure Websites: Deployment の翻訳です。

    Azure Web Sites へのデプロイメントで私が好んで使用するのは Git です。それは私が、Git を使用してデプロイする機能にその黎明期 (当時は Kudu (英語) という名称でした) から関わってきたからです。

    しかし、ローカル マシンからいくつかのファイルをデプロイしたいだけのときは、Git では大掛かりになりすぎです。そういった場合に役立つのが WebDeploy (別称 MSDeploy) です。

    WebDeploy はコマンドラインから使用するのでちょっとした慣れが必要です。発行プロファイルを (Azure Web Sites ダッシュボードから) ダウンロードしたら、そこから情報を抽出し、それをまとめると、次のようなコマンドラインになります。これでローカル フォルダーを Azure Web Sites にデプロイできます。

    msdeploy.exe
    -verb:sync
    -source:contentPath=”c:\FolderToDeploy”
    -dest:
    contentPath=’MyAzureSite’,
    ComputerName=”https://waws-prod-blu-001.publish.azurewebsites.windows.net:443/msdeploy.axd?site=MyAzureSite”,
    UserName=’$myazuresite’,
    Password=’fgsghfgskhBigUglyPasswordjfghkjsdhgfkj’,
    AuthType=’Basic’

    これでは長くて複雑ですね。そこで…

    お助けツール WAWSDeploy

    もっと簡単にできないかと思い、コマンドラインをできるだけシンプルにする簡単なツールを作成しました。同じく Azure ポータルから公開プロファイルをダウンロードする必要がありますが、後は次のシンプルなコマンドを実行するだけです。

    WAWSDeploy   c:\FolderToDeploy MyAzureSite.PublishSettings

    基本的には、ファイルの場所を指定するだけです。ツールがプロファイルの必要な情報を割り出してくれます。zip ファイルの中身を直接デプロイすることもできます。

    WAWSDeploy   c:\MyFiles.zip MyAzureSite.PublishSettings

    ツールを入手するには、自分でソース (英語) からビルドするか、Chocolatey (英語) からダウンロードしてください。

    その他のメモ

    • このツールはビルドが不要なシンプルなサイト向けです (ASP.NET MVC には向いていません)。
    • 片手間に作った簡単なツールですので、マイクロソフトが公式にサポートしている訳ではありません。
    • WebDeploy と同様、WAWSDeploy も Windows にのみ対応しています。

    私のブログ (英語) で Kudu や Azure Web Sites の開発について詳しく紹介しているので、ぜひご覧になってください!

    Azure Web Sites での PDF の生成、およびファイル ベースの証明書の読み込み

    MSDN Blogs - Thu, 07/31/2014 - 23:10

    このポストは、7 月 25 日に投稿した PDF Generation and loading file based certificates in Azure Websites の翻訳です。

    Microsoft Azure Web Sites に関して、マイクロソフトは、普段使用する IIS と親和性の高い開発プラットフォームの実現に力を注いでいます。目指すは、開発者がオンプレミス環境で開発したコードをクラウドにデプロイする際の手順が容易で、煩雑さを感じさせないプラットフォームです。しかし現状では、マルチテナント型サービスに関連することとして、Azure Web Sites で実行されるアプリケーション保護により問題が発生することがあります。そこで今回、これまでは制限のあったシナリオの実行を可能にするために、Basic および Standard のサービスをご利用のお客様に向けて 2 つの新機能をリリースいたします。

    SQL Server Reporting Services (レポート ビューアー) を使用した PDF の生成

    現在 Azure Web Sites では、さまざまなツールやフレームワークを PDF ファイルの作成に使用できますが、SQL Server Reporting Services は、広く普及しているツールでありながら、これまでは使用することができませんでした。サービスにいくつか変更を加えたことにより、Basic または Standard レベルのインスタンスを実行中の Azure Web Sites のお客様は、このシナリオを実行できるようになりました。現在、PDF 機能はシームレスにご利用いただけます。

    ファイル ベースの PFX 証明書の読み込みのサポート

    他の HTTP のサービスやエンドポイントへの認証にクライアント証明書を使用するアプリケーションでは、通常、ファイル システムから証明書を読み込み (X509Certificate2 クラスを使用して PFX ファイルを指定)、HTTP 要求の開始時にこの証明書を参照します。Windows がファイルから証明書を読み込む方法では、PFX をファイル システムから読み込むためには、Web アプリケーションでユーザー プロファイルを使用できる必要があります。ユーザー プロファイルを読み込む機能は、通常使用する IIS サーバーでは「アプリケーション プール単位」の設定としてサポートされています。今回 Azure Web Sites 上のアプリケーションが PFX から証明書を読み込めるようにするために、IIS サーバーと同じ設定機能を Azure に追加しました (この機能も、Basic または Standard レベルのインスタンスをご利用のお客様のみ利用可能です)。[App Settings] で [WEBSITE_LOAD_USER_PROFILE] を「1」に設定 (下図参照) すると、Azure Web Sites でユーザー プロファイルを読み込み、特定のアプリケーションで使用できるようになります。これでアプリケーションが PFX ファイルから証明書を読み込めます。次善策を講じる必要はありません。

    お客様からのご意見、ご感想は、機能を適切に向上していくうえでたいへん貴重なものです。これまでお客様の関心が高かった上記の 2 つの課題には、最新のリリースで適切に対応できたものと思います。今後も引き続き、お客様からのフィードバックを心よりお待ちしております。

    Azure Automation: Visual Studio Online を利用した Runbook ソース管理の統合

    MSDN Blogs - Thu, 07/31/2014 - 23:00

    このポストは、7 月 24 日に投稿した Azure Automation: Integrating Runbook Source Control using Visual Studio Online の翻訳です。

    はじめに

    Azure Automation は Azure のリソースやサードパーティ システムの管理に役立つものですが、Azure Automation のリソース自体 (Runbook、モジュール、アセットなど) を管理するにはどうすればよいでしょうか? もちろん、Azure Automation のポータルや Azure Automation PowerShell コマンドレット (英語) を使用すれば基本的な管理タスクは実行できますが、Runbook、モジュール、アセットをソース管理システムに保存したり、変更履歴、監査、過去のバージョンの復元、さらに、開発、ステージング、本番の各ブランチ間でのバージョン移行における変更管理を行うには別の方法が必要になります。

    実は Runbook をうまく利用することで、Azure Automation のリソースをソース管理システムに継続的に統合するように Azure Automation をセットアップすることができます。この記事では、Azure Automation を使用して Visual Studio Online (VSO) の Git リポジトリに対して繰り返しクエリを実行する方法と、Runbook (ps1 ファイル) をこのソース管理リポジトリから Automation アカウントに自動的に発行する方法について説明します。今回は Runbook のみを取り上げますが、Azure Automation を使用すればソース管理システムに保存されているモジュールやアセットを Azure Automation と継続的に統合することが可能です。

    Sync-VsoGitRunbook Runbook

    このシナリオのすべてのタスクは、Sync-VsoGitRunbook という Runbook を使用して実行できます。この Runbook は下のダウンロード ボタンから入手できます。

    下の図は、ソース管理システムに保存されている Runbook を Azure Automation アカウントに継続的に統合するプロセスの全体像を示しています。この統合の優れている点は、Visual Studio Online の Git リポジトリを通常どおりに管理するだけで Runbook を管理できることです。

    • Runbook を更新したら、コミットして更新を Visual Studio Online の Git リポジトリに保存します。
    • 更新を元に戻したい場合は、コミットを取り消します。
    • ステージング ブランチでの更新を本番ブランチに反映させるには、ステージングを本番にマージするだけです。

    Sync-VsoGitRunbook Runbook は、同期元の Visual Studio Online の Git リポジトリと、同期先の Azure Automation アカウントをパラメーターで指定できます。また、この Runbook を実行している Automation アカウント、または別のアカウントと同期することもできます。内部的な処理としては、Runbook は指定された Visual Studio Online の Git リポジトリの情報を取得し、Runbook を指定の Azure Automation アカウントに再帰的 (子 Runbook、親 Runbook の順) にインポー��して発行します。

    Runbook を手動で開始して、オンデマンドで Azure Automation アカウントと Visual Studio Online の Git リポジトリを同期したり、スケジュール アセットを使用して同期を自動化したりすることができます。この Runbook の実行スケジュールは複数セットアップすることが可能なため、Git のブランチおよび Azure Automation アカウントの種類別に実行スケジュールを設定して、QA から本番までの変更管理を実現できます。たとえば、Git のステージング ブランチとステージングの Automation アカウントのパラメーター値を持つ Runbook と、Git の本番ブランチと本番の Automation アカウントのパラメーター値を持つ Runbook のスケジュールを設定すると、ステージングの Automation アカウントは Git のステージング ブランチと同期し、本番の Automation アカウントは Git の本番ブランチと同期します。Git のステージング ブランチから Git の本番ブランチにマージにすると、更新された Runbook が本番の Automation アカウントに自動的に移行されます。

    Visual Studio Online をセットアップする

    最初に Visual Studio Online アカウントを取得し、プロジェクトとリポジトリを構成する必要があります。アカウントを作成するには、こちらにアクセスしてください。

    Git プロジェクトとリポジトリの構成については、こちらのブログ記事 (英語) を参照してください。

    サンプル プロジェクトを作成する

    これで Automation Runbook の Visual Studio プロジェクトを作成する準備が整いました。この例では、シンプルな Empty Project を使用します。

    Runbook のプロジェクト構造

    プロジェクトの構造は、親 Runbook を最上位のディレクトリに、子 Runbook をその配下のディレクトリに、子 Runbook の子をそのまた配下のディレクトリに置く階層構造にします。Runbook はディレクトリ ツリーを再帰的に参照し、一番下のディレクトリにある Runbook (最下位の子 Runbook) を最初に発行し、順次上位の子 Runbook を発行していきます。このため、子 Runbook が呼び出し元の Runbook (すなわち親 Runbook) よりも常に先にインポートされます。これは Azure Automation サービスでは子 Runbook をすべて最初に公開する必要があるためです。

    この階層構造を図解すると以下のとおりです。

    Visual Studio Online プロジェクト ビューでは次のような構造になります。

    Visual Studio Online で代替認証資格情報をセットアップする

    Sync-VsoGitRunbook Runbook を使用するには、Visual Studio Online ダッシュボード (右上) の [My Profile] で構成した Visual Studio Online の代替認証資格情報を使用します。

    User Profile ダイアログで [CREDENTIALS] を選択して、代替認証資格情報を定義します。ここで設定したユーザー名とパスワードが Sync-VsoGitRunbook Runbook のパラメーターとして使用されます。

    Sync-VsoGitRunbook Runbook を開始する
    1. まず、Connect-Azure Runbook を使用して Azure サブスクリプションを管理できるように Azure Automation アカウントをセットアップします。セットアップ方法の詳細については、IIS がある場合にはこちらのブログ記事 (英語) を、IIS がない場合にはこちらのブログ記事 (英語) を参照してください。
    2. Sync-VsoGitRunbook Runbook を次の Script Center からダウンロードします。  
    3. Sync-VsoGitRunbook Runbook をインポートし発行します。
    4. 以下の Azure Automation アセットを作成します。
      • Credential – 代替認証資格情報のユーザー名とパスワードが含まれます。
      • Connection – 発行先の Automation アカウントがあるサブスクリプション ID を持つ Azure 接続の種類を作成します。
    5. Sync-VsoGitRunbook Runbook の毎日のスケジュールを以下のパラメーターで追加します。
      • VSOCredentialName – Visual Studio Online の Profile ダイアログで設定した Visual Studio Online の代替認証資格情報の名前とパスワードを含む資格情報アセット名です。
      • VSOAccount – Visual Studio Online のアカウント名です (例: https://accountname.visualstudio.com)。
      • VSOProject – リポジトリを含む Visual Studio Online プロジェクト名です。
      • VSORepository – Runbook プロジェクトが格納されたリポジトリ名です。
      • VSORunbookFolderPath – Runbook が存在するルートのプロジェクト パスです。下の例では /Project1/Project1 を使用します。
      •  

      • VSOBranch – Runbook の詳細を照会するために使用するブランチ名です (任意)。既定値は「master」です。
      • AutomationAccount – Runbook の同期先の Automation アカウント名です。
      • AzureConnection – Automation サービスで作成された Azure 接続設定の名前です。この接続設定には、サブスクリプション ID と管理証明書がある証明書設定の名前が含まれます。
    まとめ

    この記事では Sync-VsoGitRunbook Runbook を例に、Runbook でソース管理と継続的な統合を実現する方法について説明しました。ここで例示した手法は GitHub をはじめとするその他のオンライン ソース管理システムにも応用できます。ScriptCenter には Azure Automation Runbook が既に用意されています。GitHub リポジトリのコンテンツをダウンロードするにはこちら (英語) にアクセスしてください。Runbook を使用すれば、ここでご紹介したようなソリューションを構築して、GitHub をソース管理システムとして使用することができます。ご覧いただいたとおり、Azure Automation はとても便利で強力な自動化/統合サービスです。

    Azure Automation をまだご利用いただいていない方は、こちらからぜひプレビューにサインアップして、スタートアップ ガイドをご覧ください。

    A silver respite

    MSDN Blogs - Thu, 07/31/2014 - 23:00

     I skipped writing this month, and instead took a holiday with my wife in celebration of our 25th wedding anniversary. We had a wonderful time, recalling old memories and creating new ones. Hard Code will return next month.

    メディア アセットのライフサイクルの監視 – パート 1

    MSDN Blogs - Thu, 07/31/2014 - 22:45

    このポストは、7 月 23 日に投稿した Auditing Media Assets Lifecycle – Part 1 の翻訳です。

    付加価値の高いコンテンツを扱うメディア アプリケーションでは、通常、MPAA (英語)CDSA (英語)、またはそれと同等のコンプライアンス要件に従う必要があります。また、その監査手順の一環として、メディア アセットのライフサイクルを明示する監査レポートを作成し、アプリケーションおよびサービスの全体を説明するように求められることがあります。このブログでは、Media Services 全体を通してメディア アセットの監査レポートを生成する方法を、シリーズとして複数回に分けて説明します。第 1 回は、メディア アセットの作成と削除を示すアセット監査レポートの作成方法を扱います。

    Media Services のメディア アセット

    メディア アセットを作成すると、Media Services では GUID が生成され、この GUID に基づいて “nb:cid:UUID:” というプレフィックスの後に GUID が続く形でメディア アセットの ID が作成されます。これらの ID は URN 形式です。“nb” は Media Services のコードネーム (Nimbus) のイニシャルを、“cid” はコンテンツ ID (Content ID) を表しています。つまり、メディア アセットの ID は “nb:cid:UUID:<GUID>” となります。Media Services では次に、アセットのレコードが作成され、内部に格納されます。さらに、指定されたストレージ アカウントに “asset-<GUID>” という名前のコンテナーが作成されます。アセットの作成が完了したら、そのストレージ コンテナーにメディア ファイルをアップロードできます。メディア アセットを削除すると、Media Services では内部データベースからアセットのレコードが削除され、さらにストレージ コンテナーが削除されます。このため、アセットが削除されない限り、Media Services API を使用して作成時刻を特定することはできますが、アセットの削除時刻は、メディア アプリケーションで追跡しない限り特定することはできません。

    Storage のログでメディア アセットの���成と削除を追跡する

    メディア アセットは Storage のコンテナーとして表されるため、Storage のログからメディア アセットの作成時刻と削除時刻を特定することができます。ただしこの場合、使用しているストレージ アカウントで Storage のログ記録が有効になっている必要があります。詳細については、ログ記録の構成 (英語) を参照してください。監査レポートをいつまでさかのぼることができるかは、保持ポリシーの設定により決まります。ポリシーを 0 に設定した場合、ログは消去されず、ログ記録が有効化された時点までさかのぼることができます。Azure Storage のログは、ストレージ アカウント内の $logs というコンテナーに保存されます。ログの保存方法および命名規則の詳細については、MSDN の「Storage Analytics Logging について」のページをお読みください。

    サンプル コード

    次のサンプル コードは、Media Services のアセットのコレクションと Storage のログの両方を使用して AssetAudit という名前の Azure Storage Tables を作成するものです。この AssetAudit テーブルは、アセットの作成時刻と削除時刻を示すアセットの監査レポートを生成する際に使用できます。ロジックの内容は、主に次のようになっています。

    • Media Services API を使用してすべてのアセットのリストを作成します。
    • リストに挙げられたそれぞれのアセットについて、Asset.Created プロパティを使用して AssetAudit テーブルにエントリを作成します。
    • $logs/blob にあるすべての BLOB を処理ます。
    • それぞれの BLOB ファイルを取得し、さらに MSDN の「Storage Analytics のログの形式」のページに書かれているログ エントリの形式に従って解析します。
    • “asset-” で始まるオブジェクトに対する操作を検出します。
    • CreateContainer および DeleteContainer の操作を検出し、それぞれのエントリを AssetAudit テーブルに作成します。

    サンプル コードの App.Config ファイルは次のようになります。

    <?xml version="1.0" encoding="utf-8"?>

    <configuration>

      <startup>

        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />

      </startup>

      <appSettings>

        <add key="MediaServicesAccountName" value="<MediaAccountName>" />

        <add key="MediaServicesAccountKey" value="<MediaAccountKey>" />

        <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=<StorageAccountName>;AccountKey=<StorageAccountKey>"/>

      </appSettings>

      <runtime>

        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

          <dependentAssembly>

            <assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral" />

            <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />

          </dependentAssembly>

        </assemblyBinding>

      </runtime>

    </configuration>

    上の App.Config 内の <MediaAccountName> および <MediaAccountKey> の部分は、お客様の Media Services アカウントの名前とキーに置き換えてください。また、<StorageAccountName> および <StorageAccountKey> の部分は Media Services アカウントに関連付けられているストレージ アカウントの名前とキーに置き換えます。

    コード本体は次のようになります。

    using System;

    using System.Linq;

    using System.Configuration;

    using System.IO;

    using System.Text;

    using System.Threading;

    using System.Threading.Tasks;

    using System.Collections.Generic;

    using Microsoft.WindowsAzure;

    using Microsoft.WindowsAzure.Storage;

    using Microsoft.WindowsAzure.Storage.Blob;

    using Microsoft.WindowsAzure.Storage.Table;

    using Microsoft.WindowsAzure.MediaServices.Client;

     

    namespace AssetAuditing

    {

        /// <summary>

        ///

        /// </summary>

        public class AssetAuditEntity : TableEntity

        {

            public string OperationType { get; set; }

        }

     

        /// <summary>

        ///

        /// </summary>

        class Program

        {

            // App.config ファイルから値を読み込む

            private static readonly string _mediaServicesAccountName = ConfigurationManager.AppSettings["MediaServicesAccountName"];

            private static readonly string _mediaServicesAccountKey = ConfigurationManager.AppSettings["MediaServicesAccountKey"];

            private static readonly string _storageConnectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

            private static string _lastLogFile = ConfigurationManager.AppSettings["LastLogFile"];

     

            // サービスのコンテキストのフィールド

            private static CloudMediaContext _context = null;

            private static MediaServicesCredentials _cachedCredentials = null;

            private static CloudStorageAccount _cloudStorage = null;

     

            private static CloudBlobClient _blobClient = null;

            private static CloudTableClient _tableClient = null;

            private static CloudTable _assetAuditTable = null;

     

            /// <summary>

            ///

            /// </summary>

            /// <param name="args"></param>

            static void Main(string[] args)

            {

                try

                {

                    // Media Services の認証情報を静的クラス変数の形で作成しキャッシュする

                    _cachedCredentials = new MediaServicesCredentials(_mediaServicesAccountName, _mediaServicesAccountKey);

     

                    // キャッシュされた認証情報から CloudMediaContext を作成する

                    _context = new CloudMediaContext(_cachedCredentials);

     

                    _cloudStorage = CloudStorageAccount.Parse(_storageConnectionString);

     

                    _blobClient = _cloudStorage.CreateCloudBlobClient();

                    _tableClient = _cloudStorage.CreateCloudTableClient();

     

                    _assetAuditTable = _tableClient.GetTableReference("AssetAudit");

                    _assetAuditTable.CreateIfNotExists();

     

                    ProcessAssetData();

                    ParseStorageLogs();

                }

                catch (Exception ex)

                {

                    Console.WriteLine(ex.Message + ex.InnerException.StackTrace);

                }

            }

     

            /// <summary>

            /// この関数では、$logs コンテナーに格納されている Storage のすべてのログ ファイルを解析する

            /// ただし app.config のエントリに基づいて、直近の実行時に既に解析済みのファイルは飛ばして進む

            /// </summary>

            static void ParseStorageLogs()

            {

                try

                {

                    // $logs/blob にあるすべての BLOB のリストを作成する

                    foreach (CloudBlockBlob _blobItem in _blobClient.ListBlobs("$logs/blob", true))

                    {

                        // BLOB のリストは昇順で作成される

                        // ログは時系列順に整理されるため、直近の処理済みのログ ファイルと BLOB 名を比較すれば、再び処理しないようにできる                   

                        if (String.Compare(_blobItem.Name, _lastLogFile) > 0)

                        {

                            try

                            {

                                Console.WriteLine("Processing " + _blobItem.Name);

                                string _logs = GetBlobData(_blobItem);  // BLOB を取得

     

                                // 新しい行の区切り記号を検出してログの各行を取得

                                List<string> _logLines = ParseDelimitedString(_logs, "\n");

     

                                for (int i = 0; i < _logLines.Count; i++)

                                {

                                    // 区切り記号の ; を検出してログの各項目を分割

                                    List<string> _logLineItems = ParseDelimitedString(_logLines[i], ";");

                                    if (_logLineItems.Count > 0)

                                    {

                                        // ログの各行を解析

                                        ParseLogLine(_logLineItems);

                                    }

                                }

     

                                // BLOB 名を直近の処理済みのログ ファイルとして保存

                                _lastLogFile = _blobItem.Name;

                                SaveLastLogFileInConfig();

                            }

                            catch (Exception x)

                            {

                                Console.WriteLine(x.Message + x.InnerException.StackTrace);

                            }

                        }

                        else

                        {

                            Console.WriteLine("Skipping " + _blobItem.Name);

                        }

                    }

     

                    SaveLastLogFileInConfig();

                }

                catch (Exception ex)

                {

                    Console.WriteLine(ex.Message + ex.InnerException.StackTrace);

                }

            }

     

            /// <summary>

            /// この関数では、Media Services アカウントのすべてのアセットをループ処理 (1 回あたり 1000 個) し、AssetAudit テーブルにアセットの作成時刻を記録する

            /// </summary>

            static void ProcessAssetData()

            {

                try

                {

                    int skipSize = 0;

                    int batchSize = 1000;

                    int currentSkipSize = 0;

     

                    while (true)

                    {

                        // すべてのアセットのリストを作成する (1 回あたり 1000 個)

                        foreach (IAsset asset in _context.Assets.Skip(skipSize).Take(batchSize))

                        {

                            currentSkipSize++;

                            Console.WriteLine("Processing Asset " + asset.Id);

     

                            // AssetAudit テーブルにアセットの作成時刻を入力する

                            InsertAssetData(asset.Id, asset.Created.ToString("o"), "Create");

                        }

     

                        if (currentSkipSize == batchSize)

                        {

                            skipSize += batchSize;

                            currentSkipSize = 0;

                        }

                        else

                        {

                            break;

                        }

                    }

                }

                catch (Exception ex)

                {

                    Console.WriteLine(ex.Message);

                }

            }

     

            /// <summary>

            /// この関数では、解析された最終のログ ファイルを app.config に保存する

            /// </summary>

            static void SaveLastLogFileInConfig()

            {

                var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

                var settings = configFile.AppSettings.Settings;

                if (settings["LastLogFile"] == null)

                {

                    settings.Add("LastLogFile", _lastLogFile);

                }

                else

                {

                    settings["LastLogFile"].Value = _lastLogFile;

                }

     

                configFile.Save(ConfigurationSaveMode.Modified);

                ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);

            }

     

            /// <summary>

            /// この関数では BLOB を取得して、その中のデータを文字列として読み込む

            /// </summary>

            /// <param name="_blobItem"></param>

            /// <returns></returns>

            static string GetBlobData(CloudBlockBlob _blobItem)

            {

                MemoryStream ms = new MemoryStream();

                _blobItem.DownloadToStream(ms);

     

                byte[] buffer = new byte[ms.Length];

                ms.Seek(0, SeekOrigin.Begin);

                ms.Read(buffer, 0, (int)ms.Length);

     

                string _logs = Encoding.UTF8.GetString(buffer);

     

                ms.Dispose();

     

                return _logs;

            }

     

            /// <summary>

            /// この関数では文字列を解析し、指定された区切り記号で分割されたサブ文字列のリストを生成する

            /// 引用符の内側にある区切り記号は無視する

            /// </summary>

            /// <param name="_stringToParse"></param>

            /// <param name="strDelimiter"></param>

            /// <returns></returns>

            public static List<string> ParseDelimitedString(string _stringToParse, string strDelimiter)

            {

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

                if (!String.IsNullOrEmpty(_stringToParse))

                {

                    int j = 0;

                    int i = _stringToParse.IndexOf(strDelimiter);

                    while (i >= 0)

                    {

                        if (_stringToParse.Length > 0)

                        {

                            // この部分では、サブ文字列の先頭が引用符かどうかを確認する

                            // 引用符である場合、一致するペアを検索し、その後ろにある区切り記号を検出する

                            if (_stringToParse[j] == '\"')

                            {

                                i = _stringToParse.IndexOf("\"", j + 1);

                                if (i > 0)

                                {

                                    i = _stringToParse.IndexOf(strDelimiter, i);

                                }

                            }

                        }

     

                        string _str = _stringToParse.Substring(j, i - j);

                        _parsedStrings.Add(_str);

     

                        j = i + strDelimiter.Length;

                        i = _stringToParse.IndexOf(strDelimiter, j);

                    }

     

                    _parsedStrings.Add(_stringToParse.Substring(j, _stringToParse.Length - j));

                }

     

                return _parsedStrings;

            }

     

            /// <summary>

            /// この関数では、ログの各行を解析する

            /// </summary>

            /// <param name="_logLineItems"></param>

            static void ParseLogLine(List<string> _logLineItems)

            {

                try

                {

                    // バージョン 1.0 のログを処理していることと、すべてのログ項目が正常に分割されたことを確認する

                    if ((_logLineItems[0] == "1.0") && (_logLineItems.Count == 30))

                    {

                        // 必要なログ項目を解析する (このサンプルではすべてのアイテムを解析する必要はない)

                        string _requestedObjectKey = _logLineItems[12];

     

                        string _assetPrefix = "\"/" + _cloudStorage.Credentials.AccountName + "/asset-";

                        int _assetIdIndex = _requestedObjectKey.IndexOf(_assetPrefix);

                        if (_assetIdIndex == 0)

                        {

                            Console.WriteLine("Processing ObjectKey=" + _requestedObjectKey);

     

                            _assetIdIndex += _assetPrefix.Length;

                            int j = _requestedObjectKey.IndexOf("/", _assetIdIndex);

                            if (j < 0)

                            {

                                j = _requestedObjectKey.Length - 1;

                            }

                            string _assetId = _requestedObjectKey.Substring(_assetIdIndex, j - _assetIdIndex);

                            _assetId = "nb:cid:UUID:" + _assetId;

     

                            string _timeStamp = _logLineItems[1];

                            string _operationType = _logLineItems[2];

                            string _requestStatus = _logLineItems[3];

                            string _authType = _logLineItems[7];

     

                            string _requesterIpAddress = _logLineItems[15];

     

                            Console.WriteLine("Processing Asset Id:" + _assetId + " TimeStamp:" + _timeStamp + " OperationType:" + _operationType);

     

                            switch (_operationType)

                            {

                                case "CreateContainer":

                                    _operationType = "Create";

                                    InsertAssetData(_assetId, _timeStamp, _operationType);

                                    break;

     

                                case "DeleteContainer":

                                    _operationType = "Delete";

                                    InsertAssetData(_assetId, _timeStamp, _operationType);

                                    break;

                            }

                        }

                    }

                }

                catch (Exception ex)

                {

                    Console.WriteLine(ex.Message + ex.InnerException.StackTrace);

                }

            }

     

            /// <summary>

            /// この関数では、AssetAudit テーブルにエントリを追加する

            /// Create 操作の場合はデータに 2 つのソースがあるので、エントリが重複しないように、エントリが既に存在しているかどうかを確認する

            /// Azure のロール インスタンス間で時計がずれるために、アセットのコレクションと Storage のログのタイムスタンプは多少異なる場合がある

            /// </summary>

            /// <param name="_assetId"></param>

            /// <param name="_timeStamp"></param>

            /// <param name="_operationType"></param>

            static void InsertAssetData(string _assetId, string _timeStamp, string _operationType)

            {

                try

                {

                    bool _insert = true;

                    if (_operationType == "Create")

                    {

                        // operationType (操作の種類) が "Create" の場合、そのアセットの ID でエントリが存在するかどうかを確認する

     

                        TableQuery<AssetAuditEntity> query = new TableQuery<AssetAuditEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, _assetId));

                        query.Take(1);

     

                        TableQuerySegment<AssetAuditEntity> tqs = _assetAuditTable.ExecuteQuerySegmented(query, null);

                        if ((tqs != null) && (tqs.Results != null))

                        {

                            if (tqs.Results.Count > 0)

                            {

                                if (tqs.Results[0].OperationType == "Create")

                                {

                                    _insert = false;

                                }

                            }

                        }

                    }

     

                    if (_insert)

                    {

                        AssetAuditEntity _asset = new AssetAuditEntity();

                        _asset.PartitionKey = _assetId;

                        _asset.RowKey = _timeStamp;

                        _asset.OperationType = _operationType;

     

                        TableOperation op = TableOperation.Insert(_asset);

                        _assetAuditTable.Execute(op);

                    }

                }

                catch (Exception ex)

                {               

                    Console.WriteLine(ex.Message);               

                }

            }

     

        }

    }

    このコー��で使用されている関数について簡単に説明します。

    ProcessAssetData

    この関数は、指定された Media Services アカウントのすべてのアセットをループ処理します。Media Services は、アセットのコレクションで 1,000 個のアセットを返します。この関数では Skip および Take を使用して、アカウント内に 1,000 個以上のアセットが存在する場合にも確実にすべてのアセットをリストに含めます。

    ParseStorageLogs

    この関数は、$logs/blob に格納されているすべての BLOB のリストを作成し、処理が済んだ BLOB を直近の処理済みのログ ファイルとして保存して、コードが再実行されても処理が重複しないようにします。

    SaveLastLogFileInConfig

    この関数は、直近の処理済みのログ ファイルの名前を App.Config に保存して、プログラムが再実行されたときに取得できるようにします。

    GetBlobData

    この関数では、Storage から BLOB を取得して、その中のデータを文字列として読み込みます。

    ParseDelimitedString

    この関数は、指定された区切り記号に基づいて文字列を分割します。分割されたデータは文字列のコレクションとして返されます。

    ParseLogLine

    この関数は、ログの各行を解析して “asset-” で始まるコンテナーの CreateContainer および DeleteContainer の操作を抽出します。

    InsertAssetData

    この関数は、AssetAudit テーブルにエントリを追加します。

    アセットの監査データ

    上記のコードを実行すると、AssetAudit テーブルが作成されます。テスト アカウントで作成されたこのテーブルの内容のスクリーンショットを次に示します。赤枠で囲まれているのは、あるアセットの Create と Delete の組み合わせです。Media Services にはこのアセットが存在しないため、これらのエントリは、上記のコードを実行して Storage ログから作成するしかありません。

    また、このデータは Excel の Power Query を使用して Excel に読み込むことができます。Excel を利用すると、さらに高度なフィルタリングを行ったり、ピボット テーブルに読み込んで詳細な分析を行ったりすることができます。Excel の Power Query を使用したことのないお客様は、Microsoft Power Query for Excel のダウンロード ページ (英語) からダウンロードしてご利用ください。インストール完了後に Excel を起動すると、[POWER QUERY] というタブが表示されます。このタブをクリックし、続いて [From Other Sources] ボタンをクリックすると、次のスクリーンショットのように [From Windows Azure Table Storage] というメニュー項目が表示されます。

    AssetAudit テーブルからデータをインポートするには、上記のメニュー項目を選択して、画面の指示に従います。Azure の Table が右側の [Navigator] ウィンドウに読み込まれた後、AssetAudit テーブルをダブル クリックすると、次のスクリーンショットのように新しいウィンドウが開きます。

    [Content] 列の隣のボタンをクリックして、さらに [OK]、画面上部の [Apply & Close] の順にクリックします。画面が閉じて、データが Excel に読み込まれます。これで、Excel を使用して自由にデータを分析できるようになります。

    考慮事項

    最後に、サンプル コードを使用する際の注意事項について説明します。

    • この記事でご紹介したサンプル コードは、すべてのアセットが 1 つのストレージ アカウントに含まれている Media Services アカウントで使用することを前提としていますが、簡単な変更で複数のストレージ アカウントでも動作するようにできます。
    • 監査は Storage のログに関連付けられている保持ポリシーによる制限を受けます。
    • デバッガーでサンプル コードを実行する場合は、直近に処理されたログの BLOB 名が App.Config ファイルに更新されることはありません。更新はデバッガー以外でサンプル コードを実行した場合にのみ行われます。
    • 例外はコンソールにのみ出力されます。ただし、必要に応じて Azure Tables やローカル ファイルに書き出すようにすることもできます。

    Azurové novinky–červenec 2014

    MSDN Blogs - Thu, 07/31/2014 - 22:40
    Léto udeřilo na Českou republiku rukou těžkou a horkou. Přestože občasné bouřky dokázaly proměnit některé pražské ulice v řeky, následná vedra vše dokonale vysušila. Tedy skoro vše – pravidelný přísun novinek z Microsoftího cloudu je k nezastavení. Pojďme se podívat, co přinesl červenec. Vylepšení Preview portálu Nový Azure preview portál, který...(read more)

    Azure Mobile Services の node.js バックエンドによる MongoDB コレクションのクエリ

    MSDN Blogs - Thu, 07/31/2014 - 22:30

    このポストは、7 月 23 日に投稿した Querying MongoDB collections via the Azure Mobile Service node.js backend の翻訳です。

    前回の記事 (英語) では、Azure Mobile Services の Table を使用して Mongo データベースを既定の Azure SQL Database のストレージ レイヤーの代わりに使用する方法についてご紹介しました。このときは、作成、更新、削除、読み込みといった操作の実装方法を説明しましたが、クエリ機能については、Table の読み込み操作がコレクションのアイテムを 1 つだけ返すのかすべて返すのかを説明しただけであったため、説明が十分ではありませんでした。今回の記事では、これまで説明したことがなかった node.js ランタイムの機能について説明したいと思います。この機能では、ユーザーから渡されるクエリ パラメーターを取得することで、ページング、並べ替え、選択、数種類のフィルタリングがサポートされ、MongoDB コレクションを Mobile Services の node.js から完全 (またはほぼ完全) に使用できるようになります。

    クエリ コンポーネント

    Mobile Services の node.js で MongoDB コレクションのクエリを実行する方法について説明した記事はいくつかあります (例 1例 2、いずれも英語)。クエリの実行方法としては、カスタマイズされたクエリ文字列のパラメーターで行う方法と、コード内にハードコードする方法があります。その中でも特に、クライアントが送信する OData のクエリ パラメーター (英語) に対応するランタイムを使用すると、クライアント アプリケーションのコードをより自然な形で作成できるのでおすすめです。具体的には、クライアントのコードは以下のように作成できます。

    var table = client.GetTable<Order>();

    var last10Orders = await table

        .OrderByDescending(o => o.OrderDate)

        .Take(10)

        .ToListAsync();

    また、このランタイムには、Mongo コレクションのクエリを実行するときに上記のオプションを適用します。上記のコードは、/tables/order?$top=10&$orderby=OrderDate desc というクエリ文字列の HTTP 要求に送信します。OData のクエリ パラメーター (‘$’ で始まるもの) には、読み込みスクリプトの request オブジェクトparameters プロパティで公開されないという問題があります。ただし、getComponents を公開する query オブジェクトの機能 (今回初めて説明する機能) を使用すると、読み込み操作で取得することができます。この方法では、ページング (skip/top)、順序付け、選択、フィルタリングなどのクライアントから送信される OData のパラメーターをすべて取得できます。ここで、クエリ コンポーネントを出力するように読み込みスクリプトを変更します。

    function read(query, user, request) {

        console.log(query.getComponents());

        request.execute();

    }

    これで、上記の要求がサーバーに送信されるようになります。Mobile Services のログを見ると、クエリ コンポーネントから取得可能な情報をすべて確認できます。

    { filters: null,

      selections: [],

      projection: null,

      ordering: { OrderDate: false },

      skip: null,

      take: 10,

      table: 'complexOrders',

      context: undefined,

      includeTotalCount: false,

      version: 2 }

    このコンポーネントには、スクリプトで OData のクエリ パラメーターを読み込むために必要な情報がすべて含まれています。以下では、その使用方法について説明します。

    ページング (take/skip)

    前回の記事に戻って、Mongo コレクションから複数のアイテムを取得する場合について見てみましょう。

    function returnMultipleObjects(collection, query, mongoHelper, request) {

     

    // 目的: クエリ パラメーターを確認する。ここではすべてのアイテムを返す。

        collection.find().toArray(function(err, items) {

            if (err) {

                console.log('error querying collection: ', err);

                request.respond(200, { error: err });

            } else {

                items.forEach(function(item) {

                    mongoHelper.mongoIdToMobileServiceId(item);

                });

                request.respond(200, items);

            }

        });

    }

    ここでは collection.find メソッド (英語) を使用していて、クエリ オプションのパラメーターを追加できます。その中で、limitskip はそれぞれ OData パラメーターの $top$skip に相当します。これにより、find メソッドに上記のオプションを追加できます。

    function returnMultipleObjects(collection, query, mongoHelper, request) {

        var findOptions = {};

     

        var queryComponents = query.getComponents();

     

        applyTopAndSkip(findOptions, queryComponents);

        applyOrdering(findOptions, queryComponents);

        applySelect(findOptions, queryComponents);

        var findQuery = getFilterQuery(queryComponents, request);

        if (findQuery === null) {

         // 送信済みの応答

            return;

        }

     

        collection.find({}, findOptions).toArray(function(err, items) {

            if (err) {

                console.log('error querying collection: ', err);

                request.respond(200, { error: err });

            } else {

                items.forEach(function(item) {

                    mongoHelper.mongoIdToMobileServiceId(item);

                });

                request.respond(200, items);

            }

        });

     

        function applyTopAndSkip(findOptions, queryComponents) {

            if (queryComponents.take) {

                findOptions.limit = queryComponents.take;

            }

     

            if (queryComponents.skip) {

                findOptions.skip = queryComponents.skip;

            }

        }

     

        function applySelect(findOptions, queryComponents) { }

        function applyOrdering(findOptions, queryComponents) { }

        function applyFilter(queryComponents, request) { }

        function getFilterQuery(queryComponents, request) { return {}; }

    }

    これで、/tables/order?$skip=3&$top=5 という要求を送信すると、最初の 3 つを無視して 5 つのドキュメントのみを取得するようになります (ただし、コレクションの既定の順序に従います。この順序は後で取得します)。さらに、この要求に $top クエリ パラメーターが含まれていない場合、queryComponents.take の値は 0 にはなりません (この場合、node.js ランタイムで返される既定の最大アイテム数である 50 になります)。このため、find オプションで制限を定義する場合にはこの値を確認することを推奨します。

    順序付け

    ページング (skip/take) は強力な機能で、ページングの実行時にクライアントの名前順や日付順などの順序を定義することができます。クエリ コンポーネントの出力を見ると、この順序は、フィールドを表すキーと順序の要求が昇順か降順かを示すブール値を含むオブジェクトとして定義されていることがわかります。このため、MongoDB ノード パッケージに準拠した書式 (フィールド名を含む配列または順序) に従う必要があります。

    function applyOrdering(findOptions, queryComponents) {

        var orderBy = [];

        var ordering = queryComponents.ordering;

        for (var orderField in ordering) {

            if (ordering.hasOwnProperty(orderField)) {

                var ascending = queryComponents.ordering[orderField] ? 'ascending' : 'descending';

                orderBy.push([ orderField, ascending ]);

            }

        }

     

        if (orderBy.length) {

            findOptions.sort = orderBy;

        }

    }

    これで、この記事の序盤で説明した /tables/order?$top=10&orderby=orderDate desc というコード スニペットを実行できます。

    選択

    MongoDB のドキュメント (および通常データベースに格納されているエンティティ) には、必須以外の情報 (プロパティまたは列) が含まれていることがあり、これらをすべて取得していると帯域幅と処理に不必要なコストがかかってしまいます。OData および MongoDB では、次のように、取得するフィールドを選択して、より多くのクエリ コンポーネントを一度に MongoDB ノードのドライバーに準拠した書式にマッピングすることができます。

    function applySelect(findOptions, queryComponents) {

        var selects = queryComponents.selections;

        if (selects && selects.length) {

            if (selects.length === 1 && selects[0] === '*') {

                // $select がない場合と同様に、何の処理も行わない

            } else {

                findOptions.fields = {};

                selects.forEach(function(field) {

                    findOptions.fields[field] = 1;

                });

            }

        }

    }

    クライアント名を新しい順に 10 個だけ必要な場合のコードは、/tables/order?$top=10&$orderby=orderDate desc&$select=client となります。

    フィルタリング

    コレクションのすべての要素を要求するのではなく (ページングされている場合でも)、クライアントは特定の条件に一致したドキュメントのみを要求する場合もあります。たとえば、”J” から始まるクライアントの順序のみが必要な場合は以下のとおりです。

    var table = Client.GetTable<Order>();

    var items = await table

        .Where(o => o.Client.StartsWith("J"))

        .OrderByDescending(o => o.OrderDate)

        .Take(10)

        .ToListAsync();

    上���フィルターでは、OData のクエリ パラメーターである $filter が /tables/order?$top=10&$orderby=orderDate desc&$filter=startswith(client,'J') によって送信されます。クエリ コンポーネントのログを記録している場合は、下の例のように、filters オブジェクトの ”queryString” の値でフィルターの式を確認できます。filters には他のプロパティ (args、type) が含まれていますが、この例では使用されていません。OData とこのクエリ文字列を変換するコードはサーバーのランタイムと JavaScript クライアント SDK で共有されますが、これらのプロパティはクライアントでのみ使用されるためです。

    { filters:

       { queryString: 'startswith(client,\'J\')',

         args: [],

         type: 'LiteralExpression' },

      selections: [],

      projection: null,

      ordering: { orderDate: false },

      skip: 0,

      take: 10,

      table: 'complexOrders',

      context: undefined,

      includeTotalCount: false,

      version: 4 }

    さらに、このフィルターを使用して結果を node.js の MongoDB ライブラリの collection.find メソッド (英語) に渡すこともできます。しかし、これは簡単な作業ではありません。フィルターは文字列として指定されているため、手動でこれを解析してノードのドライバーに準拠した適切な書式に変換する必要があります。次に示すのは、いくつかのコンストラクト (単純なバイナリ演算子と ”startswith” 関数) をサポートする場合の例です。ただし、完全に実装する場合は、クエリ文字列を解析して式ツリーに変換し、同等の MongoDB のクエリ オブジェクトを作成するように検討する必要があります。これはほぼクエリ コンポーネントの機能の概要にあたるため、この記事では取り扱いません。

    function getFilterQuery(queryComponents, request) {

    // 単純な場合: フィルターがすべてを除外し、データベースと通信を行う必要がない

        if (queryComponents.filters && queryComponents.filters.queryString === 'false') {

            request.respond(200, []);

            return null;

        }

     

        var findQuery = convertFilter(queryComponents.filters);

        if (findQuery === null) {

            request.respond(500, { error: 'Unsupported filter: ' + queryComponents.filters.queryString });

            return null;

        }

     

        return findQuery;

    }

     

    function convertFilter(filters) {

        var findQuery = {};

     

        var startsWith = [ /^startswith\(([^,]+),\'([^\']+)\'\)/, function(p) {

            var field = p[1];

            var value = p[2];

            var result = {};

            result[field] = new RegExp('^' + value);

            return result;

        } ];

     

        var binaryOperator = [ /^\(([^\s]+)\s+([^\s]{2})\s(.+)$/, function(p) {

            var field = p[1];

            var operator = p[2];

            var value = p[3].slice(0, -1); // 最後の ")" を削除

            if (/datetime\'\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}\.\d{3}Z\'/.test(value)) {

            // 日付リテラル

                value = new Date(Date.parse(value.slice(9, -1)));

            } else if (/^\'.+\'$/.test(value)) {

            // 文字列リテラル

                value = value.slice(1, -1);

            } else {

            // 数値

                value = parseFloat(value);

            }

     

            var result = {};

            if (operator === 'eq') {

                result[field] = value;

            } else {

                result[field] = {};

                result[field]['$' + operator] = value;

            }

            return result;

        } ];

     

        var supportedFilters = [startsWith, binaryOperator];

     

        if (filters) {

        // 簡単な場合

            if (filters.queryString === 'true') {

                return {};

            }

     

            var foundMatch = false;

            for (var i = 0; i < supportedFilters.length; i++) {

                var match = filters.queryString.match(supportedFilters[i][0]);

                if (match) {

                    findQuery = supportedFilters[i][1](match);

                    foundMatch = true;

                    break;

                }

            }

     

            if (!foundMatch) {

                return null;

            }

        }

     

        return findQuery;

    }

    これで、サポートされているどの Mobile Services のクライアント SDK を使用しても、複雑な MongoDB のクエリを実行できるようになりました。

    まとめ

    この記事では、query オブジェクトを使用して読み込みスクリプトが OData のクエリ パラメーターにアクセスできるようにする機能 (この記事で初めて説明)、およびこの機能を使用して MongoDB コレクションに複雑なクエリを実行する方法についてご紹介しました。この機能は、フィルターの変換のサポートなどに改良の余地がありますが、この機能を使用することで、この記事 (および前回の記事) で取り扱った例、つまり、すべてのクライアントがサポートしている同一の Table の抽象化を他のバックエンド ストレージに拡張する、というシナリオが可能になります。

    今回の記事で使用したすべてのコードは、こちらのサンプル リポジトリ (英語) からダウンロードできます。ご意見やご感想がありました��、お気軽にこの記事のコメント欄か MSDN のフォーラムまでお寄せください。

    Hadoop Yarn memory settings in HDInsigh

    MSDN Blogs - Thu, 07/31/2014 - 22:29

    There are several related memory settings for jobs running in HDInsight cluster which most customers need to pay close attention to. When not correctly set, it will cause obscure failures in Hive/Pig/Mapreduce/Tez jobs.

     

    1. Mapreduce memory settings:

    HDInsight 3.x service deploys Hadoop 2.x clusters. Hadoop 2.x (Yarn) introduced the concept of containers. Unlike Hadoop 1.x where each node is assigned a fixed number of "slots", in Hadoop 2.x each Yarn task (mapper, reducer or Tez task) is assigned a container which has an memory limit. Yarn Node Manager will monitor the memory usage of the task and kill a container when the memory usage exceeds that limit.

     

    These are the default settings in HDInsight for the mapper, reducer and AM(Application Master):

    mapreduce.map.memory.mb = 512

    mapreduce.reduce.memory.mb = 1024

    yarn.app.mapreduce.am.resource.mb = 1024

     

    This is a typical error message in your job attempt log, if these limits are exceeded:

     

    Container[pid=container_1406552545451_0009_01_000002,containerID=container_1406552545451_0009_01_000002] is running beyond physical memory limits. Current usage: 519.1 MB of 512 MB physical memory used; 770.1 MB of 1.0 GB virtual memory used. Killing container. Dump of the process-tree for container_1406552545451_0009_01_000002 : |- PID CPU_TIME(MILLIS) VMEM(BYTES) WORKING_SET(BYTES) |- 4912 15 667648 2502656 |-4712 9546 232022016 97697792 |- 6000 78 1867776 2605056 |- 4780 50234 571166720 438947840 |- 4516 31 1810432 2588672 Container killed on request. Exit code is 137

     

    Aside from the memory monitoring, each Java process has its own heap space settings. These are the default settings for the mapper, reducer and AM:

    mapreduce.map.java.opts = "-Xmx410m"

    mapreduce.reduce.java.opts = "-Xmx819m"

    yarn.app.mapreduce.am.command-opts = "-Xmx819m"

     

    This is a typical error message in your job attempt log:

     

    Error: java.lang.RuntimeException: java.lang.OutOfMemoryError: GC overhead limit exceeded

    or

    Error: java.lang.RuntimeException: java.lang.OutOfMemoryError: Java heap space

     

    If you see any of these errors, you can consider increasing the memory limit. For example, to increase memory limit for the mapper, you can overwrite these settings in Mapreduce configuration:

    mapreduce.map.memory.mb = 1024

    mapreduce.map.java.opts = "-Xmx819m"

     

     

    2. Hive memory settings for Tez:

    When using Tez for Hive, you can specify Tez task's memory settings, these are default values:

    hive.tez.container.size = -1

    hive.tez.java.opts = ""

     

    The default settings mean that the actual Tez task will use the mapper's memory setting:

    hive.tez.container.size = mapreduce.map.memory.mb

    hive.tez.java.opts = mapreduce.map.java.opts

     

    If you want to have Tez use different memory setting from the Mapreduce framework, you can modify these settings for Hive configuration.

     

    3. WebHCat memory settings:

    WebHCat(also known as Templeton) uses Mapreduce job (the LaunchMapper) to submit user's Hadoop job. So the Mapreduce memory settings are also applicable to WebHCat's LaunchMapper. However, usually the LaunchMapper will need more memory than the default mapper memory limit of 512MB. For example, for a user's Hive job submitted through WebHCat, LaunchMapper will call hive command line which may start local task that requires close to 1GB memory. In this case you can use this configuration to set LaunchMapper's memory limit to 1GB:

    templeton.mapper.memory.mb = 1024

     

    References:

    http://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.0.9.1/bk_installing_manually_book/content/rpm-chap1-11.html

    新時代のハイブリッド クラウド

    MSDN Blogs - Thu, 07/31/2014 - 22:00

    このポストは、7 月 22 日に投稿した Not your father’s #hybridCloud の翻訳です。

    現代のビジネスにおいて、俊敏性を実現することは企業の最重要課題となっています。Microsoft Azure は柔軟性の高いインフラストラクチャと世界トップレベルのツールによって、企業がごく短期間でそのためのソリューションを実現できるよう支援を行っています。しかし実際のところ、企業には、最新のテクノロジを採用して効率性と拡張性を高めていく必要がある一方で、今ある既存のリソースやインフラストラクチャを最大限に活用することが求められています。そのため、生産性を向上させるには、今後クラウドとオンプレミスの両方のリソースを組み合わせたハイブリッド ソリューションが必要不可欠となることは間違いありません。

    5 月には、Azure BizTalk Services スイートの新機能である Hybrid Connections (英語) がリリースされました。Hybrid Connections は、Azure Web Sites および Mobile Servicesオンプレミスのデータベースやサービスに直接安全に接続することができるターンキー ソリューションです。これを使用すれば、受信トラフィックを許可するようにファイアウォールを設定したり、VPN ゲートウェイをデプロイしたりする必要はありません。

    既に多くのお客様が Hybrid Connections を使用して迅速にハイブリッド ソリューションのプロトタイプ作成およびデプロイを行っており、次のようにパターン化されつつあります。

    • 容易な移行: Hybrid Connections では、既存のオンプレミスの Web ワークロードを利用して、Azure Web Sites に再デプロイすることができます。その場合も、コードを 1 行も変更することなく、サイトが依存関係にあるオンプレミスのデータベースおよびサービスに安全にアクセスできます。
    • 開発/テスト: 企業は Azure の柔軟性の高いインフラストラクチャを活用して、迅速に新しいソリューションの開発とテストを行っています。Hybrid Connections を使用すれば、ネットワーク境界を変更しなくても、これらの新しいソリューションをオンプレミスのデータおよびサービスに簡単に接続できます。準備ができたら、パブリック クラウド、プライベート クラウド、管理対象サーバーなど、企業にとって最適な場所にソリューションをデプロイできます。
    • モバイル アプリ: BYOD やユビキタスなモバイル環境といった近年の新たなトレンドは、クラウド テクノロジとの親和性が高いものです。Mobile Services などのプラットフォームでカスタムのモバイル バックエンドのデプロイ時間を短縮することにより、この親和性はさらに強力になります。しかし、それでも企業では、これらのソリューションにオンプレミスのリソースを活用する必要があります。Hybrid Connections を使用すれば、それは簡単に実現できます。

    Hybrid Connections は、効率性と俊敏性の向上、よりスピーディな価値提供を目指す企業にとって、大きな変化をもたらすものです。セキュリティも、もちろん今後もきわめて重要な課題であるため、マイクロソフトではハイブリッド ソリューションを保護できるように包括的な管理ツールを提供しています。これには、エンタープライズ IT でのグループ ポリシーのサポートが含まれ、Hybrid Connections が接続できるアセットへのアクセスを集中管理することができます。

    ハイブリッド クラウドは新時代を迎えました。ハイブリッド ソリューションをごく短期間で構築できる、まったく新しい方法が誕生したのです。

    ハイブリッドに関する課題をいかに簡単かつ安全に解決できるようになったかについては、Join Nir Mashkowski と Josh Twist が解説するこちらのビデオ (英語) をご覧ください。

    Microsoft Azure への SAP HANA Developer Edition のデプロイ手順

    MSDN Blogs - Thu, 07/31/2014 - 21:30

    このポストは、7 月 22 日に投稿した Step-by-step guide for deployment of SAP HANA Developer Edition on Microsoft Azure の翻訳です。

     

    はじめに

    今年の前半に、Microsoft Azure で SAP ワークロードがサポートされることが発表されました (Azure の SAP サポートに関する発表、英語)。これには、SAP HANA Developer Edition のデプロイも可能になるというメッセージが含まれていました。SAP HANA Developer Edition のデプロイには、SAP Cloud Appliance Library (SAP CAL) を使用します。このトピックについては、SAP から以下のブログ記事およびドキュメントが公開されています。

    下記に示す手順を正しく理解するためには、どうしてこのような手順を踏む必要があるのかという背景をまず知る必要があります。SAP HANA Developer Edition は、そのまま使用できる単一のイメージとして Azure ギャラリーに提供されているわけではありません。最終的に SAP HANA Developer Edition を含める VM は、Azure ギャラリーの OS イメージを使用してから SAP ソフトウェアを追加することで動的にアセンブルされます。SAP CAL ポータルでは、これを実行するプロセスをお客様のサブスクリプション内で開始するために、適切なアクセス許可が必要となります。Azure の場合、そのためにはお客様がサブスクリプション ID を入力して VM を作成する場所を指定する必要があります。また、SAP CAL で開始されるアクティビティの認証には、管理証明書が必要となります。

    Azure 証明書の詳細については、こちらのページを参照してください。

    手順の説明

    SAP CAL では、お客様の Azure サブスクリプション内に HANA Developer Edition の VM が作成されます。そのため、まずはサブスクリプションを取得する必要があります。Azure ホーム ページにアクセスしてサブスクリプションを取得するか、既存の MSDN アカウントを使用することができます。次の 2 つのスクリーンショットを参照してください。

     

    図 1: Azure ホーム ページにアクセスし、サブスクリプションを取得します。

     

     図 2: 既存の MSDN アカウントを使用する場合、Microsoft Azure の使用をアクティブ化します。

     

    図 3: Azure 上の SAP HANA Developer Edition で作業を行うには、まず SAP Cloud Appliance Library (SAP CAL、英語) にアクセスします。

     

    図 4: SAP CAL の Web サイト内を下にスクロールすると、ソリューションをデプロイするための手順が表示されます。

     

    図 5: 手順 1 から開始します。まずは登録済みのユーザー アカウントでログインします。

     

    図 6: ログインしたら、[SOLUTIONS] タブで「hana dev edition」を検索します。今回使用するのは、バージョン 1.0 Rev 80 です。ただし、アカウントが関連付けられていない場合、ソリューションをアクティブ化することはできません。

     

    図 7: そこで、[ACCOUNTS] タブでアカウントを作成する必要があります。

     

    図 8: SAP CAL のアカウントを作成するには、まず名前を入力します。

     

    図 9: 次に、クラウド プロバイダー (ここでは「Microsoft Azure」) を選択します。Microsoft Azure を選択した場合、サブスクリプション ID を入力します。この情報は、HANA Developer Edition の VM を構築する場所を指定するために必要となります。作成したアカウントは、[ACCOUNTS] タブの表に表示されます。

     

    図 10: Azure サブスクリプション ID を取得するには、Azure ポータル (現時点では新バージョンでない方) にログインし、左側のナビゲーション内を下にスクロールして [SETTINGS] を選択します。[SUBSCRIPTIONS] タブから ID をコピーします。複数のサブスクリプションが存在する場合は、適切なサブスクリプションを選択してください。

     

    図 11: SAP CAL に Azure サブスクリプション ID を入力すると、管理証明書をダウンロードするかどうかを尋ねるダイアログが表示されます。管理証明書については、「はじめに」のセクションでご説明したと おりです。SAP CAL では、お客様の Azure サブスクリプション内の新しい VM を動的にアセンブルします。そのために適切な許可を得るには、管理証明書が必要となります。

     

    図 12: SAP CAL での手順を続行する前に、先ほどダウンロードした Azure 管理証明書をアップロードする必要があります。Azure 管理証明書をアップロードしないと、SAP CAL で VM が作成されません。ダウンロードした管理証明書では、Issuer (発行者) や Valid to (有効期限) などの詳細を確認できます。これらの詳細は、後で Azure ポータルに表示されます。

     

    図 13: 管理証明書をアップロードするために Azure サブスクリプション ID をコピーするには、先ほどと同様に、左側のナビゲーション内を下にスクロールして [SETTINGS] を選択します。[MANAGEMENT CERTIFICATES] タブで、ポータル ウィンドウ下部の [UPLOAD] ボタンを使用して、新しい証明書を Azure サブスクリプションにアップロードします。

     

    図 14: アップロードした証明書は、Azure ポータルに表示されます。図 12 に示した発行者や有効期限などの詳細を確認できます。

     

    図 15: SAP CAL の [SOLUTIONS] タブに戻ると、ソリューションをアクティブ化できるようになっています。ここで、先ほど作成したアカウントのアクティブ化と関連付けを行います。これ以降 は、Microsoft Azure で VM インスタンスを作成することができます。[Create Instance] をクリックします。

     

    図 16: インスタンス (Azure VM) を再度作成するには、名前を入力します。この名前は、後で Azure の VM 名として使用されます。適切なアカウントと Azure リージョンを選択します。この例では、Azure リージョンとして [West Europe] を選択しています。

     

    図 17: 現時点では、Azure 上の HANA Developer Edition で選択できる VM サイズは A7 (仮想 CPU: 8、メモリ: 56 GB) のみです。SAP CAL に、Azure VM 用に作成されたすべてのエンドポイントの一覧が表示されます。

     

    図 18: 次に、SAP CAL でソリューションのマスター パスワードを設定します。

     

    図 19: スケジュールのオプションには、[Manually activate and suspend] を選択します。次の手順は省略し、最後のまとめ画面で処理を完了します。これにより、Microsoft Azure で VM の作成プロセスが開始されます。

     

    図 20: Azure ポータルに新しい VM と、関連情報が表示されます。

     

    図 21: Azure ポータルで VM を確認すると、先ほど SAP CAL に表示されたすべてのエンドポイントを [ENDPOINTS] タブで確認できます。

     

    図 22: Azure VM のダッシュボードには、VM ディスクとそれに対応する Azure ストレージ アカウントが表示されます。Azure ポータルの左側にある [STORAGE] を選択すると、SAP CAL によって作成されたストレージ アカウントと 2 つのコンテナーを確認できます。

     

    図 23: Azure VM が稼働したら、ブラウザーに VM の Azure パブリック IP アドレスを入力します。これで、HANA Developer Edition 環境が開始されます。

     

    図 24: 上記の手順を実行する代わりに、SAP HANA Studio (英語) をダウンロードして、ローカルのオンプレミスにインストールすることもできます。

     

    図 25: HANA Studio をインストールすると、Azure 上で実行される HANA Developer Edition インスタンス (デプロイには SAP CAL を使用) に接続できます。

    [Sample Of October 1] How to delete a row from Windows Azure Table storage without retrieving it first

    MSDN Blogs - Thu, 07/31/2014 - 20:17
    Oct. 1

    Sample Download : http://code.msdn.microsoft.com/How-to-delete-a-row-from-4c051eda

    When you develop an app that needs connecting to Azure storage service, it will take a long time to send requests and get responses in the client application.

    This sample demonstrates how reduce the times of connection between client app and Azure storage service. It also shows how to handle general exception when you get the response.

     

    You can find more code samples that demonstrate the most typical programming scenarios by using Microsoft All-In-One Code Framework Sample Browser or Sample Browser Visual Studio extension. They give you the flexibility to search samples, download samples on demand, manage the downloaded samples in a centralized place, and automatically be notified about sample updates. If it is the first time that you hear about Microsoft All-In-One Code Framework, please watch the introduction video on Microsoft Showcase, or read the introduction on our homepage http://1code.codeplex.com/.

    Pages

    Subscribe to Randy Riness @ SPSCC aggregator
    Drupal 7 Appliance - Powered by TurnKey Linux